clang 22.0.0git
SemaOpenMP.cpp
Go to the documentation of this file.
1//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements semantic analysis for OpenMP directives and
10/// clauses.
11///
12//===----------------------------------------------------------------------===//
13
16
17#include "TreeTransform.h"
21#include "clang/AST/Decl.h"
22#include "clang/AST/DeclCXX.h"
26#include "clang/AST/StmtCXX.h"
35#include "clang/Sema/Lookup.h"
37#include "clang/Sema/Scope.h"
39#include "clang/Sema/Sema.h"
40#include "llvm/ADT/IndexedMap.h"
41#include "llvm/ADT/PointerEmbeddedInt.h"
42#include "llvm/ADT/STLExtras.h"
43#include "llvm/ADT/Sequence.h"
44#include "llvm/ADT/SetVector.h"
45#include "llvm/ADT/SmallSet.h"
46#include "llvm/ADT/StringExtras.h"
47#include "llvm/Frontend/OpenMP/OMPAssume.h"
48#include "llvm/Frontend/OpenMP/OMPConstants.h"
49#include "llvm/IR/Assumptions.h"
50#include <optional>
51
52using namespace clang;
53using namespace llvm::omp;
54
55//===----------------------------------------------------------------------===//
56// Stack of data-sharing attributes for variables
57//===----------------------------------------------------------------------===//
58
60 Sema &SemaRef, Expr *E,
62 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
63
65
66namespace {
67/// Default data sharing attributes, which can be applied to directive.
68enum DefaultDataSharingAttributes {
69 DSA_unspecified = 0, /// Data sharing attribute not specified.
70 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
71 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
72 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
73 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
74};
75
76/// Variable Category attributes to restrict the modifier of the
77/// default clause (DefaultDataSharingAttributes)
78/// Not mentioning any Variable category attribute indicates
79/// the modifier (DefaultDataSharingAttributes) is for all variables.
80enum DefaultDataSharingVCAttributes {
81 DSA_VC_all = 0, /// for all variables.
82 DSA_VC_aggregate, /// for aggregate variables.
83 DSA_VC_pointer, /// for pointer variables.
84 DSA_VC_scalar, /// for scalar variables.
85};
86
87/// Stack for tracking declarations used in OpenMP directives and
88/// clauses and their data-sharing attributes.
89class DSAStackTy {
90public:
91 struct DSAVarData {
92 OpenMPDirectiveKind DKind = OMPD_unknown;
93 OpenMPClauseKind CKind = OMPC_unknown;
94 unsigned Modifier = 0;
95 const Expr *RefExpr = nullptr;
96 DeclRefExpr *PrivateCopy = nullptr;
97 SourceLocation ImplicitDSALoc;
98 bool AppliedToPointee = false;
99 DSAVarData() = default;
100 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
101 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
102 SourceLocation ImplicitDSALoc, unsigned Modifier,
103 bool AppliedToPointee)
104 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
105 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
106 AppliedToPointee(AppliedToPointee) {}
107 };
108 using OperatorOffsetTy =
109 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
110 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
111 /// Kind of the declaration used in the uses_allocators clauses.
112 enum class UsesAllocatorsDeclKind {
113 /// Predefined allocator
114 PredefinedAllocator,
115 /// User-defined allocator
116 UserDefinedAllocator,
117 /// The declaration that represent allocator trait
118 AllocatorTrait,
119 };
120
121private:
122 struct DSAInfo {
123 OpenMPClauseKind Attributes = OMPC_unknown;
124 unsigned Modifier = 0;
125 /// Pointer to a reference expression and a flag which shows that the
126 /// variable is marked as lastprivate(true) or not (false).
127 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
128 DeclRefExpr *PrivateCopy = nullptr;
129 /// true if the attribute is applied to the pointee, not the variable
130 /// itself.
131 bool AppliedToPointee = false;
132 };
133 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
134 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
135 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
136 using LoopControlVariablesMapTy =
137 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
138 /// Struct that associates a component with the clause kind where they are
139 /// found.
140 struct MappedExprComponentTy {
142 OpenMPClauseKind Kind = OMPC_unknown;
143 };
144 using MappedExprComponentsTy =
145 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
146 using CriticalsWithHintsTy =
147 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
148 struct ReductionData {
149 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
150 SourceRange ReductionRange;
151 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
152 ReductionData() = default;
153 void set(BinaryOperatorKind BO, SourceRange RR) {
154 ReductionRange = RR;
155 ReductionOp = BO;
156 }
157 void set(const Expr *RefExpr, SourceRange RR) {
158 ReductionRange = RR;
159 ReductionOp = RefExpr;
160 }
161 };
162 using DeclReductionMapTy =
163 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
164 struct DefaultmapInfo {
165 OpenMPDefaultmapClauseModifier ImplicitBehavior =
167 SourceLocation SLoc;
168 DefaultmapInfo() = default;
169 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
170 : ImplicitBehavior(M), SLoc(Loc) {}
171 };
172
173 struct SharingMapTy {
174 DeclSAMapTy SharingMap;
175 DeclReductionMapTy ReductionMap;
176 UsedRefMapTy AlignedMap;
177 UsedRefMapTy NontemporalMap;
178 MappedExprComponentsTy MappedExprComponents;
179 LoopControlVariablesMapTy LCVMap;
180 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
181 SourceLocation DefaultAttrLoc;
182 DefaultDataSharingVCAttributes DefaultVCAttr = DSA_VC_all;
183 SourceLocation DefaultAttrVCLoc;
184 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
185 OpenMPDirectiveKind Directive = OMPD_unknown;
186 DeclarationNameInfo DirectiveName;
187 Scope *CurScope = nullptr;
188 DeclContext *Context = nullptr;
189 SourceLocation ConstructLoc;
190 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
191 /// get the data (loop counters etc.) about enclosing loop-based construct.
192 /// This data is required during codegen.
193 DoacrossClauseMapTy DoacrossDepends;
194 /// First argument (Expr *) contains optional argument of the
195 /// 'ordered' clause, the second one is true if the regions has 'ordered'
196 /// clause, false otherwise.
197 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
198 bool RegionHasOrderConcurrent = false;
199 unsigned AssociatedLoops = 1;
200 bool HasMutipleLoops = false;
201 const Decl *PossiblyLoopCounter = nullptr;
202 bool NowaitRegion = false;
203 bool UntiedRegion = false;
204 bool CancelRegion = false;
205 bool LoopStart = false;
206 bool BodyComplete = false;
207 SourceLocation PrevScanLocation;
208 SourceLocation PrevOrderedLocation;
209 SourceLocation InnerTeamsRegionLoc;
210 /// Reference to the taskgroup task_reduction reference expression.
211 Expr *TaskgroupReductionRef = nullptr;
212 llvm::DenseSet<QualType> MappedClassesQualTypes;
213 SmallVector<Expr *, 4> InnerUsedAllocators;
214 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
215 /// List of globals marked as declare target link in this target region
216 /// (isOpenMPTargetExecutionDirective(Directive) == true).
217 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
218 /// List of decls used in inclusive/exclusive clauses of the scan directive.
219 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
220 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
221 UsesAllocatorsDecls;
222 /// Data is required on creating capture fields for implicit
223 /// default first|private clause.
224 struct ImplicitDefaultFDInfoTy {
225 /// Field decl.
226 const FieldDecl *FD = nullptr;
227 /// Nesting stack level
228 size_t StackLevel = 0;
229 /// Capture variable decl.
230 VarDecl *VD = nullptr;
231 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
232 VarDecl *VD)
233 : FD(FD), StackLevel(StackLevel), VD(VD) {}
234 };
235 /// List of captured fields
236 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
237 ImplicitDefaultFirstprivateFDs;
238 Expr *DeclareMapperVar = nullptr;
239 SmallVector<VarDecl *, 16> IteratorVarDecls;
240 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
241 Scope *CurScope, SourceLocation Loc)
242 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
243 ConstructLoc(Loc) {}
244 SharingMapTy() = default;
245 };
246
247 using StackTy = SmallVector<SharingMapTy, 4>;
248
249 /// Stack of used declaration and their data-sharing attributes.
250 DeclSAMapTy Threadprivates;
251 DeclSAMapTy Groupprivates;
252 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
253 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
254 /// true, if check for DSA must be from parent directive, false, if
255 /// from current directive.
256 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
257 Sema &SemaRef;
258 bool ForceCapturing = false;
259 /// true if all the variables in the target executable directives must be
260 /// captured by reference.
261 bool ForceCaptureByReferenceInTargetExecutable = false;
262 CriticalsWithHintsTy Criticals;
263 unsigned IgnoredStackElements = 0;
264
265 /// Iterators over the stack iterate in order from innermost to outermost
266 /// directive.
267 using const_iterator = StackTy::const_reverse_iterator;
268 const_iterator begin() const {
269 return Stack.empty() ? const_iterator()
270 : Stack.back().first.rbegin() + IgnoredStackElements;
271 }
272 const_iterator end() const {
273 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
274 }
275 using iterator = StackTy::reverse_iterator;
276 iterator begin() {
277 return Stack.empty() ? iterator()
278 : Stack.back().first.rbegin() + IgnoredStackElements;
279 }
280 iterator end() {
281 return Stack.empty() ? iterator() : Stack.back().first.rend();
282 }
283
284 // Convenience operations to get at the elements of the stack.
285
286 bool isStackEmpty() const {
287 return Stack.empty() ||
288 Stack.back().second != CurrentNonCapturingFunctionScope ||
289 Stack.back().first.size() <= IgnoredStackElements;
290 }
291 size_t getStackSize() const {
292 return isStackEmpty() ? 0
293 : Stack.back().first.size() - IgnoredStackElements;
294 }
295
296 SharingMapTy *getTopOfStackOrNull() {
297 size_t Size = getStackSize();
298 if (Size == 0)
299 return nullptr;
300 return &Stack.back().first[Size - 1];
301 }
302 const SharingMapTy *getTopOfStackOrNull() const {
303 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
304 }
305 SharingMapTy &getTopOfStack() {
306 assert(!isStackEmpty() && "no current directive");
307 return *getTopOfStackOrNull();
308 }
309 const SharingMapTy &getTopOfStack() const {
310 return const_cast<DSAStackTy &>(*this).getTopOfStack();
311 }
312
313 SharingMapTy *getSecondOnStackOrNull() {
314 size_t Size = getStackSize();
315 if (Size <= 1)
316 return nullptr;
317 return &Stack.back().first[Size - 2];
318 }
319 const SharingMapTy *getSecondOnStackOrNull() const {
320 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
321 }
322
323 /// Get the stack element at a certain level (previously returned by
324 /// \c getNestingLevel).
325 ///
326 /// Note that nesting levels count from outermost to innermost, and this is
327 /// the reverse of our iteration order where new inner levels are pushed at
328 /// the front of the stack.
329 SharingMapTy &getStackElemAtLevel(unsigned Level) {
330 assert(Level < getStackSize() && "no such stack element");
331 return Stack.back().first[Level];
332 }
333 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
334 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
335 }
336
337 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
338
339 /// Checks if the variable is a local for OpenMP region.
340 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
341
342 /// Vector of previously declared requires directives
343 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
344 /// omp_allocator_handle_t type.
345 QualType OMPAllocatorHandleT;
346 /// omp_depend_t type.
347 QualType OMPDependT;
348 /// omp_event_handle_t type.
349 QualType OMPEventHandleT;
350 /// omp_alloctrait_t type.
351 QualType OMPAlloctraitT;
352 /// Expression for the predefined allocators.
353 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
354 nullptr};
355 /// Vector of previously encountered target directives
356 SmallVector<SourceLocation, 2> TargetLocations;
357 SourceLocation AtomicLocation;
358 /// Vector of declare variant construct traits.
359 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
360
361public:
362 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
363
364 /// Sets omp_allocator_handle_t type.
365 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
366 /// Gets omp_allocator_handle_t type.
367 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
368 /// Sets omp_alloctrait_t type.
369 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
370 /// Gets omp_alloctrait_t type.
371 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
372 /// Sets the given default allocator.
373 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
374 Expr *Allocator) {
375 OMPPredefinedAllocators[AllocatorKind] = Allocator;
376 }
377 /// Returns the specified default allocator.
378 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
379 return OMPPredefinedAllocators[AllocatorKind];
380 }
381 /// Sets omp_depend_t type.
382 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
383 /// Gets omp_depend_t type.
384 QualType getOMPDependT() const { return OMPDependT; }
385
386 /// Sets omp_event_handle_t type.
387 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
388 /// Gets omp_event_handle_t type.
389 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
390
391 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
392 OpenMPClauseKind getClauseParsingMode() const {
393 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
394 return ClauseKindMode;
395 }
396 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
397
398 bool isBodyComplete() const {
399 const SharingMapTy *Top = getTopOfStackOrNull();
400 return Top && Top->BodyComplete;
401 }
402 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
403
404 bool isForceVarCapturing() const { return ForceCapturing; }
405 void setForceVarCapturing(bool V) { ForceCapturing = V; }
406
407 void setForceCaptureByReferenceInTargetExecutable(bool V) {
408 ForceCaptureByReferenceInTargetExecutable = V;
409 }
410 bool isForceCaptureByReferenceInTargetExecutable() const {
411 return ForceCaptureByReferenceInTargetExecutable;
412 }
413
414 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
415 Scope *CurScope, SourceLocation Loc) {
416 assert(!IgnoredStackElements &&
417 "cannot change stack while ignoring elements");
418 if (Stack.empty() ||
419 Stack.back().second != CurrentNonCapturingFunctionScope)
420 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
421 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
422 Stack.back().first.back().DefaultAttrLoc = Loc;
423 }
424
425 void pop() {
426 assert(!IgnoredStackElements &&
427 "cannot change stack while ignoring elements");
428 assert(!Stack.back().first.empty() &&
429 "Data-sharing attributes stack is empty!");
430 Stack.back().first.pop_back();
431 }
432
433 /// RAII object to temporarily leave the scope of a directive when we want to
434 /// logically operate in its parent.
435 class ParentDirectiveScope {
436 DSAStackTy &Self;
437 bool Active;
438
439 public:
440 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
441 : Self(Self), Active(false) {
442 if (Activate)
443 enable();
444 }
445 ~ParentDirectiveScope() { disable(); }
446 void disable() {
447 if (Active) {
448 --Self.IgnoredStackElements;
449 Active = false;
450 }
451 }
452 void enable() {
453 if (!Active) {
454 ++Self.IgnoredStackElements;
455 Active = true;
456 }
457 }
458 };
459
460 /// Marks that we're started loop parsing.
461 void loopInit() {
462 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
463 "Expected loop-based directive.");
464 getTopOfStack().LoopStart = true;
465 }
466 /// Start capturing of the variables in the loop context.
467 void loopStart() {
468 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
469 "Expected loop-based directive.");
470 getTopOfStack().LoopStart = false;
471 }
472 /// true, if variables are captured, false otherwise.
473 bool isLoopStarted() const {
474 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
475 "Expected loop-based directive.");
476 return !getTopOfStack().LoopStart;
477 }
478 /// Marks (or clears) declaration as possibly loop counter.
479 void resetPossibleLoopCounter(const Decl *D = nullptr) {
480 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
481 }
482 /// Gets the possible loop counter decl.
483 const Decl *getPossiblyLoopCounter() const {
484 return getTopOfStack().PossiblyLoopCounter;
485 }
486 /// Start new OpenMP region stack in new non-capturing function.
487 void pushFunction() {
488 assert(!IgnoredStackElements &&
489 "cannot change stack while ignoring elements");
490 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
491 assert(!isa<CapturingScopeInfo>(CurFnScope));
492 CurrentNonCapturingFunctionScope = CurFnScope;
493 }
494 /// Pop region stack for non-capturing function.
495 void popFunction(const FunctionScopeInfo *OldFSI) {
496 assert(!IgnoredStackElements &&
497 "cannot change stack while ignoring elements");
498 if (!Stack.empty() && Stack.back().second == OldFSI) {
499 assert(Stack.back().first.empty());
500 Stack.pop_back();
501 }
502 CurrentNonCapturingFunctionScope = nullptr;
503 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
504 if (!isa<CapturingScopeInfo>(FSI)) {
505 CurrentNonCapturingFunctionScope = FSI;
506 break;
507 }
508 }
509 }
510
511 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
512 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
513 }
514 std::pair<const OMPCriticalDirective *, llvm::APSInt>
515 getCriticalWithHint(const DeclarationNameInfo &Name) const {
516 auto I = Criticals.find(Name.getAsString());
517 if (I != Criticals.end())
518 return I->second;
519 return std::make_pair(nullptr, llvm::APSInt());
520 }
521 /// If 'aligned' declaration for given variable \a D was not seen yet,
522 /// add it and return NULL; otherwise return previous occurrence's expression
523 /// for diagnostics.
524 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
525 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
526 /// add it and return NULL; otherwise return previous occurrence's expression
527 /// for diagnostics.
528 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
529
530 /// Register specified variable as loop control variable.
531 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
532 /// Check if the specified variable is a loop control variable for
533 /// current region.
534 /// \return The index of the loop control variable in the list of associated
535 /// for-loops (from outer to inner).
536 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
537 /// Check if the specified variable is a loop control variable for
538 /// parent region.
539 /// \return The index of the loop control variable in the list of associated
540 /// for-loops (from outer to inner).
541 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
542 /// Check if the specified variable is a loop control variable for
543 /// current region.
544 /// \return The index of the loop control variable in the list of associated
545 /// for-loops (from outer to inner).
546 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
547 unsigned Level) const;
548 /// Get the loop control variable for the I-th loop (or nullptr) in
549 /// parent directive.
550 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
551
552 /// Marks the specified decl \p D as used in scan directive.
553 void markDeclAsUsedInScanDirective(ValueDecl *D) {
554 if (SharingMapTy *Stack = getSecondOnStackOrNull())
555 Stack->UsedInScanDirective.insert(D);
556 }
557
558 /// Checks if the specified declaration was used in the inner scan directive.
559 bool isUsedInScanDirective(ValueDecl *D) const {
560 if (const SharingMapTy *Stack = getTopOfStackOrNull())
561 return Stack->UsedInScanDirective.contains(D);
562 return false;
563 }
564
565 /// Adds explicit data sharing attribute to the specified declaration.
566 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
567 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
568 bool AppliedToPointee = false);
569
570 /// Adds additional information for the reduction items with the reduction id
571 /// represented as an operator.
572 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
574 /// Adds additional information for the reduction items with the reduction id
575 /// represented as reduction identifier.
576 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
577 const Expr *ReductionRef);
578 /// Returns the location and reduction operation from the innermost parent
579 /// region for the given \p D.
580 const DSAVarData
581 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
583 Expr *&TaskgroupDescriptor) const;
584 /// Returns the location and reduction operation from the innermost parent
585 /// region for the given \p D.
586 const DSAVarData
587 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
588 const Expr *&ReductionRef,
589 Expr *&TaskgroupDescriptor) const;
590 /// Return reduction reference expression for the current taskgroup or
591 /// parallel/worksharing directives with task reductions.
592 Expr *getTaskgroupReductionRef() const {
593 assert((getTopOfStack().Directive == OMPD_taskgroup ||
594 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
595 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
596 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
597 "taskgroup reference expression requested for non taskgroup or "
598 "parallel/worksharing directive.");
599 return getTopOfStack().TaskgroupReductionRef;
600 }
601 /// Checks if the given \p VD declaration is actually a taskgroup reduction
602 /// descriptor variable at the \p Level of OpenMP regions.
603 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
604 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
605 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
606 ->getDecl() == VD;
607 }
608
609 /// Returns data sharing attributes from top of the stack for the
610 /// specified declaration.
611 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
612 /// Returns data-sharing attributes for the specified declaration.
613 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
614 /// Returns data-sharing attributes for the specified declaration.
615 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
616 /// Checks if the specified variables has data-sharing attributes which
617 /// match specified \a CPred predicate in any directive which matches \a DPred
618 /// predicate.
619 const DSAVarData
620 hasDSA(ValueDecl *D,
621 const llvm::function_ref<bool(OpenMPClauseKind, bool,
622 DefaultDataSharingAttributes)>
623 CPred,
624 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
625 bool FromParent) const;
626 /// Checks if the specified variables has data-sharing attributes which
627 /// match specified \a CPred predicate in any innermost directive which
628 /// matches \a DPred predicate.
629 const DSAVarData
630 hasInnermostDSA(ValueDecl *D,
631 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
632 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
633 bool FromParent) const;
634 /// Checks if the specified variables has explicit data-sharing
635 /// attributes which match specified \a CPred predicate at the specified
636 /// OpenMP region.
637 bool
638 hasExplicitDSA(const ValueDecl *D,
639 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
640 unsigned Level, bool NotLastprivate = false) const;
641
642 /// Returns true if the directive at level \Level matches in the
643 /// specified \a DPred predicate.
644 bool hasExplicitDirective(
645 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
646 unsigned Level) const;
647
648 /// Finds a directive which matches specified \a DPred predicate.
649 bool hasDirective(
650 const llvm::function_ref<bool(
651 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
652 DPred,
653 bool FromParent) const;
654
655 /// Returns currently analyzed directive.
656 OpenMPDirectiveKind getCurrentDirective() const {
657 const SharingMapTy *Top = getTopOfStackOrNull();
658 return Top ? Top->Directive : OMPD_unknown;
659 }
660 /// Returns directive kind at specified level.
661 OpenMPDirectiveKind getDirective(unsigned Level) const {
662 assert(!isStackEmpty() && "No directive at specified level.");
663 return getStackElemAtLevel(Level).Directive;
664 }
665 /// Returns the capture region at the specified level.
666 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
667 unsigned OpenMPCaptureLevel) const {
668 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
669 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
670 return CaptureRegions[OpenMPCaptureLevel];
671 }
672 /// Returns parent directive.
673 OpenMPDirectiveKind getParentDirective() const {
674 const SharingMapTy *Parent = getSecondOnStackOrNull();
675 return Parent ? Parent->Directive : OMPD_unknown;
676 }
677
678 /// Add requires decl to internal vector
679 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
680
681 /// Checks if the defined 'requires' directive has specified type of clause.
682 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
683 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
684 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
685 return isa<ClauseType>(C);
686 });
687 });
688 }
689
690 /// Checks for a duplicate clause amongst previously declared requires
691 /// directives
692 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
693 bool IsDuplicate = false;
694 for (OMPClause *CNew : ClauseList) {
695 for (const OMPRequiresDecl *D : RequiresDecls) {
696 for (const OMPClause *CPrev : D->clauselists()) {
697 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
698 SemaRef.Diag(CNew->getBeginLoc(),
699 diag::err_omp_requires_clause_redeclaration)
700 << getOpenMPClauseNameForDiag(CNew->getClauseKind());
701 SemaRef.Diag(CPrev->getBeginLoc(),
702 diag::note_omp_requires_previous_clause)
703 << getOpenMPClauseNameForDiag(CPrev->getClauseKind());
704 IsDuplicate = true;
705 }
706 }
707 }
708 }
709 return IsDuplicate;
710 }
711
712 /// Add location of previously encountered target to internal vector
713 void addTargetDirLocation(SourceLocation LocStart) {
714 TargetLocations.push_back(LocStart);
715 }
716
717 /// Add location for the first encountered atomic directive.
718 void addAtomicDirectiveLoc(SourceLocation Loc) {
719 if (AtomicLocation.isInvalid())
720 AtomicLocation = Loc;
721 }
722
723 /// Returns the location of the first encountered atomic directive in the
724 /// module.
725 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
726
727 // Return previously encountered target region locations.
728 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
729 return TargetLocations;
730 }
731
732 /// Set default data sharing attribute to none.
733 void setDefaultDSANone(SourceLocation Loc) {
734 getTopOfStack().DefaultAttr = DSA_none;
735 getTopOfStack().DefaultAttrLoc = Loc;
736 }
737 /// Set default data sharing attribute to shared.
738 void setDefaultDSAShared(SourceLocation Loc) {
739 getTopOfStack().DefaultAttr = DSA_shared;
740 getTopOfStack().DefaultAttrLoc = Loc;
741 }
742 /// Set default data sharing attribute to private.
743 void setDefaultDSAPrivate(SourceLocation Loc) {
744 getTopOfStack().DefaultAttr = DSA_private;
745 getTopOfStack().DefaultAttrLoc = Loc;
746 }
747 /// Set default data sharing attribute to firstprivate.
748 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
749 getTopOfStack().DefaultAttr = DSA_firstprivate;
750 getTopOfStack().DefaultAttrLoc = Loc;
751 }
752 /// Set default data sharing variable category attribute to aggregate.
753 void setDefaultDSAVCAggregate(SourceLocation VCLoc) {
754 getTopOfStack().DefaultVCAttr = DSA_VC_aggregate;
755 getTopOfStack().DefaultAttrVCLoc = VCLoc;
756 }
757 /// Set default data sharing variable category attribute to all.
758 void setDefaultDSAVCAll(SourceLocation VCLoc) {
759 getTopOfStack().DefaultVCAttr = DSA_VC_all;
760 getTopOfStack().DefaultAttrVCLoc = VCLoc;
761 }
762 /// Set default data sharing variable category attribute to pointer.
763 void setDefaultDSAVCPointer(SourceLocation VCLoc) {
764 getTopOfStack().DefaultVCAttr = DSA_VC_pointer;
765 getTopOfStack().DefaultAttrVCLoc = VCLoc;
766 }
767 /// Set default data sharing variable category attribute to scalar.
768 void setDefaultDSAVCScalar(SourceLocation VCLoc) {
769 getTopOfStack().DefaultVCAttr = DSA_VC_scalar;
770 getTopOfStack().DefaultAttrVCLoc = VCLoc;
771 }
772 /// Set default data mapping attribute to Modifier:Kind
773 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
774 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
775 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
776 DMI.ImplicitBehavior = M;
777 DMI.SLoc = Loc;
778 }
779 /// Check whether the implicit-behavior has been set in defaultmap
780 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
781 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
782 return getTopOfStack()
783 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
784 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
785 getTopOfStack()
786 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
787 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
788 getTopOfStack()
789 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
790 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
791 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
793 }
794
795 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
796 return ConstructTraits;
797 }
798 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
799 bool ScopeEntry) {
800 if (ScopeEntry)
801 ConstructTraits.append(Traits.begin(), Traits.end());
802 else
803 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
804 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
805 assert(Top == Trait && "Something left a trait on the stack!");
806 (void)Trait;
807 (void)Top;
808 }
809 }
810
811 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
812 return getStackSize() <= Level ? DSA_unspecified
813 : getStackElemAtLevel(Level).DefaultAttr;
814 }
815 DefaultDataSharingAttributes getDefaultDSA() const {
816 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
817 }
818 SourceLocation getDefaultDSALocation() const {
819 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
820 }
822 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
823 return isStackEmpty()
825 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
826 }
828 getDefaultmapModifierAtLevel(unsigned Level,
829 OpenMPDefaultmapClauseKind Kind) const {
830 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
831 }
832 bool isDefaultmapCapturedByRef(unsigned Level,
833 OpenMPDefaultmapClauseKind Kind) const {
835 getDefaultmapModifierAtLevel(Level, Kind);
836 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
837 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
838 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
839 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
840 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
841 (M == OMPC_DEFAULTMAP_MODIFIER_present) ||
842 (M == OMPC_DEFAULTMAP_MODIFIER_storage);
843 }
844 return true;
845 }
846 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
848 switch (Kind) {
849 case OMPC_DEFAULTMAP_scalar:
850 case OMPC_DEFAULTMAP_pointer:
851 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
852 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
853 (M == OMPC_DEFAULTMAP_MODIFIER_default);
854 case OMPC_DEFAULTMAP_aggregate:
855 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
856 default:
857 break;
858 }
859 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
860 }
861 bool mustBeFirstprivateAtLevel(unsigned Level,
862 OpenMPDefaultmapClauseKind Kind) const {
864 getDefaultmapModifierAtLevel(Level, Kind);
865 return mustBeFirstprivateBase(M, Kind);
866 }
867 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
868 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
869 return mustBeFirstprivateBase(M, Kind);
870 }
871
872 /// Checks if the specified variable is a threadprivate.
873 bool isThreadPrivate(VarDecl *D) {
874 const DSAVarData DVar = getTopDSA(D, false);
875 return isOpenMPThreadPrivate(DVar.CKind);
876 }
877
878 /// Marks current region as ordered (it has an 'ordered' clause).
879 void setOrderedRegion(bool IsOrdered, const Expr *Param,
880 OMPOrderedClause *Clause) {
881 if (IsOrdered)
882 getTopOfStack().OrderedRegion.emplace(Param, Clause);
883 else
884 getTopOfStack().OrderedRegion.reset();
885 }
886 /// Returns true, if region is ordered (has associated 'ordered' clause),
887 /// false - otherwise.
888 bool isOrderedRegion() const {
889 if (const SharingMapTy *Top = getTopOfStackOrNull())
890 return Top->OrderedRegion.has_value();
891 return false;
892 }
893 /// Returns optional parameter for the ordered region.
894 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
895 if (const SharingMapTy *Top = getTopOfStackOrNull())
896 if (Top->OrderedRegion)
897 return *Top->OrderedRegion;
898 return std::make_pair(nullptr, nullptr);
899 }
900 /// Returns true, if parent region is ordered (has associated
901 /// 'ordered' clause), false - otherwise.
902 bool isParentOrderedRegion() const {
903 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
904 return Parent->OrderedRegion.has_value();
905 return false;
906 }
907 /// Returns optional parameter for the ordered region.
908 std::pair<const Expr *, OMPOrderedClause *>
909 getParentOrderedRegionParam() const {
910 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
911 if (Parent->OrderedRegion)
912 return *Parent->OrderedRegion;
913 return std::make_pair(nullptr, nullptr);
914 }
915 /// Marks current region as having an 'order' clause.
916 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
917 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
918 }
919 /// Returns true, if parent region is order (has associated
920 /// 'order' clause), false - otherwise.
921 bool isParentOrderConcurrent() const {
922 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
923 return Parent->RegionHasOrderConcurrent;
924 return false;
925 }
926 /// Marks current region as nowait (it has a 'nowait' clause).
927 void setNowaitRegion(bool IsNowait = true) {
928 getTopOfStack().NowaitRegion = IsNowait;
929 }
930 /// Returns true, if parent region is nowait (has associated
931 /// 'nowait' clause), false - otherwise.
932 bool isParentNowaitRegion() const {
933 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
934 return Parent->NowaitRegion;
935 return false;
936 }
937 /// Marks current region as untied (it has a 'untied' clause).
938 void setUntiedRegion(bool IsUntied = true) {
939 getTopOfStack().UntiedRegion = IsUntied;
940 }
941 /// Return true if current region is untied.
942 bool isUntiedRegion() const {
943 const SharingMapTy *Top = getTopOfStackOrNull();
944 return Top ? Top->UntiedRegion : false;
945 }
946 /// Marks parent region as cancel region.
947 void setParentCancelRegion(bool Cancel = true) {
948 if (SharingMapTy *Parent = getSecondOnStackOrNull())
949 Parent->CancelRegion |= Cancel;
950 }
951 /// Return true if current region has inner cancel construct.
952 bool isCancelRegion() const {
953 const SharingMapTy *Top = getTopOfStackOrNull();
954 return Top ? Top->CancelRegion : false;
955 }
956
957 /// Mark that parent region already has scan directive.
958 void setParentHasScanDirective(SourceLocation Loc) {
959 if (SharingMapTy *Parent = getSecondOnStackOrNull())
960 Parent->PrevScanLocation = Loc;
961 }
962 /// Return true if current region has inner cancel construct.
963 bool doesParentHasScanDirective() const {
964 const SharingMapTy *Top = getSecondOnStackOrNull();
965 return Top ? Top->PrevScanLocation.isValid() : false;
966 }
967 /// Return true if current region has inner cancel construct.
968 SourceLocation getParentScanDirectiveLoc() const {
969 const SharingMapTy *Top = getSecondOnStackOrNull();
970 return Top ? Top->PrevScanLocation : SourceLocation();
971 }
972 /// Mark that parent region already has ordered directive.
973 void setParentHasOrderedDirective(SourceLocation Loc) {
974 if (SharingMapTy *Parent = getSecondOnStackOrNull())
975 Parent->PrevOrderedLocation = Loc;
976 }
977 /// Return true if current region has inner ordered construct.
978 bool doesParentHasOrderedDirective() const {
979 const SharingMapTy *Top = getSecondOnStackOrNull();
980 return Top ? Top->PrevOrderedLocation.isValid() : false;
981 }
982 /// Returns the location of the previously specified ordered directive.
983 SourceLocation getParentOrderedDirectiveLoc() const {
984 const SharingMapTy *Top = getSecondOnStackOrNull();
985 return Top ? Top->PrevOrderedLocation : SourceLocation();
986 }
987
988 /// Set collapse value for the region.
989 void setAssociatedLoops(unsigned Val) {
990 getTopOfStack().AssociatedLoops = Val;
991 if (Val > 1)
992 getTopOfStack().HasMutipleLoops = true;
993 }
994 /// Return collapse value for region.
995 unsigned getAssociatedLoops() const {
996 const SharingMapTy *Top = getTopOfStackOrNull();
997 return Top ? Top->AssociatedLoops : 0;
998 }
999 /// Returns true if the construct is associated with multiple loops.
1000 bool hasMutipleLoops() const {
1001 const SharingMapTy *Top = getTopOfStackOrNull();
1002 return Top ? Top->HasMutipleLoops : false;
1003 }
1004
1005 /// Marks current target region as one with closely nested teams
1006 /// region.
1007 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
1008 if (SharingMapTy *Parent = getSecondOnStackOrNull())
1009 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
1010 }
1011 /// Returns true, if current region has closely nested teams region.
1012 bool hasInnerTeamsRegion() const {
1013 return getInnerTeamsRegionLoc().isValid();
1014 }
1015 /// Returns location of the nested teams region (if any).
1016 SourceLocation getInnerTeamsRegionLoc() const {
1017 const SharingMapTy *Top = getTopOfStackOrNull();
1018 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1019 }
1020
1021 Scope *getCurScope() const {
1022 const SharingMapTy *Top = getTopOfStackOrNull();
1023 return Top ? Top->CurScope : nullptr;
1024 }
1025 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1026 SourceLocation getConstructLoc() const {
1027 const SharingMapTy *Top = getTopOfStackOrNull();
1028 return Top ? Top->ConstructLoc : SourceLocation();
1029 }
1030
1031 /// Do the check specified in \a Check to all component lists and return true
1032 /// if any issue is found.
1033 bool checkMappableExprComponentListsForDecl(
1034 const ValueDecl *VD, bool CurrentRegionOnly,
1035 const llvm::function_ref<
1038 Check) const {
1039 if (isStackEmpty())
1040 return false;
1041 auto SI = begin();
1042 auto SE = end();
1043
1044 if (SI == SE)
1045 return false;
1046
1047 if (CurrentRegionOnly)
1048 SE = std::next(SI);
1049 else
1050 std::advance(SI, 1);
1051
1052 for (; SI != SE; ++SI) {
1053 auto MI = SI->MappedExprComponents.find(VD);
1054 if (MI != SI->MappedExprComponents.end())
1056 MI->second.Components)
1057 if (Check(L, MI->second.Kind))
1058 return true;
1059 }
1060 return false;
1061 }
1062
1063 /// Do the check specified in \a Check to all component lists at a given level
1064 /// and return true if any issue is found.
1065 bool checkMappableExprComponentListsForDeclAtLevel(
1066 const ValueDecl *VD, unsigned Level,
1067 const llvm::function_ref<
1070 Check) const {
1071 if (getStackSize() <= Level)
1072 return false;
1073
1074 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1075 auto MI = StackElem.MappedExprComponents.find(VD);
1076 if (MI != StackElem.MappedExprComponents.end())
1078 MI->second.Components)
1079 if (Check(L, MI->second.Kind))
1080 return true;
1081 return false;
1082 }
1083
1084 /// Create a new mappable expression component list associated with a given
1085 /// declaration and initialize it with the provided list of components.
1086 void addMappableExpressionComponents(
1087 const ValueDecl *VD,
1089 OpenMPClauseKind WhereFoundClauseKind) {
1090 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1091 // Create new entry and append the new components there.
1092 MEC.Components.resize(MEC.Components.size() + 1);
1093 MEC.Components.back().append(Components.begin(), Components.end());
1094 MEC.Kind = WhereFoundClauseKind;
1095 }
1096
1097 unsigned getNestingLevel() const {
1098 assert(!isStackEmpty());
1099 return getStackSize() - 1;
1100 }
1101 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1102 SharingMapTy *Parent = getSecondOnStackOrNull();
1103 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1104 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1105 }
1106 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1107 getDoacrossDependClauses() const {
1108 const SharingMapTy &StackElem = getTopOfStack();
1109 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1110 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1111 return llvm::make_range(Ref.begin(), Ref.end());
1112 }
1113 return llvm::make_range(StackElem.DoacrossDepends.end(),
1114 StackElem.DoacrossDepends.end());
1115 }
1116
1117 // Store types of classes which have been explicitly mapped
1118 void addMappedClassesQualTypes(QualType QT) {
1119 SharingMapTy &StackElem = getTopOfStack();
1120 StackElem.MappedClassesQualTypes.insert(QT);
1121 }
1122
1123 // Return set of mapped classes types
1124 bool isClassPreviouslyMapped(QualType QT) const {
1125 const SharingMapTy &StackElem = getTopOfStack();
1126 return StackElem.MappedClassesQualTypes.contains(QT);
1127 }
1128
1129 /// Adds global declare target to the parent target region.
1130 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1131 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1132 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1133 "Expected declare target link global.");
1134 for (auto &Elem : *this) {
1135 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1136 Elem.DeclareTargetLinkVarDecls.push_back(E);
1137 return;
1138 }
1139 }
1140 }
1141
1142 /// Returns the list of globals with declare target link if current directive
1143 /// is target.
1144 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1145 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1146 "Expected target executable directive.");
1147 return getTopOfStack().DeclareTargetLinkVarDecls;
1148 }
1149
1150 /// Adds list of allocators expressions.
1151 void addInnerAllocatorExpr(Expr *E) {
1152 getTopOfStack().InnerUsedAllocators.push_back(E);
1153 }
1154 /// Return list of used allocators.
1155 ArrayRef<Expr *> getInnerAllocators() const {
1156 return getTopOfStack().InnerUsedAllocators;
1157 }
1158 /// Marks the declaration as implicitly firstprivate nin the task-based
1159 /// regions.
1160 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1161 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1162 }
1163 /// Checks if the decl is implicitly firstprivate in the task-based region.
1164 bool isImplicitTaskFirstprivate(Decl *D) const {
1165 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1166 }
1167
1168 /// Marks decl as used in uses_allocators clause as the allocator.
1169 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1170 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1171 }
1172 /// Checks if specified decl is used in uses allocator clause as the
1173 /// allocator.
1174 std::optional<UsesAllocatorsDeclKind>
1175 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1176 const SharingMapTy &StackElem = getTopOfStack();
1177 auto I = StackElem.UsesAllocatorsDecls.find(D);
1178 if (I == StackElem.UsesAllocatorsDecls.end())
1179 return std::nullopt;
1180 return I->getSecond();
1181 }
1182 std::optional<UsesAllocatorsDeclKind>
1183 isUsesAllocatorsDecl(const Decl *D) const {
1184 const SharingMapTy &StackElem = getTopOfStack();
1185 auto I = StackElem.UsesAllocatorsDecls.find(D);
1186 if (I == StackElem.UsesAllocatorsDecls.end())
1187 return std::nullopt;
1188 return I->getSecond();
1189 }
1190
1191 void addDeclareMapperVarRef(Expr *Ref) {
1192 SharingMapTy &StackElem = getTopOfStack();
1193 StackElem.DeclareMapperVar = Ref;
1194 }
1195 const Expr *getDeclareMapperVarRef() const {
1196 const SharingMapTy *Top = getTopOfStackOrNull();
1197 return Top ? Top->DeclareMapperVar : nullptr;
1198 }
1199
1200 /// Add a new iterator variable.
1201 void addIteratorVarDecl(VarDecl *VD) {
1202 SharingMapTy &StackElem = getTopOfStack();
1203 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1204 }
1205 /// Check if variable declaration is an iterator VarDecl.
1206 bool isIteratorVarDecl(const VarDecl *VD) const {
1207 const SharingMapTy *Top = getTopOfStackOrNull();
1208 if (!Top)
1209 return false;
1210
1211 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1212 }
1213 /// get captured field from ImplicitDefaultFirstprivateFDs
1214 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1215 const_iterator I = begin();
1216 const_iterator EndI = end();
1217 size_t StackLevel = getStackSize();
1218 for (; I != EndI; ++I) {
1219 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1220 break;
1221 StackLevel--;
1222 }
1223 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1224 if (I == EndI)
1225 return nullptr;
1226 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1227 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1228 return IFD.VD;
1229 return nullptr;
1230 }
1231 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1232 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1233 const_iterator I = begin();
1234 const_iterator EndI = end();
1235 for (; I != EndI; ++I)
1236 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1237 break;
1238 if (I == EndI)
1239 return false;
1240 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1241 if (IFD.VD == VD)
1242 return true;
1243 return false;
1244 }
1245 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1246 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1247 iterator I = begin();
1248 const_iterator EndI = end();
1249 size_t StackLevel = getStackSize();
1250 for (; I != EndI; ++I) {
1251 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1252 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1253 break;
1254 }
1255 StackLevel--;
1256 }
1257 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1258 }
1259};
1260
1261bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1262 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1263}
1264
1265bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1266 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1267 DKind == OMPD_unknown;
1268}
1269
1270} // namespace
1271
1272static const Expr *getExprAsWritten(const Expr *E) {
1273 if (const auto *FE = dyn_cast<FullExpr>(E))
1274 E = FE->getSubExpr();
1275
1276 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1277 E = MTE->getSubExpr();
1278
1279 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1280 E = Binder->getSubExpr();
1281
1282 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1283 E = ICE->getSubExprAsWritten();
1284 return E->IgnoreParens();
1285}
1286
1288 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1289}
1290
1291static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1292 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1293 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1294 D = ME->getMemberDecl();
1295
1297 return D;
1298}
1299
1301 return const_cast<ValueDecl *>(
1302 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1303}
1304
1306 if (C == OMPC_threadprivate)
1307 return getOpenMPClauseName(C).str() + " or thread local";
1308 return getOpenMPClauseName(C).str();
1309}
1310
1311DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1312 ValueDecl *D) const {
1313 D = getCanonicalDecl(D);
1314 auto *VD = dyn_cast<VarDecl>(D);
1315 const auto *FD = dyn_cast<FieldDecl>(D);
1316 DSAVarData DVar;
1317 if (Iter == end()) {
1318 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1319 // in a region but not in construct]
1320 // File-scope or namespace-scope variables referenced in called routines
1321 // in the region are shared unless they appear in a threadprivate
1322 // directive.
1323 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1324 DVar.CKind = OMPC_shared;
1325
1326 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1327 // in a region but not in construct]
1328 // Variables with static storage duration that are declared in called
1329 // routines in the region are shared.
1330 if (VD && VD->hasGlobalStorage())
1331 DVar.CKind = OMPC_shared;
1332
1333 // Non-static data members are shared by default.
1334 if (FD)
1335 DVar.CKind = OMPC_shared;
1336
1337 return DVar;
1338 }
1339
1340 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1341 // in a Construct, C/C++, predetermined, p.1]
1342 // Variables with automatic storage duration that are declared in a scope
1343 // inside the construct are private.
1344 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1345 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1346 DVar.CKind = OMPC_private;
1347 return DVar;
1348 }
1349
1350 DVar.DKind = Iter->Directive;
1351 // Explicitly specified attributes and local variables with predetermined
1352 // attributes.
1353 if (Iter->SharingMap.count(D)) {
1354 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1355 DVar.RefExpr = Data.RefExpr.getPointer();
1356 DVar.PrivateCopy = Data.PrivateCopy;
1357 DVar.CKind = Data.Attributes;
1358 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1359 DVar.Modifier = Data.Modifier;
1360 DVar.AppliedToPointee = Data.AppliedToPointee;
1361 return DVar;
1362 }
1363
1364 DefaultDataSharingAttributes IterDA = Iter->DefaultAttr;
1365 switch (Iter->DefaultVCAttr) {
1366 case DSA_VC_aggregate:
1367 if (!D->getType()->isAggregateType())
1368 IterDA = DSA_none;
1369 break;
1370 case DSA_VC_pointer:
1371 if (!D->getType()->isPointerType())
1372 IterDA = DSA_none;
1373 break;
1374 case DSA_VC_scalar:
1375 if (!D->getType()->isScalarType())
1376 IterDA = DSA_none;
1377 break;
1378 case DSA_VC_all:
1379 break;
1380 }
1381
1382 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1383 // in a Construct, C/C++, implicitly determined, p.1]
1384 // In a parallel or task construct, the data-sharing attributes of these
1385 // variables are determined by the default clause, if present.
1386 switch (IterDA) {
1387 case DSA_shared:
1388 DVar.CKind = OMPC_shared;
1389 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1390 return DVar;
1391 case DSA_none:
1392 return DVar;
1393 case DSA_firstprivate:
1394 if (VD && VD->getStorageDuration() == SD_Static &&
1395 VD->getDeclContext()->isFileContext()) {
1396 DVar.CKind = OMPC_unknown;
1397 } else {
1398 DVar.CKind = OMPC_firstprivate;
1399 }
1400 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1401 return DVar;
1402 case DSA_private:
1403 // each variable with static storage duration that is declared
1404 // in a namespace or global scope and referenced in the construct,
1405 // and that does not have a predetermined data-sharing attribute
1406 if (VD && VD->getStorageDuration() == SD_Static &&
1407 VD->getDeclContext()->isFileContext()) {
1408 DVar.CKind = OMPC_unknown;
1409 } else {
1410 DVar.CKind = OMPC_private;
1411 }
1412 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1413 return DVar;
1414 case DSA_unspecified:
1415 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1416 // in a Construct, implicitly determined, p.2]
1417 // In a parallel construct, if no default clause is present, these
1418 // variables are shared.
1419 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1420 if ((isOpenMPParallelDirective(DVar.DKind) &&
1421 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1422 isOpenMPTeamsDirective(DVar.DKind)) {
1423 DVar.CKind = OMPC_shared;
1424 return DVar;
1425 }
1426
1427 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1428 // in a Construct, implicitly determined, p.4]
1429 // In a task construct, if no default clause is present, a variable that in
1430 // the enclosing context is determined to be shared by all implicit tasks
1431 // bound to the current team is shared.
1432 if (isOpenMPTaskingDirective(DVar.DKind)) {
1433 DSAVarData DVarTemp;
1434 const_iterator I = Iter, E = end();
1435 do {
1436 ++I;
1437 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1438 // Referenced in a Construct, implicitly determined, p.6]
1439 // In a task construct, if no default clause is present, a variable
1440 // whose data-sharing attribute is not determined by the rules above is
1441 // firstprivate.
1442 DVarTemp = getDSA(I, D);
1443 if (DVarTemp.CKind != OMPC_shared) {
1444 DVar.RefExpr = nullptr;
1445 DVar.CKind = OMPC_firstprivate;
1446 return DVar;
1447 }
1448 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1449 DVar.CKind =
1450 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1451 return DVar;
1452 }
1453 }
1454 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1455 // in a Construct, implicitly determined, p.3]
1456 // For constructs other than task, if no default clause is present, these
1457 // variables inherit their data-sharing attributes from the enclosing
1458 // context.
1459 return getDSA(++Iter, D);
1460}
1461
1462const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1463 const Expr *NewDE) {
1464 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1465 D = getCanonicalDecl(D);
1466 SharingMapTy &StackElem = getTopOfStack();
1467 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(D, NewDE);
1468 if (Inserted) {
1469 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1470 return nullptr;
1471 }
1472 assert(It->second && "Unexpected nullptr expr in the aligned map");
1473 return It->second;
1474}
1475
1476const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1477 const Expr *NewDE) {
1478 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1479 D = getCanonicalDecl(D);
1480 SharingMapTy &StackElem = getTopOfStack();
1481 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(D, NewDE);
1482 if (Inserted) {
1483 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1484 return nullptr;
1485 }
1486 assert(It->second && "Unexpected nullptr expr in the aligned map");
1487 return It->second;
1488}
1489
1490void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1491 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1492 D = getCanonicalDecl(D);
1493 SharingMapTy &StackElem = getTopOfStack();
1494 StackElem.LCVMap.try_emplace(
1495 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1496}
1497
1498const DSAStackTy::LCDeclInfo
1499DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1500 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1501 D = getCanonicalDecl(D);
1502 const SharingMapTy &StackElem = getTopOfStack();
1503 auto It = StackElem.LCVMap.find(D);
1504 if (It != StackElem.LCVMap.end())
1505 return It->second;
1506 return {0, nullptr};
1507}
1508
1509const DSAStackTy::LCDeclInfo
1510DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1511 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1512 D = getCanonicalDecl(D);
1513 for (unsigned I = Level + 1; I > 0; --I) {
1514 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1515 auto It = StackElem.LCVMap.find(D);
1516 if (It != StackElem.LCVMap.end())
1517 return It->second;
1518 }
1519 return {0, nullptr};
1520}
1521
1522const DSAStackTy::LCDeclInfo
1523DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1524 const SharingMapTy *Parent = getSecondOnStackOrNull();
1525 assert(Parent && "Data-sharing attributes stack is empty");
1526 D = getCanonicalDecl(D);
1527 auto It = Parent->LCVMap.find(D);
1528 if (It != Parent->LCVMap.end())
1529 return It->second;
1530 return {0, nullptr};
1531}
1532
1533const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1534 const SharingMapTy *Parent = getSecondOnStackOrNull();
1535 assert(Parent && "Data-sharing attributes stack is empty");
1536 if (Parent->LCVMap.size() < I)
1537 return nullptr;
1538 for (const auto &Pair : Parent->LCVMap)
1539 if (Pair.second.first == I)
1540 return Pair.first;
1541 return nullptr;
1542}
1543
1544void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1545 DeclRefExpr *PrivateCopy, unsigned Modifier,
1546 bool AppliedToPointee) {
1547 D = getCanonicalDecl(D);
1548 if (A == OMPC_threadprivate) {
1549 DSAInfo &Data = Threadprivates[D];
1550 Data.Attributes = A;
1551 Data.RefExpr.setPointer(E);
1552 Data.PrivateCopy = nullptr;
1553 Data.Modifier = Modifier;
1554 } else if (A == OMPC_groupprivate) {
1555 DSAInfo &Data = Groupprivates[D];
1556 Data.Attributes = A;
1557 Data.RefExpr.setPointer(E);
1558 Data.PrivateCopy = nullptr;
1559 Data.Modifier = Modifier;
1560 } else {
1561 DSAInfo &Data = getTopOfStack().SharingMap[D];
1562 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1563 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1564 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1565 (isLoopControlVariable(D).first && A == OMPC_private));
1566 Data.Modifier = Modifier;
1567 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1568 Data.RefExpr.setInt(/*IntVal=*/true);
1569 return;
1570 }
1571 const bool IsLastprivate =
1572 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1573 Data.Attributes = A;
1574 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1575 Data.PrivateCopy = PrivateCopy;
1576 Data.AppliedToPointee = AppliedToPointee;
1577 if (PrivateCopy) {
1578 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1579 Data.Modifier = Modifier;
1580 Data.Attributes = A;
1581 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1582 Data.PrivateCopy = nullptr;
1583 Data.AppliedToPointee = AppliedToPointee;
1584 }
1585 }
1586}
1587
1588/// Build a variable declaration for OpenMP loop iteration variable.
1590 StringRef Name, const AttrVec *Attrs = nullptr,
1591 DeclRefExpr *OrigRef = nullptr) {
1592 DeclContext *DC = SemaRef.CurContext;
1593 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1594 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1595 auto *Decl =
1596 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1597 if (Attrs) {
1598 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1599 I != E; ++I)
1600 Decl->addAttr(*I);
1601 }
1602 Decl->setImplicit();
1603 if (OrigRef) {
1604 Decl->addAttr(
1605 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1606 }
1607 return Decl;
1608}
1609
1611 SourceLocation Loc,
1612 bool RefersToCapture = false) {
1613 D->setReferenced();
1614 D->markUsed(S.Context);
1616 SourceLocation(), D, RefersToCapture, Loc, Ty,
1617 VK_LValue);
1618}
1619
1620void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1621 BinaryOperatorKind BOK) {
1622 D = getCanonicalDecl(D);
1623 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1624 assert(
1625 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1626 "Additional reduction info may be specified only for reduction items.");
1627 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1628 assert(ReductionData.ReductionRange.isInvalid() &&
1629 (getTopOfStack().Directive == OMPD_taskgroup ||
1630 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1631 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1632 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1633 "Additional reduction info may be specified only once for reduction "
1634 "items.");
1635 ReductionData.set(BOK, SR);
1636 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1637 if (!TaskgroupReductionRef) {
1638 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1639 SemaRef.Context.VoidPtrTy, ".task_red.");
1640 TaskgroupReductionRef =
1641 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1642 }
1643}
1644
1645void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1646 const Expr *ReductionRef) {
1647 D = getCanonicalDecl(D);
1648 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1649 assert(
1650 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1651 "Additional reduction info may be specified only for reduction items.");
1652 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1653 assert(ReductionData.ReductionRange.isInvalid() &&
1654 (getTopOfStack().Directive == OMPD_taskgroup ||
1655 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1656 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1657 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1658 "Additional reduction info may be specified only once for reduction "
1659 "items.");
1660 ReductionData.set(ReductionRef, SR);
1661 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1662 if (!TaskgroupReductionRef) {
1663 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1664 SemaRef.Context.VoidPtrTy, ".task_red.");
1665 TaskgroupReductionRef =
1666 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1667 }
1668}
1669
1670const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1671 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1672 Expr *&TaskgroupDescriptor) const {
1673 D = getCanonicalDecl(D);
1674 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1675 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1676 const DSAInfo &Data = I->SharingMap.lookup(D);
1677 if (Data.Attributes != OMPC_reduction ||
1678 Data.Modifier != OMPC_REDUCTION_task)
1679 continue;
1680 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1681 if (!ReductionData.ReductionOp ||
1682 isa<const Expr *>(ReductionData.ReductionOp))
1683 return DSAVarData();
1684 SR = ReductionData.ReductionRange;
1685 BOK = cast<ReductionData::BOKPtrType>(ReductionData.ReductionOp);
1686 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1687 "expression for the descriptor is not "
1688 "set.");
1689 TaskgroupDescriptor = I->TaskgroupReductionRef;
1690 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1691 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1692 /*AppliedToPointee=*/false);
1693 }
1694 return DSAVarData();
1695}
1696
1697const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1698 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1699 Expr *&TaskgroupDescriptor) const {
1700 D = getCanonicalDecl(D);
1701 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1702 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1703 const DSAInfo &Data = I->SharingMap.lookup(D);
1704 if (Data.Attributes != OMPC_reduction ||
1705 Data.Modifier != OMPC_REDUCTION_task)
1706 continue;
1707 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1708 if (!ReductionData.ReductionOp ||
1709 !isa<const Expr *>(ReductionData.ReductionOp))
1710 return DSAVarData();
1711 SR = ReductionData.ReductionRange;
1712 ReductionRef = cast<const Expr *>(ReductionData.ReductionOp);
1713 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1714 "expression for the descriptor is not "
1715 "set.");
1716 TaskgroupDescriptor = I->TaskgroupReductionRef;
1717 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1718 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1719 /*AppliedToPointee=*/false);
1720 }
1721 return DSAVarData();
1722}
1723
1724bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1725 D = D->getCanonicalDecl();
1726 for (const_iterator E = end(); I != E; ++I) {
1727 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1728 isOpenMPTargetExecutionDirective(I->Directive)) {
1729 if (I->CurScope) {
1730 Scope *TopScope = I->CurScope->getParent();
1731 Scope *CurScope = getCurScope();
1732 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1733 CurScope = CurScope->getParent();
1734 return CurScope != TopScope;
1735 }
1736 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1737 if (I->Context == DC)
1738 return true;
1739 return false;
1740 }
1741 }
1742 return false;
1743}
1744
1746 bool AcceptIfMutable = true,
1747 bool *IsClassType = nullptr) {
1748 ASTContext &Context = SemaRef.getASTContext();
1749 Type = Type.getNonReferenceType().getCanonicalType();
1750 bool IsConstant = Type.isConstant(Context);
1751 Type = Context.getBaseElementType(Type);
1752 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1754 : nullptr;
1755 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1756 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1757 RD = CTD->getTemplatedDecl();
1758 if (IsClassType)
1759 *IsClassType = RD;
1760 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1761 RD->hasDefinition() && RD->hasMutableFields());
1762}
1763
1764static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1766 SourceLocation ELoc,
1767 bool AcceptIfMutable = true,
1768 bool ListItemNotVar = false) {
1769 ASTContext &Context = SemaRef.getASTContext();
1770 bool IsClassType;
1771 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1772 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1773 : IsClassType ? diag::err_omp_const_not_mutable_variable
1774 : diag::err_omp_const_variable;
1775 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseNameForDiag(CKind);
1776 if (!ListItemNotVar && D) {
1777 const VarDecl *VD = dyn_cast<VarDecl>(D);
1778 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1780 SemaRef.Diag(D->getLocation(),
1781 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1782 << D;
1783 }
1784 return true;
1785 }
1786 return false;
1787}
1788
1789const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1790 bool FromParent) {
1791 D = getCanonicalDecl(D);
1792 DSAVarData DVar;
1793
1794 auto *VD = dyn_cast<VarDecl>(D);
1795 auto TI = Threadprivates.find(D);
1796 if (TI != Threadprivates.end()) {
1797 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1798 DVar.CKind = OMPC_threadprivate;
1799 DVar.Modifier = TI->getSecond().Modifier;
1800 return DVar;
1801 }
1802 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1803 DVar.RefExpr = buildDeclRefExpr(
1804 SemaRef, VD, D->getType().getNonReferenceType(),
1805 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1806 DVar.CKind = OMPC_threadprivate;
1807 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1808 return DVar;
1809 }
1810 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1811 // in a Construct, C/C++, predetermined, p.1]
1812 // Variables appearing in threadprivate directives are threadprivate.
1813 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1814 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1815 SemaRef.getLangOpts().OpenMPUseTLS &&
1816 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1817 (VD && VD->getStorageClass() == SC_Register &&
1818 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1819 DVar.RefExpr = buildDeclRefExpr(
1820 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1821 DVar.CKind = OMPC_threadprivate;
1822 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1823 return DVar;
1824 }
1825 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1826 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1827 !isLoopControlVariable(D).first) {
1828 const_iterator IterTarget =
1829 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1830 return isOpenMPTargetExecutionDirective(Data.Directive);
1831 });
1832 if (IterTarget != end()) {
1833 const_iterator ParentIterTarget = IterTarget + 1;
1834 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1835 if (isOpenMPLocal(VD, Iter)) {
1836 DVar.RefExpr =
1837 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1838 D->getLocation());
1839 DVar.CKind = OMPC_threadprivate;
1840 return DVar;
1841 }
1842 }
1843 if (!isClauseParsingMode() || IterTarget != begin()) {
1844 auto DSAIter = IterTarget->SharingMap.find(D);
1845 if (DSAIter != IterTarget->SharingMap.end() &&
1846 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1847 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1848 DVar.CKind = OMPC_threadprivate;
1849 return DVar;
1850 }
1851 const_iterator End = end();
1852 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1853 D, std::distance(ParentIterTarget, End),
1854 /*OpenMPCaptureLevel=*/0)) {
1855 DVar.RefExpr =
1856 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1857 IterTarget->ConstructLoc);
1858 DVar.CKind = OMPC_threadprivate;
1859 return DVar;
1860 }
1861 }
1862 }
1863 }
1864
1865 if (isStackEmpty())
1866 // Not in OpenMP execution region and top scope was already checked.
1867 return DVar;
1868
1869 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1870 // in a Construct, C/C++, predetermined, p.4]
1871 // Static data members are shared.
1872 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1873 // in a Construct, C/C++, predetermined, p.7]
1874 // Variables with static storage duration that are declared in a scope
1875 // inside the construct are shared.
1876 if (VD && VD->isStaticDataMember()) {
1877 // Check for explicitly specified attributes.
1878 const_iterator I = begin();
1879 const_iterator EndI = end();
1880 if (FromParent && I != EndI)
1881 ++I;
1882 if (I != EndI) {
1883 auto It = I->SharingMap.find(D);
1884 if (It != I->SharingMap.end()) {
1885 const DSAInfo &Data = It->getSecond();
1886 DVar.RefExpr = Data.RefExpr.getPointer();
1887 DVar.PrivateCopy = Data.PrivateCopy;
1888 DVar.CKind = Data.Attributes;
1889 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1890 DVar.DKind = I->Directive;
1891 DVar.Modifier = Data.Modifier;
1892 DVar.AppliedToPointee = Data.AppliedToPointee;
1893 return DVar;
1894 }
1895 }
1896
1897 DVar.CKind = OMPC_shared;
1898 return DVar;
1899 }
1900
1901 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1902 // The predetermined shared attribute for const-qualified types having no
1903 // mutable members was removed after OpenMP 3.1.
1904 if (SemaRef.LangOpts.OpenMP <= 31) {
1905 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1906 // in a Construct, C/C++, predetermined, p.6]
1907 // Variables with const qualified type having no mutable member are
1908 // shared.
1909 if (isConstNotMutableType(SemaRef, D->getType())) {
1910 // Variables with const-qualified type having no mutable member may be
1911 // listed in a firstprivate clause, even if they are static data members.
1912 DSAVarData DVarTemp = hasInnermostDSA(
1913 D,
1914 [](OpenMPClauseKind C, bool) {
1915 return C == OMPC_firstprivate || C == OMPC_shared;
1916 },
1917 MatchesAlways, FromParent);
1918 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1919 return DVarTemp;
1920
1921 DVar.CKind = OMPC_shared;
1922 return DVar;
1923 }
1924 }
1925
1926 // Explicitly specified attributes and local variables with predetermined
1927 // attributes.
1928 const_iterator I = begin();
1929 const_iterator EndI = end();
1930 if (FromParent && I != EndI)
1931 ++I;
1932 if (I == EndI)
1933 return DVar;
1934 auto It = I->SharingMap.find(D);
1935 if (It != I->SharingMap.end()) {
1936 const DSAInfo &Data = It->getSecond();
1937 DVar.RefExpr = Data.RefExpr.getPointer();
1938 DVar.PrivateCopy = Data.PrivateCopy;
1939 DVar.CKind = Data.Attributes;
1940 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1941 DVar.DKind = I->Directive;
1942 DVar.Modifier = Data.Modifier;
1943 DVar.AppliedToPointee = Data.AppliedToPointee;
1944 }
1945
1946 return DVar;
1947}
1948
1949const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1950 bool FromParent) const {
1951 if (isStackEmpty()) {
1952 const_iterator I;
1953 return getDSA(I, D);
1954 }
1955 D = getCanonicalDecl(D);
1956 const_iterator StartI = begin();
1957 const_iterator EndI = end();
1958 if (FromParent && StartI != EndI)
1959 ++StartI;
1960 return getDSA(StartI, D);
1961}
1962
1963const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1964 unsigned Level) const {
1965 if (getStackSize() <= Level)
1966 return DSAVarData();
1967 D = getCanonicalDecl(D);
1968 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1969 return getDSA(StartI, D);
1970}
1971
1972const DSAStackTy::DSAVarData
1973DSAStackTy::hasDSA(ValueDecl *D,
1974 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1975 DefaultDataSharingAttributes)>
1976 CPred,
1977 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1978 bool FromParent) const {
1979 if (isStackEmpty())
1980 return {};
1981 D = getCanonicalDecl(D);
1982 const_iterator I = begin();
1983 const_iterator EndI = end();
1984 if (FromParent && I != EndI)
1985 ++I;
1986 for (; I != EndI; ++I) {
1987 if (!DPred(I->Directive) &&
1988 !isImplicitOrExplicitTaskingRegion(I->Directive))
1989 continue;
1990 const_iterator NewI = I;
1991 DSAVarData DVar = getDSA(NewI, D);
1992 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1993 return DVar;
1994 }
1995 return {};
1996}
1997
1998const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1999 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2000 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2001 bool FromParent) const {
2002 if (isStackEmpty())
2003 return {};
2004 D = getCanonicalDecl(D);
2005 const_iterator StartI = begin();
2006 const_iterator EndI = end();
2007 if (FromParent && StartI != EndI)
2008 ++StartI;
2009 if (StartI == EndI || !DPred(StartI->Directive))
2010 return {};
2011 const_iterator NewI = StartI;
2012 DSAVarData DVar = getDSA(NewI, D);
2013 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
2014 ? DVar
2015 : DSAVarData();
2016}
2017
2018bool DSAStackTy::hasExplicitDSA(
2019 const ValueDecl *D,
2020 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2021 unsigned Level, bool NotLastprivate) const {
2022 if (getStackSize() <= Level)
2023 return false;
2024 D = getCanonicalDecl(D);
2025 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2026 auto I = StackElem.SharingMap.find(D);
2027 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
2028 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
2029 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
2030 return true;
2031 // Check predetermined rules for the loop control variables.
2032 auto LI = StackElem.LCVMap.find(D);
2033 if (LI != StackElem.LCVMap.end())
2034 return CPred(OMPC_private, /*AppliedToPointee=*/false);
2035 return false;
2036}
2037
2038bool DSAStackTy::hasExplicitDirective(
2039 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2040 unsigned Level) const {
2041 if (getStackSize() <= Level)
2042 return false;
2043 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2044 return DPred(StackElem.Directive);
2045}
2046
2047bool DSAStackTy::hasDirective(
2048 const llvm::function_ref<bool(OpenMPDirectiveKind,
2049 const DeclarationNameInfo &, SourceLocation)>
2050 DPred,
2051 bool FromParent) const {
2052 // We look only in the enclosing region.
2053 size_t Skip = FromParent ? 2 : 1;
2054 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
2055 I != E; ++I) {
2056 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2057 return true;
2058 }
2059 return false;
2060}
2061
2062void SemaOpenMP::InitDataSharingAttributesStack() {
2063 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2064}
2065
2066#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2067
2068void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2069
2070void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2071 DSAStack->popFunction(OldFSI);
2072}
2073
2075 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2076 "Expected OpenMP device compilation.");
2078}
2079
2080namespace {
2081/// Status of the function emission on the host/device.
2082enum class FunctionEmissionStatus {
2083 Emitted,
2084 Discarded,
2085 Unknown,
2086};
2087} // anonymous namespace
2088
2089SemaBase::SemaDiagnosticBuilder
2091 const FunctionDecl *FD) {
2092 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2093 "Expected OpenMP device compilation.");
2094
2095 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2096 if (FD) {
2097 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
2098 switch (FES) {
2100 Kind = SemaDiagnosticBuilder::K_Immediate;
2101 break;
2103 // TODO: We should always delay diagnostics here in case a target
2104 // region is in a function we do not emit. However, as the
2105 // current diagnostics are associated with the function containing
2106 // the target region and we do not emit that one, we would miss out
2107 // on diagnostics for the target region itself. We need to anchor
2108 // the diagnostics with the new generated function *or* ensure we
2109 // emit diagnostics associated with the surrounding function.
2111 ? SemaDiagnosticBuilder::K_Deferred
2112 : SemaDiagnosticBuilder::K_Immediate;
2113 break;
2116 Kind = SemaDiagnosticBuilder::K_Nop;
2117 break;
2119 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2120 break;
2121 }
2122 }
2123
2124 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2125}
2126
2129 const FunctionDecl *FD) {
2130 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2131 "Expected OpenMP host compilation.");
2132
2133 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2134 if (FD) {
2135 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
2136 switch (FES) {
2138 Kind = SemaDiagnosticBuilder::K_Immediate;
2139 break;
2141 Kind = SemaDiagnosticBuilder::K_Deferred;
2142 break;
2146 Kind = SemaDiagnosticBuilder::K_Nop;
2147 break;
2148 }
2149 }
2150
2151 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2152}
2153
2156 if (LO.OpenMP <= 45) {
2158 return OMPC_DEFAULTMAP_scalar;
2159 return OMPC_DEFAULTMAP_aggregate;
2160 }
2162 return OMPC_DEFAULTMAP_pointer;
2164 return OMPC_DEFAULTMAP_scalar;
2165 return OMPC_DEFAULTMAP_aggregate;
2166}
2167
2168bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2169 unsigned OpenMPCaptureLevel) const {
2170 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2171
2172 ASTContext &Ctx = getASTContext();
2173 bool IsByRef = true;
2174
2175 // Find the directive that is associated with the provided scope.
2177 QualType Ty = D->getType();
2178
2179 bool IsVariableUsedInMapClause = false;
2180 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2181 // This table summarizes how a given variable should be passed to the device
2182 // given its type and the clauses where it appears. This table is based on
2183 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2184 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2185 //
2186 // =========================================================================
2187 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2188 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2189 // =========================================================================
2190 // | scl | | | | - | | bycopy|
2191 // | scl | | - | x | - | - | bycopy|
2192 // | scl | | x | - | - | - | null |
2193 // | scl | x | | | - | | byref |
2194 // | scl | x | - | x | - | - | bycopy|
2195 // | scl | x | x | - | - | - | null |
2196 // | scl | | - | - | - | x | byref |
2197 // | scl | x | - | - | - | x | byref |
2198 //
2199 // | agg | n.a. | | | - | | byref |
2200 // | agg | n.a. | - | x | - | - | byref |
2201 // | agg | n.a. | x | - | - | - | null |
2202 // | agg | n.a. | - | - | - | x | byref |
2203 // | agg | n.a. | - | - | - | x[] | byref |
2204 //
2205 // | ptr | n.a. | | | - | | bycopy|
2206 // | ptr | n.a. | - | x | - | - | bycopy|
2207 // | ptr | n.a. | x | - | - | - | null |
2208 // | ptr | n.a. | - | - | - | x | byref |
2209 // | ptr | n.a. | - | - | - | x[] | bycopy|
2210 // | ptr | n.a. | - | - | x | | bycopy|
2211 // | ptr | n.a. | - | - | x | x | bycopy|
2212 // | ptr | n.a. | - | - | x | x[] | bycopy|
2213 // =========================================================================
2214 // Legend:
2215 // scl - scalar
2216 // ptr - pointer
2217 // agg - aggregate
2218 // x - applies
2219 // - - invalid in this combination
2220 // [] - mapped with an array section
2221 // byref - should be mapped by reference
2222 // byval - should be mapped by value
2223 // null - initialize a local variable to null on the device
2224 //
2225 // Observations:
2226 // - All scalar declarations that show up in a map clause have to be passed
2227 // by reference, because they may have been mapped in the enclosing data
2228 // environment.
2229 // - If the scalar value does not fit the size of uintptr, it has to be
2230 // passed by reference, regardless the result in the table above.
2231 // - For pointers mapped by value that have either an implicit map or an
2232 // array section, the runtime library may pass the NULL value to the
2233 // device instead of the value passed to it by the compiler.
2234
2235 if (Ty->isReferenceType())
2236 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2237
2238 // Locate map clauses and see if the variable being captured is referred to
2239 // in any of those clauses. Here we only care about variables, not fields,
2240 // because fields are part of aggregates.
2241 bool IsVariableAssociatedWithSection = false;
2242
2243 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2244 D, Level,
2245 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2247 MapExprComponents,
2248 OpenMPClauseKind WhereFoundClauseKind) {
2249 // Both map and has_device_addr clauses information influences how a
2250 // variable is captured. E.g. is_device_ptr does not require changing
2251 // the default behavior.
2252 if (WhereFoundClauseKind != OMPC_map &&
2253 WhereFoundClauseKind != OMPC_has_device_addr)
2254 return false;
2255
2256 auto EI = MapExprComponents.rbegin();
2257 auto EE = MapExprComponents.rend();
2258
2259 assert(EI != EE && "Invalid map expression!");
2260
2261 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2262 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2263
2264 ++EI;
2265 if (EI == EE)
2266 return false;
2267 auto Last = std::prev(EE);
2268 const auto *UO =
2269 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2270 if ((UO && UO->getOpcode() == UO_Deref) ||
2271 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2272 isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2273 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2274 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2275 IsVariableAssociatedWithSection = true;
2276 // There is nothing more we need to know about this variable.
2277 return true;
2278 }
2279
2280 // Keep looking for more map info.
2281 return false;
2282 });
2283
2284 if (IsVariableUsedInMapClause) {
2285 // If variable is identified in a map clause it is always captured by
2286 // reference except if it is a pointer that is dereferenced somehow.
2287 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2288 } else {
2289 // By default, all the data that has a scalar type is mapped by copy
2290 // (except for reduction variables).
2291 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2292 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2293 !Ty->isAnyPointerType()) ||
2294 !Ty->isScalarType() ||
2295 DSAStack->isDefaultmapCapturedByRef(
2297 DSAStack->hasExplicitDSA(
2298 D,
2299 [](OpenMPClauseKind K, bool AppliedToPointee) {
2300 return K == OMPC_reduction && !AppliedToPointee;
2301 },
2302 Level);
2303 }
2304 }
2305
2306 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2307 IsByRef =
2308 ((IsVariableUsedInMapClause &&
2309 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2310 OMPD_target) ||
2311 !(DSAStack->hasExplicitDSA(
2312 D,
2313 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2314 return K == OMPC_firstprivate ||
2315 (K == OMPC_reduction && AppliedToPointee);
2316 },
2317 Level, /*NotLastprivate=*/true) ||
2318 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2319 // If the variable is artificial and must be captured by value - try to
2320 // capture by value.
2321 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2322 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2323 // If the variable is implicitly firstprivate and scalar - capture by
2324 // copy
2325 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2326 DSAStack->getDefaultDSA() == DSA_private) &&
2327 !DSAStack->hasExplicitDSA(
2328 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2329 Level) &&
2330 !DSAStack->isLoopControlVariable(D, Level).first);
2331 }
2332
2333 // When passing data by copy, we need to make sure it fits the uintptr size
2334 // and alignment, because the runtime library only deals with uintptr types.
2335 // If it does not fit the uintptr size, we need to pass the data by reference
2336 // instead.
2337 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2339 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2340 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2341 IsByRef = true;
2342 }
2343
2344 return IsByRef;
2345}
2346
2347unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2348 assert(getLangOpts().OpenMP);
2349 return DSAStack->getNestingLevel();
2350}
2351
2353 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2354 DSAStack->isUntiedRegion();
2355}
2356
2358 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2359 !DSAStack->isClauseParsingMode()) ||
2360 DSAStack->hasDirective(
2362 SourceLocation) -> bool {
2364 },
2365 false);
2366}
2367
2369 // Only rebuild for Field.
2370 if (!isa<FieldDecl>(D))
2371 return false;
2372 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2373 D,
2374 [](OpenMPClauseKind C, bool AppliedToPointee,
2375 DefaultDataSharingAttributes DefaultAttr) {
2376 return isOpenMPPrivate(C) && !AppliedToPointee &&
2377 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2378 },
2379 [](OpenMPDirectiveKind) { return true; },
2380 DSAStack->isClauseParsingMode());
2381 if (DVarPrivate.CKind != OMPC_unknown)
2382 return true;
2383 return false;
2384}
2385
2387 Expr *CaptureExpr, bool WithInit,
2388 DeclContext *CurContext,
2389 bool AsExpression);
2390
2392 unsigned StopAt) {
2393 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2394 D = getCanonicalDecl(D);
2395
2396 auto *VD = dyn_cast<VarDecl>(D);
2397 // Do not capture constexpr variables.
2398 if (VD && VD->isConstexpr())
2399 return nullptr;
2400
2401 // If we want to determine whether the variable should be captured from the
2402 // perspective of the current capturing scope, and we've already left all the
2403 // capturing scopes of the top directive on the stack, check from the
2404 // perspective of its parent directive (if any) instead.
2405 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2406 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2407
2408 // If we are attempting to capture a global variable in a directive with
2409 // 'target' we return true so that this global is also mapped to the device.
2410 //
2411 if (VD && !VD->hasLocalStorage() &&
2412 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2413 SemaRef.getCurLambda())) {
2415 DSAStackTy::DSAVarData DVarTop =
2416 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2417 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2418 return VD;
2419 // If the declaration is enclosed in a 'declare target' directive,
2420 // then it should not be captured.
2421 //
2422 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2423 return nullptr;
2424 CapturedRegionScopeInfo *CSI = nullptr;
2425 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2426 llvm::reverse(SemaRef.FunctionScopes),
2427 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2428 : 0)) {
2429 if (!isa<CapturingScopeInfo>(FSI))
2430 return nullptr;
2431 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2432 if (RSI->CapRegionKind == CR_OpenMP) {
2433 CSI = RSI;
2434 break;
2435 }
2436 }
2437 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2440 DSAStack->getDirective(CSI->OpenMPLevel));
2441 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2442 return VD;
2443 }
2445 // Try to mark variable as declare target if it is used in capturing
2446 // regions.
2447 if (getLangOpts().OpenMP <= 45 &&
2448 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2450 return nullptr;
2451 }
2452 }
2453
2454 if (CheckScopeInfo) {
2455 bool OpenMPFound = false;
2456 for (unsigned I = StopAt + 1; I > 0; --I) {
2457 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2458 if (!isa<CapturingScopeInfo>(FSI))
2459 return nullptr;
2460 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2461 if (RSI->CapRegionKind == CR_OpenMP) {
2462 OpenMPFound = true;
2463 break;
2464 }
2465 }
2466 if (!OpenMPFound)
2467 return nullptr;
2468 }
2469
2470 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2471 (!DSAStack->isClauseParsingMode() ||
2472 DSAStack->getParentDirective() != OMPD_unknown)) {
2473 auto &&Info = DSAStack->isLoopControlVariable(D);
2474 if (Info.first ||
2475 (VD && VD->hasLocalStorage() &&
2476 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2477 (VD && DSAStack->isForceVarCapturing()))
2478 return VD ? VD : Info.second;
2479 DSAStackTy::DSAVarData DVarTop =
2480 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2481 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2482 (!VD || VD->hasLocalStorage() ||
2483 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2484 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2485 // Threadprivate variables must not be captured.
2486 if (isOpenMPThreadPrivate(DVarTop.CKind))
2487 return nullptr;
2488 // The variable is not private or it is the variable in the directive with
2489 // default(none) clause and not used in any clause.
2490 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2491 D,
2492 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2493 return isOpenMPPrivate(C) && !AppliedToPointee;
2494 },
2495 [](OpenMPDirectiveKind) { return true; },
2496 DSAStack->isClauseParsingMode());
2497 // Global shared must not be captured.
2498 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2499 ((DSAStack->getDefaultDSA() != DSA_none &&
2500 DSAStack->getDefaultDSA() != DSA_private &&
2501 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2502 DVarTop.CKind == OMPC_shared))
2503 return nullptr;
2504 auto *FD = dyn_cast<FieldDecl>(D);
2505 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2506 !DVarPrivate.PrivateCopy) {
2507 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2508 D,
2509 [](OpenMPClauseKind C, bool AppliedToPointee,
2510 DefaultDataSharingAttributes DefaultAttr) {
2511 return isOpenMPPrivate(C) && !AppliedToPointee &&
2512 (DefaultAttr == DSA_firstprivate ||
2513 DefaultAttr == DSA_private);
2514 },
2515 [](OpenMPDirectiveKind) { return true; },
2516 DSAStack->isClauseParsingMode());
2517 if (DVarPrivate.CKind == OMPC_unknown)
2518 return nullptr;
2519
2520 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2521 if (VD)
2522 return VD;
2523 if (SemaRef.getCurrentThisType().isNull())
2524 return nullptr;
2525 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(SourceLocation(),
2526 SemaRef.getCurrentThisType(),
2527 /*IsImplicit=*/true);
2528 const CXXScopeSpec CS = CXXScopeSpec();
2529 Expr *ME = SemaRef.BuildMemberExpr(
2530 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2533 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2536 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2537 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2538 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2540 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2541 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2542 return VD;
2543 }
2544 if (DVarPrivate.CKind != OMPC_unknown ||
2545 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2546 DSAStack->getDefaultDSA() == DSA_private ||
2547 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2548 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2549 }
2550 return nullptr;
2551}
2552
2553void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2554 unsigned Level) const {
2555 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2556}
2557
2559 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2560 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2561 DSAStack->loopInit();
2562}
2563
2565 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2566 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2567 DSAStack->resetPossibleLoopCounter();
2568 DSAStack->loopStart();
2569 }
2570}
2571
2573 unsigned CapLevel) const {
2574 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2575 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2576 (!DSAStack->isClauseParsingMode() ||
2577 DSAStack->getParentDirective() != OMPD_unknown)) {
2578 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2579 D,
2580 [](OpenMPClauseKind C, bool AppliedToPointee,
2581 DefaultDataSharingAttributes DefaultAttr) {
2582 return isOpenMPPrivate(C) && !AppliedToPointee &&
2583 DefaultAttr == DSA_private;
2584 },
2585 [](OpenMPDirectiveKind) { return true; },
2586 DSAStack->isClauseParsingMode());
2587 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2588 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2589 !DSAStack->isLoopControlVariable(D).first)
2590 return OMPC_private;
2591 }
2592 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2593 bool IsTriviallyCopyable =
2595 getASTContext()) &&
2596 !D->getType()
2600 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2602 getOpenMPCaptureRegions(CaptureRegions, DKind);
2603 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2604 (IsTriviallyCopyable ||
2605 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2606 if (DSAStack->hasExplicitDSA(
2607 D,
2608 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2609 Level, /*NotLastprivate=*/true))
2610 return OMPC_firstprivate;
2611 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2612 if (DVar.CKind != OMPC_shared &&
2613 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2614 DSAStack->addImplicitTaskFirstprivate(Level, D);
2615 return OMPC_firstprivate;
2616 }
2617 }
2618 }
2619 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2620 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2621 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2622 DSAStack->resetPossibleLoopCounter(D);
2623 DSAStack->loopStart();
2624 return OMPC_private;
2625 }
2626 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2627 DSAStack->isLoopControlVariable(D).first) &&
2628 !DSAStack->hasExplicitDSA(
2629 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2630 Level) &&
2631 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2632 return OMPC_private;
2633 }
2634 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2635 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2636 DSAStack->isForceVarCapturing() &&
2637 !DSAStack->hasExplicitDSA(
2638 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2639 Level))
2640 return OMPC_private;
2641 }
2642 // User-defined allocators are private since they must be defined in the
2643 // context of target region.
2644 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2645 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2646 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2647 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2648 return OMPC_private;
2649 return (DSAStack->hasExplicitDSA(
2650 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2651 Level) ||
2652 (DSAStack->isClauseParsingMode() &&
2653 DSAStack->getClauseParsingMode() == OMPC_private) ||
2654 // Consider taskgroup reduction descriptor variable a private
2655 // to avoid possible capture in the region.
2656 (DSAStack->hasExplicitDirective(
2657 [](OpenMPDirectiveKind K) {
2658 return K == OMPD_taskgroup ||
2659 ((isOpenMPParallelDirective(K) ||
2660 isOpenMPWorksharingDirective(K)) &&
2661 !isOpenMPSimdDirective(K));
2662 },
2663 Level) &&
2664 DSAStack->isTaskgroupReductionRef(D, Level)))
2665 ? OMPC_private
2666 : OMPC_unknown;
2667}
2668
2670 unsigned Level) {
2671 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2672 D = getCanonicalDecl(D);
2673 OpenMPClauseKind OMPC = OMPC_unknown;
2674 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2675 const unsigned NewLevel = I - 1;
2676 if (DSAStack->hasExplicitDSA(
2677 D,
2678 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2679 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2680 OMPC = K;
2681 return true;
2682 }
2683 return false;
2684 },
2685 NewLevel))
2686 break;
2687 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2688 D, NewLevel,
2690 OpenMPClauseKind) { return true; })) {
2691 OMPC = OMPC_map;
2692 break;
2693 }
2694 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2695 NewLevel)) {
2696 OMPC = OMPC_map;
2697 if (DSAStack->mustBeFirstprivateAtLevel(
2699 OMPC = OMPC_firstprivate;
2700 break;
2701 }
2702 }
2703 if (OMPC != OMPC_unknown)
2704 FD->addAttr(
2705 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2706}
2707
2709 unsigned CaptureLevel) const {
2710 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2711 // Return true if the current level is no longer enclosed in a target region.
2712
2714 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2715 const auto *VD = dyn_cast<VarDecl>(D);
2716 return VD && !VD->hasLocalStorage() &&
2717 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2718 Level) &&
2719 Regions[CaptureLevel] != OMPD_task;
2720}
2721
2723 unsigned CaptureLevel) const {
2724 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2725 // Return true if the current level is no longer enclosed in a target region.
2726
2727 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2728 if (!VD->hasLocalStorage()) {
2730 return true;
2731 DSAStackTy::DSAVarData TopDVar =
2732 DSAStack->getTopDSA(D, /*FromParent=*/false);
2733 unsigned NumLevels =
2734 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2735 if (Level == 0)
2736 // non-file scope static variable with default(firstprivate)
2737 // should be global captured.
2738 return (NumLevels == CaptureLevel + 1 &&
2739 (TopDVar.CKind != OMPC_shared ||
2740 DSAStack->getDefaultDSA() == DSA_firstprivate));
2741 do {
2742 --Level;
2743 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2744 if (DVar.CKind != OMPC_shared)
2745 return true;
2746 } while (Level > 0);
2747 }
2748 }
2749 return true;
2750}
2751
2752void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2753
2755 OMPTraitInfo &TI) {
2756 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2757}
2758
2761 "Not in OpenMP declare variant scope!");
2762
2763 OMPDeclareVariantScopes.pop_back();
2764}
2765
2767 const FunctionDecl *Callee,
2768 SourceLocation Loc) {
2769 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2770 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2771 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2772 // Ignore host functions during device analysis.
2773 if (getLangOpts().OpenMPIsTargetDevice &&
2774 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2775 return;
2776 // Ignore nohost functions during host analysis.
2777 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2778 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2779 return;
2780 const FunctionDecl *FD = Callee->getMostRecentDecl();
2781 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2782 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2783 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2784 // Diagnose host function called during device codegen.
2785 StringRef HostDevTy =
2786 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2787 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2788 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2789 diag::note_omp_marked_device_type_here)
2790 << HostDevTy;
2791 return;
2792 }
2793 if (!getLangOpts().OpenMPIsTargetDevice &&
2794 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2795 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2796 // In OpenMP 5.2 or later, if the function has a host variant then allow
2797 // that to be called instead
2798 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2799 for (OMPDeclareVariantAttr *A :
2800 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2801 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2802 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2803 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2804 OMPDeclareTargetDeclAttr::getDeviceType(
2805 VariantFD->getMostRecentDecl());
2806 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2807 return true;
2808 }
2809 return false;
2810 };
2811 if (getLangOpts().OpenMP >= 52 &&
2812 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2813 return;
2814 // Diagnose nohost function called during host codegen.
2815 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2816 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2817 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2818 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2819 diag::note_omp_marked_device_type_here)
2820 << NoHostDevTy;
2821 }
2822}
2823
2825 const DeclarationNameInfo &DirName,
2826 Scope *CurScope, SourceLocation Loc) {
2827 DSAStack->push(DKind, DirName, CurScope, Loc);
2828 SemaRef.PushExpressionEvaluationContext(
2830}
2831
2833 DSAStack->setClauseParsingMode(K);
2834}
2835
2837 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2838 SemaRef.CleanupVarDeclMarking();
2839}
2840
2841static std::pair<ValueDecl *, bool>
2842getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2843 SourceRange &ERange, bool AllowArraySection = false,
2844 bool AllowAssumedSizeArray = false, StringRef DiagType = "");
2845
2846/// Check consistency of the reduction clauses.
2847static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2848 ArrayRef<OMPClause *> Clauses) {
2849 bool InscanFound = false;
2850 SourceLocation InscanLoc;
2851 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2852 // A reduction clause without the inscan reduction-modifier may not appear on
2853 // a construct on which a reduction clause with the inscan reduction-modifier
2854 // appears.
2855 for (OMPClause *C : Clauses) {
2856 if (C->getClauseKind() != OMPC_reduction)
2857 continue;
2858 auto *RC = cast<OMPReductionClause>(C);
2859 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2860 InscanFound = true;
2861 InscanLoc = RC->getModifierLoc();
2862 continue;
2863 }
2864 if (RC->getModifier() == OMPC_REDUCTION_task) {
2865 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2866 // A reduction clause with the task reduction-modifier may only appear on
2867 // a parallel construct, a worksharing construct or a combined or
2868 // composite construct for which any of the aforementioned constructs is a
2869 // constituent construct and simd or loop are not constituent constructs.
2870 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2871 if (!(isOpenMPParallelDirective(CurDir) ||
2873 isOpenMPSimdDirective(CurDir))
2874 S.Diag(RC->getModifierLoc(),
2875 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2876 continue;
2877 }
2878 }
2879 if (InscanFound) {
2880 for (OMPClause *C : Clauses) {
2881 if (C->getClauseKind() != OMPC_reduction)
2882 continue;
2883 auto *RC = cast<OMPReductionClause>(C);
2884 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2885 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2886 ? RC->getBeginLoc()
2887 : RC->getModifierLoc(),
2888 diag::err_omp_inscan_reduction_expected);
2889 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2890 continue;
2891 }
2892 for (Expr *Ref : RC->varlist()) {
2893 assert(Ref && "NULL expr in OpenMP reduction clause.");
2894 SourceLocation ELoc;
2895 SourceRange ERange;
2896 Expr *SimpleRefExpr = Ref;
2897 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2898 /*AllowArraySection=*/true);
2899 ValueDecl *D = Res.first;
2900 if (!D)
2901 continue;
2902 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2903 S.Diag(Ref->getExprLoc(),
2904 diag::err_omp_reduction_not_inclusive_exclusive)
2905 << Ref->getSourceRange();
2906 }
2907 }
2908 }
2909 }
2910}
2911
2912static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2913 ArrayRef<OMPClause *> Clauses);
2914static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2915 bool WithInit);
2916
2917static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2918 const ValueDecl *D,
2919 const DSAStackTy::DSAVarData &DVar,
2920 bool IsLoopIterVar = false);
2921
2923 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2924 // A variable of class type (or array thereof) that appears in a lastprivate
2925 // clause requires an accessible, unambiguous default constructor for the
2926 // class type, unless the list item is also specified in a firstprivate
2927 // clause.
2928
2929 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2930 SmallVector<Expr *, 8> PrivateCopies;
2931 for (Expr *DE : Clause->varlist()) {
2932 if (DE->isValueDependent() || DE->isTypeDependent()) {
2933 PrivateCopies.push_back(nullptr);
2934 continue;
2935 }
2936 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2937 auto *VD = cast<VarDecl>(DRE->getDecl());
2939 const DSAStackTy::DSAVarData DVar =
2940 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2941 if (DVar.CKind != OMPC_lastprivate) {
2942 // The variable is also a firstprivate, so initialization sequence
2943 // for private copy is generated already.
2944 PrivateCopies.push_back(nullptr);
2945 continue;
2946 }
2947 // Generate helper private variable and initialize it with the
2948 // default value. The address of the original variable is replaced
2949 // by the address of the new private variable in CodeGen. This new
2950 // variable is not added to IdResolver, so the code in the OpenMP
2951 // region uses original variable for proper diagnostics.
2952 VarDecl *VDPrivate = buildVarDecl(
2953 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(),
2954 VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2955 SemaRef.ActOnUninitializedDecl(VDPrivate);
2956 if (VDPrivate->isInvalidDecl()) {
2957 PrivateCopies.push_back(nullptr);
2958 continue;
2959 }
2960 PrivateCopies.push_back(buildDeclRefExpr(
2961 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2962 }
2963 Clause->setPrivateCopies(PrivateCopies);
2964 };
2965
2966 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
2967 // Finalize nontemporal clause by handling private copies, if any.
2968 SmallVector<Expr *, 8> PrivateRefs;
2969 for (Expr *RefExpr : Clause->varlist()) {
2970 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2971 SourceLocation ELoc;
2972 SourceRange ERange;
2973 Expr *SimpleRefExpr = RefExpr;
2974 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
2975 if (Res.second)
2976 // It will be analyzed later.
2977 PrivateRefs.push_back(RefExpr);
2978 ValueDecl *D = Res.first;
2979 if (!D)
2980 continue;
2981
2982 const DSAStackTy::DSAVarData DVar =
2983 DSAStack->getTopDSA(D, /*FromParent=*/false);
2984 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2985 : SimpleRefExpr);
2986 }
2987 Clause->setPrivateRefs(PrivateRefs);
2988 };
2989
2990 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
2991 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2992 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2993 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2994 if (!DRE)
2995 continue;
2996 ValueDecl *VD = DRE->getDecl();
2997 if (!VD || !isa<VarDecl>(VD))
2998 continue;
2999 DSAStackTy::DSAVarData DVar =
3000 DSAStack->getTopDSA(VD, /*FromParent=*/false);
3001 // OpenMP [2.12.5, target Construct]
3002 // Memory allocators that appear in a uses_allocators clause cannot
3003 // appear in other data-sharing attribute clauses or data-mapping
3004 // attribute clauses in the same construct.
3005 Expr *MapExpr = nullptr;
3006 if (DVar.RefExpr ||
3007 DSAStack->checkMappableExprComponentListsForDecl(
3008 VD, /*CurrentRegionOnly=*/true,
3009 [VD, &MapExpr](
3011 MapExprComponents,
3013 auto MI = MapExprComponents.rbegin();
3014 auto ME = MapExprComponents.rend();
3015 if (MI != ME &&
3016 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3017 VD->getCanonicalDecl()) {
3018 MapExpr = MI->getAssociatedExpression();
3019 return true;
3020 }
3021 return false;
3022 })) {
3023 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
3024 << D.Allocator->getSourceRange();
3025 if (DVar.RefExpr)
3027 else
3028 Diag(MapExpr->getExprLoc(), diag::note_used_here)
3029 << MapExpr->getSourceRange();
3030 }
3031 }
3032 };
3033
3034 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
3035 for (OMPClause *C : D->clauses()) {
3036 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
3037 FinalizeLastprivate(Clause);
3038 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
3039 FinalizeNontemporal(Clause);
3040 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
3041 FinalizeAllocators(Clause);
3042 }
3043 }
3044 // Check allocate clauses.
3045 if (!SemaRef.CurContext->isDependentContext())
3046 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
3047 checkReductionClauses(SemaRef, DSAStack, D->clauses());
3048 }
3049
3050 DSAStack->pop();
3053}
3054
3055static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3056 Expr *NumIterations, Sema &SemaRef,
3057 Scope *S, DSAStackTy *Stack);
3058
3059static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
3060 OMPLoopBasedDirective::HelperExprs &B,
3061 DSAStackTy *Stack) {
3062 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3063 "loop exprs were not built");
3064
3065 if (SemaRef.CurContext->isDependentContext())
3066 return false;
3067
3068 // Finalize the clauses that need pre-built expressions for CodeGen.
3069 for (OMPClause *C : Clauses) {
3070 auto *LC = dyn_cast<OMPLinearClause>(C);
3071 if (!LC)
3072 continue;
3073 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3074 B.NumIterations, SemaRef,
3075 SemaRef.getCurScope(), Stack))
3076 return true;
3077 }
3078
3079 return false;
3080}
3081
3082namespace {
3083
3084class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3085private:
3086 Sema &SemaRef;
3087
3088public:
3089 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3090 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3091 NamedDecl *ND = Candidate.getCorrectionDecl();
3092 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3093 return VD->hasGlobalStorage() &&
3094 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3095 SemaRef.getCurScope());
3096 }
3097 return false;
3098 }
3099
3100 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3101 return std::make_unique<VarDeclFilterCCC>(*this);
3102 }
3103};
3104
3105class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3106private:
3107 Sema &SemaRef;
3108
3109public:
3110 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3111 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3112 NamedDecl *ND = Candidate.getCorrectionDecl();
3113 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3114 isa<FunctionDecl>(ND))) {
3115 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3116 SemaRef.getCurScope());
3117 }
3118 return false;
3119 }
3120
3121 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3122 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3123 }
3124};
3125
3126} // namespace
3127
3129 CXXScopeSpec &ScopeSpec,
3130 const DeclarationNameInfo &Id,
3131 OpenMPDirectiveKind Kind) {
3132 ASTContext &Context = getASTContext();
3133 unsigned OMPVersion = getLangOpts().OpenMP;
3135 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3136 /*ObjectType=*/QualType(),
3137 /*AllowBuiltinCreation=*/true);
3138
3139 if (Lookup.isAmbiguous())
3140 return ExprError();
3141
3142 VarDecl *VD;
3143 if (!Lookup.isSingleResult()) {
3144 VarDeclFilterCCC CCC(SemaRef);
3145 if (TypoCorrection Corrected =
3146 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3148 SemaRef.diagnoseTypo(
3149 Corrected,
3150 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3151 : diag::err_omp_expected_var_arg_suggest)
3152 << Id.getName());
3153 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3154 } else {
3155 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3156 : diag::err_omp_expected_var_arg)
3157 << Id.getName();
3158 return ExprError();
3159 }
3160 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3161 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3162 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3163 return ExprError();
3164 }
3165 Lookup.suppressDiagnostics();
3166
3167 // OpenMP [2.9.2, Syntax, C/C++]
3168 // Variables must be file-scope, namespace-scope, or static block-scope.
3169 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3170 !VD->hasGlobalStorage()) {
3171 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3172 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->isStaticLocal();
3173 bool IsDecl =
3175 Diag(VD->getLocation(),
3176 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3177 << VD;
3178 return ExprError();
3179 }
3180
3181 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3182 NamedDecl *ND = CanonicalVD;
3183 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3184 // A threadprivate or groupprivate directive for file-scope variables must
3185 // appear outside any definition or declaration.
3186 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3187 !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3188 Diag(Id.getLoc(), diag::err_omp_var_scope)
3189 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3190 bool IsDecl =
3192 Diag(VD->getLocation(),
3193 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3194 << VD;
3195 return ExprError();
3196 }
3197 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3198 // A threadprivate or groupprivate directive for static class member
3199 // variables must appear in the class definition, in the same scope in which
3200 // the member variables are declared.
3201 if (CanonicalVD->isStaticDataMember() &&
3202 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3203 Diag(Id.getLoc(), diag::err_omp_var_scope)
3204 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3205 bool IsDecl =
3207 Diag(VD->getLocation(),
3208 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3209 << VD;
3210 return ExprError();
3211 }
3212 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3213 // A threadprivate or groupprivate directive for namespace-scope variables
3214 // must appear outside any definition or declaration other than the
3215 // namespace definition itself.
3216 if (CanonicalVD->getDeclContext()->isNamespace() &&
3217 (!SemaRef.getCurLexicalContext()->isFileContext() ||
3218 !SemaRef.getCurLexicalContext()->Encloses(
3219 CanonicalVD->getDeclContext()))) {
3220 Diag(Id.getLoc(), diag::err_omp_var_scope)
3221 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3222 bool IsDecl =
3224 Diag(VD->getLocation(),
3225 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3226 << VD;
3227 return ExprError();
3228 }
3229 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3230 // A threadprivate or groupprivate directive for static block-scope
3231 // variables must appear in the scope of the variable and not in a nested
3232 // scope.
3233 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3234 !SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), CurScope)) {
3235 Diag(Id.getLoc(), diag::err_omp_var_scope)
3236 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3237 bool IsDecl =
3239 Diag(VD->getLocation(),
3240 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3241 << VD;
3242 return ExprError();
3243 }
3244
3245 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3246 // A threadprivate or groupprivate directive must lexically precede all
3247 // references to any of the variables in its list.
3248 if ((Kind == OMPD_threadprivate && VD->isUsed() &&
3249 !DSAStack->isThreadPrivate(VD)) ||
3250 (Kind == OMPD_groupprivate && VD->isUsed())) {
3251 Diag(Id.getLoc(), diag::err_omp_var_used)
3252 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3253 return ExprError();
3254 }
3255
3256 QualType ExprType = VD->getType().getNonReferenceType();
3258 SourceLocation(), VD,
3259 /*RefersToEnclosingVariableOrCapture=*/false,
3260 Id.getLoc(), ExprType, VK_LValue);
3261}
3262
3265 ArrayRef<Expr *> VarList) {
3266 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3267 SemaRef.CurContext->addDecl(D);
3269 }
3270 return nullptr;
3271}
3272
3275 ArrayRef<Expr *> VarList) {
3276 if (!getLangOpts().OpenMP || getLangOpts().OpenMP < 60) {
3277 Diag(Loc, diag::err_omp_unexpected_directive)
3278 << getOpenMPDirectiveName(OMPD_groupprivate, getLangOpts().OpenMP);
3279 return nullptr;
3280 }
3281 if (OMPGroupPrivateDecl *D = CheckOMPGroupPrivateDecl(Loc, VarList)) {
3282 SemaRef.CurContext->addDecl(D);
3284 }
3285 return nullptr;
3286}
3287
3288namespace {
3289class LocalVarRefChecker final
3290 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3291 Sema &SemaRef;
3292
3293public:
3294 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3295 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3296 if (VD->hasLocalStorage()) {
3297 SemaRef.Diag(E->getBeginLoc(),
3298 diag::err_omp_local_var_in_threadprivate_init)
3299 << E->getSourceRange();
3300 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3301 << VD << VD->getSourceRange();
3302 return true;
3303 }
3304 }
3305 return false;
3306 }
3307 bool VisitStmt(const Stmt *S) {
3308 for (const Stmt *Child : S->children()) {
3309 if (Child && Visit(Child))
3310 return true;
3311 }
3312 return false;
3313 }
3314 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3315};
3316} // namespace
3317
3318OMPThreadPrivateDecl *
3320 ArrayRef<Expr *> VarList) {
3321 ASTContext &Context = getASTContext();
3323 for (Expr *RefExpr : VarList) {
3324 auto *DE = cast<DeclRefExpr>(RefExpr);
3325 auto *VD = cast<VarDecl>(DE->getDecl());
3326 SourceLocation ILoc = DE->getExprLoc();
3327
3328 // Mark variable as used.
3329 VD->setReferenced();
3330 VD->markUsed(Context);
3331
3332 QualType QType = VD->getType();
3333 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3334 // It will be analyzed later.
3335 Vars.push_back(DE);
3336 continue;
3337 }
3338
3339 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3340 // A threadprivate variable must not have an incomplete type.
3341 if (SemaRef.RequireCompleteType(
3342 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3343 continue;
3344 }
3345
3346 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3347 // A threadprivate variable must not have a reference type.
3348 if (VD->getType()->isReferenceType()) {
3349 unsigned OMPVersion = getLangOpts().OpenMP;
3350 Diag(ILoc, diag::err_omp_ref_type_arg)
3351 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3352 << VD->getType();
3353 bool IsDecl =
3355 Diag(VD->getLocation(),
3356 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3357 << VD;
3358 continue;
3359 }
3360
3361 // Check if this is a TLS variable. If TLS is not being supported, produce
3362 // the corresponding diagnostic.
3363 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3364 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3365 getLangOpts().OpenMPUseTLS &&
3366 getASTContext().getTargetInfo().isTLSSupported())) ||
3367 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3368 !VD->isLocalVarDecl())) {
3369 Diag(ILoc, diag::err_omp_var_thread_local)
3370 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3371 bool IsDecl =
3373 Diag(VD->getLocation(),
3374 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3375 << VD;
3376 continue;
3377 }
3378
3379 // Check if initial value of threadprivate variable reference variable with
3380 // local storage (it is not supported by runtime).
3381 if (const Expr *Init = VD->getAnyInitializer()) {
3382 LocalVarRefChecker Checker(SemaRef);
3383 if (Checker.Visit(Init))
3384 continue;
3385 }
3386
3387 Vars.push_back(RefExpr);
3388 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3389 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3390 Context, SourceRange(Loc, Loc)));
3391 if (ASTMutationListener *ML = Context.getASTMutationListener())
3392 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3393 }
3394 OMPThreadPrivateDecl *D = nullptr;
3395 if (!Vars.empty()) {
3396 D = OMPThreadPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3397 Loc, Vars);
3398 D->setAccess(AS_public);
3399 }
3400 return D;
3401}
3402
3405 ArrayRef<Expr *> VarList) {
3406 ASTContext &Context = getASTContext();
3408 for (Expr *RefExpr : VarList) {
3409 auto *DE = cast<DeclRefExpr>(RefExpr);
3410 auto *VD = cast<VarDecl>(DE->getDecl());
3411 SourceLocation ILoc = DE->getExprLoc();
3412
3413 // Mark variable as used.
3414 VD->setReferenced();
3415 VD->markUsed(Context);
3416
3417 QualType QType = VD->getType();
3418 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3419 // It will be analyzed later.
3420 Vars.push_back(DE);
3421 continue;
3422 }
3423
3424 // OpenMP groupprivate restrictions:
3425 // A groupprivate variable must not have an incomplete type.
3426 if (SemaRef.RequireCompleteType(
3427 ILoc, VD->getType(), diag::err_omp_groupprivate_incomplete_type)) {
3428 continue;
3429 }
3430
3431 // A groupprivate variable must not have a reference type.
3432 if (VD->getType()->isReferenceType()) {
3433 Diag(ILoc, diag::err_omp_ref_type_arg)
3434 << getOpenMPDirectiveName(OMPD_groupprivate) << VD->getType();
3435 bool IsDecl =
3437 Diag(VD->getLocation(),
3438 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3439 << VD;
3440 continue;
3441 }
3442
3443 // A variable that is declared with an initializer must not appear in a
3444 // groupprivate directive.
3445 if (VD->getAnyInitializer()) {
3446 Diag(ILoc, diag::err_omp_groupprivate_with_initializer)
3447 << VD->getDeclName();
3448 bool IsDecl =
3450 Diag(VD->getLocation(),
3451 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3452 << VD;
3453 continue;
3454 }
3455
3456 Vars.push_back(RefExpr);
3457 DSAStack->addDSA(VD, DE, OMPC_groupprivate);
3458 VD->addAttr(OMPGroupPrivateDeclAttr::CreateImplicit(Context,
3459 SourceRange(Loc, Loc)));
3460 if (ASTMutationListener *ML = Context.getASTMutationListener())
3461 ML->DeclarationMarkedOpenMPGroupPrivate(VD);
3462 }
3463 OMPGroupPrivateDecl *D = nullptr;
3464 if (!Vars.empty()) {
3465 D = OMPGroupPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3466 Loc, Vars);
3467 D->setAccess(AS_public);
3468 }
3469 return D;
3470}
3471
3472static OMPAllocateDeclAttr::AllocatorTypeTy
3473getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3474 if (!Allocator)
3475 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3476 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3477 Allocator->isInstantiationDependent() ||
3479 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3480 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3481 llvm::FoldingSetNodeID AEId;
3482 const Expr *AE = Allocator->IgnoreParenImpCasts();
3483 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3484 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3485 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3486 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3487 llvm::FoldingSetNodeID DAEId;
3488 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3489 /*Canonical=*/true);
3490 if (AEId == DAEId) {
3491 AllocatorKindRes = AllocatorKind;
3492 break;
3493 }
3494 }
3495 return AllocatorKindRes;
3496}
3497
3499 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3500 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3501 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3502 return false;
3503 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3504 Expr *PrevAllocator = A->getAllocator();
3505 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3506 getAllocatorKind(S, Stack, PrevAllocator);
3507 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3508 if (AllocatorsMatch &&
3509 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3510 Allocator && PrevAllocator) {
3511 const Expr *AE = Allocator->IgnoreParenImpCasts();
3512 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3513 llvm::FoldingSetNodeID AEId, PAEId;
3514 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3515 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3516 AllocatorsMatch = AEId == PAEId;
3517 }
3518 if (!AllocatorsMatch) {
3519 SmallString<256> AllocatorBuffer;
3520 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3521 if (Allocator)
3522 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3523 SmallString<256> PrevAllocatorBuffer;
3524 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3525 if (PrevAllocator)
3526 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3527 S.getPrintingPolicy());
3528
3529 SourceLocation AllocatorLoc =
3530 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3531 SourceRange AllocatorRange =
3532 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3533 SourceLocation PrevAllocatorLoc =
3534 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3535 SourceRange PrevAllocatorRange =
3536 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3537 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3538 << (Allocator ? 1 : 0) << AllocatorStream.str()
3539 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3540 << AllocatorRange;
3541 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3542 << PrevAllocatorRange;
3543 return true;
3544 }
3545 return false;
3546}
3547
3548static void
3550 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3551 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3552 if (VD->hasAttr<OMPAllocateDeclAttr>())
3553 return;
3554 if (Alignment &&
3555 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3556 Alignment->isInstantiationDependent() ||
3557 Alignment->containsUnexpandedParameterPack()))
3558 // Apply later when we have a usable value.
3559 return;
3560 if (Allocator &&
3561 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3562 Allocator->isInstantiationDependent() ||
3563 Allocator->containsUnexpandedParameterPack()))
3564 return;
3565 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3566 Allocator, Alignment, SR);
3567 VD->addAttr(A);
3569 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3570}
3571
3574 DeclContext *Owner) {
3575 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3576 Expr *Alignment = nullptr;
3577 Expr *Allocator = nullptr;
3578 if (Clauses.empty()) {
3579 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3580 // allocate directives that appear in a target region must specify an
3581 // allocator clause unless a requires directive with the dynamic_allocators
3582 // clause is present in the same compilation unit.
3583 if (getLangOpts().OpenMPIsTargetDevice &&
3584 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3585 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3586 } else {
3587 for (const OMPClause *C : Clauses)
3588 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3589 Allocator = AC->getAllocator();
3590 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3591 Alignment = AC->getAlignment();
3592 else
3593 llvm_unreachable("Unexpected clause on allocate directive");
3594 }
3595 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3596 getAllocatorKind(SemaRef, DSAStack, Allocator);
3598 for (Expr *RefExpr : VarList) {
3599 auto *DE = cast<DeclRefExpr>(RefExpr);
3600 auto *VD = cast<VarDecl>(DE->getDecl());
3601
3602 // Check if this is a TLS variable or global register.
3603 if (VD->getTLSKind() != VarDecl::TLS_None ||
3604 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3605 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3606 !VD->isLocalVarDecl()))
3607 continue;
3608
3609 // If the used several times in the allocate directive, the same allocator
3610 // must be used.
3612 AllocatorKind, Allocator))
3613 continue;
3614
3615 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3616 // If a list item has a static storage type, the allocator expression in the
3617 // allocator clause must be a constant expression that evaluates to one of
3618 // the predefined memory allocator values.
3619 if (Allocator && VD->hasGlobalStorage()) {
3620 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3621 Diag(Allocator->getExprLoc(),
3622 diag::err_omp_expected_predefined_allocator)
3623 << Allocator->getSourceRange();
3624 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3626 Diag(VD->getLocation(),
3627 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3628 << VD;
3629 continue;
3630 }
3631 }
3632
3633 Vars.push_back(RefExpr);
3634 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3635 DE->getSourceRange());
3636 }
3637 if (Vars.empty())
3638 return nullptr;
3639 if (!Owner)
3640 Owner = SemaRef.getCurLexicalContext();
3641 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3642 D->setAccess(AS_public);
3643 Owner->addDecl(D);
3645}
3646
3649 ArrayRef<OMPClause *> ClauseList) {
3650 OMPRequiresDecl *D = nullptr;
3651 if (!SemaRef.CurContext->isFileContext()) {
3652 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3653 } else {
3654 D = CheckOMPRequiresDecl(Loc, ClauseList);
3655 if (D) {
3656 SemaRef.CurContext->addDecl(D);
3657 DSAStack->addRequiresDecl(D);
3658 }
3659 }
3661}
3662
3664 OpenMPDirectiveKind DKind,
3665 ArrayRef<std::string> Assumptions,
3666 bool SkippedClauses) {
3667 if (!SkippedClauses && Assumptions.empty()) {
3668 unsigned OMPVersion = getLangOpts().OpenMP;
3669 Diag(Loc, diag::err_omp_no_clause_for_directive)
3670 << llvm::omp::getAllAssumeClauseOptions()
3671 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3672 }
3673
3674 auto *AA =
3675 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3676 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3677 OMPAssumeScoped.push_back(AA);
3678 return;
3679 }
3680
3681 // Global assumes without assumption clauses are ignored.
3682 if (Assumptions.empty())
3683 return;
3684
3685 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3686 "Unexpected omp assumption directive!");
3687 OMPAssumeGlobal.push_back(AA);
3688
3689 // The OMPAssumeGlobal scope above will take care of new declarations but
3690 // we also want to apply the assumption to existing ones, e.g., to
3691 // declarations in included headers. To this end, we traverse all existing
3692 // declaration contexts and annotate function declarations here.
3693 SmallVector<DeclContext *, 8> DeclContexts;
3694 auto *Ctx = SemaRef.CurContext;
3695 while (Ctx->getLexicalParent())
3696 Ctx = Ctx->getLexicalParent();
3697 DeclContexts.push_back(Ctx);
3698 while (!DeclContexts.empty()) {
3699 DeclContext *DC = DeclContexts.pop_back_val();
3700 for (auto *SubDC : DC->decls()) {
3701 if (SubDC->isInvalidDecl())
3702 continue;
3703 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3704 DeclContexts.push_back(CTD->getTemplatedDecl());
3705 llvm::append_range(DeclContexts, CTD->specializations());
3706 continue;
3707 }
3708 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3709 DeclContexts.push_back(DC);
3710 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3711 F->addAttr(AA);
3712 continue;
3713 }
3714 }
3715 }
3716}
3717
3719 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3720 OMPAssumeScoped.pop_back();
3721}
3722
3724 Stmt *AStmt,
3725 SourceLocation StartLoc,
3726 SourceLocation EndLoc) {
3727 if (!AStmt)
3728 return StmtError();
3729
3730 return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
3731 AStmt);
3732}
3733
3736 ArrayRef<OMPClause *> ClauseList) {
3737 /// For target specific clauses, the requires directive cannot be
3738 /// specified after the handling of any of the target regions in the
3739 /// current compilation unit.
3740 ArrayRef<SourceLocation> TargetLocations =
3741 DSAStack->getEncounteredTargetLocs();
3742 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3743 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3744 for (const OMPClause *CNew : ClauseList) {
3745 // Check if any of the requires clauses affect target regions.
3750 Diag(Loc, diag::err_omp_directive_before_requires)
3751 << "target" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3752 for (SourceLocation TargetLoc : TargetLocations) {
3753 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3754 << "target";
3755 }
3756 } else if (!AtomicLoc.isInvalid() &&
3758 Diag(Loc, diag::err_omp_directive_before_requires)
3759 << "atomic" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3760 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3761 << "atomic";
3762 }
3763 }
3764 }
3765
3766 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3768 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3769 return nullptr;
3770}
3771
3772static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3773 const ValueDecl *D,
3774 const DSAStackTy::DSAVarData &DVar,
3775 bool IsLoopIterVar) {
3776 if (DVar.RefExpr) {
3777 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3778 << getOpenMPClauseNameForDiag(DVar.CKind);
3779 return;
3780 }
3781 enum {
3782 PDSA_StaticMemberShared,
3783 PDSA_StaticLocalVarShared,
3784 PDSA_LoopIterVarPrivate,
3785 PDSA_LoopIterVarLinear,
3786 PDSA_LoopIterVarLastprivate,
3787 PDSA_ConstVarShared,
3788 PDSA_GlobalVarShared,
3789 PDSA_TaskVarFirstprivate,
3790 PDSA_LocalVarPrivate,
3791 PDSA_Implicit
3792 } Reason = PDSA_Implicit;
3793 bool ReportHint = false;
3794 auto ReportLoc = D->getLocation();
3795 auto *VD = dyn_cast<VarDecl>(D);
3796 if (IsLoopIterVar) {
3797 if (DVar.CKind == OMPC_private)
3798 Reason = PDSA_LoopIterVarPrivate;
3799 else if (DVar.CKind == OMPC_lastprivate)
3800 Reason = PDSA_LoopIterVarLastprivate;
3801 else
3802 Reason = PDSA_LoopIterVarLinear;
3803 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3804 DVar.CKind == OMPC_firstprivate) {
3805 Reason = PDSA_TaskVarFirstprivate;
3806 ReportLoc = DVar.ImplicitDSALoc;
3807 } else if (VD && VD->isStaticLocal())
3808 Reason = PDSA_StaticLocalVarShared;
3809 else if (VD && VD->isStaticDataMember())
3810 Reason = PDSA_StaticMemberShared;
3811 else if (VD && VD->isFileVarDecl())
3812 Reason = PDSA_GlobalVarShared;
3813 else if (D->getType().isConstant(SemaRef.getASTContext()))
3814 Reason = PDSA_ConstVarShared;
3815 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3816 ReportHint = true;
3817 Reason = PDSA_LocalVarPrivate;
3818 }
3819 if (Reason != PDSA_Implicit) {
3820 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
3821 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3822 << Reason << ReportHint
3823 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3824 } else if (DVar.ImplicitDSALoc.isValid()) {
3825 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3826 << getOpenMPClauseNameForDiag(DVar.CKind);
3827 }
3828}
3829
3832 bool IsAggregateOrDeclareTarget) {
3834 switch (M) {
3835 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3836 case OMPC_DEFAULTMAP_MODIFIER_storage:
3837 Kind = OMPC_MAP_alloc;
3838 break;
3839 case OMPC_DEFAULTMAP_MODIFIER_to:
3840 Kind = OMPC_MAP_to;
3841 break;
3842 case OMPC_DEFAULTMAP_MODIFIER_from:
3843 Kind = OMPC_MAP_from;
3844 break;
3845 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3846 Kind = OMPC_MAP_tofrom;
3847 break;
3848 case OMPC_DEFAULTMAP_MODIFIER_present:
3849 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3850 // If implicit-behavior is present, each variable referenced in the
3851 // construct in the category specified by variable-category is treated as if
3852 // it had been listed in a map clause with the map-type of alloc and
3853 // map-type-modifier of present.
3854 Kind = OMPC_MAP_alloc;
3855 break;
3856 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3857 case OMPC_DEFAULTMAP_MODIFIER_private:
3859 llvm_unreachable("Unexpected defaultmap implicit behavior");
3860 case OMPC_DEFAULTMAP_MODIFIER_none:
3861 case OMPC_DEFAULTMAP_MODIFIER_default:
3863 // IsAggregateOrDeclareTarget could be true if:
3864 // 1. the implicit behavior for aggregate is tofrom
3865 // 2. it's a declare target link
3866 if (IsAggregateOrDeclareTarget) {
3867 Kind = OMPC_MAP_tofrom;
3868 break;
3869 }
3870 llvm_unreachable("Unexpected defaultmap implicit behavior");
3871 }
3872 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3873 return Kind;
3874}
3875
3876namespace {
3877struct VariableImplicitInfo {
3878 static const unsigned MapKindNum = OMPC_MAP_unknown;
3879 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3880
3881 llvm::SetVector<Expr *> Privates;
3882 llvm::SetVector<Expr *> Firstprivates;
3883 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3884 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3885 MapModifiers[DefaultmapKindNum];
3886};
3887
3888class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3889 DSAStackTy *Stack;
3890 Sema &SemaRef;
3891 OpenMPDirectiveKind DKind = OMPD_unknown;
3892 bool ErrorFound = false;
3893 bool TryCaptureCXXThisMembers = false;
3894 CapturedStmt *CS = nullptr;
3895
3896 VariableImplicitInfo ImpInfo;
3897 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3898 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3899
3900 void VisitSubCaptures(OMPExecutableDirective *S) {
3901 // Check implicitly captured variables.
3902 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3903 return;
3904 if (S->getDirectiveKind() == OMPD_atomic ||
3905 S->getDirectiveKind() == OMPD_critical ||
3906 S->getDirectiveKind() == OMPD_section ||
3907 S->getDirectiveKind() == OMPD_master ||
3908 S->getDirectiveKind() == OMPD_masked ||
3909 S->getDirectiveKind() == OMPD_scope ||
3910 S->getDirectiveKind() == OMPD_assume ||
3911 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3912 Visit(S->getAssociatedStmt());
3913 return;
3914 }
3915 visitSubCaptures(S->getInnermostCapturedStmt());
3916 // Try to capture inner this->member references to generate correct mappings
3917 // and diagnostics.
3918 if (TryCaptureCXXThisMembers ||
3920 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3921 [](const CapturedStmt::Capture &C) {
3922 return C.capturesThis();
3923 }))) {
3924 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3925 TryCaptureCXXThisMembers = true;
3926 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3927 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3928 }
3929 // In tasks firstprivates are not captured anymore, need to analyze them
3930 // explicitly.
3931 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3932 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3933 for (OMPClause *C : S->clauses())
3934 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3935 for (Expr *Ref : FC->varlist())
3936 Visit(Ref);
3937 }
3938 }
3939 }
3940
3941public:
3942 void VisitDeclRefExpr(DeclRefExpr *E) {
3943 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3947 return;
3948 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3949 // Check the datasharing rules for the expressions in the clauses.
3950 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3951 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3952 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3953 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3954 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3955 Visit(CED->getInit());
3956 return;
3957 }
3958 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3959 // Do not analyze internal variables and do not enclose them into
3960 // implicit clauses.
3961 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3962 return;
3963 VD = VD->getCanonicalDecl();
3964 // Skip internally declared variables.
3965 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3966 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3967 !Stack->isImplicitTaskFirstprivate(VD))
3968 return;
3969 // Skip allocators in uses_allocators clauses.
3970 if (Stack->isUsesAllocatorsDecl(VD))
3971 return;
3972
3973 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3974 // Check if the variable has explicit DSA set and stop analysis if it so.
3975 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3976 return;
3977
3978 // Skip internally declared static variables.
3979 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3980 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3981 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3982 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3983 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3984 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3985 !Stack->isImplicitTaskFirstprivate(VD))
3986 return;
3987
3988 SourceLocation ELoc = E->getExprLoc();
3989 // The default(none) clause requires that each variable that is referenced
3990 // in the construct, and does not have a predetermined data-sharing
3991 // attribute, must have its data-sharing attribute explicitly determined
3992 // by being listed in a data-sharing attribute clause.
3993 if (DVar.CKind == OMPC_unknown &&
3994 (Stack->getDefaultDSA() == DSA_none ||
3995 Stack->getDefaultDSA() == DSA_private ||
3996 Stack->getDefaultDSA() == DSA_firstprivate) &&
3997 isImplicitOrExplicitTaskingRegion(DKind) &&
3998 VarsWithInheritedDSA.count(VD) == 0) {
3999 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4000 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4001 Stack->getDefaultDSA() == DSA_private)) {
4002 DSAStackTy::DSAVarData DVar =
4003 Stack->getImplicitDSA(VD, /*FromParent=*/false);
4004 InheritedDSA = DVar.CKind == OMPC_unknown;
4005 }
4006 if (InheritedDSA)
4007 VarsWithInheritedDSA[VD] = E;
4008 if (Stack->getDefaultDSA() == DSA_none)
4009 return;
4010 }
4011
4012 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
4013 // If implicit-behavior is none, each variable referenced in the
4014 // construct that does not have a predetermined data-sharing attribute
4015 // and does not appear in a to or link clause on a declare target
4016 // directive must be listed in a data-mapping attribute clause, a
4017 // data-sharing attribute clause (including a data-sharing attribute
4018 // clause on a combined construct where target. is one of the
4019 // constituent constructs), or an is_device_ptr clause.
4020 OpenMPDefaultmapClauseKind ClauseKind =
4022 if (SemaRef.getLangOpts().OpenMP >= 50) {
4023 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
4024 OMPC_DEFAULTMAP_MODIFIER_none;
4025 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4026 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
4027 // Only check for data-mapping attribute and is_device_ptr here
4028 // since we have already make sure that the declaration does not
4029 // have a data-sharing attribute above
4030 if (!Stack->checkMappableExprComponentListsForDecl(
4031 VD, /*CurrentRegionOnly=*/true,
4033 MapExprComponents,
4035 auto MI = MapExprComponents.rbegin();
4036 auto ME = MapExprComponents.rend();
4037 return MI != ME && MI->getAssociatedDeclaration() == VD;
4038 })) {
4039 VarsWithInheritedDSA[VD] = E;
4040 return;
4041 }
4042 }
4043 }
4044 if (SemaRef.getLangOpts().OpenMP > 50) {
4045 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
4046 OMPC_DEFAULTMAP_MODIFIER_present;
4047 if (IsModifierPresent) {
4048 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
4049 OMPC_MAP_MODIFIER_present)) {
4050 ImpInfo.MapModifiers[ClauseKind].push_back(
4051 OMPC_MAP_MODIFIER_present);
4052 }
4053 }
4054 }
4055
4057 !Stack->isLoopControlVariable(VD).first) {
4058 if (!Stack->checkMappableExprComponentListsForDecl(
4059 VD, /*CurrentRegionOnly=*/true,
4061 StackComponents,
4063 if (SemaRef.LangOpts.OpenMP >= 50)
4064 return !StackComponents.empty();
4065 // Variable is used if it has been marked as an array, array
4066 // section, array shaping or the variable itself.
4067 return StackComponents.size() == 1 ||
4068 llvm::all_of(
4069 llvm::drop_begin(llvm::reverse(StackComponents)),
4070 [](const OMPClauseMappableExprCommon::
4071 MappableComponent &MC) {
4072 return MC.getAssociatedDeclaration() ==
4073 nullptr &&
4074 (isa<ArraySectionExpr>(
4075 MC.getAssociatedExpression()) ||
4076 isa<OMPArrayShapingExpr>(
4077 MC.getAssociatedExpression()) ||
4078 isa<ArraySubscriptExpr>(
4079 MC.getAssociatedExpression()));
4080 });
4081 })) {
4082 bool IsFirstprivate = false;
4083 // By default lambdas are captured as firstprivates.
4084 if (const auto *RD =
4086 IsFirstprivate = RD->isLambda();
4087 IsFirstprivate =
4088 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
4089 if (IsFirstprivate) {
4090 ImpInfo.Firstprivates.insert(E);
4091 } else {
4093 Stack->getDefaultmapModifier(ClauseKind);
4094 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4095 ImpInfo.Privates.insert(E);
4096 } else {
4098 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
4099 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4100 }
4101 }
4102 return;
4103 }
4104 }
4105
4106 // OpenMP [2.9.3.6, Restrictions, p.2]
4107 // A list item that appears in a reduction clause of the innermost
4108 // enclosing worksharing or parallel construct may not be accessed in an
4109 // explicit task.
4110 DVar = Stack->hasInnermostDSA(
4111 VD,
4112 [](OpenMPClauseKind C, bool AppliedToPointee) {
4113 return C == OMPC_reduction && !AppliedToPointee;
4114 },
4115 [](OpenMPDirectiveKind K) {
4116 return isOpenMPParallelDirective(K) ||
4118 },
4119 /*FromParent=*/true);
4120 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4121 ErrorFound = true;
4122 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4123 reportOriginalDsa(SemaRef, Stack, VD, DVar);
4124 return;
4125 }
4126
4127 // Define implicit data-sharing attributes for task.
4128 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
4129 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
4130 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4131 DVar.CKind == OMPC_firstprivate) ||
4132 (Stack->getDefaultDSA() == DSA_private &&
4133 DVar.CKind == OMPC_private)) &&
4134 !DVar.RefExpr)) &&
4135 !Stack->isLoopControlVariable(VD).first) {
4136 if (Stack->getDefaultDSA() == DSA_private)
4137 ImpInfo.Privates.insert(E);
4138 else
4139 ImpInfo.Firstprivates.insert(E);
4140 return;
4141 }
4142
4143 // Store implicitly used globals with declare target link for parent
4144 // target.
4145 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
4146 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4147 Stack->addToParentTargetRegionLinkGlobals(E);
4148 return;
4149 }
4150 }
4151 }
4152 void VisitMemberExpr(MemberExpr *E) {
4153 if (E->isTypeDependent() || E->isValueDependent() ||
4155 return;
4156 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
4157 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
4158 if (!FD)
4159 return;
4160 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
4161 // Check if the variable has explicit DSA set and stop analysis if it
4162 // so.
4163 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4164 return;
4165
4167 !Stack->isLoopControlVariable(FD).first &&
4168 !Stack->checkMappableExprComponentListsForDecl(
4169 FD, /*CurrentRegionOnly=*/true,
4171 StackComponents,
4173 return isa<CXXThisExpr>(
4174 cast<MemberExpr>(
4175 StackComponents.back().getAssociatedExpression())
4176 ->getBase()
4177 ->IgnoreParens());
4178 })) {
4179 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4180 // A bit-field cannot appear in a map clause.
4181 //
4182 if (FD->isBitField())
4183 return;
4184
4185 // Check to see if the member expression is referencing a class that
4186 // has already been explicitly mapped
4187 if (Stack->isClassPreviouslyMapped(TE->getType()))
4188 return;
4189
4191 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4192 OpenMPDefaultmapClauseKind ClauseKind =
4195 Modifier, /*IsAggregateOrDeclareTarget=*/true);
4196 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4197 return;
4198 }
4199
4200 SourceLocation ELoc = E->getExprLoc();
4201 // OpenMP [2.9.3.6, Restrictions, p.2]
4202 // A list item that appears in a reduction clause of the innermost
4203 // enclosing worksharing or parallel construct may not be accessed in
4204 // an explicit task.
4205 DVar = Stack->hasInnermostDSA(
4206 FD,
4207 [](OpenMPClauseKind C, bool AppliedToPointee) {
4208 return C == OMPC_reduction && !AppliedToPointee;
4209 },
4210 [](OpenMPDirectiveKind K) {
4211 return isOpenMPParallelDirective(K) ||
4213 },
4214 /*FromParent=*/true);
4215 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4216 ErrorFound = true;
4217 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4218 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4219 return;
4220 }
4221
4222 // Define implicit data-sharing attributes for task.
4223 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4224 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4225 !Stack->isLoopControlVariable(FD).first) {
4226 // Check if there is a captured expression for the current field in the
4227 // region. Do not mark it as firstprivate unless there is no captured
4228 // expression.
4229 // TODO: try to make it firstprivate.
4230 if (DVar.CKind != OMPC_unknown)
4231 ImpInfo.Firstprivates.insert(E);
4232 }
4233 return;
4234 }
4237 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4238 DKind, /*NoDiagnose=*/true))
4239 return;
4240 const auto *VD = cast<ValueDecl>(
4241 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4242 if (!Stack->checkMappableExprComponentListsForDecl(
4243 VD, /*CurrentRegionOnly=*/true,
4244 [&CurComponents](
4246 StackComponents,
4248 auto CCI = CurComponents.rbegin();
4249 auto CCE = CurComponents.rend();
4250 for (const auto &SC : llvm::reverse(StackComponents)) {
4251 // Do both expressions have the same kind?
4252 if (CCI->getAssociatedExpression()->getStmtClass() !=
4253 SC.getAssociatedExpression()->getStmtClass())
4254 if (!((isa<ArraySectionExpr>(
4255 SC.getAssociatedExpression()) ||
4256 isa<OMPArrayShapingExpr>(
4257 SC.getAssociatedExpression())) &&
4258 isa<ArraySubscriptExpr>(
4259 CCI->getAssociatedExpression())))
4260 return false;
4261
4262 const Decl *CCD = CCI->getAssociatedDeclaration();
4263 const Decl *SCD = SC.getAssociatedDeclaration();
4264 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4265 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4266 if (SCD != CCD)
4267 return false;
4268 std::advance(CCI, 1);
4269 if (CCI == CCE)
4270 break;
4271 }
4272 return true;
4273 })) {
4274 Visit(E->getBase());
4275 }
4276 } else if (!TryCaptureCXXThisMembers) {
4277 Visit(E->getBase());
4278 }
4279 }
4280 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4281 for (OMPClause *C : S->clauses()) {
4282 // Skip analysis of arguments of private clauses for task|target
4283 // directives.
4284 if (isa_and_nonnull<OMPPrivateClause>(C))
4285 continue;
4286 // Skip analysis of arguments of implicitly defined firstprivate clause
4287 // for task|target directives.
4288 // Skip analysis of arguments of implicitly defined map clause for target
4289 // directives.
4291 C->isImplicit() && !isOpenMPTaskingDirective(DKind))) {
4292 for (Stmt *CC : C->children()) {
4293 if (CC)
4294 Visit(CC);
4295 }
4296 }
4297 }
4298 // Check implicitly captured variables.
4299 VisitSubCaptures(S);
4300 }
4301
4302 void VisitOMPCanonicalLoopNestTransformationDirective(
4303 OMPCanonicalLoopNestTransformationDirective *S) {
4304 // Loop transformation directives do not introduce data sharing
4305 VisitStmt(S);
4306 }
4307
4308 void VisitCallExpr(CallExpr *S) {
4309 for (Stmt *C : S->arguments()) {
4310 if (C) {
4311 // Check implicitly captured variables in the task-based directives to
4312 // check if they must be firstprivatized.
4313 Visit(C);
4314 }
4315 }
4316 if (Expr *Callee = S->getCallee()) {
4317 auto *CI = Callee->IgnoreParenImpCasts();
4318 if (auto *CE = dyn_cast<MemberExpr>(CI))
4319 Visit(CE->getBase());
4320 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4321 Visit(CE);
4322 }
4323 }
4324 void VisitStmt(Stmt *S) {
4325 for (Stmt *C : S->children()) {
4326 if (C) {
4327 // Check implicitly captured variables in the task-based directives to
4328 // check if they must be firstprivatized.
4329 Visit(C);
4330 }
4331 }
4332 }
4333
4334 void visitSubCaptures(CapturedStmt *S) {
4335 for (const CapturedStmt::Capture &Cap : S->captures()) {
4336 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4337 continue;
4338 VarDecl *VD = Cap.getCapturedVar();
4339 // Do not try to map the variable if it or its sub-component was mapped
4340 // already.
4342 Stack->checkMappableExprComponentListsForDecl(
4343 VD, /*CurrentRegionOnly=*/true,
4345 OpenMPClauseKind) { return true; }))
4346 continue;
4347 DeclRefExpr *DRE = buildDeclRefExpr(
4348 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4349 Cap.getLocation(), /*RefersToCapture=*/true);
4350 Visit(DRE);
4351 }
4352 }
4353 bool isErrorFound() const { return ErrorFound; }
4354 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4355 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4356 return VarsWithInheritedDSA;
4357 }
4358
4359 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4360 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4361 DKind = S->getCurrentDirective();
4362 // Process declare target link variables for the target directives.
4364 for (DeclRefExpr *E : Stack->getLinkGlobals())
4365 Visit(E);
4366 }
4367 }
4368};
4369} // namespace
4370
4371static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4372 OpenMPDirectiveKind DKind,
4373 bool ScopeEntry) {
4376 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4377 if (isOpenMPTeamsDirective(DKind))
4378 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4379 if (isOpenMPParallelDirective(DKind))
4380 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4382 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4383 if (isOpenMPSimdDirective(DKind))
4384 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4385 Stack->handleConstructTrait(Traits, ScopeEntry);
4386}
4387
4388static SmallVector<SemaOpenMP::CapturedParamNameType>
4389getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4390 ASTContext &Context = SemaRef.getASTContext();
4391 QualType KmpInt32Ty =
4392 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4393 QualType KmpInt32PtrTy =
4394 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4396 std::make_pair(".global_tid.", KmpInt32PtrTy),
4397 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4398 };
4399 if (LoopBoundSharing) {
4400 QualType KmpSizeTy = Context.getSizeType().withConst();
4401 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4402 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4403 }
4404
4405 // __context with shared vars
4406 Params.push_back(std::make_pair(StringRef(), QualType()));
4407 return Params;
4408}
4409
4410static SmallVector<SemaOpenMP::CapturedParamNameType>
4412 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4413}
4414
4415static SmallVector<SemaOpenMP::CapturedParamNameType>
4417 ASTContext &Context = SemaRef.getASTContext();
4418 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4419 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4420 QualType KmpInt32PtrTy =
4421 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4422 QualType Args[] = {VoidPtrTy};
4424 EPI.Variadic = true;
4425 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4427 std::make_pair(".global_tid.", KmpInt32Ty),
4428 std::make_pair(".part_id.", KmpInt32PtrTy),
4429 std::make_pair(".privates.", VoidPtrTy),
4430 std::make_pair(
4431 ".copy_fn.",
4432 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4433 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4434 std::make_pair(StringRef(), QualType()) // __context with shared vars
4435 };
4436 return Params;
4437}
4438
4439static SmallVector<SemaOpenMP::CapturedParamNameType>
4441 ASTContext &Context = SemaRef.getASTContext();
4443 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4444 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4445 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4446 }
4447 // __context with shared vars
4448 Params.push_back(std::make_pair(StringRef(), QualType()));
4449 return Params;
4450}
4451
4452static SmallVector<SemaOpenMP::CapturedParamNameType>
4455 std::make_pair(StringRef(), QualType()) // __context with shared vars
4456 };
4457 return Params;
4458}
4459
4460static SmallVector<SemaOpenMP::CapturedParamNameType>
4462 ASTContext &Context = SemaRef.getASTContext();
4463 QualType KmpInt32Ty =
4464 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4465 QualType KmpUInt64Ty =
4466 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4467 QualType KmpInt64Ty =
4468 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4469 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4470 QualType KmpInt32PtrTy =
4471 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4472 QualType Args[] = {VoidPtrTy};
4474 EPI.Variadic = true;
4475 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4477 std::make_pair(".global_tid.", KmpInt32Ty),
4478 std::make_pair(".part_id.", KmpInt32PtrTy),
4479 std::make_pair(".privates.", VoidPtrTy),
4480 std::make_pair(
4481 ".copy_fn.",
4482 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4483 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4484 std::make_pair(".lb.", KmpUInt64Ty),
4485 std::make_pair(".ub.", KmpUInt64Ty),
4486 std::make_pair(".st.", KmpInt64Ty),
4487 std::make_pair(".liter.", KmpInt32Ty),
4488 std::make_pair(".reductions.", VoidPtrTy),
4489 std::make_pair(StringRef(), QualType()) // __context with shared vars
4490 };
4491 return Params;
4492}
4493
4495 Scope *CurScope, SourceLocation Loc) {
4497 getOpenMPCaptureRegions(Regions, DKind);
4498
4499 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4500
4501 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4502 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4503 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4504 };
4505
4506 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4507 switch (RKind) {
4508 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4509 // are listed here.
4510 case OMPD_parallel:
4512 Loc, CurScope, CR_OpenMP,
4513 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4514 break;
4515 case OMPD_teams:
4516 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4517 getTeamsRegionParams(SemaRef), Level);
4518 break;
4519 case OMPD_task:
4520 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4521 getTaskRegionParams(SemaRef), Level);
4522 // Mark this captured region as inlined, because we don't use outlined
4523 // function directly.
4524 MarkAsInlined(SemaRef.getCurCapturedRegion());
4525 break;
4526 case OMPD_taskloop:
4527 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4528 getTaskloopRegionParams(SemaRef), Level);
4529 // Mark this captured region as inlined, because we don't use outlined
4530 // function directly.
4531 MarkAsInlined(SemaRef.getCurCapturedRegion());
4532 break;
4533 case OMPD_target:
4534 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4535 getTargetRegionParams(SemaRef), Level);
4536 break;
4537 case OMPD_unknown:
4538 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4539 getUnknownRegionParams(SemaRef));
4540 break;
4541 case OMPD_metadirective:
4542 case OMPD_nothing:
4543 default:
4544 llvm_unreachable("Unexpected capture region");
4545 }
4546 }
4547}
4548
4550 Scope *CurScope) {
4551 switch (DKind) {
4552 case OMPD_atomic:
4553 case OMPD_critical:
4554 case OMPD_masked:
4555 case OMPD_master:
4556 case OMPD_section:
4557 case OMPD_tile:
4558 case OMPD_stripe:
4559 case OMPD_unroll:
4560 case OMPD_reverse:
4561 case OMPD_interchange:
4562 case OMPD_fuse:
4563 case OMPD_assume:
4564 break;
4565 default:
4566 processCapturedRegions(SemaRef, DKind, CurScope,
4567 DSAStack->getConstructLoc());
4568 break;
4569 }
4570
4571 DSAStack->setContext(SemaRef.CurContext);
4572 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4573}
4574
4575int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4576 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4577}
4578
4581 getOpenMPCaptureRegions(CaptureRegions, DKind);
4582 return CaptureRegions.size();
4583}
4584
4586 Expr *CaptureExpr, bool WithInit,
4587 DeclContext *CurContext,
4588 bool AsExpression) {
4589 assert(CaptureExpr);
4590 ASTContext &C = S.getASTContext();
4591 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4592 QualType Ty = Init->getType();
4593 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4594 if (S.getLangOpts().CPlusPlus) {
4595 Ty = C.getLValueReferenceType(Ty);
4596 } else {
4597 Ty = C.getPointerType(Ty);
4598 ExprResult Res =
4599 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4600 if (!Res.isUsable())
4601 return nullptr;
4602 Init = Res.get();
4603 }
4604 WithInit = true;
4605 }
4606 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4607 CaptureExpr->getBeginLoc());
4608 if (!WithInit)
4609 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4610 CurContext->addHiddenDecl(CED);
4612 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4613 return CED;
4614}
4615
4616static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4617 bool WithInit) {
4619 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4621 else
4622 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4623 S.CurContext,
4624 /*AsExpression=*/false);
4625 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4626 CaptureExpr->getExprLoc());
4627}
4628
4629static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4630 StringRef Name) {
4631 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4632 if (!Ref) {
4634 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4635 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4636 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4637 CaptureExpr->getExprLoc());
4638 }
4639 ExprResult Res = Ref;
4640 if (!S.getLangOpts().CPlusPlus &&
4641 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4642 Ref->getType()->isPointerType()) {
4643 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4644 if (!Res.isUsable())
4645 return ExprError();
4646 }
4647 return S.DefaultLvalueConversion(Res.get());
4648}
4649
4650namespace {
4651// OpenMP directives parsed in this section are represented as a
4652// CapturedStatement with an associated statement. If a syntax error
4653// is detected during the parsing of the associated statement, the
4654// compiler must abort processing and close the CapturedStatement.
4655//
4656// Combined directives such as 'target parallel' have more than one
4657// nested CapturedStatements. This RAII ensures that we unwind out
4658// of all the nested CapturedStatements when an error is found.
4659class CaptureRegionUnwinderRAII {
4660private:
4661 Sema &S;
4662 bool &ErrorFound;
4663 OpenMPDirectiveKind DKind = OMPD_unknown;
4664
4665public:
4666 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4667 OpenMPDirectiveKind DKind)
4668 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4669 ~CaptureRegionUnwinderRAII() {
4670 if (ErrorFound) {
4671 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4672 while (--ThisCaptureLevel >= 0)
4674 }
4675 }
4676};
4677} // namespace
4678
4680 // Capture variables captured by reference in lambdas for target-based
4681 // directives.
4682 if (!SemaRef.CurContext->isDependentContext() &&
4683 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4685 DSAStack->getCurrentDirective()))) {
4686 QualType Type = V->getType();
4687 if (const auto *RD = Type.getCanonicalType()
4688 .getNonReferenceType()
4689 ->getAsCXXRecordDecl()) {
4690 bool SavedForceCaptureByReferenceInTargetExecutable =
4691 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4692 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4693 /*V=*/true);
4694 if (RD->isLambda()) {
4695 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4696 FieldDecl *ThisCapture;
4697 RD->getCaptureFields(Captures, ThisCapture);
4698 for (const LambdaCapture &LC : RD->captures()) {
4699 if (LC.getCaptureKind() == LCK_ByRef) {
4700 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4701 DeclContext *VDC = VD->getDeclContext();
4702 if (!VDC->Encloses(SemaRef.CurContext))
4703 continue;
4704 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4705 } else if (LC.getCaptureKind() == LCK_This) {
4706 QualType ThisTy = SemaRef.getCurrentThisType();
4707 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4708 ThisTy, ThisCapture->getType()))
4709 SemaRef.CheckCXXThisCapture(LC.getLocation());
4710 }
4711 }
4712 }
4713 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4714 SavedForceCaptureByReferenceInTargetExecutable);
4715 }
4716 }
4717}
4718
4720 const ArrayRef<OMPClause *> Clauses) {
4721 const OMPOrderedClause *Ordered = nullptr;
4722 const OMPOrderClause *Order = nullptr;
4723
4724 for (const OMPClause *Clause : Clauses) {
4725 if (Clause->getClauseKind() == OMPC_ordered)
4726 Ordered = cast<OMPOrderedClause>(Clause);
4727 else if (Clause->getClauseKind() == OMPC_order) {
4728 Order = cast<OMPOrderClause>(Clause);
4729 if (Order->getKind() != OMPC_ORDER_concurrent)
4730 Order = nullptr;
4731 }
4732 if (Ordered && Order)
4733 break;
4734 }
4735
4736 if (Ordered && Order) {
4737 S.Diag(Order->getKindKwLoc(),
4738 diag::err_omp_simple_clause_incompatible_with_ordered)
4739 << getOpenMPClauseNameForDiag(OMPC_order)
4740 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4741 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4742 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4743 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4744 return true;
4745 }
4746 return false;
4747}
4748
4750 ArrayRef<OMPClause *> Clauses) {
4752 /*ScopeEntry=*/false);
4753 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4754 return S;
4755
4756 bool ErrorFound = false;
4757 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4758 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4759 if (!S.isUsable()) {
4760 ErrorFound = true;
4761 return StmtError();
4762 }
4763
4765 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4766 OMPOrderedClause *OC = nullptr;
4767 OMPScheduleClause *SC = nullptr;
4770 // This is required for proper codegen.
4771 for (OMPClause *Clause : Clauses) {
4772 if (!getLangOpts().OpenMPSimd &&
4773 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4774 DSAStack->getCurrentDirective() == OMPD_target) &&
4775 Clause->getClauseKind() == OMPC_in_reduction) {
4776 // Capture taskgroup task_reduction descriptors inside the tasking regions
4777 // with the corresponding in_reduction items.
4778 auto *IRC = cast<OMPInReductionClause>(Clause);
4779 for (Expr *E : IRC->taskgroup_descriptors())
4780 if (E)
4781 SemaRef.MarkDeclarationsReferencedInExpr(E);
4782 }
4783 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4784 Clause->getClauseKind() == OMPC_copyprivate ||
4785 (getLangOpts().OpenMPUseTLS &&
4786 getASTContext().getTargetInfo().isTLSSupported() &&
4787 Clause->getClauseKind() == OMPC_copyin)) {
4788 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4789 // Mark all variables in private list clauses as used in inner region.
4790 for (Stmt *VarRef : Clause->children()) {
4791 if (auto *E = cast_or_null<Expr>(VarRef)) {
4792 SemaRef.MarkDeclarationsReferencedInExpr(E);
4793 }
4794 }
4795 DSAStack->setForceVarCapturing(/*V=*/false);
4796 } else if (CaptureRegions.size() > 1 ||
4797 CaptureRegions.back() != OMPD_unknown) {
4798 if (auto *C = OMPClauseWithPreInit::get(Clause))
4799 PICs.push_back(C);
4800 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4801 if (Expr *E = C->getPostUpdateExpr())
4802 SemaRef.MarkDeclarationsReferencedInExpr(E);
4803 }
4804 }
4805 if (Clause->getClauseKind() == OMPC_schedule)
4806 SC = cast<OMPScheduleClause>(Clause);
4807 else if (Clause->getClauseKind() == OMPC_ordered)
4808 OC = cast<OMPOrderedClause>(Clause);
4809 else if (Clause->getClauseKind() == OMPC_linear)
4810 LCs.push_back(cast<OMPLinearClause>(Clause));
4811 }
4812 // Capture allocator expressions if used.
4813 for (Expr *E : DSAStack->getInnerAllocators())
4814 SemaRef.MarkDeclarationsReferencedInExpr(E);
4815 // OpenMP, 2.7.1 Loop Construct, Restrictions
4816 // The nonmonotonic modifier cannot be specified if an ordered clause is
4817 // specified.
4818 if (SC &&
4819 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4821 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4822 OC) {
4823 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4826 diag::err_omp_simple_clause_incompatible_with_ordered)
4827 << getOpenMPClauseNameForDiag(OMPC_schedule)
4828 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4829 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4830 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4831 ErrorFound = true;
4832 }
4833 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4834 // If an order(concurrent) clause is present, an ordered clause may not appear
4835 // on the same directive.
4836 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4837 ErrorFound = true;
4838 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4839 for (const OMPLinearClause *C : LCs) {
4840 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4841 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4842 }
4843 ErrorFound = true;
4844 }
4845 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4846 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4847 OC->getNumForLoops()) {
4848 unsigned OMPVersion = getLangOpts().OpenMP;
4849 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4850 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), OMPVersion);
4851 ErrorFound = true;
4852 }
4853 if (ErrorFound) {
4854 return StmtError();
4855 }
4856 StmtResult SR = S;
4857 unsigned CompletedRegions = 0;
4858 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4859 // Mark all variables in private list clauses as used in inner region.
4860 // Required for proper codegen of combined directives.
4861 // TODO: add processing for other clauses.
4862 if (ThisCaptureRegion != OMPD_unknown) {
4863 for (const clang::OMPClauseWithPreInit *C : PICs) {
4864 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4865 // Find the particular capture region for the clause if the
4866 // directive is a combined one with multiple capture regions.
4867 // If the directive is not a combined one, the capture region
4868 // associated with the clause is OMPD_unknown and is generated
4869 // only once.
4870 if (CaptureRegion == ThisCaptureRegion ||
4871 CaptureRegion == OMPD_unknown) {
4872 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4873 for (Decl *D : DS->decls())
4874 SemaRef.MarkVariableReferenced(D->getLocation(),
4875 cast<VarDecl>(D));
4876 }
4877 }
4878 }
4879 }
4880 if (ThisCaptureRegion == OMPD_target) {
4881 // Capture allocator traits in the target region. They are used implicitly
4882 // and, thus, are not captured by default.
4883 for (OMPClause *C : Clauses) {
4884 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4885 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4886 ++I) {
4887 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4888 if (Expr *E = D.AllocatorTraits)
4889 SemaRef.MarkDeclarationsReferencedInExpr(E);
4890 }
4891 continue;
4892 }
4893 }
4894 }
4895 if (ThisCaptureRegion == OMPD_parallel) {
4896 // Capture temp arrays for inscan reductions and locals in aligned
4897 // clauses.
4898 for (OMPClause *C : Clauses) {
4899 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4900 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4901 continue;
4902 for (Expr *E : RC->copy_array_temps())
4903 if (E)
4904 SemaRef.MarkDeclarationsReferencedInExpr(E);
4905 }
4906 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4907 for (Expr *E : AC->varlist())
4908 SemaRef.MarkDeclarationsReferencedInExpr(E);
4909 }
4910 }
4911 }
4912 if (++CompletedRegions == CaptureRegions.size())
4913 DSAStack->setBodyComplete();
4914 SR = SemaRef.ActOnCapturedRegionEnd(SR.get());
4915 }
4916 return SR;
4917}
4918
4919static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4920 OpenMPDirectiveKind CancelRegion,
4921 SourceLocation StartLoc) {
4922 // CancelRegion is only needed for cancel and cancellation_point.
4923 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4924 return false;
4925
4926 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4927 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4928 return false;
4929
4930 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4931 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4932 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
4933 return true;
4934}
4935
4936static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4937 OpenMPDirectiveKind CurrentRegion,
4938 const DeclarationNameInfo &CurrentName,
4939 OpenMPDirectiveKind CancelRegion,
4940 OpenMPBindClauseKind BindKind,
4941 SourceLocation StartLoc) {
4942 if (!Stack->getCurScope())
4943 return false;
4944
4945 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4946 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4947 bool NestingProhibited = false;
4948 bool CloseNesting = true;
4949 bool OrphanSeen = false;
4950 enum {
4951 NoRecommend,
4952 ShouldBeInParallelRegion,
4953 ShouldBeInOrderedRegion,
4954 ShouldBeInTargetRegion,
4955 ShouldBeInTeamsRegion,
4956 ShouldBeInLoopSimdRegion,
4957 } Recommend = NoRecommend;
4958
4961 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4962 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4963 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4964
4965 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
4967 SemaRef.LangOpts)) {
4968 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
4969 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
4970 return true;
4971 }
4972 if (isOpenMPSimdDirective(ParentRegion) &&
4973 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
4974 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
4975 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4976 CurrentRegion != OMPD_scan))) {
4977 // OpenMP [2.16, Nesting of Regions]
4978 // OpenMP constructs may not be nested inside a simd region.
4979 // OpenMP [2.8.1,simd Construct, Restrictions]
4980 // An ordered construct with the simd clause is the only OpenMP
4981 // construct that can appear in the simd region.
4982 // Allowing a SIMD construct nested in another SIMD construct is an
4983 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4984 // message.
4985 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4986 // The only OpenMP constructs that can be encountered during execution of
4987 // a simd region are the atomic construct, the loop construct, the simd
4988 // construct and the ordered construct with the simd clause.
4989 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4990 ? diag::err_omp_prohibited_region_simd
4991 : diag::warn_omp_nesting_simd)
4992 << (OMPVersion >= 50 ? 1 : 0);
4993 return CurrentRegion != OMPD_simd;
4994 }
4995 if (EnclosingConstruct == OMPD_atomic) {
4996 // OpenMP [2.16, Nesting of Regions]
4997 // OpenMP constructs may not be nested inside an atomic region.
4998 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4999 return true;
5000 }
5001 if (CurrentRegion == OMPD_section) {
5002 // OpenMP [2.7.2, sections Construct, Restrictions]
5003 // Orphaned section directives are prohibited. That is, the section
5004 // directives must appear within the sections construct and must not be
5005 // encountered elsewhere in the sections region.
5006 if (EnclosingConstruct != OMPD_sections) {
5007 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5008 << (ParentRegion != OMPD_unknown)
5009 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
5010 return true;
5011 }
5012 return false;
5013 }
5014 // Allow some constructs (except teams and cancellation constructs) to be
5015 // orphaned (they could be used in functions, called from OpenMP regions
5016 // with the required preconditions).
5017 if (ParentRegion == OMPD_unknown &&
5018 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5019 CurrentRegion != OMPD_cancellation_point &&
5020 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5021 return false;
5022 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5023 // for a detailed explanation
5024 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5025 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5026 (isOpenMPWorksharingDirective(ParentRegion) ||
5027 EnclosingConstruct == OMPD_loop)) {
5028 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5029 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5030 << true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
5031 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5032 return true;
5033 }
5034 if (CurrentRegion == OMPD_cancellation_point ||
5035 CurrentRegion == OMPD_cancel) {
5036 // OpenMP [2.16, Nesting of Regions]
5037 // A cancellation point construct for which construct-type-clause is
5038 // taskgroup must be nested inside a task construct. A cancellation
5039 // point construct for which construct-type-clause is not taskgroup must
5040 // be closely nested inside an OpenMP construct that matches the type
5041 // specified in construct-type-clause.
5042 // A cancel construct for which construct-type-clause is taskgroup must be
5043 // nested inside a task construct. A cancel construct for which
5044 // construct-type-clause is not taskgroup must be closely nested inside an
5045 // OpenMP construct that matches the type specified in
5046 // construct-type-clause.
5047 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
5048 if (CancelRegion == OMPD_taskgroup) {
5049 NestingProhibited =
5050 EnclosingConstruct != OMPD_task &&
5051 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5052 } else if (CancelRegion == OMPD_sections) {
5053 NestingProhibited = EnclosingConstruct != OMPD_section &&
5054 EnclosingConstruct != OMPD_sections;
5055 } else {
5056 NestingProhibited = CancelRegion != Leafs.back();
5057 }
5058 OrphanSeen = ParentRegion == OMPD_unknown;
5059 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5060 // OpenMP 5.1 [2.22, Nesting of Regions]
5061 // A masked region may not be closely nested inside a worksharing, loop,
5062 // atomic, task, or taskloop region.
5063 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5064 isOpenMPGenericLoopDirective(ParentRegion) ||
5065 isOpenMPTaskingDirective(ParentRegion);
5066 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5067 // OpenMP [2.16, Nesting of Regions]
5068 // A critical region may not be nested (closely or otherwise) inside a
5069 // critical region with the same name. Note that this restriction is not
5070 // sufficient to prevent deadlock.
5071 SourceLocation PreviousCriticalLoc;
5072 bool DeadLock = Stack->hasDirective(
5073 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5074 const DeclarationNameInfo &DNI,
5075 SourceLocation Loc) {
5076 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5077 PreviousCriticalLoc = Loc;
5078 return true;
5079 }
5080 return false;
5081 },
5082 false /* skip top directive */);
5083 if (DeadLock) {
5084 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
5085 << CurrentName.getName();
5086 if (PreviousCriticalLoc.isValid())
5087 SemaRef.Diag(PreviousCriticalLoc,
5088 diag::note_omp_previous_critical_region);
5089 return true;
5090 }
5091 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5092 // OpenMP 5.1 [2.22, Nesting of Regions]
5093 // A scope region may not be closely nested inside a worksharing, loop,
5094 // task, taskloop, critical, ordered, atomic, or masked region.
5095 // OpenMP 5.1 [2.22, Nesting of Regions]
5096 // A barrier region may not be closely nested inside a worksharing, loop,
5097 // task, taskloop, critical, ordered, atomic, or masked region.
5098 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5099 isOpenMPGenericLoopDirective(ParentRegion) ||
5100 isOpenMPTaskingDirective(ParentRegion) ||
5101 llvm::is_contained({OMPD_masked, OMPD_master,
5102 OMPD_critical, OMPD_ordered},
5103 EnclosingConstruct);
5104 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5105 !isOpenMPParallelDirective(CurrentRegion) &&
5106 !isOpenMPTeamsDirective(CurrentRegion)) {
5107 // OpenMP 5.1 [2.22, Nesting of Regions]
5108 // A loop region that binds to a parallel region or a worksharing region
5109 // may not be closely nested inside a worksharing, loop, task, taskloop,
5110 // critical, ordered, atomic, or masked region.
5111 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5112 isOpenMPGenericLoopDirective(ParentRegion) ||
5113 isOpenMPTaskingDirective(ParentRegion) ||
5114 llvm::is_contained({OMPD_masked, OMPD_master,
5115 OMPD_critical, OMPD_ordered},
5116 EnclosingConstruct);
5117 Recommend = ShouldBeInParallelRegion;
5118 } else if (CurrentRegion == OMPD_ordered) {
5119 // OpenMP [2.16, Nesting of Regions]
5120 // An ordered region may not be closely nested inside a critical,
5121 // atomic, or explicit task region.
5122 // An ordered region must be closely nested inside a loop region (or
5123 // parallel loop region) with an ordered clause.
5124 // OpenMP [2.8.1,simd Construct, Restrictions]
5125 // An ordered construct with the simd clause is the only OpenMP construct
5126 // that can appear in the simd region.
5127 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5128 isOpenMPTaskingDirective(ParentRegion) ||
5129 !(isOpenMPSimdDirective(ParentRegion) ||
5130 Stack->isParentOrderedRegion());
5131 Recommend = ShouldBeInOrderedRegion;
5132 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5133 // OpenMP [2.16, Nesting of Regions]
5134 // If specified, a teams construct must be contained within a target
5135 // construct.
5136 NestingProhibited =
5137 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5138 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5139 EnclosingConstruct != OMPD_target);
5140 OrphanSeen = ParentRegion == OMPD_unknown;
5141 Recommend = ShouldBeInTargetRegion;
5142 } else if (CurrentRegion == OMPD_scan) {
5143 if (OMPVersion >= 50) {
5144 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
5145 // simd, or for simd. This has to take into account combined directives.
5146 // In 5.2 this seems to be implied by the fact that the specified
5147 // separated constructs are do, for, and simd.
5148 NestingProhibited = !llvm::is_contained(
5149 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
5150 } else {
5151 NestingProhibited = true;
5152 }
5153 OrphanSeen = ParentRegion == OMPD_unknown;
5154 Recommend = ShouldBeInLoopSimdRegion;
5155 }
5156 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5157 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5158 EnclosingConstruct == OMPD_teams) {
5159 // OpenMP [5.1, 2.22, Nesting of Regions]
5160 // distribute, distribute simd, distribute parallel worksharing-loop,
5161 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5162 // including any parallel regions arising from combined constructs,
5163 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5164 // only OpenMP regions that may be strictly nested inside the teams
5165 // region.
5166 //
5167 // As an extension, we permit atomic within teams as well.
5168 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5169 !isOpenMPDistributeDirective(CurrentRegion) &&
5170 CurrentRegion != OMPD_loop &&
5171 !(SemaRef.getLangOpts().OpenMPExtensions &&
5172 CurrentRegion == OMPD_atomic);
5173 Recommend = ShouldBeInParallelRegion;
5174 }
5175 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5176 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5177 // If the bind clause is present on the loop construct and binding is
5178 // teams then the corresponding loop region must be strictly nested inside
5179 // a teams region.
5180 NestingProhibited =
5181 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5182 Recommend = ShouldBeInTeamsRegion;
5183 }
5184 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5185 // OpenMP 4.5 [2.17 Nesting of Regions]
5186 // The region associated with the distribute construct must be strictly
5187 // nested inside a teams region
5188 NestingProhibited = EnclosingConstruct != OMPD_teams;
5189 Recommend = ShouldBeInTeamsRegion;
5190 }
5191 if (!NestingProhibited &&
5192 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5193 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5194 // OpenMP 4.5 [2.17 Nesting of Regions]
5195 // If a target, target update, target data, target enter data, or
5196 // target exit data construct is encountered during execution of a
5197 // target region, the behavior is unspecified.
5198 NestingProhibited = Stack->hasDirective(
5199 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5202 OffendingRegion = K;
5203 return true;
5204 }
5205 return false;
5206 },
5207 false /* don't skip top directive */);
5208 CloseNesting = false;
5209 }
5210 if (NestingProhibited) {
5211 if (OrphanSeen) {
5212 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5213 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5214 } else {
5215 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5216 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5217 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5218 }
5219 return true;
5220 }
5221 return false;
5222}
5223
5229 ArrayRef<OMPClause *> Clauses,
5230 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5231 bool ErrorFound = false;
5232 unsigned NamedModifiersNumber = 0;
5233 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5234 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5235 SmallVector<SourceLocation, 4> NameModifierLoc;
5236 unsigned OMPVersion = S.getLangOpts().OpenMP;
5237 for (const OMPClause *C : Clauses) {
5238 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5239 // At most one if clause without a directive-name-modifier can appear on
5240 // the directive.
5241 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5242 auto &FNM = FoundNameModifiers[CurNM];
5243 if (FNM) {
5244 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5245 << getOpenMPDirectiveName(Kind, OMPVersion)
5246 << getOpenMPClauseNameForDiag(OMPC_if) << (CurNM != OMPD_unknown)
5247 << getOpenMPDirectiveName(CurNM, OMPVersion);
5248 ErrorFound = true;
5249 } else if (CurNM != OMPD_unknown) {
5250 NameModifierLoc.push_back(IC->getNameModifierLoc());
5251 ++NamedModifiersNumber;
5252 }
5253 FNM = IC;
5254 if (CurNM == OMPD_unknown)
5255 continue;
5256 // Check if the specified name modifier is allowed for the current
5257 // directive.
5258 // At most one if clause with the particular directive-name-modifier can
5259 // appear on the directive.
5260 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5261 S.Diag(IC->getNameModifierLoc(),
5262 diag::err_omp_wrong_if_directive_name_modifier)
5263 << getOpenMPDirectiveName(CurNM, OMPVersion)
5264 << getOpenMPDirectiveName(Kind, OMPVersion);
5265 ErrorFound = true;
5266 }
5267 }
5268 }
5269 // If any if clause on the directive includes a directive-name-modifier then
5270 // all if clauses on the directive must include a directive-name-modifier.
5271 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5272 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5273 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5274 diag::err_omp_no_more_if_clause);
5275 } else {
5276 std::string Values;
5277 std::string Sep(", ");
5278 unsigned AllowedCnt = 0;
5279 unsigned TotalAllowedNum =
5280 AllowedNameModifiers.size() - NamedModifiersNumber;
5281 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5282 ++Cnt) {
5283 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5284 if (!FoundNameModifiers[NM]) {
5285 Values += "'";
5286 Values += getOpenMPDirectiveName(NM, OMPVersion);
5287 Values += "'";
5288 if (AllowedCnt + 2 == TotalAllowedNum)
5289 Values += " or ";
5290 else if (AllowedCnt + 1 != TotalAllowedNum)
5291 Values += Sep;
5292 ++AllowedCnt;
5293 }
5294 }
5295 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5296 diag::err_omp_unnamed_if_clause)
5297 << (TotalAllowedNum > 1) << Values;
5298 }
5299 for (SourceLocation Loc : NameModifierLoc) {
5300 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5301 }
5302 ErrorFound = true;
5303 }
5304 return ErrorFound;
5305}
5306
5307static std::pair<ValueDecl *, bool>
5309 SourceRange &ERange, bool AllowArraySection,
5310 bool AllowAssumedSizeArray, StringRef DiagType) {
5311 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5313 return std::make_pair(nullptr, true);
5314
5315 // OpenMP [3.1, C/C++]
5316 // A list item is a variable name.
5317 // OpenMP [2.9.3.3, Restrictions, p.1]
5318 // A variable that is part of another variable (as an array or
5319 // structure element) cannot appear in a private clause.
5320 //
5321 // OpenMP [6.0]
5322 // 5.2.5 Array Sections, p. 166, L28-29
5323 // When the length is absent and the size of the dimension is not known,
5324 // the array section is an assumed-size array.
5325 // 2 Glossary, p. 23, L4-6
5326 // assumed-size array
5327 // For C/C++, an array section for which the length is absent and the
5328 // size of the dimensions is not known.
5329 // 5.2.5 Array Sections, p. 168, L11
5330 // An assumed-size array can appear only in clauses for which it is
5331 // explicitly allowed.
5332 // 7.4 List Item Privatization, Restrictions, p. 222, L15
5333 // Assumed-size arrays must not be privatized.
5334 RefExpr = RefExpr->IgnoreParens();
5335 enum {
5336 NoArrayExpr = -1,
5337 ArraySubscript = 0,
5338 OMPArraySection = 1
5339 } IsArrayExpr = NoArrayExpr;
5340 if (AllowArraySection) {
5341 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5342 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5343 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5344 Base = TempASE->getBase()->IgnoreParenImpCasts();
5345 RefExpr = Base;
5346 IsArrayExpr = ArraySubscript;
5347 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5348 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5349 if (S.getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5350 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5352 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5353 !BaseType->isVariableArrayType())) {
5354 S.Diag(OASE->getColonLocFirst(),
5355 diag::err_omp_section_length_undefined)
5356 << (!BaseType.isNull() && BaseType->isArrayType());
5357 return std::make_pair(nullptr, false);
5358 }
5359 }
5360 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5361 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5362 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5363 Base = TempASE->getBase()->IgnoreParenImpCasts();
5364 RefExpr = Base;
5365 IsArrayExpr = OMPArraySection;
5366 }
5367 }
5368 ELoc = RefExpr->getExprLoc();
5369 ERange = RefExpr->getSourceRange();
5370 RefExpr = RefExpr->IgnoreParenImpCasts();
5371 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5372 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5373 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5374 (S.getCurrentThisType().isNull() || !ME ||
5375 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5376 !isa<FieldDecl>(ME->getMemberDecl()))) {
5377 if (IsArrayExpr != NoArrayExpr) {
5378 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5379 << IsArrayExpr << ERange;
5380 } else if (!DiagType.empty()) {
5381 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5382 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5383 : 0;
5384 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5385 << DiagSelect << DiagType << ERange;
5386 } else {
5387 S.Diag(ELoc,
5388 AllowArraySection
5389 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5390 : diag::err_omp_expected_var_name_member_expr)
5391 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5392 }
5393 return std::make_pair(nullptr, false);
5394 }
5395 return std::make_pair(
5396 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5397}
5398
5399namespace {
5400/// Checks if the allocator is used in uses_allocators clause to be allowed in
5401/// target regions.
5402class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5403 DSAStackTy *S = nullptr;
5404
5405public:
5406 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5407 return S->isUsesAllocatorsDecl(E->getDecl())
5408 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5409 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5410 }
5411 bool VisitStmt(const Stmt *S) {
5412 for (const Stmt *Child : S->children()) {
5413 if (Child && Visit(Child))
5414 return true;
5415 }
5416 return false;
5417 }
5418 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5419};
5420} // namespace
5421
5422static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5423 ArrayRef<OMPClause *> Clauses) {
5424 assert(!S.CurContext->isDependentContext() &&
5425 "Expected non-dependent context.");
5426 auto AllocateRange =
5427 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5428 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5429 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5430 return isOpenMPPrivate(C->getClauseKind());
5431 });
5432 for (OMPClause *Cl : PrivateRange) {
5434 if (Cl->getClauseKind() == OMPC_private) {
5435 auto *PC = cast<OMPPrivateClause>(Cl);
5436 I = PC->private_copies().begin();
5437 It = PC->varlist_begin();
5438 Et = PC->varlist_end();
5439 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5440 auto *PC = cast<OMPFirstprivateClause>(Cl);
5441 I = PC->private_copies().begin();
5442 It = PC->varlist_begin();
5443 Et = PC->varlist_end();
5444 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5445 auto *PC = cast<OMPLastprivateClause>(Cl);
5446 I = PC->private_copies().begin();
5447 It = PC->varlist_begin();
5448 Et = PC->varlist_end();
5449 } else if (Cl->getClauseKind() == OMPC_linear) {
5450 auto *PC = cast<OMPLinearClause>(Cl);
5451 I = PC->privates().begin();
5452 It = PC->varlist_begin();
5453 Et = PC->varlist_end();
5454 } else if (Cl->getClauseKind() == OMPC_reduction) {
5455 auto *PC = cast<OMPReductionClause>(Cl);
5456 I = PC->privates().begin();
5457 It = PC->varlist_begin();
5458 Et = PC->varlist_end();
5459 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5460 auto *PC = cast<OMPTaskReductionClause>(Cl);
5461 I = PC->privates().begin();
5462 It = PC->varlist_begin();
5463 Et = PC->varlist_end();
5464 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5465 auto *PC = cast<OMPInReductionClause>(Cl);
5466 I = PC->privates().begin();
5467 It = PC->varlist_begin();
5468 Et = PC->varlist_end();
5469 } else {
5470 llvm_unreachable("Expected private clause.");
5471 }
5472 for (Expr *E : llvm::make_range(It, Et)) {
5473 if (!*I) {
5474 ++I;
5475 continue;
5476 }
5477 SourceLocation ELoc;
5478 SourceRange ERange;
5479 Expr *SimpleRefExpr = E;
5480 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5481 /*AllowArraySection=*/true);
5482 DeclToCopy.try_emplace(Res.first,
5483 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5484 ++I;
5485 }
5486 }
5487 for (OMPClause *C : AllocateRange) {
5488 auto *AC = cast<OMPAllocateClause>(C);
5489 if (S.getLangOpts().OpenMP >= 50 &&
5490 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5491 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5492 AC->getAllocator()) {
5493 Expr *Allocator = AC->getAllocator();
5494 // OpenMP, 2.12.5 target Construct
5495 // Memory allocators that do not appear in a uses_allocators clause cannot
5496 // appear as an allocator in an allocate clause or be used in the target
5497 // region unless a requires directive with the dynamic_allocators clause
5498 // is present in the same compilation unit.
5499 AllocatorChecker Checker(Stack);
5500 if (Checker.Visit(Allocator))
5501 S.Diag(Allocator->getExprLoc(),
5502 diag::err_omp_allocator_not_in_uses_allocators)
5503 << Allocator->getSourceRange();
5504 }
5505 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5506 getAllocatorKind(S, Stack, AC->getAllocator());
5507 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5508 // For task, taskloop or target directives, allocation requests to memory
5509 // allocators with the trait access set to thread result in unspecified
5510 // behavior.
5511 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5512 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5513 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5514 unsigned OMPVersion = S.getLangOpts().OpenMP;
5515 S.Diag(AC->getAllocator()->getExprLoc(),
5516 diag::warn_omp_allocate_thread_on_task_target_directive)
5517 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5518 }
5519 for (Expr *E : AC->varlist()) {
5520 SourceLocation ELoc;
5521 SourceRange ERange;
5522 Expr *SimpleRefExpr = E;
5523 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5524 ValueDecl *VD = Res.first;
5525 if (!VD)
5526 continue;
5527 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5528 if (!isOpenMPPrivate(Data.CKind)) {
5529 S.Diag(E->getExprLoc(),
5530 diag::err_omp_expected_private_copy_for_allocate);
5531 continue;
5532 }
5533 VarDecl *PrivateVD = DeclToCopy[VD];
5534 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5535 AllocatorKind, AC->getAllocator()))
5536 continue;
5537 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5538 AC->getAlignment(), E->getSourceRange());
5539 }
5540 }
5541}
5542
5543namespace {
5544/// Rewrite statements and expressions for Sema \p Actions CurContext.
5545///
5546/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5547/// context. DeclRefExpr used inside the new context are changed to refer to the
5548/// captured variable instead.
5549class CaptureVars : public TreeTransform<CaptureVars> {
5550 using BaseTransform = TreeTransform<CaptureVars>;
5551
5552public:
5553 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5554
5555 bool AlwaysRebuild() { return true; }
5556};
5557} // namespace
5558
5559static VarDecl *precomputeExpr(Sema &Actions,
5560 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5561 StringRef Name) {
5562 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5563 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5564 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5565 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5566 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5567 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5568 BodyStmts.push_back(NewDeclStmt);
5569 return NewVar;
5570}
5571
5572/// Create a closure that computes the number of iterations of a loop.
5573///
5574/// \param Actions The Sema object.
5575/// \param LogicalTy Type for the logical iteration number.
5576/// \param Rel Comparison operator of the loop condition.
5577/// \param StartExpr Value of the loop counter at the first iteration.
5578/// \param StopExpr Expression the loop counter is compared against in the loop
5579/// condition. \param StepExpr Amount of increment after each iteration.
5580///
5581/// \return Closure (CapturedStmt) of the distance calculation.
5582static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5584 Expr *StartExpr, Expr *StopExpr,
5585 Expr *StepExpr) {
5586 ASTContext &Ctx = Actions.getASTContext();
5587 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5588
5589 // Captured regions currently don't support return values, we use an
5590 // out-parameter instead. All inputs are implicit captures.
5591 // TODO: Instead of capturing each DeclRefExpr occurring in
5592 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5593 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5594 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5595 {StringRef(), QualType()}};
5596 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5597
5598 Stmt *Body;
5599 {
5600 Sema::CompoundScopeRAII CompoundScope(Actions);
5602
5603 // Get the LValue expression for the result.
5604 ImplicitParamDecl *DistParam = CS->getParam(0);
5605 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5606 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5607
5608 SmallVector<Stmt *, 4> BodyStmts;
5609
5610 // Capture all referenced variable references.
5611 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5612 // CapturedStmt, we could compute them before and capture the result, to be
5613 // used jointly with the LoopVar function.
5614 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5615 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5616 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5617 auto BuildVarRef = [&](VarDecl *VD) {
5618 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5619 };
5620
5622 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5624 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5625 Expr *Dist;
5626 if (Rel == BO_NE) {
5627 // When using a != comparison, the increment can be +1 or -1. This can be
5628 // dynamic at runtime, so we need to check for the direction.
5629 Expr *IsNegStep = AssertSuccess(
5630 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5631
5632 // Positive increment.
5633 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5634 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5635 ForwardRange = AssertSuccess(
5636 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5637 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5638 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5639
5640 // Negative increment.
5641 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5642 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5643 BackwardRange = AssertSuccess(
5644 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5645 Expr *NegIncAmount = AssertSuccess(
5646 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5647 Expr *BackwardDist = AssertSuccess(
5648 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5649
5650 // Use the appropriate case.
5651 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5652 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5653 } else {
5654 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5655 "Expected one of these relational operators");
5656
5657 // We can derive the direction from any other comparison operator. It is
5658 // non well-formed OpenMP if Step increments/decrements in the other
5659 // directions. Whether at least the first iteration passes the loop
5660 // condition.
5661 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5662 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5663
5664 // Compute the range between first and last counter value.
5665 Expr *Range;
5666 if (Rel == BO_GE || Rel == BO_GT)
5667 Range = AssertSuccess(Actions.BuildBinOp(
5668 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5669 else
5670 Range = AssertSuccess(Actions.BuildBinOp(
5671 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5672
5673 // Ensure unsigned range space.
5674 Range =
5675 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5676
5677 if (Rel == BO_LE || Rel == BO_GE) {
5678 // Add one to the range if the relational operator is inclusive.
5679 Range =
5680 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5681 }
5682
5683 // Divide by the absolute step amount. If the range is not a multiple of
5684 // the step size, rounding-up the effective upper bound ensures that the
5685 // last iteration is included.
5686 // Note that the rounding-up may cause an overflow in a temporary that
5687 // could be avoided, but would have occurred in a C-style for-loop as
5688 // well.
5689 Expr *Divisor = BuildVarRef(NewStep);
5690 if (Rel == BO_GE || Rel == BO_GT)
5691 Divisor =
5692 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5693 Expr *DivisorMinusOne =
5694 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5695 Expr *RangeRoundUp = AssertSuccess(
5696 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5697 Dist = AssertSuccess(
5698 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5699
5700 // If there is not at least one iteration, the range contains garbage. Fix
5701 // to zero in this case.
5702 Dist = AssertSuccess(
5703 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5704 }
5705
5706 // Assign the result to the out-parameter.
5707 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5708 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5709 BodyStmts.push_back(ResultAssign);
5710
5711 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5712 }
5713
5714 return cast<CapturedStmt>(
5715 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5716}
5717
5718/// Create a closure that computes the loop variable from the logical iteration
5719/// number.
5720///
5721/// \param Actions The Sema object.
5722/// \param LoopVarTy Type for the loop variable used for result value.
5723/// \param LogicalTy Type for the logical iteration number.
5724/// \param StartExpr Value of the loop counter at the first iteration.
5725/// \param Step Amount of increment after each iteration.
5726/// \param Deref Whether the loop variable is a dereference of the loop
5727/// counter variable.
5728///
5729/// \return Closure (CapturedStmt) of the loop value calculation.
5730static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5731 QualType LogicalTy,
5732 DeclRefExpr *StartExpr, Expr *Step,
5733 bool Deref) {
5734 ASTContext &Ctx = Actions.getASTContext();
5735
5736 // Pass the result as an out-parameter. Passing as return value would require
5737 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5738 // invoke a copy constructor.
5739 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5740 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5741 {"Logical", LogicalTy},
5742 {StringRef(), QualType()}};
5743 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5744
5745 // Capture the initial iterator which represents the LoopVar value at the
5746 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5747 // it in every iteration, capture it by value before it is modified.
5748 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5749 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5751 (void)Invalid;
5752 assert(!Invalid && "Expecting capture-by-value to work.");
5753
5754 Expr *Body;
5755 {
5756 Sema::CompoundScopeRAII CompoundScope(Actions);
5757 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5758
5759 ImplicitParamDecl *TargetParam = CS->getParam(0);
5760 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5761 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5762 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5763 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5764 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5765
5766 // Capture the Start expression.
5767 CaptureVars Recap(Actions);
5768 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5769 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5770
5772 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5773 // TODO: Explicitly cast to the iterator's difference_type instead of
5774 // relying on implicit conversion.
5775 Expr *Advanced =
5776 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5777
5778 if (Deref) {
5779 // For range-based for-loops convert the loop counter value to a concrete
5780 // loop variable value by dereferencing the iterator.
5781 Advanced =
5782 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5783 }
5784
5785 // Assign the result to the output parameter.
5786 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5787 BO_Assign, TargetRef, Advanced));
5788 }
5789 return cast<CapturedStmt>(
5790 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5791}
5792
5794 ASTContext &Ctx = getASTContext();
5795
5796 // Extract the common elements of ForStmt and CXXForRangeStmt:
5797 // Loop variable, repeat condition, increment
5798 Expr *Cond, *Inc;
5799 VarDecl *LIVDecl, *LUVDecl;
5800 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5801 Stmt *Init = For->getInit();
5802 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5803 // For statement declares loop variable.
5804 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5805 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5806 // For statement reuses variable.
5807 assert(LCAssign->getOpcode() == BO_Assign &&
5808 "init part must be a loop variable assignment");
5809 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5810 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5811 } else
5812 llvm_unreachable("Cannot determine loop variable");
5813 LUVDecl = LIVDecl;
5814
5815 Cond = For->getCond();
5816 Inc = For->getInc();
5817 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5818 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5819 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5820 LUVDecl = RangeFor->getLoopVariable();
5821
5822 Cond = RangeFor->getCond();
5823 Inc = RangeFor->getInc();
5824 } else
5825 llvm_unreachable("unhandled kind of loop");
5826
5827 QualType CounterTy = LIVDecl->getType();
5828 QualType LVTy = LUVDecl->getType();
5829
5830 // Analyze the loop condition.
5831 Expr *LHS, *RHS;
5832 BinaryOperator::Opcode CondRel;
5833 Cond = Cond->IgnoreImplicit();
5834 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5835 LHS = CondBinExpr->getLHS();
5836 RHS = CondBinExpr->getRHS();
5837 CondRel = CondBinExpr->getOpcode();
5838 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5839 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5840 LHS = CondCXXOp->getArg(0);
5841 RHS = CondCXXOp->getArg(1);
5842 switch (CondCXXOp->getOperator()) {
5843 case OO_ExclaimEqual:
5844 CondRel = BO_NE;
5845 break;
5846 case OO_Less:
5847 CondRel = BO_LT;
5848 break;
5849 case OO_LessEqual:
5850 CondRel = BO_LE;
5851 break;
5852 case OO_Greater:
5853 CondRel = BO_GT;
5854 break;
5855 case OO_GreaterEqual:
5856 CondRel = BO_GE;
5857 break;
5858 default:
5859 llvm_unreachable("unexpected iterator operator");
5860 }
5861 } else
5862 llvm_unreachable("unexpected loop condition");
5863
5864 // Normalize such that the loop counter is on the LHS.
5865 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5866 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5867 std::swap(LHS, RHS);
5868 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5869 }
5870 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5871
5872 // Decide the bit width for the logical iteration counter. By default use the
5873 // unsigned ptrdiff_t integer size (for iterators and pointers).
5874 // TODO: For iterators, use iterator::difference_type,
5875 // std::iterator_traits<>::difference_type or decltype(it - end).
5876 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5877 if (CounterTy->isIntegerType()) {
5878 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5879 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5880 }
5881
5882 // Analyze the loop increment.
5883 Expr *Step;
5884 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5885 int Direction;
5886 switch (IncUn->getOpcode()) {
5887 case UO_PreInc:
5888 case UO_PostInc:
5889 Direction = 1;
5890 break;
5891 case UO_PreDec:
5892 case UO_PostDec:
5893 Direction = -1;
5894 break;
5895 default:
5896 llvm_unreachable("unhandled unary increment operator");
5897 }
5899 Ctx,
5900 llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction, /*isSigned=*/true),
5901 LogicalTy, {});
5902 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5903 if (IncBin->getOpcode() == BO_AddAssign) {
5904 Step = IncBin->getRHS();
5905 } else if (IncBin->getOpcode() == BO_SubAssign) {
5906 Step = AssertSuccess(
5907 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5908 } else
5909 llvm_unreachable("unhandled binary increment operator");
5910 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5911 switch (CondCXXOp->getOperator()) {
5912 case OO_PlusPlus:
5914 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5915 break;
5916 case OO_MinusMinus:
5918 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5919 break;
5920 case OO_PlusEqual:
5921 Step = CondCXXOp->getArg(1);
5922 break;
5923 case OO_MinusEqual:
5924 Step = AssertSuccess(
5925 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5926 break;
5927 default:
5928 llvm_unreachable("unhandled overloaded increment operator");
5929 }
5930 } else
5931 llvm_unreachable("unknown increment expression");
5932
5933 CapturedStmt *DistanceFunc =
5934 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
5935 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5936 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5937 DeclRefExpr *LVRef =
5938 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5939 nullptr, nullptr, {}, nullptr);
5940 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5941 LoopVarFunc, LVRef);
5942}
5943
5945 // Handle a literal loop.
5946 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5947 return ActOnOpenMPCanonicalLoop(AStmt);
5948
5949 // If not a literal loop, it must be the result of a loop transformation.
5951 assert(
5952 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5953 "Loop transformation directive expected");
5954 return LoopTransform;
5955}
5956
5958 CXXScopeSpec &MapperIdScopeSpec,
5959 const DeclarationNameInfo &MapperId,
5960 QualType Type,
5961 Expr *UnresolvedMapper);
5962
5963/// Perform DFS through the structure/class data members trying to find
5964/// member(s) with user-defined 'default' mapper and generate implicit map
5965/// clauses for such members with the found 'default' mapper.
5966static void
5969 // Check for the default mapper for data members.
5970 if (S.getLangOpts().OpenMP < 50)
5971 return;
5972 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5973 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5974 if (!C)
5975 continue;
5976 SmallVector<Expr *, 4> SubExprs;
5977 auto *MI = C->mapperlist_begin();
5978 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5979 ++I, ++MI) {
5980 // Expression is mapped using mapper - skip it.
5981 if (*MI)
5982 continue;
5983 Expr *E = *I;
5984 // Expression is dependent - skip it, build the mapper when it gets
5985 // instantiated.
5986 if (E->isTypeDependent() || E->isValueDependent() ||
5988 continue;
5989 // Array section - need to check for the mapping of the array section
5990 // element.
5991 QualType CanonType = E->getType().getCanonicalType();
5992 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
5993 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
5994 QualType BaseType =
5996 QualType ElemType;
5997 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
5998 ElemType = ATy->getElementType();
5999 else
6000 ElemType = BaseType->getPointeeType();
6001 CanonType = ElemType;
6002 }
6003
6004 // DFS over data members in structures/classes.
6006 1, {CanonType, nullptr});
6007 llvm::DenseMap<const Type *, Expr *> Visited;
6009 1, {nullptr, 1});
6010 while (!Types.empty()) {
6011 QualType BaseType;
6012 FieldDecl *CurFD;
6013 std::tie(BaseType, CurFD) = Types.pop_back_val();
6014 while (ParentChain.back().second == 0)
6015 ParentChain.pop_back();
6016 --ParentChain.back().second;
6017 if (BaseType.isNull())
6018 continue;
6019 // Only structs/classes are allowed to have mappers.
6020 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6021 if (!RD)
6022 continue;
6023 auto It = Visited.find(BaseType.getTypePtr());
6024 if (It == Visited.end()) {
6025 // Try to find the associated user-defined mapper.
6026 CXXScopeSpec MapperIdScopeSpec;
6027 DeclarationNameInfo DefaultMapperId;
6029 &S.Context.Idents.get("default")));
6030 DefaultMapperId.setLoc(E->getExprLoc());
6032 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6033 BaseType, /*UnresolvedMapper=*/nullptr);
6034 if (ER.isInvalid())
6035 continue;
6036 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6037 }
6038 // Found default mapper.
6039 if (It->second) {
6040 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6042 OE->setIsUnique(/*V=*/true);
6043 Expr *BaseExpr = OE;
6044 for (const auto &P : ParentChain) {
6045 if (P.first) {
6046 BaseExpr = S.BuildMemberExpr(
6047 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6049 DeclAccessPair::make(P.first, P.first->getAccess()),
6050 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6051 P.first->getType(), VK_LValue, OK_Ordinary);
6052 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6053 }
6054 }
6055 if (CurFD)
6056 BaseExpr = S.BuildMemberExpr(
6057 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6059 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6060 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6061 CurFD->getType(), VK_LValue, OK_Ordinary);
6062 SubExprs.push_back(BaseExpr);
6063 continue;
6064 }
6065 // Check for the "default" mapper for data members.
6066 bool FirstIter = true;
6067 for (FieldDecl *FD : RD->fields()) {
6068 if (!FD)
6069 continue;
6070 QualType FieldTy = FD->getType();
6071 if (FieldTy.isNull() ||
6072 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6073 continue;
6074 if (FirstIter) {
6075 FirstIter = false;
6076 ParentChain.emplace_back(CurFD, 1);
6077 } else {
6078 ++ParentChain.back().second;
6079 }
6080 Types.emplace_back(FieldTy, FD);
6081 }
6082 }
6083 }
6084 if (SubExprs.empty())
6085 continue;
6086 CXXScopeSpec MapperIdScopeSpec;
6087 DeclarationNameInfo MapperId;
6088 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
6089 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6090 MapperIdScopeSpec, MapperId, C->getMapType(),
6091 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6092 SubExprs, OMPVarListLocTy()))
6093 Clauses.push_back(NewClause);
6094 }
6095}
6096
6097namespace {
6098/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
6099/// call in the associated loop-nest cannot be a 'parallel for'.
6100class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
6101 Sema &SemaRef;
6102
6103public:
6104 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
6105
6106 // Is there a nested OpenMP loop bind(parallel)
6107 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
6108 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6109 if (const auto *C = D->getSingleClause<OMPBindClause>())
6110 if (C->getBindKind() == OMPC_BIND_parallel) {
6111 TeamsLoopCanBeParallelFor = false;
6112 // No need to continue visiting any more
6113 return;
6114 }
6115 }
6116 for (const Stmt *Child : D->children())
6117 if (Child)
6118 Visit(Child);
6119 }
6120
6121 void VisitCallExpr(const CallExpr *C) {
6122 // Function calls inhibit parallel loop translation of 'target teams loop'
6123 // unless the assume-no-nested-parallelism flag has been specified.
6124 // OpenMP API runtime library calls do not inhibit parallel loop
6125 // translation, regardless of the assume-no-nested-parallelism.
6126 bool IsOpenMPAPI = false;
6127 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
6128 if (FD) {
6129 std::string Name = FD->getNameInfo().getAsString();
6130 IsOpenMPAPI = Name.find("omp_") == 0;
6131 }
6132 TeamsLoopCanBeParallelFor =
6133 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6134 if (!TeamsLoopCanBeParallelFor)
6135 return;
6136
6137 for (const Stmt *Child : C->children())
6138 if (Child)
6139 Visit(Child);
6140 }
6141
6142 void VisitCapturedStmt(const CapturedStmt *S) {
6143 if (!S)
6144 return;
6145 Visit(S->getCapturedDecl()->getBody());
6146 }
6147
6148 void VisitStmt(const Stmt *S) {
6149 if (!S)
6150 return;
6151 for (const Stmt *Child : S->children())
6152 if (Child)
6153 Visit(Child);
6154 }
6155 explicit TeamsLoopChecker(Sema &SemaRef)
6156 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
6157
6158private:
6159 bool TeamsLoopCanBeParallelFor;
6160};
6161} // namespace
6162
6163static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
6164 TeamsLoopChecker Checker(SemaRef);
6165 Checker.Visit(AStmt);
6166 return Checker.teamsLoopCanBeParallelFor();
6167}
6168
6170 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6171 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6172 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6173 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
6174
6175 StmtResult Res = StmtError();
6177 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6178
6179 if (const OMPBindClause *BC =
6180 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6181 BindKind = BC->getBindKind();
6182
6183 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6184 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6185
6186 // Setting the enclosing teams or parallel construct for the loop
6187 // directive without bind clause.
6188 // [5.0:129:25-28] If the bind clause is not present on the construct and
6189 // the loop construct is closely nested inside a teams or parallel
6190 // construct, the binding region is the corresponding teams or parallel
6191 // region. If none of those conditions hold, the binding region is not
6192 // defined.
6193 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6194 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6195 getLeafConstructsOrSelf(ParentDirective);
6196
6197 if (ParentDirective == OMPD_unknown) {
6198 Diag(DSAStack->getDefaultDSALocation(),
6199 diag::err_omp_bind_required_on_loop);
6200 } else if (ParentLeafs.back() == OMPD_parallel) {
6201 BindKind = OMPC_BIND_parallel;
6202 } else if (ParentLeafs.back() == OMPD_teams) {
6203 BindKind = OMPC_BIND_teams;
6204 }
6205
6206 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6207
6208 OMPClause *C =
6211 ClausesWithImplicit.push_back(C);
6212 }
6213
6214 // Diagnose "loop bind(teams)" with "reduction".
6215 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6216 for (OMPClause *C : Clauses) {
6217 if (C->getClauseKind() == OMPC_reduction)
6218 Diag(DSAStack->getDefaultDSALocation(),
6219 diag::err_omp_loop_reduction_clause);
6220 }
6221 }
6222
6223 // First check CancelRegion which is then used in checkNestingOfRegions.
6224 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6225 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6226 BindKind, StartLoc)) {
6227 return StmtError();
6228 }
6229
6230 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6233 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6234
6235 VarsWithInheritedDSAType VarsWithInheritedDSA;
6236 bool ErrorFound = false;
6237 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6238
6239 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6241 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6242
6243 // Check default data sharing attributes for referenced variables.
6244 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6245 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6246 Stmt *S = AStmt;
6247 while (--ThisCaptureLevel >= 0)
6248 S = cast<CapturedStmt>(S)->getCapturedStmt();
6249 DSAChecker.Visit(S);
6251 !isOpenMPTaskingDirective(Kind)) {
6252 // Visit subcaptures to generate implicit clauses for captured vars.
6253 auto *CS = cast<CapturedStmt>(AStmt);
6255 getOpenMPCaptureRegions(CaptureRegions, Kind);
6256 // Ignore outer tasking regions for target directives.
6257 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6259 DSAChecker.visitSubCaptures(CS);
6260 }
6261 if (DSAChecker.isErrorFound())
6262 return StmtError();
6263 // Generate list of implicitly defined firstprivate variables.
6264 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6265 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6266
6268 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6269 // Get the original location of present modifier from Defaultmap clause.
6270 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6271 for (OMPClause *C : Clauses) {
6272 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6273 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6274 PresentModifierLocs[DMC->getDefaultmapKind()] =
6275 DMC->getDefaultmapModifierLoc();
6276 }
6277
6279 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6281 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6282 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6283 }
6284 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6285 for (OMPClause *C : Clauses) {
6286 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6287 for (Expr *E : IRC->taskgroup_descriptors())
6288 if (E)
6289 ImpInfo.Firstprivates.insert(E);
6290 }
6291 // OpenMP 5.0, 2.10.1 task Construct
6292 // [detach clause]... The event-handle will be considered as if it was
6293 // specified on a firstprivate clause.
6294 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6295 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6296 }
6297 if (!ImpInfo.Firstprivates.empty()) {
6299 ImpInfo.Firstprivates.getArrayRef(), SourceLocation(),
6301 ClausesWithImplicit.push_back(Implicit);
6302 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6303 ImpInfo.Firstprivates.size();
6304 } else {
6305 ErrorFound = true;
6306 }
6307 }
6308 if (!ImpInfo.Privates.empty()) {
6310 ImpInfo.Privates.getArrayRef(), SourceLocation(),
6312 ClausesWithImplicit.push_back(Implicit);
6313 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6314 ImpInfo.Privates.size();
6315 } else {
6316 ErrorFound = true;
6317 }
6318 }
6319 // OpenMP 5.0 [2.19.7]
6320 // If a list item appears in a reduction, lastprivate or linear
6321 // clause on a combined target construct then it is treated as
6322 // if it also appears in a map clause with a map-type of tofrom
6323 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6325 SmallVector<Expr *, 4> ImplicitExprs;
6326 for (OMPClause *C : Clauses) {
6327 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6328 for (Expr *E : RC->varlist())
6330 ImplicitExprs.emplace_back(E);
6331 }
6332 if (!ImplicitExprs.empty()) {
6333 ArrayRef<Expr *> Exprs = ImplicitExprs;
6334 CXXScopeSpec MapperIdScopeSpec;
6335 DeclarationNameInfo MapperId;
6338 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6339 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6340 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6341 ClausesWithImplicit.emplace_back(Implicit);
6342 }
6343 }
6344 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6345 int ClauseKindCnt = -1;
6346 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6347 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6348 ++ClauseKindCnt;
6349 if (ImplicitMap.empty())
6350 continue;
6351 CXXScopeSpec MapperIdScopeSpec;
6352 DeclarationNameInfo MapperId;
6353 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6355 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6356 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6357 SourceLocation(), SourceLocation(), ImplicitMap,
6358 OMPVarListLocTy())) {
6359 ClausesWithImplicit.emplace_back(Implicit);
6360 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6361 ImplicitMap.size();
6362 } else {
6363 ErrorFound = true;
6364 }
6365 }
6366 }
6367 // Build expressions for implicit maps of data members with 'default'
6368 // mappers.
6369 if (getLangOpts().OpenMP >= 50)
6371 ClausesWithImplicit);
6372 }
6373
6374 switch (Kind) {
6375 case OMPD_parallel:
6376 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6377 EndLoc);
6378 break;
6379 case OMPD_simd:
6380 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6381 VarsWithInheritedDSA);
6382 break;
6383 case OMPD_tile:
6384 Res =
6385 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6386 break;
6387 case OMPD_stripe:
6388 Res = ActOnOpenMPStripeDirective(ClausesWithImplicit, AStmt, StartLoc,
6389 EndLoc);
6390 break;
6391 case OMPD_unroll:
6392 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6393 EndLoc);
6394 break;
6395 case OMPD_reverse:
6396 assert(ClausesWithImplicit.empty() &&
6397 "reverse directive does not support any clauses");
6398 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6399 break;
6400 case OMPD_interchange:
6401 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6402 EndLoc);
6403 break;
6404 case OMPD_fuse:
6405 Res =
6406 ActOnOpenMPFuseDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6407 break;
6408 case OMPD_for:
6409 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6410 VarsWithInheritedDSA);
6411 break;
6412 case OMPD_for_simd:
6413 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6414 EndLoc, VarsWithInheritedDSA);
6415 break;
6416 case OMPD_sections:
6417 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6418 EndLoc);
6419 break;
6420 case OMPD_section:
6421 assert(ClausesWithImplicit.empty() &&
6422 "No clauses are allowed for 'omp section' directive");
6423 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6424 break;
6425 case OMPD_single:
6426 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6427 EndLoc);
6428 break;
6429 case OMPD_master:
6430 assert(ClausesWithImplicit.empty() &&
6431 "No clauses are allowed for 'omp master' directive");
6432 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6433 break;
6434 case OMPD_masked:
6435 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6436 EndLoc);
6437 break;
6438 case OMPD_critical:
6439 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6440 StartLoc, EndLoc);
6441 break;
6442 case OMPD_parallel_for:
6443 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6444 EndLoc, VarsWithInheritedDSA);
6445 break;
6446 case OMPD_parallel_for_simd:
6448 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6449 break;
6450 case OMPD_scope:
6451 Res =
6452 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6453 break;
6454 case OMPD_parallel_master:
6455 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6456 StartLoc, EndLoc);
6457 break;
6458 case OMPD_parallel_masked:
6459 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6460 StartLoc, EndLoc);
6461 break;
6462 case OMPD_parallel_sections:
6463 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6464 StartLoc, EndLoc);
6465 break;
6466 case OMPD_task:
6467 Res =
6468 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6469 break;
6470 case OMPD_taskyield:
6471 assert(ClausesWithImplicit.empty() &&
6472 "No clauses are allowed for 'omp taskyield' directive");
6473 assert(AStmt == nullptr &&
6474 "No associated statement allowed for 'omp taskyield' directive");
6475 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6476 break;
6477 case OMPD_error:
6478 assert(AStmt == nullptr &&
6479 "No associated statement allowed for 'omp error' directive");
6480 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6481 break;
6482 case OMPD_barrier:
6483 assert(ClausesWithImplicit.empty() &&
6484 "No clauses are allowed for 'omp barrier' directive");
6485 assert(AStmt == nullptr &&
6486 "No associated statement allowed for 'omp barrier' directive");
6487 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6488 break;
6489 case OMPD_taskwait:
6490 assert(AStmt == nullptr &&
6491 "No associated statement allowed for 'omp taskwait' directive");
6492 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6493 break;
6494 case OMPD_taskgroup:
6495 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6496 EndLoc);
6497 break;
6498 case OMPD_flush:
6499 assert(AStmt == nullptr &&
6500 "No associated statement allowed for 'omp flush' directive");
6501 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6502 break;
6503 case OMPD_depobj:
6504 assert(AStmt == nullptr &&
6505 "No associated statement allowed for 'omp depobj' directive");
6506 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6507 break;
6508 case OMPD_scan:
6509 assert(AStmt == nullptr &&
6510 "No associated statement allowed for 'omp scan' directive");
6511 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6512 break;
6513 case OMPD_ordered:
6514 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6515 EndLoc);
6516 break;
6517 case OMPD_atomic:
6518 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6519 EndLoc);
6520 break;
6521 case OMPD_teams:
6522 Res =
6523 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6524 break;
6525 case OMPD_target:
6526 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6527 EndLoc);
6528 break;
6529 case OMPD_target_parallel:
6530 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6531 StartLoc, EndLoc);
6532 break;
6533 case OMPD_target_parallel_for:
6535 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6536 break;
6537 case OMPD_cancellation_point:
6538 assert(ClausesWithImplicit.empty() &&
6539 "No clauses are allowed for 'omp cancellation point' directive");
6540 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6541 "cancellation point' directive");
6542 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6543 break;
6544 case OMPD_cancel:
6545 assert(AStmt == nullptr &&
6546 "No associated statement allowed for 'omp cancel' directive");
6547 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6548 CancelRegion);
6549 break;
6550 case OMPD_target_data:
6551 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6552 EndLoc);
6553 break;
6554 case OMPD_target_enter_data:
6555 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6556 EndLoc, AStmt);
6557 break;
6558 case OMPD_target_exit_data:
6559 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6560 EndLoc, AStmt);
6561 break;
6562 case OMPD_taskloop:
6563 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6564 EndLoc, VarsWithInheritedDSA);
6565 break;
6566 case OMPD_taskloop_simd:
6567 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6568 EndLoc, VarsWithInheritedDSA);
6569 break;
6570 case OMPD_master_taskloop:
6572 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6573 break;
6574 case OMPD_masked_taskloop:
6576 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6577 break;
6578 case OMPD_master_taskloop_simd:
6580 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6581 break;
6582 case OMPD_masked_taskloop_simd:
6584 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6585 break;
6586 case OMPD_parallel_master_taskloop:
6588 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6589 break;
6590 case OMPD_parallel_masked_taskloop:
6592 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6593 break;
6594 case OMPD_parallel_master_taskloop_simd:
6596 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6597 break;
6598 case OMPD_parallel_masked_taskloop_simd:
6600 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6601 break;
6602 case OMPD_distribute:
6603 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6604 EndLoc, VarsWithInheritedDSA);
6605 break;
6606 case OMPD_target_update:
6607 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6608 EndLoc, AStmt);
6609 break;
6610 case OMPD_distribute_parallel_for:
6612 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6613 break;
6614 case OMPD_distribute_parallel_for_simd:
6616 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6617 break;
6618 case OMPD_distribute_simd:
6620 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6621 break;
6622 case OMPD_target_parallel_for_simd:
6624 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6625 break;
6626 case OMPD_target_simd:
6627 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6628 EndLoc, VarsWithInheritedDSA);
6629 break;
6630 case OMPD_teams_distribute:
6632 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6633 break;
6634 case OMPD_teams_distribute_simd:
6636 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6637 break;
6638 case OMPD_teams_distribute_parallel_for_simd:
6640 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6641 break;
6642 case OMPD_teams_distribute_parallel_for:
6644 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6645 break;
6646 case OMPD_target_teams:
6647 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6648 EndLoc);
6649 break;
6650 case OMPD_target_teams_distribute:
6652 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6653 break;
6654 case OMPD_target_teams_distribute_parallel_for:
6656 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6657 break;
6658 case OMPD_target_teams_distribute_parallel_for_simd:
6660 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6661 break;
6662 case OMPD_target_teams_distribute_simd:
6664 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6665 break;
6666 case OMPD_interop:
6667 assert(AStmt == nullptr &&
6668 "No associated statement allowed for 'omp interop' directive");
6669 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6670 break;
6671 case OMPD_dispatch:
6672 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6673 EndLoc);
6674 break;
6675 case OMPD_loop:
6676 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6677 EndLoc, VarsWithInheritedDSA);
6678 break;
6679 case OMPD_teams_loop:
6681 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6682 break;
6683 case OMPD_target_teams_loop:
6685 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6686 break;
6687 case OMPD_parallel_loop:
6689 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6690 break;
6691 case OMPD_target_parallel_loop:
6693 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6694 break;
6695 case OMPD_declare_target:
6696 case OMPD_end_declare_target:
6697 case OMPD_threadprivate:
6698 case OMPD_allocate:
6699 case OMPD_declare_reduction:
6700 case OMPD_declare_mapper:
6701 case OMPD_declare_simd:
6702 case OMPD_requires:
6703 case OMPD_declare_variant:
6704 case OMPD_begin_declare_variant:
6705 case OMPD_end_declare_variant:
6706 llvm_unreachable("OpenMP Directive is not allowed");
6707 case OMPD_unknown:
6708 default:
6709 llvm_unreachable("Unknown OpenMP directive");
6710 }
6711
6712 ErrorFound = Res.isInvalid() || ErrorFound;
6713
6714 // Check variables in the clauses if default(none) or
6715 // default(firstprivate) was specified.
6716 if (DSAStack->getDefaultDSA() == DSA_none ||
6717 DSAStack->getDefaultDSA() == DSA_private ||
6718 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6719 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6720 for (OMPClause *C : Clauses) {
6721 switch (C->getClauseKind()) {
6722 case OMPC_num_threads:
6723 case OMPC_dist_schedule:
6724 // Do not analyze if no parent teams directive.
6725 if (isOpenMPTeamsDirective(Kind))
6726 break;
6727 continue;
6728 case OMPC_if:
6729 if (isOpenMPTeamsDirective(Kind) &&
6730 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6731 break;
6732 if (isOpenMPParallelDirective(Kind) &&
6734 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6735 break;
6736 continue;
6737 case OMPC_schedule:
6738 case OMPC_detach:
6739 break;
6740 case OMPC_grainsize:
6741 case OMPC_num_tasks:
6742 case OMPC_final:
6743 case OMPC_priority:
6744 case OMPC_novariants:
6745 case OMPC_nocontext:
6746 // Do not analyze if no parent parallel directive.
6747 if (isOpenMPParallelDirective(Kind))
6748 break;
6749 continue;
6750 case OMPC_ordered:
6751 case OMPC_device:
6752 case OMPC_num_teams:
6753 case OMPC_thread_limit:
6754 case OMPC_hint:
6755 case OMPC_collapse:
6756 case OMPC_safelen:
6757 case OMPC_simdlen:
6758 case OMPC_sizes:
6759 case OMPC_default:
6760 case OMPC_proc_bind:
6761 case OMPC_private:
6762 case OMPC_firstprivate:
6763 case OMPC_lastprivate:
6764 case OMPC_shared:
6765 case OMPC_reduction:
6766 case OMPC_task_reduction:
6767 case OMPC_in_reduction:
6768 case OMPC_linear:
6769 case OMPC_aligned:
6770 case OMPC_copyin:
6771 case OMPC_copyprivate:
6772 case OMPC_nowait:
6773 case OMPC_untied:
6774 case OMPC_mergeable:
6775 case OMPC_allocate:
6776 case OMPC_read:
6777 case OMPC_write:
6778 case OMPC_update:
6779 case OMPC_capture:
6780 case OMPC_compare:
6781 case OMPC_seq_cst:
6782 case OMPC_acq_rel:
6783 case OMPC_acquire:
6784 case OMPC_release:
6785 case OMPC_relaxed:
6786 case OMPC_depend:
6787 case OMPC_threads:
6788 case OMPC_simd:
6789 case OMPC_map:
6790 case OMPC_nogroup:
6791 case OMPC_defaultmap:
6792 case OMPC_to:
6793 case OMPC_from:
6794 case OMPC_use_device_ptr:
6795 case OMPC_use_device_addr:
6796 case OMPC_is_device_ptr:
6797 case OMPC_has_device_addr:
6798 case OMPC_nontemporal:
6799 case OMPC_order:
6800 case OMPC_destroy:
6801 case OMPC_inclusive:
6802 case OMPC_exclusive:
6803 case OMPC_uses_allocators:
6804 case OMPC_affinity:
6805 case OMPC_bind:
6806 case OMPC_filter:
6807 case OMPC_severity:
6808 case OMPC_message:
6809 continue;
6810 case OMPC_allocator:
6811 case OMPC_flush:
6812 case OMPC_depobj:
6813 case OMPC_threadprivate:
6814 case OMPC_groupprivate:
6815 case OMPC_uniform:
6816 case OMPC_unknown:
6817 case OMPC_unified_address:
6818 case OMPC_unified_shared_memory:
6819 case OMPC_reverse_offload:
6820 case OMPC_dynamic_allocators:
6821 case OMPC_atomic_default_mem_order:
6822 case OMPC_self_maps:
6823 case OMPC_device_type:
6824 case OMPC_match:
6825 case OMPC_when:
6826 case OMPC_at:
6827 default:
6828 llvm_unreachable("Unexpected clause");
6829 }
6830 for (Stmt *CC : C->children()) {
6831 if (CC)
6832 DSAChecker.Visit(CC);
6833 }
6834 }
6835 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6836 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6837 }
6838 for (const auto &P : VarsWithInheritedDSA) {
6839 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6840 continue;
6841 ErrorFound = true;
6842 if (DSAStack->getDefaultDSA() == DSA_none ||
6843 DSAStack->getDefaultDSA() == DSA_private ||
6844 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6845 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6846 << P.first << P.second->getSourceRange();
6847 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6848 } else if (getLangOpts().OpenMP >= 50) {
6849 Diag(P.second->getExprLoc(),
6850 diag::err_omp_defaultmap_no_attr_for_variable)
6851 << P.first << P.second->getSourceRange();
6852 Diag(DSAStack->getDefaultDSALocation(),
6853 diag::note_omp_defaultmap_attr_none);
6854 }
6855 }
6856
6857 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6858 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6859 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6860 AllowedNameModifiers.push_back(D);
6861 }
6862 if (!AllowedNameModifiers.empty())
6863 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6864 ErrorFound;
6865
6866 if (ErrorFound)
6867 return StmtError();
6868
6869 if (!SemaRef.CurContext->isDependentContext() &&
6871 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6872 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6873 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6874 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6875 // Register target to DSA Stack.
6876 DSAStack->addTargetDirLocation(StartLoc);
6877 }
6878
6879 return Res;
6880}
6881
6883 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6884 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6885 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6886 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6887 assert(Aligneds.size() == Alignments.size());
6888 assert(Linears.size() == LinModifiers.size());
6889 assert(Linears.size() == Steps.size());
6890 if (!DG || DG.get().isNull())
6891 return DeclGroupPtrTy();
6892
6893 const int SimdId = 0;
6894 if (!DG.get().isSingleDecl()) {
6895 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6896 << SimdId;
6897 return DG;
6898 }
6899 Decl *ADecl = DG.get().getSingleDecl();
6900 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6901 ADecl = FTD->getTemplatedDecl();
6902
6903 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6904 if (!FD) {
6905 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6906 return DeclGroupPtrTy();
6907 }
6908
6909 // OpenMP [2.8.2, declare simd construct, Description]
6910 // The parameter of the simdlen clause must be a constant positive integer
6911 // expression.
6912 ExprResult SL;
6913 if (Simdlen)
6914 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6915 // OpenMP [2.8.2, declare simd construct, Description]
6916 // The special this pointer can be used as if was one of the arguments to the
6917 // function in any of the linear, aligned, or uniform clauses.
6918 // The uniform clause declares one or more arguments to have an invariant
6919 // value for all concurrent invocations of the function in the execution of a
6920 // single SIMD loop.
6921 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6922 const Expr *UniformedLinearThis = nullptr;
6923 for (const Expr *E : Uniforms) {
6924 E = E->IgnoreParenImpCasts();
6925 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6926 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6927 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6928 FD->getParamDecl(PVD->getFunctionScopeIndex())
6929 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6930 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6931 continue;
6932 }
6933 if (isa<CXXThisExpr>(E)) {
6934 UniformedLinearThis = E;
6935 continue;
6936 }
6937 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6938 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6939 }
6940 // OpenMP [2.8.2, declare simd construct, Description]
6941 // The aligned clause declares that the object to which each list item points
6942 // is aligned to the number of bytes expressed in the optional parameter of
6943 // the aligned clause.
6944 // The special this pointer can be used as if was one of the arguments to the
6945 // function in any of the linear, aligned, or uniform clauses.
6946 // The type of list items appearing in the aligned clause must be array,
6947 // pointer, reference to array, or reference to pointer.
6948 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6949 const Expr *AlignedThis = nullptr;
6950 for (const Expr *E : Aligneds) {
6951 E = E->IgnoreParenImpCasts();
6952 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6953 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6954 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6955 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6956 FD->getParamDecl(PVD->getFunctionScopeIndex())
6957 ->getCanonicalDecl() == CanonPVD) {
6958 // OpenMP [2.8.1, simd construct, Restrictions]
6959 // A list-item cannot appear in more than one aligned clause.
6960 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
6961 if (!Inserted) {
6962 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6963 << 1 << getOpenMPClauseNameForDiag(OMPC_aligned)
6964 << E->getSourceRange();
6965 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6966 << getOpenMPClauseNameForDiag(OMPC_aligned);
6967 continue;
6968 }
6969 QualType QTy = PVD->getType()
6970 .getNonReferenceType()
6971 .getUnqualifiedType()
6972 .getCanonicalType();
6973 const Type *Ty = QTy.getTypePtrOrNull();
6974 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6975 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6976 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6977 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6978 }
6979 continue;
6980 }
6981 }
6982 if (isa<CXXThisExpr>(E)) {
6983 if (AlignedThis) {
6984 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6985 << 2 << getOpenMPClauseNameForDiag(OMPC_aligned)
6986 << E->getSourceRange();
6987 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6988 << getOpenMPClauseNameForDiag(OMPC_aligned);
6989 }
6990 AlignedThis = E;
6991 continue;
6992 }
6993 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6994 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6995 }
6996 // The optional parameter of the aligned clause, alignment, must be a constant
6997 // positive integer expression. If no optional parameter is specified,
6998 // implementation-defined default alignments for SIMD instructions on the
6999 // target platforms are assumed.
7001 for (Expr *E : Alignments) {
7002 ExprResult Align;
7003 if (E)
7004 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
7005 NewAligns.push_back(Align.get());
7006 }
7007 // OpenMP [2.8.2, declare simd construct, Description]
7008 // The linear clause declares one or more list items to be private to a SIMD
7009 // lane and to have a linear relationship with respect to the iteration space
7010 // of a loop.
7011 // The special this pointer can be used as if was one of the arguments to the
7012 // function in any of the linear, aligned, or uniform clauses.
7013 // When a linear-step expression is specified in a linear clause it must be
7014 // either a constant integer expression or an integer-typed parameter that is
7015 // specified in a uniform clause on the directive.
7016 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7017 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7018 auto MI = LinModifiers.begin();
7019 for (const Expr *E : Linears) {
7020 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7021 ++MI;
7022 E = E->IgnoreParenImpCasts();
7023 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7024 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7025 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7026 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7027 FD->getParamDecl(PVD->getFunctionScopeIndex())
7028 ->getCanonicalDecl() == CanonPVD) {
7029 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7030 // A list-item cannot appear in more than one linear clause.
7031 if (auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
7032 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7033 << getOpenMPClauseNameForDiag(OMPC_linear)
7034 << getOpenMPClauseNameForDiag(OMPC_linear)
7035 << E->getSourceRange();
7036 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7037 << getOpenMPClauseNameForDiag(OMPC_linear);
7038 continue;
7039 }
7040 // Each argument can appear in at most one uniform or linear clause.
7041 if (auto It = UniformedArgs.find(CanonPVD);
7042 It != UniformedArgs.end()) {
7043 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7044 << getOpenMPClauseNameForDiag(OMPC_linear)
7045 << getOpenMPClauseNameForDiag(OMPC_uniform)
7046 << E->getSourceRange();
7047 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7048 << getOpenMPClauseNameForDiag(OMPC_uniform);
7049 continue;
7050 }
7051 LinearArgs[CanonPVD] = E;
7052 if (E->isValueDependent() || E->isTypeDependent() ||
7055 continue;
7056 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7057 PVD->getOriginalType(),
7058 /*IsDeclareSimd=*/true);
7059 continue;
7060 }
7061 }
7062 if (isa<CXXThisExpr>(E)) {
7063 if (UniformedLinearThis) {
7064 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7065 << getOpenMPClauseNameForDiag(OMPC_linear)
7066 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7067 : OMPC_linear)
7068 << E->getSourceRange();
7069 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7070 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7071 : OMPC_linear);
7072 continue;
7073 }
7074 UniformedLinearThis = E;
7075 if (E->isValueDependent() || E->isTypeDependent() ||
7077 continue;
7078 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7079 E->getType(), /*IsDeclareSimd=*/true);
7080 continue;
7081 }
7082 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7083 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7084 }
7085 Expr *Step = nullptr;
7086 Expr *NewStep = nullptr;
7087 SmallVector<Expr *, 4> NewSteps;
7088 for (Expr *E : Steps) {
7089 // Skip the same step expression, it was checked already.
7090 if (Step == E || !E) {
7091 NewSteps.push_back(E ? NewStep : nullptr);
7092 continue;
7093 }
7094 Step = E;
7095 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7096 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7097 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7098 if (UniformedArgs.count(CanonPVD) == 0) {
7099 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7100 << Step->getSourceRange();
7101 } else if (E->isValueDependent() || E->isTypeDependent() ||
7104 CanonPVD->getType()->hasIntegerRepresentation()) {
7105 NewSteps.push_back(Step);
7106 } else {
7107 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7108 << Step->getSourceRange();
7109 }
7110 continue;
7111 }
7112 NewStep = Step;
7113 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7114 !Step->isInstantiationDependent() &&
7116 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7117 .get();
7118 if (NewStep)
7119 NewStep = SemaRef
7120 .VerifyIntegerConstantExpression(
7121 NewStep, /*FIXME*/ AllowFoldKind::Allow)
7122 .get();
7123 }
7124 NewSteps.push_back(NewStep);
7125 }
7126 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7127 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7128 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7129 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7130 const_cast<Expr **>(Linears.data()), Linears.size(),
7131 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7132 NewSteps.data(), NewSteps.size(), SR);
7133 ADecl->addAttr(NewAttr);
7134 return DG;
7135}
7136
7138 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
7139 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
7140 SourceLocation EndLoc) {
7141 assert(isOpenMPInformationalDirective(Kind) &&
7142 "Unexpected directive category");
7143
7144 StmtResult Res = StmtError();
7145
7146 switch (Kind) {
7147 case OMPD_assume:
7148 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
7149 break;
7150 default:
7151 llvm_unreachable("Unknown OpenMP directive");
7152 }
7153
7154 return Res;
7155}
7156
7157static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7158 QualType NewType) {
7159 assert(NewType->isFunctionProtoType() &&
7160 "Expected function type with prototype.");
7161 assert(FD->getType()->isFunctionNoProtoType() &&
7162 "Expected function with type with no prototype.");
7163 assert(FDWithProto->getType()->isFunctionProtoType() &&
7164 "Expected function with prototype.");
7165 // Synthesize parameters with the same types.
7166 FD->setType(NewType);
7168 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7169 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7170 SourceLocation(), nullptr, P->getType(),
7171 /*TInfo=*/nullptr, SC_None, nullptr);
7172 Param->setScopeInfo(0, Params.size());
7173 Param->setImplicit();
7174 Params.push_back(Param);
7175 }
7176
7177 FD->setParams(Params);
7178}
7179
7181 if (D->isInvalidDecl())
7182 return;
7183 FunctionDecl *FD = nullptr;
7184 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7185 FD = UTemplDecl->getTemplatedDecl();
7186 else
7187 FD = cast<FunctionDecl>(D);
7188 assert(FD && "Expected a function declaration!");
7189
7190 // If we are instantiating templates we do *not* apply scoped assumptions but
7191 // only global ones. We apply scoped assumption to the template definition
7192 // though.
7193 if (!SemaRef.inTemplateInstantiation()) {
7194 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7195 FD->addAttr(AA);
7196 }
7197 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7198 FD->addAttr(AA);
7199}
7200
7201SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7202 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7203
7205 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7207 if (!D.getIdentifier())
7208 return;
7209
7210 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7211
7212 // Template specialization is an extension, check if we do it.
7213 bool IsTemplated = !TemplateParamLists.empty();
7214 if (IsTemplated &&
7215 !DVScope.TI->isExtensionActive(
7216 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7217 return;
7218
7219 const IdentifierInfo *BaseII = D.getIdentifier();
7222 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7223 /*ObjectType=*/QualType());
7224
7225 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7226 QualType FType = TInfo->getType();
7227
7228 bool IsConstexpr =
7230 bool IsConsteval =
7232
7233 for (auto *Candidate : Lookup) {
7234 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7235 FunctionDecl *UDecl = nullptr;
7236 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7237 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7238 // FIXME: Should this compare the template parameter lists on all levels?
7239 if (SemaRef.Context.isSameTemplateParameterList(
7240 FTD->getTemplateParameters(), TemplateParamLists.back()))
7241 UDecl = FTD->getTemplatedDecl();
7242 } else if (!IsTemplated)
7243 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7244 if (!UDecl)
7245 continue;
7246
7247 // Don't specialize constexpr/consteval functions with
7248 // non-constexpr/consteval functions.
7249 if (UDecl->isConstexpr() && !IsConstexpr)
7250 continue;
7251 if (UDecl->isConsteval() && !IsConsteval)
7252 continue;
7253
7254 QualType UDeclTy = UDecl->getType();
7255 if (!UDeclTy->isDependentType()) {
7257 FType, UDeclTy, /*OfBlockPointer=*/false,
7258 /*Unqualified=*/false, /*AllowCXX=*/true);
7259 if (NewType.isNull())
7260 continue;
7261 }
7262
7263 // Found a base!
7264 Bases.push_back(UDecl);
7265 }
7266
7267 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7268 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7269 // If no base was found we create a declaration that we use as base.
7270 if (Bases.empty() && UseImplicitBase) {
7272 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7273 BaseD->setImplicit(true);
7274 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7275 Bases.push_back(BaseTemplD->getTemplatedDecl());
7276 else
7277 Bases.push_back(cast<FunctionDecl>(BaseD));
7278 }
7279
7280 std::string MangledName;
7281 MangledName += D.getIdentifier()->getName();
7282 MangledName += getOpenMPVariantManglingSeparatorStr();
7283 MangledName += DVScope.NameSuffix;
7284 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7285
7286 VariantII.setMangledOpenMPVariantName(true);
7287 D.SetIdentifier(&VariantII, D.getBeginLoc());
7288}
7289
7292 // Do not mark function as is used to prevent its emission if this is the
7293 // only place where it is used.
7296
7297 FunctionDecl *FD = nullptr;
7298 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7299 FD = UTemplDecl->getTemplatedDecl();
7300 else
7301 FD = cast<FunctionDecl>(D);
7302 auto *VariantFuncRef = DeclRefExpr::Create(
7304 /*RefersToEnclosingVariableOrCapture=*/false,
7305 /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue);
7306
7307 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7308 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7309 getASTContext(), VariantFuncRef, DVScope.TI,
7310 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7311 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7312 /*NeedDeviceAddrArgs=*/nullptr, /*NeedDeviceAddrArgsSize=*/0,
7313 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7314 for (FunctionDecl *BaseFD : Bases)
7315 BaseFD->addAttr(OMPDeclareVariantA);
7316}
7317
7319 SourceLocation LParenLoc,
7320 MultiExprArg ArgExprs,
7321 SourceLocation RParenLoc,
7322 Expr *ExecConfig) {
7323 // The common case is a regular call we do not want to specialize at all. Try
7324 // to make that case fast by bailing early.
7325 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7326 if (!CE)
7327 return Call;
7328
7329 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7330 if (!CalleeFnDecl)
7331 return Call;
7332
7333 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7334 CalleeFnDecl->getIdentifier() &&
7335 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7336 // checking for any calls inside an Order region
7338 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7339 }
7340
7341 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7342 return Call;
7343
7344 ASTContext &Context = getASTContext();
7345 std::function<void(StringRef)> DiagUnknownTrait = [this,
7346 CE](StringRef ISATrait) {
7347 // TODO Track the selector locations in a way that is accessible here to
7348 // improve the diagnostic location.
7349 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7350 << ISATrait;
7351 };
7352 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7353 SemaRef.getCurFunctionDecl(),
7354 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7355
7356 QualType CalleeFnType = CalleeFnDecl->getType();
7357
7360 while (CalleeFnDecl) {
7361 for (OMPDeclareVariantAttr *A :
7362 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7363 Expr *VariantRef = A->getVariantFuncRef();
7364
7365 VariantMatchInfo VMI;
7366 OMPTraitInfo &TI = A->getTraitInfo();
7367 TI.getAsVariantMatchInfo(Context, VMI);
7368 if (!isVariantApplicableInContext(VMI, OMPCtx,
7369 /*DeviceSetOnly=*/false))
7370 continue;
7371
7372 VMIs.push_back(VMI);
7373 Exprs.push_back(VariantRef);
7374 }
7375
7376 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7377 }
7378
7379 ExprResult NewCall;
7380 do {
7381 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7382 if (BestIdx < 0)
7383 return Call;
7384 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7385 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7386
7387 {
7388 // Try to build a (member) call expression for the current best applicable
7389 // variant expression. We allow this to fail in which case we continue
7390 // with the next best variant expression. The fail case is part of the
7391 // implementation defined behavior in the OpenMP standard when it talks
7392 // about what differences in the function prototypes: "Any differences
7393 // that the specific OpenMP context requires in the prototype of the
7394 // variant from the base function prototype are implementation defined."
7395 // This wording is there to allow the specialized variant to have a
7396 // different type than the base function. This is intended and OK but if
7397 // we cannot create a call the difference is not in the "implementation
7398 // defined range" we allow.
7400
7401 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7402 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7403 BestExpr = MemberExpr::CreateImplicit(
7404 Context, MemberCall->getImplicitObjectArgument(),
7405 /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy,
7406 MemberCall->getValueKind(), MemberCall->getObjectKind());
7407 }
7408 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7409 RParenLoc, ExecConfig);
7410 if (NewCall.isUsable()) {
7411 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7412 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7414 CalleeFnType, NewCalleeFnDecl->getType(),
7415 /*OfBlockPointer=*/false,
7416 /*Unqualified=*/false, /*AllowCXX=*/true);
7417 if (!NewType.isNull())
7418 break;
7419 // Don't use the call if the function type was not compatible.
7420 NewCall = nullptr;
7421 }
7422 }
7423 }
7424
7425 VMIs.erase(VMIs.begin() + BestIdx);
7426 Exprs.erase(Exprs.begin() + BestIdx);
7427 } while (!VMIs.empty());
7428
7429 if (!NewCall.isUsable())
7430 return Call;
7431 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7432}
7433
7434std::optional<std::pair<FunctionDecl *, Expr *>>
7436 Expr *VariantRef,
7437 OMPTraitInfo &TI,
7438 unsigned NumAppendArgs,
7439 SourceRange SR) {
7440 ASTContext &Context = getASTContext();
7441 if (!DG || DG.get().isNull())
7442 return std::nullopt;
7443
7444 const int VariantId = 1;
7445 // Must be applied only to single decl.
7446 if (!DG.get().isSingleDecl()) {
7447 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7448 << VariantId << SR;
7449 return std::nullopt;
7450 }
7451 Decl *ADecl = DG.get().getSingleDecl();
7452 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7453 ADecl = FTD->getTemplatedDecl();
7454
7455 // Decl must be a function.
7456 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7457 if (!FD) {
7458 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7459 << VariantId << SR;
7460 return std::nullopt;
7461 }
7462
7463 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7464 // The 'target' attribute needs to be separately checked because it does
7465 // not always signify a multiversion function declaration.
7466 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7467 };
7468 // OpenMP is not compatible with multiversion function attributes.
7469 if (HasMultiVersionAttributes(FD)) {
7470 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7471 << SR;
7472 return std::nullopt;
7473 }
7474
7475 // Allow #pragma omp declare variant only if the function is not used.
7476 if (FD->isUsed(false))
7477 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7478 << FD->getLocation();
7479
7480 // Check if the function was emitted already.
7481 const FunctionDecl *Definition;
7482 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7483 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7484 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7485 << FD->getLocation();
7486
7487 // The VariantRef must point to function.
7488 if (!VariantRef) {
7489 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7490 return std::nullopt;
7491 }
7492
7493 auto ShouldDelayChecks = [](Expr *&E, bool) {
7494 return E && (E->isTypeDependent() || E->isValueDependent() ||
7497 };
7498 // Do not check templates, wait until instantiation.
7499 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7500 TI.anyScoreOrCondition(ShouldDelayChecks))
7501 return std::make_pair(FD, VariantRef);
7502
7503 // Deal with non-constant score and user condition expressions.
7504 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7505 bool IsScore) -> bool {
7506 if (!E || E->isIntegerConstantExpr(getASTContext()))
7507 return false;
7508
7509 if (IsScore) {
7510 // We warn on non-constant scores and pretend they were not present.
7511 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7512 << E;
7513 E = nullptr;
7514 } else {
7515 // We could replace a non-constant user condition with "false" but we
7516 // will soon need to handle these anyway for the dynamic version of
7517 // OpenMP context selectors.
7518 Diag(E->getExprLoc(),
7519 diag::err_omp_declare_variant_user_condition_not_constant)
7520 << E;
7521 }
7522 return true;
7523 };
7524 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7525 return std::nullopt;
7526
7527 QualType AdjustedFnType = FD->getType();
7528 if (NumAppendArgs) {
7529 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7530 if (!PTy) {
7531 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7532 << SR;
7533 return std::nullopt;
7534 }
7535 // Adjust the function type to account for an extra omp_interop_t for each
7536 // specified in the append_args clause.
7537 const TypeDecl *TD = nullptr;
7538 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7540 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
7541 NamedDecl *ND = Result.getFoundDecl();
7542 TD = dyn_cast_or_null<TypeDecl>(ND);
7543 }
7544 if (!TD) {
7545 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7546 return std::nullopt;
7547 }
7548 QualType InteropType =
7549 Context.getTypeDeclType(ElaboratedTypeKeyword::None,
7550 /*Qualifier=*/std::nullopt, TD);
7551 if (PTy->isVariadic()) {
7552 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7553 return std::nullopt;
7554 }
7556 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7557 Params.insert(Params.end(), NumAppendArgs, InteropType);
7558 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7559 PTy->getExtProtoInfo());
7560 }
7561
7562 // Convert VariantRef expression to the type of the original function to
7563 // resolve possible conflicts.
7564 ExprResult VariantRefCast = VariantRef;
7565 if (getLangOpts().CPlusPlus) {
7566 QualType FnPtrType;
7567 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7568 if (Method && !Method->isStatic()) {
7569 FnPtrType = Context.getMemberPointerType(
7570 AdjustedFnType, /*Qualifier=*/std::nullopt, Method->getParent());
7571 ExprResult ER;
7572 {
7573 // Build addr_of unary op to correctly handle type checks for member
7574 // functions.
7576 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7577 VariantRef);
7578 }
7579 if (!ER.isUsable()) {
7580 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7581 << VariantId << VariantRef->getSourceRange();
7582 return std::nullopt;
7583 }
7584 VariantRef = ER.get();
7585 } else {
7586 FnPtrType = Context.getPointerType(AdjustedFnType);
7587 }
7588 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7589 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7590 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7591 VariantRef, FnPtrType.getUnqualifiedType(),
7592 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7593 /*InOverloadResolution=*/false,
7594 /*CStyle=*/false,
7595 /*AllowObjCWritebackConversion=*/false);
7596 if (ICS.isFailure()) {
7597 Diag(VariantRef->getExprLoc(),
7598 diag::err_omp_declare_variant_incompat_types)
7599 << VariantRef->getType()
7600 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7601 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7602 return std::nullopt;
7603 }
7604 VariantRefCast = SemaRef.PerformImplicitConversion(
7605 VariantRef, FnPtrType.getUnqualifiedType(),
7607 if (!VariantRefCast.isUsable())
7608 return std::nullopt;
7609 }
7610 // Drop previously built artificial addr_of unary op for member functions.
7611 if (Method && !Method->isStatic()) {
7612 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7613 if (auto *UO = dyn_cast<UnaryOperator>(
7614 PossibleAddrOfVariantRef->IgnoreImplicit()))
7615 VariantRefCast = UO->getSubExpr();
7616 }
7617 }
7618
7619 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7620 if (!ER.isUsable() ||
7622 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7623 << VariantId << VariantRef->getSourceRange();
7624 return std::nullopt;
7625 }
7626
7627 // The VariantRef must point to function.
7628 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7629 if (!DRE) {
7630 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7631 << VariantId << VariantRef->getSourceRange();
7632 return std::nullopt;
7633 }
7634 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7635 if (!NewFD) {
7636 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7637 << VariantId << VariantRef->getSourceRange();
7638 return std::nullopt;
7639 }
7640
7641 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7642 Diag(VariantRef->getExprLoc(),
7643 diag::err_omp_declare_variant_same_base_function)
7644 << VariantRef->getSourceRange();
7645 return std::nullopt;
7646 }
7647
7648 // Check if function types are compatible in C.
7649 if (!getLangOpts().CPlusPlus) {
7650 QualType NewType =
7651 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7652 if (NewType.isNull()) {
7653 Diag(VariantRef->getExprLoc(),
7654 diag::err_omp_declare_variant_incompat_types)
7655 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7656 << VariantRef->getSourceRange();
7657 return std::nullopt;
7658 }
7659 if (NewType->isFunctionProtoType()) {
7660 if (FD->getType()->isFunctionNoProtoType())
7661 setPrototype(SemaRef, FD, NewFD, NewType);
7662 else if (NewFD->getType()->isFunctionNoProtoType())
7663 setPrototype(SemaRef, NewFD, FD, NewType);
7664 }
7665 }
7666
7667 // Check if variant function is not marked with declare variant directive.
7668 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7669 Diag(VariantRef->getExprLoc(),
7670 diag::warn_omp_declare_variant_marked_as_declare_variant)
7671 << VariantRef->getSourceRange();
7672 SourceRange SR =
7673 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7674 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7675 return std::nullopt;
7676 }
7677
7678 enum DoesntSupport {
7679 VirtFuncs = 1,
7680 Constructors = 3,
7681 Destructors = 4,
7682 DeletedFuncs = 5,
7683 DefaultedFuncs = 6,
7684 ConstexprFuncs = 7,
7685 ConstevalFuncs = 8,
7686 };
7687 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7688 if (CXXFD->isVirtual()) {
7689 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7690 << VirtFuncs;
7691 return std::nullopt;
7692 }
7693
7694 if (isa<CXXConstructorDecl>(FD)) {
7695 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7696 << Constructors;
7697 return std::nullopt;
7698 }
7699
7700 if (isa<CXXDestructorDecl>(FD)) {
7701 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7702 << Destructors;
7703 return std::nullopt;
7704 }
7705 }
7706
7707 if (FD->isDeleted()) {
7708 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7709 << DeletedFuncs;
7710 return std::nullopt;
7711 }
7712
7713 if (FD->isDefaulted()) {
7714 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7715 << DefaultedFuncs;
7716 return std::nullopt;
7717 }
7718
7719 if (FD->isConstexpr()) {
7720 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7721 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7722 return std::nullopt;
7723 }
7724
7725 // Check general compatibility.
7726 if (SemaRef.areMultiversionVariantFunctionsCompatible(
7731 VariantRef->getExprLoc(),
7732 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7733 PartialDiagnosticAt(VariantRef->getExprLoc(),
7734 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7735 << FD->getLocation()),
7736 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7737 /*CLinkageMayDiffer=*/true))
7738 return std::nullopt;
7739 return std::make_pair(FD, cast<Expr>(DRE));
7740}
7741
7743 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7744 ArrayRef<Expr *> AdjustArgsNothing,
7745 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7746 ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
7747 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7748 SourceLocation AppendArgsLoc, SourceRange SR) {
7749
7750 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7751 // An adjust_args clause or append_args clause can only be specified if the
7752 // dispatch selector of the construct selector set appears in the match
7753 // clause.
7754
7755 SmallVector<Expr *, 8> AllAdjustArgs;
7756 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7757 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7758 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7759
7760 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7761 VariantMatchInfo VMI;
7763 if (!llvm::is_contained(
7764 VMI.ConstructTraits,
7765 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7766 if (!AllAdjustArgs.empty())
7767 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7768 << getOpenMPClauseNameForDiag(OMPC_adjust_args);
7769 if (!AppendArgs.empty())
7770 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7771 << getOpenMPClauseNameForDiag(OMPC_append_args);
7772 return;
7773 }
7774 }
7775
7776 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7777 // Each argument can only appear in a single adjust_args clause for each
7778 // declare variant directive.
7780
7781 for (Expr *E : AllAdjustArgs) {
7782 E = E->IgnoreParenImpCasts();
7783 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7784 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7785 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7786 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7787 FD->getParamDecl(PVD->getFunctionScopeIndex())
7788 ->getCanonicalDecl() == CanonPVD) {
7789 // It's a parameter of the function, check duplicates.
7790 if (!AdjustVars.insert(CanonPVD).second) {
7791 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7792 << PVD;
7793 return;
7794 }
7795 continue;
7796 }
7797 }
7798 }
7799 // Anything that is not a function parameter is an error.
7800 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7801 return;
7802 }
7803
7804 // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
7805 // If the `need_device_addr` adjust-op modifier is present, each list item
7806 // that appears in the clause must refer to an argument in the declaration of
7807 // the function variant that has a reference type
7808 if (getLangOpts().OpenMP >= 60) {
7809 for (Expr *E : AdjustArgsNeedDeviceAddr) {
7810 E = E->IgnoreParenImpCasts();
7811 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7812 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7813 if (!VD->getType()->isReferenceType())
7814 Diag(E->getExprLoc(),
7815 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7816 }
7817 }
7818 }
7819 }
7820
7821 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7822 getASTContext(), VariantRef, &TI,
7823 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7824 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7825 AdjustArgsNeedDevicePtr.size(),
7826 const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
7827 AdjustArgsNeedDeviceAddr.size(),
7828 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7829 FD->addAttr(NewAttr);
7830}
7831
7832static CapturedStmt *
7834 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7835 assert(CS && "Captured statement expected");
7836 // 1.2.2 OpenMP Language Terminology
7837 // Structured block - An executable statement with a single entry at the
7838 // top and a single exit at the bottom.
7839 // The point of exit cannot be a branch out of the structured block.
7840 // longjmp() and throw() must not violate the entry/exit criteria.
7841 CS->getCapturedDecl()->setNothrow();
7842
7843 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7844 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7846 // 1.2.2 OpenMP Language Terminology
7847 // Structured block - An executable statement with a single entry at the
7848 // top and a single exit at the bottom.
7849 // The point of exit cannot be a branch out of the structured block.
7850 // longjmp() and throw() must not violate the entry/exit criteria.
7851 CS->getCapturedDecl()->setNothrow();
7852 }
7854 return CS;
7855}
7856
7859 Stmt *AStmt, SourceLocation StartLoc,
7860 SourceLocation EndLoc) {
7861 if (!AStmt)
7862 return StmtError();
7863
7864 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7865
7866 return OMPParallelDirective::Create(
7867 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7868 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7869}
7870
7871namespace {
7872/// Iteration space of a single for loop.
7873struct LoopIterationSpace final {
7874 /// True if the condition operator is the strict compare operator (<, > or
7875 /// !=).
7876 bool IsStrictCompare = false;
7877 /// Condition of the loop.
7878 Expr *PreCond = nullptr;
7879 /// This expression calculates the number of iterations in the loop.
7880 /// It is always possible to calculate it before starting the loop.
7881 Expr *NumIterations = nullptr;
7882 /// The loop counter variable.
7883 Expr *CounterVar = nullptr;
7884 /// Private loop counter variable.
7885 Expr *PrivateCounterVar = nullptr;
7886 /// This is initializer for the initial value of #CounterVar.
7887 Expr *CounterInit = nullptr;
7888 /// This is step for the #CounterVar used to generate its update:
7889 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7890 Expr *CounterStep = nullptr;
7891 /// Should step be subtracted?
7892 bool Subtract = false;
7893 /// Source range of the loop init.
7894 SourceRange InitSrcRange;
7895 /// Source range of the loop condition.
7896 SourceRange CondSrcRange;
7897 /// Source range of the loop increment.
7898 SourceRange IncSrcRange;
7899 /// Minimum value that can have the loop control variable. Used to support
7900 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7901 /// since only such variables can be used in non-loop invariant expressions.
7902 Expr *MinValue = nullptr;
7903 /// Maximum value that can have the loop control variable. Used to support
7904 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7905 /// since only such variables can be used in non-loop invariant expressions.
7906 Expr *MaxValue = nullptr;
7907 /// true, if the lower bound depends on the outer loop control var.
7908 bool IsNonRectangularLB = false;
7909 /// true, if the upper bound depends on the outer loop control var.
7910 bool IsNonRectangularUB = false;
7911 /// Index of the loop this loop depends on and forms non-rectangular loop
7912 /// nest.
7913 unsigned LoopDependentIdx = 0;
7914 /// Final condition for the non-rectangular loop nest support. It is used to
7915 /// check that the number of iterations for this particular counter must be
7916 /// finished.
7917 Expr *FinalCondition = nullptr;
7918};
7919
7920/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
7921/// set are referenced. Used for verifying loop nest structure before
7922/// performing a loop collapse operation.
7923class ForSubExprChecker : public DynamicRecursiveASTVisitor {
7924 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7925 VarDecl *ForbiddenVar = nullptr;
7926 SourceRange ErrLoc;
7927
7928public:
7929 explicit ForSubExprChecker(
7930 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7931 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7932 // We want to visit implicit code, i.e. synthetic initialisation statements
7933 // created during range-for lowering.
7934 ShouldVisitImplicitCode = true;
7935 }
7936
7937 bool VisitDeclRefExpr(DeclRefExpr *E) override {
7938 ValueDecl *VD = E->getDecl();
7940 return true;
7941 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
7942 if (V->getType()->isReferenceType()) {
7943 VarDecl *VD = V->getDefinition();
7944 if (VD->hasInit()) {
7945 Expr *I = VD->getInit();
7946 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7947 if (!DRE)
7948 return true;
7950 }
7951 }
7952 Decl *Canon = V->getCanonicalDecl();
7953 if (CollapsedLoopVarDecls.contains(Canon)) {
7954 ForbiddenVar = V;
7955 ErrLoc = E->getSourceRange();
7956 return false;
7957 }
7958
7959 return true;
7960 }
7961
7962 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
7963 SourceRange getErrRange() const { return ErrLoc; }
7964};
7965
7966/// Helper class for checking canonical form of the OpenMP loops and
7967/// extracting iteration space of each loop in the loop nest, that will be used
7968/// for IR generation.
7969class OpenMPIterationSpaceChecker {
7970 /// Reference to Sema.
7971 Sema &SemaRef;
7972 /// Does the loop associated directive support non-rectangular loops?
7973 bool SupportsNonRectangular;
7974 /// Data-sharing stack.
7975 DSAStackTy &Stack;
7976 /// A location for diagnostics (when there is no some better location).
7977 SourceLocation DefaultLoc;
7978 /// A location for diagnostics (when increment is not compatible).
7979 SourceLocation ConditionLoc;
7980 /// The set of variables declared within the (to be collapsed) loop nest.
7981 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7982 /// A source location for referring to loop init later.
7983 SourceRange InitSrcRange;
7984 /// A source location for referring to condition later.
7985 SourceRange ConditionSrcRange;
7986 /// A source location for referring to increment later.
7987 SourceRange IncrementSrcRange;
7988 /// Loop variable.
7989 ValueDecl *LCDecl = nullptr;
7990 /// Reference to loop variable.
7991 Expr *LCRef = nullptr;
7992 /// Lower bound (initializer for the var).
7993 Expr *LB = nullptr;
7994 /// Upper bound.
7995 Expr *UB = nullptr;
7996 /// Loop step (increment).
7997 Expr *Step = nullptr;
7998 /// This flag is true when condition is one of:
7999 /// Var < UB
8000 /// Var <= UB
8001 /// UB > Var
8002 /// UB >= Var
8003 /// This will have no value when the condition is !=
8004 std::optional<bool> TestIsLessOp;
8005 /// This flag is true when condition is strict ( < or > ).
8006 bool TestIsStrictOp = false;
8007 /// This flag is true when step is subtracted on each iteration.
8008 bool SubtractStep = false;
8009 /// The outer loop counter this loop depends on (if any).
8010 const ValueDecl *DepDecl = nullptr;
8011 /// Contains number of loop (starts from 1) on which loop counter init
8012 /// expression of this loop depends on.
8013 std::optional<unsigned> InitDependOnLC;
8014 /// Contains number of loop (starts from 1) on which loop counter condition
8015 /// expression of this loop depends on.
8016 std::optional<unsigned> CondDependOnLC;
8017 /// Checks if the provide statement depends on the loop counter.
8018 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8019 bool IsInitializer);
8020 /// Original condition required for checking of the exit condition for
8021 /// non-rectangular loop.
8022 Expr *Condition = nullptr;
8023
8024public:
8025 OpenMPIterationSpaceChecker(
8026 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
8027 SourceLocation DefaultLoc,
8028 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
8029 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8030 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8031 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
8032 /// Check init-expr for canonical loop form and save loop counter
8033 /// variable - #Var and its initialization value - #LB.
8034 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8035 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8036 /// for less/greater and for strict/non-strict comparison.
8037 bool checkAndSetCond(Expr *S);
8038 /// Check incr-expr for canonical loop form and return true if it
8039 /// does not conform, otherwise save loop step (#Step).
8040 bool checkAndSetInc(Expr *S);
8041 /// Return the loop counter variable.
8042 ValueDecl *getLoopDecl() const { return LCDecl; }
8043 /// Return the reference expression to loop counter variable.
8044 Expr *getLoopDeclRefExpr() const { return LCRef; }
8045 /// Source range of the loop init.
8046 SourceRange getInitSrcRange() const { return InitSrcRange; }
8047 /// Source range of the loop condition.
8048 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8049 /// Source range of the loop increment.
8050 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8051 /// True if the step should be subtracted.
8052 bool shouldSubtractStep() const { return SubtractStep; }
8053 /// True, if the compare operator is strict (<, > or !=).
8054 bool isStrictTestOp() const { return TestIsStrictOp; }
8055 /// Build the expression to calculate the number of iterations.
8056 Expr *buildNumIterations(
8057 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8058 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8059 /// Build the precondition expression for the loops.
8060 Expr *
8061 buildPreCond(Scope *S, Expr *Cond,
8062 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8063 /// Build reference expression to the counter be used for codegen.
8064 DeclRefExpr *
8065 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8066 DSAStackTy &DSA) const;
8067 /// Build reference expression to the private counter be used for
8068 /// codegen.
8069 Expr *buildPrivateCounterVar() const;
8070 /// Build initialization of the counter be used for codegen.
8071 Expr *buildCounterInit() const;
8072 /// Build step of the counter be used for codegen.
8073 Expr *buildCounterStep() const;
8074 /// Build loop data with counter value for depend clauses in ordered
8075 /// directives.
8076 Expr *
8077 buildOrderedLoopData(Scope *S, Expr *Counter,
8078 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8079 SourceLocation Loc, Expr *Inc = nullptr,
8080 OverloadedOperatorKind OOK = OO_Amp);
8081 /// Builds the minimum value for the loop counter.
8082 std::pair<Expr *, Expr *> buildMinMaxValues(
8083 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8084 /// Builds final condition for the non-rectangular loops.
8085 Expr *buildFinalCondition(Scope *S) const;
8086 /// Return true if any expression is dependent.
8087 bool dependent() const;
8088 /// Returns true if the initializer forms non-rectangular loop.
8089 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8090 /// Returns true if the condition forms non-rectangular loop.
8091 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8092 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8093 unsigned getLoopDependentIdx() const {
8094 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8095 }
8096
8097private:
8098 /// Check the right-hand side of an assignment in the increment
8099 /// expression.
8100 bool checkAndSetIncRHS(Expr *RHS);
8101 /// Helper to set loop counter variable and its initializer.
8102 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8103 bool EmitDiags);
8104 /// Helper to set upper bound.
8105 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8106 SourceRange SR, SourceLocation SL);
8107 /// Helper to set loop increment.
8108 bool setStep(Expr *NewStep, bool Subtract);
8109};
8110
8111bool OpenMPIterationSpaceChecker::dependent() const {
8112 if (!LCDecl) {
8113 assert(!LB && !UB && !Step);
8114 return false;
8115 }
8116 return LCDecl->getType()->isDependentType() ||
8117 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8118 (Step && Step->isValueDependent());
8119}
8120
8121bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8122 Expr *NewLCRefExpr,
8123 Expr *NewLB, bool EmitDiags) {
8124 // State consistency checking to ensure correct usage.
8125 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8126 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8127 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8128 return true;
8129 LCDecl = getCanonicalDecl(NewLCDecl);
8130 LCRef = NewLCRefExpr;
8131 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8132 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8133 if ((Ctor->isCopyOrMoveConstructor() ||
8134 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8135 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8136 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
8137 LB = NewLB;
8138 if (EmitDiags)
8139 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8140 return false;
8141}
8142
8143bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8144 bool StrictOp, SourceRange SR,
8145 SourceLocation SL) {
8146 // State consistency checking to ensure correct usage.
8147 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8148 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8149 if (!NewUB || NewUB->containsErrors())
8150 return true;
8151 UB = NewUB;
8152 if (LessOp)
8153 TestIsLessOp = LessOp;
8154 TestIsStrictOp = StrictOp;
8155 ConditionSrcRange = SR;
8156 ConditionLoc = SL;
8157 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8158 return false;
8159}
8160
8161bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8162 // State consistency checking to ensure correct usage.
8163 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8164 if (!NewStep || NewStep->containsErrors())
8165 return true;
8166 if (!NewStep->isValueDependent()) {
8167 // Check that the step is integer expression.
8168 SourceLocation StepLoc = NewStep->getBeginLoc();
8170 StepLoc, getExprAsWritten(NewStep));
8171 if (Val.isInvalid())
8172 return true;
8173 NewStep = Val.get();
8174
8175 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8176 // If test-expr is of form var relational-op b and relational-op is < or
8177 // <= then incr-expr must cause var to increase on each iteration of the
8178 // loop. If test-expr is of form var relational-op b and relational-op is
8179 // > or >= then incr-expr must cause var to decrease on each iteration of
8180 // the loop.
8181 // If test-expr is of form b relational-op var and relational-op is < or
8182 // <= then incr-expr must cause var to decrease on each iteration of the
8183 // loop. If test-expr is of form b relational-op var and relational-op is
8184 // > or >= then incr-expr must cause var to increase on each iteration of
8185 // the loop.
8186 std::optional<llvm::APSInt> Result =
8187 NewStep->getIntegerConstantExpr(SemaRef.Context);
8188 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8189 bool IsConstNeg =
8190 Result && Result->isSigned() && (Subtract != Result->isNegative());
8191 bool IsConstPos =
8192 Result && Result->isSigned() && (Subtract == Result->isNegative());
8193 bool IsConstZero = Result && !Result->getBoolValue();
8194
8195 // != with increment is treated as <; != with decrement is treated as >
8196 if (!TestIsLessOp)
8197 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8198 if (UB && (IsConstZero ||
8199 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8200 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8201 SemaRef.Diag(NewStep->getExprLoc(),
8202 diag::err_omp_loop_incr_not_compatible)
8203 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8204 SemaRef.Diag(ConditionLoc,
8205 diag::note_omp_loop_cond_requires_compatible_incr)
8206 << *TestIsLessOp << ConditionSrcRange;
8207 return true;
8208 }
8209 if (*TestIsLessOp == Subtract) {
8210 NewStep =
8211 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8212 .get();
8213 Subtract = !Subtract;
8214 }
8215 }
8216
8217 Step = NewStep;
8218 SubtractStep = Subtract;
8219 return false;
8220}
8221
8222namespace {
8223/// Checker for the non-rectangular loops. Checks if the initializer or
8224/// condition expression references loop counter variable.
8225class LoopCounterRefChecker final
8226 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8227 Sema &SemaRef;
8228 DSAStackTy &Stack;
8229 const ValueDecl *CurLCDecl = nullptr;
8230 const ValueDecl *DepDecl = nullptr;
8231 const ValueDecl *PrevDepDecl = nullptr;
8232 bool IsInitializer = true;
8233 bool SupportsNonRectangular;
8234 unsigned BaseLoopId = 0;
8235 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8236 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8237 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8238 << (IsInitializer ? 0 : 1);
8239 return false;
8240 }
8241 const auto &&Data = Stack.isLoopControlVariable(VD);
8242 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8243 // The type of the loop iterator on which we depend may not have a random
8244 // access iterator type.
8245 if (Data.first && VD->getType()->isRecordType()) {
8246 SmallString<128> Name;
8247 llvm::raw_svector_ostream OS(Name);
8248 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8249 /*Qualified=*/true);
8250 SemaRef.Diag(E->getExprLoc(),
8251 diag::err_omp_wrong_dependency_iterator_type)
8252 << OS.str();
8253 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8254 return false;
8255 }
8256 if (Data.first && !SupportsNonRectangular) {
8257 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8258 return false;
8259 }
8260 if (Data.first &&
8261 (DepDecl || (PrevDepDecl &&
8262 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8263 if (!DepDecl && PrevDepDecl)
8264 DepDecl = PrevDepDecl;
8265 SmallString<128> Name;
8266 llvm::raw_svector_ostream OS(Name);
8267 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8268 /*Qualified=*/true);
8269 SemaRef.Diag(E->getExprLoc(),
8270 diag::err_omp_invariant_or_linear_dependency)
8271 << OS.str();
8272 return false;
8273 }
8274 if (Data.first) {
8275 DepDecl = VD;
8276 BaseLoopId = Data.first;
8277 }
8278 return Data.first;
8279 }
8280
8281public:
8282 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8283 const ValueDecl *VD = E->getDecl();
8284 if (isa<VarDecl>(VD))
8285 return checkDecl(E, VD);
8286 return false;
8287 }
8288 bool VisitMemberExpr(const MemberExpr *E) {
8289 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8290 const ValueDecl *VD = E->getMemberDecl();
8291 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8292 return checkDecl(E, VD);
8293 }
8294 return false;
8295 }
8296 bool VisitStmt(const Stmt *S) {
8297 bool Res = false;
8298 for (const Stmt *Child : S->children())
8299 Res = (Child && Visit(Child)) || Res;
8300 return Res;
8301 }
8302 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8303 const ValueDecl *CurLCDecl, bool IsInitializer,
8304 const ValueDecl *PrevDepDecl = nullptr,
8305 bool SupportsNonRectangular = true)
8306 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8307 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8308 SupportsNonRectangular(SupportsNonRectangular) {}
8309 unsigned getBaseLoopId() const {
8310 assert(CurLCDecl && "Expected loop dependency.");
8311 return BaseLoopId;
8312 }
8313 const ValueDecl *getDepDecl() const {
8314 assert(CurLCDecl && "Expected loop dependency.");
8315 return DepDecl;
8316 }
8317};
8318} // namespace
8319
8320std::optional<unsigned>
8321OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8322 bool IsInitializer) {
8323 // Check for the non-rectangular loops.
8324 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8325 DepDecl, SupportsNonRectangular);
8326 if (LoopStmtChecker.Visit(S)) {
8327 DepDecl = LoopStmtChecker.getDepDecl();
8328 return LoopStmtChecker.getBaseLoopId();
8329 }
8330 return std::nullopt;
8331}
8332
8333bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8334 // Check init-expr for canonical loop form and save loop counter
8335 // variable - #Var and its initialization value - #LB.
8336 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8337 // var = lb
8338 // integer-type var = lb
8339 // random-access-iterator-type var = lb
8340 // pointer-type var = lb
8341 //
8342 if (!S) {
8343 if (EmitDiags) {
8344 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8345 }
8346 return true;
8347 }
8348 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8349 if (!ExprTemp->cleanupsHaveSideEffects())
8350 S = ExprTemp->getSubExpr();
8351
8352 if (!CollapsedLoopVarDecls.empty()) {
8353 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8354 if (!FSEC.TraverseStmt(S)) {
8355 SourceRange Range = FSEC.getErrRange();
8356 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8357 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8358 return true;
8359 }
8360 }
8361
8362 InitSrcRange = S->getSourceRange();
8363 if (Expr *E = dyn_cast<Expr>(S))
8364 S = E->IgnoreParens();
8365 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8366 if (BO->getOpcode() == BO_Assign) {
8367 Expr *LHS = BO->getLHS()->IgnoreParens();
8368 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8369 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8370 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8371 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8372 EmitDiags);
8373 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8374 }
8375 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8376 if (ME->isArrow() &&
8377 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8378 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8379 EmitDiags);
8380 }
8381 }
8382 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8383 if (DS->isSingleDecl()) {
8384 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8385 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8386 // Accept non-canonical init form here but emit ext. warning.
8387 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8388 SemaRef.Diag(S->getBeginLoc(),
8389 diag::ext_omp_loop_not_canonical_init)
8390 << S->getSourceRange();
8391 return setLCDeclAndLB(
8392 Var,
8393 buildDeclRefExpr(SemaRef, Var,
8394 Var->getType().getNonReferenceType(),
8395 DS->getBeginLoc()),
8396 Var->getInit(), EmitDiags);
8397 }
8398 }
8399 }
8400 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8401 if (CE->getOperator() == OO_Equal) {
8402 Expr *LHS = CE->getArg(0);
8403 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8404 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8405 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8406 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8407 EmitDiags);
8408 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8409 }
8410 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8411 if (ME->isArrow() &&
8412 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8413 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8414 EmitDiags);
8415 }
8416 }
8417 }
8418
8419 if (dependent() || SemaRef.CurContext->isDependentContext())
8420 return false;
8421 if (EmitDiags) {
8422 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8423 << S->getSourceRange();
8424 }
8425 return true;
8426}
8427
8428/// Ignore parenthesizes, implicit casts, copy constructor and return the
8429/// variable (which may be the loop variable) if possible.
8430static const ValueDecl *getInitLCDecl(const Expr *E) {
8431 if (!E)
8432 return nullptr;
8433 E = getExprAsWritten(E);
8434 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8435 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8436 if ((Ctor->isCopyOrMoveConstructor() ||
8437 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8438 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8439 E = CE->getArg(0)->IgnoreParenImpCasts();
8440 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8441 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8442 return getCanonicalDecl(VD);
8443 }
8444 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8445 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8446 return getCanonicalDecl(ME->getMemberDecl());
8447 return nullptr;
8448}
8449
8450bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8451 // Check test-expr for canonical form, save upper-bound UB, flags for
8452 // less/greater and for strict/non-strict comparison.
8453 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8454 // var relational-op b
8455 // b relational-op var
8456 //
8457 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8458 if (!S) {
8459 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8460 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8461 return true;
8462 }
8463 Condition = S;
8464 S = getExprAsWritten(S);
8465
8466 if (!CollapsedLoopVarDecls.empty()) {
8467 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8468 if (!FSEC.TraverseStmt(S)) {
8469 SourceRange Range = FSEC.getErrRange();
8470 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8471 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8472 return true;
8473 }
8474 }
8475
8476 SourceLocation CondLoc = S->getBeginLoc();
8477 auto &&CheckAndSetCond =
8478 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8479 const Expr *RHS, SourceRange SR,
8480 SourceLocation OpLoc) -> std::optional<bool> {
8481 if (BinaryOperator::isRelationalOp(Opcode)) {
8482 if (getInitLCDecl(LHS) == LCDecl)
8483 return setUB(const_cast<Expr *>(RHS),
8484 (Opcode == BO_LT || Opcode == BO_LE),
8485 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8486 if (getInitLCDecl(RHS) == LCDecl)
8487 return setUB(const_cast<Expr *>(LHS),
8488 (Opcode == BO_GT || Opcode == BO_GE),
8489 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8490 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8491 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8492 /*LessOp=*/std::nullopt,
8493 /*StrictOp=*/true, SR, OpLoc);
8494 }
8495 return std::nullopt;
8496 };
8497 std::optional<bool> Res;
8498 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8499 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8500 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8501 RBO->getOperatorLoc());
8502 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8503 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8504 BO->getSourceRange(), BO->getOperatorLoc());
8505 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8506 if (CE->getNumArgs() == 2) {
8507 Res = CheckAndSetCond(
8508 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8509 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8510 }
8511 }
8512 if (Res)
8513 return *Res;
8514 if (dependent() || SemaRef.CurContext->isDependentContext())
8515 return false;
8516 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8517 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8518 return true;
8519}
8520
8521bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8522 // RHS of canonical loop form increment can be:
8523 // var + incr
8524 // incr + var
8525 // var - incr
8526 //
8527 RHS = RHS->IgnoreParenImpCasts();
8528 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8529 if (BO->isAdditiveOp()) {
8530 bool IsAdd = BO->getOpcode() == BO_Add;
8531 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8532 return setStep(BO->getRHS(), !IsAdd);
8533 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8534 return setStep(BO->getLHS(), /*Subtract=*/false);
8535 }
8536 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8537 bool IsAdd = CE->getOperator() == OO_Plus;
8538 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8539 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8540 return setStep(CE->getArg(1), !IsAdd);
8541 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8542 return setStep(CE->getArg(0), /*Subtract=*/false);
8543 }
8544 }
8545 if (dependent() || SemaRef.CurContext->isDependentContext())
8546 return false;
8547 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8548 << RHS->getSourceRange() << LCDecl;
8549 return true;
8550}
8551
8552bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8553 // Check incr-expr for canonical loop form and return true if it
8554 // does not conform.
8555 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8556 // ++var
8557 // var++
8558 // --var
8559 // var--
8560 // var += incr
8561 // var -= incr
8562 // var = var + incr
8563 // var = incr + var
8564 // var = var - incr
8565 //
8566 if (!S) {
8567 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8568 return true;
8569 }
8570 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8571 if (!ExprTemp->cleanupsHaveSideEffects())
8572 S = ExprTemp->getSubExpr();
8573
8574 if (!CollapsedLoopVarDecls.empty()) {
8575 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8576 if (!FSEC.TraverseStmt(S)) {
8577 SourceRange Range = FSEC.getErrRange();
8578 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8579 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8580 return true;
8581 }
8582 }
8583
8584 IncrementSrcRange = S->getSourceRange();
8585 S = S->IgnoreParens();
8586 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8587 if (UO->isIncrementDecrementOp() &&
8588 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8589 return setStep(SemaRef
8590 .ActOnIntegerConstant(UO->getBeginLoc(),
8591 (UO->isDecrementOp() ? -1 : 1))
8592 .get(),
8593 /*Subtract=*/false);
8594 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8595 switch (BO->getOpcode()) {
8596 case BO_AddAssign:
8597 case BO_SubAssign:
8598 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8599 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8600 break;
8601 case BO_Assign:
8602 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8603 return checkAndSetIncRHS(BO->getRHS());
8604 break;
8605 default:
8606 break;
8607 }
8608 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8609 switch (CE->getOperator()) {
8610 case OO_PlusPlus:
8611 case OO_MinusMinus:
8612 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8613 return setStep(SemaRef
8614 .ActOnIntegerConstant(
8615 CE->getBeginLoc(),
8616 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8617 .get(),
8618 /*Subtract=*/false);
8619 break;
8620 case OO_PlusEqual:
8621 case OO_MinusEqual:
8622 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8623 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8624 break;
8625 case OO_Equal:
8626 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8627 return checkAndSetIncRHS(CE->getArg(1));
8628 break;
8629 default:
8630 break;
8631 }
8632 }
8633 if (dependent() || SemaRef.CurContext->isDependentContext())
8634 return false;
8635 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8636 << S->getSourceRange() << LCDecl;
8637 return true;
8638}
8639
8640static ExprResult
8641tryBuildCapture(Sema &SemaRef, Expr *Capture,
8642 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8643 StringRef Name = ".capture_expr.") {
8644 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8645 return Capture;
8646 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8647 return SemaRef.PerformImplicitConversion(Capture->IgnoreImpCasts(),
8648 Capture->getType(),
8650 /*AllowExplicit=*/true);
8651 auto I = Captures.find(Capture);
8652 if (I != Captures.end())
8653 return buildCapture(SemaRef, Capture, I->second, Name);
8654 DeclRefExpr *Ref = nullptr;
8655 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8656 Captures[Capture] = Ref;
8657 return Res;
8658}
8659
8660/// Calculate number of iterations, transforming to unsigned, if number of
8661/// iterations may be larger than the original type.
8662static Expr *
8663calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8664 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8665 bool TestIsStrictOp, bool RoundToStep,
8666 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8667 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8668 if (!NewStep.isUsable())
8669 return nullptr;
8670 llvm::APSInt LRes, SRes;
8671 bool IsLowerConst = false, IsStepConst = false;
8672 if (std::optional<llvm::APSInt> Res =
8673 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8674 LRes = *Res;
8675 IsLowerConst = true;
8676 }
8677 if (std::optional<llvm::APSInt> Res =
8678 Step->getIntegerConstantExpr(SemaRef.Context)) {
8679 SRes = *Res;
8680 IsStepConst = true;
8681 }
8682 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8683 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8684 (TestIsStrictOp && LRes.isStrictlyPositive()));
8685 bool NeedToReorganize = false;
8686 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8687 if (!NoNeedToConvert && IsLowerConst &&
8688 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8689 NoNeedToConvert = true;
8690 if (RoundToStep) {
8691 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8692 ? LRes.getBitWidth()
8693 : SRes.getBitWidth();
8694 LRes = LRes.extend(BW + 1);
8695 LRes.setIsSigned(true);
8696 SRes = SRes.extend(BW + 1);
8697 SRes.setIsSigned(true);
8698 LRes -= SRes;
8699 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8700 LRes = LRes.trunc(BW);
8701 }
8702 if (TestIsStrictOp) {
8703 unsigned BW = LRes.getBitWidth();
8704 LRes = LRes.extend(BW + 1);
8705 LRes.setIsSigned(true);
8706 ++LRes;
8707 NoNeedToConvert =
8708 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8709 // truncate to the original bitwidth.
8710 LRes = LRes.trunc(BW);
8711 }
8712 NeedToReorganize = NoNeedToConvert;
8713 }
8714 llvm::APSInt URes;
8715 bool IsUpperConst = false;
8716 if (std::optional<llvm::APSInt> Res =
8717 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8718 URes = *Res;
8719 IsUpperConst = true;
8720 }
8721 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8722 (!RoundToStep || IsStepConst)) {
8723 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8724 : URes.getBitWidth();
8725 LRes = LRes.extend(BW + 1);
8726 LRes.setIsSigned(true);
8727 URes = URes.extend(BW + 1);
8728 URes.setIsSigned(true);
8729 URes -= LRes;
8730 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8731 NeedToReorganize = NoNeedToConvert;
8732 }
8733 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8734 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8735 // unsigned.
8736 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8737 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8738 QualType LowerTy = Lower->getType();
8739 QualType UpperTy = Upper->getType();
8740 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8741 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8742 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8743 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8745 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8746 Upper =
8747 SemaRef
8749 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8751 .get();
8752 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8753 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8754 }
8755 }
8756 if (!Lower || !Upper || NewStep.isInvalid())
8757 return nullptr;
8758
8759 ExprResult Diff;
8760 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8761 // 1]).
8762 if (NeedToReorganize) {
8763 Diff = Lower;
8764
8765 if (RoundToStep) {
8766 // Lower - Step
8767 Diff =
8768 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8769 if (!Diff.isUsable())
8770 return nullptr;
8771 }
8772
8773 // Lower - Step [+ 1]
8774 if (TestIsStrictOp)
8775 Diff = SemaRef.BuildBinOp(
8776 S, DefaultLoc, BO_Add, Diff.get(),
8777 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8778 if (!Diff.isUsable())
8779 return nullptr;
8780
8781 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8782 if (!Diff.isUsable())
8783 return nullptr;
8784
8785 // Upper - (Lower - Step [+ 1]).
8786 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8787 if (!Diff.isUsable())
8788 return nullptr;
8789 } else {
8790 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8791
8792 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8793 // BuildBinOp already emitted error, this one is to point user to upper
8794 // and lower bound, and to tell what is passed to 'operator-'.
8795 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8796 << Upper->getSourceRange() << Lower->getSourceRange();
8797 return nullptr;
8798 }
8799
8800 if (!Diff.isUsable())
8801 return nullptr;
8802
8803 // Upper - Lower [- 1]
8804 if (TestIsStrictOp)
8805 Diff = SemaRef.BuildBinOp(
8806 S, DefaultLoc, BO_Sub, Diff.get(),
8807 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8808 if (!Diff.isUsable())
8809 return nullptr;
8810
8811 if (RoundToStep) {
8812 // Upper - Lower [- 1] + Step
8813 Diff =
8814 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8815 if (!Diff.isUsable())
8816 return nullptr;
8817 }
8818 }
8819
8820 // Parentheses (for dumping/debugging purposes only).
8821 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8822 if (!Diff.isUsable())
8823 return nullptr;
8824
8825 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8826 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8827 if (!Diff.isUsable())
8828 return nullptr;
8829
8830 return Diff.get();
8831}
8832
8833/// Build the expression to calculate the number of iterations.
8834Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8835 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8836 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8837 QualType VarType = LCDecl->getType().getNonReferenceType();
8838 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8839 !SemaRef.getLangOpts().CPlusPlus)
8840 return nullptr;
8841 Expr *LBVal = LB;
8842 Expr *UBVal = UB;
8843 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8844 // max(LB(MinVal), LB(MaxVal)))
8845 if (InitDependOnLC) {
8846 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8847 if (!IS.MinValue || !IS.MaxValue)
8848 return nullptr;
8849 // OuterVar = Min
8850 ExprResult MinValue =
8851 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8852 if (!MinValue.isUsable())
8853 return nullptr;
8854
8855 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8856 IS.CounterVar, MinValue.get());
8857 if (!LBMinVal.isUsable())
8858 return nullptr;
8859 // OuterVar = Min, LBVal
8860 LBMinVal =
8861 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8862 if (!LBMinVal.isUsable())
8863 return nullptr;
8864 // (OuterVar = Min, LBVal)
8865 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8866 if (!LBMinVal.isUsable())
8867 return nullptr;
8868
8869 // OuterVar = Max
8870 ExprResult MaxValue =
8871 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8872 if (!MaxValue.isUsable())
8873 return nullptr;
8874
8875 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8876 IS.CounterVar, MaxValue.get());
8877 if (!LBMaxVal.isUsable())
8878 return nullptr;
8879 // OuterVar = Max, LBVal
8880 LBMaxVal =
8881 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8882 if (!LBMaxVal.isUsable())
8883 return nullptr;
8884 // (OuterVar = Max, LBVal)
8885 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8886 if (!LBMaxVal.isUsable())
8887 return nullptr;
8888
8889 Expr *LBMin =
8890 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8891 Expr *LBMax =
8892 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8893 if (!LBMin || !LBMax)
8894 return nullptr;
8895 // LB(MinVal) < LB(MaxVal)
8896 ExprResult MinLessMaxRes =
8897 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8898 if (!MinLessMaxRes.isUsable())
8899 return nullptr;
8900 Expr *MinLessMax =
8901 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8902 .get();
8903 if (!MinLessMax)
8904 return nullptr;
8905 if (*TestIsLessOp) {
8906 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8907 // LB(MaxVal))
8908 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8909 MinLessMax, LBMin, LBMax);
8910 if (!MinLB.isUsable())
8911 return nullptr;
8912 LBVal = MinLB.get();
8913 } else {
8914 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8915 // LB(MaxVal))
8916 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8917 MinLessMax, LBMax, LBMin);
8918 if (!MaxLB.isUsable())
8919 return nullptr;
8920 LBVal = MaxLB.get();
8921 }
8922 // OuterVar = LB
8923 LBMinVal =
8924 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8925 if (!LBMinVal.isUsable())
8926 return nullptr;
8927 LBVal = LBMinVal.get();
8928 }
8929 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8930 // min(UB(MinVal), UB(MaxVal))
8931 if (CondDependOnLC) {
8932 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8933 if (!IS.MinValue || !IS.MaxValue)
8934 return nullptr;
8935 // OuterVar = Min
8936 ExprResult MinValue =
8937 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8938 if (!MinValue.isUsable())
8939 return nullptr;
8940
8941 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8942 IS.CounterVar, MinValue.get());
8943 if (!UBMinVal.isUsable())
8944 return nullptr;
8945 // OuterVar = Min, UBVal
8946 UBMinVal =
8947 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8948 if (!UBMinVal.isUsable())
8949 return nullptr;
8950 // (OuterVar = Min, UBVal)
8951 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8952 if (!UBMinVal.isUsable())
8953 return nullptr;
8954
8955 // OuterVar = Max
8956 ExprResult MaxValue =
8957 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8958 if (!MaxValue.isUsable())
8959 return nullptr;
8960
8961 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8962 IS.CounterVar, MaxValue.get());
8963 if (!UBMaxVal.isUsable())
8964 return nullptr;
8965 // OuterVar = Max, UBVal
8966 UBMaxVal =
8967 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8968 if (!UBMaxVal.isUsable())
8969 return nullptr;
8970 // (OuterVar = Max, UBVal)
8971 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8972 if (!UBMaxVal.isUsable())
8973 return nullptr;
8974
8975 Expr *UBMin =
8976 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8977 Expr *UBMax =
8978 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8979 if (!UBMin || !UBMax)
8980 return nullptr;
8981 // UB(MinVal) > UB(MaxVal)
8982 ExprResult MinGreaterMaxRes =
8983 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8984 if (!MinGreaterMaxRes.isUsable())
8985 return nullptr;
8986 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8987 Captures, ".min_greater_max")
8988 .get();
8989 if (!MinGreaterMax)
8990 return nullptr;
8991 if (*TestIsLessOp) {
8992 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8993 // UB(MaxVal))
8994 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8995 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8996 if (!MaxUB.isUsable())
8997 return nullptr;
8998 UBVal = MaxUB.get();
8999 } else {
9000 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9001 // UB(MaxVal))
9002 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9003 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9004 if (!MinUB.isUsable())
9005 return nullptr;
9006 UBVal = MinUB.get();
9007 }
9008 }
9009 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9010 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9011 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
9012 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
9013 if (!Upper || !Lower)
9014 return nullptr;
9015
9016 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9017 Step, VarType, TestIsStrictOp,
9018 /*RoundToStep=*/true, Captures);
9019 if (!Diff.isUsable())
9020 return nullptr;
9021
9022 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9023 QualType Type = Diff.get()->getType();
9024 ASTContext &C = SemaRef.Context;
9025 bool UseVarType = VarType->hasIntegerRepresentation() &&
9026 C.getTypeSize(Type) > C.getTypeSize(VarType);
9027 if (!Type->isIntegerType() || UseVarType) {
9028 unsigned NewSize =
9029 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
9030 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9032 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
9033 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
9034 Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type,
9036 /*AllowExplicit=*/true);
9037 if (!Diff.isUsable())
9038 return nullptr;
9039 }
9040 }
9041 if (LimitedType) {
9042 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
9043 if (NewSize != C.getTypeSize(Type)) {
9044 if (NewSize < C.getTypeSize(Type)) {
9045 assert(NewSize == 64 && "incorrect loop var size");
9046 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9047 << InitSrcRange << ConditionSrcRange;
9048 }
9049 QualType NewType = C.getIntTypeForBitwidth(
9051 C.getTypeSize(Type) < NewSize);
9052 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
9053 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
9055 /*AllowExplicit=*/true);
9056 if (!Diff.isUsable())
9057 return nullptr;
9058 }
9059 }
9060 }
9061
9062 return Diff.get();
9063}
9064
9065std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9066 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9067 // Do not build for iterators, they cannot be used in non-rectangular loop
9068 // nests.
9069 if (LCDecl->getType()->isRecordType())
9070 return std::make_pair(nullptr, nullptr);
9071 // If we subtract, the min is in the condition, otherwise the min is in the
9072 // init value.
9073 Expr *MinExpr = nullptr;
9074 Expr *MaxExpr = nullptr;
9075 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9076 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9077 bool LBNonRect =
9078 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9079 bool UBNonRect =
9080 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9081 Expr *Lower =
9082 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9083 Expr *Upper =
9084 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9085 if (!Upper || !Lower)
9086 return std::make_pair(nullptr, nullptr);
9087
9088 if (*TestIsLessOp)
9089 MinExpr = Lower;
9090 else
9091 MaxExpr = Upper;
9092
9093 // Build minimum/maximum value based on number of iterations.
9094 QualType VarType = LCDecl->getType().getNonReferenceType();
9095
9096 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9097 Step, VarType, TestIsStrictOp,
9098 /*RoundToStep=*/false, Captures);
9099 if (!Diff.isUsable())
9100 return std::make_pair(nullptr, nullptr);
9101
9102 // ((Upper - Lower [- 1]) / Step) * Step
9103 // Parentheses (for dumping/debugging purposes only).
9104 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9105 if (!Diff.isUsable())
9106 return std::make_pair(nullptr, nullptr);
9107
9108 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
9109 if (!NewStep.isUsable())
9110 return std::make_pair(nullptr, nullptr);
9111 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
9112 if (!Diff.isUsable())
9113 return std::make_pair(nullptr, nullptr);
9114
9115 // Parentheses (for dumping/debugging purposes only).
9116 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9117 if (!Diff.isUsable())
9118 return std::make_pair(nullptr, nullptr);
9119
9120 // Convert to the ptrdiff_t, if original type is pointer.
9121 if (VarType->isAnyPointerType() &&
9122 !SemaRef.Context.hasSameType(
9123 Diff.get()->getType(),
9125 Diff = SemaRef.PerformImplicitConversion(
9126 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
9127 AssignmentAction::Converting, /*AllowExplicit=*/true);
9128 }
9129 if (!Diff.isUsable())
9130 return std::make_pair(nullptr, nullptr);
9131
9132 if (*TestIsLessOp) {
9133 // MinExpr = Lower;
9134 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9135 Diff = SemaRef.BuildBinOp(
9136 S, DefaultLoc, BO_Add,
9137 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
9138 Diff.get());
9139 if (!Diff.isUsable())
9140 return std::make_pair(nullptr, nullptr);
9141 } else {
9142 // MaxExpr = Upper;
9143 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9144 Diff = SemaRef.BuildBinOp(
9145 S, DefaultLoc, BO_Sub,
9146 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
9147 Diff.get());
9148 if (!Diff.isUsable())
9149 return std::make_pair(nullptr, nullptr);
9150 }
9151
9152 // Convert to the original type.
9153 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
9154 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
9156 /*AllowExplicit=*/true);
9157 if (!Diff.isUsable())
9158 return std::make_pair(nullptr, nullptr);
9159
9160 Sema::TentativeAnalysisScope Trap(SemaRef);
9161 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
9162 if (!Diff.isUsable())
9163 return std::make_pair(nullptr, nullptr);
9164
9165 if (*TestIsLessOp)
9166 MaxExpr = Diff.get();
9167 else
9168 MinExpr = Diff.get();
9169
9170 return std::make_pair(MinExpr, MaxExpr);
9171}
9172
9173Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9174 if (InitDependOnLC || CondDependOnLC)
9175 return Condition;
9176 return nullptr;
9177}
9178
9179Expr *OpenMPIterationSpaceChecker::buildPreCond(
9180 Scope *S, Expr *Cond,
9181 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9182 // Do not build a precondition when the condition/initialization is dependent
9183 // to prevent pessimistic early loop exit.
9184 // TODO: this can be improved by calculating min/max values but not sure that
9185 // it will be very effective.
9186 if (CondDependOnLC || InitDependOnLC)
9187 return SemaRef
9189 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
9190 SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
9191 /*AllowExplicit=*/true)
9192 .get();
9193
9194 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9195 Sema::TentativeAnalysisScope Trap(SemaRef);
9196
9197 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9198 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9199 if (!NewLB.isUsable() || !NewUB.isUsable())
9200 return nullptr;
9201
9202 ExprResult CondExpr =
9203 SemaRef.BuildBinOp(S, DefaultLoc,
9204 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9205 : (TestIsStrictOp ? BO_GT : BO_GE),
9206 NewLB.get(), NewUB.get());
9207 if (CondExpr.isUsable()) {
9208 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9209 SemaRef.Context.BoolTy))
9210 CondExpr = SemaRef.PerformImplicitConversion(
9211 CondExpr.get(), SemaRef.Context.BoolTy,
9212 /*Action=*/AssignmentAction::Casting,
9213 /*AllowExplicit=*/true);
9214 }
9215
9216 // Otherwise use original loop condition and evaluate it in runtime.
9217 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9218}
9219
9220/// Build reference expression to the counter be used for codegen.
9221DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9222 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9223 DSAStackTy &DSA) const {
9224 auto *VD = dyn_cast<VarDecl>(LCDecl);
9225 if (!VD) {
9226 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
9228 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9229 const DSAStackTy::DSAVarData Data =
9230 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9231 // If the loop control decl is explicitly marked as private, do not mark it
9232 // as captured again.
9233 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9234 Captures.insert(std::make_pair(LCRef, Ref));
9235 return Ref;
9236 }
9237 return cast<DeclRefExpr>(LCRef);
9238}
9239
9240Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9241 if (LCDecl && !LCDecl->isInvalidDecl()) {
9243 VarDecl *PrivateVar = buildVarDecl(
9244 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9245 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9246 isa<VarDecl>(LCDecl)
9247 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9248 : nullptr);
9249 if (PrivateVar->isInvalidDecl())
9250 return nullptr;
9251 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9252 }
9253 return nullptr;
9254}
9255
9256/// Build initialization of the counter to be used for codegen.
9257Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9258
9259/// Build step of the counter be used for codegen.
9260Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9261
9262Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9263 Scope *S, Expr *Counter,
9264 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9265 Expr *Inc, OverloadedOperatorKind OOK) {
9266 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9267 if (!Cnt)
9268 return nullptr;
9269 if (Inc) {
9270 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9271 "Expected only + or - operations for depend clauses.");
9272 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9273 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9274 if (!Cnt)
9275 return nullptr;
9276 }
9277 QualType VarType = LCDecl->getType().getNonReferenceType();
9278 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9279 !SemaRef.getLangOpts().CPlusPlus)
9280 return nullptr;
9281 // Upper - Lower
9282 Expr *Upper =
9283 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9284 Expr *Lower =
9285 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9286 if (!Upper || !Lower)
9287 return nullptr;
9288
9289 ExprResult Diff = calculateNumIters(
9290 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9291 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9292 if (!Diff.isUsable())
9293 return nullptr;
9294
9295 return Diff.get();
9296}
9297} // namespace
9298
9300 Stmt *Init) {
9301 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9302 assert(Init && "Expected loop in canonical form.");
9303 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9304 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9305 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9306 return;
9307
9308 DSAStack->loopStart();
9310 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9311 *DSAStack, ForLoc, EmptyDeclSet);
9312 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9313 if (ValueDecl *D = ISC.getLoopDecl()) {
9314 auto *VD = dyn_cast<VarDecl>(D);
9315 DeclRefExpr *PrivateRef = nullptr;
9316 if (!VD) {
9318 VD = Private;
9319 } else {
9320 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9321 /*WithInit=*/false);
9322 VD = cast<VarDecl>(PrivateRef->getDecl());
9323 }
9324 }
9325 DSAStack->addLoopControlVariable(D, VD);
9326 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9327 if (LD != D->getCanonicalDecl()) {
9328 DSAStack->resetPossibleLoopCounter();
9329 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9330 SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr(
9331 SemaRef, const_cast<VarDecl *>(Var),
9332 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9333 /*RefersToCapture=*/true));
9334 }
9335 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9336 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9337 // associated for-loop of a simd construct with just one associated
9338 // for-loop may be listed in a linear clause with a constant-linear-step
9339 // that is the increment of the associated for-loop. The loop iteration
9340 // variable(s) in the associated for-loop(s) of a for or parallel for
9341 // construct may be listed in a private or lastprivate clause.
9342 DSAStackTy::DSAVarData DVar =
9343 DSAStack->getTopDSA(D, /*FromParent=*/false);
9344 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9345 // is declared in the loop and it is predetermined as a private.
9346 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9347 OpenMPClauseKind PredeterminedCKind =
9349 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9350 : OMPC_private;
9351 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9352 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9353 };
9354 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9355 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9356 (getLangOpts().OpenMP <= 45 ||
9357 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9359 IsOpenMPTaskloopDirective(DKind) ||
9361 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9362 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9363 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9364 unsigned OMPVersion = getLangOpts().OpenMP;
9365 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9366 << getOpenMPClauseNameForDiag(DVar.CKind)
9367 << getOpenMPDirectiveName(DKind, OMPVersion)
9368 << getOpenMPClauseNameForDiag(PredeterminedCKind);
9369 if (DVar.RefExpr == nullptr)
9370 DVar.CKind = PredeterminedCKind;
9371 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9372 } else if (LoopDeclRefExpr) {
9373 // Make the loop iteration variable private (for worksharing
9374 // constructs), linear (for simd directives with the only one
9375 // associated loop) or lastprivate (for simd directives with several
9376 // collapsed or ordered loops).
9377 if (DVar.CKind == OMPC_unknown)
9378 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9379 }
9380 }
9381 }
9382 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9383}
9384
9385namespace {
9386// Utility for OpenMP doacross clause kind
9387class OMPDoacrossKind {
9388public:
9389 bool isSource(const OMPDoacrossClause *C) {
9390 return C->getDependenceType() == OMPC_DOACROSS_source ||
9391 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9392 }
9393 bool isSink(const OMPDoacrossClause *C) {
9394 return C->getDependenceType() == OMPC_DOACROSS_sink;
9395 }
9396 bool isSinkIter(const OMPDoacrossClause *C) {
9397 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9398 }
9399};
9400} // namespace
9401/// Called on a for stmt to check and extract its iteration space
9402/// for further processing (such as collapsing).
9404 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9405 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9406 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9407 Expr *OrderedLoopCountExpr,
9408 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9410 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9411 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9412 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9413 // OpenMP [2.9.1, Canonical Loop Form]
9414 // for (init-expr; test-expr; incr-expr) structured-block
9415 // for (range-decl: range-expr) structured-block
9416 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9417 S = CanonLoop->getLoopStmt();
9418 auto *For = dyn_cast_or_null<ForStmt>(S);
9419 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9420 // Ranged for is supported only in OpenMP 5.0.
9421 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9422 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
9423 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9424 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9425 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9426 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9427 if (TotalNestedLoopCount > 1) {
9428 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9429 SemaRef.Diag(DSA.getConstructLoc(),
9430 diag::note_omp_collapse_ordered_expr)
9431 << 2 << CollapseLoopCountExpr->getSourceRange()
9432 << OrderedLoopCountExpr->getSourceRange();
9433 else if (CollapseLoopCountExpr)
9434 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9435 diag::note_omp_collapse_ordered_expr)
9436 << 0 << CollapseLoopCountExpr->getSourceRange();
9437 else if (OrderedLoopCountExpr)
9438 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9439 diag::note_omp_collapse_ordered_expr)
9440 << 1 << OrderedLoopCountExpr->getSourceRange();
9441 }
9442 return true;
9443 }
9444 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9445 "No loop body.");
9446 // Postpone analysis in dependent contexts for ranged for loops.
9447 if (CXXFor && SemaRef.CurContext->isDependentContext())
9448 return false;
9449
9450 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9451 For ? For->getForLoc() : CXXFor->getForLoc(),
9452 CollapsedLoopVarDecls);
9453
9454 // Check init.
9455 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9456 if (ISC.checkAndSetInit(Init))
9457 return true;
9458
9459 bool HasErrors = false;
9460
9461 // Check loop variable's type.
9462 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9463 // OpenMP [2.6, Canonical Loop Form]
9464 // Var is one of the following:
9465 // A variable of signed or unsigned integer type.
9466 // For C++, a variable of a random access iterator type.
9467 // For C, a variable of a pointer type.
9468 QualType VarType = LCDecl->getType().getNonReferenceType();
9469 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9470 !VarType->isPointerType() &&
9471 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9472 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9473 << SemaRef.getLangOpts().CPlusPlus;
9474 HasErrors = true;
9475 }
9476
9477 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9478 // a Construct
9479 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9480 // parallel for construct is (are) private.
9481 // The loop iteration variable in the associated for-loop of a simd
9482 // construct with just one associated for-loop is linear with a
9483 // constant-linear-step that is the increment of the associated for-loop.
9484 // Exclude loop var from the list of variables with implicitly defined data
9485 // sharing attributes.
9486 VarsWithImplicitDSA.erase(LCDecl);
9487
9488 assert((isOpenMPLoopDirective(DKind) ||
9490 "DSA for non-loop vars");
9491
9492 // Check test-expr.
9493 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9494
9495 // Check incr-expr.
9496 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9497 }
9498
9499 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9500 return HasErrors;
9501
9502 // Build the loop's iteration space representation.
9503 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9504 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9505 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9506 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9512 Captures);
9513 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9514 ISC.buildCounterVar(Captures, DSA);
9515 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9516 ISC.buildPrivateCounterVar();
9517 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9518 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9519 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9520 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9521 ISC.getConditionSrcRange();
9522 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9523 ISC.getIncrementSrcRange();
9524 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9525 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9526 ISC.isStrictTestOp();
9527 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9528 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9529 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9530 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9531 ISC.buildFinalCondition(DSA.getCurScope());
9532 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9533 ISC.doesInitDependOnLC();
9534 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9535 ISC.doesCondDependOnLC();
9536 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9537 ISC.getLoopDependentIdx();
9538
9539 HasErrors |=
9540 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9541 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9542 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9543 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9544 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9545 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9546 if (!HasErrors && DSA.isOrderedRegion()) {
9547 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9548 if (CurrentNestedLoopCount <
9549 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9550 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9551 CurrentNestedLoopCount,
9552 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9553 DSA.getOrderedRegionParam().second->setLoopCounter(
9554 CurrentNestedLoopCount,
9555 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9556 }
9557 }
9558 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9559 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9560 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9561 unsigned NumLoops =
9562 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9563 if (CurrentNestedLoopCount >= NumLoops) {
9564 // Erroneous case - clause has some problems.
9565 continue;
9566 }
9567 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9568 Pair.second.size() <= CurrentNestedLoopCount) {
9569 // Erroneous case - clause has some problems.
9570 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9571 continue;
9572 }
9573 OMPDoacrossKind ODK;
9574 if (DoacrossC && ODK.isSink(DoacrossC) &&
9575 Pair.second.size() <= CurrentNestedLoopCount) {
9576 // Erroneous case - clause has some problems.
9577 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9578 continue;
9579 }
9580 Expr *CntValue;
9581 SourceLocation DepLoc =
9582 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9583 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9584 (DoacrossC && ODK.isSource(DoacrossC)))
9585 CntValue = ISC.buildOrderedLoopData(
9586 DSA.getCurScope(),
9587 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9588 DepLoc);
9589 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9590 Expr *Cnt = SemaRef
9592 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9593 .get();
9594 if (!Cnt)
9595 continue;
9596 // build CounterVar - 1
9597 Expr *Inc =
9598 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9599 .get();
9600 CntValue = ISC.buildOrderedLoopData(
9601 DSA.getCurScope(),
9602 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9603 DepLoc, Inc, clang::OO_Minus);
9604 } else
9605 CntValue = ISC.buildOrderedLoopData(
9606 DSA.getCurScope(),
9607 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9608 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9609 Pair.second[CurrentNestedLoopCount].second);
9610 if (DependC)
9611 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9612 else
9613 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9614 }
9615 }
9616
9617 return HasErrors;
9618}
9619
9620/// Build 'VarRef = Start.
9621static ExprResult
9623 ExprResult Start, bool IsNonRectangularLB,
9624 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9625 // Build 'VarRef = Start.
9626 ExprResult NewStart = IsNonRectangularLB
9627 ? Start.get()
9628 : tryBuildCapture(SemaRef, Start.get(), Captures);
9629 if (!NewStart.isUsable())
9630 return ExprError();
9631 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9632 VarRef.get()->getType())) {
9633 NewStart = SemaRef.PerformImplicitConversion(
9634 NewStart.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9635 /*AllowExplicit=*/true);
9636 if (!NewStart.isUsable())
9637 return ExprError();
9638 }
9639
9641 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9642 return Init;
9643}
9644
9645/// Build 'VarRef = Start + Iter * Step'.
9647 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9648 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9649 bool IsNonRectangularLB,
9650 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9651 // Add parentheses (for debugging purposes only).
9652 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9653 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9654 !Step.isUsable())
9655 return ExprError();
9656
9657 ExprResult NewStep = Step;
9658 if (Captures)
9659 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9660 if (NewStep.isInvalid())
9661 return ExprError();
9663 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9664 if (!Update.isUsable())
9665 return ExprError();
9666
9667 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9668 // 'VarRef = Start (+|-) Iter * Step'.
9669 if (!Start.isUsable())
9670 return ExprError();
9671 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9672 if (!NewStart.isUsable())
9673 return ExprError();
9674 if (Captures && !IsNonRectangularLB)
9675 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9676 if (NewStart.isInvalid())
9677 return ExprError();
9678
9679 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9680 ExprResult SavedUpdate = Update;
9681 ExprResult UpdateVal;
9682 if (VarRef.get()->getType()->isOverloadableType() ||
9683 NewStart.get()->getType()->isOverloadableType() ||
9684 Update.get()->getType()->isOverloadableType()) {
9685 Sema::TentativeAnalysisScope Trap(SemaRef);
9686
9687 Update =
9688 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9689 if (Update.isUsable()) {
9690 UpdateVal =
9691 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9692 VarRef.get(), SavedUpdate.get());
9693 if (UpdateVal.isUsable()) {
9694 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9695 UpdateVal.get());
9696 }
9697 }
9698 }
9699
9700 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9701 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9702 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9703 NewStart.get(), SavedUpdate.get());
9704 if (!Update.isUsable())
9705 return ExprError();
9706
9707 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9708 VarRef.get()->getType())) {
9710 Update.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9711 /*AllowExplicit=*/true);
9712 if (!Update.isUsable())
9713 return ExprError();
9714 }
9715
9716 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9717 }
9718 return Update;
9719}
9720
9721/// Convert integer expression \a E to make it have at least \a Bits
9722/// bits.
9723static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9724 if (E == nullptr)
9725 return ExprError();
9726 ASTContext &C = SemaRef.Context;
9727 QualType OldType = E->getType();
9728 unsigned HasBits = C.getTypeSize(OldType);
9729 if (HasBits >= Bits)
9730 return ExprResult(E);
9731 // OK to convert to signed, because new type has more bits than old.
9732 QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true);
9733 return SemaRef.PerformImplicitConversion(
9734 E, NewType, AssignmentAction::Converting, /*AllowExplicit=*/true);
9735}
9736
9737/// Check if the given expression \a E is a constant integer that fits
9738/// into \a Bits bits.
9739static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9740 if (E == nullptr)
9741 return false;
9742 if (std::optional<llvm::APSInt> Result =
9743 E->getIntegerConstantExpr(SemaRef.Context))
9744 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9745 return false;
9746}
9747
9748/// Build preinits statement for the given declarations.
9750 MutableArrayRef<Decl *> PreInits) {
9751 if (!PreInits.empty()) {
9752 return new (Context) DeclStmt(
9753 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9755 }
9756 return nullptr;
9757}
9758
9759/// Append the \p Item or the content of a CompoundStmt to the list \p
9760/// TargetList.
9761///
9762/// A CompoundStmt is used as container in case multiple statements need to be
9763/// stored in lieu of using an explicit list. Flattening is necessary because
9764/// contained DeclStmts need to be visible after the execution of the list. Used
9765/// for OpenMP pre-init declarations/statements.
9767 Stmt *Item) {
9768 // nullptr represents an empty list.
9769 if (!Item)
9770 return;
9771
9772 if (auto *CS = dyn_cast<CompoundStmt>(Item))
9773 llvm::append_range(TargetList, CS->body());
9774 else
9775 TargetList.push_back(Item);
9776}
9777
9778/// Build preinits statement for the given declarations.
9779static Stmt *
9781 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9782 if (!Captures.empty()) {
9783 SmallVector<Decl *, 16> PreInits;
9784 for (const auto &Pair : Captures)
9785 PreInits.push_back(Pair.second->getDecl());
9786 return buildPreInits(Context, PreInits);
9787 }
9788 return nullptr;
9789}
9790
9791/// Build pre-init statement for the given statements.
9792static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9793 if (PreInits.empty())
9794 return nullptr;
9795
9796 SmallVector<Stmt *> Stmts;
9797 for (Stmt *S : PreInits)
9798 appendFlattenedStmtList(Stmts, S);
9799 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9800}
9801
9802/// Build postupdate expression for the given list of postupdates expressions.
9803static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9804 Expr *PostUpdate = nullptr;
9805 if (!PostUpdates.empty()) {
9806 for (Expr *E : PostUpdates) {
9807 Expr *ConvE = S.BuildCStyleCastExpr(
9808 E->getExprLoc(),
9810 E->getExprLoc(), E)
9811 .get();
9812 PostUpdate = PostUpdate
9813 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9814 PostUpdate, ConvE)
9815 .get()
9816 : ConvE;
9817 }
9818 }
9819 return PostUpdate;
9820}
9821
9822/// Look for variables declared in the body parts of a for-loop nest. Used
9823/// for verifying loop nest structure before performing a loop collapse
9824/// operation.
9826 int NestingDepth = 0;
9827 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9828
9829public:
9830 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
9831 : VarDecls(VD) {}
9832
9833 bool VisitForStmt(ForStmt *F) override {
9834 ++NestingDepth;
9835 TraverseStmt(F->getBody());
9836 --NestingDepth;
9837 return false;
9838 }
9839
9841 ++NestingDepth;
9842 TraverseStmt(RF->getBody());
9843 --NestingDepth;
9844 return false;
9845 }
9846
9847 bool VisitVarDecl(VarDecl *D) override {
9848 Decl *C = D->getCanonicalDecl();
9849 if (NestingDepth > 0)
9850 VarDecls.insert(C);
9851 return true;
9852 }
9853};
9854
9855/// Called on a for stmt to check itself and nested loops (if any).
9856/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9857/// number of collapsed loops otherwise.
9858static unsigned
9859checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9860 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9861 DSAStackTy &DSA,
9862 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9863 OMPLoopBasedDirective::HelperExprs &Built) {
9864 // If either of the loop expressions exist and contain errors, we bail out
9865 // early because diagnostics have already been emitted and we can't reliably
9866 // check more about the loop.
9867 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
9868 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
9869 return 0;
9870
9871 unsigned NestedLoopCount = 1;
9872 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9874 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
9875
9876 if (CollapseLoopCountExpr) {
9877 // Found 'collapse' clause - calculate collapse number.
9878 Expr::EvalResult Result;
9879 if (!CollapseLoopCountExpr->isValueDependent() &&
9880 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9881 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9882
9883 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9884 FVDF.TraverseStmt(AStmt);
9885 } else {
9886 Built.clear(/*Size=*/1);
9887 return 1;
9888 }
9889 }
9890 unsigned OrderedLoopCount = 1;
9891 if (OrderedLoopCountExpr) {
9892 // Found 'ordered' clause - calculate collapse number.
9893 Expr::EvalResult EVResult;
9894 if (!OrderedLoopCountExpr->isValueDependent() &&
9895 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9896 SemaRef.getASTContext())) {
9897 llvm::APSInt Result = EVResult.Val.getInt();
9898 if (Result.getLimitedValue() < NestedLoopCount) {
9899 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9900 diag::err_omp_wrong_ordered_loop_count)
9901 << OrderedLoopCountExpr->getSourceRange();
9902 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9903 diag::note_collapse_loop_count)
9904 << CollapseLoopCountExpr->getSourceRange();
9905 }
9906 OrderedLoopCount = Result.getLimitedValue();
9907 } else {
9908 Built.clear(/*Size=*/1);
9909 return 1;
9910 }
9911 }
9912 // This is helper routine for loop directives (e.g., 'for', 'simd',
9913 // 'for simd', etc.).
9914 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9915 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9916 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9917 if (!OMPLoopBasedDirective::doForAllLoops(
9918 AStmt->IgnoreContainers(
9920 SupportsNonPerfectlyNested, NumLoops,
9921 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9922 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9923 &IterSpaces, &Captures,
9924 &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
9926 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9927 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9928 VarsWithImplicitDSA, IterSpaces, Captures,
9929 CollapsedLoopVarDecls))
9930 return true;
9931 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9932 IterSpaces[Cnt].CounterVar) {
9933 // Handle initialization of captured loop iterator variables.
9934 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9935 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9936 Captures[DRE] = DRE;
9937 }
9938 }
9939 return false;
9940 },
9941 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9942 Stmt *DependentPreInits = Transform->getPreInits();
9943 if (!DependentPreInits)
9944 return;
9945
9946 // Search for pre-init declared variables that need to be captured
9947 // to be referenceable inside the directive.
9948 SmallVector<Stmt *> Constituents;
9949 appendFlattenedStmtList(Constituents, DependentPreInits);
9950 for (Stmt *S : Constituents) {
9951 if (auto *DC = dyn_cast<DeclStmt>(S)) {
9952 for (Decl *C : DC->decls()) {
9953 auto *D = cast<VarDecl>(C);
9955 SemaRef, D, D->getType().getNonReferenceType(),
9956 cast<OMPExecutableDirective>(Transform->getDirective())
9957 ->getBeginLoc());
9958 Captures[Ref] = Ref;
9959 }
9960 }
9961 }
9962 }))
9963 return 0;
9964
9965 Built.clear(/*size=*/NestedLoopCount);
9966
9967 if (SemaRef.CurContext->isDependentContext())
9968 return NestedLoopCount;
9969
9970 // An example of what is generated for the following code:
9971 //
9972 // #pragma omp simd collapse(2) ordered(2)
9973 // for (i = 0; i < NI; ++i)
9974 // for (k = 0; k < NK; ++k)
9975 // for (j = J0; j < NJ; j+=2) {
9976 // <loop body>
9977 // }
9978 //
9979 // We generate the code below.
9980 // Note: the loop body may be outlined in CodeGen.
9981 // Note: some counters may be C++ classes, operator- is used to find number of
9982 // iterations and operator+= to calculate counter value.
9983 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9984 // or i64 is currently supported).
9985 //
9986 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9987 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9988 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9989 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9990 // // similar updates for vars in clauses (e.g. 'linear')
9991 // <loop body (using local i and j)>
9992 // }
9993 // i = NI; // assign final values of counters
9994 // j = NJ;
9995 //
9996
9997 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9998 // the iteration counts of the collapsed for loops.
9999 // Precondition tests if there is at least one iteration (all conditions are
10000 // true).
10001 auto PreCond = ExprResult(IterSpaces[0].PreCond);
10002 Expr *N0 = IterSpaces[0].NumIterations;
10003 ExprResult LastIteration32 = widenIterationCount(
10004 /*Bits=*/32,
10005 SemaRef
10006 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10008 /*AllowExplicit=*/true)
10009 .get(),
10010 SemaRef);
10011 ExprResult LastIteration64 = widenIterationCount(
10012 /*Bits=*/64,
10013 SemaRef
10014 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10016 /*AllowExplicit=*/true)
10017 .get(),
10018 SemaRef);
10019
10020 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
10021 return NestedLoopCount;
10022
10023 ASTContext &C = SemaRef.Context;
10024 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
10025
10026 Scope *CurScope = DSA.getCurScope();
10027 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10028 if (PreCond.isUsable()) {
10029 PreCond =
10030 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10031 PreCond.get(), IterSpaces[Cnt].PreCond);
10032 }
10033 Expr *N = IterSpaces[Cnt].NumIterations;
10034 SourceLocation Loc = N->getExprLoc();
10035 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
10036 if (LastIteration32.isUsable())
10037 LastIteration32 = SemaRef.BuildBinOp(
10038 CurScope, Loc, BO_Mul, LastIteration32.get(),
10039 SemaRef
10042 /*AllowExplicit=*/true)
10043 .get());
10044 if (LastIteration64.isUsable())
10045 LastIteration64 = SemaRef.BuildBinOp(
10046 CurScope, Loc, BO_Mul, LastIteration64.get(),
10047 SemaRef
10050 /*AllowExplicit=*/true)
10051 .get());
10052 }
10053
10054 // Choose either the 32-bit or 64-bit version.
10055 ExprResult LastIteration = LastIteration64;
10056 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
10057 (LastIteration32.isUsable() &&
10058 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
10059 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10060 fitsInto(
10061 /*Bits=*/32,
10062 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
10063 LastIteration64.get(), SemaRef))))
10064 LastIteration = LastIteration32;
10065 QualType VType = LastIteration.get()->getType();
10066 QualType RealVType = VType;
10067 QualType StrideVType = VType;
10068 if (isOpenMPTaskLoopDirective(DKind)) {
10069 VType =
10070 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
10071 StrideVType =
10072 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
10073 }
10074
10075 if (!LastIteration.isUsable())
10076 return 0;
10077
10078 // Save the number of iterations.
10079 ExprResult NumIterations = LastIteration;
10080 {
10081 LastIteration = SemaRef.BuildBinOp(
10082 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
10083 LastIteration.get(),
10084 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10085 if (!LastIteration.isUsable())
10086 return 0;
10087 }
10088
10089 // Calculate the last iteration number beforehand instead of doing this on
10090 // each iteration. Do not do this if the number of iterations may be kfold-ed.
10091 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
10092 ExprResult CalcLastIteration;
10093 if (!IsConstant) {
10094 ExprResult SaveRef =
10095 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
10096 LastIteration = SaveRef;
10097
10098 // Prepare SaveRef + 1.
10099 NumIterations = SemaRef.BuildBinOp(
10100 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
10101 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10102 if (!NumIterations.isUsable())
10103 return 0;
10104 }
10105
10106 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
10107
10108 // Build variables passed into runtime, necessary for worksharing directives.
10109 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10114 // Lower bound variable, initialized with zero.
10115 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
10116 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
10117 SemaRef.AddInitializerToDecl(LBDecl,
10118 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10119 /*DirectInit=*/false);
10120
10121 // Upper bound variable, initialized with last iteration number.
10122 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
10123 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
10124 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
10125 /*DirectInit=*/false);
10126
10127 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
10128 // This will be used to implement clause 'lastprivate'.
10129 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
10130 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
10131 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
10132 SemaRef.AddInitializerToDecl(ILDecl,
10133 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10134 /*DirectInit=*/false);
10135
10136 // Stride variable returned by runtime (we initialize it to 1 by default).
10137 VarDecl *STDecl =
10138 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
10139 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
10140 SemaRef.AddInitializerToDecl(STDecl,
10141 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
10142 /*DirectInit=*/false);
10143
10144 // Build expression: UB = min(UB, LastIteration)
10145 // It is necessary for CodeGen of directives with static scheduling.
10146 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
10147 UB.get(), LastIteration.get());
10148 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10149 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
10150 LastIteration.get(), UB.get());
10151 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
10152 CondOp.get());
10153 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false);
10154
10155 // If we have a combined directive that combines 'distribute', 'for' or
10156 // 'simd' we need to be able to access the bounds of the schedule of the
10157 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10158 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10160 // Lower bound variable, initialized with zero.
10161 VarDecl *CombLBDecl =
10162 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
10163 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
10164 SemaRef.AddInitializerToDecl(
10165 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10166 /*DirectInit=*/false);
10167
10168 // Upper bound variable, initialized with last iteration number.
10169 VarDecl *CombUBDecl =
10170 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
10171 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
10172 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
10173 /*DirectInit=*/false);
10174
10175 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10176 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
10177 ExprResult CombCondOp =
10178 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
10179 LastIteration.get(), CombUB.get());
10180 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
10181 CombCondOp.get());
10182 CombEUB =
10183 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false);
10184
10185 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
10186 // We expect to have at least 2 more parameters than the 'parallel'
10187 // directive does - the lower and upper bounds of the previous schedule.
10188 assert(CD->getNumParams() >= 4 &&
10189 "Unexpected number of parameters in loop combined directive");
10190
10191 // Set the proper type for the bounds given what we learned from the
10192 // enclosed loops.
10193 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
10194 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
10195
10196 // Previous lower and upper bounds are obtained from the region
10197 // parameters.
10198 PrevLB =
10199 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10200 PrevUB =
10201 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10202 }
10203 }
10204
10205 // Build the iteration variable and its initialization before loop.
10206 ExprResult IV;
10207 ExprResult Init, CombInit;
10208 {
10209 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10210 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10211 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10216 ? LB.get()
10217 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10218 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10219 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false);
10220
10222 Expr *CombRHS =
10227 ? CombLB.get()
10228 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10229 CombInit =
10230 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10231 CombInit =
10232 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false);
10233 }
10234 }
10235
10236 bool UseStrictCompare =
10237 RealVType->hasUnsignedIntegerRepresentation() &&
10238 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10239 return LIS.IsStrictCompare;
10240 });
10241 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10242 // unsigned IV)) for worksharing loops.
10243 SourceLocation CondLoc = AStmt->getBeginLoc();
10244 Expr *BoundUB = UB.get();
10245 if (UseStrictCompare) {
10246 BoundUB =
10247 SemaRef
10248 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10249 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10250 .get();
10251 BoundUB =
10252 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get();
10253 }
10259 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10260 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10261 BoundUB)
10262 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10263 NumIterations.get());
10264 ExprResult CombDistCond;
10266 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10267 NumIterations.get());
10268 }
10269
10270 ExprResult CombCond;
10272 Expr *BoundCombUB = CombUB.get();
10273 if (UseStrictCompare) {
10274 BoundCombUB =
10275 SemaRef
10276 .BuildBinOp(
10277 CurScope, CondLoc, BO_Add, BoundCombUB,
10278 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10279 .get();
10280 BoundCombUB =
10281 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false)
10282 .get();
10283 }
10284 CombCond =
10285 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10286 IV.get(), BoundCombUB);
10287 }
10288 // Loop increment (IV = IV + 1)
10289 SourceLocation IncLoc = AStmt->getBeginLoc();
10290 ExprResult Inc =
10291 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10292 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10293 if (!Inc.isUsable())
10294 return 0;
10295 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10296 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false);
10297 if (!Inc.isUsable())
10298 return 0;
10299
10300 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10301 // Used for directives with static scheduling.
10302 // In combined construct, add combined version that use CombLB and CombUB
10303 // base variables for the update
10304 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10309 // LB + ST
10310 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10311 if (!NextLB.isUsable())
10312 return 0;
10313 // LB = LB + ST
10314 NextLB =
10315 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10316 NextLB =
10317 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false);
10318 if (!NextLB.isUsable())
10319 return 0;
10320 // UB + ST
10321 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10322 if (!NextUB.isUsable())
10323 return 0;
10324 // UB = UB + ST
10325 NextUB =
10326 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10327 NextUB =
10328 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false);
10329 if (!NextUB.isUsable())
10330 return 0;
10332 CombNextLB =
10333 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10334 if (!NextLB.isUsable())
10335 return 0;
10336 // LB = LB + ST
10337 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10338 CombNextLB.get());
10339 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10340 /*DiscardedValue=*/false);
10341 if (!CombNextLB.isUsable())
10342 return 0;
10343 // UB + ST
10344 CombNextUB =
10345 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10346 if (!CombNextUB.isUsable())
10347 return 0;
10348 // UB = UB + ST
10349 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10350 CombNextUB.get());
10351 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10352 /*DiscardedValue=*/false);
10353 if (!CombNextUB.isUsable())
10354 return 0;
10355 }
10356 }
10357
10358 // Create increment expression for distribute loop when combined in a same
10359 // directive with for as IV = IV + ST; ensure upper bound expression based
10360 // on PrevUB instead of NumIterations - used to implement 'for' when found
10361 // in combination with 'distribute', like in 'distribute parallel for'
10362 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10363 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10365 DistCond = SemaRef.BuildBinOp(
10366 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10367 assert(DistCond.isUsable() && "distribute cond expr was not built");
10368
10369 DistInc =
10370 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10371 assert(DistInc.isUsable() && "distribute inc expr was not built");
10372 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10373 DistInc.get());
10374 DistInc =
10375 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false);
10376 assert(DistInc.isUsable() && "distribute inc expr was not built");
10377
10378 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10379 // construct
10380 ExprResult NewPrevUB = PrevUB;
10381 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10382 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10383 PrevUB.get()->getType())) {
10384 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10385 DistEUBLoc,
10387 DistEUBLoc, NewPrevUB.get());
10388 if (!NewPrevUB.isUsable())
10389 return 0;
10390 }
10391 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10392 UB.get(), NewPrevUB.get());
10393 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10394 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10395 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10396 CondOp.get());
10397 PrevEUB =
10398 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false);
10399
10400 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10401 // parallel for is in combination with a distribute directive with
10402 // schedule(static, 1)
10403 Expr *BoundPrevUB = PrevUB.get();
10404 if (UseStrictCompare) {
10405 BoundPrevUB =
10406 SemaRef
10407 .BuildBinOp(
10408 CurScope, CondLoc, BO_Add, BoundPrevUB,
10409 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10410 .get();
10411 BoundPrevUB =
10412 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false)
10413 .get();
10414 }
10415 ParForInDistCond =
10416 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10417 IV.get(), BoundPrevUB);
10418 }
10419
10420 // Build updates and final values of the loop counters.
10421 bool HasErrors = false;
10422 Built.Counters.resize(NestedLoopCount);
10423 Built.Inits.resize(NestedLoopCount);
10424 Built.Updates.resize(NestedLoopCount);
10425 Built.Finals.resize(NestedLoopCount);
10426 Built.DependentCounters.resize(NestedLoopCount);
10427 Built.DependentInits.resize(NestedLoopCount);
10428 Built.FinalsConditions.resize(NestedLoopCount);
10429 {
10430 // We implement the following algorithm for obtaining the
10431 // original loop iteration variable values based on the
10432 // value of the collapsed loop iteration variable IV.
10433 //
10434 // Let n+1 be the number of collapsed loops in the nest.
10435 // Iteration variables (I0, I1, .... In)
10436 // Iteration counts (N0, N1, ... Nn)
10437 //
10438 // Acc = IV;
10439 //
10440 // To compute Ik for loop k, 0 <= k <= n, generate:
10441 // Prod = N(k+1) * N(k+2) * ... * Nn;
10442 // Ik = Acc / Prod;
10443 // Acc -= Ik * Prod;
10444 //
10445 ExprResult Acc = IV;
10446 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10447 LoopIterationSpace &IS = IterSpaces[Cnt];
10448 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10449 ExprResult Iter;
10450
10451 // Compute prod
10452 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10453 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10454 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10455 IterSpaces[K].NumIterations);
10456
10457 // Iter = Acc / Prod
10458 // If there is at least one more inner loop to avoid
10459 // multiplication by 1.
10460 if (Cnt + 1 < NestedLoopCount)
10461 Iter =
10462 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10463 else
10464 Iter = Acc;
10465 if (!Iter.isUsable()) {
10466 HasErrors = true;
10467 break;
10468 }
10469
10470 // Update Acc:
10471 // Acc -= Iter * Prod
10472 // Check if there is at least one more inner loop to avoid
10473 // multiplication by 1.
10474 if (Cnt + 1 < NestedLoopCount)
10475 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10476 Prod.get());
10477 else
10478 Prod = Iter;
10479 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10480
10481 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10482 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10483 DeclRefExpr *CounterVar = buildDeclRefExpr(
10484 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10485 /*RefersToCapture=*/true);
10487 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10488 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10489 if (!Init.isUsable()) {
10490 HasErrors = true;
10491 break;
10492 }
10494 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10495 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10496 if (!Update.isUsable()) {
10497 HasErrors = true;
10498 break;
10499 }
10500
10501 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10502 ExprResult Final =
10503 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10504 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10505 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10506 if (!Final.isUsable()) {
10507 HasErrors = true;
10508 break;
10509 }
10510
10511 if (!Update.isUsable() || !Final.isUsable()) {
10512 HasErrors = true;
10513 break;
10514 }
10515 // Save results
10516 Built.Counters[Cnt] = IS.CounterVar;
10517 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10518 Built.Inits[Cnt] = Init.get();
10519 Built.Updates[Cnt] = Update.get();
10520 Built.Finals[Cnt] = Final.get();
10521 Built.DependentCounters[Cnt] = nullptr;
10522 Built.DependentInits[Cnt] = nullptr;
10523 Built.FinalsConditions[Cnt] = nullptr;
10524 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10525 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10526 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10527 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10528 }
10529 }
10530 }
10531
10532 if (HasErrors)
10533 return 0;
10534
10535 // Save results
10536 Built.IterationVarRef = IV.get();
10537 Built.LastIteration = LastIteration.get();
10538 Built.NumIterations = NumIterations.get();
10539 Built.CalcLastIteration = SemaRef
10540 .ActOnFinishFullExpr(CalcLastIteration.get(),
10541 /*DiscardedValue=*/false)
10542 .get();
10543 Built.PreCond = PreCond.get();
10544 Built.PreInits = buildPreInits(C, Captures);
10545 Built.Cond = Cond.get();
10546 Built.Init = Init.get();
10547 Built.Inc = Inc.get();
10548 Built.LB = LB.get();
10549 Built.UB = UB.get();
10550 Built.IL = IL.get();
10551 Built.ST = ST.get();
10552 Built.EUB = EUB.get();
10553 Built.NLB = NextLB.get();
10554 Built.NUB = NextUB.get();
10555 Built.PrevLB = PrevLB.get();
10556 Built.PrevUB = PrevUB.get();
10557 Built.DistInc = DistInc.get();
10558 Built.PrevEUB = PrevEUB.get();
10559 Built.DistCombinedFields.LB = CombLB.get();
10560 Built.DistCombinedFields.UB = CombUB.get();
10561 Built.DistCombinedFields.EUB = CombEUB.get();
10562 Built.DistCombinedFields.Init = CombInit.get();
10563 Built.DistCombinedFields.Cond = CombCond.get();
10564 Built.DistCombinedFields.NLB = CombNextLB.get();
10565 Built.DistCombinedFields.NUB = CombNextUB.get();
10566 Built.DistCombinedFields.DistCond = CombDistCond.get();
10567 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10568
10569 return NestedLoopCount;
10570}
10571
10573 auto CollapseClauses =
10574 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10575 if (CollapseClauses.begin() != CollapseClauses.end())
10576 return (*CollapseClauses.begin())->getNumForLoops();
10577 return nullptr;
10578}
10579
10581 auto OrderedClauses =
10582 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10583 if (OrderedClauses.begin() != OrderedClauses.end())
10584 return (*OrderedClauses.begin())->getNumForLoops();
10585 return nullptr;
10586}
10587
10589 const ArrayRef<OMPClause *> Clauses) {
10590 const OMPSafelenClause *Safelen = nullptr;
10591 const OMPSimdlenClause *Simdlen = nullptr;
10592
10593 for (const OMPClause *Clause : Clauses) {
10594 if (Clause->getClauseKind() == OMPC_safelen)
10595 Safelen = cast<OMPSafelenClause>(Clause);
10596 else if (Clause->getClauseKind() == OMPC_simdlen)
10597 Simdlen = cast<OMPSimdlenClause>(Clause);
10598 if (Safelen && Simdlen)
10599 break;
10600 }
10601
10602 if (Simdlen && Safelen) {
10603 const Expr *SimdlenLength = Simdlen->getSimdlen();
10604 const Expr *SafelenLength = Safelen->getSafelen();
10605 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10606 SimdlenLength->isInstantiationDependent() ||
10607 SimdlenLength->containsUnexpandedParameterPack())
10608 return false;
10609 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10610 SafelenLength->isInstantiationDependent() ||
10611 SafelenLength->containsUnexpandedParameterPack())
10612 return false;
10613 Expr::EvalResult SimdlenResult, SafelenResult;
10614 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10615 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10616 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10617 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10618 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10619 // If both simdlen and safelen clauses are specified, the value of the
10620 // simdlen parameter must be less than or equal to the value of the safelen
10621 // parameter.
10622 if (SimdlenRes > SafelenRes) {
10623 S.Diag(SimdlenLength->getExprLoc(),
10624 diag::err_omp_wrong_simdlen_safelen_values)
10625 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10626 return true;
10627 }
10628 }
10629 return false;
10630}
10631
10633 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10634 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10635 if (!AStmt)
10636 return StmtError();
10637
10638 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10639
10640 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10641 OMPLoopBasedDirective::HelperExprs B;
10642 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10643 // define the nested loops number.
10644 unsigned NestedLoopCount = checkOpenMPLoop(
10645 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10646 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10647 if (NestedLoopCount == 0)
10648 return StmtError();
10649
10650 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10651 return StmtError();
10652
10654 return StmtError();
10655
10656 auto *SimdDirective = OMPSimdDirective::Create(
10657 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10658 return SimdDirective;
10659}
10660
10662 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10663 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10664 if (!AStmt)
10665 return StmtError();
10666
10667 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10668 OMPLoopBasedDirective::HelperExprs B;
10669 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10670 // define the nested loops number.
10671 unsigned NestedLoopCount = checkOpenMPLoop(
10672 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10673 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10674 if (NestedLoopCount == 0)
10675 return StmtError();
10676
10677 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10678 return StmtError();
10679
10680 auto *ForDirective = OMPForDirective::Create(
10681 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10682 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10683 return ForDirective;
10684}
10685
10687 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10688 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10689 if (!AStmt)
10690 return StmtError();
10691
10692 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10693
10694 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10695 OMPLoopBasedDirective::HelperExprs B;
10696 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10697 // define the nested loops number.
10698 unsigned NestedLoopCount =
10699 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10700 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10701 VarsWithImplicitDSA, B);
10702 if (NestedLoopCount == 0)
10703 return StmtError();
10704
10705 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10706 return StmtError();
10707
10709 return StmtError();
10710
10711 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10712 NestedLoopCount, Clauses, AStmt, B);
10713}
10714
10716 Stmt *AStmt, DSAStackTy *Stack) {
10717 if (!AStmt)
10718 return true;
10719
10720 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10721 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
10722 auto BaseStmt = AStmt;
10723 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10724 BaseStmt = CS->getCapturedStmt();
10725 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10726 auto S = C->children();
10727 if (S.begin() == S.end())
10728 return true;
10729 // All associated statements must be '#pragma omp section' except for
10730 // the first one.
10731 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10732 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10733 if (SectionStmt)
10734 SemaRef.Diag(SectionStmt->getBeginLoc(),
10735 diag::err_omp_sections_substmt_not_section)
10736 << getOpenMPDirectiveName(DKind, OMPVersion);
10737 return true;
10738 }
10739 cast<OMPSectionDirective>(SectionStmt)
10740 ->setHasCancel(Stack->isCancelRegion());
10741 }
10742 } else {
10743 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10744 << getOpenMPDirectiveName(DKind, OMPVersion);
10745 return true;
10746 }
10747 return false;
10748}
10749
10752 Stmt *AStmt, SourceLocation StartLoc,
10753 SourceLocation EndLoc) {
10754 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10755 return StmtError();
10756
10757 SemaRef.setFunctionHasBranchProtectedScope();
10758
10759 return OMPSectionsDirective::Create(
10760 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10761 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10762}
10763
10765 SourceLocation StartLoc,
10766 SourceLocation EndLoc) {
10767 if (!AStmt)
10768 return StmtError();
10769
10770 SemaRef.setFunctionHasBranchProtectedScope();
10771 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10772
10773 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10774 DSAStack->isCancelRegion());
10775}
10776
10778 E = E->IgnoreParenCasts()->IgnoreImplicit();
10779 if (auto *CE = dyn_cast<CallExpr>(E))
10780 if (CE->getDirectCallee())
10781 return E;
10782 return nullptr;
10783}
10784
10787 Stmt *AStmt, SourceLocation StartLoc,
10788 SourceLocation EndLoc) {
10789 if (!AStmt)
10790 return StmtError();
10791
10792 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10793
10794 // 5.1 OpenMP
10795 // expression-stmt : an expression statement with one of the following forms:
10796 // expression = target-call ( [expression-list] );
10797 // target-call ( [expression-list] );
10798
10799 SourceLocation TargetCallLoc;
10800
10801 if (!SemaRef.CurContext->isDependentContext()) {
10802 Expr *TargetCall = nullptr;
10803
10804 auto *E = dyn_cast<Expr>(S);
10805 if (!E) {
10806 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10807 return StmtError();
10808 }
10809
10810 E = E->IgnoreParenCasts()->IgnoreImplicit();
10811
10812 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10813 if (BO->getOpcode() == BO_Assign)
10814 TargetCall = getDirectCallExpr(BO->getRHS());
10815 } else {
10816 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10817 if (COCE->getOperator() == OO_Equal)
10818 TargetCall = getDirectCallExpr(COCE->getArg(1));
10819 if (!TargetCall)
10820 TargetCall = getDirectCallExpr(E);
10821 }
10822 if (!TargetCall) {
10823 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10824 return StmtError();
10825 }
10826 TargetCallLoc = TargetCall->getExprLoc();
10827 }
10828
10829 SemaRef.setFunctionHasBranchProtectedScope();
10830
10831 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10832 Clauses, AStmt, TargetCallLoc);
10833}
10834
10837 DSAStackTy *Stack) {
10838 bool ErrorFound = false;
10839 for (OMPClause *C : Clauses) {
10840 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10841 for (Expr *RefExpr : LPC->varlist()) {
10842 SourceLocation ELoc;
10843 SourceRange ERange;
10844 Expr *SimpleRefExpr = RefExpr;
10845 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10846 if (ValueDecl *D = Res.first) {
10847 auto &&Info = Stack->isLoopControlVariable(D);
10848 if (!Info.first) {
10849 unsigned OMPVersion = S.getLangOpts().OpenMP;
10850 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10851 << getOpenMPDirectiveName(K, OMPVersion);
10852 ErrorFound = true;
10853 }
10854 }
10855 }
10856 }
10857 }
10858 return ErrorFound;
10859}
10860
10862 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10863 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10864 if (!AStmt)
10865 return StmtError();
10866
10867 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10868 // A list item may not appear in a lastprivate clause unless it is the
10869 // loop iteration variable of a loop that is associated with the construct.
10870 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10871 return StmtError();
10872
10873 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10874
10875 OMPLoopDirective::HelperExprs B;
10876 // In presence of clause 'collapse', it will define the nested loops number.
10877 unsigned NestedLoopCount = checkOpenMPLoop(
10878 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10879 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10880 if (NestedLoopCount == 0)
10881 return StmtError();
10882
10883 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10884 "omp loop exprs were not built");
10885
10886 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10887 NestedLoopCount, Clauses, AStmt, B);
10888}
10889
10891 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10892 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10893 if (!AStmt)
10894 return StmtError();
10895
10896 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10897 // A list item may not appear in a lastprivate clause unless it is the
10898 // loop iteration variable of a loop that is associated with the construct.
10899 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10900 return StmtError();
10901
10902 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10903
10904 OMPLoopDirective::HelperExprs B;
10905 // In presence of clause 'collapse', it will define the nested loops number.
10906 unsigned NestedLoopCount =
10907 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10908 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10909 VarsWithImplicitDSA, B);
10910 if (NestedLoopCount == 0)
10911 return StmtError();
10912
10913 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10914 "omp loop exprs were not built");
10915
10916 DSAStack->setParentTeamsRegionLoc(StartLoc);
10917
10919 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10920}
10921
10923 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10924 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10925 if (!AStmt)
10926 return StmtError();
10927
10928 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10929 // A list item may not appear in a lastprivate clause unless it is the
10930 // loop iteration variable of a loop that is associated with the construct.
10931 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10932 DSAStack))
10933 return StmtError();
10934
10935 CapturedStmt *CS =
10936 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10937
10938 OMPLoopDirective::HelperExprs B;
10939 // In presence of clause 'collapse', it will define the nested loops number.
10940 unsigned NestedLoopCount =
10941 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10942 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10943 VarsWithImplicitDSA, B);
10944 if (NestedLoopCount == 0)
10945 return StmtError();
10946
10947 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10948 "omp loop exprs were not built");
10949
10951 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10953}
10954
10956 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10957 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10958 if (!AStmt)
10959 return StmtError();
10960
10961 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10962 // A list item may not appear in a lastprivate clause unless it is the
10963 // loop iteration variable of a loop that is associated with the construct.
10964 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
10965 DSAStack))
10966 return StmtError();
10967
10968 CapturedStmt *CS =
10969 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
10970
10971 OMPLoopDirective::HelperExprs B;
10972 // In presence of clause 'collapse', it will define the nested loops number.
10973 unsigned NestedLoopCount =
10974 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10975 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10976 VarsWithImplicitDSA, B);
10977 if (NestedLoopCount == 0)
10978 return StmtError();
10979
10980 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10981 "omp loop exprs were not built");
10982
10984 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10985}
10986
10988 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10989 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10990 if (!AStmt)
10991 return StmtError();
10992
10993 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10994 // A list item may not appear in a lastprivate clause unless it is the
10995 // loop iteration variable of a loop that is associated with the construct.
10996 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
10997 DSAStack))
10998 return StmtError();
10999
11000 CapturedStmt *CS =
11001 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
11002
11003 OMPLoopDirective::HelperExprs B;
11004 // In presence of clause 'collapse', it will define the nested loops number.
11005 unsigned NestedLoopCount =
11006 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
11007 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11008 VarsWithImplicitDSA, B);
11009 if (NestedLoopCount == 0)
11010 return StmtError();
11011
11012 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11013 "omp loop exprs were not built");
11014
11016 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11017}
11018
11020 Stmt *AStmt,
11021 SourceLocation StartLoc,
11022 SourceLocation EndLoc) {
11023 if (!AStmt)
11024 return StmtError();
11025
11026 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11027
11028 SemaRef.setFunctionHasBranchProtectedScope();
11029
11030 // OpenMP [2.7.3, single Construct, Restrictions]
11031 // The copyprivate clause must not be used with the nowait clause.
11032 const OMPClause *Nowait = nullptr;
11033 const OMPClause *Copyprivate = nullptr;
11034 for (const OMPClause *Clause : Clauses) {
11035 if (Clause->getClauseKind() == OMPC_nowait)
11036 Nowait = Clause;
11037 else if (Clause->getClauseKind() == OMPC_copyprivate)
11038 Copyprivate = Clause;
11039 if (Copyprivate && Nowait) {
11040 Diag(Copyprivate->getBeginLoc(),
11041 diag::err_omp_single_copyprivate_with_nowait);
11042 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
11043 return StmtError();
11044 }
11045 }
11046
11047 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11048 AStmt);
11049}
11050
11052 SourceLocation StartLoc,
11053 SourceLocation EndLoc) {
11054 if (!AStmt)
11055 return StmtError();
11056
11057 SemaRef.setFunctionHasBranchProtectedScope();
11058
11059 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
11060}
11061
11063 Stmt *AStmt,
11064 SourceLocation StartLoc,
11065 SourceLocation EndLoc) {
11066 if (!AStmt)
11067 return StmtError();
11068
11069 SemaRef.setFunctionHasBranchProtectedScope();
11070
11071 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11072 AStmt);
11073}
11074
11076 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11077 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11078 if (!AStmt)
11079 return StmtError();
11080
11081 bool ErrorFound = false;
11082 llvm::APSInt Hint;
11083 SourceLocation HintLoc;
11084 bool DependentHint = false;
11085 for (const OMPClause *C : Clauses) {
11086 if (C->getClauseKind() == OMPC_hint) {
11087 if (!DirName.getName()) {
11088 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11089 ErrorFound = true;
11090 }
11091 Expr *E = cast<OMPHintClause>(C)->getHint();
11092 if (E->isTypeDependent() || E->isValueDependent() ||
11094 DependentHint = true;
11095 } else {
11097 HintLoc = C->getBeginLoc();
11098 }
11099 }
11100 }
11101 if (ErrorFound)
11102 return StmtError();
11103 const auto Pair = DSAStack->getCriticalWithHint(DirName);
11104 if (Pair.first && DirName.getName() && !DependentHint) {
11105 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11106 Diag(StartLoc, diag::err_omp_critical_with_hint);
11107 if (HintLoc.isValid())
11108 Diag(HintLoc, diag::note_omp_critical_hint_here)
11109 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
11110 else
11111 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11112 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11113 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
11114 << 1
11115 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
11116 /*Radix=*/10, /*Signed=*/false);
11117 } else {
11118 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11119 }
11120 }
11121 }
11122
11123 SemaRef.setFunctionHasBranchProtectedScope();
11124
11125 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
11126 EndLoc, Clauses, AStmt);
11127 if (!Pair.first && DirName.getName() && !DependentHint)
11128 DSAStack->addCriticalWithHint(Dir, Hint);
11129 return Dir;
11130}
11131
11133 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11134 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11135 if (!AStmt)
11136 return StmtError();
11137
11138 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
11139
11140 OMPLoopBasedDirective::HelperExprs B;
11141 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11142 // define the nested loops number.
11143 unsigned NestedLoopCount =
11144 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
11145 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
11146 VarsWithImplicitDSA, B);
11147 if (NestedLoopCount == 0)
11148 return StmtError();
11149
11150 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11151 return StmtError();
11152
11153 return OMPParallelForDirective::Create(
11154 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11155 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11156}
11157
11159 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11160 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11161 if (!AStmt)
11162 return StmtError();
11163
11164 CapturedStmt *CS =
11165 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
11166
11167 OMPLoopBasedDirective::HelperExprs B;
11168 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11169 // define the nested loops number.
11170 unsigned NestedLoopCount =
11171 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
11172 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
11173 VarsWithImplicitDSA, B);
11174 if (NestedLoopCount == 0)
11175 return StmtError();
11176
11177 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11178 return StmtError();
11179
11181 return StmtError();
11182
11183 return OMPParallelForSimdDirective::Create(
11184 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11185}
11186
11188 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11189 SourceLocation EndLoc) {
11190 if (!AStmt)
11191 return StmtError();
11192
11193 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
11194
11195 return OMPParallelMasterDirective::Create(
11196 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11197 DSAStack->getTaskgroupReductionRef());
11198}
11199
11201 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11202 SourceLocation EndLoc) {
11203 if (!AStmt)
11204 return StmtError();
11205
11206 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
11207
11208 return OMPParallelMaskedDirective::Create(
11209 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11210 DSAStack->getTaskgroupReductionRef());
11211}
11212
11214 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11215 SourceLocation EndLoc) {
11216 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
11217 return StmtError();
11218
11219 SemaRef.setFunctionHasBranchProtectedScope();
11220
11221 return OMPParallelSectionsDirective::Create(
11222 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11223 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11224}
11225
11226/// Find and diagnose mutually exclusive clause kinds.
11228 Sema &S, ArrayRef<OMPClause *> Clauses,
11229 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11230 const OMPClause *PrevClause = nullptr;
11231 bool ErrorFound = false;
11232 for (const OMPClause *C : Clauses) {
11233 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11234 if (!PrevClause) {
11235 PrevClause = C;
11236 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11237 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11238 << getOpenMPClauseNameForDiag(C->getClauseKind())
11239 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11240 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11241 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11242 ErrorFound = true;
11243 }
11244 }
11245 }
11246 return ErrorFound;
11247}
11248
11250 Stmt *AStmt,
11251 SourceLocation StartLoc,
11252 SourceLocation EndLoc) {
11253 if (!AStmt)
11254 return StmtError();
11255
11256 // OpenMP 5.0, 2.10.1 task Construct
11257 // If a detach clause appears on the directive, then a mergeable clause cannot
11258 // appear on the same directive.
11260 {OMPC_detach, OMPC_mergeable}))
11261 return StmtError();
11262
11263 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
11264
11265 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11266 AStmt, DSAStack->isCancelRegion());
11267}
11268
11270 SourceLocation EndLoc) {
11271 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11272}
11273
11275 SourceLocation EndLoc) {
11276 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11277}
11278
11280 SourceLocation StartLoc,
11281 SourceLocation EndLoc,
11282 bool InExContext) {
11283 const OMPAtClause *AtC =
11284 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11285
11286 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11287 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11288 return StmtError();
11289 }
11290
11291 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11292 const OMPSeverityClause *SeverityC =
11293 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11294 const OMPMessageClause *MessageC =
11295 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11296 std::optional<std::string> SL =
11297 MessageC ? MessageC->tryEvaluateString(getASTContext()) : std::nullopt;
11298
11299 if (MessageC && !SL)
11300 Diag(MessageC->getMessageString()->getBeginLoc(),
11301 diag::warn_clause_expected_string)
11302 << getOpenMPClauseNameForDiag(OMPC_message) << 1;
11303 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11304 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11305 << SL.value_or("WARNING");
11306 else
11307 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or("ERROR");
11308 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11309 return StmtError();
11310 }
11311
11312 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11313}
11314
11317 SourceLocation StartLoc,
11318 SourceLocation EndLoc) {
11319 const OMPNowaitClause *NowaitC =
11320 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11321 bool HasDependC =
11322 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11323 .empty();
11324 if (NowaitC && !HasDependC) {
11325 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11326 return StmtError();
11327 }
11328
11329 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11330 Clauses);
11331}
11332
11335 Stmt *AStmt, SourceLocation StartLoc,
11336 SourceLocation EndLoc) {
11337 if (!AStmt)
11338 return StmtError();
11339
11340 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11341
11342 SemaRef.setFunctionHasBranchProtectedScope();
11343
11344 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11345 Clauses, AStmt,
11346 DSAStack->getTaskgroupReductionRef());
11347}
11348
11350 SourceLocation StartLoc,
11351 SourceLocation EndLoc) {
11352 OMPFlushClause *FC = nullptr;
11353 OMPClause *OrderClause = nullptr;
11354 for (OMPClause *C : Clauses) {
11355 if (C->getClauseKind() == OMPC_flush)
11356 FC = cast<OMPFlushClause>(C);
11357 else
11358 OrderClause = C;
11359 }
11360 unsigned OMPVersion = getLangOpts().OpenMP;
11361 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11362 SourceLocation MemOrderLoc;
11363 for (const OMPClause *C : Clauses) {
11364 if (C->getClauseKind() == OMPC_acq_rel ||
11365 C->getClauseKind() == OMPC_acquire ||
11366 C->getClauseKind() == OMPC_release ||
11367 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11368 if (MemOrderKind != OMPC_unknown) {
11369 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11370 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11371 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11372 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11373 << getOpenMPClauseNameForDiag(MemOrderKind);
11374 } else {
11375 MemOrderKind = C->getClauseKind();
11376 MemOrderLoc = C->getBeginLoc();
11377 }
11378 }
11379 }
11380 if (FC && OrderClause) {
11381 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11382 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11383 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11384 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11385 return StmtError();
11386 }
11387 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11388}
11389
11391 SourceLocation StartLoc,
11392 SourceLocation EndLoc) {
11393 if (Clauses.empty()) {
11394 Diag(StartLoc, diag::err_omp_depobj_expected);
11395 return StmtError();
11396 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11397 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11398 return StmtError();
11399 }
11400 // Only depobj expression and another single clause is allowed.
11401 if (Clauses.size() > 2) {
11402 Diag(Clauses[2]->getBeginLoc(),
11403 diag::err_omp_depobj_single_clause_expected);
11404 return StmtError();
11405 } else if (Clauses.size() < 1) {
11406 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11407 return StmtError();
11408 }
11409 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11410}
11411
11413 SourceLocation StartLoc,
11414 SourceLocation EndLoc) {
11415 // Check that exactly one clause is specified.
11416 if (Clauses.size() != 1) {
11417 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11418 diag::err_omp_scan_single_clause_expected);
11419 return StmtError();
11420 }
11421 // Check that scan directive is used in the scope of the OpenMP loop body.
11422 if (Scope *S = DSAStack->getCurScope()) {
11423 Scope *ParentS = S->getParent();
11424 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11425 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11426 unsigned OMPVersion = getLangOpts().OpenMP;
11427 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11428 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11429 }
11430 }
11431 // Check that only one instance of scan directives is used in the same outer
11432 // region.
11433 if (DSAStack->doesParentHasScanDirective()) {
11434 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11435 Diag(DSAStack->getParentScanDirectiveLoc(),
11436 diag::note_omp_previous_directive)
11437 << "scan";
11438 return StmtError();
11439 }
11440 DSAStack->setParentHasScanDirective(StartLoc);
11441 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11442}
11443
11446 Stmt *AStmt, SourceLocation StartLoc,
11447 SourceLocation EndLoc) {
11448 const OMPClause *DependFound = nullptr;
11449 const OMPClause *DependSourceClause = nullptr;
11450 const OMPClause *DependSinkClause = nullptr;
11451 const OMPClause *DoacrossFound = nullptr;
11452 const OMPClause *DoacrossSourceClause = nullptr;
11453 const OMPClause *DoacrossSinkClause = nullptr;
11454 bool ErrorFound = false;
11455 const OMPThreadsClause *TC = nullptr;
11456 const OMPSIMDClause *SC = nullptr;
11457 for (const OMPClause *C : Clauses) {
11458 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11459 auto DC = dyn_cast<OMPDependClause>(C);
11460 if (DC || DOC) {
11461 DependFound = DC ? C : nullptr;
11462 DoacrossFound = DOC ? C : nullptr;
11463 OMPDoacrossKind ODK;
11464 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11465 (DOC && (ODK.isSource(DOC)))) {
11466 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11467 unsigned OMPVersion = getLangOpts().OpenMP;
11468 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11469 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11470 << getOpenMPClauseNameForDiag(DC ? OMPC_depend : OMPC_doacross)
11471 << 2;
11472 ErrorFound = true;
11473 } else {
11474 if (DC)
11475 DependSourceClause = C;
11476 else
11477 DoacrossSourceClause = C;
11478 }
11479 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11480 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11481 << (DC ? "depend" : "doacross") << 0;
11482 ErrorFound = true;
11483 }
11484 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11485 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11486 if (DependSourceClause || DoacrossSourceClause) {
11487 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11488 << (DC ? "depend" : "doacross") << 1;
11489 ErrorFound = true;
11490 }
11491 if (DC)
11492 DependSinkClause = C;
11493 else
11494 DoacrossSinkClause = C;
11495 }
11496 } else if (C->getClauseKind() == OMPC_threads) {
11498 } else if (C->getClauseKind() == OMPC_simd) {
11499 SC = cast<OMPSIMDClause>(C);
11500 }
11501 }
11502 if (!ErrorFound && !SC &&
11503 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11504 // OpenMP [2.8.1,simd Construct, Restrictions]
11505 // An ordered construct with the simd clause is the only OpenMP construct
11506 // that can appear in the simd region.
11507 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11508 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11509 ErrorFound = true;
11510 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11511 SourceLocation Loc =
11512 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11513 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11514 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend : OMPC_doacross)
11516 : SC->getClauseKind());
11517 ErrorFound = true;
11518 } else if ((DependFound || DoacrossFound) &&
11519 !DSAStack->getParentOrderedRegionParam().first) {
11520 SourceLocation Loc =
11521 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11522 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11523 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend
11524 : OMPC_doacross);
11525 ErrorFound = true;
11526 } else if (TC || Clauses.empty()) {
11527 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11528 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11529 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11530 << (TC != nullptr);
11531 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11532 ErrorFound = true;
11533 }
11534 }
11535 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11536 return StmtError();
11537
11538 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11539 // During execution of an iteration of a worksharing-loop or a loop nest
11540 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11541 // must not execute more than one ordered region corresponding to an ordered
11542 // construct without a depend clause.
11543 if (!DependFound && !DoacrossFound) {
11544 if (DSAStack->doesParentHasOrderedDirective()) {
11545 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11546 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11547 diag::note_omp_previous_directive)
11548 << "ordered";
11549 return StmtError();
11550 }
11551 DSAStack->setParentHasOrderedDirective(StartLoc);
11552 }
11553
11554 if (AStmt) {
11555 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11556
11557 SemaRef.setFunctionHasBranchProtectedScope();
11558 }
11559
11560 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11561 AStmt);
11562}
11563
11564namespace {
11565/// Helper class for checking expression in 'omp atomic [update]'
11566/// construct.
11567class OpenMPAtomicUpdateChecker {
11568 /// Error results for atomic update expressions.
11569 enum ExprAnalysisErrorCode {
11570 /// A statement is not an expression statement.
11571 NotAnExpression,
11572 /// Expression is not builtin binary or unary operation.
11573 NotABinaryOrUnaryExpression,
11574 /// Unary operation is not post-/pre- increment/decrement operation.
11575 NotAnUnaryIncDecExpression,
11576 /// An expression is not of scalar type.
11577 NotAScalarType,
11578 /// A binary operation is not an assignment operation.
11579 NotAnAssignmentOp,
11580 /// RHS part of the binary operation is not a binary expression.
11581 NotABinaryExpression,
11582 /// RHS part is not additive/multiplicative/shift/bitwise binary
11583 /// expression.
11584 NotABinaryOperator,
11585 /// RHS binary operation does not have reference to the updated LHS
11586 /// part.
11587 NotAnUpdateExpression,
11588 /// An expression contains semantical error not related to
11589 /// 'omp atomic [update]'
11590 NotAValidExpression,
11591 /// No errors is found.
11592 NoError
11593 };
11594 /// Reference to Sema.
11595 Sema &SemaRef;
11596 /// A location for note diagnostics (when error is found).
11597 SourceLocation NoteLoc;
11598 /// 'x' lvalue part of the source atomic expression.
11599 Expr *X;
11600 /// 'expr' rvalue part of the source atomic expression.
11601 Expr *E;
11602 /// Helper expression of the form
11603 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11604 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11605 Expr *UpdateExpr;
11606 /// Is 'x' a LHS in a RHS part of full update expression. It is
11607 /// important for non-associative operations.
11608 bool IsXLHSInRHSPart;
11610 SourceLocation OpLoc;
11611 /// true if the source expression is a postfix unary operation, false
11612 /// if it is a prefix unary operation.
11613 bool IsPostfixUpdate;
11614
11615public:
11616 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11617 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11618 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11619 /// Check specified statement that it is suitable for 'atomic update'
11620 /// constructs and extract 'x', 'expr' and Operation from the original
11621 /// expression. If DiagId and NoteId == 0, then only check is performed
11622 /// without error notification.
11623 /// \param DiagId Diagnostic which should be emitted if error is found.
11624 /// \param NoteId Diagnostic note for the main error message.
11625 /// \return true if statement is not an update expression, false otherwise.
11626 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11627 /// Return the 'x' lvalue part of the source atomic expression.
11628 Expr *getX() const { return X; }
11629 /// Return the 'expr' rvalue part of the source atomic expression.
11630 Expr *getExpr() const { return E; }
11631 /// Return the update expression used in calculation of the updated
11632 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11633 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11634 Expr *getUpdateExpr() const { return UpdateExpr; }
11635 /// Return true if 'x' is LHS in RHS part of full update expression,
11636 /// false otherwise.
11637 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11638
11639 /// true if the source expression is a postfix unary operation, false
11640 /// if it is a prefix unary operation.
11641 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11642
11643private:
11644 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11645 unsigned NoteId = 0);
11646};
11647
11648bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11649 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11650 ExprAnalysisErrorCode ErrorFound = NoError;
11651 SourceLocation ErrorLoc, NoteLoc;
11652 SourceRange ErrorRange, NoteRange;
11653 // Allowed constructs are:
11654 // x = x binop expr;
11655 // x = expr binop x;
11656 if (AtomicBinOp->getOpcode() == BO_Assign) {
11657 X = AtomicBinOp->getLHS();
11658 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11659 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11660 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11661 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11662 AtomicInnerBinOp->isBitwiseOp()) {
11663 Op = AtomicInnerBinOp->getOpcode();
11664 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11665 Expr *LHS = AtomicInnerBinOp->getLHS();
11666 Expr *RHS = AtomicInnerBinOp->getRHS();
11667 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11668 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11669 /*Canonical=*/true);
11670 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11671 /*Canonical=*/true);
11672 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11673 /*Canonical=*/true);
11674 if (XId == LHSId) {
11675 E = RHS;
11676 IsXLHSInRHSPart = true;
11677 } else if (XId == RHSId) {
11678 E = LHS;
11679 IsXLHSInRHSPart = false;
11680 } else {
11681 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11682 ErrorRange = AtomicInnerBinOp->getSourceRange();
11683 NoteLoc = X->getExprLoc();
11684 NoteRange = X->getSourceRange();
11685 ErrorFound = NotAnUpdateExpression;
11686 }
11687 } else {
11688 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11689 ErrorRange = AtomicInnerBinOp->getSourceRange();
11690 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11691 NoteRange = SourceRange(NoteLoc, NoteLoc);
11692 ErrorFound = NotABinaryOperator;
11693 }
11694 } else {
11695 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11696 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11697 ErrorFound = NotABinaryExpression;
11698 }
11699 } else {
11700 ErrorLoc = AtomicBinOp->getExprLoc();
11701 ErrorRange = AtomicBinOp->getSourceRange();
11702 NoteLoc = AtomicBinOp->getOperatorLoc();
11703 NoteRange = SourceRange(NoteLoc, NoteLoc);
11704 ErrorFound = NotAnAssignmentOp;
11705 }
11706 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11707 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11708 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11709 return true;
11710 }
11711 if (SemaRef.CurContext->isDependentContext())
11712 E = X = UpdateExpr = nullptr;
11713 return ErrorFound != NoError;
11714}
11715
11716bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11717 unsigned NoteId) {
11718 ExprAnalysisErrorCode ErrorFound = NoError;
11719 SourceLocation ErrorLoc, NoteLoc;
11720 SourceRange ErrorRange, NoteRange;
11721 // Allowed constructs are:
11722 // x++;
11723 // x--;
11724 // ++x;
11725 // --x;
11726 // x binop= expr;
11727 // x = x binop expr;
11728 // x = expr binop x;
11729 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11730 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11731 if (AtomicBody->getType()->isScalarType() ||
11732 AtomicBody->isInstantiationDependent()) {
11733 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11734 AtomicBody->IgnoreParenImpCasts())) {
11735 // Check for Compound Assignment Operation
11737 AtomicCompAssignOp->getOpcode());
11738 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11739 E = AtomicCompAssignOp->getRHS();
11740 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11741 IsXLHSInRHSPart = true;
11742 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11743 AtomicBody->IgnoreParenImpCasts())) {
11744 // Check for Binary Operation
11745 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11746 return true;
11747 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11748 AtomicBody->IgnoreParenImpCasts())) {
11749 // Check for Unary Operation
11750 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11751 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11752 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11753 OpLoc = AtomicUnaryOp->getOperatorLoc();
11754 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11755 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11756 IsXLHSInRHSPart = true;
11757 } else {
11758 ErrorFound = NotAnUnaryIncDecExpression;
11759 ErrorLoc = AtomicUnaryOp->getExprLoc();
11760 ErrorRange = AtomicUnaryOp->getSourceRange();
11761 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11762 NoteRange = SourceRange(NoteLoc, NoteLoc);
11763 }
11764 } else if (!AtomicBody->isInstantiationDependent()) {
11765 ErrorFound = NotABinaryOrUnaryExpression;
11766 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11767 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11768 } else if (AtomicBody->containsErrors()) {
11769 ErrorFound = NotAValidExpression;
11770 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11771 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11772 }
11773 } else {
11774 ErrorFound = NotAScalarType;
11775 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11776 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11777 }
11778 } else {
11779 ErrorFound = NotAnExpression;
11780 NoteLoc = ErrorLoc = S->getBeginLoc();
11781 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11782 }
11783 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11784 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11785 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11786 return true;
11787 }
11788 if (SemaRef.CurContext->isDependentContext())
11789 E = X = UpdateExpr = nullptr;
11790 if (ErrorFound == NoError && E && X) {
11791 // Build an update expression of form 'OpaqueValueExpr(x) binop
11792 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11793 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11794 auto *OVEX = new (SemaRef.getASTContext())
11795 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11796 auto *OVEExpr = new (SemaRef.getASTContext())
11799 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11800 IsXLHSInRHSPart ? OVEExpr : OVEX);
11801 if (Update.isInvalid())
11802 return true;
11803 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11805 if (Update.isInvalid())
11806 return true;
11807 UpdateExpr = Update.get();
11808 }
11809 return ErrorFound != NoError;
11810}
11811
11812/// Get the node id of the fixed point of an expression \a S.
11813llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11814 llvm::FoldingSetNodeID Id;
11815 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11816 return Id;
11817}
11818
11819/// Check if two expressions are same.
11820bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11821 const Expr *RHS) {
11822 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11823}
11824
11825class OpenMPAtomicCompareChecker {
11826public:
11827 /// All kinds of errors that can occur in `atomic compare`
11828 enum ErrorTy {
11829 /// Empty compound statement.
11830 NoStmt = 0,
11831 /// More than one statement in a compound statement.
11832 MoreThanOneStmt,
11833 /// Not an assignment binary operator.
11834 NotAnAssignment,
11835 /// Not a conditional operator.
11836 NotCondOp,
11837 /// Wrong false expr. According to the spec, 'x' should be at the false
11838 /// expression of a conditional expression.
11839 WrongFalseExpr,
11840 /// The condition of a conditional expression is not a binary operator.
11841 NotABinaryOp,
11842 /// Invalid binary operator (not <, >, or ==).
11843 InvalidBinaryOp,
11844 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11845 InvalidComparison,
11846 /// X is not a lvalue.
11847 XNotLValue,
11848 /// Not a scalar.
11849 NotScalar,
11850 /// Not an integer.
11851 NotInteger,
11852 /// 'else' statement is not expected.
11853 UnexpectedElse,
11854 /// Not an equality operator.
11855 NotEQ,
11856 /// Invalid assignment (not v == x).
11857 InvalidAssignment,
11858 /// Not if statement
11859 NotIfStmt,
11860 /// More than two statements in a compound statement.
11861 MoreThanTwoStmts,
11862 /// Not a compound statement.
11863 NotCompoundStmt,
11864 /// No else statement.
11865 NoElse,
11866 /// Not 'if (r)'.
11867 InvalidCondition,
11868 /// No error.
11869 NoError,
11870 };
11871
11872 struct ErrorInfoTy {
11873 ErrorTy Error;
11874 SourceLocation ErrorLoc;
11875 SourceRange ErrorRange;
11876 SourceLocation NoteLoc;
11877 SourceRange NoteRange;
11878 };
11879
11880 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11881
11882 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11883 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11884
11885 Expr *getX() const { return X; }
11886 Expr *getE() const { return E; }
11887 Expr *getD() const { return D; }
11888 Expr *getCond() const { return C; }
11889 bool isXBinopExpr() const { return IsXBinopExpr; }
11890
11891protected:
11892 /// Reference to ASTContext
11893 ASTContext &ContextRef;
11894 /// 'x' lvalue part of the source atomic expression.
11895 Expr *X = nullptr;
11896 /// 'expr' or 'e' rvalue part of the source atomic expression.
11897 Expr *E = nullptr;
11898 /// 'd' rvalue part of the source atomic expression.
11899 Expr *D = nullptr;
11900 /// 'cond' part of the source atomic expression. It is in one of the following
11901 /// forms:
11902 /// expr ordop x
11903 /// x ordop expr
11904 /// x == e
11905 /// e == x
11906 Expr *C = nullptr;
11907 /// True if the cond expr is in the form of 'x ordop expr'.
11908 bool IsXBinopExpr = true;
11909
11910 /// Check if it is a valid conditional update statement (cond-update-stmt).
11911 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11912
11913 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11914 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11915
11916 /// Check if all captured values have right type.
11917 bool checkType(ErrorInfoTy &ErrorInfo) const;
11918
11919 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11920 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11921 if (E->isInstantiationDependent())
11922 return true;
11923
11924 if (ShouldBeLValue && !E->isLValue()) {
11925 ErrorInfo.Error = ErrorTy::XNotLValue;
11926 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11927 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11928 return false;
11929 }
11930
11931 QualType QTy = E->getType();
11932 if (!QTy->isScalarType()) {
11933 ErrorInfo.Error = ErrorTy::NotScalar;
11934 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11935 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11936 return false;
11937 }
11938 if (ShouldBeInteger && !QTy->isIntegerType()) {
11939 ErrorInfo.Error = ErrorTy::NotInteger;
11940 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11941 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11942 return false;
11943 }
11944
11945 return true;
11946 }
11947};
11948
11949bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11950 ErrorInfoTy &ErrorInfo) {
11951 auto *Then = S->getThen();
11952 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11953 if (CS->body_empty()) {
11954 ErrorInfo.Error = ErrorTy::NoStmt;
11955 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11956 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11957 return false;
11958 }
11959 if (CS->size() > 1) {
11960 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11961 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11962 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11963 return false;
11964 }
11965 Then = CS->body_front();
11966 }
11967
11968 auto *BO = dyn_cast<BinaryOperator>(Then);
11969 if (!BO) {
11970 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11971 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11972 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11973 return false;
11974 }
11975 if (BO->getOpcode() != BO_Assign) {
11976 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11977 ErrorInfo.ErrorLoc = BO->getExprLoc();
11978 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11979 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11980 return false;
11981 }
11982
11983 X = BO->getLHS();
11984
11985 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11986 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
11987 Expr *LHS = nullptr;
11988 Expr *RHS = nullptr;
11989 if (Cond) {
11990 LHS = Cond->getLHS();
11991 RHS = Cond->getRHS();
11992 } else if (Call) {
11993 LHS = Call->getArg(0);
11994 RHS = Call->getArg(1);
11995 } else {
11996 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11997 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11998 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11999 return false;
12000 }
12001
12002 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12003 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12004 C = S->getCond();
12005 D = BO->getRHS();
12006 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12007 E = RHS;
12008 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12009 E = LHS;
12010 } else {
12011 ErrorInfo.Error = ErrorTy::InvalidComparison;
12012 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12013 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12014 S->getCond()->getSourceRange();
12015 return false;
12016 }
12017 } else if ((Cond &&
12018 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12019 (Call &&
12020 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12021 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12022 E = BO->getRHS();
12023 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12024 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12025 C = S->getCond();
12026 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12027 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12028 C = S->getCond();
12029 IsXBinopExpr = false;
12030 } else {
12031 ErrorInfo.Error = ErrorTy::InvalidComparison;
12032 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12033 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12034 S->getCond()->getSourceRange();
12035 return false;
12036 }
12037 } else {
12038 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12039 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12040 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12041 return false;
12042 }
12043
12044 if (S->getElse()) {
12045 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12046 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12047 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12048 return false;
12049 }
12050
12051 return true;
12052}
12053
12054bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12055 ErrorInfoTy &ErrorInfo) {
12056 auto *BO = dyn_cast<BinaryOperator>(S);
12057 if (!BO) {
12058 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12059 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12060 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12061 return false;
12062 }
12063 if (BO->getOpcode() != BO_Assign) {
12064 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12065 ErrorInfo.ErrorLoc = BO->getExprLoc();
12066 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12067 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12068 return false;
12069 }
12070
12071 X = BO->getLHS();
12072
12073 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12074 if (!CO) {
12075 ErrorInfo.Error = ErrorTy::NotCondOp;
12076 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12077 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12078 return false;
12079 }
12080
12081 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
12082 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12083 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12084 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12085 CO->getFalseExpr()->getSourceRange();
12086 return false;
12087 }
12088
12089 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
12090 auto *Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
12091 Expr *LHS = nullptr;
12092 Expr *RHS = nullptr;
12093 if (Cond) {
12094 LHS = Cond->getLHS();
12095 RHS = Cond->getRHS();
12096 } else if (Call) {
12097 LHS = Call->getArg(0);
12098 RHS = Call->getArg(1);
12099 } else {
12100 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12101 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12102 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12103 CO->getCond()->getSourceRange();
12104 return false;
12105 }
12106
12107 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12108 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12109 C = CO->getCond();
12110 D = CO->getTrueExpr();
12111 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12112 E = RHS;
12113 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12114 E = LHS;
12115 } else {
12116 ErrorInfo.Error = ErrorTy::InvalidComparison;
12117 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12118 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12119 CO->getCond()->getSourceRange();
12120 return false;
12121 }
12122 } else if ((Cond &&
12123 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12124 (Call &&
12125 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12126 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12127
12128 E = CO->getTrueExpr();
12129 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12130 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12131 C = CO->getCond();
12132 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12133 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12134 C = CO->getCond();
12135 IsXBinopExpr = false;
12136 } else {
12137 ErrorInfo.Error = ErrorTy::InvalidComparison;
12138 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12139 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12140 CO->getCond()->getSourceRange();
12141 return false;
12142 }
12143 } else {
12144 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12145 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12146 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12147 CO->getCond()->getSourceRange();
12148 return false;
12149 }
12150
12151 return true;
12152}
12153
12154bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12155 // 'x' and 'e' cannot be nullptr
12156 assert(X && E && "X and E cannot be nullptr");
12157
12158 if (!CheckValue(X, ErrorInfo, true))
12159 return false;
12160
12161 if (!CheckValue(E, ErrorInfo, false))
12162 return false;
12163
12164 if (D && !CheckValue(D, ErrorInfo, false))
12165 return false;
12166
12167 return true;
12168}
12169
12170bool OpenMPAtomicCompareChecker::checkStmt(
12171 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12172 auto *CS = dyn_cast<CompoundStmt>(S);
12173 if (CS) {
12174 if (CS->body_empty()) {
12175 ErrorInfo.Error = ErrorTy::NoStmt;
12176 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12177 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12178 return false;
12179 }
12180
12181 if (CS->size() != 1) {
12182 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12183 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12184 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12185 return false;
12186 }
12187 S = CS->body_front();
12188 }
12189
12190 auto Res = false;
12191
12192 if (auto *IS = dyn_cast<IfStmt>(S)) {
12193 // Check if the statement is in one of the following forms
12194 // (cond-update-stmt):
12195 // if (expr ordop x) { x = expr; }
12196 // if (x ordop expr) { x = expr; }
12197 // if (x == e) { x = d; }
12198 Res = checkCondUpdateStmt(IS, ErrorInfo);
12199 } else {
12200 // Check if the statement is in one of the following forms (cond-expr-stmt):
12201 // x = expr ordop x ? expr : x;
12202 // x = x ordop expr ? expr : x;
12203 // x = x == e ? d : x;
12204 Res = checkCondExprStmt(S, ErrorInfo);
12205 }
12206
12207 if (!Res)
12208 return false;
12209
12210 return checkType(ErrorInfo);
12211}
12212
12213class OpenMPAtomicCompareCaptureChecker final
12214 : public OpenMPAtomicCompareChecker {
12215public:
12216 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12217
12218 Expr *getV() const { return V; }
12219 Expr *getR() const { return R; }
12220 bool isFailOnly() const { return IsFailOnly; }
12221 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12222
12223 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12224 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12225
12226private:
12227 bool checkType(ErrorInfoTy &ErrorInfo);
12228
12229 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12230 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12231 // spec p.p. 82:
12232 // (1) { v = x; cond-update-stmt }
12233 // (2) { cond-update-stmt v = x; }
12234 // (3) if(x == e) { x = d; } else { v = x; }
12235 // (4) { r = x == e; if(r) { x = d; } }
12236 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12237
12238 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12239 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12240
12241 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12242 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12243 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12244
12245 /// 'v' lvalue part of the source atomic expression.
12246 Expr *V = nullptr;
12247 /// 'r' lvalue part of the source atomic expression.
12248 Expr *R = nullptr;
12249 /// If 'v' is only updated when the comparison fails.
12250 bool IsFailOnly = false;
12251 /// If original value of 'x' must be stored in 'v', not an updated one.
12252 bool IsPostfixUpdate = false;
12253};
12254
12255bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12256 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12257 return false;
12258
12259 if (V && !CheckValue(V, ErrorInfo, true))
12260 return false;
12261
12262 if (R && !CheckValue(R, ErrorInfo, true, true))
12263 return false;
12264
12265 return true;
12266}
12267
12268bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12269 ErrorInfoTy &ErrorInfo) {
12270 IsFailOnly = true;
12271
12272 auto *Then = S->getThen();
12273 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12274 if (CS->body_empty()) {
12275 ErrorInfo.Error = ErrorTy::NoStmt;
12276 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12277 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12278 return false;
12279 }
12280 if (CS->size() > 1) {
12281 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12282 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12283 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12284 return false;
12285 }
12286 Then = CS->body_front();
12287 }
12288
12289 auto *BO = dyn_cast<BinaryOperator>(Then);
12290 if (!BO) {
12291 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12292 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12293 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12294 return false;
12295 }
12296 if (BO->getOpcode() != BO_Assign) {
12297 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12298 ErrorInfo.ErrorLoc = BO->getExprLoc();
12299 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12300 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12301 return false;
12302 }
12303
12304 X = BO->getLHS();
12305 D = BO->getRHS();
12306
12307 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12308 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12309 Expr *LHS = nullptr;
12310 Expr *RHS = nullptr;
12311 if (Cond) {
12312 LHS = Cond->getLHS();
12313 RHS = Cond->getRHS();
12314 } else if (Call) {
12315 LHS = Call->getArg(0);
12316 RHS = Call->getArg(1);
12317 } else {
12318 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12319 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12320 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12321 return false;
12322 }
12323 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12324 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12325 ErrorInfo.Error = ErrorTy::NotEQ;
12326 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12327 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12328 return false;
12329 }
12330
12331 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12332 E = RHS;
12333 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12334 E = LHS;
12335 } else {
12336 ErrorInfo.Error = ErrorTy::InvalidComparison;
12337 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12338 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12339 return false;
12340 }
12341
12342 C = S->getCond();
12343
12344 if (!S->getElse()) {
12345 ErrorInfo.Error = ErrorTy::NoElse;
12346 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12347 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12348 return false;
12349 }
12350
12351 auto *Else = S->getElse();
12352 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12353 if (CS->body_empty()) {
12354 ErrorInfo.Error = ErrorTy::NoStmt;
12355 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12356 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12357 return false;
12358 }
12359 if (CS->size() > 1) {
12360 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12361 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12362 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12363 return false;
12364 }
12365 Else = CS->body_front();
12366 }
12367
12368 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12369 if (!ElseBO) {
12370 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12371 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12372 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12373 return false;
12374 }
12375 if (ElseBO->getOpcode() != BO_Assign) {
12376 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12377 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12378 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12379 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12380 return false;
12381 }
12382
12383 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12384 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12385 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12386 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12387 ElseBO->getRHS()->getSourceRange();
12388 return false;
12389 }
12390
12391 V = ElseBO->getLHS();
12392
12393 return checkType(ErrorInfo);
12394}
12395
12396bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12397 ErrorInfoTy &ErrorInfo) {
12398 // We don't check here as they should be already done before call this
12399 // function.
12400 auto *CS = cast<CompoundStmt>(S);
12401 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12402 auto *S1 = cast<BinaryOperator>(CS->body_front());
12403 auto *S2 = cast<IfStmt>(CS->body_back());
12404 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12405
12406 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12407 ErrorInfo.Error = ErrorTy::InvalidCondition;
12408 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12409 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12410 return false;
12411 }
12412
12413 R = S1->getLHS();
12414
12415 auto *Then = S2->getThen();
12416 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12417 if (ThenCS->body_empty()) {
12418 ErrorInfo.Error = ErrorTy::NoStmt;
12419 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12420 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12421 return false;
12422 }
12423 if (ThenCS->size() > 1) {
12424 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12425 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12426 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12427 return false;
12428 }
12429 Then = ThenCS->body_front();
12430 }
12431
12432 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12433 if (!ThenBO) {
12434 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12435 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12436 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12437 return false;
12438 }
12439 if (ThenBO->getOpcode() != BO_Assign) {
12440 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12441 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12442 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12443 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12444 return false;
12445 }
12446
12447 X = ThenBO->getLHS();
12448 D = ThenBO->getRHS();
12449
12450 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12451 if (BO->getOpcode() != BO_EQ) {
12452 ErrorInfo.Error = ErrorTy::NotEQ;
12453 ErrorInfo.ErrorLoc = BO->getExprLoc();
12454 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12455 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12456 return false;
12457 }
12458
12459 C = BO;
12460
12461 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12462 E = BO->getRHS();
12463 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12464 E = BO->getLHS();
12465 } else {
12466 ErrorInfo.Error = ErrorTy::InvalidComparison;
12467 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12468 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12469 return false;
12470 }
12471
12472 if (S2->getElse()) {
12473 IsFailOnly = true;
12474
12475 auto *Else = S2->getElse();
12476 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12477 if (ElseCS->body_empty()) {
12478 ErrorInfo.Error = ErrorTy::NoStmt;
12479 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12480 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12481 return false;
12482 }
12483 if (ElseCS->size() > 1) {
12484 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12485 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12486 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12487 return false;
12488 }
12489 Else = ElseCS->body_front();
12490 }
12491
12492 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12493 if (!ElseBO) {
12494 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12495 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12496 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12497 return false;
12498 }
12499 if (ElseBO->getOpcode() != BO_Assign) {
12500 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12501 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12502 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12503 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12504 return false;
12505 }
12506 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12507 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12508 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12509 ErrorInfo.NoteLoc = X->getExprLoc();
12510 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12511 ErrorInfo.NoteRange = X->getSourceRange();
12512 return false;
12513 }
12514
12515 V = ElseBO->getLHS();
12516 }
12517
12518 return checkType(ErrorInfo);
12519}
12520
12521bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12522 ErrorInfoTy &ErrorInfo) {
12523 // if(x == e) { x = d; } else { v = x; }
12524 if (auto *IS = dyn_cast<IfStmt>(S))
12525 return checkForm3(IS, ErrorInfo);
12526
12527 auto *CS = dyn_cast<CompoundStmt>(S);
12528 if (!CS) {
12529 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12530 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12531 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12532 return false;
12533 }
12534 if (CS->body_empty()) {
12535 ErrorInfo.Error = ErrorTy::NoStmt;
12536 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12537 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12538 return false;
12539 }
12540
12541 // { if(x == e) { x = d; } else { v = x; } }
12542 if (CS->size() == 1) {
12543 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12544 if (!IS) {
12545 ErrorInfo.Error = ErrorTy::NotIfStmt;
12546 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12547 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12548 CS->body_front()->getSourceRange();
12549 return false;
12550 }
12551
12552 return checkForm3(IS, ErrorInfo);
12553 } else if (CS->size() == 2) {
12554 auto *S1 = CS->body_front();
12555 auto *S2 = CS->body_back();
12556
12557 Stmt *UpdateStmt = nullptr;
12558 Stmt *CondUpdateStmt = nullptr;
12559 Stmt *CondExprStmt = nullptr;
12560
12561 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12562 // It could be one of the following cases:
12563 // { v = x; cond-update-stmt }
12564 // { v = x; cond-expr-stmt }
12565 // { cond-expr-stmt; v = x; }
12566 // form 45
12567 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12568 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12569 // check if form 45
12570 if (isa<IfStmt>(S2))
12571 return checkForm45(CS, ErrorInfo);
12572 // { cond-expr-stmt; v = x; }
12573 CondExprStmt = S1;
12574 UpdateStmt = S2;
12575 } else {
12576 IsPostfixUpdate = true;
12577 UpdateStmt = S1;
12578 if (isa<IfStmt>(S2)) {
12579 // { v = x; cond-update-stmt }
12580 CondUpdateStmt = S2;
12581 } else {
12582 // { v = x; cond-expr-stmt }
12583 CondExprStmt = S2;
12584 }
12585 }
12586 } else {
12587 // { cond-update-stmt v = x; }
12588 UpdateStmt = S2;
12589 CondUpdateStmt = S1;
12590 }
12591
12592 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12593 auto *IS = dyn_cast<IfStmt>(CUS);
12594 if (!IS) {
12595 ErrorInfo.Error = ErrorTy::NotIfStmt;
12596 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12597 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12598 return false;
12599 }
12600
12601 return checkCondUpdateStmt(IS, ErrorInfo);
12602 };
12603
12604 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12605 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12606 auto *BO = dyn_cast<BinaryOperator>(US);
12607 if (!BO) {
12608 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12609 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12610 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12611 return false;
12612 }
12613 if (BO->getOpcode() != BO_Assign) {
12614 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12615 ErrorInfo.ErrorLoc = BO->getExprLoc();
12616 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12617 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12618 return false;
12619 }
12620 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12621 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12622 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12623 ErrorInfo.NoteLoc = this->X->getExprLoc();
12624 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12625 ErrorInfo.NoteRange = this->X->getSourceRange();
12626 return false;
12627 }
12628
12629 this->V = BO->getLHS();
12630
12631 return true;
12632 };
12633
12634 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12635 return false;
12636 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12637 return false;
12638 if (!CheckUpdateStmt(UpdateStmt))
12639 return false;
12640 } else {
12641 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12642 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12643 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12644 return false;
12645 }
12646
12647 return checkType(ErrorInfo);
12648}
12649} // namespace
12650
12652 Stmt *AStmt,
12653 SourceLocation StartLoc,
12654 SourceLocation EndLoc) {
12655 ASTContext &Context = getASTContext();
12656 unsigned OMPVersion = getLangOpts().OpenMP;
12657 // Register location of the first atomic directive.
12658 DSAStack->addAtomicDirectiveLoc(StartLoc);
12659 if (!AStmt)
12660 return StmtError();
12661
12662 // 1.2.2 OpenMP Language Terminology
12663 // Structured block - An executable statement with a single entry at the
12664 // top and a single exit at the bottom.
12665 // The point of exit cannot be a branch out of the structured block.
12666 // longjmp() and throw() must not violate the entry/exit criteria.
12667 OpenMPClauseKind AtomicKind = OMPC_unknown;
12668 SourceLocation AtomicKindLoc;
12669 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12670 SourceLocation MemOrderLoc;
12671 bool MutexClauseEncountered = false;
12672 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12673 for (const OMPClause *C : Clauses) {
12674 switch (C->getClauseKind()) {
12675 case OMPC_read:
12676 case OMPC_write:
12677 case OMPC_update:
12678 MutexClauseEncountered = true;
12679 [[fallthrough]];
12680 case OMPC_capture:
12681 case OMPC_compare: {
12682 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12683 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12684 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12685 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12686 << getOpenMPClauseNameForDiag(AtomicKind);
12687 } else {
12688 AtomicKind = C->getClauseKind();
12689 AtomicKindLoc = C->getBeginLoc();
12690 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12691 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12692 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12693 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12694 << getOpenMPClauseNameForDiag(AtomicKind);
12695 }
12696 }
12697 break;
12698 }
12699 case OMPC_weak:
12700 case OMPC_fail: {
12701 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12702 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12703 << getOpenMPClauseNameForDiag(C->getClauseKind())
12704 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12705 return StmtError();
12706 }
12707 break;
12708 }
12709 case OMPC_seq_cst:
12710 case OMPC_acq_rel:
12711 case OMPC_acquire:
12712 case OMPC_release:
12713 case OMPC_relaxed: {
12714 if (MemOrderKind != OMPC_unknown) {
12715 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12716 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12717 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12718 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12719 << getOpenMPClauseNameForDiag(MemOrderKind);
12720 } else {
12721 MemOrderKind = C->getClauseKind();
12722 MemOrderLoc = C->getBeginLoc();
12723 }
12724 break;
12725 }
12726 // The following clauses are allowed, but we don't need to do anything here.
12727 case OMPC_hint:
12728 break;
12729 default:
12730 llvm_unreachable("unknown clause is encountered");
12731 }
12732 }
12733 bool IsCompareCapture = false;
12734 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12735 EncounteredAtomicKinds.contains(OMPC_capture)) {
12736 IsCompareCapture = true;
12737 AtomicKind = OMPC_compare;
12738 }
12739 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12740 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12741 // release.
12742 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12743 // acquire.
12744 // If atomic-clause is update or not present then memory-order-clause must not
12745 // be acq_rel or acquire.
12746 if ((AtomicKind == OMPC_read &&
12747 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12748 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12749 AtomicKind == OMPC_unknown) &&
12750 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12751 SourceLocation Loc = AtomicKindLoc;
12752 if (AtomicKind == OMPC_unknown)
12753 Loc = StartLoc;
12754 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12755 << getOpenMPClauseNameForDiag(AtomicKind)
12756 << (AtomicKind == OMPC_unknown ? 1 : 0)
12757 << getOpenMPClauseNameForDiag(MemOrderKind);
12758 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12759 << getOpenMPClauseNameForDiag(MemOrderKind);
12760 }
12761
12762 Stmt *Body = AStmt;
12763 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12764 Body = EWC->getSubExpr();
12765
12766 Expr *X = nullptr;
12767 Expr *V = nullptr;
12768 Expr *E = nullptr;
12769 Expr *UE = nullptr;
12770 Expr *D = nullptr;
12771 Expr *CE = nullptr;
12772 Expr *R = nullptr;
12773 bool IsXLHSInRHSPart = false;
12774 bool IsPostfixUpdate = false;
12775 bool IsFailOnly = false;
12776 // OpenMP [2.12.6, atomic Construct]
12777 // In the next expressions:
12778 // * x and v (as applicable) are both l-value expressions with scalar type.
12779 // * During the execution of an atomic region, multiple syntactic
12780 // occurrences of x must designate the same storage location.
12781 // * Neither of v and expr (as applicable) may access the storage location
12782 // designated by x.
12783 // * Neither of x and expr (as applicable) may access the storage location
12784 // designated by v.
12785 // * expr is an expression with scalar type.
12786 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12787 // * binop, binop=, ++, and -- are not overloaded operators.
12788 // * The expression x binop expr must be numerically equivalent to x binop
12789 // (expr). This requirement is satisfied if the operators in expr have
12790 // precedence greater than binop, or by using parentheses around expr or
12791 // subexpressions of expr.
12792 // * The expression expr binop x must be numerically equivalent to (expr)
12793 // binop x. This requirement is satisfied if the operators in expr have
12794 // precedence equal to or greater than binop, or by using parentheses around
12795 // expr or subexpressions of expr.
12796 // * For forms that allow multiple occurrences of x, the number of times
12797 // that x is evaluated is unspecified.
12798 if (AtomicKind == OMPC_read) {
12799 enum {
12800 NotAnExpression,
12801 NotAnAssignmentOp,
12802 NotAScalarType,
12803 NotAnLValue,
12804 NoError
12805 } ErrorFound = NoError;
12806 SourceLocation ErrorLoc, NoteLoc;
12807 SourceRange ErrorRange, NoteRange;
12808 // If clause is read:
12809 // v = x;
12810 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12811 const auto *AtomicBinOp =
12812 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12813 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12814 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12815 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12816 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12817 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12818 if (!X->isLValue() || !V->isLValue()) {
12819 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12820 ErrorFound = NotAnLValue;
12821 ErrorLoc = AtomicBinOp->getExprLoc();
12822 ErrorRange = AtomicBinOp->getSourceRange();
12823 NoteLoc = NotLValueExpr->getExprLoc();
12824 NoteRange = NotLValueExpr->getSourceRange();
12825 }
12826 } else if (!X->isInstantiationDependent() ||
12827 !V->isInstantiationDependent()) {
12828 const Expr *NotScalarExpr =
12829 (X->isInstantiationDependent() || X->getType()->isScalarType())
12830 ? V
12831 : X;
12832 ErrorFound = NotAScalarType;
12833 ErrorLoc = AtomicBinOp->getExprLoc();
12834 ErrorRange = AtomicBinOp->getSourceRange();
12835 NoteLoc = NotScalarExpr->getExprLoc();
12836 NoteRange = NotScalarExpr->getSourceRange();
12837 }
12838 } else if (!AtomicBody->isInstantiationDependent()) {
12839 ErrorFound = NotAnAssignmentOp;
12840 ErrorLoc = AtomicBody->getExprLoc();
12841 ErrorRange = AtomicBody->getSourceRange();
12842 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12843 : AtomicBody->getExprLoc();
12844 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12845 : AtomicBody->getSourceRange();
12846 }
12847 } else {
12848 ErrorFound = NotAnExpression;
12849 NoteLoc = ErrorLoc = Body->getBeginLoc();
12850 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12851 }
12852 if (ErrorFound != NoError) {
12853 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12854 << ErrorRange;
12855 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12856 << ErrorFound << NoteRange;
12857 return StmtError();
12858 }
12859 if (SemaRef.CurContext->isDependentContext())
12860 V = X = nullptr;
12861 } else if (AtomicKind == OMPC_write) {
12862 enum {
12863 NotAnExpression,
12864 NotAnAssignmentOp,
12865 NotAScalarType,
12866 NotAnLValue,
12867 NoError
12868 } ErrorFound = NoError;
12869 SourceLocation ErrorLoc, NoteLoc;
12870 SourceRange ErrorRange, NoteRange;
12871 // If clause is write:
12872 // x = expr;
12873 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12874 const auto *AtomicBinOp =
12875 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12876 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12877 X = AtomicBinOp->getLHS();
12878 E = AtomicBinOp->getRHS();
12879 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12880 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12881 if (!X->isLValue()) {
12882 ErrorFound = NotAnLValue;
12883 ErrorLoc = AtomicBinOp->getExprLoc();
12884 ErrorRange = AtomicBinOp->getSourceRange();
12885 NoteLoc = X->getExprLoc();
12886 NoteRange = X->getSourceRange();
12887 }
12888 } else if (!X->isInstantiationDependent() ||
12890 const Expr *NotScalarExpr =
12891 (X->isInstantiationDependent() || X->getType()->isScalarType())
12892 ? E
12893 : X;
12894 ErrorFound = NotAScalarType;
12895 ErrorLoc = AtomicBinOp->getExprLoc();
12896 ErrorRange = AtomicBinOp->getSourceRange();
12897 NoteLoc = NotScalarExpr->getExprLoc();
12898 NoteRange = NotScalarExpr->getSourceRange();
12899 }
12900 } else if (!AtomicBody->isInstantiationDependent()) {
12901 ErrorFound = NotAnAssignmentOp;
12902 ErrorLoc = AtomicBody->getExprLoc();
12903 ErrorRange = AtomicBody->getSourceRange();
12904 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12905 : AtomicBody->getExprLoc();
12906 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12907 : AtomicBody->getSourceRange();
12908 }
12909 } else {
12910 ErrorFound = NotAnExpression;
12911 NoteLoc = ErrorLoc = Body->getBeginLoc();
12912 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12913 }
12914 if (ErrorFound != NoError) {
12915 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12916 << ErrorRange;
12917 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12918 << ErrorFound << NoteRange;
12919 return StmtError();
12920 }
12921 if (SemaRef.CurContext->isDependentContext())
12922 E = X = nullptr;
12923 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12924 // If clause is update:
12925 // x++;
12926 // x--;
12927 // ++x;
12928 // --x;
12929 // x binop= expr;
12930 // x = x binop expr;
12931 // x = expr binop x;
12932 OpenMPAtomicUpdateChecker Checker(SemaRef);
12933 if (Checker.checkStatement(
12934 Body,
12935 (AtomicKind == OMPC_update)
12936 ? diag::err_omp_atomic_update_not_expression_statement
12937 : diag::err_omp_atomic_not_expression_statement,
12938 diag::note_omp_atomic_update))
12939 return StmtError();
12940 if (!SemaRef.CurContext->isDependentContext()) {
12941 E = Checker.getExpr();
12942 X = Checker.getX();
12943 UE = Checker.getUpdateExpr();
12944 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12945 }
12946 } else if (AtomicKind == OMPC_capture) {
12947 enum {
12948 NotAnAssignmentOp,
12949 NotACompoundStatement,
12950 NotTwoSubstatements,
12951 NotASpecificExpression,
12952 NoError
12953 } ErrorFound = NoError;
12954 SourceLocation ErrorLoc, NoteLoc;
12955 SourceRange ErrorRange, NoteRange;
12956 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12957 // If clause is a capture:
12958 // v = x++;
12959 // v = x--;
12960 // v = ++x;
12961 // v = --x;
12962 // v = x binop= expr;
12963 // v = x = x binop expr;
12964 // v = x = expr binop x;
12965 const auto *AtomicBinOp =
12966 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12967 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12968 V = AtomicBinOp->getLHS();
12969 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12970 OpenMPAtomicUpdateChecker Checker(SemaRef);
12971 if (Checker.checkStatement(
12972 Body, diag::err_omp_atomic_capture_not_expression_statement,
12973 diag::note_omp_atomic_update))
12974 return StmtError();
12975 E = Checker.getExpr();
12976 X = Checker.getX();
12977 UE = Checker.getUpdateExpr();
12978 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12979 IsPostfixUpdate = Checker.isPostfixUpdate();
12980 } else if (!AtomicBody->isInstantiationDependent()) {
12981 ErrorLoc = AtomicBody->getExprLoc();
12982 ErrorRange = AtomicBody->getSourceRange();
12983 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12984 : AtomicBody->getExprLoc();
12985 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12986 : AtomicBody->getSourceRange();
12987 ErrorFound = NotAnAssignmentOp;
12988 }
12989 if (ErrorFound != NoError) {
12990 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12991 << ErrorRange;
12992 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12993 return StmtError();
12994 }
12995 if (SemaRef.CurContext->isDependentContext())
12996 UE = V = E = X = nullptr;
12997 } else {
12998 // If clause is a capture:
12999 // { v = x; x = expr; }
13000 // { v = x; x++; }
13001 // { v = x; x--; }
13002 // { v = x; ++x; }
13003 // { v = x; --x; }
13004 // { v = x; x binop= expr; }
13005 // { v = x; x = x binop expr; }
13006 // { v = x; x = expr binop x; }
13007 // { x++; v = x; }
13008 // { x--; v = x; }
13009 // { ++x; v = x; }
13010 // { --x; v = x; }
13011 // { x binop= expr; v = x; }
13012 // { x = x binop expr; v = x; }
13013 // { x = expr binop x; v = x; }
13014 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
13015 // Check that this is { expr1; expr2; }
13016 if (CS->size() == 2) {
13017 Stmt *First = CS->body_front();
13018 Stmt *Second = CS->body_back();
13019 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
13020 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13021 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13022 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13023 // Need to find what subexpression is 'v' and what is 'x'.
13024 OpenMPAtomicUpdateChecker Checker(SemaRef);
13025 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13026 BinaryOperator *BinOp = nullptr;
13027 if (IsUpdateExprFound) {
13028 BinOp = dyn_cast<BinaryOperator>(First);
13029 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13030 }
13031 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
13032 // { v = x; x++; }
13033 // { v = x; x--; }
13034 // { v = x; ++x; }
13035 // { v = x; --x; }
13036 // { v = x; x binop= expr; }
13037 // { v = x; x = x binop expr; }
13038 // { v = x; x = expr binop x; }
13039 // Check that the first expression has form v = x.
13040 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13041 llvm::FoldingSetNodeID XId, PossibleXId;
13042 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13043 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13044 IsUpdateExprFound = XId == PossibleXId;
13045 if (IsUpdateExprFound) {
13046 V = BinOp->getLHS();
13047 X = Checker.getX();
13048 E = Checker.getExpr();
13049 UE = Checker.getUpdateExpr();
13050 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13051 IsPostfixUpdate = true;
13052 }
13053 }
13054 if (!IsUpdateExprFound) {
13055 IsUpdateExprFound = !Checker.checkStatement(First);
13056 BinOp = nullptr;
13057 if (IsUpdateExprFound) {
13058 BinOp = dyn_cast<BinaryOperator>(Second);
13059 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13060 }
13061 if (IsUpdateExprFound &&
13062 !SemaRef.CurContext->isDependentContext()) {
13063 // { x++; v = x; }
13064 // { x--; v = x; }
13065 // { ++x; v = x; }
13066 // { --x; v = x; }
13067 // { x binop= expr; v = x; }
13068 // { x = x binop expr; v = x; }
13069 // { x = expr binop x; v = x; }
13070 // Check that the second expression has form v = x.
13071 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13072 llvm::FoldingSetNodeID XId, PossibleXId;
13073 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13074 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13075 IsUpdateExprFound = XId == PossibleXId;
13076 if (IsUpdateExprFound) {
13077 V = BinOp->getLHS();
13078 X = Checker.getX();
13079 E = Checker.getExpr();
13080 UE = Checker.getUpdateExpr();
13081 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13082 IsPostfixUpdate = false;
13083 }
13084 }
13085 }
13086 if (!IsUpdateExprFound) {
13087 // { v = x; x = expr; }
13088 auto *FirstExpr = dyn_cast<Expr>(First);
13089 auto *SecondExpr = dyn_cast<Expr>(Second);
13090 if (!FirstExpr || !SecondExpr ||
13091 !(FirstExpr->isInstantiationDependent() ||
13092 SecondExpr->isInstantiationDependent())) {
13093 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
13094 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13095 ErrorFound = NotAnAssignmentOp;
13096 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13097 : First->getBeginLoc();
13098 NoteRange = ErrorRange = FirstBinOp
13099 ? FirstBinOp->getSourceRange()
13100 : SourceRange(ErrorLoc, ErrorLoc);
13101 } else {
13102 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13103 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13104 ErrorFound = NotAnAssignmentOp;
13105 NoteLoc = ErrorLoc = SecondBinOp
13106 ? SecondBinOp->getOperatorLoc()
13107 : Second->getBeginLoc();
13108 NoteRange = ErrorRange =
13109 SecondBinOp ? SecondBinOp->getSourceRange()
13110 : SourceRange(ErrorLoc, ErrorLoc);
13111 } else {
13112 Expr *PossibleXRHSInFirst =
13113 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13114 Expr *PossibleXLHSInSecond =
13115 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13116 llvm::FoldingSetNodeID X1Id, X2Id;
13117 PossibleXRHSInFirst->Profile(X1Id, Context,
13118 /*Canonical=*/true);
13119 PossibleXLHSInSecond->Profile(X2Id, Context,
13120 /*Canonical=*/true);
13121 IsUpdateExprFound = X1Id == X2Id;
13122 if (IsUpdateExprFound) {
13123 V = FirstBinOp->getLHS();
13124 X = SecondBinOp->getLHS();
13125 E = SecondBinOp->getRHS();
13126 UE = nullptr;
13127 IsXLHSInRHSPart = false;
13128 IsPostfixUpdate = true;
13129 } else {
13130 ErrorFound = NotASpecificExpression;
13131 ErrorLoc = FirstBinOp->getExprLoc();
13132 ErrorRange = FirstBinOp->getSourceRange();
13133 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13134 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13135 }
13136 }
13137 }
13138 }
13139 }
13140 } else {
13141 NoteLoc = ErrorLoc = Body->getBeginLoc();
13142 NoteRange = ErrorRange =
13143 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13144 ErrorFound = NotTwoSubstatements;
13145 }
13146 } else {
13147 NoteLoc = ErrorLoc = Body->getBeginLoc();
13148 NoteRange = ErrorRange =
13149 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13150 ErrorFound = NotACompoundStatement;
13151 }
13152 }
13153 if (ErrorFound != NoError) {
13154 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13155 << ErrorRange;
13156 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13157 return StmtError();
13158 }
13159 if (SemaRef.CurContext->isDependentContext())
13160 UE = V = E = X = nullptr;
13161 } else if (AtomicKind == OMPC_compare) {
13162 if (IsCompareCapture) {
13163 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13164 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
13165 if (!Checker.checkStmt(Body, ErrorInfo)) {
13166 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13167 << ErrorInfo.ErrorRange;
13168 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13169 << ErrorInfo.Error << ErrorInfo.NoteRange;
13170 return StmtError();
13171 }
13172 X = Checker.getX();
13173 E = Checker.getE();
13174 D = Checker.getD();
13175 CE = Checker.getCond();
13176 V = Checker.getV();
13177 R = Checker.getR();
13178 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13179 IsXLHSInRHSPart = Checker.isXBinopExpr();
13180 IsFailOnly = Checker.isFailOnly();
13181 IsPostfixUpdate = Checker.isPostfixUpdate();
13182 } else {
13183 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13184 OpenMPAtomicCompareChecker Checker(SemaRef);
13185 if (!Checker.checkStmt(Body, ErrorInfo)) {
13186 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13187 << ErrorInfo.ErrorRange;
13188 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13189 << ErrorInfo.Error << ErrorInfo.NoteRange;
13190 return StmtError();
13191 }
13192 X = Checker.getX();
13193 E = Checker.getE();
13194 D = Checker.getD();
13195 CE = Checker.getCond();
13196 // The weak clause may only appear if the resulting atomic operation is
13197 // an atomic conditional update for which the comparison tests for
13198 // equality. It was not possible to do this check in
13199 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13200 // could not be performed (Clauses are not available).
13201 auto *It = find_if(Clauses, [](OMPClause *C) {
13202 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13203 });
13204 if (It != Clauses.end()) {
13205 auto *Cond = dyn_cast<BinaryOperator>(CE);
13206 if (Cond->getOpcode() != BO_EQ) {
13207 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13208 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13209 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13210 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13211
13212 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13213 << ErrorInfo.ErrorRange;
13214 return StmtError();
13215 }
13216 }
13217 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13218 IsXLHSInRHSPart = Checker.isXBinopExpr();
13219 }
13220 }
13221
13222 SemaRef.setFunctionHasBranchProtectedScope();
13223
13224 return OMPAtomicDirective::Create(
13225 Context, StartLoc, EndLoc, Clauses, AStmt,
13226 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13227}
13228
13230 Stmt *AStmt,
13231 SourceLocation StartLoc,
13232 SourceLocation EndLoc) {
13233 if (!AStmt)
13234 return StmtError();
13235
13236 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
13237
13238 // OpenMP [2.16, Nesting of Regions]
13239 // If specified, a teams construct must be contained within a target
13240 // construct. That target construct must contain no statements or directives
13241 // outside of the teams construct.
13242 if (DSAStack->hasInnerTeamsRegion()) {
13243 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13244 bool OMPTeamsFound = true;
13245 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13246 auto I = CS->body_begin();
13247 while (I != CS->body_end()) {
13248 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13249 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13250 if (!IsTeams || I != CS->body_begin()) {
13251 OMPTeamsFound = false;
13252 if (IsTeams && I != CS->body_begin()) {
13253 // This is the two teams case. Since the InnerTeamsRegionLoc will
13254 // point to this second one reset the iterator to the other teams.
13255 --I;
13256 }
13257 break;
13258 }
13259 ++I;
13260 }
13261 assert(I != CS->body_end() && "Not found statement");
13262 S = *I;
13263 } else {
13264 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13265 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13266 }
13267 if (!OMPTeamsFound) {
13268 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13269 Diag(DSAStack->getInnerTeamsRegionLoc(),
13270 diag::note_omp_nested_teams_construct_here);
13271 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13273 return StmtError();
13274 }
13275 }
13276
13277 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13278 AStmt);
13279}
13280
13282 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13283 SourceLocation EndLoc) {
13284 if (!AStmt)
13285 return StmtError();
13286
13287 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
13288
13290 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
13291 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13292}
13293
13295 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13296 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13297 if (!AStmt)
13298 return StmtError();
13299
13300 CapturedStmt *CS =
13301 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
13302
13303 OMPLoopBasedDirective::HelperExprs B;
13304 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13305 // define the nested loops number.
13306 unsigned NestedLoopCount =
13307 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13308 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13309 VarsWithImplicitDSA, B);
13310 if (NestedLoopCount == 0)
13311 return StmtError();
13312
13313 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13314 return StmtError();
13315
13317 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13318 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13319}
13320
13321/// Check for existence of a map clause in the list of clauses.
13323 const OpenMPClauseKind K) {
13324 return llvm::any_of(
13325 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13326}
13327
13328template <typename... Params>
13330 const Params... ClauseTypes) {
13331 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13332}
13333
13334/// Check if the variables in the mapping clause are externally visible.
13336 for (const OMPClause *C : Clauses) {
13337 if (auto *TC = dyn_cast<OMPToClause>(C))
13338 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13339 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13340 (VD->isExternallyVisible() &&
13341 VD->getVisibility() != HiddenVisibility);
13342 });
13343 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13344 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13345 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13346 (VD->isExternallyVisible() &&
13347 VD->getVisibility() != HiddenVisibility);
13348 });
13349 }
13350
13351 return true;
13352}
13353
13356 Stmt *AStmt, SourceLocation StartLoc,
13357 SourceLocation EndLoc) {
13358 if (!AStmt)
13359 return StmtError();
13360
13361 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13362
13363 // OpenMP [2.12.2, target data Construct, Restrictions]
13364 // At least one map, use_device_addr or use_device_ptr clause must appear on
13365 // the directive.
13366 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13367 (getLangOpts().OpenMP < 50 ||
13368 !hasClauses(Clauses, OMPC_use_device_addr))) {
13369 StringRef Expected;
13370 if (getLangOpts().OpenMP < 50)
13371 Expected = "'map' or 'use_device_ptr'";
13372 else
13373 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13374 unsigned OMPVersion = getLangOpts().OpenMP;
13375 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13376 << Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13377 return StmtError();
13378 }
13379
13380 SemaRef.setFunctionHasBranchProtectedScope();
13381
13382 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13383 Clauses, AStmt);
13384}
13385
13387 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13388 SourceLocation EndLoc, Stmt *AStmt) {
13389 if (!AStmt)
13390 return StmtError();
13391
13392 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13393
13394 // OpenMP [2.10.2, Restrictions, p. 99]
13395 // At least one map clause must appear on the directive.
13396 if (!hasClauses(Clauses, OMPC_map)) {
13397 unsigned OMPVersion = getLangOpts().OpenMP;
13398 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13399 << "'map'"
13400 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13401 return StmtError();
13402 }
13403
13404 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13405 Clauses, AStmt);
13406}
13407
13409 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13410 SourceLocation EndLoc, Stmt *AStmt) {
13411 if (!AStmt)
13412 return StmtError();
13413
13414 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13415
13416 // OpenMP [2.10.3, Restrictions, p. 102]
13417 // At least one map clause must appear on the directive.
13418 if (!hasClauses(Clauses, OMPC_map)) {
13419 unsigned OMPVersion = getLangOpts().OpenMP;
13420 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13421 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13422 return StmtError();
13423 }
13424
13425 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13426 Clauses, AStmt);
13427}
13428
13430 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13431 SourceLocation EndLoc, Stmt *AStmt) {
13432 if (!AStmt)
13433 return StmtError();
13434
13435 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13436
13437 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13438 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13439 return StmtError();
13440 }
13441
13442 if (!isClauseMappable(Clauses)) {
13443 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13444 return StmtError();
13445 }
13446
13447 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13448 Clauses, AStmt);
13449}
13450
13451/// This checks whether a \p ClauseType clause \p C has at most \p Max
13452/// expression. If not, a diag of number \p Diag will be emitted.
13453template <typename ClauseType>
13454static bool checkNumExprsInClause(SemaBase &SemaRef,
13455 ArrayRef<OMPClause *> Clauses,
13456 unsigned MaxNum, unsigned Diag) {
13457 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13458 if (ClauseItr == Clauses.end())
13459 return true;
13460 const auto *C = cast<ClauseType>(*ClauseItr);
13461 auto VarList = C->getVarRefs();
13462 if (VarList.size() > MaxNum) {
13463 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13464 << getOpenMPClauseNameForDiag(C->getClauseKind());
13465 return false;
13466 }
13467 return true;
13468}
13469
13471 Stmt *AStmt,
13472 SourceLocation StartLoc,
13473 SourceLocation EndLoc) {
13474 if (!AStmt)
13475 return StmtError();
13476
13478 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13480 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13481 return StmtError();
13482
13483 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13484 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13485 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13486
13487 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13488
13489 DSAStack->setParentTeamsRegionLoc(StartLoc);
13490
13491 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13492 AStmt);
13493}
13494
13496 SourceLocation StartLoc, SourceLocation EndLoc,
13497 OpenMPDirectiveKind CancelRegion) {
13498 if (DSAStack->isParentNowaitRegion()) {
13499 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13500 return StmtError();
13501 }
13502 if (DSAStack->isParentOrderedRegion()) {
13503 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13504 return StmtError();
13505 }
13507 EndLoc, CancelRegion);
13508}
13509
13511 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13512 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13513 if (DSAStack->isParentNowaitRegion()) {
13514 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13515 return StmtError();
13516 }
13517 if (DSAStack->isParentOrderedRegion()) {
13518 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13519 return StmtError();
13520 }
13521 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13522 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13523 CancelRegion);
13524}
13525
13527 ArrayRef<OMPClause *> Clauses) {
13528 const OMPClause *ReductionClause = nullptr;
13529 const OMPClause *NogroupClause = nullptr;
13530 for (const OMPClause *C : Clauses) {
13531 if (C->getClauseKind() == OMPC_reduction) {
13532 ReductionClause = C;
13533 if (NogroupClause)
13534 break;
13535 continue;
13536 }
13537 if (C->getClauseKind() == OMPC_nogroup) {
13538 NogroupClause = C;
13539 if (ReductionClause)
13540 break;
13541 continue;
13542 }
13543 }
13544 if (ReductionClause && NogroupClause) {
13545 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13546 << SourceRange(NogroupClause->getBeginLoc(),
13547 NogroupClause->getEndLoc());
13548 return true;
13549 }
13550 return false;
13551}
13552
13554 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13555 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13556 if (!AStmt)
13557 return StmtError();
13558
13559 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13560 OMPLoopBasedDirective::HelperExprs B;
13561 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13562 // define the nested loops number.
13563 unsigned NestedLoopCount =
13564 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13565 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13566 *DSAStack, VarsWithImplicitDSA, B);
13567 if (NestedLoopCount == 0)
13568 return StmtError();
13569
13570 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13571 "omp for loop exprs were not built");
13572
13573 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13574 // The grainsize clause and num_tasks clause are mutually exclusive and may
13575 // not appear on the same taskloop directive.
13577 {OMPC_grainsize, OMPC_num_tasks}))
13578 return StmtError();
13579 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13580 // If a reduction clause is present on the taskloop directive, the nogroup
13581 // clause must not be specified.
13583 return StmtError();
13584
13585 SemaRef.setFunctionHasBranchProtectedScope();
13586 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13587 NestedLoopCount, Clauses, AStmt, B,
13588 DSAStack->isCancelRegion());
13589}
13590
13592 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13593 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13594 if (!AStmt)
13595 return StmtError();
13596
13597 CapturedStmt *CS =
13598 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13599
13600 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13601 OMPLoopBasedDirective::HelperExprs B;
13602 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13603 // define the nested loops number.
13604 unsigned NestedLoopCount =
13605 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13606 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13607 VarsWithImplicitDSA, B);
13608 if (NestedLoopCount == 0)
13609 return StmtError();
13610
13611 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13612 return StmtError();
13613
13614 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13615 // The grainsize clause and num_tasks clause are mutually exclusive and may
13616 // not appear on the same taskloop directive.
13618 {OMPC_grainsize, OMPC_num_tasks}))
13619 return StmtError();
13620 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13621 // If a reduction clause is present on the taskloop directive, the nogroup
13622 // clause must not be specified.
13624 return StmtError();
13626 return StmtError();
13627
13628 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13629 NestedLoopCount, Clauses, AStmt, B);
13630}
13631
13633 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13634 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13635 if (!AStmt)
13636 return StmtError();
13637
13638 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13639 OMPLoopBasedDirective::HelperExprs B;
13640 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13641 // define the nested loops number.
13642 unsigned NestedLoopCount =
13643 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13644 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13645 *DSAStack, VarsWithImplicitDSA, B);
13646 if (NestedLoopCount == 0)
13647 return StmtError();
13648
13649 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13650 "omp for loop exprs were not built");
13651
13652 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13653 // The grainsize clause and num_tasks clause are mutually exclusive and may
13654 // not appear on the same taskloop directive.
13656 {OMPC_grainsize, OMPC_num_tasks}))
13657 return StmtError();
13658 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13659 // If a reduction clause is present on the taskloop directive, the nogroup
13660 // clause must not be specified.
13662 return StmtError();
13663
13664 SemaRef.setFunctionHasBranchProtectedScope();
13665 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13666 NestedLoopCount, Clauses, AStmt, B,
13667 DSAStack->isCancelRegion());
13668}
13669
13671 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13672 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13673 if (!AStmt)
13674 return StmtError();
13675
13676 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13677 OMPLoopBasedDirective::HelperExprs B;
13678 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13679 // define the nested loops number.
13680 unsigned NestedLoopCount =
13681 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13682 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13683 *DSAStack, VarsWithImplicitDSA, B);
13684 if (NestedLoopCount == 0)
13685 return StmtError();
13686
13687 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13688 "omp for loop exprs were not built");
13689
13690 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13691 // The grainsize clause and num_tasks clause are mutually exclusive and may
13692 // not appear on the same taskloop directive.
13694 {OMPC_grainsize, OMPC_num_tasks}))
13695 return StmtError();
13696 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13697 // If a reduction clause is present on the taskloop directive, the nogroup
13698 // clause must not be specified.
13700 return StmtError();
13701
13702 SemaRef.setFunctionHasBranchProtectedScope();
13703 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13704 NestedLoopCount, Clauses, AStmt, B,
13705 DSAStack->isCancelRegion());
13706}
13707
13709 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13710 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13711 if (!AStmt)
13712 return StmtError();
13713
13714 CapturedStmt *CS =
13715 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13716
13717 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13718 OMPLoopBasedDirective::HelperExprs B;
13719 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13720 // define the nested loops number.
13721 unsigned NestedLoopCount =
13722 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13723 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13724 VarsWithImplicitDSA, B);
13725 if (NestedLoopCount == 0)
13726 return StmtError();
13727
13728 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13729 return StmtError();
13730
13731 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13732 // The grainsize clause and num_tasks clause are mutually exclusive and may
13733 // not appear on the same taskloop directive.
13735 {OMPC_grainsize, OMPC_num_tasks}))
13736 return StmtError();
13737 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13738 // If a reduction clause is present on the taskloop directive, the nogroup
13739 // clause must not be specified.
13741 return StmtError();
13743 return StmtError();
13744
13746 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13747}
13748
13750 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13751 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13752 if (!AStmt)
13753 return StmtError();
13754
13755 CapturedStmt *CS =
13756 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13757
13758 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13759 OMPLoopBasedDirective::HelperExprs B;
13760 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13761 // define the nested loops number.
13762 unsigned NestedLoopCount =
13763 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13764 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13765 VarsWithImplicitDSA, B);
13766 if (NestedLoopCount == 0)
13767 return StmtError();
13768
13769 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13770 return StmtError();
13771
13772 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13773 // The grainsize clause and num_tasks clause are mutually exclusive and may
13774 // not appear on the same taskloop directive.
13776 {OMPC_grainsize, OMPC_num_tasks}))
13777 return StmtError();
13778 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13779 // If a reduction clause is present on the taskloop directive, the nogroup
13780 // clause must not be specified.
13782 return StmtError();
13784 return StmtError();
13785
13787 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13788}
13789
13791 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13792 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13793 if (!AStmt)
13794 return StmtError();
13795
13796 CapturedStmt *CS =
13797 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13798
13799 OMPLoopBasedDirective::HelperExprs B;
13800 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13801 // define the nested loops number.
13802 unsigned NestedLoopCount = checkOpenMPLoop(
13803 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13804 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13805 VarsWithImplicitDSA, B);
13806 if (NestedLoopCount == 0)
13807 return StmtError();
13808
13809 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13810 "omp for loop exprs were not built");
13811
13812 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13813 // The grainsize clause and num_tasks clause are mutually exclusive and may
13814 // not appear on the same taskloop directive.
13816 {OMPC_grainsize, OMPC_num_tasks}))
13817 return StmtError();
13818 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13819 // If a reduction clause is present on the taskloop directive, the nogroup
13820 // clause must not be specified.
13822 return StmtError();
13823
13825 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13826 DSAStack->isCancelRegion());
13827}
13828
13830 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13831 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13832 if (!AStmt)
13833 return StmtError();
13834
13835 CapturedStmt *CS =
13836 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13837
13838 OMPLoopBasedDirective::HelperExprs B;
13839 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13840 // define the nested loops number.
13841 unsigned NestedLoopCount = checkOpenMPLoop(
13842 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13843 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13844 VarsWithImplicitDSA, B);
13845 if (NestedLoopCount == 0)
13846 return StmtError();
13847
13848 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13849 "omp for loop exprs were not built");
13850
13851 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13852 // The grainsize clause and num_tasks clause are mutually exclusive and may
13853 // not appear on the same taskloop directive.
13855 {OMPC_grainsize, OMPC_num_tasks}))
13856 return StmtError();
13857 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13858 // If a reduction clause is present on the taskloop directive, the nogroup
13859 // clause must not be specified.
13861 return StmtError();
13862
13864 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13865 DSAStack->isCancelRegion());
13866}
13867
13869 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13870 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13871 if (!AStmt)
13872 return StmtError();
13873
13875 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13876
13877 OMPLoopBasedDirective::HelperExprs B;
13878 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13879 // define the nested loops number.
13880 unsigned NestedLoopCount = checkOpenMPLoop(
13881 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13882 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13883 VarsWithImplicitDSA, B);
13884 if (NestedLoopCount == 0)
13885 return StmtError();
13886
13887 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13888 return StmtError();
13889
13890 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13891 // The grainsize clause and num_tasks clause are mutually exclusive and may
13892 // not appear on the same taskloop directive.
13894 {OMPC_grainsize, OMPC_num_tasks}))
13895 return StmtError();
13896 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13897 // If a reduction clause is present on the taskloop directive, the nogroup
13898 // clause must not be specified.
13900 return StmtError();
13902 return StmtError();
13903
13905 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13906}
13907
13909 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13910 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13911 if (!AStmt)
13912 return StmtError();
13913
13915 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13916
13917 OMPLoopBasedDirective::HelperExprs B;
13918 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13919 // define the nested loops number.
13920 unsigned NestedLoopCount = checkOpenMPLoop(
13921 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13922 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13923 VarsWithImplicitDSA, B);
13924 if (NestedLoopCount == 0)
13925 return StmtError();
13926
13927 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13928 return StmtError();
13929
13930 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13931 // The grainsize clause and num_tasks clause are mutually exclusive and may
13932 // not appear on the same taskloop directive.
13934 {OMPC_grainsize, OMPC_num_tasks}))
13935 return StmtError();
13936 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13937 // If a reduction clause is present on the taskloop directive, the nogroup
13938 // clause must not be specified.
13940 return StmtError();
13942 return StmtError();
13943
13945 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13946}
13947
13949 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13950 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13951 if (!AStmt)
13952 return StmtError();
13953
13954 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13955 OMPLoopBasedDirective::HelperExprs B;
13956 // In presence of clause 'collapse' with number of loops, it will
13957 // define the nested loops number.
13958 unsigned NestedLoopCount =
13959 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13960 nullptr /*ordered not a clause on distribute*/, AStmt,
13961 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13962 if (NestedLoopCount == 0)
13963 return StmtError();
13964
13965 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13966 "omp for loop exprs were not built");
13967
13968 SemaRef.setFunctionHasBranchProtectedScope();
13969 auto *DistributeDirective = OMPDistributeDirective::Create(
13970 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13971 return DistributeDirective;
13972}
13973
13975 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13976 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13977 if (!AStmt)
13978 return StmtError();
13979
13980 CapturedStmt *CS =
13981 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
13982
13983 OMPLoopBasedDirective::HelperExprs B;
13984 // In presence of clause 'collapse' with number of loops, it will
13985 // define the nested loops number.
13986 unsigned NestedLoopCount = checkOpenMPLoop(
13987 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13988 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13989 VarsWithImplicitDSA, B);
13990 if (NestedLoopCount == 0)
13991 return StmtError();
13992
13993 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13994 "omp for loop exprs were not built");
13995
13997 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13998 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13999}
14000
14002 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14003 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14004 if (!AStmt)
14005 return StmtError();
14006
14008 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
14009
14010 OMPLoopBasedDirective::HelperExprs B;
14011 // In presence of clause 'collapse' with number of loops, it will
14012 // define the nested loops number.
14013 unsigned NestedLoopCount = checkOpenMPLoop(
14014 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14015 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14016 VarsWithImplicitDSA, B);
14017 if (NestedLoopCount == 0)
14018 return StmtError();
14019
14020 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14021 return StmtError();
14022
14024 return StmtError();
14025
14027 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14028}
14029
14031 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14032 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14033 if (!AStmt)
14034 return StmtError();
14035
14036 CapturedStmt *CS =
14037 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
14038
14039 OMPLoopBasedDirective::HelperExprs B;
14040 // In presence of clause 'collapse' with number of loops, it will
14041 // define the nested loops number.
14042 unsigned NestedLoopCount =
14043 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14044 nullptr /*ordered not a clause on distribute*/, CS,
14045 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14046 if (NestedLoopCount == 0)
14047 return StmtError();
14048
14049 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14050 return StmtError();
14051
14053 return StmtError();
14054
14055 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14056 NestedLoopCount, Clauses, AStmt, B);
14057}
14058
14060 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14061 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14062 if (!AStmt)
14063 return StmtError();
14064
14065 CapturedStmt *CS =
14066 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
14067
14068 OMPLoopBasedDirective::HelperExprs B;
14069 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14070 // define the nested loops number.
14071 unsigned NestedLoopCount = checkOpenMPLoop(
14072 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14073 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14074 VarsWithImplicitDSA, B);
14075 if (NestedLoopCount == 0)
14076 return StmtError();
14077
14078 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14079 return StmtError();
14080
14082 return StmtError();
14083
14085 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14086}
14087
14089 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14090 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14091 if (!AStmt)
14092 return StmtError();
14093
14094 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
14095
14096 OMPLoopBasedDirective::HelperExprs B;
14097 // In presence of clause 'collapse' with number of loops, it will define the
14098 // nested loops number.
14099 unsigned NestedLoopCount =
14100 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14101 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14102 VarsWithImplicitDSA, B);
14103 if (NestedLoopCount == 0)
14104 return StmtError();
14105
14106 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14107 return StmtError();
14108
14110 return StmtError();
14111
14112 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14113 NestedLoopCount, Clauses, AStmt, B);
14114}
14115
14117 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14118 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14119 if (!AStmt)
14120 return StmtError();
14121
14122 CapturedStmt *CS =
14123 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
14124
14125 OMPLoopBasedDirective::HelperExprs B;
14126 // In presence of clause 'collapse' with number of loops, it will
14127 // define the nested loops number.
14128 unsigned NestedLoopCount =
14129 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14130 nullptr /*ordered not a clause on distribute*/, CS,
14131 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14132 if (NestedLoopCount == 0)
14133 return StmtError();
14134
14135 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14136 "omp teams distribute loop exprs were not built");
14137
14138 DSAStack->setParentTeamsRegionLoc(StartLoc);
14139
14141 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14142}
14143
14145 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14146 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14147 if (!AStmt)
14148 return StmtError();
14149
14150 CapturedStmt *CS =
14151 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
14152
14153 OMPLoopBasedDirective::HelperExprs B;
14154 // In presence of clause 'collapse' with number of loops, it will
14155 // define the nested loops number.
14156 unsigned NestedLoopCount = checkOpenMPLoop(
14157 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14158 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14159 VarsWithImplicitDSA, B);
14160 if (NestedLoopCount == 0)
14161 return StmtError();
14162
14163 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14164 return StmtError();
14165
14167 return StmtError();
14168
14169 DSAStack->setParentTeamsRegionLoc(StartLoc);
14170
14172 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14173}
14174
14176 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14177 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14178 if (!AStmt)
14179 return StmtError();
14180
14182 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
14183
14184 OMPLoopBasedDirective::HelperExprs B;
14185 // In presence of clause 'collapse' with number of loops, it will
14186 // define the nested loops number.
14187 unsigned NestedLoopCount = checkOpenMPLoop(
14188 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14189 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14190 VarsWithImplicitDSA, B);
14191 if (NestedLoopCount == 0)
14192 return StmtError();
14193
14194 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14195 return StmtError();
14196
14198 return StmtError();
14199
14200 DSAStack->setParentTeamsRegionLoc(StartLoc);
14201
14203 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14204}
14205
14207 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14208 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14209 if (!AStmt)
14210 return StmtError();
14211
14213 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14214
14215 OMPLoopBasedDirective::HelperExprs B;
14216 // In presence of clause 'collapse' with number of loops, it will
14217 // define the nested loops number.
14218 unsigned NestedLoopCount = checkOpenMPLoop(
14219 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14220 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14221 VarsWithImplicitDSA, B);
14222
14223 if (NestedLoopCount == 0)
14224 return StmtError();
14225
14226 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14227 "omp for loop exprs were not built");
14228
14229 DSAStack->setParentTeamsRegionLoc(StartLoc);
14230
14232 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14233 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14234}
14235
14237 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14238 SourceLocation EndLoc) {
14239 if (!AStmt)
14240 return StmtError();
14241
14242 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
14243
14244 const OMPClause *BareClause = nullptr;
14245 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14246 hasClauses(Clauses, OMPC_thread_limit);
14247 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
14248 BareClause = C;
14249 return C->getClauseKind() == OMPC_ompx_bare;
14250 });
14251
14252 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14253 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14254 return StmtError();
14255 }
14256
14257 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14258 unsigned DiagNo = HasBareClause
14259 ? diag::err_ompx_more_than_three_expr_not_allowed
14260 : diag::err_omp_multi_expr_not_allowed;
14261 if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses,
14262 ClauseMaxNumExprs, DiagNo) ||
14264 ClauseMaxNumExprs, DiagNo))
14265 return StmtError();
14266
14267 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
14268 Clauses, AStmt);
14269}
14270
14272 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14273 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14274 if (!AStmt)
14275 return StmtError();
14276
14278 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14280 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14281 return StmtError();
14282
14283 CapturedStmt *CS =
14284 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
14285
14286 OMPLoopBasedDirective::HelperExprs B;
14287 // In presence of clause 'collapse' with number of loops, it will
14288 // define the nested loops number.
14289 unsigned NestedLoopCount = checkOpenMPLoop(
14290 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14291 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14292 VarsWithImplicitDSA, B);
14293 if (NestedLoopCount == 0)
14294 return StmtError();
14295
14296 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14297 "omp target teams distribute loop exprs were not built");
14298
14300 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14301}
14302
14304 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14305 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14306 if (!AStmt)
14307 return StmtError();
14308
14310 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14312 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14313 return StmtError();
14314
14316 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14317
14318 OMPLoopBasedDirective::HelperExprs B;
14319 // In presence of clause 'collapse' with number of loops, it will
14320 // define the nested loops number.
14321 unsigned NestedLoopCount = checkOpenMPLoop(
14322 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14323 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14324 VarsWithImplicitDSA, B);
14325 if (NestedLoopCount == 0)
14326 return StmtError();
14327
14328 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14329 return StmtError();
14330
14332 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14333 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14334}
14335
14337 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14338 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14339 if (!AStmt)
14340 return StmtError();
14341
14343 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14345 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14346 return StmtError();
14347
14349 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14350
14351 OMPLoopBasedDirective::HelperExprs B;
14352 // In presence of clause 'collapse' with number of loops, it will
14353 // define the nested loops number.
14354 unsigned NestedLoopCount =
14355 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14356 getCollapseNumberExpr(Clauses),
14357 nullptr /*ordered not a clause on distribute*/, CS,
14358 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14359 if (NestedLoopCount == 0)
14360 return StmtError();
14361
14362 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14363 return StmtError();
14364
14366 return StmtError();
14367
14369 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14370}
14371
14373 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14374 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14375 if (!AStmt)
14376 return StmtError();
14377
14379 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14381 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14382 return StmtError();
14383
14385 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14386
14387 OMPLoopBasedDirective::HelperExprs B;
14388 // In presence of clause 'collapse' with number of loops, it will
14389 // define the nested loops number.
14390 unsigned NestedLoopCount = checkOpenMPLoop(
14391 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14392 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14393 VarsWithImplicitDSA, B);
14394 if (NestedLoopCount == 0)
14395 return StmtError();
14396
14397 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14398 return StmtError();
14399
14401 return StmtError();
14402
14404 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14405}
14406
14407/// Updates OriginalInits by checking Transform against loop transformation
14408/// directives and appending their pre-inits if a match is found.
14410 SmallVectorImpl<Stmt *> &PreInits) {
14411 Stmt *Dir = Transform->getDirective();
14412 switch (Dir->getStmtClass()) {
14413#define STMT(CLASS, PARENT)
14414#define ABSTRACT_STMT(CLASS)
14415#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14416 case Stmt::CLASS##Class: \
14417 appendFlattenedStmtList(PreInits, \
14418 static_cast<const CLASS *>(Dir)->getPreInits()); \
14419 break;
14420#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14421 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14422#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14423 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14424#include "clang/AST/StmtNodes.inc"
14425#undef COMMON_OMP_LOOP_TRANSFORMATION
14426 default:
14427 llvm_unreachable("Not a loop transformation");
14428 }
14429}
14430
14431bool SemaOpenMP::checkTransformableLoopNest(
14432 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14434 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *>> &OriginalInits) {
14435 OriginalInits.emplace_back();
14436 bool Result = OMPLoopBasedDirective::doForAllLoops(
14437 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14438 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14439 Stmt *CurStmt) {
14440 VarsWithInheritedDSAType TmpDSA;
14441 unsigned SingleNumLoops =
14442 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14443 TmpDSA, LoopHelpers[Cnt]);
14444 if (SingleNumLoops == 0)
14445 return true;
14446 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14447 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14448 OriginalInits.back().push_back(For->getInit());
14449 Body = For->getBody();
14450 } else {
14451 assert(isa<CXXForRangeStmt>(CurStmt) &&
14452 "Expected canonical for or range-based for loops.");
14453 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14454 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14455 Body = CXXFor->getBody();
14456 }
14457 OriginalInits.emplace_back();
14458 return false;
14459 },
14460 [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14461 updatePreInits(Transform, OriginalInits.back());
14462 });
14463 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14464 OriginalInits.pop_back();
14465 return Result;
14466}
14467
14468/// Counts the total number of OpenMP canonical nested loops, including the
14469/// outermost loop (the original loop). PRECONDITION of this visitor is that it
14470/// must be invoked from the original loop to be analyzed. The traversal stops
14471/// for Decl's and Expr's given that they may contain inner loops that must not
14472/// be counted.
14473///
14474/// Example AST structure for the code:
14475///
14476/// int main() {
14477/// #pragma omp fuse
14478/// {
14479/// for (int i = 0; i < 100; i++) { <-- Outer loop
14480/// []() {
14481/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (1)
14482/// };
14483/// for(int j = 0; j < 5; ++j) {} <-- Inner loop
14484/// }
14485/// for (int r = 0; i < 100; i++) { <-- Outer loop
14486/// struct LocalClass {
14487/// void bar() {
14488/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (2)
14489/// }
14490/// };
14491/// for(int k = 0; k < 10; ++k) {} <-- Inner loop
14492/// {x = 5; for(k = 0; k < 10; ++k) x += k; x}; <-- NOT A LOOP (3)
14493/// }
14494/// }
14495/// }
14496/// (1) because in a different function (here: a lambda)
14497/// (2) because in a different function (here: class method)
14498/// (3) because considered to be intervening-code of non-perfectly nested loop
14499/// Result: Loop 'i' contains 2 loops, Loop 'r' also contains 2 loops.
14501private:
14502 unsigned NestedLoopCount = 0;
14503
14504public:
14505 explicit NestedLoopCounterVisitor() = default;
14506
14507 unsigned getNestedLoopCount() const { return NestedLoopCount; }
14508
14509 bool VisitForStmt(ForStmt *FS) override {
14510 ++NestedLoopCount;
14511 return true;
14512 }
14513
14515 ++NestedLoopCount;
14516 return true;
14517 }
14518
14519 bool TraverseStmt(Stmt *S) override {
14520 if (!S)
14521 return true;
14522
14523 // Skip traversal of all expressions, including special cases like
14524 // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
14525 // may contain inner statements (and even loops), but they are not part
14526 // of the syntactic body of the surrounding loop structure.
14527 // Therefore must not be counted.
14528 if (isa<Expr>(S))
14529 return true;
14530
14531 // Only recurse into CompoundStmt (block {}) and loop bodies.
14534 }
14535
14536 // Stop traversal of the rest of statements, that break perfect
14537 // loop nesting, such as control flow (IfStmt, SwitchStmt...).
14538 return true;
14539 }
14540
14541 bool TraverseDecl(Decl *D) override {
14542 // Stop in the case of finding a declaration, it is not important
14543 // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
14544 // FunctionDecl...).
14545 return true;
14546 }
14547};
14548
14549bool SemaOpenMP::analyzeLoopSequence(Stmt *LoopSeqStmt,
14550 LoopSequenceAnalysis &SeqAnalysis,
14551 ASTContext &Context,
14552 OpenMPDirectiveKind Kind) {
14554 // Helper Lambda to handle storing initialization and body statements for
14555 // both ForStmt and CXXForRangeStmt.
14556 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14557 if (auto *For = dyn_cast<ForStmt>(LoopStmt)) {
14558 Analysis.OriginalInits.push_back(For->getInit());
14559 Analysis.TheForStmt = For;
14560 } else {
14561 auto *CXXFor = cast<CXXForRangeStmt>(LoopStmt);
14562 Analysis.OriginalInits.push_back(CXXFor->getBeginStmt());
14563 Analysis.TheForStmt = CXXFor;
14564 }
14565 };
14566
14567 // Helper lambda functions to encapsulate the processing of different
14568 // derivations of the canonical loop sequence grammar
14569 // Modularized code for handling loop generation and transformations.
14570 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14571 auto *LoopTransform = cast<OMPLoopTransformationDirective>(Child);
14572 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14573 unsigned NumGeneratedTopLevelLoops =
14574 LoopTransform->getNumGeneratedTopLevelLoops();
14575 // Handle the case where transformed statement is not available due to
14576 // dependent contexts
14577 if (!TransformedStmt) {
14578 if (NumGeneratedTopLevelLoops > 0) {
14579 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14580 return true;
14581 }
14582 // Unroll full (0 loops produced)
14583 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14584 << 0 << getOpenMPDirectiveName(Kind);
14585 return false;
14586 }
14587 // Handle loop transformations with multiple loop nests
14588 // Unroll full
14589 if (!NumGeneratedTopLevelLoops) {
14590 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14591 << 0 << getOpenMPDirectiveName(Kind);
14592 return false;
14593 }
14594 // Loop transformatons such as split or loopranged fuse
14595 if (NumGeneratedTopLevelLoops > 1) {
14596 // Get the preinits related to this loop sequence generating
14597 // loop transformation (i.e loopranged fuse, split...)
14598 // These preinits differ slightly from regular inits/pre-inits related
14599 // to single loop generating loop transformations (interchange, unroll)
14600 // given that they are not bounded to a particular loop nest
14601 // so they need to be treated independently
14602 updatePreInits(LoopTransform, SeqAnalysis.LoopSequencePreInits);
14603 return analyzeLoopSequence(TransformedStmt, SeqAnalysis, Context, Kind);
14604 }
14605 // Vast majority: (Tile, Unroll, Stripe, Reverse, Interchange, Fuse all)
14606 // Process the transformed loop statement
14607 LoopAnalysis &NewTransformedSingleLoop =
14608 SeqAnalysis.Loops.emplace_back(Child);
14609 unsigned IsCanonical = checkOpenMPLoop(
14610 Kind, nullptr, nullptr, TransformedStmt, SemaRef, *DSAStack, TmpDSA,
14611 NewTransformedSingleLoop.HelperExprs);
14612
14613 if (!IsCanonical)
14614 return false;
14615
14616 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
14617 updatePreInits(LoopTransform, NewTransformedSingleLoop.TransformsPreInits);
14618
14619 SeqAnalysis.LoopSeqSize++;
14620 return true;
14621 };
14622
14623 // Modularized code for handling regular canonical loops.
14624 auto AnalyzeRegularLoop = [&](Stmt *Child) {
14625 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Child);
14626 unsigned IsCanonical =
14627 checkOpenMPLoop(Kind, nullptr, nullptr, Child, SemaRef, *DSAStack,
14628 TmpDSA, NewRegularLoop.HelperExprs);
14629
14630 if (!IsCanonical)
14631 return false;
14632
14633 StoreLoopStatements(NewRegularLoop, Child);
14634 NestedLoopCounterVisitor NLCV;
14635 NLCV.TraverseStmt(Child);
14636 return true;
14637 };
14638
14639 // High level grammar validation.
14640 for (Stmt *Child : LoopSeqStmt->children()) {
14641 if (!Child)
14642 continue;
14643 // Skip over non-loop-sequence statements.
14644 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14645 Child = Child->IgnoreContainers();
14646 // Ignore empty compound statement.
14647 if (!Child)
14648 continue;
14649 // In the case of a nested loop sequence ignoring containers would not
14650 // be enough, a recurisve transversal of the loop sequence is required.
14651 if (isa<CompoundStmt>(Child)) {
14652 if (!analyzeLoopSequence(Child, SeqAnalysis, Context, Kind))
14653 return false;
14654 // Already been treated, skip this children
14655 continue;
14656 }
14657 }
14658 // Regular loop sequence handling.
14659 if (LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14660 if (LoopAnalysis::isLoopTransformation(Child)) {
14661 if (!AnalyzeLoopGeneration(Child))
14662 return false;
14663 // AnalyzeLoopGeneration updates SeqAnalysis.LoopSeqSize accordingly.
14664 } else {
14665 if (!AnalyzeRegularLoop(Child))
14666 return false;
14667 SeqAnalysis.LoopSeqSize++;
14668 }
14669 } else {
14670 // Report error for invalid statement inside canonical loop sequence.
14671 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14672 << 0 << getOpenMPDirectiveName(Kind);
14673 return false;
14674 }
14675 }
14676 return true;
14677}
14678
14679bool SemaOpenMP::checkTransformableLoopSequence(
14680 OpenMPDirectiveKind Kind, Stmt *AStmt, LoopSequenceAnalysis &SeqAnalysis,
14681 ASTContext &Context) {
14682 // Following OpenMP 6.0 API Specification, a Canonical Loop Sequence follows
14683 // the grammar:
14684 //
14685 // canonical-loop-sequence:
14686 // {
14687 // loop-sequence+
14688 // }
14689 // where loop-sequence can be any of the following:
14690 // 1. canonical-loop-sequence
14691 // 2. loop-nest
14692 // 3. loop-sequence-generating-construct (i.e OMPLoopTransformationDirective)
14693 //
14694 // To recognise and traverse this structure the helper function
14695 // analyzeLoopSequence serves as the recurisve entry point
14696 // and tries to match the input AST to the canonical loop sequence grammar
14697 // structure. This function will perform both a semantic and syntactical
14698 // analysis of the given statement according to OpenMP 6.0 definition of
14699 // the aforementioned canonical loop sequence.
14700
14701 // We expect an outer compound statement.
14702 if (!isa<CompoundStmt>(AStmt)) {
14703 Diag(AStmt->getBeginLoc(), diag::err_omp_not_a_loop_sequence)
14704 << getOpenMPDirectiveName(Kind);
14705 return false;
14706 }
14707
14708 // Recursive entry point to process the main loop sequence
14709 if (!analyzeLoopSequence(AStmt, SeqAnalysis, Context, Kind))
14710 return false;
14711
14712 // Diagnose an empty loop sequence.
14713 if (!SeqAnalysis.LoopSeqSize) {
14714 Diag(AStmt->getBeginLoc(), diag::err_omp_empty_loop_sequence)
14715 << getOpenMPDirectiveName(Kind);
14716 return false;
14717 }
14718 return true;
14719}
14720
14721/// Add preinit statements that need to be propagated from the selected loop.
14722static void addLoopPreInits(ASTContext &Context,
14723 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14724 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14725 SmallVectorImpl<Stmt *> &PreInits) {
14726
14727 // For range-based for-statements, ensure that their syntactic sugar is
14728 // executed by adding them as pre-init statements.
14729 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14730 Stmt *RangeInit = CXXRangeFor->getInit();
14731 if (RangeInit)
14732 PreInits.push_back(RangeInit);
14733
14734 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14735 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14736 RangeStmt->getBeginLoc(),
14737 RangeStmt->getEndLoc()));
14738
14739 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14740 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14741 RangeEnd->getBeginLoc(),
14742 RangeEnd->getEndLoc()));
14743 }
14744
14745 llvm::append_range(PreInits, OriginalInit);
14746
14747 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14748 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14749 PreInits.push_back(new (Context) DeclStmt(
14750 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14751 }
14752
14753 // Gather declarations for the data members used as counters.
14754 for (Expr *CounterRef : LoopHelper.Counters) {
14755 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14756 if (isa<OMPCapturedExprDecl>(CounterDecl))
14757 PreInits.push_back(new (Context) DeclStmt(
14758 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14759 }
14760}
14761
14762/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14763/// loop of a construct.
14764static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14765 size_t NumLoops = LoopStmts.size();
14766 OMPLoopBasedDirective::doForAllLoops(
14767 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14768 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14769 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14770 LoopStmts[Cnt] = CurStmt;
14771 return false;
14772 });
14773 assert(!is_contained(LoopStmts, nullptr) &&
14774 "Expecting a loop statement for each affected loop");
14775}
14776
14777/// Build and return a DeclRefExpr for the floor induction variable using the
14778/// SemaRef and the provided parameters.
14779static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
14780 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
14781 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14782 OrigCntVar->getExprLoc());
14783}
14784
14786 Stmt *AStmt,
14787 SourceLocation StartLoc,
14788 SourceLocation EndLoc) {
14789 ASTContext &Context = getASTContext();
14790 Scope *CurScope = SemaRef.getCurScope();
14791
14792 const auto *SizesClause =
14793 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14794 if (!SizesClause ||
14795 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14796 return StmtError();
14797 unsigned NumLoops = SizesClause->getNumSizes();
14798
14799 // Empty statement should only be possible if there already was an error.
14800 if (!AStmt)
14801 return StmtError();
14802
14803 // Verify and diagnose loop nest.
14805 Stmt *Body = nullptr;
14806 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
14807 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14808 OriginalInits))
14809 return StmtError();
14810
14811 // Delay tiling to when template is completely instantiated.
14812 if (SemaRef.CurContext->isDependentContext())
14813 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14814 NumLoops, AStmt, nullptr, nullptr);
14815
14816 assert(LoopHelpers.size() == NumLoops &&
14817 "Expecting loop iteration space dimensionality to match number of "
14818 "affected loops");
14819 assert(OriginalInits.size() == NumLoops &&
14820 "Expecting loop iteration space dimensionality to match number of "
14821 "affected loops");
14822
14823 // Collect all affected loop statements.
14824 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14825 collectLoopStmts(AStmt, LoopStmts);
14826
14827 SmallVector<Stmt *, 4> PreInits;
14828 CaptureVars CopyTransformer(SemaRef);
14829
14830 // Create iteration variables for the generated loops.
14831 SmallVector<VarDecl *, 4> FloorIndVars;
14832 SmallVector<VarDecl *, 4> TileIndVars;
14833 FloorIndVars.resize(NumLoops);
14834 TileIndVars.resize(NumLoops);
14835 for (unsigned I = 0; I < NumLoops; ++I) {
14836 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14837
14838 assert(LoopHelper.Counters.size() == 1 &&
14839 "Expect single-dimensional loop iteration space");
14840 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14841 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14842 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14843 QualType CntTy = IterVarRef->getType();
14844
14845 // Iteration variable for the floor (i.e. outer) loop.
14846 {
14847 std::string FloorCntName =
14848 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14849 VarDecl *FloorCntDecl =
14850 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14851 FloorIndVars[I] = FloorCntDecl;
14852 }
14853
14854 // Iteration variable for the tile (i.e. inner) loop.
14855 {
14856 std::string TileCntName =
14857 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14858
14859 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14860 // used by the expressions to derive the original iteration variable's
14861 // value from the logical iteration number.
14862 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14863 TileCntDecl->setDeclName(
14864 &SemaRef.PP.getIdentifierTable().get(TileCntName));
14865 TileIndVars[I] = TileCntDecl;
14866 }
14867
14868 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14869 PreInits);
14870 }
14871
14872 // Once the original iteration values are set, append the innermost body.
14873 Stmt *Inner = Body;
14874
14875 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14876 SizesClause, CurScope](int I) -> Expr * {
14877 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14878
14879 if (DimTileSizeExpr->containsErrors())
14880 return nullptr;
14881
14882 if (isa<ConstantExpr>(DimTileSizeExpr))
14883 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14884
14885 // When the tile size is not a constant but a variable, it is possible to
14886 // pass non-positive numbers. For instance:
14887 // \code{c}
14888 // int a = 0;
14889 // #pragma omp tile sizes(a)
14890 // for (int i = 0; i < 42; ++i)
14891 // body(i);
14892 // \endcode
14893 // Although there is no meaningful interpretation of the tile size, the body
14894 // should still be executed 42 times to avoid surprises. To preserve the
14895 // invariant that every loop iteration is executed exactly once and not
14896 // cause an infinite loop, apply a minimum tile size of one.
14897 // Build expr:
14898 // \code{c}
14899 // (TS <= 0) ? 1 : TS
14900 // \endcode
14901 QualType DimTy = DimTileSizeExpr->getType();
14902 uint64_t DimWidth = Context.getTypeSize(DimTy);
14904 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14905 IntegerLiteral *One =
14906 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14907 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
14908 CurScope, {}, BO_LE,
14909 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14910 Expr *MinOne = new (Context) ConditionalOperator(
14911 Cond, {}, One, {},
14912 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14914 return MinOne;
14915 };
14916
14917 // Create tile loops from the inside to the outside.
14918 for (int I = NumLoops - 1; I >= 0; --I) {
14919 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14920 Expr *NumIterations = LoopHelper.NumIterations;
14921 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14922 QualType IVTy = NumIterations->getType();
14923 Stmt *LoopStmt = LoopStmts[I];
14924
14925 // Commonly used variables. One of the constraints of an AST is that every
14926 // node object must appear at most once, hence we define a lambda that
14927 // creates a new AST node at every use.
14928 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14929 OrigCntVar]() {
14930 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14931 OrigCntVar->getExprLoc());
14932 };
14933
14934 // For init-statement: auto .tile.iv = .floor.iv
14935 SemaRef.AddInitializerToDecl(
14936 TileIndVars[I],
14937 SemaRef
14938 .DefaultLvalueConversion(
14939 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14940 .get(),
14941 /*DirectInit=*/false);
14942 Decl *CounterDecl = TileIndVars[I];
14943 StmtResult InitStmt = new (Context)
14944 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14945 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14946 if (!InitStmt.isUsable())
14947 return StmtError();
14948
14949 // For cond-expression:
14950 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14951 Expr *DimTileSize = MakeDimTileSize(I);
14952 if (!DimTileSize)
14953 return StmtError();
14954 ExprResult EndOfTile = SemaRef.BuildBinOp(
14955 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14956 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14957 DimTileSize);
14958 if (!EndOfTile.isUsable())
14959 return StmtError();
14960 ExprResult IsPartialTile =
14961 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14962 NumIterations, EndOfTile.get());
14963 if (!IsPartialTile.isUsable())
14964 return StmtError();
14965 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14966 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14967 IsPartialTile.get(), NumIterations, EndOfTile.get());
14968 if (!MinTileAndIterSpace.isUsable())
14969 return StmtError();
14970 ExprResult CondExpr =
14971 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14972 MakeTileIVRef(), MinTileAndIterSpace.get());
14973 if (!CondExpr.isUsable())
14974 return StmtError();
14975
14976 // For incr-statement: ++.tile.iv
14977 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14978 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
14979 if (!IncrStmt.isUsable())
14980 return StmtError();
14981
14982 // Statements to set the original iteration variable's value from the
14983 // logical iteration number.
14984 // Generated for loop is:
14985 // \code
14986 // Original_for_init;
14987 // for (auto .tile.iv = .floor.iv;
14988 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
14989 // ++.tile.iv) {
14990 // Original_Body;
14991 // Original_counter_update;
14992 // }
14993 // \endcode
14994 // FIXME: If the innermost body is an loop itself, inserting these
14995 // statements stops it being recognized as a perfectly nested loop (e.g.
14996 // for applying tiling again). If this is the case, sink the expressions
14997 // further into the inner loop.
14998 SmallVector<Stmt *, 4> BodyParts;
14999 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15000 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15001 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15002 BodyParts.push_back(Inner);
15003 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15004 Inner->getBeginLoc(), Inner->getEndLoc());
15005 Inner = new (Context)
15006 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15007 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15008 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15009 }
15010
15011 // Create floor loops from the inside to the outside.
15012 for (int I = NumLoops - 1; I >= 0; --I) {
15013 auto &LoopHelper = LoopHelpers[I];
15014 Expr *NumIterations = LoopHelper.NumIterations;
15015 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15016 QualType IVTy = NumIterations->getType();
15017
15018 // For init-statement: auto .floor.iv = 0
15019 SemaRef.AddInitializerToDecl(
15020 FloorIndVars[I],
15021 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15022 /*DirectInit=*/false);
15023 Decl *CounterDecl = FloorIndVars[I];
15024 StmtResult InitStmt = new (Context)
15025 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15026 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15027 if (!InitStmt.isUsable())
15028 return StmtError();
15029
15030 // For cond-expression: .floor.iv < NumIterations
15031 ExprResult CondExpr = SemaRef.BuildBinOp(
15032 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15033 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15034 NumIterations);
15035 if (!CondExpr.isUsable())
15036 return StmtError();
15037
15038 // For incr-statement: .floor.iv += DimTileSize
15039 Expr *DimTileSize = MakeDimTileSize(I);
15040 if (!DimTileSize)
15041 return StmtError();
15042 ExprResult IncrStmt = SemaRef.BuildBinOp(
15043 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15044 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15045 DimTileSize);
15046 if (!IncrStmt.isUsable())
15047 return StmtError();
15048
15049 Inner = new (Context)
15050 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15051 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15052 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15053 }
15054
15055 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
15056 AStmt, Inner,
15057 buildPreInits(Context, PreInits));
15058}
15059
15061 Stmt *AStmt,
15062 SourceLocation StartLoc,
15063 SourceLocation EndLoc) {
15064 ASTContext &Context = getASTContext();
15065 Scope *CurScope = SemaRef.getCurScope();
15066
15067 const auto *SizesClause =
15068 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15069 if (!SizesClause ||
15070 llvm::any_of(SizesClause->getSizesRefs(), [](const Expr *SizeExpr) {
15071 return !SizeExpr || SizeExpr->containsErrors();
15072 }))
15073 return StmtError();
15074 unsigned NumLoops = SizesClause->getNumSizes();
15075
15076 // Empty statement should only be possible if there already was an error.
15077 if (!AStmt)
15078 return StmtError();
15079
15080 // Verify and diagnose loop nest.
15082 Stmt *Body = nullptr;
15083 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
15084 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15085 Body, OriginalInits))
15086 return StmtError();
15087
15088 // Delay striping to when template is completely instantiated.
15089 if (SemaRef.CurContext->isDependentContext())
15090 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15091 NumLoops, AStmt, nullptr, nullptr);
15092
15093 assert(LoopHelpers.size() == NumLoops &&
15094 "Expecting loop iteration space dimensionality to match number of "
15095 "affected loops");
15096 assert(OriginalInits.size() == NumLoops &&
15097 "Expecting loop iteration space dimensionality to match number of "
15098 "affected loops");
15099
15100 // Collect all affected loop statements.
15101 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15102 collectLoopStmts(AStmt, LoopStmts);
15103
15104 SmallVector<Stmt *, 4> PreInits;
15105 CaptureVars CopyTransformer(SemaRef);
15106
15107 // Create iteration variables for the generated loops.
15108 SmallVector<VarDecl *, 4> FloorIndVars;
15109 SmallVector<VarDecl *, 4> StripeIndVars;
15110 FloorIndVars.resize(NumLoops);
15111 StripeIndVars.resize(NumLoops);
15112 for (unsigned I : llvm::seq<unsigned>(NumLoops)) {
15113 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15114
15115 assert(LoopHelper.Counters.size() == 1 &&
15116 "Expect single-dimensional loop iteration space");
15117 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15118 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15119 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15120 QualType CntTy = IterVarRef->getType();
15121
15122 // Iteration variable for the stripe (i.e. outer) loop.
15123 {
15124 std::string FloorCntName =
15125 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15126 VarDecl *FloorCntDecl =
15127 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
15128 FloorIndVars[I] = FloorCntDecl;
15129 }
15130
15131 // Iteration variable for the stripe (i.e. inner) loop.
15132 {
15133 std::string StripeCntName =
15134 (Twine(".stripe_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15135
15136 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15137 // used by the expressions to derive the original iteration variable's
15138 // value from the logical iteration number.
15139 auto *StripeCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15140 StripeCntDecl->setDeclName(
15141 &SemaRef.PP.getIdentifierTable().get(StripeCntName));
15142 StripeIndVars[I] = StripeCntDecl;
15143 }
15144
15145 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15146 PreInits);
15147 }
15148
15149 // Once the original iteration values are set, append the innermost body.
15150 Stmt *Inner = Body;
15151
15152 auto MakeDimStripeSize = [&](int I) -> Expr * {
15153 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15154 if (isa<ConstantExpr>(DimStripeSizeExpr))
15155 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
15156
15157 // When the stripe size is not a constant but a variable, it is possible to
15158 // pass non-positive numbers. For instance:
15159 // \code{c}
15160 // int a = 0;
15161 // #pragma omp stripe sizes(a)
15162 // for (int i = 0; i < 42; ++i)
15163 // body(i);
15164 // \endcode
15165 // Although there is no meaningful interpretation of the stripe size, the
15166 // body should still be executed 42 times to avoid surprises. To preserve
15167 // the invariant that every loop iteration is executed exactly once and not
15168 // cause an infinite loop, apply a minimum stripe size of one.
15169 // Build expr:
15170 // \code{c}
15171 // (TS <= 0) ? 1 : TS
15172 // \endcode
15173 QualType DimTy = DimStripeSizeExpr->getType();
15174 uint64_t DimWidth = Context.getTypeSize(DimTy);
15176 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15177 IntegerLiteral *One =
15178 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
15179 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
15180 CurScope, {}, BO_LE,
15181 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), Zero));
15182 Expr *MinOne = new (Context) ConditionalOperator(
15183 Cond, {}, One, {},
15184 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
15186 return MinOne;
15187 };
15188
15189 // Create stripe loops from the inside to the outside.
15190 for (int I = NumLoops - 1; I >= 0; --I) {
15191 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15192 Expr *NumIterations = LoopHelper.NumIterations;
15193 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15194 QualType IVTy = NumIterations->getType();
15195 Stmt *LoopStmt = LoopStmts[I];
15196
15197 // For init-statement: auto .stripe.iv = .floor.iv
15198 SemaRef.AddInitializerToDecl(
15199 StripeIndVars[I],
15200 SemaRef
15201 .DefaultLvalueConversion(
15202 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15203 .get(),
15204 /*DirectInit=*/false);
15205 Decl *CounterDecl = StripeIndVars[I];
15206 StmtResult InitStmt = new (Context)
15207 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15208 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15209 if (!InitStmt.isUsable())
15210 return StmtError();
15211
15212 // For cond-expression:
15213 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
15214 ExprResult EndOfStripe = SemaRef.BuildBinOp(
15215 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15216 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15217 MakeDimStripeSize(I));
15218 if (!EndOfStripe.isUsable())
15219 return StmtError();
15220 ExprResult IsPartialStripe =
15221 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15222 NumIterations, EndOfStripe.get());
15223 if (!IsPartialStripe.isUsable())
15224 return StmtError();
15225 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
15226 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15227 IsPartialStripe.get(), NumIterations, EndOfStripe.get());
15228 if (!MinStripeAndIterSpace.isUsable())
15229 return StmtError();
15230 ExprResult CondExpr = SemaRef.BuildBinOp(
15231 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15232 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar),
15233 MinStripeAndIterSpace.get());
15234 if (!CondExpr.isUsable())
15235 return StmtError();
15236
15237 // For incr-statement: ++.stripe.iv
15238 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15239 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
15240 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar));
15241 if (!IncrStmt.isUsable())
15242 return StmtError();
15243
15244 // Statements to set the original iteration variable's value from the
15245 // logical iteration number.
15246 // Generated for loop is:
15247 // \code
15248 // Original_for_init;
15249 // for (auto .stripe.iv = .floor.iv;
15250 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
15251 // ++.stripe.iv) {
15252 // Original_Body;
15253 // Original_counter_update;
15254 // }
15255 // \endcode
15256 // FIXME: If the innermost body is a loop itself, inserting these
15257 // statements stops it being recognized as a perfectly nested loop (e.g.
15258 // for applying another loop transformation). If this is the case, sink the
15259 // expressions further into the inner loop.
15260 SmallVector<Stmt *, 4> BodyParts;
15261 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15262 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15263 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15264 BodyParts.push_back(Inner);
15265 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15266 Inner->getBeginLoc(), Inner->getEndLoc());
15267 Inner = new (Context)
15268 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15269 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15270 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15271 }
15272
15273 // Create grid loops from the inside to the outside.
15274 for (int I = NumLoops - 1; I >= 0; --I) {
15275 auto &LoopHelper = LoopHelpers[I];
15276 Expr *NumIterations = LoopHelper.NumIterations;
15277 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15278 QualType IVTy = NumIterations->getType();
15279
15280 // For init-statement: auto .grid.iv = 0
15281 SemaRef.AddInitializerToDecl(
15282 FloorIndVars[I],
15283 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15284 /*DirectInit=*/false);
15285 Decl *CounterDecl = FloorIndVars[I];
15286 StmtResult InitStmt = new (Context)
15287 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15288 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15289 if (!InitStmt.isUsable())
15290 return StmtError();
15291
15292 // For cond-expression: .floor.iv < NumIterations
15293 ExprResult CondExpr = SemaRef.BuildBinOp(
15294 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15295 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15296 NumIterations);
15297 if (!CondExpr.isUsable())
15298 return StmtError();
15299
15300 // For incr-statement: .floor.iv += DimStripeSize
15301 ExprResult IncrStmt = SemaRef.BuildBinOp(
15302 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15303 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15304 MakeDimStripeSize(I));
15305 if (!IncrStmt.isUsable())
15306 return StmtError();
15307
15308 Inner = new (Context)
15309 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15310 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15311 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15312 }
15313
15314 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15315 NumLoops, AStmt, Inner,
15316 buildPreInits(Context, PreInits));
15317}
15318
15320 Stmt *AStmt,
15321 SourceLocation StartLoc,
15322 SourceLocation EndLoc) {
15323 ASTContext &Context = getASTContext();
15324 Scope *CurScope = SemaRef.getCurScope();
15325 // Empty statement should only be possible if there already was an error.
15326 if (!AStmt)
15327 return StmtError();
15328
15330 {OMPC_partial, OMPC_full}))
15331 return StmtError();
15332
15333 const OMPFullClause *FullClause =
15334 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15335 const OMPPartialClause *PartialClause =
15336 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15337 assert(!(FullClause && PartialClause) &&
15338 "mutual exclusivity must have been checked before");
15339
15340 constexpr unsigned NumLoops = 1;
15341 Stmt *Body = nullptr;
15343 NumLoops);
15344 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15345 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15346 Body, OriginalInits))
15347 return StmtError();
15348
15349 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15350
15351 // Delay unrolling to when template is completely instantiated.
15352 if (SemaRef.CurContext->isDependentContext())
15353 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15354 NumGeneratedTopLevelLoops, nullptr,
15355 nullptr);
15356
15357 assert(LoopHelpers.size() == NumLoops &&
15358 "Expecting a single-dimensional loop iteration space");
15359 assert(OriginalInits.size() == NumLoops &&
15360 "Expecting a single-dimensional loop iteration space");
15361 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15362
15363 if (FullClause) {
15365 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15366 /*SuppressExprDiags=*/true)
15367 .isUsable()) {
15368 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15369 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15370 << "#pragma omp unroll full";
15371 return StmtError();
15372 }
15373 }
15374
15375 // The generated loop may only be passed to other loop-associated directive
15376 // when a partial clause is specified. Without the requirement it is
15377 // sufficient to generate loop unroll metadata at code-generation.
15378 if (NumGeneratedTopLevelLoops == 0)
15379 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15380 NumGeneratedTopLevelLoops, nullptr,
15381 nullptr);
15382
15383 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15384 // associated with another loop directive.
15385 //
15386 // The canonical loop analysis return by checkTransformableLoopNest assumes
15387 // the following structure to be the same loop without transformations or
15388 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15389 // LoopHelper.Counters;
15390 // for (; IV < LoopHelper.NumIterations; ++IV) {
15391 // LoopHelper.Updates;
15392 // Body;
15393 // }
15394 // \endcode
15395 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15396 // and referenced by LoopHelper.IterationVarRef.
15397 //
15398 // The unrolling directive transforms this into the following loop:
15399 // \code
15400 // OriginalInits; \
15401 // LoopHelper.PreInits; > NewPreInits
15402 // LoopHelper.Counters; /
15403 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15404 // #pragma clang loop unroll_count(Factor)
15405 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15406 // {
15407 // LoopHelper.Updates;
15408 // Body;
15409 // }
15410 // }
15411 // \endcode
15412 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15413 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15414 // references it. If the partially unrolled loop is associated with another
15415 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15416 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15417 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15418 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15419 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15420 // property of the OMPLoopBasedDirective instead of statements in
15421 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15422 // of a canonical loop nest where these PreInits are emitted before the
15423 // outermost directive.
15424
15425 // Find the loop statement.
15426 Stmt *LoopStmt = nullptr;
15427 collectLoopStmts(AStmt, {LoopStmt});
15428
15429 // Determine the PreInit declarations.
15430 SmallVector<Stmt *, 4> PreInits;
15431 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15432
15433 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15434 QualType IVTy = IterationVarRef->getType();
15435 assert(LoopHelper.Counters.size() == 1 &&
15436 "Expecting a single-dimensional loop iteration space");
15437 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15438
15439 // Determine the unroll factor.
15440 uint64_t Factor;
15441 SourceLocation FactorLoc;
15442 if (Expr *FactorVal = PartialClause->getFactor();
15443 FactorVal && !FactorVal->containsErrors()) {
15444 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15445 FactorLoc = FactorVal->getExprLoc();
15446 } else {
15447 // TODO: Use a better profitability model.
15448 Factor = 2;
15449 }
15450 assert(Factor > 0 && "Expected positive unroll factor");
15451 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15453 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
15454 IVTy, FactorLoc);
15455 };
15456
15457 // Iteration variable SourceLocations.
15458 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15459 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15460 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15461
15462 // Internal variable names.
15463 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15464 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15465 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15466
15467 // Create the iteration variable for the unrolled loop.
15468 VarDecl *OuterIVDecl =
15469 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
15470 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15471 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
15472 };
15473
15474 // Iteration variable for the inner loop: Reuse the iteration variable created
15475 // by checkOpenMPLoop.
15476 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15477 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
15478 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15479 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
15480 };
15481
15482 // Make a copy of the NumIterations expression for each use: By the AST
15483 // constraints, every expression object in a DeclContext must be unique.
15484 CaptureVars CopyTransformer(SemaRef);
15485 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15486 return AssertSuccess(
15487 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15488 };
15489
15490 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15491 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
15492 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
15493 /*DirectInit=*/false);
15494 StmtResult InnerInit = new (Context)
15495 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15496 if (!InnerInit.isUsable())
15497 return StmtError();
15498
15499 // Inner For cond-expression:
15500 // \code
15501 // .unroll_inner.iv < .unrolled.iv + Factor &&
15502 // .unroll_inner.iv < NumIterations
15503 // \endcode
15504 // This conjunction of two conditions allows ScalarEvolution to derive the
15505 // maximum trip count of the inner loop.
15506 ExprResult EndOfTile =
15507 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15508 MakeOuterRef(), MakeFactorExpr());
15509 if (!EndOfTile.isUsable())
15510 return StmtError();
15511 ExprResult InnerCond1 =
15512 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15513 MakeInnerRef(), EndOfTile.get());
15514 if (!InnerCond1.isUsable())
15515 return StmtError();
15516 ExprResult InnerCond2 =
15517 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15518 MakeInnerRef(), MakeNumIterations());
15519 if (!InnerCond2.isUsable())
15520 return StmtError();
15521 ExprResult InnerCond =
15522 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15523 InnerCond1.get(), InnerCond2.get());
15524 if (!InnerCond.isUsable())
15525 return StmtError();
15526
15527 // Inner For incr-statement: ++.unroll_inner.iv
15528 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15529 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15530 if (!InnerIncr.isUsable())
15531 return StmtError();
15532
15533 // Inner For statement.
15534 SmallVector<Stmt *> InnerBodyStmts;
15535 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15536 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15537 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15538 InnerBodyStmts.push_back(Body);
15539 CompoundStmt *InnerBody =
15541 Body->getBeginLoc(), Body->getEndLoc());
15542 ForStmt *InnerFor = new (Context)
15543 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15544 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15545 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15546
15547 // Unroll metadata for the inner loop.
15548 // This needs to take into account the remainder portion of the unrolled loop,
15549 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15550 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15551 // the maximum trip count, which will also generate a remainder loop. Just
15552 // `unroll(enable)` (which could have been useful if the user has not
15553 // specified a concrete factor; even though the outer loop cannot be
15554 // influenced anymore, would avoid more code bloat than necessary) will refuse
15555 // the loop because "Won't unroll; remainder loop could not be generated when
15556 // assuming runtime trip count". Even if it did work, it must not choose a
15557 // larger unroll factor than the maximum loop length, or it would always just
15558 // execute the remainder loop.
15559 LoopHintAttr *UnrollHintAttr =
15560 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15561 LoopHintAttr::Numeric, MakeFactorExpr());
15562 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15563 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
15564
15565 // Outer For init-statement: auto .unrolled.iv = 0
15566 SemaRef.AddInitializerToDecl(
15567 OuterIVDecl,
15568 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15569 /*DirectInit=*/false);
15570 StmtResult OuterInit = new (Context)
15571 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15572 if (!OuterInit.isUsable())
15573 return StmtError();
15574
15575 // Outer For cond-expression: .unrolled.iv < NumIterations
15576 ExprResult OuterConde =
15577 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15578 MakeOuterRef(), MakeNumIterations());
15579 if (!OuterConde.isUsable())
15580 return StmtError();
15581
15582 // Outer For incr-statement: .unrolled.iv += Factor
15583 ExprResult OuterIncr =
15584 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15585 MakeOuterRef(), MakeFactorExpr());
15586 if (!OuterIncr.isUsable())
15587 return StmtError();
15588
15589 // Outer For statement.
15590 ForStmt *OuterFor = new (Context)
15591 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15592 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15593 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15594
15595 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15596 NumGeneratedTopLevelLoops, OuterFor,
15597 buildPreInits(Context, PreInits));
15598}
15599
15601 SourceLocation StartLoc,
15602 SourceLocation EndLoc) {
15603 ASTContext &Context = getASTContext();
15604 Scope *CurScope = SemaRef.getCurScope();
15605
15606 // Empty statement should only be possible if there already was an error.
15607 if (!AStmt)
15608 return StmtError();
15609
15610 constexpr unsigned NumLoops = 1;
15611 Stmt *Body = nullptr;
15613 NumLoops);
15614 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15615 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15616 Body, OriginalInits))
15617 return StmtError();
15618
15619 // Delay applying the transformation to when template is completely
15620 // instantiated.
15621 if (SemaRef.CurContext->isDependentContext())
15622 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
15623 NumLoops, nullptr, nullptr);
15624
15625 assert(LoopHelpers.size() == NumLoops &&
15626 "Expecting a single-dimensional loop iteration space");
15627 assert(OriginalInits.size() == NumLoops &&
15628 "Expecting a single-dimensional loop iteration space");
15629 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15630
15631 // Find the loop statement.
15632 Stmt *LoopStmt = nullptr;
15633 collectLoopStmts(AStmt, {LoopStmt});
15634
15635 // Determine the PreInit declarations.
15636 SmallVector<Stmt *> PreInits;
15637 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15638
15639 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15640 QualType IVTy = IterationVarRef->getType();
15641 uint64_t IVWidth = Context.getTypeSize(IVTy);
15642 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15643
15644 // Iteration variable SourceLocations.
15645 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15646 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15647 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15648
15649 // Locations pointing to the transformation.
15650 SourceLocation TransformLoc = StartLoc;
15651 SourceLocation TransformLocBegin = StartLoc;
15652 SourceLocation TransformLocEnd = EndLoc;
15653
15654 // Internal variable names.
15655 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15656 SmallString<64> ForwardIVName(".forward.iv.");
15657 ForwardIVName += OrigVarName;
15658 SmallString<64> ReversedIVName(".reversed.iv.");
15659 ReversedIVName += OrigVarName;
15660
15661 // LoopHelper.Updates will read the logical iteration number from
15662 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
15663 // that logical iteration from it, then assign it to the user loop counter
15664 // variable. We cannot directly use LoopHelper.IterationVarRef as the
15665 // induction variable of the generated loop because it may cause an underflow:
15666 // \code{.c}
15667 // for (unsigned i = 0; i < n; ++i)
15668 // body(i);
15669 // \endcode
15670 //
15671 // Naive reversal:
15672 // \code{.c}
15673 // for (unsigned i = n-1; i >= 0; --i)
15674 // body(i);
15675 // \endcode
15676 //
15677 // Instead, we introduce a new iteration variable representing the logical
15678 // iteration counter of the original loop, convert it to the logical iteration
15679 // number of the reversed loop, then let LoopHelper.Updates compute the user's
15680 // loop iteration variable from it.
15681 // \code{.cpp}
15682 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
15683 // auto .reversed.iv = n - .forward.iv - 1;
15684 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
15685 // body(i); // Body
15686 // }
15687 // \endcode
15688
15689 // Subexpressions with more than one use. One of the constraints of an AST is
15690 // that every node object must appear at most once, hence we define a lambda
15691 // that creates a new AST node at every use.
15692 CaptureVars CopyTransformer(SemaRef);
15693 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15694 return AssertSuccess(
15695 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15696 };
15697
15698 // Create the iteration variable for the forward loop (from 0 to n-1).
15699 VarDecl *ForwardIVDecl =
15700 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
15701 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15702 OrigVarLoc]() {
15703 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
15704 };
15705
15706 // Iteration variable for the reversed induction variable (from n-1 downto 0):
15707 // Reuse the iteration variable created by checkOpenMPLoop.
15708 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15709 ReversedIVDecl->setDeclName(
15710 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15711
15712 // For init-statement:
15713 // \code{.cpp}
15714 // auto .forward.iv = 0;
15715 // \endcode
15716 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
15717 ForwardIVDecl->getType(), OrigVarLoc);
15718 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
15719 StmtResult Init = new (Context)
15720 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15721 if (!Init.isUsable())
15722 return StmtError();
15723
15724 // Forward iv cond-expression:
15725 // \code{.cpp}
15726 // .forward.iv < MakeNumIterations()
15727 // \endcode
15729 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15730 MakeForwardRef(), MakeNumIterations());
15731 if (!Cond.isUsable())
15732 return StmtError();
15733
15734 // Forward incr-statement:
15735 // \code{.c}
15736 // ++.forward.iv
15737 // \endcode
15738 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15739 UO_PreInc, MakeForwardRef());
15740 if (!Incr.isUsable())
15741 return StmtError();
15742
15743 // Reverse the forward-iv:
15744 // \code{.cpp}
15745 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
15746 // \endcode
15747 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
15748 TransformLoc);
15749 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
15750 MakeNumIterations(), One);
15751 if (!Minus.isUsable())
15752 return StmtError();
15753 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
15754 MakeForwardRef());
15755 if (!Minus.isUsable())
15756 return StmtError();
15757 StmtResult InitReversed = new (Context) DeclStmt(
15758 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15759 if (!InitReversed.isUsable())
15760 return StmtError();
15761 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
15762 /*DirectInit=*/false);
15763
15764 // The new loop body.
15765 SmallVector<Stmt *, 4> BodyStmts;
15766 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15767 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
15768 BodyStmts.push_back(InitReversed.get());
15769 llvm::append_range(BodyStmts, LoopHelper.Updates);
15770 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15771 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15772 BodyStmts.push_back(Body);
15773 auto *ReversedBody =
15774 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
15775 Body->getBeginLoc(), Body->getEndLoc());
15776
15777 // Finally create the reversed For-statement.
15778 auto *ReversedFor = new (Context)
15779 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
15780 ReversedBody, LoopHelper.Init->getBeginLoc(),
15781 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15782 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt, NumLoops,
15783 ReversedFor,
15784 buildPreInits(Context, PreInits));
15785}
15786
15788 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15789 SourceLocation EndLoc) {
15790 ASTContext &Context = getASTContext();
15791 DeclContext *CurContext = SemaRef.CurContext;
15792 Scope *CurScope = SemaRef.getCurScope();
15793
15794 // Empty statement should only be possible if there already was an error.
15795 if (!AStmt)
15796 return StmtError();
15797
15798 // interchange without permutation clause swaps two loops.
15799 const OMPPermutationClause *PermutationClause =
15800 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15801 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
15802
15803 // Verify and diagnose loop nest.
15805 Stmt *Body = nullptr;
15806 SmallVector<SmallVector<Stmt *>, 2> OriginalInits;
15807 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15808 LoopHelpers, Body, OriginalInits))
15809 return StmtError();
15810
15811 // Delay interchange to when template is completely instantiated.
15812 if (CurContext->isDependentContext())
15813 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15814 NumLoops, AStmt, nullptr, nullptr);
15815
15816 // An invalid expression in the permutation clause is set to nullptr in
15817 // ActOnOpenMPPermutationClause.
15818 if (PermutationClause &&
15819 llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
15820 return StmtError();
15821
15822 assert(LoopHelpers.size() == NumLoops &&
15823 "Expecting loop iteration space dimensionaly to match number of "
15824 "affected loops");
15825 assert(OriginalInits.size() == NumLoops &&
15826 "Expecting loop iteration space dimensionaly to match number of "
15827 "affected loops");
15828
15829 // Decode the permutation clause.
15830 SmallVector<uint64_t, 2> Permutation;
15831 if (!PermutationClause) {
15832 Permutation = {1, 0};
15833 } else {
15834 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
15835 llvm::BitVector Flags(PermArgs.size());
15836 for (Expr *PermArg : PermArgs) {
15837 std::optional<llvm::APSInt> PermCstExpr =
15838 PermArg->getIntegerConstantExpr(Context);
15839 if (!PermCstExpr)
15840 continue;
15841 uint64_t PermInt = PermCstExpr->getZExtValue();
15842 assert(1 <= PermInt && PermInt <= NumLoops &&
15843 "Must be a permutation; diagnostic emitted in "
15844 "ActOnOpenMPPermutationClause");
15845 if (Flags[PermInt - 1]) {
15846 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15847 Diag(PermArg->getExprLoc(),
15848 diag::err_omp_interchange_permutation_value_repeated)
15849 << PermInt << ExprRange;
15850 continue;
15851 }
15852 Flags[PermInt - 1] = true;
15853
15854 Permutation.push_back(PermInt - 1);
15855 }
15856
15857 if (Permutation.size() != NumLoops)
15858 return StmtError();
15859 }
15860
15861 // Nothing to transform with trivial permutation.
15862 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
15863 auto [Idx, Arg] = P;
15864 return Idx == Arg;
15865 }))
15866 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15867 NumLoops, AStmt, AStmt, nullptr);
15868
15869 // Find the affected loops.
15870 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15871 collectLoopStmts(AStmt, LoopStmts);
15872
15873 // Collect pre-init statements on the order before the permuation.
15874 SmallVector<Stmt *> PreInits;
15875 for (auto I : llvm::seq<int>(NumLoops)) {
15876 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15877
15878 assert(LoopHelper.Counters.size() == 1 &&
15879 "Single-dimensional loop iteration space expected");
15880
15881 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15882 PreInits);
15883 }
15884
15885 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
15886 CaptureVars CopyTransformer(SemaRef);
15887
15888 // Create the permuted loops from the inside to the outside of the
15889 // interchanged loop nest. Body of the innermost new loop is the original
15890 // innermost body.
15891 Stmt *Inner = Body;
15892 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15893 // Get the original loop that belongs to this new position.
15894 uint64_t SourceIdx = Permutation[TargetIdx];
15895 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15896 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15897 assert(SourceHelper.Counters.size() == 1 &&
15898 "Single-dimensional loop iteration space expected");
15899 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
15900
15901 // Normalized loop counter variable: From 0 to n-1, always an integer type.
15902 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
15903 QualType IVTy = IterVarRef->getType();
15904 assert(IVTy->isIntegerType() &&
15905 "Expected the logical iteration counter to be an integer");
15906
15907 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15908 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
15909
15910 // Make a copy of the NumIterations expression for each use: By the AST
15911 // constraints, every expression object in a DeclContext must be unique.
15912 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
15913 return AssertSuccess(
15914 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15915 };
15916
15917 // Iteration variable for the permuted loop. Reuse the one from
15918 // checkOpenMPLoop which will also be used to update the original loop
15919 // variable.
15920 SmallString<64> PermutedCntName(".permuted_");
15921 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
15922 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15923 PermutedCntDecl->setDeclName(
15924 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15925 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15926 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15927 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
15928 };
15929
15930 // For init-statement:
15931 // \code
15932 // auto .permuted_{target}.iv = 0
15933 // \endcode
15934 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
15935 if (!Zero.isUsable())
15936 return StmtError();
15937 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
15938 /*DirectInit=*/false);
15939 StmtResult InitStmt = new (Context)
15940 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
15941 OrigCntVar->getEndLoc());
15942 if (!InitStmt.isUsable())
15943 return StmtError();
15944
15945 // For cond-expression:
15946 // \code
15947 // .permuted_{target}.iv < MakeNumIterations()
15948 // \endcode
15949 ExprResult CondExpr =
15950 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15951 MakePermutedRef(), MakeNumIterations());
15952 if (!CondExpr.isUsable())
15953 return StmtError();
15954
15955 // For incr-statement:
15956 // \code
15957 // ++.tile.iv
15958 // \endcode
15959 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15960 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15961 if (!IncrStmt.isUsable())
15962 return StmtError();
15963
15964 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
15965 SourceHelper.Updates.end());
15966 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15967 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15968 BodyParts.push_back(Inner);
15969 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15970 Inner->getBeginLoc(), Inner->getEndLoc());
15971 Inner = new (Context) ForStmt(
15972 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
15973 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
15974 SourceHelper.Inc->getEndLoc());
15975 }
15976
15977 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15978 NumLoops, AStmt, Inner,
15979 buildPreInits(Context, PreInits));
15980}
15981
15983 Stmt *AStmt,
15984 SourceLocation StartLoc,
15985 SourceLocation EndLoc) {
15986
15987 ASTContext &Context = getASTContext();
15988 DeclContext *CurrContext = SemaRef.CurContext;
15989 Scope *CurScope = SemaRef.getCurScope();
15990 CaptureVars CopyTransformer(SemaRef);
15991
15992 // Ensure the structured block is not empty
15993 if (!AStmt)
15994 return StmtError();
15995
15996 // Defer transformation in dependent contexts
15997 // The NumLoopNests argument is set to a placeholder 1 (even though
15998 // using looprange fuse could yield up to 3 top level loop nests)
15999 // because a dependent context could prevent determining its true value
16000 if (CurrContext->isDependentContext())
16001 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
16002 /* NumLoops */ 1, AStmt, nullptr, nullptr);
16003
16004 // Validate that the potential loop sequence is transformable for fusion
16005 // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops
16006 LoopSequenceAnalysis SeqAnalysis;
16007 if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, SeqAnalysis, Context))
16008 return StmtError();
16009
16010 // SeqAnalysis.LoopSeqSize exists mostly to handle dependent contexts,
16011 // otherwise it must be the same as SeqAnalysis.Loops.size().
16012 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16013 "Inconsistent size of the loop sequence and the number of loops "
16014 "found in the sequence");
16015
16016 // Handle clauses, which can be any of the following: [looprange, apply]
16017 const auto *LRC =
16018 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16019
16020 // The clause arguments are invalidated if any error arises
16021 // such as non-constant or non-positive arguments
16022 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16023 return StmtError();
16024
16025 // Delayed semantic check of LoopRange constraint
16026 // Evaluates the loop range arguments and returns the first and count values
16027 auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count,
16028 uint64_t &FirstVal,
16029 uint64_t &CountVal) {
16030 llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Context);
16031 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context);
16032 FirstVal = FirstInt.getZExtValue();
16033 CountVal = CountInt.getZExtValue();
16034 };
16035
16036 // OpenMP [6.0, Restrictions]
16037 // first + count - 1 must not evaluate to a value greater than the
16038 // loop sequence length of the associated canonical loop sequence.
16039 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16040 unsigned NumLoops) -> bool {
16041 return FirstVal + CountVal - 1 <= NumLoops;
16042 };
16043 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16044
16045 // Validates the loop range after evaluating the semantic information
16046 // and ensures that the range is valid for the given loop sequence size.
16047 // Expressions are evaluated at compile time to obtain constant values.
16048 if (LRC) {
16049 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16050 CountVal);
16051 if (CountVal == 1)
16052 SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion)
16053 << getOpenMPDirectiveName(OMPD_fuse);
16054
16055 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16056 SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange)
16057 << getOpenMPDirectiveName(OMPD_fuse) << FirstVal
16058 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16059 return StmtError();
16060 }
16061
16062 LastVal = FirstVal + CountVal - 1;
16063 }
16064
16065 // Complete fusion generates a single canonical loop nest
16066 // However looprange clause may generate several loop nests
16067 unsigned NumGeneratedTopLevelLoops =
16068 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16069
16070 // Emit a warning for redundant loop fusion when the sequence contains only
16071 // one loop.
16072 if (SeqAnalysis.LoopSeqSize == 1)
16073 SemaRef.Diag(AStmt->getBeginLoc(), diag::warn_omp_redundant_fusion)
16074 << getOpenMPDirectiveName(OMPD_fuse);
16075
16076 // Select the type with the largest bit width among all induction variables
16077 QualType IVType =
16078 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16079 for (unsigned I : llvm::seq<unsigned>(FirstVal, LastVal)) {
16080 QualType CurrentIVType =
16081 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16082 if (Context.getTypeSize(CurrentIVType) > Context.getTypeSize(IVType)) {
16083 IVType = CurrentIVType;
16084 }
16085 }
16086 uint64_t IVBitWidth = Context.getIntWidth(IVType);
16087
16088 // Create pre-init declarations for all loops lower bounds, upper bounds,
16089 // strides and num-iterations for every top level loop in the fusion
16090 SmallVector<VarDecl *, 4> LBVarDecls;
16091 SmallVector<VarDecl *, 4> STVarDecls;
16092 SmallVector<VarDecl *, 4> NIVarDecls;
16093 SmallVector<VarDecl *, 4> UBVarDecls;
16094 SmallVector<VarDecl *, 4> IVVarDecls;
16095
16096 // Helper lambda to create variables for bounds, strides, and other
16097 // expressions. Generates both the variable declaration and the corresponding
16098 // initialization statement.
16099 auto CreateHelperVarAndStmt =
16100 [&, &SemaRef = SemaRef](Expr *ExprToCopy, const std::string &BaseName,
16101 unsigned I, bool NeedsNewVD = false) {
16102 Expr *TransformedExpr =
16103 AssertSuccess(CopyTransformer.TransformExpr(ExprToCopy));
16104 if (!TransformedExpr)
16105 return std::pair<VarDecl *, StmtResult>(nullptr, StmtError());
16106
16107 auto Name = (Twine(".omp.") + BaseName + std::to_string(I)).str();
16108
16109 VarDecl *VD;
16110 if (NeedsNewVD) {
16111 VD = buildVarDecl(SemaRef, SourceLocation(), IVType, Name);
16112 SemaRef.AddInitializerToDecl(VD, TransformedExpr, false);
16113 } else {
16114 // Create a unique variable name
16115 DeclRefExpr *DRE = cast<DeclRefExpr>(TransformedExpr);
16116 VD = cast<VarDecl>(DRE->getDecl());
16117 VD->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name));
16118 }
16119 // Create the corresponding declaration statement
16120 StmtResult DeclStmt = new (Context) class DeclStmt(
16122 return std::make_pair(VD, DeclStmt);
16123 };
16124
16125 // PreInits hold a sequence of variable declarations that must be executed
16126 // before the fused loop begins. These include bounds, strides, and other
16127 // helper variables required for the transformation. Other loop transforms
16128 // also contain their own preinits
16129 SmallVector<Stmt *> PreInits;
16130
16131 // Update the general preinits using the preinits generated by loop sequence
16132 // generating loop transformations. These preinits differ slightly from
16133 // single-loop transformation preinits, as they can be detached from a
16134 // specific loop inside multiple generated loop nests. This happens
16135 // because certain helper variables, like '.omp.fuse.max', are introduced to
16136 // handle fused iteration spaces and may not be directly tied to a single
16137 // original loop. The preinit structure must ensure that hidden variables
16138 // like '.omp.fuse.max' are still properly handled.
16139 // Transformations that apply this concept: Loopranged Fuse, Split
16140 llvm::append_range(PreInits, SeqAnalysis.LoopSequencePreInits);
16141
16142 // Process each single loop to generate and collect declarations
16143 // and statements for all helper expressions related to
16144 // particular single loop nests
16145
16146 // Also In the case of the fused loops, we keep track of their original
16147 // inits by appending them to their preinits statement, and in the case of
16148 // transformations, also append their preinits (which contain the original
16149 // loop initialization statement or other statements)
16150
16151 // Firstly we need to set TransformIndex to match the begining of the
16152 // looprange section
16153 unsigned int TransformIndex = 0;
16154 for (unsigned I : llvm::seq<unsigned>(FirstVal - 1)) {
16155 if (SeqAnalysis.Loops[I].isLoopTransformation())
16156 ++TransformIndex;
16157 }
16158
16159 for (unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16160 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16161 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
16162 SeqAnalysis.Loops[I].TheForStmt,
16163 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16164 } else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16165 // For transformed loops, insert both pre-inits and original inits.
16166 // Order matters: pre-inits may define variables used in the original
16167 // inits such as upper bounds...
16168 SmallVector<Stmt *> &TransformPreInit =
16169 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16170 llvm::append_range(PreInits, TransformPreInit);
16171
16172 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
16173 SeqAnalysis.Loops[I].TheForStmt,
16174 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16175 }
16176 auto [UBVD, UBDStmt] =
16177 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB, "ub", J);
16178 auto [LBVD, LBDStmt] =
16179 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB, "lb", J);
16180 auto [STVD, STDStmt] =
16181 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST, "st", J);
16182 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16183 SeqAnalysis.Loops[I].HelperExprs.NumIterations, "ni", J, true);
16184 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16185 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef, "iv", J);
16186
16187 assert(LBVD && STVD && NIVD && IVVD &&
16188 "OpenMP Fuse Helper variables creation failed");
16189
16190 UBVarDecls.push_back(UBVD);
16191 LBVarDecls.push_back(LBVD);
16192 STVarDecls.push_back(STVD);
16193 NIVarDecls.push_back(NIVD);
16194 IVVarDecls.push_back(IVVD);
16195
16196 PreInits.push_back(LBDStmt.get());
16197 PreInits.push_back(STDStmt.get());
16198 PreInits.push_back(NIDStmt.get());
16199 PreInits.push_back(IVDStmt.get());
16200 }
16201
16202 auto MakeVarDeclRef = [&SemaRef = this->SemaRef](VarDecl *VD) {
16203 return buildDeclRefExpr(SemaRef, VD, VD->getType(), VD->getLocation(),
16204 false);
16205 };
16206
16207 // Following up the creation of the final fused loop will be performed
16208 // which has the following shape (considering the selected loops):
16209 //
16210 // for (fuse.index = 0; fuse.index < max(ni0, ni1..., nik); ++fuse.index) {
16211 // if (fuse.index < ni0){
16212 // iv0 = lb0 + st0 * fuse.index;
16213 // original.index0 = iv0
16214 // body(0);
16215 // }
16216 // if (fuse.index < ni1){
16217 // iv1 = lb1 + st1 * fuse.index;
16218 // original.index1 = iv1
16219 // body(1);
16220 // }
16221 //
16222 // ...
16223 //
16224 // if (fuse.index < nik){
16225 // ivk = lbk + stk * fuse.index;
16226 // original.indexk = ivk
16227 // body(k); Expr *InitVal = IntegerLiteral::Create(Context,
16228 // llvm::APInt(IVWidth, 0),
16229 // }
16230
16231 // 1. Create the initialized fuse index
16232 StringRef IndexName = ".omp.fuse.index";
16233 Expr *InitVal = IntegerLiteral::Create(Context, llvm::APInt(IVBitWidth, 0),
16234 IVType, SourceLocation());
16235 VarDecl *IndexDecl =
16236 buildVarDecl(SemaRef, {}, IVType, IndexName, nullptr, nullptr);
16237 SemaRef.AddInitializerToDecl(IndexDecl, InitVal, false);
16238 StmtResult InitStmt = new (Context)
16240
16241 if (!InitStmt.isUsable())
16242 return StmtError();
16243
16244 auto MakeIVRef = [&SemaRef = this->SemaRef, IndexDecl, IVType,
16245 Loc = InitVal->getExprLoc()]() {
16246 return buildDeclRefExpr(SemaRef, IndexDecl, IVType, Loc, false);
16247 };
16248
16249 // 2. Iteratively compute the max number of logical iterations Max(NI_1, NI_2,
16250 // ..., NI_k)
16251 //
16252 // This loop accumulates the maximum value across multiple expressions,
16253 // ensuring each step constructs a unique AST node for correctness. By using
16254 // intermediate temporary variables and conditional operators, we maintain
16255 // distinct nodes and avoid duplicating subtrees, For instance, max(a,b,c):
16256 // omp.temp0 = max(a, b)
16257 // omp.temp1 = max(omp.temp0, c)
16258 // omp.fuse.max = max(omp.temp1, omp.temp0)
16259
16260 ExprResult MaxExpr;
16261 // I is the range of loops in the sequence that we fuse.
16262 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16263 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16264 QualType NITy = NIRef->getType();
16265
16266 if (MaxExpr.isUnset()) {
16267 // Initialize MaxExpr with the first NI expression
16268 MaxExpr = NIRef;
16269 } else {
16270 // Create a new acummulator variable t_i = MaxExpr
16271 std::string TempName = (Twine(".omp.temp.") + Twine(J)).str();
16272 VarDecl *TempDecl =
16273 buildVarDecl(SemaRef, {}, NITy, TempName, nullptr, nullptr);
16274 TempDecl->setInit(MaxExpr.get());
16275 DeclRefExpr *TempRef =
16276 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
16277 DeclRefExpr *TempRef2 =
16278 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
16279 // Add a DeclStmt to PreInits to ensure the variable is declared.
16280 StmtResult TempStmt = new (Context)
16282
16283 if (!TempStmt.isUsable())
16284 return StmtError();
16285 PreInits.push_back(TempStmt.get());
16286
16287 // Build MaxExpr <-(MaxExpr > NIRef ? MaxExpr : NIRef)
16289 SemaRef.BuildBinOp(nullptr, SourceLocation(), BO_GT, TempRef, NIRef);
16290 // Handle any errors in Comparison creation
16291 if (!Comparison.isUsable())
16292 return StmtError();
16293
16294 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
16295 // Update MaxExpr using a conditional expression to hold the max value
16296 MaxExpr = new (Context) ConditionalOperator(
16297 Comparison.get(), SourceLocation(), TempRef2, SourceLocation(),
16298 NIRef2->getExprStmt(), NITy, VK_LValue, OK_Ordinary);
16299
16300 if (!MaxExpr.isUsable())
16301 return StmtError();
16302 }
16303 }
16304 if (!MaxExpr.isUsable())
16305 return StmtError();
16306
16307 // 3. Declare the max variable
16308 const std::string MaxName = Twine(".omp.fuse.max").str();
16309 VarDecl *MaxDecl =
16310 buildVarDecl(SemaRef, {}, IVType, MaxName, nullptr, nullptr);
16311 MaxDecl->setInit(MaxExpr.get());
16312 DeclRefExpr *MaxRef = buildDeclRefExpr(SemaRef, MaxDecl, IVType, {}, false);
16313 StmtResult MaxStmt = new (Context)
16315
16316 if (MaxStmt.isInvalid())
16317 return StmtError();
16318 PreInits.push_back(MaxStmt.get());
16319
16320 // 4. Create condition Expr: index < n_max
16321 ExprResult CondExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT,
16322 MakeIVRef(), MaxRef);
16323 if (!CondExpr.isUsable())
16324 return StmtError();
16325
16326 // 5. Increment Expr: ++index
16327 ExprResult IncrExpr =
16328 SemaRef.BuildUnaryOp(CurScope, SourceLocation(), UO_PreInc, MakeIVRef());
16329 if (!IncrExpr.isUsable())
16330 return StmtError();
16331
16332 // 6. Build the Fused Loop Body
16333 // The final fused loop iterates over the maximum logical range. Inside the
16334 // loop, each original loop's index is calculated dynamically, and its body
16335 // is executed conditionally.
16336 //
16337 // Each sub-loop's body is guarded by a conditional statement to ensure
16338 // it executes only within its logical iteration range:
16339 //
16340 // if (fuse.index < ni_k){
16341 // iv_k = lb_k + st_k * fuse.index;
16342 // original.index = iv_k
16343 // body(k);
16344 // }
16345
16346 CompoundStmt *FusedBody = nullptr;
16347 SmallVector<Stmt *, 4> FusedBodyStmts;
16348 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16349 // Assingment of the original sub-loop index to compute the logical index
16350 // IV_k = LB_k + omp.fuse.index * ST_k
16351 ExprResult IdxExpr =
16352 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Mul,
16353 MakeVarDeclRef(STVarDecls[J]), MakeIVRef());
16354 if (!IdxExpr.isUsable())
16355 return StmtError();
16356 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Add,
16357 MakeVarDeclRef(LBVarDecls[J]), IdxExpr.get());
16358
16359 if (!IdxExpr.isUsable())
16360 return StmtError();
16361 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Assign,
16362 MakeVarDeclRef(IVVarDecls[J]), IdxExpr.get());
16363 if (!IdxExpr.isUsable())
16364 return StmtError();
16365
16366 // Update the original i_k = IV_k
16367 SmallVector<Stmt *, 4> BodyStmts;
16368 BodyStmts.push_back(IdxExpr.get());
16369 llvm::append_range(BodyStmts, SeqAnalysis.Loops[I].HelperExprs.Updates);
16370
16371 // If the loop is a CXXForRangeStmt then the iterator variable is needed
16372 if (auto *SourceCXXFor =
16373 dyn_cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt))
16374 BodyStmts.push_back(SourceCXXFor->getLoopVarStmt());
16375
16376 Stmt *Body =
16377 (isa<ForStmt>(SeqAnalysis.Loops[I].TheForStmt))
16378 ? cast<ForStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody()
16379 : cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody();
16380 BodyStmts.push_back(Body);
16381
16382 CompoundStmt *CombinedBody =
16383 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
16386 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT, MakeIVRef(),
16387 MakeVarDeclRef(NIVarDecls[J]));
16388
16389 if (!Condition.isUsable())
16390 return StmtError();
16391
16392 IfStmt *IfStatement = IfStmt::Create(
16393 Context, SourceLocation(), IfStatementKind::Ordinary, nullptr, nullptr,
16394 Condition.get(), SourceLocation(), SourceLocation(), CombinedBody,
16395 SourceLocation(), nullptr);
16396
16397 FusedBodyStmts.push_back(IfStatement);
16398 }
16399 FusedBody = CompoundStmt::Create(Context, FusedBodyStmts, FPOptionsOverride(),
16401
16402 // 7. Construct the final fused loop
16403 ForStmt *FusedForStmt = new (Context)
16404 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, IncrExpr.get(),
16405 FusedBody, InitStmt.get()->getBeginLoc(), SourceLocation(),
16406 IncrExpr.get()->getEndLoc());
16407
16408 // In the case of looprange, the result of fuse won't simply
16409 // be a single loop (ForStmt), but rather a loop sequence
16410 // (CompoundStmt) of 3 parts: the pre-fusion loops, the fused loop
16411 // and the post-fusion loops, preserving its original order.
16412 //
16413 // Note: If looprange clause produces a single fused loop nest then
16414 // this compound statement wrapper is unnecessary (Therefore this
16415 // treatment is skipped)
16416
16417 Stmt *FusionStmt = FusedForStmt;
16418 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
16419 SmallVector<Stmt *, 4> FinalLoops;
16420
16421 // Reset the transform index
16422 TransformIndex = 0;
16423
16424 // Collect all non-fused loops before and after the fused region.
16425 // Pre-fusion and post-fusion loops are inserted in order exploiting their
16426 // symmetry, along with their corresponding transformation pre-inits if
16427 // needed. The fused loop is added between the two regions.
16428 for (unsigned I : llvm::seq<unsigned>(SeqAnalysis.LoopSeqSize)) {
16429 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
16430 // Update the Transformation counter to skip already treated
16431 // loop transformations
16432 if (!SeqAnalysis.Loops[I].isLoopTransformation())
16433 ++TransformIndex;
16434 continue;
16435 }
16436
16437 // No need to handle:
16438 // Regular loops: they are kept intact as-is.
16439 // Loop-sequence-generating transformations: already handled earlier.
16440 // Only TransformSingleLoop requires inserting pre-inits here
16441 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16442 const auto &TransformPreInit =
16443 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16444 if (!TransformPreInit.empty())
16445 llvm::append_range(PreInits, TransformPreInit);
16446 }
16447
16448 FinalLoops.push_back(SeqAnalysis.Loops[I].TheForStmt);
16449 }
16450
16451 FinalLoops.insert(FinalLoops.begin() + (FirstVal - 1), FusedForStmt);
16452 FusionStmt = CompoundStmt::Create(Context, FinalLoops, FPOptionsOverride(),
16454 }
16455 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
16456 NumGeneratedTopLevelLoops, AStmt, FusionStmt,
16457 buildPreInits(Context, PreInits));
16458}
16459
16461 Expr *Expr,
16462 SourceLocation StartLoc,
16463 SourceLocation LParenLoc,
16464 SourceLocation EndLoc) {
16465 OMPClause *Res = nullptr;
16466 switch (Kind) {
16467 case OMPC_final:
16468 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
16469 break;
16470 case OMPC_safelen:
16471 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
16472 break;
16473 case OMPC_simdlen:
16474 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
16475 break;
16476 case OMPC_allocator:
16477 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
16478 break;
16479 case OMPC_collapse:
16480 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
16481 break;
16482 case OMPC_ordered:
16483 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
16484 break;
16485 case OMPC_nowait:
16486 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc, LParenLoc, Expr);
16487 break;
16488 case OMPC_priority:
16489 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
16490 break;
16491 case OMPC_hint:
16492 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
16493 break;
16494 case OMPC_depobj:
16495 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
16496 break;
16497 case OMPC_detach:
16498 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
16499 break;
16500 case OMPC_novariants:
16501 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
16502 break;
16503 case OMPC_nocontext:
16504 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
16505 break;
16506 case OMPC_filter:
16507 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
16508 break;
16509 case OMPC_partial:
16510 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
16511 break;
16512 case OMPC_message:
16513 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
16514 break;
16515 case OMPC_align:
16516 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
16517 break;
16518 case OMPC_ompx_dyn_cgroup_mem:
16519 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
16520 break;
16521 case OMPC_holds:
16522 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
16523 break;
16524 case OMPC_dyn_groupprivate:
16525 case OMPC_grainsize:
16526 case OMPC_num_tasks:
16527 case OMPC_num_threads:
16528 case OMPC_device:
16529 case OMPC_if:
16530 case OMPC_default:
16531 case OMPC_proc_bind:
16532 case OMPC_schedule:
16533 case OMPC_private:
16534 case OMPC_firstprivate:
16535 case OMPC_lastprivate:
16536 case OMPC_shared:
16537 case OMPC_reduction:
16538 case OMPC_task_reduction:
16539 case OMPC_in_reduction:
16540 case OMPC_linear:
16541 case OMPC_aligned:
16542 case OMPC_copyin:
16543 case OMPC_copyprivate:
16544 case OMPC_untied:
16545 case OMPC_mergeable:
16546 case OMPC_threadprivate:
16547 case OMPC_groupprivate:
16548 case OMPC_sizes:
16549 case OMPC_allocate:
16550 case OMPC_flush:
16551 case OMPC_read:
16552 case OMPC_write:
16553 case OMPC_update:
16554 case OMPC_capture:
16555 case OMPC_compare:
16556 case OMPC_seq_cst:
16557 case OMPC_acq_rel:
16558 case OMPC_acquire:
16559 case OMPC_release:
16560 case OMPC_relaxed:
16561 case OMPC_depend:
16562 case OMPC_threads:
16563 case OMPC_simd:
16564 case OMPC_map:
16565 case OMPC_nogroup:
16566 case OMPC_dist_schedule:
16567 case OMPC_defaultmap:
16568 case OMPC_unknown:
16569 case OMPC_uniform:
16570 case OMPC_to:
16571 case OMPC_from:
16572 case OMPC_use_device_ptr:
16573 case OMPC_use_device_addr:
16574 case OMPC_is_device_ptr:
16575 case OMPC_unified_address:
16576 case OMPC_unified_shared_memory:
16577 case OMPC_reverse_offload:
16578 case OMPC_dynamic_allocators:
16579 case OMPC_atomic_default_mem_order:
16580 case OMPC_self_maps:
16581 case OMPC_device_type:
16582 case OMPC_match:
16583 case OMPC_nontemporal:
16584 case OMPC_order:
16585 case OMPC_at:
16586 case OMPC_severity:
16587 case OMPC_destroy:
16588 case OMPC_inclusive:
16589 case OMPC_exclusive:
16590 case OMPC_uses_allocators:
16591 case OMPC_affinity:
16592 case OMPC_when:
16593 case OMPC_bind:
16594 case OMPC_num_teams:
16595 case OMPC_thread_limit:
16596 default:
16597 llvm_unreachable("Clause is not allowed.");
16598 }
16599 return Res;
16600}
16601
16602// An OpenMP directive such as 'target parallel' has two captured regions:
16603// for the 'target' and 'parallel' respectively. This function returns
16604// the region in which to capture expressions associated with a clause.
16605// A return value of OMPD_unknown signifies that the expression should not
16606// be captured.
16608 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
16609 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
16610 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
16611 "Invalid directive with CKind-clause");
16612
16613 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
16614 if (NameModifier != OMPD_unknown &&
16615 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
16616 return OMPD_unknown;
16617
16618 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
16619
16620 // [5.2:341:24-30]
16621 // If the clauses have expressions on them, such as for various clauses where
16622 // the argument of the clause is an expression, or lower-bound, length, or
16623 // stride expressions inside array sections (or subscript and stride
16624 // expressions in subscript-triplet for Fortran), or linear-step or alignment
16625 // expressions, the expressions are evaluated immediately before the construct
16626 // to which the clause has been split or duplicated per the above rules
16627 // (therefore inside of the outer leaf constructs). However, the expressions
16628 // inside the num_teams and thread_limit clauses are always evaluated before
16629 // the outermost leaf construct.
16630
16631 // Process special cases first.
16632 switch (CKind) {
16633 case OMPC_if:
16634 switch (DKind) {
16635 case OMPD_teams_loop:
16636 case OMPD_target_teams_loop:
16637 // For [target] teams loop, assume capture region is 'teams' so it's
16638 // available for codegen later to use if/when necessary.
16639 return OMPD_teams;
16640 case OMPD_target_update:
16641 case OMPD_target_enter_data:
16642 case OMPD_target_exit_data:
16643 return OMPD_task;
16644 default:
16645 break;
16646 }
16647 break;
16648 case OMPC_num_teams:
16649 case OMPC_thread_limit:
16650 case OMPC_ompx_dyn_cgroup_mem:
16651 case OMPC_dyn_groupprivate:
16652 // TODO: This may need to consider teams too.
16653 if (Leafs[0] == OMPD_target)
16654 return OMPD_target;
16655 break;
16656 case OMPC_device:
16657 if (Leafs[0] == OMPD_target ||
16658 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
16659 OMPD_target_enter_data, OMPD_target_exit_data},
16660 DKind))
16661 return OMPD_task;
16662 break;
16663 case OMPC_novariants:
16664 case OMPC_nocontext:
16665 if (DKind == OMPD_dispatch)
16666 return OMPD_task;
16667 break;
16668 case OMPC_when:
16669 if (DKind == OMPD_metadirective)
16670 return OMPD_metadirective;
16671 break;
16672 case OMPC_filter:
16673 return OMPD_unknown;
16674 default:
16675 break;
16676 }
16677
16678 // If none of the special cases above applied, and DKind is a capturing
16679 // directive, find the innermost enclosing leaf construct that allows the
16680 // clause, and returns the corresponding capture region.
16681
16682 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
16683 // Find the index in "Leafs" of the last leaf that allows the given
16684 // clause. The search will only include indexes [0, EndIdx).
16685 // EndIdx may be set to the index of the NameModifier, if present.
16686 int InnermostIdx = [&]() {
16687 for (int I = EndIdx - 1; I >= 0; --I) {
16688 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
16689 return I;
16690 }
16691 return -1;
16692 }();
16693
16694 // Find the nearest enclosing capture region.
16696 for (int I = InnermostIdx - 1; I >= 0; --I) {
16697 if (!isOpenMPCapturingDirective(Leafs[I]))
16698 continue;
16699 Regions.clear();
16700 getOpenMPCaptureRegions(Regions, Leafs[I]);
16701 if (Regions[0] != OMPD_unknown)
16702 return Regions.back();
16703 }
16704 return OMPD_unknown;
16705 };
16706
16707 if (isOpenMPCapturingDirective(DKind)) {
16708 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
16709 for (int I = 0, E = Leafs.size(); I != E; ++I) {
16710 if (Leafs[I] == Dir)
16711 return I + 1;
16712 }
16713 return 0;
16714 };
16715
16716 int End = NameModifier == OMPD_unknown ? Leafs.size()
16717 : GetLeafIndex(NameModifier);
16718 return GetEnclosingRegion(End, CKind);
16719 }
16720
16721 return OMPD_unknown;
16722}
16723
16725 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
16726 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
16727 SourceLocation ColonLoc, SourceLocation EndLoc) {
16728 Expr *ValExpr = Condition;
16729 Stmt *HelperValStmt = nullptr;
16730 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16731 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16732 !Condition->isInstantiationDependent() &&
16733 !Condition->containsUnexpandedParameterPack()) {
16734 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
16735 if (Val.isInvalid())
16736 return nullptr;
16737
16738 ValExpr = Val.get();
16739
16740 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16741 CaptureRegion = getOpenMPCaptureRegionForClause(
16742 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
16743 if (CaptureRegion != OMPD_unknown &&
16744 !SemaRef.CurContext->isDependentContext()) {
16745 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16746 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16747 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16748 HelperValStmt = buildPreInits(getASTContext(), Captures);
16749 }
16750 }
16751
16752 return new (getASTContext())
16753 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16754 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16755}
16756
16758 SourceLocation StartLoc,
16759 SourceLocation LParenLoc,
16760 SourceLocation EndLoc) {
16761 Expr *ValExpr = Condition;
16762 Stmt *HelperValStmt = nullptr;
16763 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16764 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16765 !Condition->isInstantiationDependent() &&
16766 !Condition->containsUnexpandedParameterPack()) {
16767 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
16768 if (Val.isInvalid())
16769 return nullptr;
16770
16771 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16772
16773 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16774 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
16775 getLangOpts().OpenMP);
16776 if (CaptureRegion != OMPD_unknown &&
16777 !SemaRef.CurContext->isDependentContext()) {
16778 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16779 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16780 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16781 HelperValStmt = buildPreInits(getASTContext(), Captures);
16782 }
16783 }
16784
16785 return new (getASTContext()) OMPFinalClause(
16786 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16787}
16788
16791 Expr *Op) {
16792 if (!Op)
16793 return ExprError();
16794
16795 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
16796 public:
16797 IntConvertDiagnoser()
16798 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
16799 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16800 QualType T) override {
16801 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16802 }
16803 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16804 QualType T) override {
16805 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16806 }
16807 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16808 QualType T,
16809 QualType ConvTy) override {
16810 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16811 }
16812 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16813 QualType ConvTy) override {
16814 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16815 << ConvTy->isEnumeralType() << ConvTy;
16816 }
16817 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16818 QualType T) override {
16819 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16820 }
16821 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16822 QualType ConvTy) override {
16823 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16824 << ConvTy->isEnumeralType() << ConvTy;
16825 }
16826 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16827 QualType) override {
16828 llvm_unreachable("conversion functions are permitted");
16829 }
16830 } ConvertDiagnoser;
16831 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16832}
16833
16834static bool
16836 bool StrictlyPositive, bool BuildCapture = false,
16837 OpenMPDirectiveKind DKind = OMPD_unknown,
16838 OpenMPDirectiveKind *CaptureRegion = nullptr,
16839 Stmt **HelperValStmt = nullptr) {
16840 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16841 !ValExpr->isInstantiationDependent()) {
16842 SourceLocation Loc = ValExpr->getExprLoc();
16844 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16845 if (Value.isInvalid())
16846 return false;
16847
16848 ValExpr = Value.get();
16849 // The expression must evaluate to a non-negative integer value.
16850 if (std::optional<llvm::APSInt> Result =
16851 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16852 if (Result->isSigned() &&
16853 !((!StrictlyPositive && Result->isNonNegative()) ||
16854 (StrictlyPositive && Result->isStrictlyPositive()))) {
16855 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16856 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
16857 << ValExpr->getSourceRange();
16858 return false;
16859 }
16860 }
16861 if (!BuildCapture)
16862 return true;
16863 *CaptureRegion =
16864 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16865 if (*CaptureRegion != OMPD_unknown &&
16866 !SemaRef.CurContext->isDependentContext()) {
16867 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16868 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16869 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16870 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16871 }
16872 }
16873 return true;
16874}
16875
16876static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
16877 unsigned Last,
16878 ArrayRef<unsigned> Exclude = {}) {
16879 SmallString<256> Buffer;
16880 llvm::raw_svector_ostream Out(Buffer);
16881 unsigned Skipped = Exclude.size();
16882 for (unsigned I = First; I < Last; ++I) {
16883 if (llvm::is_contained(Exclude, I)) {
16884 --Skipped;
16885 continue;
16886 }
16887 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
16888 if (I + Skipped + 2 == Last)
16889 Out << " or ";
16890 else if (I + Skipped + 1 != Last)
16891 Out << ", ";
16892 }
16893 return std::string(Out.str());
16894}
16895
16897 OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads,
16898 SourceLocation StartLoc, SourceLocation LParenLoc,
16899 SourceLocation ModifierLoc, SourceLocation EndLoc) {
16900 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 60) &&
16901 "Unexpected num_threads modifier in OpenMP < 60.");
16902
16903 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTHREADS_unknown) {
16904 std::string Values = getListOfPossibleValues(OMPC_num_threads, /*First=*/0,
16906 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
16907 << Values << getOpenMPClauseNameForDiag(OMPC_num_threads);
16908 return nullptr;
16909 }
16910
16911 Expr *ValExpr = NumThreads;
16912 Stmt *HelperValStmt = nullptr;
16913
16914 // OpenMP [2.5, Restrictions]
16915 // The num_threads expression must evaluate to a positive integer value.
16916 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
16917 /*StrictlyPositive=*/true))
16918 return nullptr;
16919
16920 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16922 DKind, OMPC_num_threads, getLangOpts().OpenMP);
16923 if (CaptureRegion != OMPD_unknown &&
16924 !SemaRef.CurContext->isDependentContext()) {
16925 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16926 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16927 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16928 HelperValStmt = buildPreInits(getASTContext(), Captures);
16929 }
16930
16931 return new (getASTContext())
16932 OMPNumThreadsClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
16933 StartLoc, LParenLoc, ModifierLoc, EndLoc);
16934}
16935
16937 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
16938 bool SuppressExprDiags) {
16939 if (!E)
16940 return ExprError();
16941 if (E->isValueDependent() || E->isTypeDependent() ||
16943 return E;
16944
16945 llvm::APSInt Result;
16946 ExprResult ICE;
16947 if (SuppressExprDiags) {
16948 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16949 // expression.
16950 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16951 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16953 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
16954 llvm_unreachable("Diagnostic suppressed");
16955 }
16956 } Diagnoser;
16957 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser,
16959 } else {
16960 ICE =
16961 SemaRef.VerifyIntegerConstantExpression(E, &Result,
16962 /*FIXME*/ AllowFoldKind::Allow);
16963 }
16964 if (ICE.isInvalid())
16965 return ExprError();
16966
16967 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16968 (!StrictlyPositive && !Result.isNonNegative())) {
16969 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16970 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
16971 << E->getSourceRange();
16972 return ExprError();
16973 }
16974 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
16975 CKind == OMPC_allocate) &&
16976 !Result.isPowerOf2()) {
16977 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16978 << E->getSourceRange();
16979 return ExprError();
16980 }
16981
16982 if (!Result.isRepresentableByInt64()) {
16983 Diag(E->getExprLoc(), diag::err_omp_large_expression_in_clause)
16985 return ExprError();
16986 }
16987
16988 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16989 DSAStack->setAssociatedLoops(Result.getExtValue());
16990 else if (CKind == OMPC_ordered)
16991 DSAStack->setAssociatedLoops(Result.getExtValue());
16992 return ICE;
16993}
16994
16995void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
16996
16997void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
16998
16999int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
17000
17002 llvm::APSInt Result;
17003 Expr::EvalResult EvalResult;
17004 // Evaluate the expression to an integer value
17005 if (!DeviceNumExpr->isValueDependent() &&
17006 DeviceNumExpr->EvaluateAsInt(EvalResult, SemaRef.Context)) {
17007 // The device expression must evaluate to a non-negative integer value.
17008 Result = EvalResult.Val.getInt();
17009 if (Result.isNonNegative()) {
17010 setOpenMPDeviceNum(Result.getZExtValue());
17011 } else {
17012 Diag(DeviceNumExpr->getExprLoc(),
17013 diag::err_omp_negative_expression_in_clause)
17014 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
17015 }
17016 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
17017 // Check if the expression is an identifier
17018 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
17019 if (IdInfo) {
17020 setOpenMPDeviceNumID(IdInfo->getName());
17021 }
17022 } else {
17023 Diag(DeviceNumExpr->getExprLoc(), diag::err_expected_expression);
17024 }
17025}
17026
17028 SourceLocation StartLoc,
17029 SourceLocation LParenLoc,
17030 SourceLocation EndLoc) {
17031 // OpenMP [2.8.1, simd construct, Description]
17032 // The parameter of the safelen clause must be a constant
17033 // positive integer expression.
17034 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
17035 if (Safelen.isInvalid())
17036 return nullptr;
17037 return new (getASTContext())
17038 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
17039}
17040
17042 SourceLocation StartLoc,
17043 SourceLocation LParenLoc,
17044 SourceLocation EndLoc) {
17045 // OpenMP [2.8.1, simd construct, Description]
17046 // The parameter of the simdlen clause must be a constant
17047 // positive integer expression.
17048 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
17049 if (Simdlen.isInvalid())
17050 return nullptr;
17051 return new (getASTContext())
17052 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
17053}
17054
17055/// Tries to find omp_allocator_handle_t type.
17057 DSAStackTy *Stack) {
17058 if (!Stack->getOMPAllocatorHandleT().isNull())
17059 return true;
17060
17061 // Set the allocator handle type.
17062 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
17063 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
17064 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
17065 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17066 << "omp_allocator_handle_t";
17067 return false;
17068 }
17069 QualType AllocatorHandleEnumTy = PT.get();
17070 AllocatorHandleEnumTy.addConst();
17071 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17072
17073 // Fill the predefined allocator map.
17074 bool ErrorFound = false;
17075 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17076 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
17077 StringRef Allocator =
17078 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
17079 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
17080 auto *VD = dyn_cast_or_null<ValueDecl>(
17081 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
17082 if (!VD) {
17083 ErrorFound = true;
17084 break;
17085 }
17086 QualType AllocatorType =
17088 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
17089 if (!Res.isUsable()) {
17090 ErrorFound = true;
17091 break;
17092 }
17093 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
17095 /*AllowExplicit=*/true);
17096 if (!Res.isUsable()) {
17097 ErrorFound = true;
17098 break;
17099 }
17100 Stack->setAllocator(AllocatorKind, Res.get());
17101 }
17102 if (ErrorFound) {
17103 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17104 << "omp_allocator_handle_t";
17105 return false;
17106 }
17107
17108 return true;
17109}
17110
17112 SourceLocation StartLoc,
17113 SourceLocation LParenLoc,
17114 SourceLocation EndLoc) {
17115 // OpenMP [2.11.3, allocate Directive, Description]
17116 // allocator is an expression of omp_allocator_handle_t type.
17118 return nullptr;
17119
17120 ExprResult Allocator = SemaRef.DefaultLvalueConversion(A);
17121 if (Allocator.isInvalid())
17122 return nullptr;
17123 Allocator = SemaRef.PerformImplicitConversion(
17124 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
17126 /*AllowExplicit=*/true);
17127 if (Allocator.isInvalid())
17128 return nullptr;
17129 return new (getASTContext())
17130 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
17131}
17132
17134 SourceLocation StartLoc,
17135 SourceLocation LParenLoc,
17136 SourceLocation EndLoc) {
17137 // OpenMP [2.7.1, loop construct, Description]
17138 // OpenMP [2.8.1, simd construct, Description]
17139 // OpenMP [2.9.6, distribute construct, Description]
17140 // The parameter of the collapse clause must be a constant
17141 // positive integer expression.
17142 ExprResult NumForLoopsResult =
17143 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
17144 if (NumForLoopsResult.isInvalid())
17145 return nullptr;
17146 return new (getASTContext())
17147 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
17148}
17149
17151 SourceLocation EndLoc,
17152 SourceLocation LParenLoc,
17153 Expr *NumForLoops) {
17154 // OpenMP [2.7.1, loop construct, Description]
17155 // OpenMP [2.8.1, simd construct, Description]
17156 // OpenMP [2.9.6, distribute construct, Description]
17157 // The parameter of the ordered clause must be a constant
17158 // positive integer expression if any.
17159 if (NumForLoops && LParenLoc.isValid()) {
17160 ExprResult NumForLoopsResult =
17161 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
17162 if (NumForLoopsResult.isInvalid())
17163 return nullptr;
17164 NumForLoops = NumForLoopsResult.get();
17165 } else {
17166 NumForLoops = nullptr;
17167 }
17168 auto *Clause =
17170 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
17171 StartLoc, LParenLoc, EndLoc);
17172 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
17173 return Clause;
17174}
17175
17177 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
17178 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17179 OMPClause *Res = nullptr;
17180 switch (Kind) {
17181 case OMPC_proc_bind:
17182 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
17183 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17184 break;
17185 case OMPC_atomic_default_mem_order:
17187 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
17188 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17189 break;
17190 case OMPC_fail:
17191 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
17192 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17193 break;
17194 case OMPC_update:
17195 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
17196 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17197 break;
17198 case OMPC_bind:
17199 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
17200 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17201 break;
17202 case OMPC_at:
17203 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
17204 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17205 break;
17206 case OMPC_severity:
17208 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
17209 LParenLoc, EndLoc);
17210 break;
17211 case OMPC_threadset:
17212 Res = ActOnOpenMPThreadsetClause(static_cast<OpenMPThreadsetKind>(Argument),
17213 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17214 break;
17215 case OMPC_if:
17216 case OMPC_final:
17217 case OMPC_num_threads:
17218 case OMPC_safelen:
17219 case OMPC_simdlen:
17220 case OMPC_sizes:
17221 case OMPC_allocator:
17222 case OMPC_collapse:
17223 case OMPC_schedule:
17224 case OMPC_private:
17225 case OMPC_firstprivate:
17226 case OMPC_lastprivate:
17227 case OMPC_shared:
17228 case OMPC_reduction:
17229 case OMPC_task_reduction:
17230 case OMPC_in_reduction:
17231 case OMPC_linear:
17232 case OMPC_aligned:
17233 case OMPC_copyin:
17234 case OMPC_copyprivate:
17235 case OMPC_ordered:
17236 case OMPC_nowait:
17237 case OMPC_untied:
17238 case OMPC_mergeable:
17239 case OMPC_threadprivate:
17240 case OMPC_groupprivate:
17241 case OMPC_allocate:
17242 case OMPC_flush:
17243 case OMPC_depobj:
17244 case OMPC_read:
17245 case OMPC_write:
17246 case OMPC_capture:
17247 case OMPC_compare:
17248 case OMPC_seq_cst:
17249 case OMPC_acq_rel:
17250 case OMPC_acquire:
17251 case OMPC_release:
17252 case OMPC_relaxed:
17253 case OMPC_depend:
17254 case OMPC_device:
17255 case OMPC_threads:
17256 case OMPC_simd:
17257 case OMPC_map:
17258 case OMPC_num_teams:
17259 case OMPC_thread_limit:
17260 case OMPC_priority:
17261 case OMPC_grainsize:
17262 case OMPC_nogroup:
17263 case OMPC_num_tasks:
17264 case OMPC_hint:
17265 case OMPC_dist_schedule:
17266 case OMPC_default:
17267 case OMPC_defaultmap:
17268 case OMPC_unknown:
17269 case OMPC_uniform:
17270 case OMPC_to:
17271 case OMPC_from:
17272 case OMPC_use_device_ptr:
17273 case OMPC_use_device_addr:
17274 case OMPC_is_device_ptr:
17275 case OMPC_has_device_addr:
17276 case OMPC_unified_address:
17277 case OMPC_unified_shared_memory:
17278 case OMPC_reverse_offload:
17279 case OMPC_dynamic_allocators:
17280 case OMPC_self_maps:
17281 case OMPC_device_type:
17282 case OMPC_match:
17283 case OMPC_nontemporal:
17284 case OMPC_destroy:
17285 case OMPC_novariants:
17286 case OMPC_nocontext:
17287 case OMPC_detach:
17288 case OMPC_inclusive:
17289 case OMPC_exclusive:
17290 case OMPC_uses_allocators:
17291 case OMPC_affinity:
17292 case OMPC_when:
17293 case OMPC_message:
17294 default:
17295 llvm_unreachable("Clause is not allowed.");
17296 }
17297 return Res;
17298}
17299
17301 llvm::omp::DefaultKind M, SourceLocation MLoc,
17303 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17304 if (M == OMP_DEFAULT_unknown) {
17305 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17306 << getListOfPossibleValues(OMPC_default, /*First=*/0,
17307 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17308 << getOpenMPClauseNameForDiag(OMPC_default);
17309 return nullptr;
17310 }
17311 if (VCKind == OMPC_DEFAULT_VC_unknown) {
17312 Diag(VCKindLoc, diag::err_omp_default_vc)
17313 << getOpenMPSimpleClauseTypeName(OMPC_default, unsigned(M));
17314 return nullptr;
17315 }
17316
17317 bool IsTargetDefault =
17318 getLangOpts().OpenMP >= 60 &&
17319 isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective());
17320
17321 // OpenMP 6.0, page 224, lines 3-4 default Clause, Semantics
17322 // If data-sharing-attribute is shared then the clause has no effect
17323 // on a target construct;
17324 if (IsTargetDefault && M == OMP_DEFAULT_shared)
17325 return nullptr;
17326
17327 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
17330 OpenMPDefaultmapClauseKind DefMapKind;
17331 // default data-sharing-attribute
17332 switch (M) {
17333 case OMP_DEFAULT_none:
17334 if (IsTargetDefault)
17335 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
17336 else
17337 DSAStack->setDefaultDSANone(MLoc);
17338 break;
17339 case OMP_DEFAULT_firstprivate:
17340 if (IsTargetDefault)
17341 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
17342 else
17343 DSAStack->setDefaultDSAFirstPrivate(MLoc);
17344 break;
17345 case OMP_DEFAULT_private:
17346 if (IsTargetDefault)
17347 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
17348 else
17349 DSAStack->setDefaultDSAPrivate(MLoc);
17350 break;
17351 case OMP_DEFAULT_shared:
17352 assert(!IsTargetDefault && "DSA shared invalid with target directive");
17353 DSAStack->setDefaultDSAShared(MLoc);
17354 break;
17355 default:
17356 llvm_unreachable("unexpected DSA in OpenMP default clause");
17357 }
17358 // default variable-category
17359 switch (VCKind) {
17360 case OMPC_DEFAULT_VC_aggregate:
17361 if (IsTargetDefault)
17362 DefMapKind = OMPC_DEFAULTMAP_aggregate;
17363 else
17364 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
17365 break;
17366 case OMPC_DEFAULT_VC_pointer:
17367 if (IsTargetDefault)
17368 DefMapKind = OMPC_DEFAULTMAP_pointer;
17369 else
17370 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
17371 break;
17372 case OMPC_DEFAULT_VC_scalar:
17373 if (IsTargetDefault)
17374 DefMapKind = OMPC_DEFAULTMAP_scalar;
17375 else
17376 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
17377 break;
17378 case OMPC_DEFAULT_VC_all:
17379 if (IsTargetDefault)
17380 DefMapKind = OMPC_DEFAULTMAP_all;
17381 else
17382 DSAStack->setDefaultDSAVCAll(VCKindLoc);
17383 break;
17384 default:
17385 llvm_unreachable("unexpected variable category in OpenMP default clause");
17386 }
17387 // OpenMP 6.0, page 224, lines 4-5 default Clause, Semantics
17388 // otherwise, its effect on a target construct is equivalent to
17389 // specifying the defaultmap clause with the same data-sharing-attribute
17390 // and variable-category.
17391 //
17392 // If earlier than OpenMP 6.0, or not a target directive, the default DSA
17393 // is/was set as before.
17394 if (IsTargetDefault) {
17395 if (DefMapKind == OMPC_DEFAULTMAP_all) {
17396 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_aggregate, MLoc);
17397 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_scalar, MLoc);
17398 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_pointer, MLoc);
17399 } else {
17400 DSAStack->setDefaultDMAAttr(DefMapMod, DefMapKind, MLoc);
17401 }
17402 }
17403 };
17404
17405 SetDefaultClauseAttrs(M, VCKind);
17406 return new (getASTContext())
17407 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
17408}
17409
17411 SourceLocation KindLoc,
17412 SourceLocation StartLoc,
17413 SourceLocation LParenLoc,
17414 SourceLocation EndLoc) {
17415 if (Kind == OMPC_THREADSET_unknown) {
17416 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17417 << getListOfPossibleValues(OMPC_threadset, /*First=*/0,
17418 /*Last=*/unsigned(OMPC_THREADSET_unknown))
17419 << getOpenMPClauseName(OMPC_threadset);
17420 return nullptr;
17421 }
17422
17423 return new (getASTContext())
17424 OMPThreadsetClause(Kind, KindLoc, StartLoc, LParenLoc, EndLoc);
17425}
17426
17428 SourceLocation KindKwLoc,
17429 SourceLocation StartLoc,
17430 SourceLocation LParenLoc,
17431 SourceLocation EndLoc) {
17432 if (Kind == OMP_PROC_BIND_unknown) {
17433 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17434 << getListOfPossibleValues(OMPC_proc_bind,
17435 /*First=*/unsigned(OMP_PROC_BIND_master),
17436 /*Last=*/
17437 unsigned(getLangOpts().OpenMP > 50
17438 ? OMP_PROC_BIND_primary
17439 : OMP_PROC_BIND_spread) +
17440 1)
17441 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
17442 return nullptr;
17443 }
17444 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
17445 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17446 << getListOfPossibleValues(OMPC_proc_bind,
17447 /*First=*/unsigned(OMP_PROC_BIND_master),
17448 /*Last=*/
17449 unsigned(OMP_PROC_BIND_spread) + 1)
17450 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
17451 return new (getASTContext())
17452 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17453}
17454
17457 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17459 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17461 OMPC_atomic_default_mem_order, /*First=*/0,
17463 << getOpenMPClauseNameForDiag(OMPC_atomic_default_mem_order);
17464 return nullptr;
17465 }
17467 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17468}
17469
17471 SourceLocation KindKwLoc,
17472 SourceLocation StartLoc,
17473 SourceLocation LParenLoc,
17474 SourceLocation EndLoc) {
17475 if (Kind == OMPC_AT_unknown) {
17476 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17477 << getListOfPossibleValues(OMPC_at, /*First=*/0,
17478 /*Last=*/OMPC_AT_unknown)
17479 << getOpenMPClauseNameForDiag(OMPC_at);
17480 return nullptr;
17481 }
17482 return new (getASTContext())
17483 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17484}
17485
17487 SourceLocation KindKwLoc,
17488 SourceLocation StartLoc,
17489 SourceLocation LParenLoc,
17490 SourceLocation EndLoc) {
17491 if (Kind == OMPC_SEVERITY_unknown) {
17492 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17493 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
17494 /*Last=*/OMPC_SEVERITY_unknown)
17495 << getOpenMPClauseNameForDiag(OMPC_severity);
17496 return nullptr;
17497 }
17498 return new (getASTContext())
17499 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17500}
17501
17503 SourceLocation StartLoc,
17504 SourceLocation LParenLoc,
17505 SourceLocation EndLoc) {
17506 assert(ME && "NULL expr in Message clause");
17507 QualType Type = ME->getType();
17508 if ((!Type->isPointerType() && !Type->isArrayType()) ||
17510 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
17511 << getOpenMPClauseNameForDiag(OMPC_message) << 0;
17512 return nullptr;
17513 }
17514
17515 Stmt *HelperValStmt = nullptr;
17516
17517 // Depending on whether this clause appears in an executable context or not,
17518 // we may or may not build a capture.
17519 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17520 OpenMPDirectiveKind CaptureRegion =
17521 DKind == OMPD_unknown ? OMPD_unknown
17523 DKind, OMPC_message, getLangOpts().OpenMP);
17524 if (CaptureRegion != OMPD_unknown &&
17525 !SemaRef.CurContext->isDependentContext()) {
17526 ME = SemaRef.MakeFullExpr(ME).get();
17527 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17528 ME = tryBuildCapture(SemaRef, ME, Captures).get();
17529 HelperValStmt = buildPreInits(getASTContext(), Captures);
17530 }
17531
17532 // Convert array type to pointer type if needed.
17533 ME = SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
17534
17535 return new (getASTContext()) OMPMessageClause(
17536 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17537}
17538
17541 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
17542 SourceLocation KindLoc, SourceLocation EndLoc) {
17543 if (Kind != OMPC_ORDER_concurrent ||
17544 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
17545 // Kind should be concurrent,
17546 // Modifiers introduced in OpenMP 5.1
17547 static_assert(OMPC_ORDER_unknown > 0,
17548 "OMPC_ORDER_unknown not greater than 0");
17549
17550 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17551 << getListOfPossibleValues(OMPC_order,
17552 /*First=*/0,
17553 /*Last=*/OMPC_ORDER_unknown)
17554 << getOpenMPClauseNameForDiag(OMPC_order);
17555 return nullptr;
17556 }
17557 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
17558 MLoc.isValid()) {
17559 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17560 << getListOfPossibleValues(OMPC_order,
17561 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
17562 /*Last=*/OMPC_ORDER_MODIFIER_last)
17563 << getOpenMPClauseNameForDiag(OMPC_order);
17564 } else if (getLangOpts().OpenMP >= 50) {
17565 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17566 if (DSAStack->getCurScope()) {
17567 // mark the current scope with 'order' flag
17568 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
17569 DSAStack->getCurScope()->setFlags(existingFlags |
17571 }
17572 }
17573 return new (getASTContext()) OMPOrderClause(
17574 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
17575}
17576
17578 SourceLocation KindKwLoc,
17579 SourceLocation StartLoc,
17580 SourceLocation LParenLoc,
17581 SourceLocation EndLoc) {
17582 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
17583 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17584 SmallVector<unsigned> Except = {
17585 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17586 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17587 if (getLangOpts().OpenMP < 51)
17588 Except.push_back(OMPC_DEPEND_inoutset);
17589 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17590 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
17591 /*Last=*/OMPC_DEPEND_unknown, Except)
17592 << getOpenMPClauseNameForDiag(OMPC_update);
17593 return nullptr;
17594 }
17595 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
17596 KindKwLoc, Kind, EndLoc);
17597}
17598
17600 SourceLocation StartLoc,
17601 SourceLocation LParenLoc,
17602 SourceLocation EndLoc) {
17603 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
17604
17605 for (Expr *&SizeExpr : SanitizedSizeExprs) {
17606 // Skip if already sanitized, e.g. during a partial template instantiation.
17607 if (!SizeExpr)
17608 continue;
17609
17610 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
17611 /*StrictlyPositive=*/true);
17612
17613 // isNonNegativeIntegerValue returns true for non-integral types (but still
17614 // emits error diagnostic), so check for the expected type explicitly.
17615 QualType SizeTy = SizeExpr->getType();
17616 if (!SizeTy->isIntegerType())
17617 IsValid = false;
17618
17619 // Handling in templates is tricky. There are four possibilities to
17620 // consider:
17621 //
17622 // 1a. The expression is valid and we are in a instantiated template or not
17623 // in a template:
17624 // Pass valid expression to be further analysed later in Sema.
17625 // 1b. The expression is valid and we are in a template (including partial
17626 // instantiation):
17627 // isNonNegativeIntegerValue skipped any checks so there is no
17628 // guarantee it will be correct after instantiation.
17629 // ActOnOpenMPSizesClause will be called again at instantiation when
17630 // it is not in a dependent context anymore. This may cause warnings
17631 // to be emitted multiple times.
17632 // 2a. The expression is invalid and we are in an instantiated template or
17633 // not in a template:
17634 // Invalidate the expression with a clearly wrong value (nullptr) so
17635 // later in Sema we do not have to do the same validity analysis again
17636 // or crash from unexpected data. Error diagnostics have already been
17637 // emitted.
17638 // 2b. The expression is invalid and we are in a template (including partial
17639 // instantiation):
17640 // Pass the invalid expression as-is, template instantiation may
17641 // replace unexpected types/values with valid ones. The directives
17642 // with this clause must not try to use these expressions in dependent
17643 // contexts, but delay analysis until full instantiation.
17644 if (!SizeExpr->isInstantiationDependent() && !IsValid)
17645 SizeExpr = nullptr;
17646 }
17647
17648 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17649 SanitizedSizeExprs);
17650}
17651
17653 SourceLocation StartLoc,
17654 SourceLocation LParenLoc,
17655 SourceLocation EndLoc) {
17656 size_t NumLoops = PermExprs.size();
17657 SmallVector<Expr *> SanitizedPermExprs;
17658 llvm::append_range(SanitizedPermExprs, PermExprs);
17659
17660 for (Expr *&PermExpr : SanitizedPermExprs) {
17661 // Skip if template-dependent or already sanitized, e.g. during a partial
17662 // template instantiation.
17663 if (!PermExpr || PermExpr->isInstantiationDependent())
17664 continue;
17665
17666 llvm::APSInt PermVal;
17667 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
17668 PermExpr, &PermVal, AllowFoldKind::Allow);
17669 bool IsValid = PermEvalExpr.isUsable();
17670 if (IsValid)
17671 PermExpr = PermEvalExpr.get();
17672
17673 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
17674 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
17675 PermEvalExpr.get()->getEndLoc());
17676 Diag(PermEvalExpr.get()->getExprLoc(),
17677 diag::err_omp_interchange_permutation_value_range)
17678 << NumLoops << ExprRange;
17679 IsValid = false;
17680 }
17681
17682 if (!PermExpr->isInstantiationDependent() && !IsValid)
17683 PermExpr = nullptr;
17684 }
17685
17686 return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
17687 EndLoc, SanitizedPermExprs);
17688}
17689
17691 SourceLocation EndLoc) {
17692 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
17693}
17694
17696 SourceLocation StartLoc,
17697 SourceLocation LParenLoc,
17698 SourceLocation EndLoc) {
17699 if (FactorExpr) {
17700 // If an argument is specified, it must be a constant (or an unevaluated
17701 // template expression).
17703 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
17704 if (FactorResult.isInvalid())
17705 return nullptr;
17706 FactorExpr = FactorResult.get();
17707 }
17708
17709 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17710 FactorExpr);
17711}
17712
17714 Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc,
17715 SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc) {
17716
17717 // OpenMP [6.0, Restrictions]
17718 // First and Count must be integer expressions with positive value
17719 ExprResult FirstVal =
17721 if (FirstVal.isInvalid())
17722 First = nullptr;
17723
17724 ExprResult CountVal =
17725 VerifyPositiveIntegerConstantInClause(Count, OMPC_looprange);
17726 if (CountVal.isInvalid())
17727 Count = nullptr;
17728
17729 // OpenMP [6.0, Restrictions]
17730 // first + count - 1 must not evaluate to a value greater than the
17731 // loop sequence length of the associated canonical loop sequence.
17732 // This check must be performed afterwards due to the delayed
17733 // parsing and computation of the associated loop sequence
17734 return OMPLoopRangeClause::Create(getASTContext(), StartLoc, LParenLoc,
17735 FirstLoc, CountLoc, EndLoc, First, Count);
17736}
17737
17739 SourceLocation LParenLoc,
17740 SourceLocation EndLoc) {
17741 ExprResult AlignVal;
17742 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
17743 if (AlignVal.isInvalid())
17744 return nullptr;
17745 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
17746 LParenLoc, EndLoc);
17747}
17748
17751 SourceLocation StartLoc, SourceLocation LParenLoc,
17752 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
17753 SourceLocation EndLoc) {
17754 OMPClause *Res = nullptr;
17755 switch (Kind) {
17756 case OMPC_schedule: {
17757 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17758 assert(Argument.size() == NumberOfElements &&
17759 ArgumentLoc.size() == NumberOfElements);
17761 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
17762 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17763 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
17764 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17765 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17766 break;
17767 }
17768 case OMPC_if:
17769 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17770 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17771 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17772 DelimLoc, EndLoc);
17773 break;
17774 case OMPC_dist_schedule:
17776 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
17777 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17778 break;
17779 case OMPC_default:
17780 enum { DefaultModifier, DefaultVarCategory };
17782 static_cast<llvm::omp::DefaultKind>(Argument[DefaultModifier]),
17783 ArgumentLoc[DefaultModifier],
17785 Argument[DefaultVarCategory]),
17786 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
17787 break;
17788 case OMPC_defaultmap:
17789 enum { Modifier, DefaultmapKind };
17791 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17792 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17793 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17794 EndLoc);
17795 break;
17796 case OMPC_order:
17797 enum { OrderModifier, OrderKind };
17799 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17800 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17801 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17802 break;
17803 case OMPC_device:
17804 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17806 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
17807 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17808 break;
17809 case OMPC_grainsize:
17810 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17811 "Modifier for grainsize clause and its location are expected.");
17813 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
17814 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17815 break;
17816 case OMPC_num_tasks:
17817 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17818 "Modifier for num_tasks clause and its location are expected.");
17820 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
17821 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17822 break;
17823 case OMPC_dyn_groupprivate: {
17824 enum { Modifier1, Modifier2, NumberOfElements };
17825 assert(Argument.size() == NumberOfElements &&
17826 ArgumentLoc.size() == NumberOfElements &&
17827 "Modifiers for dyn_groupprivate clause and their locations are "
17828 "expected.");
17830 static_cast<OpenMPDynGroupprivateClauseModifier>(Argument[Modifier1]),
17832 Argument[Modifier2]),
17833 Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1],
17834 ArgumentLoc[Modifier2], EndLoc);
17835 break;
17836 }
17837 case OMPC_num_threads:
17838 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17839 "Modifier for num_threads clause and its location are expected.");
17841 static_cast<OpenMPNumThreadsClauseModifier>(Argument.back()), Expr,
17842 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17843 break;
17844 case OMPC_final:
17845 case OMPC_safelen:
17846 case OMPC_simdlen:
17847 case OMPC_sizes:
17848 case OMPC_allocator:
17849 case OMPC_collapse:
17850 case OMPC_proc_bind:
17851 case OMPC_private:
17852 case OMPC_firstprivate:
17853 case OMPC_lastprivate:
17854 case OMPC_shared:
17855 case OMPC_reduction:
17856 case OMPC_task_reduction:
17857 case OMPC_in_reduction:
17858 case OMPC_linear:
17859 case OMPC_aligned:
17860 case OMPC_copyin:
17861 case OMPC_copyprivate:
17862 case OMPC_ordered:
17863 case OMPC_nowait:
17864 case OMPC_untied:
17865 case OMPC_mergeable:
17866 case OMPC_threadprivate:
17867 case OMPC_groupprivate:
17868 case OMPC_allocate:
17869 case OMPC_flush:
17870 case OMPC_depobj:
17871 case OMPC_read:
17872 case OMPC_write:
17873 case OMPC_update:
17874 case OMPC_capture:
17875 case OMPC_compare:
17876 case OMPC_seq_cst:
17877 case OMPC_acq_rel:
17878 case OMPC_acquire:
17879 case OMPC_release:
17880 case OMPC_relaxed:
17881 case OMPC_depend:
17882 case OMPC_threads:
17883 case OMPC_simd:
17884 case OMPC_map:
17885 case OMPC_num_teams:
17886 case OMPC_thread_limit:
17887 case OMPC_priority:
17888 case OMPC_nogroup:
17889 case OMPC_hint:
17890 case OMPC_unknown:
17891 case OMPC_uniform:
17892 case OMPC_to:
17893 case OMPC_from:
17894 case OMPC_use_device_ptr:
17895 case OMPC_use_device_addr:
17896 case OMPC_is_device_ptr:
17897 case OMPC_has_device_addr:
17898 case OMPC_unified_address:
17899 case OMPC_unified_shared_memory:
17900 case OMPC_reverse_offload:
17901 case OMPC_dynamic_allocators:
17902 case OMPC_atomic_default_mem_order:
17903 case OMPC_self_maps:
17904 case OMPC_device_type:
17905 case OMPC_match:
17906 case OMPC_nontemporal:
17907 case OMPC_at:
17908 case OMPC_severity:
17909 case OMPC_message:
17910 case OMPC_destroy:
17911 case OMPC_novariants:
17912 case OMPC_nocontext:
17913 case OMPC_detach:
17914 case OMPC_inclusive:
17915 case OMPC_exclusive:
17916 case OMPC_uses_allocators:
17917 case OMPC_affinity:
17918 case OMPC_when:
17919 case OMPC_bind:
17920 default:
17921 llvm_unreachable("Clause is not allowed.");
17922 }
17923 return Res;
17924}
17925
17928 SourceLocation M1Loc, SourceLocation M2Loc) {
17929 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
17930 SmallVector<unsigned, 2> Excluded;
17932 Excluded.push_back(M2);
17933 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17934 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17935 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17936 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17937 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17938 << getListOfPossibleValues(OMPC_schedule,
17939 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
17941 Excluded)
17942 << getOpenMPClauseNameForDiag(OMPC_schedule);
17943 return true;
17944 }
17945 return false;
17946}
17947
17950 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
17951 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
17952 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
17953 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
17954 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
17955 return nullptr;
17956 // OpenMP, 2.7.1, Loop Construct, Restrictions
17957 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17958 // but not both.
17959 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
17960 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17961 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17962 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17963 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17964 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17965 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
17966 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
17967 return nullptr;
17968 }
17969 if (Kind == OMPC_SCHEDULE_unknown) {
17970 std::string Values;
17971 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
17972 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
17973 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17975 Exclude);
17976 } else {
17977 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17978 /*Last=*/OMPC_SCHEDULE_unknown);
17979 }
17980 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17981 << Values << getOpenMPClauseNameForDiag(OMPC_schedule);
17982 return nullptr;
17983 }
17984 // OpenMP, 2.7.1, Loop Construct, Restrictions
17985 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17986 // schedule(guided).
17987 // OpenMP 5.0 does not have this restriction.
17988 if (getLangOpts().OpenMP < 50 &&
17989 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17990 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17991 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17992 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17993 diag::err_omp_schedule_nonmonotonic_static);
17994 return nullptr;
17995 }
17996 Expr *ValExpr = ChunkSize;
17997 Stmt *HelperValStmt = nullptr;
17998 if (ChunkSize) {
17999 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
18000 !ChunkSize->isInstantiationDependent() &&
18001 !ChunkSize->containsUnexpandedParameterPack()) {
18002 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
18003 ExprResult Val =
18004 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
18005 if (Val.isInvalid())
18006 return nullptr;
18007
18008 ValExpr = Val.get();
18009
18010 // OpenMP [2.7.1, Restrictions]
18011 // chunk_size must be a loop invariant integer expression with a positive
18012 // value.
18013 if (std::optional<llvm::APSInt> Result =
18015 if (Result->isSigned() && !Result->isStrictlyPositive()) {
18016 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
18017 << "schedule" << 1 << ChunkSize->getSourceRange();
18018 return nullptr;
18019 }
18021 DSAStack->getCurrentDirective(), OMPC_schedule,
18022 getLangOpts().OpenMP) != OMPD_unknown &&
18023 !SemaRef.CurContext->isDependentContext()) {
18024 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18025 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18026 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18027 HelperValStmt = buildPreInits(getASTContext(), Captures);
18028 }
18029 }
18030 }
18031
18032 return new (getASTContext())
18033 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
18034 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
18035}
18036
18038 SourceLocation StartLoc,
18039 SourceLocation EndLoc) {
18040 OMPClause *Res = nullptr;
18041 switch (Kind) {
18042 case OMPC_ordered:
18043 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
18044 break;
18045 case OMPC_nowait:
18046 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc,
18047 /*LParenLoc=*/SourceLocation(),
18048 /*Condition=*/nullptr);
18049 break;
18050 case OMPC_untied:
18051 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
18052 break;
18053 case OMPC_mergeable:
18054 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
18055 break;
18056 case OMPC_read:
18057 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
18058 break;
18059 case OMPC_write:
18060 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
18061 break;
18062 case OMPC_update:
18063 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
18064 break;
18065 case OMPC_capture:
18066 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
18067 break;
18068 case OMPC_compare:
18069 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
18070 break;
18071 case OMPC_fail:
18072 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
18073 break;
18074 case OMPC_seq_cst:
18075 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
18076 break;
18077 case OMPC_acq_rel:
18078 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
18079 break;
18080 case OMPC_acquire:
18081 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
18082 break;
18083 case OMPC_release:
18084 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
18085 break;
18086 case OMPC_relaxed:
18087 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
18088 break;
18089 case OMPC_weak:
18090 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
18091 break;
18092 case OMPC_threads:
18093 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
18094 break;
18095 case OMPC_simd:
18096 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
18097 break;
18098 case OMPC_nogroup:
18099 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
18100 break;
18101 case OMPC_unified_address:
18102 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
18103 break;
18104 case OMPC_unified_shared_memory:
18105 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18106 break;
18107 case OMPC_reverse_offload:
18108 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
18109 break;
18110 case OMPC_dynamic_allocators:
18111 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
18112 break;
18113 case OMPC_self_maps:
18114 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
18115 break;
18116 case OMPC_destroy:
18117 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
18118 /*LParenLoc=*/SourceLocation(),
18119 /*VarLoc=*/SourceLocation(), EndLoc);
18120 break;
18121 case OMPC_full:
18122 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
18123 break;
18124 case OMPC_partial:
18125 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
18126 break;
18127 case OMPC_ompx_bare:
18128 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
18129 break;
18130 case OMPC_if:
18131 case OMPC_final:
18132 case OMPC_num_threads:
18133 case OMPC_safelen:
18134 case OMPC_simdlen:
18135 case OMPC_sizes:
18136 case OMPC_allocator:
18137 case OMPC_collapse:
18138 case OMPC_schedule:
18139 case OMPC_private:
18140 case OMPC_firstprivate:
18141 case OMPC_lastprivate:
18142 case OMPC_shared:
18143 case OMPC_reduction:
18144 case OMPC_task_reduction:
18145 case OMPC_in_reduction:
18146 case OMPC_linear:
18147 case OMPC_aligned:
18148 case OMPC_copyin:
18149 case OMPC_copyprivate:
18150 case OMPC_default:
18151 case OMPC_proc_bind:
18152 case OMPC_threadprivate:
18153 case OMPC_groupprivate:
18154 case OMPC_allocate:
18155 case OMPC_flush:
18156 case OMPC_depobj:
18157 case OMPC_depend:
18158 case OMPC_device:
18159 case OMPC_map:
18160 case OMPC_num_teams:
18161 case OMPC_thread_limit:
18162 case OMPC_priority:
18163 case OMPC_grainsize:
18164 case OMPC_num_tasks:
18165 case OMPC_hint:
18166 case OMPC_dist_schedule:
18167 case OMPC_defaultmap:
18168 case OMPC_unknown:
18169 case OMPC_uniform:
18170 case OMPC_to:
18171 case OMPC_from:
18172 case OMPC_use_device_ptr:
18173 case OMPC_use_device_addr:
18174 case OMPC_is_device_ptr:
18175 case OMPC_has_device_addr:
18176 case OMPC_atomic_default_mem_order:
18177 case OMPC_device_type:
18178 case OMPC_match:
18179 case OMPC_nontemporal:
18180 case OMPC_order:
18181 case OMPC_at:
18182 case OMPC_severity:
18183 case OMPC_message:
18184 case OMPC_novariants:
18185 case OMPC_nocontext:
18186 case OMPC_detach:
18187 case OMPC_inclusive:
18188 case OMPC_exclusive:
18189 case OMPC_uses_allocators:
18190 case OMPC_affinity:
18191 case OMPC_when:
18192 case OMPC_ompx_dyn_cgroup_mem:
18193 case OMPC_dyn_groupprivate:
18194 default:
18195 llvm_unreachable("Clause is not allowed.");
18196 }
18197 return Res;
18198}
18199
18201 SourceLocation EndLoc,
18202 SourceLocation LParenLoc,
18203 Expr *Condition) {
18204 Expr *ValExpr = Condition;
18205 if (Condition && LParenLoc.isValid()) {
18206 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18207 !Condition->isInstantiationDependent() &&
18208 !Condition->containsUnexpandedParameterPack()) {
18209 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18210 if (Val.isInvalid())
18211 return nullptr;
18212
18213 ValExpr = Val.get();
18214 }
18215 }
18216 DSAStack->setNowaitRegion();
18217 return new (getASTContext())
18218 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
18219}
18220
18222 SourceLocation EndLoc) {
18223 DSAStack->setUntiedRegion();
18224 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
18225}
18226
18228 SourceLocation EndLoc) {
18229 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
18230}
18231
18233 SourceLocation EndLoc) {
18234 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
18235}
18236
18238 SourceLocation EndLoc) {
18239 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
18240}
18241
18243 SourceLocation EndLoc) {
18244 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
18245}
18246
18248 SourceLocation EndLoc) {
18249 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
18250}
18251
18253 SourceLocation EndLoc) {
18254 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
18255}
18256
18258 SourceLocation EndLoc) {
18259 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
18260}
18261
18263 SourceLocation KindLoc,
18264 SourceLocation StartLoc,
18265 SourceLocation LParenLoc,
18266 SourceLocation EndLoc) {
18267
18269 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
18270 return nullptr;
18271 }
18272 return new (getASTContext())
18273 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
18274}
18275
18277 SourceLocation EndLoc) {
18278 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
18279}
18280
18282 SourceLocation EndLoc) {
18283 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
18284}
18285
18287 SourceLocation EndLoc) {
18288 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
18289}
18290
18292 SourceLocation EndLoc) {
18293 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
18294}
18295
18297 SourceLocation EndLoc) {
18298 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
18299}
18300
18302 SourceLocation EndLoc) {
18303 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
18304}
18305
18307 SourceLocation EndLoc) {
18308 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
18309}
18310
18312 SourceLocation EndLoc) {
18313 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
18314}
18315
18317 SourceLocation EndLoc) {
18318 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
18319}
18320
18322 SourceLocation EndLoc) {
18323 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
18324}
18325
18326OMPClause *
18331
18333 SourceLocation EndLoc) {
18334 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
18335}
18336
18337OMPClause *
18339 SourceLocation EndLoc) {
18340 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
18341}
18342
18344 SourceLocation EndLoc) {
18345 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
18346}
18347
18350 SourceLocation StartLoc,
18351 SourceLocation EndLoc) {
18352
18353 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18354 // At least one action-clause must appear on a directive.
18355 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
18356 unsigned OMPVersion = getLangOpts().OpenMP;
18357 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
18358 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
18359 << Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
18360 return StmtError();
18361 }
18362
18363 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18364 // A depend clause can only appear on the directive if a targetsync
18365 // interop-type is present or the interop-var was initialized with
18366 // the targetsync interop-type.
18367
18368 // If there is any 'init' clause diagnose if there is no 'init' clause with
18369 // interop-type of 'targetsync'. Cases involving other directives cannot be
18370 // diagnosed.
18371 const OMPDependClause *DependClause = nullptr;
18372 bool HasInitClause = false;
18373 bool IsTargetSync = false;
18374 for (const OMPClause *C : Clauses) {
18375 if (IsTargetSync)
18376 break;
18377 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
18378 HasInitClause = true;
18379 if (InitClause->getIsTargetSync())
18380 IsTargetSync = true;
18381 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
18382 DependClause = DC;
18383 }
18384 }
18385 if (DependClause && HasInitClause && !IsTargetSync) {
18386 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
18387 return StmtError();
18388 }
18389
18390 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18391 // Each interop-var may be specified for at most one action-clause of each
18392 // interop construct.
18394 for (OMPClause *C : Clauses) {
18395 OpenMPClauseKind ClauseKind = C->getClauseKind();
18396 std::pair<ValueDecl *, bool> DeclResult;
18397 SourceLocation ELoc;
18398 SourceRange ERange;
18399
18400 if (ClauseKind == OMPC_init) {
18401 auto *E = cast<OMPInitClause>(C)->getInteropVar();
18402 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18403 } else if (ClauseKind == OMPC_use) {
18404 auto *E = cast<OMPUseClause>(C)->getInteropVar();
18405 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18406 } else if (ClauseKind == OMPC_destroy) {
18407 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
18408 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18409 }
18410
18411 if (DeclResult.first) {
18412 if (!InteropVars.insert(DeclResult.first).second) {
18413 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
18414 << DeclResult.first;
18415 return StmtError();
18416 }
18417 }
18418 }
18419
18420 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
18421 Clauses);
18422}
18423
18424static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
18425 SourceLocation VarLoc,
18426 OpenMPClauseKind Kind) {
18427 SourceLocation ELoc;
18428 SourceRange ERange;
18429 Expr *RefExpr = InteropVarExpr;
18430 auto Res = getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
18431 /*AllowArraySection=*/false,
18432 /*AllowAssumedSizeArray=*/false,
18433 /*DiagType=*/"omp_interop_t");
18434
18435 if (Res.second) {
18436 // It will be analyzed later.
18437 return true;
18438 }
18439
18440 if (!Res.first)
18441 return false;
18442
18443 // Interop variable should be of type omp_interop_t.
18444 bool HasError = false;
18445 QualType InteropType;
18446 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
18447 VarLoc, Sema::LookupOrdinaryName);
18448 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
18449 NamedDecl *ND = Result.getFoundDecl();
18450 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
18451 InteropType = QualType(TD->getTypeForDecl(), 0);
18452 } else {
18453 HasError = true;
18454 }
18455 } else {
18456 HasError = true;
18457 }
18458
18459 if (HasError) {
18460 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
18461 << "omp_interop_t";
18462 return false;
18463 }
18464
18465 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
18466 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
18467 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
18468 return false;
18469 }
18470
18471 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18472 // The interop-var passed to init or destroy must be non-const.
18473 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
18474 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
18475 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
18476 << /*non-const*/ 1;
18477 return false;
18478 }
18479 return true;
18480}
18481
18483 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
18484 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
18485
18486 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
18487 return nullptr;
18488
18489 // Check prefer_type values. These foreign-runtime-id values are either
18490 // string literals or constant integral expressions.
18491 for (const Expr *E : InteropInfo.PreferTypes) {
18492 if (E->isValueDependent() || E->isTypeDependent() ||
18494 continue;
18496 continue;
18497 if (isa<StringLiteral>(E))
18498 continue;
18499 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
18500 return nullptr;
18501 }
18502
18503 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
18504 StartLoc, LParenLoc, VarLoc, EndLoc);
18505}
18506
18508 SourceLocation StartLoc,
18509 SourceLocation LParenLoc,
18510 SourceLocation VarLoc,
18511 SourceLocation EndLoc) {
18512
18513 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
18514 return nullptr;
18515
18516 return new (getASTContext())
18517 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18518}
18519
18521 SourceLocation StartLoc,
18522 SourceLocation LParenLoc,
18523 SourceLocation VarLoc,
18524 SourceLocation EndLoc) {
18525 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
18526 DSAStack->getCurrentDirective() == OMPD_depobj) {
18527 unsigned OMPVersion = getLangOpts().OpenMP;
18528 Diag(StartLoc, diag::err_omp_expected_clause_argument)
18529 << getOpenMPClauseNameForDiag(OMPC_destroy)
18530 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
18531 return nullptr;
18532 }
18533 if (InteropVar &&
18534 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
18535 return nullptr;
18536
18537 return new (getASTContext())
18538 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18539}
18540
18542 SourceLocation StartLoc,
18543 SourceLocation LParenLoc,
18544 SourceLocation EndLoc) {
18545 Expr *ValExpr = Condition;
18546 Stmt *HelperValStmt = nullptr;
18547 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18548 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18549 !Condition->isInstantiationDependent() &&
18550 !Condition->containsUnexpandedParameterPack()) {
18551 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18552 if (Val.isInvalid())
18553 return nullptr;
18554
18555 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18556
18557 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18558 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
18559 getLangOpts().OpenMP);
18560 if (CaptureRegion != OMPD_unknown &&
18561 !SemaRef.CurContext->isDependentContext()) {
18562 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18563 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18564 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18565 HelperValStmt = buildPreInits(getASTContext(), Captures);
18566 }
18567 }
18568
18569 return new (getASTContext()) OMPNovariantsClause(
18570 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18571}
18572
18574 SourceLocation StartLoc,
18575 SourceLocation LParenLoc,
18576 SourceLocation EndLoc) {
18577 Expr *ValExpr = Condition;
18578 Stmt *HelperValStmt = nullptr;
18579 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18580 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18581 !Condition->isInstantiationDependent() &&
18582 !Condition->containsUnexpandedParameterPack()) {
18583 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18584 if (Val.isInvalid())
18585 return nullptr;
18586
18587 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18588
18589 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18590 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
18591 getLangOpts().OpenMP);
18592 if (CaptureRegion != OMPD_unknown &&
18593 !SemaRef.CurContext->isDependentContext()) {
18594 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18595 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18596 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18597 HelperValStmt = buildPreInits(getASTContext(), Captures);
18598 }
18599 }
18600
18601 return new (getASTContext()) OMPNocontextClause(
18602 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18603}
18604
18606 SourceLocation StartLoc,
18607 SourceLocation LParenLoc,
18608 SourceLocation EndLoc) {
18609 Expr *ValExpr = ThreadID;
18610 Stmt *HelperValStmt = nullptr;
18611
18612 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18613 OpenMPDirectiveKind CaptureRegion =
18614 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
18615 if (CaptureRegion != OMPD_unknown &&
18616 !SemaRef.CurContext->isDependentContext()) {
18617 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18618 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18619 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18620 HelperValStmt = buildPreInits(getASTContext(), Captures);
18621 }
18622
18623 return new (getASTContext()) OMPFilterClause(
18624 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18625}
18626
18628 ArrayRef<Expr *> VarList,
18629 const OMPVarListLocTy &Locs,
18631 SourceLocation StartLoc = Locs.StartLoc;
18632 SourceLocation LParenLoc = Locs.LParenLoc;
18633 SourceLocation EndLoc = Locs.EndLoc;
18634 OMPClause *Res = nullptr;
18635 int ExtraModifier = Data.ExtraModifier;
18636 int OriginalSharingModifier = Data.OriginalSharingModifier;
18637 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
18638 SourceLocation ColonLoc = Data.ColonLoc;
18639 switch (Kind) {
18640 case OMPC_private:
18641 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18642 break;
18643 case OMPC_firstprivate:
18644 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18645 break;
18646 case OMPC_lastprivate:
18647 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
18648 "Unexpected lastprivate modifier.");
18650 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
18651 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18652 break;
18653 case OMPC_shared:
18654 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
18655 break;
18656 case OMPC_reduction:
18657 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
18658 "Unexpected lastprivate modifier.");
18660 VarList,
18662 ExtraModifier, OriginalSharingModifier),
18663 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18664 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18665 break;
18666 case OMPC_task_reduction:
18668 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18669 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18670 break;
18671 case OMPC_in_reduction:
18673 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18674 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18675 break;
18676 case OMPC_linear:
18677 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
18678 "Unexpected linear modifier.");
18680 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
18681 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
18682 ColonLoc, Data.StepModifierLoc, EndLoc);
18683 break;
18684 case OMPC_aligned:
18685 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
18686 LParenLoc, ColonLoc, EndLoc);
18687 break;
18688 case OMPC_copyin:
18689 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
18690 break;
18691 case OMPC_copyprivate:
18692 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18693 break;
18694 case OMPC_flush:
18695 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
18696 break;
18697 case OMPC_depend:
18698 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
18699 "Unexpected depend modifier.");
18701 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
18702 ColonLoc, Data.OmpAllMemoryLoc},
18703 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18704 break;
18705 case OMPC_map:
18706 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
18707 "Unexpected map modifier.");
18709 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
18710 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
18711 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
18712 ExtraModifierLoc, ColonLoc, VarList, Locs);
18713 break;
18714 case OMPC_to:
18715 Res = ActOnOpenMPToClause(
18716 Data.MotionModifiers, Data.MotionModifiersLoc, Data.IteratorExpr,
18717 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, ColonLoc,
18718 VarList, Locs);
18719 break;
18720 case OMPC_from:
18722 Data.MotionModifiers, Data.MotionModifiersLoc, Data.IteratorExpr,
18723 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, ColonLoc,
18724 VarList, Locs);
18725 break;
18726 case OMPC_use_device_ptr:
18727 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
18728 break;
18729 case OMPC_use_device_addr:
18730 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
18731 break;
18732 case OMPC_is_device_ptr:
18733 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
18734 break;
18735 case OMPC_has_device_addr:
18736 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
18737 break;
18738 case OMPC_allocate: {
18741 SourceLocation Modifier1Loc, Modifier2Loc;
18742 if (!Data.AllocClauseModifiers.empty()) {
18743 assert(Data.AllocClauseModifiers.size() <= 2 &&
18744 "More allocate modifiers than expected");
18745 Modifier1 = Data.AllocClauseModifiers[0];
18746 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
18747 if (Data.AllocClauseModifiers.size() == 2) {
18748 Modifier2 = Data.AllocClauseModifiers[1];
18749 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
18750 }
18751 }
18753 Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc,
18754 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
18755 EndLoc);
18756 break;
18757 }
18758 case OMPC_nontemporal:
18759 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
18760 break;
18761 case OMPC_inclusive:
18762 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18763 break;
18764 case OMPC_exclusive:
18765 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18766 break;
18767 case OMPC_affinity:
18768 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
18769 Data.DepModOrTailExpr, VarList);
18770 break;
18771 case OMPC_doacross:
18773 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
18774 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18775 break;
18776 case OMPC_num_teams:
18777 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
18778 break;
18779 case OMPC_thread_limit:
18780 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
18781 break;
18782 case OMPC_if:
18783 case OMPC_depobj:
18784 case OMPC_final:
18785 case OMPC_num_threads:
18786 case OMPC_safelen:
18787 case OMPC_simdlen:
18788 case OMPC_sizes:
18789 case OMPC_allocator:
18790 case OMPC_collapse:
18791 case OMPC_default:
18792 case OMPC_proc_bind:
18793 case OMPC_schedule:
18794 case OMPC_ordered:
18795 case OMPC_nowait:
18796 case OMPC_untied:
18797 case OMPC_mergeable:
18798 case OMPC_threadprivate:
18799 case OMPC_groupprivate:
18800 case OMPC_read:
18801 case OMPC_write:
18802 case OMPC_update:
18803 case OMPC_capture:
18804 case OMPC_compare:
18805 case OMPC_seq_cst:
18806 case OMPC_acq_rel:
18807 case OMPC_acquire:
18808 case OMPC_release:
18809 case OMPC_relaxed:
18810 case OMPC_device:
18811 case OMPC_threads:
18812 case OMPC_simd:
18813 case OMPC_priority:
18814 case OMPC_grainsize:
18815 case OMPC_nogroup:
18816 case OMPC_num_tasks:
18817 case OMPC_hint:
18818 case OMPC_dist_schedule:
18819 case OMPC_defaultmap:
18820 case OMPC_unknown:
18821 case OMPC_uniform:
18822 case OMPC_unified_address:
18823 case OMPC_unified_shared_memory:
18824 case OMPC_reverse_offload:
18825 case OMPC_dynamic_allocators:
18826 case OMPC_atomic_default_mem_order:
18827 case OMPC_self_maps:
18828 case OMPC_device_type:
18829 case OMPC_match:
18830 case OMPC_order:
18831 case OMPC_at:
18832 case OMPC_severity:
18833 case OMPC_message:
18834 case OMPC_destroy:
18835 case OMPC_novariants:
18836 case OMPC_nocontext:
18837 case OMPC_detach:
18838 case OMPC_uses_allocators:
18839 case OMPC_when:
18840 case OMPC_bind:
18841 default:
18842 llvm_unreachable("Clause is not allowed.");
18843 }
18844 return Res;
18845}
18846
18848 ExprObjectKind OK,
18849 SourceLocation Loc) {
18850 ExprResult Res = SemaRef.BuildDeclRefExpr(
18851 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
18852 if (!Res.isUsable())
18853 return ExprError();
18854 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
18855 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
18856 if (!Res.isUsable())
18857 return ExprError();
18858 }
18859 if (VK != VK_LValue && Res.get()->isGLValue()) {
18860 Res = SemaRef.DefaultLvalueConversion(Res.get());
18861 if (!Res.isUsable())
18862 return ExprError();
18863 }
18864 return Res;
18865}
18866
18868 SourceLocation StartLoc,
18869 SourceLocation LParenLoc,
18870 SourceLocation EndLoc) {
18872 SmallVector<Expr *, 8> PrivateCopies;
18873 unsigned OMPVersion = getLangOpts().OpenMP;
18874 bool IsImplicitClause =
18875 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18876 for (Expr *RefExpr : VarList) {
18877 assert(RefExpr && "NULL expr in OpenMP private clause.");
18878 SourceLocation ELoc;
18879 SourceRange ERange;
18880 Expr *SimpleRefExpr = RefExpr;
18881 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18882 if (Res.second) {
18883 // It will be analyzed later.
18884 Vars.push_back(RefExpr);
18885 PrivateCopies.push_back(nullptr);
18886 }
18887 ValueDecl *D = Res.first;
18888 if (!D)
18889 continue;
18890
18891 QualType Type = D->getType();
18892 auto *VD = dyn_cast<VarDecl>(D);
18893
18894 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18895 // A variable that appears in a private clause must not have an incomplete
18896 // type or a reference type.
18897 if (SemaRef.RequireCompleteType(ELoc, Type,
18898 diag::err_omp_private_incomplete_type))
18899 continue;
18900 Type = Type.getNonReferenceType();
18901
18902 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18903 // A variable that is privatized must not have a const-qualified type
18904 // unless it is of class type with a mutable member. This restriction does
18905 // not apply to the firstprivate clause.
18906 //
18907 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18908 // A variable that appears in a private clause must not have a
18909 // const-qualified type unless it is of class type with a mutable member.
18910 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
18911 continue;
18912
18913 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18914 // in a Construct]
18915 // Variables with the predetermined data-sharing attributes may not be
18916 // listed in data-sharing attributes clauses, except for the cases
18917 // listed below. For these exceptions only, listing a predetermined
18918 // variable in a data-sharing attribute clause is allowed and overrides
18919 // the variable's predetermined data-sharing attributes.
18920 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18921 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18922 Diag(ELoc, diag::err_omp_wrong_dsa)
18923 << getOpenMPClauseNameForDiag(DVar.CKind)
18924 << getOpenMPClauseNameForDiag(OMPC_private);
18926 continue;
18927 }
18928
18929 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18930 // Variably modified types are not supported for tasks.
18932 isOpenMPTaskingDirective(CurrDir)) {
18933 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18934 << getOpenMPClauseNameForDiag(OMPC_private) << Type
18935 << getOpenMPDirectiveName(CurrDir, OMPVersion);
18936 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18938 Diag(D->getLocation(),
18939 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18940 << D;
18941 continue;
18942 }
18943
18944 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18945 // A list item cannot appear in both a map clause and a data-sharing
18946 // attribute clause on the same construct
18947 //
18948 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18949 // A list item cannot appear in both a map clause and a data-sharing
18950 // attribute clause on the same construct unless the construct is a
18951 // combined construct.
18952 if ((getLangOpts().OpenMP <= 45 &&
18954 CurrDir == OMPD_target) {
18955 OpenMPClauseKind ConflictKind;
18956 if (DSAStack->checkMappableExprComponentListsForDecl(
18957 VD, /*CurrentRegionOnly=*/true,
18959 OpenMPClauseKind WhereFoundClauseKind) -> bool {
18960 ConflictKind = WhereFoundClauseKind;
18961 return true;
18962 })) {
18963 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18964 << getOpenMPClauseNameForDiag(OMPC_private)
18965 << getOpenMPClauseNameForDiag(ConflictKind)
18966 << getOpenMPDirectiveName(CurrDir, OMPVersion);
18968 continue;
18969 }
18970 }
18971
18972 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18973 // A variable of class type (or array thereof) that appears in a private
18974 // clause requires an accessible, unambiguous default constructor for the
18975 // class type.
18976 // Generate helper private variable and initialize it with the default
18977 // value. The address of the original variable is replaced by the address of
18978 // the new private variable in CodeGen. This new variable is not added to
18979 // IdResolver, so the code in the OpenMP region uses original variable for
18980 // proper diagnostics.
18981 Type = Type.getUnqualifiedType();
18982 VarDecl *VDPrivate =
18983 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
18984 D->hasAttrs() ? &D->getAttrs() : nullptr,
18985 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18986 SemaRef.ActOnUninitializedDecl(VDPrivate);
18987 if (VDPrivate->isInvalidDecl())
18988 continue;
18989 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18990 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
18991
18992 DeclRefExpr *Ref = nullptr;
18993 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18994 auto *FD = dyn_cast<FieldDecl>(D);
18995 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18996 if (VD)
18998 RefExpr->getExprLoc());
18999 else
19000 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19001 }
19002 if (!IsImplicitClause)
19003 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
19004 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19005 ? RefExpr->IgnoreParens()
19006 : Ref);
19007 PrivateCopies.push_back(VDPrivateRefExpr);
19008 }
19009
19010 if (Vars.empty())
19011 return nullptr;
19012
19013 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19014 Vars, PrivateCopies);
19015}
19016
19018 SourceLocation StartLoc,
19019 SourceLocation LParenLoc,
19020 SourceLocation EndLoc) {
19022 SmallVector<Expr *, 8> PrivateCopies;
19024 SmallVector<Decl *, 4> ExprCaptures;
19025 bool IsImplicitClause =
19026 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
19027 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
19028 unsigned OMPVersion = getLangOpts().OpenMP;
19029
19030 for (Expr *RefExpr : VarList) {
19031 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
19032 SourceLocation ELoc;
19033 SourceRange ERange;
19034 Expr *SimpleRefExpr = RefExpr;
19035 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19036 if (Res.second) {
19037 // It will be analyzed later.
19038 Vars.push_back(RefExpr);
19039 PrivateCopies.push_back(nullptr);
19040 Inits.push_back(nullptr);
19041 }
19042 ValueDecl *D = Res.first;
19043 if (!D)
19044 continue;
19045
19046 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
19047 QualType Type = D->getType();
19048 auto *VD = dyn_cast<VarDecl>(D);
19049
19050 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19051 // A variable that appears in a private clause must not have an incomplete
19052 // type or a reference type.
19053 if (SemaRef.RequireCompleteType(ELoc, Type,
19054 diag::err_omp_firstprivate_incomplete_type))
19055 continue;
19056 Type = Type.getNonReferenceType();
19057
19058 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
19059 // A variable of class type (or array thereof) that appears in a private
19060 // clause requires an accessible, unambiguous copy constructor for the
19061 // class type.
19062 QualType ElemType =
19064
19065 // If an implicit firstprivate variable found it was checked already.
19066 DSAStackTy::DSAVarData TopDVar;
19067 if (!IsImplicitClause) {
19068 DSAStackTy::DSAVarData DVar =
19069 DSAStack->getTopDSA(D, /*FromParent=*/false);
19070 TopDVar = DVar;
19071 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19072 bool IsConstant = ElemType.isConstant(getASTContext());
19073 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
19074 // A list item that specifies a given variable may not appear in more
19075 // than one clause on the same directive, except that a variable may be
19076 // specified in both firstprivate and lastprivate clauses.
19077 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19078 // A list item may appear in a firstprivate or lastprivate clause but not
19079 // both.
19080 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
19081 (isOpenMPDistributeDirective(CurrDir) ||
19082 DVar.CKind != OMPC_lastprivate) &&
19083 DVar.RefExpr) {
19084 Diag(ELoc, diag::err_omp_wrong_dsa)
19085 << getOpenMPClauseNameForDiag(DVar.CKind)
19086 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
19088 continue;
19089 }
19090
19091 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19092 // in a Construct]
19093 // Variables with the predetermined data-sharing attributes may not be
19094 // listed in data-sharing attributes clauses, except for the cases
19095 // listed below. For these exceptions only, listing a predetermined
19096 // variable in a data-sharing attribute clause is allowed and overrides
19097 // the variable's predetermined data-sharing attributes.
19098 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19099 // in a Construct, C/C++, p.2]
19100 // Variables with const-qualified type having no mutable member may be
19101 // listed in a firstprivate clause, even if they are static data members.
19102 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
19103 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
19104 Diag(ELoc, diag::err_omp_wrong_dsa)
19105 << getOpenMPClauseNameForDiag(DVar.CKind)
19106 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
19108 continue;
19109 }
19110
19111 // OpenMP [2.9.3.4, Restrictions, p.2]
19112 // A list item that is private within a parallel region must not appear
19113 // in a firstprivate clause on a worksharing construct if any of the
19114 // worksharing regions arising from the worksharing construct ever bind
19115 // to any of the parallel regions arising from the parallel construct.
19116 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19117 // A list item that is private within a teams region must not appear in a
19118 // firstprivate clause on a distribute construct if any of the distribute
19119 // regions arising from the distribute construct ever bind to any of the
19120 // teams regions arising from the teams construct.
19121 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19122 // A list item that appears in a reduction clause of a teams construct
19123 // must not appear in a firstprivate clause on a distribute construct if
19124 // any of the distribute regions arising from the distribute construct
19125 // ever bind to any of the teams regions arising from the teams construct.
19126 if ((isOpenMPWorksharingDirective(CurrDir) ||
19127 isOpenMPDistributeDirective(CurrDir)) &&
19128 !isOpenMPParallelDirective(CurrDir) &&
19129 !isOpenMPTeamsDirective(CurrDir)) {
19130 DVar = DSAStack->getImplicitDSA(D, true);
19131 if (DVar.CKind != OMPC_shared &&
19132 (isOpenMPParallelDirective(DVar.DKind) ||
19133 isOpenMPTeamsDirective(DVar.DKind) ||
19134 DVar.DKind == OMPD_unknown)) {
19135 Diag(ELoc, diag::err_omp_required_access)
19136 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
19137 << getOpenMPClauseNameForDiag(OMPC_shared);
19139 continue;
19140 }
19141 }
19142 // OpenMP [2.9.3.4, Restrictions, p.3]
19143 // A list item that appears in a reduction clause of a parallel construct
19144 // must not appear in a firstprivate clause on a worksharing or task
19145 // construct if any of the worksharing or task regions arising from the
19146 // worksharing or task construct ever bind to any of the parallel regions
19147 // arising from the parallel construct.
19148 // OpenMP [2.9.3.4, Restrictions, p.4]
19149 // A list item that appears in a reduction clause in worksharing
19150 // construct must not appear in a firstprivate clause in a task construct
19151 // encountered during execution of any of the worksharing regions arising
19152 // from the worksharing construct.
19153 if (isOpenMPTaskingDirective(CurrDir)) {
19154 DVar = DSAStack->hasInnermostDSA(
19155 D,
19156 [](OpenMPClauseKind C, bool AppliedToPointee) {
19157 return C == OMPC_reduction && !AppliedToPointee;
19158 },
19159 [](OpenMPDirectiveKind K) {
19160 return isOpenMPParallelDirective(K) ||
19163 },
19164 /*FromParent=*/true);
19165 if (DVar.CKind == OMPC_reduction &&
19166 (isOpenMPParallelDirective(DVar.DKind) ||
19167 isOpenMPWorksharingDirective(DVar.DKind) ||
19168 isOpenMPTeamsDirective(DVar.DKind))) {
19169 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
19170 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
19172 continue;
19173 }
19174 }
19175
19176 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19177 // A list item cannot appear in both a map clause and a data-sharing
19178 // attribute clause on the same construct
19179 //
19180 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19181 // A list item cannot appear in both a map clause and a data-sharing
19182 // attribute clause on the same construct unless the construct is a
19183 // combined construct.
19184 if ((getLangOpts().OpenMP <= 45 &&
19186 CurrDir == OMPD_target) {
19187 OpenMPClauseKind ConflictKind;
19188 if (DSAStack->checkMappableExprComponentListsForDecl(
19189 VD, /*CurrentRegionOnly=*/true,
19190 [&ConflictKind](
19192 OpenMPClauseKind WhereFoundClauseKind) {
19193 ConflictKind = WhereFoundClauseKind;
19194 return true;
19195 })) {
19196 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19197 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
19198 << getOpenMPClauseNameForDiag(ConflictKind)
19199 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19200 OMPVersion);
19202 continue;
19203 }
19204 }
19205 }
19206
19207 // Variably modified types are not supported for tasks.
19209 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
19210 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19211 << getOpenMPClauseNameForDiag(OMPC_firstprivate) << Type
19212 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19213 OMPVersion);
19214 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19216 Diag(D->getLocation(),
19217 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19218 << D;
19219 continue;
19220 }
19221
19222 Type = Type.getUnqualifiedType();
19223 VarDecl *VDPrivate =
19224 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19225 D->hasAttrs() ? &D->getAttrs() : nullptr,
19226 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19227 // Generate helper private variable and initialize it with the value of the
19228 // original variable. The address of the original variable is replaced by
19229 // the address of the new private variable in the CodeGen. This new variable
19230 // is not added to IdResolver, so the code in the OpenMP region uses
19231 // original variable for proper diagnostics and variable capturing.
19232 Expr *VDInitRefExpr = nullptr;
19233 // For arrays generate initializer for single element and replace it by the
19234 // original array element in CodeGen.
19235 if (Type->isArrayType()) {
19236 VarDecl *VDInit =
19237 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
19238 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
19239 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
19240 ElemType = ElemType.getUnqualifiedType();
19241 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
19242 ElemType, ".firstprivate.temp");
19243 InitializedEntity Entity =
19246
19247 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
19248 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
19249 if (Result.isInvalid())
19250 VDPrivate->setInvalidDecl();
19251 else
19252 VDPrivate->setInit(Result.getAs<Expr>());
19253 // Remove temp variable declaration.
19254 getASTContext().Deallocate(VDInitTemp);
19255 } else {
19256 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
19257 ".firstprivate.temp");
19258 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
19259 RefExpr->getExprLoc());
19260 SemaRef.AddInitializerToDecl(
19261 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
19262 /*DirectInit=*/false);
19263 }
19264 if (VDPrivate->isInvalidDecl()) {
19265 if (IsImplicitClause) {
19266 Diag(RefExpr->getExprLoc(),
19267 diag::note_omp_task_predetermined_firstprivate_here);
19268 }
19269 continue;
19270 }
19271 SemaRef.CurContext->addDecl(VDPrivate);
19272 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19273 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
19274 RefExpr->getExprLoc());
19275 DeclRefExpr *Ref = nullptr;
19276 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19277 if (TopDVar.CKind == OMPC_lastprivate) {
19278 Ref = TopDVar.PrivateCopy;
19279 } else {
19280 auto *FD = dyn_cast<FieldDecl>(D);
19281 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19282 if (VD)
19283 Ref =
19285 RefExpr->getExprLoc());
19286 else
19287 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19288 if (VD || !isOpenMPCapturedDecl(D))
19289 ExprCaptures.push_back(Ref->getDecl());
19290 }
19291 }
19292 if (!IsImplicitClause)
19293 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
19294 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19295 ? RefExpr->IgnoreParens()
19296 : Ref);
19297 PrivateCopies.push_back(VDPrivateRefExpr);
19298 Inits.push_back(VDInitRefExpr);
19299 }
19300
19301 if (Vars.empty())
19302 return nullptr;
19303
19305 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
19306 buildPreInits(getASTContext(), ExprCaptures));
19307}
19308
19311 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
19312 SourceLocation LParenLoc, SourceLocation EndLoc) {
19313 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
19314 assert(ColonLoc.isValid() && "Colon location must be valid.");
19315 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
19316 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
19317 /*Last=*/OMPC_LASTPRIVATE_unknown)
19318 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
19319 return nullptr;
19320 }
19321
19323 SmallVector<Expr *, 8> SrcExprs;
19324 SmallVector<Expr *, 8> DstExprs;
19325 SmallVector<Expr *, 8> AssignmentOps;
19326 SmallVector<Decl *, 4> ExprCaptures;
19327 SmallVector<Expr *, 4> ExprPostUpdates;
19328 for (Expr *RefExpr : VarList) {
19329 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
19330 SourceLocation ELoc;
19331 SourceRange ERange;
19332 Expr *SimpleRefExpr = RefExpr;
19333 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19334 if (Res.second) {
19335 // It will be analyzed later.
19336 Vars.push_back(RefExpr);
19337 SrcExprs.push_back(nullptr);
19338 DstExprs.push_back(nullptr);
19339 AssignmentOps.push_back(nullptr);
19340 }
19341 ValueDecl *D = Res.first;
19342 if (!D)
19343 continue;
19344
19345 QualType Type = D->getType();
19346 auto *VD = dyn_cast<VarDecl>(D);
19347
19348 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
19349 // A variable that appears in a lastprivate clause must not have an
19350 // incomplete type or a reference type.
19351 if (SemaRef.RequireCompleteType(ELoc, Type,
19352 diag::err_omp_lastprivate_incomplete_type))
19353 continue;
19354 Type = Type.getNonReferenceType();
19355
19356 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19357 // A variable that is privatized must not have a const-qualified type
19358 // unless it is of class type with a mutable member. This restriction does
19359 // not apply to the firstprivate clause.
19360 //
19361 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
19362 // A variable that appears in a lastprivate clause must not have a
19363 // const-qualified type unless it is of class type with a mutable member.
19364 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
19365 continue;
19366
19367 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
19368 // A list item that appears in a lastprivate clause with the conditional
19369 // modifier must be a scalar variable.
19370 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
19371 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
19372 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19374 Diag(D->getLocation(),
19375 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19376 << D;
19377 continue;
19378 }
19379
19380 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19381 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19382 // in a Construct]
19383 // Variables with the predetermined data-sharing attributes may not be
19384 // listed in data-sharing attributes clauses, except for the cases
19385 // listed below.
19386 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19387 // A list item may appear in a firstprivate or lastprivate clause but not
19388 // both.
19389 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19390 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19391 (isOpenMPDistributeDirective(CurrDir) ||
19392 DVar.CKind != OMPC_firstprivate) &&
19393 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
19394 Diag(ELoc, diag::err_omp_wrong_dsa)
19395 << getOpenMPClauseNameForDiag(DVar.CKind)
19396 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
19398 continue;
19399 }
19400
19401 // OpenMP [2.14.3.5, Restrictions, p.2]
19402 // A list item that is private within a parallel region, or that appears in
19403 // the reduction clause of a parallel construct, must not appear in a
19404 // lastprivate clause on a worksharing construct if any of the corresponding
19405 // worksharing regions ever binds to any of the corresponding parallel
19406 // regions.
19407 DSAStackTy::DSAVarData TopDVar = DVar;
19408 if (isOpenMPWorksharingDirective(CurrDir) &&
19409 !isOpenMPParallelDirective(CurrDir) &&
19410 !isOpenMPTeamsDirective(CurrDir)) {
19411 DVar = DSAStack->getImplicitDSA(D, true);
19412 if (DVar.CKind != OMPC_shared) {
19413 Diag(ELoc, diag::err_omp_required_access)
19414 << getOpenMPClauseNameForDiag(OMPC_lastprivate)
19415 << getOpenMPClauseNameForDiag(OMPC_shared);
19417 continue;
19418 }
19419 }
19420
19421 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
19422 // A variable of class type (or array thereof) that appears in a
19423 // lastprivate clause requires an accessible, unambiguous default
19424 // constructor for the class type, unless the list item is also specified
19425 // in a firstprivate clause.
19426 // A variable of class type (or array thereof) that appears in a
19427 // lastprivate clause requires an accessible, unambiguous copy assignment
19428 // operator for the class type.
19430 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
19431 Type.getUnqualifiedType(), ".lastprivate.src",
19432 D->hasAttrs() ? &D->getAttrs() : nullptr);
19433 DeclRefExpr *PseudoSrcExpr =
19434 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
19435 VarDecl *DstVD =
19436 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
19437 D->hasAttrs() ? &D->getAttrs() : nullptr);
19438 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19439 // For arrays generate assignment operation for single element and replace
19440 // it by the original array element in CodeGen.
19441 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
19442 PseudoDstExpr, PseudoSrcExpr);
19443 if (AssignmentOp.isInvalid())
19444 continue;
19445 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19446 /*DiscardedValue=*/false);
19447 if (AssignmentOp.isInvalid())
19448 continue;
19449
19450 DeclRefExpr *Ref = nullptr;
19451 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19452 if (TopDVar.CKind == OMPC_firstprivate) {
19453 Ref = TopDVar.PrivateCopy;
19454 } else {
19455 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19456 if (!isOpenMPCapturedDecl(D))
19457 ExprCaptures.push_back(Ref->getDecl());
19458 }
19459 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
19460 (!isOpenMPCapturedDecl(D) &&
19461 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
19462 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
19463 if (!RefRes.isUsable())
19464 continue;
19465 ExprResult PostUpdateRes =
19466 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19467 SimpleRefExpr, RefRes.get());
19468 if (!PostUpdateRes.isUsable())
19469 continue;
19470 ExprPostUpdates.push_back(
19471 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19472 }
19473 }
19474 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
19475 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19476 ? RefExpr->IgnoreParens()
19477 : Ref);
19478 SrcExprs.push_back(PseudoSrcExpr);
19479 DstExprs.push_back(PseudoDstExpr);
19480 AssignmentOps.push_back(AssignmentOp.get());
19481 }
19482
19483 if (Vars.empty())
19484 return nullptr;
19485
19487 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
19488 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
19489 buildPreInits(getASTContext(), ExprCaptures),
19490 buildPostUpdate(SemaRef, ExprPostUpdates));
19491}
19492
19494 SourceLocation StartLoc,
19495 SourceLocation LParenLoc,
19496 SourceLocation EndLoc) {
19498 for (Expr *RefExpr : VarList) {
19499 assert(RefExpr && "NULL expr in OpenMP shared clause.");
19500 SourceLocation ELoc;
19501 SourceRange ERange;
19502 Expr *SimpleRefExpr = RefExpr;
19503 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19504 if (Res.second) {
19505 // It will be analyzed later.
19506 Vars.push_back(RefExpr);
19507 }
19508 ValueDecl *D = Res.first;
19509 if (!D)
19510 continue;
19511
19512 auto *VD = dyn_cast<VarDecl>(D);
19513 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19514 // in a Construct]
19515 // Variables with the predetermined data-sharing attributes may not be
19516 // listed in data-sharing attributes clauses, except for the cases
19517 // listed below. For these exceptions only, listing a predetermined
19518 // variable in a data-sharing attribute clause is allowed and overrides
19519 // the variable's predetermined data-sharing attributes.
19520 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19521 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
19522 DVar.RefExpr) {
19523 Diag(ELoc, diag::err_omp_wrong_dsa)
19524 << getOpenMPClauseNameForDiag(DVar.CKind)
19525 << getOpenMPClauseNameForDiag(OMPC_shared);
19527 continue;
19528 }
19529
19530 DeclRefExpr *Ref = nullptr;
19531 if (!VD && isOpenMPCapturedDecl(D) &&
19532 !SemaRef.CurContext->isDependentContext())
19533 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19534 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
19535 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
19536 ? RefExpr->IgnoreParens()
19537 : Ref);
19538 }
19539
19540 if (Vars.empty())
19541 return nullptr;
19542
19543 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19544 Vars);
19545}
19546
19547namespace {
19548class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
19549 DSAStackTy *Stack;
19550
19551public:
19552 bool VisitDeclRefExpr(DeclRefExpr *E) {
19553 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
19554 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
19555 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
19556 return false;
19557 if (DVar.CKind != OMPC_unknown)
19558 return true;
19559 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
19560 VD,
19561 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
19562 return isOpenMPPrivate(C) && !AppliedToPointee;
19563 },
19564 [](OpenMPDirectiveKind) { return true; },
19565 /*FromParent=*/true);
19566 return DVarPrivate.CKind != OMPC_unknown;
19567 }
19568 return false;
19569 }
19570 bool VisitStmt(Stmt *S) {
19571 for (Stmt *Child : S->children()) {
19572 if (Child && Visit(Child))
19573 return true;
19574 }
19575 return false;
19576 }
19577 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
19578};
19579} // namespace
19580
19581namespace {
19582// Transform MemberExpression for specified FieldDecl of current class to
19583// DeclRefExpr to specified OMPCapturedExprDecl.
19584class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
19585 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
19586 ValueDecl *Field = nullptr;
19587 DeclRefExpr *CapturedExpr = nullptr;
19588
19589public:
19590 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
19591 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
19592
19593 ExprResult TransformMemberExpr(MemberExpr *E) {
19595 E->getMemberDecl() == Field) {
19596 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
19597 return CapturedExpr;
19598 }
19599 return BaseTransform::TransformMemberExpr(E);
19600 }
19601 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
19602};
19603} // namespace
19604
19605template <typename T, typename U>
19607 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
19608 for (U &Set : Lookups) {
19609 for (auto *D : Set) {
19610 if (T Res = Gen(cast<ValueDecl>(D)))
19611 return Res;
19612 }
19613 }
19614 return T();
19615}
19616
19618 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
19619
19620 for (auto *RD : D->redecls()) {
19621 // Don't bother with extra checks if we already know this one isn't visible.
19622 if (RD == D)
19623 continue;
19624
19625 auto ND = cast<NamedDecl>(RD);
19626 if (LookupResult::isVisible(SemaRef, ND))
19627 return ND;
19628 }
19629
19630 return nullptr;
19631}
19632
19633static void
19635 SourceLocation Loc, QualType Ty,
19637 // Find all of the associated namespaces and classes based on the
19638 // arguments we have.
19639 Sema::AssociatedNamespaceSet AssociatedNamespaces;
19640 Sema::AssociatedClassSet AssociatedClasses;
19641 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
19642 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
19643 AssociatedClasses);
19644
19645 // C++ [basic.lookup.argdep]p3:
19646 // Let X be the lookup set produced by unqualified lookup (3.4.1)
19647 // and let Y be the lookup set produced by argument dependent
19648 // lookup (defined as follows). If X contains [...] then Y is
19649 // empty. Otherwise Y is the set of declarations found in the
19650 // namespaces associated with the argument types as described
19651 // below. The set of declarations found by the lookup of the name
19652 // is the union of X and Y.
19653 //
19654 // Here, we compute Y and add its members to the overloaded
19655 // candidate set.
19656 for (auto *NS : AssociatedNamespaces) {
19657 // When considering an associated namespace, the lookup is the
19658 // same as the lookup performed when the associated namespace is
19659 // used as a qualifier (3.4.3.2) except that:
19660 //
19661 // -- Any using-directives in the associated namespace are
19662 // ignored.
19663 //
19664 // -- Any namespace-scope friend functions declared in
19665 // associated classes are visible within their respective
19666 // namespaces even if they are not visible during an ordinary
19667 // lookup (11.4).
19668 DeclContext::lookup_result R = NS->lookup(Id.getName());
19669 for (auto *D : R) {
19670 auto *Underlying = D;
19671 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19672 Underlying = USD->getTargetDecl();
19673
19674 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
19675 !isa<OMPDeclareMapperDecl>(Underlying))
19676 continue;
19677
19678 if (!SemaRef.isVisible(D)) {
19679 D = findAcceptableDecl(SemaRef, D);
19680 if (!D)
19681 continue;
19682 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19683 Underlying = USD->getTargetDecl();
19684 }
19685 Lookups.emplace_back();
19686 Lookups.back().addDecl(Underlying);
19687 }
19688 }
19689}
19690
19691static ExprResult
19693 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
19694 const DeclarationNameInfo &ReductionId, QualType Ty,
19695 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
19696 if (ReductionIdScopeSpec.isInvalid())
19697 return ExprError();
19698 SmallVector<UnresolvedSet<8>, 4> Lookups;
19699 if (S) {
19700 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19701 Lookup.suppressDiagnostics();
19702 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
19703 /*ObjectType=*/QualType())) {
19704 NamedDecl *D = Lookup.getRepresentativeDecl();
19705 do {
19706 S = S->getParent();
19707 } while (S && !S->isDeclScope(D));
19708 if (S)
19709 S = S->getParent();
19710 Lookups.emplace_back();
19711 Lookups.back().append(Lookup.begin(), Lookup.end());
19712 Lookup.clear();
19713 }
19714 } else if (auto *ULE =
19715 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19716 Lookups.push_back(UnresolvedSet<8>());
19717 Decl *PrevD = nullptr;
19718 for (NamedDecl *D : ULE->decls()) {
19719 if (D == PrevD)
19720 Lookups.push_back(UnresolvedSet<8>());
19721 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19722 Lookups.back().addDecl(DRD);
19723 PrevD = D;
19724 }
19725 }
19726 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
19730 return !D->isInvalidDecl() &&
19731 (D->getType()->isDependentType() ||
19732 D->getType()->isInstantiationDependentType() ||
19733 D->getType()->containsUnexpandedParameterPack());
19734 })) {
19735 UnresolvedSet<8> ResSet;
19736 for (const UnresolvedSet<8> &Set : Lookups) {
19737 if (Set.empty())
19738 continue;
19739 ResSet.append(Set.begin(), Set.end());
19740 // The last item marks the end of all declarations at the specified scope.
19741 ResSet.addDecl(Set[Set.size() - 1]);
19742 }
19744 SemaRef.Context, /*NamingClass=*/nullptr,
19745 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
19746 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
19747 /*KnownInstantiationDependent=*/false);
19748 }
19749 // Lookup inside the classes.
19750 // C++ [over.match.oper]p3:
19751 // For a unary operator @ with an operand of a type whose
19752 // cv-unqualified version is T1, and for a binary operator @ with
19753 // a left operand of a type whose cv-unqualified version is T1 and
19754 // a right operand of a type whose cv-unqualified version is T2,
19755 // three sets of candidate functions, designated member
19756 // candidates, non-member candidates and built-in candidates, are
19757 // constructed as follows:
19758 // -- If T1 is a complete class type or a class currently being
19759 // defined, the set of member candidates is the result of the
19760 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19761 // the set of member candidates is empty.
19762 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19763 Lookup.suppressDiagnostics();
19764 if (Ty->isRecordType()) {
19765 // Complete the type if it can be completed.
19766 // If the type is neither complete nor being defined, bail out now.
19767 bool IsComplete = SemaRef.isCompleteType(Loc, Ty);
19768 auto *RD = Ty->castAsRecordDecl();
19769 if (IsComplete || RD->isBeingDefined()) {
19770 Lookup.clear();
19771 SemaRef.LookupQualifiedName(Lookup, RD);
19772 if (Lookup.empty()) {
19773 Lookups.emplace_back();
19774 Lookups.back().append(Lookup.begin(), Lookup.end());
19775 }
19776 }
19777 }
19778 // Perform ADL.
19779 if (SemaRef.getLangOpts().CPlusPlus)
19780 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
19782 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
19783 if (!D->isInvalidDecl() &&
19784 SemaRef.Context.hasSameType(D->getType(), Ty))
19785 return D;
19786 return nullptr;
19787 }))
19788 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
19789 VK_LValue, Loc);
19790 if (SemaRef.getLangOpts().CPlusPlus) {
19792 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
19793 if (!D->isInvalidDecl() &&
19794 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
19796 SemaRef.getASTContext()))
19797 return D;
19798 return nullptr;
19799 })) {
19800 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19801 /*DetectVirtual=*/false);
19802 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
19803 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
19804 VD->getType().getUnqualifiedType()))) {
19805 if (SemaRef.CheckBaseClassAccess(
19806 Loc, VD->getType(), Ty, Paths.front(),
19807 /*DiagID=*/0) != Sema::AR_inaccessible) {
19808 SemaRef.BuildBasePathArray(Paths, BasePath);
19809 return SemaRef.BuildDeclRefExpr(
19810 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
19811 }
19812 }
19813 }
19814 }
19815 }
19816 if (ReductionIdScopeSpec.isSet()) {
19817 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19818 << Ty << Range;
19819 return ExprError();
19820 }
19821 return ExprEmpty();
19822}
19823
19824namespace {
19825/// Data for the reduction-based clauses.
19826struct ReductionData {
19827 /// List of original reduction items.
19828 SmallVector<Expr *, 8> Vars;
19829 /// List of private copies of the reduction items.
19830 SmallVector<Expr *, 8> Privates;
19831 /// LHS expressions for the reduction_op expressions.
19832 SmallVector<Expr *, 8> LHSs;
19833 /// RHS expressions for the reduction_op expressions.
19834 SmallVector<Expr *, 8> RHSs;
19835 /// Reduction operation expression.
19836 SmallVector<Expr *, 8> ReductionOps;
19837 /// inscan copy operation expressions.
19838 SmallVector<Expr *, 8> InscanCopyOps;
19839 /// inscan copy temp array expressions for prefix sums.
19840 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19841 /// inscan copy temp array element expressions for prefix sums.
19842 SmallVector<Expr *, 8> InscanCopyArrayElems;
19843 /// Taskgroup descriptors for the corresponding reduction items in
19844 /// in_reduction clauses.
19845 SmallVector<Expr *, 8> TaskgroupDescriptors;
19846 /// List of captures for clause.
19847 SmallVector<Decl *, 4> ExprCaptures;
19848 /// List of postupdate expressions.
19849 SmallVector<Expr *, 4> ExprPostUpdates;
19850 /// Reduction modifier.
19851 unsigned RedModifier = 0;
19852 /// Original modifier.
19853 unsigned OrigSharingModifier = 0;
19854 /// Private Variable Reduction
19855 SmallVector<bool, 8> IsPrivateVarReduction;
19856 ReductionData() = delete;
19857 /// Reserves required memory for the reduction data.
19858 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
19859 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
19860 Vars.reserve(Size);
19861 Privates.reserve(Size);
19862 LHSs.reserve(Size);
19863 RHSs.reserve(Size);
19864 ReductionOps.reserve(Size);
19865 IsPrivateVarReduction.reserve(Size);
19866 if (RedModifier == OMPC_REDUCTION_inscan) {
19867 InscanCopyOps.reserve(Size);
19868 InscanCopyArrayTemps.reserve(Size);
19869 InscanCopyArrayElems.reserve(Size);
19870 }
19871 TaskgroupDescriptors.reserve(Size);
19872 ExprCaptures.reserve(Size);
19873 ExprPostUpdates.reserve(Size);
19874 }
19875 /// Stores reduction item and reduction operation only (required for dependent
19876 /// reduction item).
19877 void push(Expr *Item, Expr *ReductionOp) {
19878 Vars.emplace_back(Item);
19879 Privates.emplace_back(nullptr);
19880 LHSs.emplace_back(nullptr);
19881 RHSs.emplace_back(nullptr);
19882 ReductionOps.emplace_back(ReductionOp);
19883 IsPrivateVarReduction.emplace_back(false);
19884 TaskgroupDescriptors.emplace_back(nullptr);
19885 if (RedModifier == OMPC_REDUCTION_inscan) {
19886 InscanCopyOps.push_back(nullptr);
19887 InscanCopyArrayTemps.push_back(nullptr);
19888 InscanCopyArrayElems.push_back(nullptr);
19889 }
19890 }
19891 /// Stores reduction data.
19892 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19893 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19894 Expr *CopyArrayElem, bool IsPrivate) {
19895 Vars.emplace_back(Item);
19896 Privates.emplace_back(Private);
19897 LHSs.emplace_back(LHS);
19898 RHSs.emplace_back(RHS);
19899 ReductionOps.emplace_back(ReductionOp);
19900 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19901 if (RedModifier == OMPC_REDUCTION_inscan) {
19902 InscanCopyOps.push_back(CopyOp);
19903 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19904 InscanCopyArrayElems.push_back(CopyArrayElem);
19905 } else {
19906 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
19907 CopyArrayElem == nullptr &&
19908 "Copy operation must be used for inscan reductions only.");
19909 }
19910 IsPrivateVarReduction.emplace_back(IsPrivate);
19911 }
19912};
19913} // namespace
19914
19916 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
19917 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
19918 const Expr *Length = OASE->getLength();
19919 if (Length == nullptr) {
19920 // For array sections of the form [1:] or [:], we would need to analyze
19921 // the lower bound...
19922 if (OASE->getColonLocFirst().isValid())
19923 return false;
19924
19925 // This is an array subscript which has implicit length 1!
19926 SingleElement = true;
19927 ArraySizes.push_back(llvm::APSInt::get(1));
19928 } else {
19929 Expr::EvalResult Result;
19930 if (!Length->EvaluateAsInt(Result, Context))
19931 return false;
19932
19933 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19934 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19935 ArraySizes.push_back(ConstantLengthValue);
19936 }
19937
19938 // Get the base of this array section and walk up from there.
19939 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
19940
19941 // We require length = 1 for all array sections except the right-most to
19942 // guarantee that the memory region is contiguous and has no holes in it.
19943 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
19944 Length = TempOASE->getLength();
19945 if (Length == nullptr) {
19946 // For array sections of the form [1:] or [:], we would need to analyze
19947 // the lower bound...
19948 if (OASE->getColonLocFirst().isValid())
19949 return false;
19950
19951 // This is an array subscript which has implicit length 1!
19952 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
19953 ArraySizes.push_back(ConstantOne);
19954 } else {
19955 Expr::EvalResult Result;
19956 if (!Length->EvaluateAsInt(Result, Context))
19957 return false;
19958
19959 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19960 if (ConstantLengthValue.getSExtValue() != 1)
19961 return false;
19962
19963 ArraySizes.push_back(ConstantLengthValue);
19964 }
19965 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19966 }
19967
19968 // If we have a single element, we don't need to add the implicit lengths.
19969 if (!SingleElement) {
19970 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
19971 // Has implicit length 1!
19972 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
19973 ArraySizes.push_back(ConstantOne);
19974 Base = TempASE->getBase()->IgnoreParenImpCasts();
19975 }
19976 }
19977
19978 // This array section can be privatized as a single value or as a constant
19979 // sized array.
19980 return true;
19981}
19982
19983static BinaryOperatorKind
19985 if (BOK == BO_Add)
19986 return BO_AddAssign;
19987 if (BOK == BO_Mul)
19988 return BO_MulAssign;
19989 if (BOK == BO_And)
19990 return BO_AndAssign;
19991 if (BOK == BO_Or)
19992 return BO_OrAssign;
19993 if (BOK == BO_Xor)
19994 return BO_XorAssign;
19995 return BOK;
19996}
19997
19999 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
20000 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20001 SourceLocation ColonLoc, SourceLocation EndLoc,
20002 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20003 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
20004 DeclarationName DN = ReductionId.getName();
20006 BinaryOperatorKind BOK = BO_Comma;
20007
20008 ASTContext &Context = S.Context;
20009 // OpenMP [2.14.3.6, reduction clause]
20010 // C
20011 // reduction-identifier is either an identifier or one of the following
20012 // operators: +, -, *, &, |, ^, && and ||
20013 // C++
20014 // reduction-identifier is either an id-expression or one of the following
20015 // operators: +, -, *, &, |, ^, && and ||
20016 switch (OOK) {
20017 case OO_Plus:
20018 BOK = BO_Add;
20019 break;
20020 case OO_Minus:
20021 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
20022 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
20023 // reduction identifier.
20024 if (S.LangOpts.OpenMP > 52)
20025 BOK = BO_Comma;
20026 else
20027 BOK = BO_Add;
20028 break;
20029 case OO_Star:
20030 BOK = BO_Mul;
20031 break;
20032 case OO_Amp:
20033 BOK = BO_And;
20034 break;
20035 case OO_Pipe:
20036 BOK = BO_Or;
20037 break;
20038 case OO_Caret:
20039 BOK = BO_Xor;
20040 break;
20041 case OO_AmpAmp:
20042 BOK = BO_LAnd;
20043 break;
20044 case OO_PipePipe:
20045 BOK = BO_LOr;
20046 break;
20047 case OO_New:
20048 case OO_Delete:
20049 case OO_Array_New:
20050 case OO_Array_Delete:
20051 case OO_Slash:
20052 case OO_Percent:
20053 case OO_Tilde:
20054 case OO_Exclaim:
20055 case OO_Equal:
20056 case OO_Less:
20057 case OO_Greater:
20058 case OO_LessEqual:
20059 case OO_GreaterEqual:
20060 case OO_PlusEqual:
20061 case OO_MinusEqual:
20062 case OO_StarEqual:
20063 case OO_SlashEqual:
20064 case OO_PercentEqual:
20065 case OO_CaretEqual:
20066 case OO_AmpEqual:
20067 case OO_PipeEqual:
20068 case OO_LessLess:
20069 case OO_GreaterGreater:
20070 case OO_LessLessEqual:
20071 case OO_GreaterGreaterEqual:
20072 case OO_EqualEqual:
20073 case OO_ExclaimEqual:
20074 case OO_Spaceship:
20075 case OO_PlusPlus:
20076 case OO_MinusMinus:
20077 case OO_Comma:
20078 case OO_ArrowStar:
20079 case OO_Arrow:
20080 case OO_Call:
20081 case OO_Subscript:
20082 case OO_Conditional:
20083 case OO_Coawait:
20085 llvm_unreachable("Unexpected reduction identifier");
20086 case OO_None:
20087 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
20088 if (II->isStr("max"))
20089 BOK = BO_GT;
20090 else if (II->isStr("min"))
20091 BOK = BO_LT;
20092 }
20093 break;
20094 }
20095
20096 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
20097 // A reduction clause with the minus (-) operator was deprecated
20098 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
20099 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
20100
20101 SourceRange ReductionIdRange;
20102 if (ReductionIdScopeSpec.isValid())
20103 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
20104 else
20105 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
20106 ReductionIdRange.setEnd(ReductionId.getEndLoc());
20107
20108 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
20109 bool FirstIter = true;
20110 for (Expr *RefExpr : VarList) {
20111 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
20112 // OpenMP [2.1, C/C++]
20113 // A list item is a variable or array section, subject to the restrictions
20114 // specified in Section 2.4 on page 42 and in each of the sections
20115 // describing clauses and directives for which a list appears.
20116 // OpenMP [2.14.3.3, Restrictions, p.1]
20117 // A variable that is part of another variable (as an array or
20118 // structure element) cannot appear in a private clause.
20119 if (!FirstIter && IR != ER)
20120 ++IR;
20121 FirstIter = false;
20122 SourceLocation ELoc;
20123 SourceRange ERange;
20124 bool IsPrivate = false;
20125 Expr *SimpleRefExpr = RefExpr;
20126 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
20127 /*AllowArraySection=*/true);
20128 if (Res.second) {
20129 // Try to find 'declare reduction' corresponding construct before using
20130 // builtin/overloaded operators.
20131 QualType Type = Context.DependentTy;
20132 CXXCastPath BasePath;
20133 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20134 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20135 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
20136 Expr *ReductionOp = nullptr;
20137 if (S.CurContext->isDependentContext() &&
20138 (DeclareReductionRef.isUnset() ||
20139 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
20140 ReductionOp = DeclareReductionRef.get();
20141 // It will be analyzed later.
20142 RD.push(RefExpr, ReductionOp);
20143 }
20144 ValueDecl *D = Res.first;
20145 if (!D)
20146 continue;
20147
20148 Expr *TaskgroupDescriptor = nullptr;
20149 QualType Type;
20150 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
20151 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
20152 if (ASE) {
20153 Type = ASE->getType().getNonReferenceType();
20154 } else if (OASE) {
20155 QualType BaseType =
20157 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20158 Type = ATy->getElementType();
20159 else
20160 Type = BaseType->getPointeeType();
20161 Type = Type.getNonReferenceType();
20162 } else {
20163 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
20164 }
20165 auto *VD = dyn_cast<VarDecl>(D);
20166
20167 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
20168 // A variable that appears in a private clause must not have an incomplete
20169 // type or a reference type.
20170 if (S.RequireCompleteType(ELoc, D->getType(),
20171 diag::err_omp_reduction_incomplete_type))
20172 continue;
20173 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20174 // A list item that appears in a reduction clause must not be
20175 // const-qualified.
20176 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
20177 /*AcceptIfMutable=*/false, ASE || OASE))
20178 continue;
20179
20180 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
20181 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
20182 // If a list-item is a reference type then it must bind to the same object
20183 // for all threads of the team.
20184 if (!ASE && !OASE) {
20185 if (VD) {
20186 VarDecl *VDDef = VD->getDefinition();
20187 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
20188 DSARefChecker Check(Stack);
20189 if (Check.Visit(VDDef->getInit())) {
20190 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
20191 << getOpenMPClauseNameForDiag(ClauseKind) << ERange;
20192 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
20193 continue;
20194 }
20195 }
20196 }
20197
20198 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
20199 // in a Construct]
20200 // Variables with the predetermined data-sharing attributes may not be
20201 // listed in data-sharing attributes clauses, except for the cases
20202 // listed below. For these exceptions only, listing a predetermined
20203 // variable in a data-sharing attribute clause is allowed and overrides
20204 // the variable's predetermined data-sharing attributes.
20205 // OpenMP [2.14.3.6, Restrictions, p.3]
20206 // Any number of reduction clauses can be specified on the directive,
20207 // but a list item can appear only once in the reduction clauses for that
20208 // directive.
20209 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20210 if (DVar.CKind == OMPC_reduction) {
20211 S.Diag(ELoc, diag::err_omp_once_referenced)
20212 << getOpenMPClauseNameForDiag(ClauseKind);
20213 if (DVar.RefExpr)
20214 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
20215 continue;
20216 }
20217 if (DVar.CKind != OMPC_unknown) {
20218 S.Diag(ELoc, diag::err_omp_wrong_dsa)
20219 << getOpenMPClauseNameForDiag(DVar.CKind)
20220 << getOpenMPClauseNameForDiag(OMPC_reduction);
20221 reportOriginalDsa(S, Stack, D, DVar);
20222 continue;
20223 }
20224
20225 // OpenMP [2.14.3.6, Restrictions, p.1]
20226 // A list item that appears in a reduction clause of a worksharing
20227 // construct must be shared in the parallel regions to which any of the
20228 // worksharing regions arising from the worksharing construct bind.
20229
20230 if (S.getLangOpts().OpenMP <= 52 &&
20232 !isOpenMPParallelDirective(CurrDir) &&
20233 !isOpenMPTeamsDirective(CurrDir)) {
20234 DVar = Stack->getImplicitDSA(D, true);
20235 if (DVar.CKind != OMPC_shared) {
20236 S.Diag(ELoc, diag::err_omp_required_access)
20237 << getOpenMPClauseNameForDiag(OMPC_reduction)
20238 << getOpenMPClauseNameForDiag(OMPC_shared);
20239 reportOriginalDsa(S, Stack, D, DVar);
20240 continue;
20241 }
20242 } else if (isOpenMPWorksharingDirective(CurrDir) &&
20243 !isOpenMPParallelDirective(CurrDir) &&
20244 !isOpenMPTeamsDirective(CurrDir)) {
20245 // OpenMP 6.0 [ 7.6.10 ]
20246 // Support Reduction over private variables with reduction clause.
20247 // A list item in a reduction clause can now be private in the enclosing
20248 // context. For orphaned constructs it is assumed to be shared unless
20249 // the original(private) modifier appears in the clause.
20250 DVar = Stack->getImplicitDSA(D, true);
20251 // Determine if the variable should be considered private
20252 IsPrivate = DVar.CKind != OMPC_shared;
20253 bool IsOrphaned = false;
20254 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
20255 IsOrphaned = ParentDir == OMPD_unknown;
20256 if ((IsOrphaned &&
20257 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
20258 IsPrivate = true;
20259 }
20260 } else {
20261 // Threadprivates cannot be shared between threads, so dignose if the base
20262 // is a threadprivate variable.
20263 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20264 if (DVar.CKind == OMPC_threadprivate) {
20265 S.Diag(ELoc, diag::err_omp_wrong_dsa)
20266 << getOpenMPClauseNameForDiag(DVar.CKind)
20267 << getOpenMPClauseNameForDiag(OMPC_reduction);
20268 reportOriginalDsa(S, Stack, D, DVar);
20269 continue;
20270 }
20271 }
20272
20273 // Try to find 'declare reduction' corresponding construct before using
20274 // builtin/overloaded operators.
20275 CXXCastPath BasePath;
20276 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20277 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20278 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
20279 if (DeclareReductionRef.isInvalid())
20280 continue;
20281 if (S.CurContext->isDependentContext() &&
20282 (DeclareReductionRef.isUnset() ||
20283 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
20284 RD.push(RefExpr, DeclareReductionRef.get());
20285 continue;
20286 }
20287 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
20288 // Not allowed reduction identifier is found.
20289 if (S.LangOpts.OpenMP > 52)
20290 S.Diag(ReductionId.getBeginLoc(),
20291 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
20292 << Type << ReductionIdRange;
20293 else
20294 S.Diag(ReductionId.getBeginLoc(),
20295 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
20296 << Type << ReductionIdRange;
20297 continue;
20298 }
20299
20300 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20301 // The type of a list item that appears in a reduction clause must be valid
20302 // for the reduction-identifier. For a max or min reduction in C, the type
20303 // of the list item must be an allowed arithmetic data type: char, int,
20304 // float, double, or _Bool, possibly modified with long, short, signed, or
20305 // unsigned. For a max or min reduction in C++, the type of the list item
20306 // must be an allowed arithmetic data type: char, wchar_t, int, float,
20307 // double, or bool, possibly modified with long, short, signed, or unsigned.
20308 if (DeclareReductionRef.isUnset()) {
20309 if ((BOK == BO_GT || BOK == BO_LT) &&
20310 !(Type->isScalarType() ||
20311 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
20312 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
20313 << getOpenMPClauseNameForDiag(ClauseKind)
20314 << S.getLangOpts().CPlusPlus;
20315 if (!ASE && !OASE) {
20316 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20318 S.Diag(D->getLocation(),
20319 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20320 << D;
20321 }
20322 continue;
20323 }
20324 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
20325 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
20326 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
20327 << getOpenMPClauseNameForDiag(ClauseKind);
20328 if (!ASE && !OASE) {
20329 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20331 S.Diag(D->getLocation(),
20332 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20333 << D;
20334 }
20335 continue;
20336 }
20337 }
20338
20339 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
20340 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
20341 D->hasAttrs() ? &D->getAttrs() : nullptr);
20342 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
20343 D->hasAttrs() ? &D->getAttrs() : nullptr);
20344 QualType PrivateTy = Type;
20345
20346 // Try if we can determine constant lengths for all array sections and avoid
20347 // the VLA.
20348 bool ConstantLengthOASE = false;
20349 if (OASE) {
20350 bool SingleElement;
20352 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
20353 Context, OASE, SingleElement, ArraySizes);
20354
20355 // If we don't have a single element, we must emit a constant array type.
20356 if (ConstantLengthOASE && !SingleElement) {
20357 for (llvm::APSInt &Size : ArraySizes)
20358 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
20360 /*IndexTypeQuals=*/0);
20361 }
20362 }
20363
20364 if ((OASE && !ConstantLengthOASE) ||
20365 (!OASE && !ASE &&
20367 if (!Context.getTargetInfo().isVLASupported()) {
20368 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
20369 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20370 S.Diag(ELoc, diag::note_vla_unsupported);
20371 continue;
20372 } else {
20373 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20374 S.targetDiag(ELoc, diag::note_vla_unsupported);
20375 }
20376 }
20377 // For arrays/array sections only:
20378 // Create pseudo array type for private copy. The size for this array will
20379 // be generated during codegen.
20380 // For array subscripts or single variables Private Ty is the same as Type
20381 // (type of the variable or single array element).
20382 PrivateTy = Context.getVariableArrayType(
20383 Type,
20384 new (Context)
20385 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
20386 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
20387 } else if (!ASE && !OASE &&
20388 Context.getAsArrayType(D->getType().getNonReferenceType())) {
20389 PrivateTy = D->getType().getNonReferenceType();
20390 }
20391 // Private copy.
20392 VarDecl *PrivateVD =
20393 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20394 D->hasAttrs() ? &D->getAttrs() : nullptr,
20395 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20396 // Add initializer for private variable.
20397 Expr *Init = nullptr;
20398 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
20399 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
20400 if (DeclareReductionRef.isUsable()) {
20401 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
20402 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
20403 if (DRD->getInitializer()) {
20404 Init = DRDRef;
20405 RHSVD->setInit(DRDRef);
20407 }
20408 } else {
20409 switch (BOK) {
20410 case BO_Add:
20411 case BO_Xor:
20412 case BO_Or:
20413 case BO_LOr:
20414 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
20416 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
20417 break;
20418 case BO_Mul:
20419 case BO_LAnd:
20420 if (Type->isScalarType() || Type->isAnyComplexType()) {
20421 // '*' and '&&' reduction ops - initializer is '1'.
20422 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
20423 }
20424 break;
20425 case BO_And: {
20426 // '&' reduction op - initializer is '~0'.
20427 QualType OrigType = Type;
20428 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
20429 Type = ComplexTy->getElementType();
20430 if (Type->isRealFloatingType()) {
20431 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
20432 Context.getFloatTypeSemantics(Type));
20433 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20434 Type, ELoc);
20435 } else if (Type->isScalarType()) {
20436 uint64_t Size = Context.getTypeSize(Type);
20437 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
20438 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
20439 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20440 }
20441 if (Init && OrigType->isAnyComplexType()) {
20442 // Init = 0xFFFF + 0xFFFFi;
20443 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
20444 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
20445 }
20446 Type = OrigType;
20447 break;
20448 }
20449 case BO_LT:
20450 case BO_GT: {
20451 // 'min' reduction op - initializer is 'Largest representable number in
20452 // the reduction list item type'.
20453 // 'max' reduction op - initializer is 'Least representable number in
20454 // the reduction list item type'.
20455 if (Type->isIntegerType() || Type->isPointerType()) {
20456 bool IsSigned = Type->hasSignedIntegerRepresentation();
20457 uint64_t Size = Context.getTypeSize(Type);
20458 QualType IntTy =
20459 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
20460 llvm::APInt InitValue =
20461 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
20462 : llvm::APInt::getMinValue(Size)
20463 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
20464 : llvm::APInt::getMaxValue(Size);
20465 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20466 if (Type->isPointerType()) {
20467 // Cast to pointer type.
20469 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
20470 if (CastExpr.isInvalid())
20471 continue;
20472 Init = CastExpr.get();
20473 }
20474 } else if (Type->isRealFloatingType()) {
20475 llvm::APFloat InitValue = llvm::APFloat::getLargest(
20476 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
20477 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20478 Type, ELoc);
20479 }
20480 break;
20481 }
20482 case BO_PtrMemD:
20483 case BO_PtrMemI:
20484 case BO_MulAssign:
20485 case BO_Div:
20486 case BO_Rem:
20487 case BO_Sub:
20488 case BO_Shl:
20489 case BO_Shr:
20490 case BO_LE:
20491 case BO_GE:
20492 case BO_EQ:
20493 case BO_NE:
20494 case BO_Cmp:
20495 case BO_AndAssign:
20496 case BO_XorAssign:
20497 case BO_OrAssign:
20498 case BO_Assign:
20499 case BO_AddAssign:
20500 case BO_SubAssign:
20501 case BO_DivAssign:
20502 case BO_RemAssign:
20503 case BO_ShlAssign:
20504 case BO_ShrAssign:
20505 case BO_Comma:
20506 llvm_unreachable("Unexpected reduction operation");
20507 }
20508 }
20509 if (Init && DeclareReductionRef.isUnset()) {
20510 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
20511 // Store initializer for single element in private copy. Will be used
20512 // during codegen.
20513 PrivateVD->setInit(RHSVD->getInit());
20514 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20515 } else if (!Init) {
20516 S.ActOnUninitializedDecl(RHSVD);
20517 // Store initializer for single element in private copy. Will be used
20518 // during codegen.
20519 PrivateVD->setInit(RHSVD->getInit());
20520 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20521 }
20522 if (RHSVD->isInvalidDecl())
20523 continue;
20524 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
20525 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
20526 << Type << ReductionIdRange;
20527 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20529 S.Diag(D->getLocation(),
20530 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20531 << D;
20532 continue;
20533 }
20534 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
20535 ExprResult ReductionOp;
20536 if (DeclareReductionRef.isUsable()) {
20537 QualType RedTy = DeclareReductionRef.get()->getType();
20538 QualType PtrRedTy = Context.getPointerType(RedTy);
20539 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
20540 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
20541 if (!BasePath.empty()) {
20542 LHS = S.DefaultLvalueConversion(LHS.get());
20543 RHS = S.DefaultLvalueConversion(RHS.get());
20545 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
20546 LHS.get()->getValueKind(), FPOptionsOverride());
20548 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
20549 RHS.get()->getValueKind(), FPOptionsOverride());
20550 }
20552 QualType Params[] = {PtrRedTy, PtrRedTy};
20553 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
20554 auto *OVE = new (Context) OpaqueValueExpr(
20555 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
20556 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
20557 Expr *Args[] = {LHS.get(), RHS.get()};
20558 ReductionOp =
20559 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
20561 } else {
20563 if (Type->isRecordType() && CombBOK != BOK) {
20565 ReductionOp =
20566 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20567 CombBOK, LHSDRE, RHSDRE);
20568 }
20569 if (!ReductionOp.isUsable()) {
20570 ReductionOp =
20571 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
20572 LHSDRE, RHSDRE);
20573 if (ReductionOp.isUsable()) {
20574 if (BOK != BO_LT && BOK != BO_GT) {
20575 ReductionOp =
20576 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20577 BO_Assign, LHSDRE, ReductionOp.get());
20578 } else {
20579 auto *ConditionalOp = new (Context)
20580 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
20581 RHSDRE, Type, VK_LValue, OK_Ordinary);
20582 ReductionOp =
20583 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20584 BO_Assign, LHSDRE, ConditionalOp);
20585 }
20586 }
20587 }
20588 if (ReductionOp.isUsable())
20589 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
20590 /*DiscardedValue=*/false);
20591 if (!ReductionOp.isUsable())
20592 continue;
20593 }
20594
20595 // Add copy operations for inscan reductions.
20596 // LHS = RHS;
20597 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
20598 if (ClauseKind == OMPC_reduction &&
20599 RD.RedModifier == OMPC_REDUCTION_inscan) {
20600 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
20601 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
20602 RHS.get());
20603 if (!CopyOpRes.isUsable())
20604 continue;
20605 CopyOpRes =
20606 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
20607 if (!CopyOpRes.isUsable())
20608 continue;
20609 // For simd directive and simd-based directives in simd mode no need to
20610 // construct temp array, need just a single temp element.
20611 if (Stack->getCurrentDirective() == OMPD_simd ||
20612 (S.getLangOpts().OpenMPSimd &&
20613 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
20614 VarDecl *TempArrayVD =
20615 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20616 D->hasAttrs() ? &D->getAttrs() : nullptr);
20617 // Add a constructor to the temp decl.
20618 S.ActOnUninitializedDecl(TempArrayVD);
20619 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
20620 } else {
20621 // Build temp array for prefix sum.
20622 auto *Dim = new (S.Context)
20625 PrivateTy, Dim, ArraySizeModifier::Normal,
20626 /*IndexTypeQuals=*/0);
20627 VarDecl *TempArrayVD =
20628 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
20629 D->hasAttrs() ? &D->getAttrs() : nullptr);
20630 // Add a constructor to the temp decl.
20631 S.ActOnUninitializedDecl(TempArrayVD);
20632 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
20633 TempArrayElem =
20634 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
20635 auto *Idx = new (S.Context)
20637 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
20638 ELoc, Idx, ELoc);
20639 }
20640 }
20641
20642 // OpenMP [2.15.4.6, Restrictions, p.2]
20643 // A list item that appears in an in_reduction clause of a task construct
20644 // must appear in a task_reduction clause of a construct associated with a
20645 // taskgroup region that includes the participating task in its taskgroup
20646 // set. The construct associated with the innermost region that meets this
20647 // condition must specify the same reduction-identifier as the in_reduction
20648 // clause.
20649 if (ClauseKind == OMPC_in_reduction) {
20650 SourceRange ParentSR;
20651 BinaryOperatorKind ParentBOK;
20652 const Expr *ParentReductionOp = nullptr;
20653 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
20654 DSAStackTy::DSAVarData ParentBOKDSA =
20655 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
20656 ParentBOKTD);
20657 DSAStackTy::DSAVarData ParentReductionOpDSA =
20658 Stack->getTopMostTaskgroupReductionData(
20659 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
20660 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20661 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20662 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
20663 (DeclareReductionRef.isUsable() && IsParentBOK) ||
20664 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20665 bool EmitError = true;
20666 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
20667 llvm::FoldingSetNodeID RedId, ParentRedId;
20668 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
20669 DeclareReductionRef.get()->Profile(RedId, Context,
20670 /*Canonical=*/true);
20671 EmitError = RedId != ParentRedId;
20672 }
20673 if (EmitError) {
20674 S.Diag(ReductionId.getBeginLoc(),
20675 diag::err_omp_reduction_identifier_mismatch)
20676 << ReductionIdRange << RefExpr->getSourceRange();
20677 S.Diag(ParentSR.getBegin(),
20678 diag::note_omp_previous_reduction_identifier)
20679 << ParentSR
20680 << (IsParentBOK ? ParentBOKDSA.RefExpr
20681 : ParentReductionOpDSA.RefExpr)
20682 ->getSourceRange();
20683 continue;
20684 }
20685 }
20686 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20687 }
20688
20689 DeclRefExpr *Ref = nullptr;
20690 Expr *VarsExpr = RefExpr->IgnoreParens();
20691 if (!VD && !S.CurContext->isDependentContext()) {
20692 if (ASE || OASE) {
20693 TransformExprToCaptures RebuildToCapture(S, D);
20694 VarsExpr =
20695 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20696 Ref = RebuildToCapture.getCapturedExpr();
20697 } else {
20698 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
20699 }
20700 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
20701 RD.ExprCaptures.emplace_back(Ref->getDecl());
20702 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20703 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
20704 if (!RefRes.isUsable())
20705 continue;
20706 ExprResult PostUpdateRes =
20707 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20708 RefRes.get());
20709 if (!PostUpdateRes.isUsable())
20710 continue;
20711 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
20712 Stack->getCurrentDirective() == OMPD_taskgroup) {
20713 S.Diag(RefExpr->getExprLoc(),
20714 diag::err_omp_reduction_non_addressable_expression)
20715 << RefExpr->getSourceRange();
20716 continue;
20717 }
20718 RD.ExprPostUpdates.emplace_back(
20719 S.IgnoredValueConversions(PostUpdateRes.get()).get());
20720 }
20721 }
20722 }
20723 // All reduction items are still marked as reduction (to do not increase
20724 // code base size).
20725 unsigned Modifier = RD.RedModifier;
20726 // Consider task_reductions as reductions with task modifier. Required for
20727 // correct analysis of in_reduction clauses.
20728 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20729 Modifier = OMPC_REDUCTION_task;
20730 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20731 ASE || OASE);
20732 if (Modifier == OMPC_REDUCTION_task &&
20733 (CurrDir == OMPD_taskgroup ||
20734 ((isOpenMPParallelDirective(CurrDir) ||
20735 isOpenMPWorksharingDirective(CurrDir)) &&
20736 !isOpenMPSimdDirective(CurrDir)))) {
20737 if (DeclareReductionRef.isUsable())
20738 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20739 DeclareReductionRef.get());
20740 else
20741 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20742 }
20743 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
20744 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
20745 TempArrayElem.get(), IsPrivate);
20746 }
20747 return RD.Vars.empty();
20748}
20749
20751 ArrayRef<Expr *> VarList,
20753 SourceLocation StartLoc, SourceLocation LParenLoc,
20754 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
20755 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20756 ArrayRef<Expr *> UnresolvedReductions) {
20758 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
20759 OpenMPOriginalSharingModifier OriginalSharingModifier =
20760 static_cast<OpenMPOriginalSharingModifier>(
20761 Modifiers.OriginalSharingModifier);
20762 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
20763 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20764 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
20765 /*Last=*/OMPC_REDUCTION_unknown)
20766 << getOpenMPClauseNameForDiag(OMPC_reduction);
20767 return nullptr;
20768 }
20769 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20770 // A reduction clause with the inscan reduction-modifier may only appear on a
20771 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20772 // construct, a parallel worksharing-loop construct or a parallel
20773 // worksharing-loop SIMD construct.
20774 if (Modifier == OMPC_REDUCTION_inscan &&
20775 (DSAStack->getCurrentDirective() != OMPD_for &&
20776 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20777 DSAStack->getCurrentDirective() != OMPD_simd &&
20778 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20779 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20780 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20781 return nullptr;
20782 }
20783 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
20784 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
20785 StartLoc, LParenLoc, ColonLoc, EndLoc,
20786 ReductionIdScopeSpec, ReductionId,
20787 UnresolvedReductions, RD))
20788 return nullptr;
20789
20791 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
20792 Modifier, RD.Vars,
20793 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20794 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20795 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20796 buildPreInits(getASTContext(), RD.ExprCaptures),
20797 buildPostUpdate(SemaRef, RD.ExprPostUpdates), RD.IsPrivateVarReduction,
20798 OriginalSharingModifier);
20799}
20800
20802 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20803 SourceLocation ColonLoc, SourceLocation EndLoc,
20804 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20805 ArrayRef<Expr *> UnresolvedReductions) {
20806 ReductionData RD(VarList.size());
20807 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
20808 VarList, StartLoc, LParenLoc, ColonLoc,
20809 EndLoc, ReductionIdScopeSpec, ReductionId,
20810 UnresolvedReductions, RD))
20811 return nullptr;
20812
20814 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20815 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20816 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20817 buildPreInits(getASTContext(), RD.ExprCaptures),
20818 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20819}
20820
20822 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20823 SourceLocation ColonLoc, SourceLocation EndLoc,
20824 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20825 ArrayRef<Expr *> UnresolvedReductions) {
20826 ReductionData RD(VarList.size());
20827 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
20828 StartLoc, LParenLoc, ColonLoc, EndLoc,
20829 ReductionIdScopeSpec, ReductionId,
20830 UnresolvedReductions, RD))
20831 return nullptr;
20832
20834 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20835 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20836 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20837 buildPreInits(getASTContext(), RD.ExprCaptures),
20838 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20839}
20840
20842 SourceLocation LinLoc) {
20843 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
20844 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
20845 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
20846 << getLangOpts().CPlusPlus;
20847 return true;
20848 }
20849 return false;
20850}
20851
20853 OpenMPLinearClauseKind LinKind,
20854 QualType Type, bool IsDeclareSimd) {
20855 const auto *VD = dyn_cast_or_null<VarDecl>(D);
20856 // A variable must not have an incomplete type or a reference type.
20857 if (SemaRef.RequireCompleteType(ELoc, Type,
20858 diag::err_omp_linear_incomplete_type))
20859 return true;
20860 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20861 !Type->isReferenceType()) {
20862 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20863 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
20864 return true;
20865 }
20866 Type = Type.getNonReferenceType();
20867
20868 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20869 // A variable that is privatized must not have a const-qualified type
20870 // unless it is of class type with a mutable member. This restriction does
20871 // not apply to the firstprivate clause, nor to the linear clause on
20872 // declarative directives (like declare simd).
20873 if (!IsDeclareSimd &&
20874 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
20875 return true;
20876
20877 // A list item must be of integral or pointer type.
20878 Type = Type.getUnqualifiedType().getCanonicalType();
20879 const auto *Ty = Type.getTypePtrOrNull();
20880 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20881 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
20882 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
20883 if (D) {
20884 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20886 Diag(D->getLocation(),
20887 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20888 << D;
20889 }
20890 return true;
20891 }
20892 return false;
20893}
20894
20896 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
20897 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
20898 SourceLocation LinLoc, SourceLocation ColonLoc,
20899 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
20901 SmallVector<Expr *, 8> Privates;
20903 SmallVector<Decl *, 4> ExprCaptures;
20904 SmallVector<Expr *, 4> ExprPostUpdates;
20905 // OpenMP 5.2 [Section 5.4.6, linear clause]
20906 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
20907 // 'ref'
20908 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
20909 getLangOpts().OpenMP >= 52)
20910 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
20911 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
20912 LinKind = OMPC_LINEAR_val;
20913 for (Expr *RefExpr : VarList) {
20914 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20915 SourceLocation ELoc;
20916 SourceRange ERange;
20917 Expr *SimpleRefExpr = RefExpr;
20918 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20919 if (Res.second) {
20920 // It will be analyzed later.
20921 Vars.push_back(RefExpr);
20922 Privates.push_back(nullptr);
20923 Inits.push_back(nullptr);
20924 }
20925 ValueDecl *D = Res.first;
20926 if (!D)
20927 continue;
20928
20929 QualType Type = D->getType();
20930 auto *VD = dyn_cast<VarDecl>(D);
20931
20932 // OpenMP [2.14.3.7, linear clause]
20933 // A list-item cannot appear in more than one linear clause.
20934 // A list-item that appears in a linear clause cannot appear in any
20935 // other data-sharing attribute clause.
20936 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20937 if (DVar.RefExpr) {
20938 Diag(ELoc, diag::err_omp_wrong_dsa)
20939 << getOpenMPClauseNameForDiag(DVar.CKind)
20940 << getOpenMPClauseNameForDiag(OMPC_linear);
20942 continue;
20943 }
20944
20945 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
20946 continue;
20947 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20948
20949 // Build private copy of original var.
20950 VarDecl *Private =
20951 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
20952 D->hasAttrs() ? &D->getAttrs() : nullptr,
20953 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20954 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
20955 // Build var to save initial value.
20956 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
20957 Expr *InitExpr;
20958 DeclRefExpr *Ref = nullptr;
20959 if (!VD && !SemaRef.CurContext->isDependentContext()) {
20960 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
20961 if (!isOpenMPCapturedDecl(D)) {
20962 ExprCaptures.push_back(Ref->getDecl());
20963 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20964 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
20965 if (!RefRes.isUsable())
20966 continue;
20967 ExprResult PostUpdateRes =
20968 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
20969 SimpleRefExpr, RefRes.get());
20970 if (!PostUpdateRes.isUsable())
20971 continue;
20972 ExprPostUpdates.push_back(
20973 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
20974 }
20975 }
20976 }
20977 if (LinKind == OMPC_LINEAR_uval)
20978 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
20979 else
20980 InitExpr = VD ? SimpleRefExpr : Ref;
20981 SemaRef.AddInitializerToDecl(
20982 Init, SemaRef.DefaultLvalueConversion(InitExpr).get(),
20983 /*DirectInit=*/false);
20984 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
20985
20986 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20987 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
20988 ? RefExpr->IgnoreParens()
20989 : Ref);
20990 Privates.push_back(PrivateRef);
20991 Inits.push_back(InitRef);
20992 }
20993
20994 if (Vars.empty())
20995 return nullptr;
20996
20997 Expr *StepExpr = Step;
20998 Expr *CalcStepExpr = nullptr;
20999 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
21000 !Step->isInstantiationDependent() &&
21002 SourceLocation StepLoc = Step->getBeginLoc();
21004 if (Val.isInvalid())
21005 return nullptr;
21006 StepExpr = Val.get();
21007
21008 // Build var to save the step value.
21009 VarDecl *SaveVar =
21010 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
21011 ExprResult SaveRef =
21012 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
21013 ExprResult CalcStep = SemaRef.BuildBinOp(
21014 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
21015 CalcStep =
21016 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
21017
21018 // Warn about zero linear step (it would be probably better specified as
21019 // making corresponding variables 'const').
21020 if (std::optional<llvm::APSInt> Result =
21022 if (!Result->isNegative() && !Result->isStrictlyPositive())
21023 Diag(StepLoc, diag::warn_omp_linear_step_zero)
21024 << Vars[0] << (Vars.size() > 1);
21025 } else if (CalcStep.isUsable()) {
21026 // Calculate the step beforehand instead of doing this on each iteration.
21027 // (This is not used if the number of iterations may be kfold-ed).
21028 CalcStepExpr = CalcStep.get();
21029 }
21030 }
21031
21032 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
21033 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
21034 Vars, Privates, Inits, StepExpr, CalcStepExpr,
21035 buildPreInits(getASTContext(), ExprCaptures),
21036 buildPostUpdate(SemaRef, ExprPostUpdates));
21037}
21038
21040 Expr *NumIterations, Sema &SemaRef,
21041 Scope *S, DSAStackTy *Stack) {
21042 // Walk the vars and build update/final expressions for the CodeGen.
21043 SmallVector<Expr *, 8> Updates;
21045 SmallVector<Expr *, 8> UsedExprs;
21046 Expr *Step = Clause.getStep();
21047 Expr *CalcStep = Clause.getCalcStep();
21048 // OpenMP [2.14.3.7, linear clause]
21049 // If linear-step is not specified it is assumed to be 1.
21050 if (!Step)
21051 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
21052 else if (CalcStep)
21053 Step = cast<BinaryOperator>(CalcStep)->getLHS();
21054 bool HasErrors = false;
21055 auto CurInit = Clause.inits().begin();
21056 auto CurPrivate = Clause.privates().begin();
21057 OpenMPLinearClauseKind LinKind = Clause.getModifier();
21058 for (Expr *RefExpr : Clause.varlist()) {
21059 SourceLocation ELoc;
21060 SourceRange ERange;
21061 Expr *SimpleRefExpr = RefExpr;
21062 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21063 ValueDecl *D = Res.first;
21064 if (Res.second || !D) {
21065 Updates.push_back(nullptr);
21066 Finals.push_back(nullptr);
21067 HasErrors = true;
21068 continue;
21069 }
21070 auto &&Info = Stack->isLoopControlVariable(D);
21071 // OpenMP [2.15.11, distribute simd Construct]
21072 // A list item may not appear in a linear clause, unless it is the loop
21073 // iteration variable.
21074 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
21075 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
21076 SemaRef.Diag(ELoc,
21077 diag::err_omp_linear_distribute_var_non_loop_iteration);
21078 Updates.push_back(nullptr);
21079 Finals.push_back(nullptr);
21080 HasErrors = true;
21081 continue;
21082 }
21083 Expr *InitExpr = *CurInit;
21084
21085 // Build privatized reference to the current linear var.
21086 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
21087 Expr *CapturedRef;
21088 if (LinKind == OMPC_LINEAR_uval)
21089 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
21090 else
21091 CapturedRef =
21092 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
21093 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
21094 /*RefersToCapture=*/true);
21095
21096 // Build update: Var = InitExpr + IV * Step
21098 if (!Info.first)
21100 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
21101 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
21102 else
21103 Update = *CurPrivate;
21104 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
21105 /*DiscardedValue=*/false);
21106
21107 // Build final: Var = PrivCopy;
21108 ExprResult Final;
21109 if (!Info.first)
21110 Final = SemaRef.BuildBinOp(
21111 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
21112 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
21113 else
21114 Final = *CurPrivate;
21115 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
21116 /*DiscardedValue=*/false);
21117
21118 if (!Update.isUsable() || !Final.isUsable()) {
21119 Updates.push_back(nullptr);
21120 Finals.push_back(nullptr);
21121 UsedExprs.push_back(nullptr);
21122 HasErrors = true;
21123 } else {
21124 Updates.push_back(Update.get());
21125 Finals.push_back(Final.get());
21126 if (!Info.first)
21127 UsedExprs.push_back(SimpleRefExpr);
21128 }
21129 ++CurInit;
21130 ++CurPrivate;
21131 }
21132 if (Expr *S = Clause.getStep())
21133 UsedExprs.push_back(S);
21134 // Fill the remaining part with the nullptr.
21135 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
21136 Clause.setUpdates(Updates);
21137 Clause.setFinals(Finals);
21138 Clause.setUsedExprs(UsedExprs);
21139 return HasErrors;
21140}
21141
21143 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
21144 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
21146 for (Expr *RefExpr : VarList) {
21147 assert(RefExpr && "NULL expr in OpenMP aligned clause.");
21148 SourceLocation ELoc;
21149 SourceRange ERange;
21150 Expr *SimpleRefExpr = RefExpr;
21151 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21152 if (Res.second) {
21153 // It will be analyzed later.
21154 Vars.push_back(RefExpr);
21155 }
21156 ValueDecl *D = Res.first;
21157 if (!D)
21158 continue;
21159
21160 QualType QType = D->getType();
21161 auto *VD = dyn_cast<VarDecl>(D);
21162
21163 // OpenMP [2.8.1, simd construct, Restrictions]
21164 // The type of list items appearing in the aligned clause must be
21165 // array, pointer, reference to array, or reference to pointer.
21167 const Type *Ty = QType.getTypePtrOrNull();
21168 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
21169 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
21170 << QType << getLangOpts().CPlusPlus << ERange;
21171 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21173 Diag(D->getLocation(),
21174 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21175 << D;
21176 continue;
21177 }
21178
21179 // OpenMP [2.8.1, simd construct, Restrictions]
21180 // A list-item cannot appear in more than one aligned clause.
21181 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
21182 Diag(ELoc, diag::err_omp_used_in_clause_twice)
21183 << 0 << getOpenMPClauseNameForDiag(OMPC_aligned) << ERange;
21184 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
21185 << getOpenMPClauseNameForDiag(OMPC_aligned);
21186 continue;
21187 }
21188
21189 DeclRefExpr *Ref = nullptr;
21190 if (!VD && isOpenMPCapturedDecl(D))
21191 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
21192 Vars.push_back(SemaRef
21193 .DefaultFunctionArrayConversion(
21194 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
21195 .get());
21196 }
21197
21198 // OpenMP [2.8.1, simd construct, Description]
21199 // The parameter of the aligned clause, alignment, must be a constant
21200 // positive integer expression.
21201 // If no optional parameter is specified, implementation-defined default
21202 // alignments for SIMD instructions on the target platforms are assumed.
21203 if (Alignment != nullptr) {
21204 ExprResult AlignResult =
21205 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
21206 if (AlignResult.isInvalid())
21207 return nullptr;
21208 Alignment = AlignResult.get();
21209 }
21210 if (Vars.empty())
21211 return nullptr;
21212
21213 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
21214 ColonLoc, EndLoc, Vars, Alignment);
21215}
21216
21218 SourceLocation StartLoc,
21219 SourceLocation LParenLoc,
21220 SourceLocation EndLoc) {
21222 SmallVector<Expr *, 8> SrcExprs;
21223 SmallVector<Expr *, 8> DstExprs;
21224 SmallVector<Expr *, 8> AssignmentOps;
21225 for (Expr *RefExpr : VarList) {
21226 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
21227 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21228 // It will be analyzed later.
21229 Vars.push_back(RefExpr);
21230 SrcExprs.push_back(nullptr);
21231 DstExprs.push_back(nullptr);
21232 AssignmentOps.push_back(nullptr);
21233 continue;
21234 }
21235
21236 SourceLocation ELoc = RefExpr->getExprLoc();
21237 // OpenMP [2.1, C/C++]
21238 // A list item is a variable name.
21239 // OpenMP [2.14.4.1, Restrictions, p.1]
21240 // A list item that appears in a copyin clause must be threadprivate.
21241 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
21242 if (!DE || !isa<VarDecl>(DE->getDecl())) {
21243 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
21244 << 0 << RefExpr->getSourceRange();
21245 continue;
21246 }
21247
21248 Decl *D = DE->getDecl();
21249 auto *VD = cast<VarDecl>(D);
21250
21251 QualType Type = VD->getType();
21253 // It will be analyzed later.
21254 Vars.push_back(DE);
21255 SrcExprs.push_back(nullptr);
21256 DstExprs.push_back(nullptr);
21257 AssignmentOps.push_back(nullptr);
21258 continue;
21259 }
21260
21261 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
21262 // A list item that appears in a copyin clause must be threadprivate.
21263 if (!DSAStack->isThreadPrivate(VD)) {
21264 unsigned OMPVersion = getLangOpts().OpenMP;
21265 Diag(ELoc, diag::err_omp_required_access)
21266 << getOpenMPClauseNameForDiag(OMPC_copyin)
21267 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
21268 continue;
21269 }
21270
21271 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21272 // A variable of class type (or array thereof) that appears in a
21273 // copyin clause requires an accessible, unambiguous copy assignment
21274 // operator for the class type.
21275 QualType ElemType =
21277 VarDecl *SrcVD =
21278 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
21279 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21280 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
21281 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
21282 VarDecl *DstVD =
21283 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
21284 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21285 DeclRefExpr *PseudoDstExpr =
21286 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
21287 // For arrays generate assignment operation for single element and replace
21288 // it by the original array element in CodeGen.
21289 ExprResult AssignmentOp =
21290 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
21291 PseudoDstExpr, PseudoSrcExpr);
21292 if (AssignmentOp.isInvalid())
21293 continue;
21294 AssignmentOp =
21295 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
21296 /*DiscardedValue=*/false);
21297 if (AssignmentOp.isInvalid())
21298 continue;
21299
21300 DSAStack->addDSA(VD, DE, OMPC_copyin);
21301 Vars.push_back(DE);
21302 SrcExprs.push_back(PseudoSrcExpr);
21303 DstExprs.push_back(PseudoDstExpr);
21304 AssignmentOps.push_back(AssignmentOp.get());
21305 }
21306
21307 if (Vars.empty())
21308 return nullptr;
21309
21310 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21311 Vars, SrcExprs, DstExprs, AssignmentOps);
21312}
21313
21315 SourceLocation StartLoc,
21316 SourceLocation LParenLoc,
21317 SourceLocation EndLoc) {
21319 SmallVector<Expr *, 8> SrcExprs;
21320 SmallVector<Expr *, 8> DstExprs;
21321 SmallVector<Expr *, 8> AssignmentOps;
21322 for (Expr *RefExpr : VarList) {
21323 assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
21324 SourceLocation ELoc;
21325 SourceRange ERange;
21326 Expr *SimpleRefExpr = RefExpr;
21327 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21328 if (Res.second) {
21329 // It will be analyzed later.
21330 Vars.push_back(RefExpr);
21331 SrcExprs.push_back(nullptr);
21332 DstExprs.push_back(nullptr);
21333 AssignmentOps.push_back(nullptr);
21334 }
21335 ValueDecl *D = Res.first;
21336 if (!D)
21337 continue;
21338
21339 QualType Type = D->getType();
21340 auto *VD = dyn_cast<VarDecl>(D);
21341
21342 // OpenMP [2.14.4.2, Restrictions, p.2]
21343 // A list item that appears in a copyprivate clause may not appear in a
21344 // private or firstprivate clause on the single construct.
21345 if (!VD || !DSAStack->isThreadPrivate(VD)) {
21346 DSAStackTy::DSAVarData DVar =
21347 DSAStack->getTopDSA(D, /*FromParent=*/false);
21348 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
21349 DVar.RefExpr) {
21350 Diag(ELoc, diag::err_omp_wrong_dsa)
21351 << getOpenMPClauseNameForDiag(DVar.CKind)
21352 << getOpenMPClauseNameForDiag(OMPC_copyprivate);
21354 continue;
21355 }
21356
21357 // OpenMP [2.11.4.2, Restrictions, p.1]
21358 // All list items that appear in a copyprivate clause must be either
21359 // threadprivate or private in the enclosing context.
21360 if (DVar.CKind == OMPC_unknown) {
21361 DVar = DSAStack->getImplicitDSA(D, false);
21362 if (DVar.CKind == OMPC_shared) {
21363 Diag(ELoc, diag::err_omp_required_access)
21364 << getOpenMPClauseNameForDiag(OMPC_copyprivate)
21365 << "threadprivate or private in the enclosing context";
21367 continue;
21368 }
21369 }
21370 }
21371
21372 // Variably modified types are not supported.
21374 unsigned OMPVersion = getLangOpts().OpenMP;
21375 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21376 << getOpenMPClauseNameForDiag(OMPC_copyprivate) << Type
21377 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
21378 OMPVersion);
21379 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21381 Diag(D->getLocation(),
21382 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21383 << D;
21384 continue;
21385 }
21386
21387 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21388 // A variable of class type (or array thereof) that appears in a
21389 // copyin clause requires an accessible, unambiguous copy assignment
21390 // operator for the class type.
21392 .getBaseElementType(Type.getNonReferenceType())
21394 VarDecl *SrcVD =
21395 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
21396 D->hasAttrs() ? &D->getAttrs() : nullptr);
21397 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
21398 VarDecl *DstVD =
21399 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
21400 D->hasAttrs() ? &D->getAttrs() : nullptr);
21401 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
21402 ExprResult AssignmentOp = SemaRef.BuildBinOp(
21403 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
21404 if (AssignmentOp.isInvalid())
21405 continue;
21406 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
21407 /*DiscardedValue=*/false);
21408 if (AssignmentOp.isInvalid())
21409 continue;
21410
21411 // No need to mark vars as copyprivate, they are already threadprivate or
21412 // implicitly private.
21413 assert(VD || isOpenMPCapturedDecl(D));
21414 Vars.push_back(
21415 VD ? RefExpr->IgnoreParens()
21416 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
21417 SrcExprs.push_back(PseudoSrcExpr);
21418 DstExprs.push_back(PseudoDstExpr);
21419 AssignmentOps.push_back(AssignmentOp.get());
21420 }
21421
21422 if (Vars.empty())
21423 return nullptr;
21424
21425 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
21426 EndLoc, Vars, SrcExprs, DstExprs,
21427 AssignmentOps);
21428}
21429
21431 SourceLocation StartLoc,
21432 SourceLocation LParenLoc,
21433 SourceLocation EndLoc) {
21434 if (VarList.empty())
21435 return nullptr;
21436
21437 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21438 VarList);
21439}
21440
21441/// Tries to find omp_depend_t. type.
21442static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
21443 bool Diagnose = true) {
21444 QualType OMPDependT = Stack->getOMPDependT();
21445 if (!OMPDependT.isNull())
21446 return true;
21447 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
21448 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
21449 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
21450 if (Diagnose)
21451 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
21452 return false;
21453 }
21454 Stack->setOMPDependT(PT.get());
21455 return true;
21456}
21457
21459 SourceLocation StartLoc,
21460 SourceLocation LParenLoc,
21461 SourceLocation EndLoc) {
21462 if (!Depobj)
21463 return nullptr;
21464
21465 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
21466
21467 // OpenMP 5.0, 2.17.10.1 depobj Construct
21468 // depobj is an lvalue expression of type omp_depend_t.
21469 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
21470 !Depobj->isInstantiationDependent() &&
21472 (OMPDependTFound && !getASTContext().typesAreCompatible(
21473 DSAStack->getOMPDependT(), Depobj->getType(),
21474 /*CompareUnqualified=*/true))) {
21475 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21476 << 0 << Depobj->getType() << Depobj->getSourceRange();
21477 }
21478
21479 if (!Depobj->isLValue()) {
21480 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21481 << 1 << Depobj->getSourceRange();
21482 }
21483
21484 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21485 Depobj);
21486}
21487
21488namespace {
21489// Utility struct that gathers the related info for doacross clause.
21490struct DoacrossDataInfoTy {
21491 // The list of expressions.
21493 // The OperatorOffset for doacross loop.
21494 DSAStackTy::OperatorOffsetTy OpsOffs;
21495 // The depended loop count.
21496 llvm::APSInt TotalDepCount;
21497};
21498} // namespace
21499static DoacrossDataInfoTy
21501 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
21502 SourceLocation EndLoc) {
21503
21505 DSAStackTy::OperatorOffsetTy OpsOffs;
21506 llvm::APSInt DepCounter(/*BitWidth=*/32);
21507 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21508
21509 if (const Expr *OrderedCountExpr =
21510 Stack->getParentOrderedRegionParam().first) {
21511 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
21512 TotalDepCount.setIsUnsigned(/*Val=*/true);
21513 }
21514
21515 for (Expr *RefExpr : VarList) {
21516 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
21517 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21518 // It will be analyzed later.
21519 Vars.push_back(RefExpr);
21520 continue;
21521 }
21522
21523 SourceLocation ELoc = RefExpr->getExprLoc();
21524 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21525 if (!IsSource) {
21526 if (Stack->getParentOrderedRegionParam().first &&
21527 DepCounter >= TotalDepCount) {
21528 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
21529 continue;
21530 }
21531 ++DepCounter;
21532 // OpenMP [2.13.9, Summary]
21533 // depend(dependence-type : vec), where dependence-type is:
21534 // 'sink' and where vec is the iteration vector, which has the form:
21535 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
21536 // where n is the value specified by the ordered clause in the loop
21537 // directive, xi denotes the loop iteration variable of the i-th nested
21538 // loop associated with the loop directive, and di is a constant
21539 // non-negative integer.
21540 if (SemaRef.CurContext->isDependentContext()) {
21541 // It will be analyzed later.
21542 Vars.push_back(RefExpr);
21543 continue;
21544 }
21545 SimpleExpr = SimpleExpr->IgnoreImplicit();
21547 SourceLocation OOLoc;
21548 Expr *LHS = SimpleExpr;
21549 Expr *RHS = nullptr;
21550 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
21551 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
21552 OOLoc = BO->getOperatorLoc();
21553 LHS = BO->getLHS()->IgnoreParenImpCasts();
21554 RHS = BO->getRHS()->IgnoreParenImpCasts();
21555 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
21556 OOK = OCE->getOperator();
21557 OOLoc = OCE->getOperatorLoc();
21558 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21559 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
21560 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
21561 OOK = MCE->getMethodDecl()
21562 ->getNameInfo()
21563 .getName()
21564 .getCXXOverloadedOperator();
21565 OOLoc = MCE->getCallee()->getExprLoc();
21566 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
21567 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21568 }
21569 SourceLocation ELoc;
21570 SourceRange ERange;
21571 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
21572 if (Res.second) {
21573 // It will be analyzed later.
21574 Vars.push_back(RefExpr);
21575 }
21576 ValueDecl *D = Res.first;
21577 if (!D)
21578 continue;
21579
21580 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
21581 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
21582 continue;
21583 }
21584 if (RHS) {
21585 ExprResult RHSRes =
21587 RHS, OMPC_depend, /*StrictlyPositive=*/false);
21588 if (RHSRes.isInvalid())
21589 continue;
21590 }
21591 if (!SemaRef.CurContext->isDependentContext() &&
21592 Stack->getParentOrderedRegionParam().first &&
21593 DepCounter != Stack->isParentLoopControlVariable(D).first) {
21594 const ValueDecl *VD =
21595 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
21596 if (VD)
21597 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21598 << 1 << VD;
21599 else
21600 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21601 << 0;
21602 continue;
21603 }
21604 OpsOffs.emplace_back(RHS, OOK);
21605 }
21606 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21607 }
21608 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
21609 TotalDepCount > VarList.size() &&
21610 Stack->getParentOrderedRegionParam().first &&
21611 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
21612 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
21613 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
21614 }
21615 return {Vars, OpsOffs, TotalDepCount};
21616}
21617
21619 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
21620 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21621 SourceLocation EndLoc) {
21622 OpenMPDependClauseKind DepKind = Data.DepKind;
21623 SourceLocation DepLoc = Data.DepLoc;
21624 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
21625 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
21626 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21627 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_depend);
21628 return nullptr;
21629 }
21630 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
21631 DepKind == OMPC_DEPEND_mutexinoutset) {
21632 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
21633 return nullptr;
21634 }
21635 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
21636 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21637 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
21638 DepKind == OMPC_DEPEND_sink ||
21639 ((getLangOpts().OpenMP < 50 ||
21640 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21641 DepKind == OMPC_DEPEND_depobj))) {
21642 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
21643 OMPC_DEPEND_outallmemory,
21644 OMPC_DEPEND_inoutallmemory};
21645 if (getLangOpts().OpenMP < 50 ||
21646 DSAStack->getCurrentDirective() == OMPD_depobj)
21647 Except.push_back(OMPC_DEPEND_depobj);
21648 if (getLangOpts().OpenMP < 51)
21649 Except.push_back(OMPC_DEPEND_inoutset);
21650 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
21651 ? "depend modifier(iterator) or "
21652 : "";
21653 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21654 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
21655 /*Last=*/OMPC_DEPEND_unknown,
21656 Except)
21657 << getOpenMPClauseNameForDiag(OMPC_depend);
21658 return nullptr;
21659 }
21660 if (DepModifier &&
21661 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21662 Diag(DepModifier->getExprLoc(),
21663 diag::err_omp_depend_sink_source_with_modifier);
21664 return nullptr;
21665 }
21666 if (DepModifier &&
21667 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
21668 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21669
21671 DSAStackTy::OperatorOffsetTy OpsOffs;
21672 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21673
21674 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21675 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
21676 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
21677 Vars = VarOffset.Vars;
21678 OpsOffs = VarOffset.OpsOffs;
21679 TotalDepCount = VarOffset.TotalDepCount;
21680 } else {
21681 for (Expr *RefExpr : VarList) {
21682 assert(RefExpr && "NULL expr in OpenMP depend clause.");
21683 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21684 // It will be analyzed later.
21685 Vars.push_back(RefExpr);
21686 continue;
21687 }
21688
21689 SourceLocation ELoc = RefExpr->getExprLoc();
21690 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21691 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21692 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
21693 if (OMPDependTFound)
21694 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
21695 DepKind == OMPC_DEPEND_depobj);
21696 if (DepKind == OMPC_DEPEND_depobj) {
21697 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21698 // List items used in depend clauses with the depobj dependence type
21699 // must be expressions of the omp_depend_t type.
21700 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21701 !RefExpr->isInstantiationDependent() &&
21702 !RefExpr->containsUnexpandedParameterPack() &&
21703 (OMPDependTFound &&
21704 !getASTContext().hasSameUnqualifiedType(
21705 DSAStack->getOMPDependT(), RefExpr->getType()))) {
21706 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21707 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21708 continue;
21709 }
21710 if (!RefExpr->isLValue()) {
21711 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21712 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21713 continue;
21714 }
21715 } else {
21716 // OpenMP 5.0 [2.17.11, Restrictions]
21717 // List items used in depend clauses cannot be zero-length array
21718 // sections.
21719 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21720 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
21721 if (OASE) {
21722 QualType BaseType =
21724 if (BaseType.isNull())
21725 return nullptr;
21726 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21727 ExprTy = ATy->getElementType();
21728 else
21729 ExprTy = BaseType->getPointeeType();
21730 if (BaseType.isNull() || ExprTy.isNull())
21731 return nullptr;
21732 ExprTy = ExprTy.getNonReferenceType();
21733 const Expr *Length = OASE->getLength();
21735 if (Length && !Length->isValueDependent() &&
21736 Length->EvaluateAsInt(Result, getASTContext()) &&
21737 Result.Val.getInt().isZero()) {
21738 Diag(ELoc,
21739 diag::err_omp_depend_zero_length_array_section_not_allowed)
21740 << SimpleExpr->getSourceRange();
21741 continue;
21742 }
21743 }
21744
21745 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21746 // List items used in depend clauses with the in, out, inout,
21747 // inoutset, or mutexinoutset dependence types cannot be
21748 // expressions of the omp_depend_t type.
21749 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21750 !RefExpr->isInstantiationDependent() &&
21751 !RefExpr->containsUnexpandedParameterPack() &&
21752 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21753 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
21754 ExprTy.getTypePtr()))) {
21755 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21756 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21757 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21758 << RefExpr->getSourceRange();
21759 continue;
21760 }
21761
21762 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
21763 if (ASE && !ASE->getBase()->isTypeDependent() &&
21764 !ASE->getBase()
21765 ->getType()
21766 .getNonReferenceType()
21767 ->isPointerType() &&
21768 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21769 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21770 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21771 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21772 << RefExpr->getSourceRange();
21773 continue;
21774 }
21775
21776 ExprResult Res;
21777 {
21779 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21780 RefExpr->IgnoreParenImpCasts());
21781 }
21782 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
21784 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21785 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21786 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21787 << RefExpr->getSourceRange();
21788 continue;
21789 }
21790 }
21791 }
21792 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21793 }
21794 }
21795
21796 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21797 DepKind != OMPC_DEPEND_outallmemory &&
21798 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21799 return nullptr;
21800
21801 auto *C = OMPDependClause::Create(
21802 getASTContext(), StartLoc, LParenLoc, EndLoc,
21803 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
21804 TotalDepCount.getZExtValue());
21805 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21806 DSAStack->isParentOrderedRegion())
21807 DSAStack->addDoacrossDependClause(C, OpsOffs);
21808 return C;
21809}
21810
21813 SourceLocation LParenLoc, SourceLocation ModifierLoc,
21814 SourceLocation EndLoc) {
21815 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
21816 "Unexpected device modifier in OpenMP < 50.");
21817
21818 bool ErrorFound = false;
21819 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
21820 std::string Values =
21821 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
21822 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21823 << Values << getOpenMPClauseNameForDiag(OMPC_device);
21824 ErrorFound = true;
21825 }
21826
21827 Expr *ValExpr = Device;
21828 Stmt *HelperValStmt = nullptr;
21829
21830 // OpenMP [2.9.1, Restrictions]
21831 // The device expression must evaluate to a non-negative integer value.
21832 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
21833 /*StrictlyPositive=*/false) ||
21834 ErrorFound;
21835 if (ErrorFound)
21836 return nullptr;
21837
21838 // OpenMP 5.0 [2.12.5, Restrictions]
21839 // In case of ancestor device-modifier, a requires directive with
21840 // the reverse_offload clause must be specified.
21841 if (Modifier == OMPC_DEVICE_ancestor) {
21842 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
21843 SemaRef.targetDiag(
21844 StartLoc,
21845 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21846 ErrorFound = true;
21847 }
21848 }
21849
21850 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21851 OpenMPDirectiveKind CaptureRegion =
21852 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
21853 if (CaptureRegion != OMPD_unknown &&
21854 !SemaRef.CurContext->isDependentContext()) {
21855 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21856 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21857 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21858 HelperValStmt = buildPreInits(getASTContext(), Captures);
21859 }
21860
21861 return new (getASTContext())
21862 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21863 LParenLoc, ModifierLoc, EndLoc);
21864}
21865
21867 DSAStackTy *Stack, QualType QTy,
21868 bool FullCheck = true) {
21869 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
21870 return false;
21871 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
21872 !QTy.isTriviallyCopyableType(SemaRef.Context))
21873 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21874 return true;
21875}
21876
21877/// Return true if it can be proven that the provided array expression
21878/// (array section or array subscript) does NOT specify the whole size of the
21879/// array whose base type is \a BaseQTy.
21881 const Expr *E,
21882 QualType BaseQTy) {
21883 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21884
21885 // If this is an array subscript, it refers to the whole size if the size of
21886 // the dimension is constant and equals 1. Also, an array section assumes the
21887 // format of an array subscript if no colon is used.
21888 if (isa<ArraySubscriptExpr>(E) ||
21889 (OASE && OASE->getColonLocFirst().isInvalid())) {
21890 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21891 return ATy->getSExtSize() != 1;
21892 // Size can't be evaluated statically.
21893 return false;
21894 }
21895
21896 assert(OASE && "Expecting array section if not an array subscript.");
21897 const Expr *LowerBound = OASE->getLowerBound();
21898 const Expr *Length = OASE->getLength();
21899
21900 // If there is a lower bound that does not evaluates to zero, we are not
21901 // covering the whole dimension.
21902 if (LowerBound) {
21903 Expr::EvalResult Result;
21904 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
21905 return false; // Can't get the integer value as a constant.
21906
21907 llvm::APSInt ConstLowerBound = Result.Val.getInt();
21908 if (ConstLowerBound.getSExtValue())
21909 return true;
21910 }
21911
21912 // If we don't have a length we covering the whole dimension.
21913 if (!Length)
21914 return false;
21915
21916 // If the base is a pointer, we don't have a way to get the size of the
21917 // pointee.
21918 if (BaseQTy->isPointerType())
21919 return false;
21920
21921 // We can only check if the length is the same as the size of the dimension
21922 // if we have a constant array.
21923 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
21924 if (!CATy)
21925 return false;
21926
21927 Expr::EvalResult Result;
21928 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21929 return false; // Can't get the integer value as a constant.
21930
21931 llvm::APSInt ConstLength = Result.Val.getInt();
21932 return CATy->getSExtSize() != ConstLength.getSExtValue();
21933}
21934
21935// Return true if it can be proven that the provided array expression (array
21936// section or array subscript) does NOT specify a single element of the array
21937// whose base type is \a BaseQTy.
21939 const Expr *E,
21940 QualType BaseQTy) {
21941 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21942
21943 // An array subscript always refer to a single element. Also, an array section
21944 // assumes the format of an array subscript if no colon is used.
21945 if (isa<ArraySubscriptExpr>(E) ||
21946 (OASE && OASE->getColonLocFirst().isInvalid()))
21947 return false;
21948
21949 assert(OASE && "Expecting array section if not an array subscript.");
21950 const Expr *Length = OASE->getLength();
21951
21952 // If we don't have a length we have to check if the array has unitary size
21953 // for this dimension. Also, we should always expect a length if the base type
21954 // is pointer.
21955 if (!Length) {
21956 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21957 return ATy->getSExtSize() != 1;
21958 // We cannot assume anything.
21959 return false;
21960 }
21961
21962 // Check if the length evaluates to 1.
21963 Expr::EvalResult Result;
21964 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21965 return false; // Can't get the integer value as a constant.
21966
21967 llvm::APSInt ConstLength = Result.Val.getInt();
21968 return ConstLength.getSExtValue() != 1;
21969}
21970
21971// The base of elements of list in a map clause have to be either:
21972// - a reference to variable or field.
21973// - a member expression.
21974// - an array expression.
21975//
21976// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
21977// reference to 'r'.
21978//
21979// If we have:
21980//
21981// struct SS {
21982// Bla S;
21983// foo() {
21984// #pragma omp target map (S.Arr[:12]);
21985// }
21986// }
21987//
21988// We want to retrieve the member expression 'this->S';
21989
21990// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
21991// If a list item is an array section, it must specify contiguous storage.
21992//
21993// For this restriction it is sufficient that we make sure only references
21994// to variables or fields and array expressions, and that no array sections
21995// exist except in the rightmost expression (unless they cover the whole
21996// dimension of the array). E.g. these would be invalid:
21997//
21998// r.ArrS[3:5].Arr[6:7]
21999//
22000// r.ArrS[3:5].x
22001//
22002// but these would be valid:
22003// r.ArrS[3].Arr[6:7]
22004//
22005// r.ArrS[3].x
22006namespace {
22007class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
22008 Sema &SemaRef;
22009 OpenMPClauseKind CKind = OMPC_unknown;
22010 OpenMPDirectiveKind DKind = OMPD_unknown;
22012 bool IsNonContiguous = false;
22013 bool NoDiagnose = false;
22014 const Expr *RelevantExpr = nullptr;
22015 bool AllowUnitySizeArraySection = true;
22016 bool AllowWholeSizeArraySection = true;
22017 bool AllowAnotherPtr = true;
22018 SourceLocation ELoc;
22019 SourceRange ERange;
22020
22021 void emitErrorMsg() {
22022 // If nothing else worked, this is not a valid map clause expression.
22023 if (SemaRef.getLangOpts().OpenMP < 50) {
22024 SemaRef.Diag(ELoc,
22025 diag::err_omp_expected_named_var_member_or_array_expression)
22026 << ERange;
22027 } else {
22028 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22029 << getOpenMPClauseNameForDiag(CKind) << ERange;
22030 }
22031 }
22032
22033public:
22034 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
22035 if (!isa<VarDecl>(DRE->getDecl())) {
22036 emitErrorMsg();
22037 return false;
22038 }
22039 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22040 RelevantExpr = DRE;
22041 // Record the component.
22042 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
22043 return true;
22044 }
22045
22046 bool VisitMemberExpr(MemberExpr *ME) {
22047 Expr *E = ME;
22048 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
22049
22050 if (isa<CXXThisExpr>(BaseE)) {
22051 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22052 // We found a base expression: this->Val.
22053 RelevantExpr = ME;
22054 } else {
22055 E = BaseE;
22056 }
22057
22058 if (!isa<FieldDecl>(ME->getMemberDecl())) {
22059 if (!NoDiagnose) {
22060 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
22061 << ME->getSourceRange();
22062 return false;
22063 }
22064 if (RelevantExpr)
22065 return false;
22066 return Visit(E);
22067 }
22068
22069 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
22070
22071 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
22072 // A bit-field cannot appear in a map clause.
22073 //
22074 if (FD->isBitField()) {
22075 if (!NoDiagnose) {
22076 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
22077 << ME->getSourceRange() << getOpenMPClauseNameForDiag(CKind);
22078 return false;
22079 }
22080 if (RelevantExpr)
22081 return false;
22082 return Visit(E);
22083 }
22084
22085 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22086 // If the type of a list item is a reference to a type T then the type
22087 // will be considered to be T for all purposes of this clause.
22088 QualType CurType = BaseE->getType().getNonReferenceType();
22089
22090 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
22091 // A list item cannot be a variable that is a member of a structure with
22092 // a union type.
22093 //
22094 if (CurType->isUnionType()) {
22095 if (!NoDiagnose) {
22096 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
22097 << ME->getSourceRange();
22098 return false;
22099 }
22100 return RelevantExpr || Visit(E);
22101 }
22102
22103 // If we got a member expression, we should not expect any array section
22104 // before that:
22105 //
22106 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
22107 // If a list item is an element of a structure, only the rightmost symbol
22108 // of the variable reference can be an array section.
22109 //
22110 AllowUnitySizeArraySection = false;
22111 AllowWholeSizeArraySection = false;
22112
22113 // Record the component.
22114 Components.emplace_back(ME, FD, IsNonContiguous);
22115 return RelevantExpr || Visit(E);
22116 }
22117
22118 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
22119 Expr *E = AE->getBase()->IgnoreParenImpCasts();
22120
22121 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
22122 if (!NoDiagnose) {
22123 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22124 << 0 << AE->getSourceRange();
22125 return false;
22126 }
22127 return RelevantExpr || Visit(E);
22128 }
22129
22130 // If we got an array subscript that express the whole dimension we
22131 // can have any array expressions before. If it only expressing part of
22132 // the dimension, we can only have unitary-size array expressions.
22134 AllowWholeSizeArraySection = false;
22135
22136 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
22137 Expr::EvalResult Result;
22138 if (!AE->getIdx()->isValueDependent() &&
22139 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
22140 !Result.Val.getInt().isZero()) {
22141 SemaRef.Diag(AE->getIdx()->getExprLoc(),
22142 diag::err_omp_invalid_map_this_expr);
22143 SemaRef.Diag(AE->getIdx()->getExprLoc(),
22144 diag::note_omp_invalid_subscript_on_this_ptr_map);
22145 }
22146 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22147 RelevantExpr = TE;
22148 }
22149
22150 // Record the component - we don't have any declaration associated.
22151 Components.emplace_back(AE, nullptr, IsNonContiguous);
22152
22153 return RelevantExpr || Visit(E);
22154 }
22155
22156 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
22157 // After OMP 5.0 Array section in reduction clause will be implicitly
22158 // mapped
22159 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
22160 "Array sections cannot be implicitly mapped.");
22161 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22162 QualType CurType =
22164
22165 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22166 // If the type of a list item is a reference to a type T then the type
22167 // will be considered to be T for all purposes of this clause.
22168 if (CurType->isReferenceType())
22169 CurType = CurType->getPointeeType();
22170
22171 bool IsPointer = CurType->isAnyPointerType();
22172
22173 if (!IsPointer && !CurType->isArrayType()) {
22174 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22175 << 0 << OASE->getSourceRange();
22176 return false;
22177 }
22178
22179 bool NotWhole =
22180 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
22181 bool NotUnity =
22182 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
22183
22184 if (AllowWholeSizeArraySection) {
22185 // Any array section is currently allowed. Allowing a whole size array
22186 // section implies allowing a unity array section as well.
22187 //
22188 // If this array section refers to the whole dimension we can still
22189 // accept other array sections before this one, except if the base is a
22190 // pointer. Otherwise, only unitary sections are accepted.
22191 if (NotWhole || IsPointer)
22192 AllowWholeSizeArraySection = false;
22193 } else if (DKind == OMPD_target_update &&
22194 SemaRef.getLangOpts().OpenMP >= 50) {
22195 if (IsPointer && !AllowAnotherPtr)
22196 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
22197 << /*array of unknown bound */ 1;
22198 else
22199 IsNonContiguous = true;
22200 } else if (AllowUnitySizeArraySection && NotUnity) {
22201 // A unity or whole array section is not allowed and that is not
22202 // compatible with the properties of the current array section.
22203 if (NoDiagnose)
22204 return false;
22205 SemaRef.Diag(ELoc,
22206 diag::err_array_section_does_not_specify_contiguous_storage)
22207 << OASE->getSourceRange();
22208 return false;
22209 }
22210
22211 if (IsPointer)
22212 AllowAnotherPtr = false;
22213
22214 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
22215 Expr::EvalResult ResultR;
22216 Expr::EvalResult ResultL;
22217 if (!OASE->getLength()->isValueDependent() &&
22218 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
22219 !ResultR.Val.getInt().isOne()) {
22220 SemaRef.Diag(OASE->getLength()->getExprLoc(),
22221 diag::err_omp_invalid_map_this_expr);
22222 SemaRef.Diag(OASE->getLength()->getExprLoc(),
22223 diag::note_omp_invalid_length_on_this_ptr_mapping);
22224 }
22225 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
22226 OASE->getLowerBound()->EvaluateAsInt(ResultL,
22227 SemaRef.getASTContext()) &&
22228 !ResultL.Val.getInt().isZero()) {
22229 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
22230 diag::err_omp_invalid_map_this_expr);
22231 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
22232 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
22233 }
22234 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22235 RelevantExpr = TE;
22236 }
22237
22238 // Record the component - we don't have any declaration associated.
22239 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
22240 return RelevantExpr || Visit(E);
22241 }
22242 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
22243 Expr *Base = E->getBase();
22244
22245 // Record the component - we don't have any declaration associated.
22246 Components.emplace_back(E, nullptr, IsNonContiguous);
22247
22248 return Visit(Base->IgnoreParenImpCasts());
22249 }
22250
22251 bool VisitUnaryOperator(UnaryOperator *UO) {
22252 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
22253 UO->getOpcode() != UO_Deref) {
22254 emitErrorMsg();
22255 return false;
22256 }
22257 if (!RelevantExpr) {
22258 // Record the component if haven't found base decl.
22259 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
22260 }
22261 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
22262 }
22263 bool VisitBinaryOperator(BinaryOperator *BO) {
22264 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
22265 emitErrorMsg();
22266 return false;
22267 }
22268
22269 // Pointer arithmetic is the only thing we expect to happen here so after we
22270 // make sure the binary operator is a pointer type, the only thing we need
22271 // to do is to visit the subtree that has the same type as root (so that we
22272 // know the other subtree is just an offset)
22273 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
22274 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
22275 Components.emplace_back(BO, nullptr, false);
22276 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
22277 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
22278 "Either LHS or RHS have base decl inside");
22279 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
22280 return RelevantExpr || Visit(LE);
22281 return RelevantExpr || Visit(RE);
22282 }
22283 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
22284 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22285 RelevantExpr = CTE;
22286 Components.emplace_back(CTE, nullptr, IsNonContiguous);
22287 return true;
22288 }
22289 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
22290 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22291 Components.emplace_back(COCE, nullptr, IsNonContiguous);
22292 return true;
22293 }
22294 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
22295 Expr *Source = E->getSourceExpr();
22296 if (!Source) {
22297 emitErrorMsg();
22298 return false;
22299 }
22300 return Visit(Source);
22301 }
22302 bool VisitStmt(Stmt *) {
22303 emitErrorMsg();
22304 return false;
22305 }
22306 const Expr *getFoundBase() const { return RelevantExpr; }
22307 explicit MapBaseChecker(
22308 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
22310 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
22311 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
22312 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
22313};
22314} // namespace
22315
22316/// Return the expression of the base of the mappable expression or null if it
22317/// cannot be determined and do all the necessary checks to see if the
22318/// expression is valid as a standalone mappable expression. In the process,
22319/// record all the components of the expression.
22321 Sema &SemaRef, Expr *E,
22323 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
22324 SourceLocation ELoc = E->getExprLoc();
22325 SourceRange ERange = E->getSourceRange();
22326 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
22327 ERange);
22328 if (Checker.Visit(E->IgnoreParens())) {
22329 // Check if the highest dimension array section has length specified
22330 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
22331 (CKind == OMPC_to || CKind == OMPC_from)) {
22332 auto CI = CurComponents.rbegin();
22333 auto CE = CurComponents.rend();
22334 for (; CI != CE; ++CI) {
22335 const auto *OASE =
22336 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
22337 if (!OASE)
22338 continue;
22339 if (OASE && OASE->getLength())
22340 break;
22341 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
22342 << ERange;
22343 }
22344 }
22345 return Checker.getFoundBase();
22346 }
22347 return nullptr;
22348}
22349
22350// Return true if expression E associated with value VD has conflicts with other
22351// map information.
22353 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
22354 bool CurrentRegionOnly,
22356 OpenMPClauseKind CKind) {
22357 assert(VD && E);
22358 SourceLocation ELoc = E->getExprLoc();
22359 SourceRange ERange = E->getSourceRange();
22360
22361 // In order to easily check the conflicts we need to match each component of
22362 // the expression under test with the components of the expressions that are
22363 // already in the stack.
22364
22365 assert(!CurComponents.empty() && "Map clause expression with no components!");
22366 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
22367 "Map clause expression with unexpected base!");
22368
22369 // Variables to help detecting enclosing problems in data environment nests.
22370 bool IsEnclosedByDataEnvironmentExpr = false;
22371 const Expr *EnclosingExpr = nullptr;
22372
22373 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
22374 VD, CurrentRegionOnly,
22375 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
22376 ERange, CKind, &EnclosingExpr,
22378 StackComponents,
22379 OpenMPClauseKind Kind) {
22380 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
22381 return false;
22382 assert(!StackComponents.empty() &&
22383 "Map clause expression with no components!");
22384 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
22385 "Map clause expression with unexpected base!");
22386 (void)VD;
22387
22388 // The whole expression in the stack.
22389 const Expr *RE = StackComponents.front().getAssociatedExpression();
22390
22391 // Expressions must start from the same base. Here we detect at which
22392 // point both expressions diverge from each other and see if we can
22393 // detect if the memory referred to both expressions is contiguous and
22394 // do not overlap.
22395 auto CI = CurComponents.rbegin();
22396 auto CE = CurComponents.rend();
22397 auto SI = StackComponents.rbegin();
22398 auto SE = StackComponents.rend();
22399 for (; CI != CE && SI != SE; ++CI, ++SI) {
22400
22401 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
22402 // At most one list item can be an array item derived from a given
22403 // variable in map clauses of the same construct.
22404 if (CurrentRegionOnly &&
22405 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
22406 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
22407 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
22408 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
22409 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
22410 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
22411 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
22412 diag::err_omp_multiple_array_items_in_map_clause)
22413 << CI->getAssociatedExpression()->getSourceRange();
22414 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
22415 diag::note_used_here)
22416 << SI->getAssociatedExpression()->getSourceRange();
22417 return true;
22418 }
22419
22420 // Do both expressions have the same kind?
22421 if (CI->getAssociatedExpression()->getStmtClass() !=
22422 SI->getAssociatedExpression()->getStmtClass())
22423 break;
22424
22425 // Are we dealing with different variables/fields?
22426 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
22427 break;
22428 }
22429 // Check if the extra components of the expressions in the enclosing
22430 // data environment are redundant for the current base declaration.
22431 // If they are, the maps completely overlap, which is legal.
22432 for (; SI != SE; ++SI) {
22433 QualType Type;
22434 if (const auto *ASE =
22435 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
22436 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
22437 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
22438 SI->getAssociatedExpression())) {
22439 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22441 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
22442 SI->getAssociatedExpression())) {
22443 Type = OASE->getBase()->getType()->getPointeeType();
22444 }
22445 if (Type.isNull() || Type->isAnyPointerType() ||
22447 SemaRef, SI->getAssociatedExpression(), Type))
22448 break;
22449 }
22450
22451 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22452 // List items of map clauses in the same construct must not share
22453 // original storage.
22454 //
22455 // If the expressions are exactly the same or one is a subset of the
22456 // other, it means they are sharing storage.
22457 if (CI == CE && SI == SE) {
22458 if (CurrentRegionOnly) {
22459 if (CKind == OMPC_map) {
22460 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22461 } else {
22462 assert(CKind == OMPC_to || CKind == OMPC_from);
22463 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22464 << ERange;
22465 }
22466 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22467 << RE->getSourceRange();
22468 return true;
22469 }
22470 // If we find the same expression in the enclosing data environment,
22471 // that is legal.
22472 IsEnclosedByDataEnvironmentExpr = true;
22473 return false;
22474 }
22475
22476 QualType DerivedType =
22477 std::prev(CI)->getAssociatedDeclaration()->getType();
22478 SourceLocation DerivedLoc =
22479 std::prev(CI)->getAssociatedExpression()->getExprLoc();
22480
22481 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22482 // If the type of a list item is a reference to a type T then the type
22483 // will be considered to be T for all purposes of this clause.
22484 DerivedType = DerivedType.getNonReferenceType();
22485
22486 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
22487 // A variable for which the type is pointer and an array section
22488 // derived from that variable must not appear as list items of map
22489 // clauses of the same construct.
22490 //
22491 // Also, cover one of the cases in:
22492 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22493 // If any part of the original storage of a list item has corresponding
22494 // storage in the device data environment, all of the original storage
22495 // must have corresponding storage in the device data environment.
22496 //
22497 if (DerivedType->isAnyPointerType()) {
22498 if (CI == CE || SI == SE) {
22499 SemaRef.Diag(
22500 DerivedLoc,
22501 diag::err_omp_pointer_mapped_along_with_derived_section)
22502 << DerivedLoc;
22503 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22504 << RE->getSourceRange();
22505 return true;
22506 }
22507 if (CI->getAssociatedExpression()->getStmtClass() !=
22508 SI->getAssociatedExpression()->getStmtClass() ||
22509 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
22510 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
22511 assert(CI != CE && SI != SE);
22512 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
22513 << DerivedLoc;
22514 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22515 << RE->getSourceRange();
22516 return true;
22517 }
22518 }
22519
22520 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22521 // List items of map clauses in the same construct must not share
22522 // original storage.
22523 //
22524 // An expression is a subset of the other.
22525 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
22526 if (CKind == OMPC_map) {
22527 if (CI != CE || SI != SE) {
22528 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
22529 // a pointer.
22530 auto Begin =
22531 CI != CE ? CurComponents.begin() : StackComponents.begin();
22532 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
22533 auto It = Begin;
22534 while (It != End && !It->getAssociatedDeclaration())
22535 std::advance(It, 1);
22536 assert(It != End &&
22537 "Expected at least one component with the declaration.");
22538 if (It != Begin && It->getAssociatedDeclaration()
22539 ->getType()
22540 .getCanonicalType()
22541 ->isAnyPointerType()) {
22542 IsEnclosedByDataEnvironmentExpr = false;
22543 EnclosingExpr = nullptr;
22544 return false;
22545 }
22546 }
22547 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22548 } else {
22549 assert(CKind == OMPC_to || CKind == OMPC_from);
22550 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22551 << ERange;
22552 }
22553 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22554 << RE->getSourceRange();
22555 return true;
22556 }
22557
22558 // The current expression uses the same base as other expression in the
22559 // data environment but does not contain it completely.
22560 if (!CurrentRegionOnly && SI != SE)
22561 EnclosingExpr = RE;
22562
22563 // The current expression is a subset of the expression in the data
22564 // environment.
22565 IsEnclosedByDataEnvironmentExpr |=
22566 (!CurrentRegionOnly && CI != CE && SI == SE);
22567
22568 return false;
22569 });
22570
22571 if (CurrentRegionOnly)
22572 return FoundError;
22573
22574 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22575 // If any part of the original storage of a list item has corresponding
22576 // storage in the device data environment, all of the original storage must
22577 // have corresponding storage in the device data environment.
22578 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
22579 // If a list item is an element of a structure, and a different element of
22580 // the structure has a corresponding list item in the device data environment
22581 // prior to a task encountering the construct associated with the map clause,
22582 // then the list item must also have a corresponding list item in the device
22583 // data environment prior to the task encountering the construct.
22584 //
22585 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
22586 SemaRef.Diag(ELoc,
22587 diag::err_omp_original_storage_is_shared_and_does_not_contain)
22588 << ERange;
22589 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
22590 << EnclosingExpr->getSourceRange();
22591 return true;
22592 }
22593
22594 return FoundError;
22595}
22596
22597// Look up the user-defined mapper given the mapper name and mapped type, and
22598// build a reference to it.
22600 CXXScopeSpec &MapperIdScopeSpec,
22601 const DeclarationNameInfo &MapperId,
22602 QualType Type,
22603 Expr *UnresolvedMapper) {
22604 if (MapperIdScopeSpec.isInvalid())
22605 return ExprError();
22606 // Get the actual type for the array type.
22607 if (Type->isArrayType()) {
22608 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
22610 }
22611 // Find all user-defined mappers with the given MapperId.
22612 SmallVector<UnresolvedSet<8>, 4> Lookups;
22613 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22614 Lookup.suppressDiagnostics();
22615 if (S) {
22616 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
22617 /*ObjectType=*/QualType())) {
22618 NamedDecl *D = Lookup.getRepresentativeDecl();
22619 while (S && !S->isDeclScope(D))
22620 S = S->getParent();
22621 if (S)
22622 S = S->getParent();
22623 Lookups.emplace_back();
22624 Lookups.back().append(Lookup.begin(), Lookup.end());
22625 Lookup.clear();
22626 }
22627 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
22628 // Extract the user-defined mappers with the given MapperId.
22629 Lookups.push_back(UnresolvedSet<8>());
22630 for (NamedDecl *D : ULE->decls()) {
22631 auto *DMD = cast<OMPDeclareMapperDecl>(D);
22632 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
22633 Lookups.back().addDecl(DMD);
22634 }
22635 }
22636 // Defer the lookup for dependent types. The results will be passed through
22637 // UnresolvedMapper on instantiation.
22638 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22642 return !D->isInvalidDecl() &&
22643 (D->getType()->isDependentType() ||
22644 D->getType()->isInstantiationDependentType() ||
22645 D->getType()->containsUnexpandedParameterPack());
22646 })) {
22647 UnresolvedSet<8> URS;
22648 for (const UnresolvedSet<8> &Set : Lookups) {
22649 if (Set.empty())
22650 continue;
22651 URS.append(Set.begin(), Set.end());
22652 }
22654 SemaRef.Context, /*NamingClass=*/nullptr,
22655 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
22656 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
22657 /*KnownInstantiationDependent=*/false);
22658 }
22659 SourceLocation Loc = MapperId.getLoc();
22660 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22661 // The type must be of struct, union or class type in C and C++
22663 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
22664 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
22665 return ExprError();
22666 }
22667 // Perform argument dependent lookup.
22668 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22669 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22670 // Return the first user-defined mapper with the desired type.
22672 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22673 if (!D->isInvalidDecl() &&
22674 SemaRef.Context.hasSameType(D->getType(), Type))
22675 return D;
22676 return nullptr;
22677 }))
22678 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22679 // Find the first user-defined mapper with a type derived from the desired
22680 // type.
22682 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22683 if (!D->isInvalidDecl() &&
22684 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22685 !Type.isMoreQualifiedThan(D->getType(),
22686 SemaRef.getASTContext()))
22687 return D;
22688 return nullptr;
22689 })) {
22690 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22691 /*DetectVirtual=*/false);
22692 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22693 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
22694 VD->getType().getUnqualifiedType()))) {
22695 if (SemaRef.CheckBaseClassAccess(
22696 Loc, VD->getType(), Type, Paths.front(),
22697 /*DiagID=*/0) != Sema::AR_inaccessible) {
22698 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22699 }
22700 }
22701 }
22702 }
22703 // Report error if a mapper is specified, but cannot be found.
22704 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
22705 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
22706 << Type << MapperId.getName();
22707 return ExprError();
22708 }
22709 return ExprEmpty();
22710}
22711
22712namespace {
22713// Utility struct that gathers all the related lists associated with a mappable
22714// expression.
22715struct MappableVarListInfo {
22716 // The list of expressions.
22717 ArrayRef<Expr *> VarList;
22718 // The list of processed expressions.
22719 SmallVector<Expr *, 16> ProcessedVarList;
22720 // The mappble components for each expression.
22722 // The base declaration of the variable.
22723 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22724 // The reference to the user-defined mapper associated with every expression.
22725 SmallVector<Expr *, 16> UDMapperList;
22726
22727 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22728 // We have a list of components and base declarations for each entry in the
22729 // variable list.
22730 VarComponents.reserve(VarList.size());
22731 VarBaseDeclarations.reserve(VarList.size());
22732 }
22733};
22734} // namespace
22735
22737 DSAStackTy *Stack,
22739
22740 const RecordDecl *RD = BaseType->getAsRecordDecl();
22741 SourceRange Range = RD->getSourceRange();
22742 DeclarationNameInfo ImplicitName;
22743 // Dummy variable _s for Mapper.
22744 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
22745 DeclRefExpr *MapperVarRef =
22746 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
22747
22748 // Create implicit map clause for mapper.
22750 for (auto *FD : RD->fields()) {
22751 Expr *BE = S.BuildMemberExpr(
22752 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
22753 NestedNameSpecifierLoc(), Range.getBegin(), FD,
22755 /*HadMultipleCandidates=*/false,
22757 FD->getType(), VK_LValue, OK_Ordinary);
22758 SExprs.push_back(BE);
22759 }
22760 CXXScopeSpec MapperIdScopeSpec;
22761 DeclarationNameInfo MapperId;
22762 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
22763
22764 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
22765 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
22766 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
22767 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
22768 OMPVarListLocTy());
22769 Maps.push_back(MapClause);
22770 return MapperVarRef;
22771}
22772
22774 DSAStackTy *Stack) {
22775
22776 // Build impilicit map for mapper
22778 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
22779
22780 const RecordDecl *RD = BaseType->getAsRecordDecl();
22781 // AST context is RD's ParentASTContext().
22782 ASTContext &Ctx = RD->getParentASTContext();
22783 // DeclContext is RD's DeclContext.
22784 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
22785
22786 // Create implicit default mapper for "RD".
22787 DeclarationName MapperId;
22788 auto &DeclNames = Ctx.DeclarationNames;
22789 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
22790 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
22791 BaseType, MapperId, Maps, nullptr);
22792 Scope *Scope = S.getScopeForContext(DCT);
22793 if (Scope)
22794 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
22795 DCT->addDecl(DMD);
22796 DMD->setAccess(clang::AS_none);
22797 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22798 VD->setDeclContext(DMD);
22799 VD->setLexicalDeclContext(DMD);
22800 DMD->addDecl(VD);
22801 DMD->setMapperVarRef(MapperVarRef);
22802 FieldDecl *FD = *RD->field_begin();
22803 // create mapper refence.
22805 DMD, false, SourceLocation(), BaseType, VK_LValue);
22806}
22807
22808// Look up the user-defined mapper given the mapper name and mapper type,
22809// return true if found one.
22810static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
22811 CXXScopeSpec &MapperIdScopeSpec,
22812 const DeclarationNameInfo &MapperId,
22813 QualType Type) {
22814 // Find all user-defined mappers with the given MapperId.
22815 SmallVector<UnresolvedSet<8>, 4> Lookups;
22816 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22817 Lookup.suppressDiagnostics();
22818 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
22819 /*ObjectType=*/QualType())) {
22820 NamedDecl *D = Lookup.getRepresentativeDecl();
22821 while (S && !S->isDeclScope(D))
22822 S = S->getParent();
22823 if (S)
22824 S = S->getParent();
22825 Lookups.emplace_back();
22826 Lookups.back().append(Lookup.begin(), Lookup.end());
22827 Lookup.clear();
22828 }
22829 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22833 return !D->isInvalidDecl() &&
22834 (D->getType()->isDependentType() ||
22835 D->getType()->isInstantiationDependentType() ||
22836 D->getType()->containsUnexpandedParameterPack());
22837 }))
22838 return false;
22839 // Perform argument dependent lookup.
22840 SourceLocation Loc = MapperId.getLoc();
22841 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22842 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22844 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22845 if (!D->isInvalidDecl() &&
22846 SemaRef.Context.hasSameType(D->getType(), Type))
22847 return D;
22848 return nullptr;
22849 }))
22850 return true;
22851 // Find the first user-defined mapper with a type derived from the desired
22852 // type.
22854 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22855 if (!D->isInvalidDecl() &&
22856 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22857 !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext()))
22858 return D;
22859 return nullptr;
22860 });
22861 if (!VD)
22862 return false;
22863 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22864 /*DetectVirtual=*/false);
22865 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22866 bool IsAmbiguous = !Paths.isAmbiguous(
22868 if (IsAmbiguous)
22869 return false;
22870 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
22871 /*DiagID=*/0) != Sema::AR_inaccessible)
22872 return true;
22873 }
22874 return false;
22875}
22876
22877static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
22878 QualType CanonType, const Expr *E) {
22879
22880 // DFS over data members in structures/classes.
22882 {CanonType, nullptr});
22883 llvm::DenseMap<const Type *, bool> Visited;
22884 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
22885 while (!Types.empty()) {
22886 auto [BaseType, CurFD] = Types.pop_back_val();
22887 while (ParentChain.back().second == 0)
22888 ParentChain.pop_back();
22889 --ParentChain.back().second;
22890 if (BaseType.isNull())
22891 continue;
22892 // Only structs/classes are allowed to have mappers.
22893 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
22894 if (!RD)
22895 continue;
22896 auto It = Visited.find(BaseType.getTypePtr());
22897 if (It == Visited.end()) {
22898 // Try to find the associated user-defined mapper.
22899 CXXScopeSpec MapperIdScopeSpec;
22900 DeclarationNameInfo DefaultMapperId;
22902 &S.Context.Idents.get("default")));
22903 DefaultMapperId.setLoc(E->getExprLoc());
22904 bool HasUDMapper =
22905 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
22906 DefaultMapperId, BaseType);
22907 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
22908 }
22909 // Found default mapper.
22910 if (It->second)
22911 return true;
22912 // Check for the "default" mapper for data members.
22913 bool FirstIter = true;
22914 for (FieldDecl *FD : RD->fields()) {
22915 if (!FD)
22916 continue;
22917 QualType FieldTy = FD->getType();
22918 if (FieldTy.isNull() ||
22919 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
22920 continue;
22921 if (FirstIter) {
22922 FirstIter = false;
22923 ParentChain.emplace_back(CurFD, 1);
22924 } else {
22925 ++ParentChain.back().second;
22926 }
22927 Types.emplace_back(FieldTy, FD);
22928 }
22929 }
22930 return false;
22931}
22932
22933// Check the validity of the provided variable list for the provided clause kind
22934// \a CKind. In the check process the valid expressions, mappable expression
22935// components, variables, and user-defined mappers are extracted and used to
22936// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
22937// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22938// and \a MapperId are expected to be valid if the clause kind is 'map'.
22940 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
22941 MappableVarListInfo &MVLI, SourceLocation StartLoc,
22942 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
22943 ArrayRef<Expr *> UnresolvedMappers,
22945 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
22946 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
22947 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
22948 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
22949 "Unexpected clause kind with mappable expressions!");
22950 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
22951
22952 // If the identifier of user-defined mapper is not specified, it is "default".
22953 // We do not change the actual name in this clause to distinguish whether a
22954 // mapper is specified explicitly, i.e., it is not explicitly specified when
22955 // MapperId.getName() is empty.
22956 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
22957 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
22958 MapperId.setName(DeclNames.getIdentifier(
22959 &SemaRef.getASTContext().Idents.get("default")));
22960 MapperId.setLoc(StartLoc);
22961 }
22962
22963 // Iterators to find the current unresolved mapper expression.
22964 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
22965 bool UpdateUMIt = false;
22966 Expr *UnresolvedMapper = nullptr;
22967
22968 bool HasHoldModifier =
22969 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
22970
22971 // Keep track of the mappable components and base declarations in this clause.
22972 // Each entry in the list is going to have a list of components associated. We
22973 // record each set of the components so that we can build the clause later on.
22974 // In the end we should have the same amount of declarations and component
22975 // lists.
22976
22977 for (Expr *RE : MVLI.VarList) {
22978 assert(RE && "Null expr in omp to/from/map clause");
22979 SourceLocation ELoc = RE->getExprLoc();
22980
22981 // Find the current unresolved mapper expression.
22982 if (UpdateUMIt && UMIt != UMEnd) {
22983 UMIt++;
22984 assert(
22985 UMIt != UMEnd &&
22986 "Expect the size of UnresolvedMappers to match with that of VarList");
22987 }
22988 UpdateUMIt = true;
22989 if (UMIt != UMEnd)
22990 UnresolvedMapper = *UMIt;
22991
22992 const Expr *VE = RE->IgnoreParenLValueCasts();
22993
22994 if (VE->isValueDependent() || VE->isTypeDependent() ||
22995 VE->isInstantiationDependent() ||
22996 VE->containsUnexpandedParameterPack()) {
22997 // Try to find the associated user-defined mapper.
22999 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23000 VE->getType().getCanonicalType(), UnresolvedMapper);
23001 if (ER.isInvalid())
23002 continue;
23003 MVLI.UDMapperList.push_back(ER.get());
23004 // We can only analyze this information once the missing information is
23005 // resolved.
23006 MVLI.ProcessedVarList.push_back(RE);
23007 continue;
23008 }
23009
23011
23012 if (!RE->isLValue()) {
23013 if (SemaRef.getLangOpts().OpenMP < 50) {
23014 SemaRef.Diag(
23015 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
23016 << RE->getSourceRange();
23017 } else {
23018 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
23019 << getOpenMPClauseNameForDiag(CKind) << RE->getSourceRange();
23020 }
23021 continue;
23022 }
23023
23025 ValueDecl *CurDeclaration = nullptr;
23026
23027 // Obtain the array or member expression bases if required. Also, fill the
23028 // components array with all the components identified in the process.
23029 const Expr *BE =
23030 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
23031 DSAS->getCurrentDirective(), NoDiagnose);
23032 if (!BE)
23033 continue;
23034
23035 assert(!CurComponents.empty() &&
23036 "Invalid mappable expression information.");
23037
23038 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
23039 // Add store "this" pointer to class in DSAStackTy for future checking
23040 DSAS->addMappedClassesQualTypes(TE->getType());
23041 // Try to find the associated user-defined mapper.
23043 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23044 VE->getType().getCanonicalType(), UnresolvedMapper);
23045 if (ER.isInvalid())
23046 continue;
23047 MVLI.UDMapperList.push_back(ER.get());
23048 // Skip restriction checking for variable or field declarations
23049 MVLI.ProcessedVarList.push_back(RE);
23050 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23051 MVLI.VarComponents.back().append(CurComponents.begin(),
23052 CurComponents.end());
23053 MVLI.VarBaseDeclarations.push_back(nullptr);
23054 continue;
23055 }
23056
23057 // For the following checks, we rely on the base declaration which is
23058 // expected to be associated with the last component. The declaration is
23059 // expected to be a variable or a field (if 'this' is being mapped).
23060 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
23061 assert(CurDeclaration && "Null decl on map clause.");
23062 assert(
23063 CurDeclaration->isCanonicalDecl() &&
23064 "Expecting components to have associated only canonical declarations.");
23065
23066 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
23067 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
23068
23069 assert((VD || FD) && "Only variables or fields are expected here!");
23070 (void)FD;
23071
23072 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
23073 // threadprivate variables cannot appear in a map clause.
23074 // OpenMP 4.5 [2.10.5, target update Construct]
23075 // threadprivate variables cannot appear in a from clause.
23076 if (VD && DSAS->isThreadPrivate(VD)) {
23077 if (NoDiagnose)
23078 continue;
23079 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
23080 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
23082 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
23083 continue;
23084 }
23085
23086 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23087 // A list item cannot appear in both a map clause and a data-sharing
23088 // attribute clause on the same construct.
23089
23090 // Check conflicts with other map clause expressions. We check the conflicts
23091 // with the current construct separately from the enclosing data
23092 // environment, because the restrictions are different. We only have to
23093 // check conflicts across regions for the map clauses.
23094 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
23095 /*CurrentRegionOnly=*/true, CurComponents, CKind))
23096 break;
23097 if (CKind == OMPC_map &&
23098 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
23099 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
23100 /*CurrentRegionOnly=*/false, CurComponents, CKind))
23101 break;
23102
23103 // OpenMP 4.5 [2.10.5, target update Construct]
23104 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
23105 // If the type of a list item is a reference to a type T then the type will
23106 // be considered to be T for all purposes of this clause.
23107 auto I = llvm::find_if(
23108 CurComponents,
23110 return MC.getAssociatedDeclaration();
23111 });
23112 assert(I != CurComponents.end() && "Null decl on map clause.");
23113 (void)I;
23114 QualType Type;
23115 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
23116 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
23117 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
23118 if (ASE) {
23119 Type = ASE->getType().getNonReferenceType();
23120 } else if (OASE) {
23121 QualType BaseType =
23123 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
23124 Type = ATy->getElementType();
23125 else
23126 Type = BaseType->getPointeeType();
23127 Type = Type.getNonReferenceType();
23128 } else if (OAShE) {
23129 Type = OAShE->getBase()->getType()->getPointeeType();
23130 } else {
23131 Type = VE->getType();
23132 }
23133
23134 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
23135 // A list item in a to or from clause must have a mappable type.
23136 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23137 // A list item must have a mappable type.
23138 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
23139 DSAS, Type, /*FullCheck=*/true))
23140 continue;
23141
23142 if (CKind == OMPC_map) {
23143 // target enter data
23144 // OpenMP [2.10.2, Restrictions, p. 99]
23145 // A map-type must be specified in all map clauses and must be either
23146 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
23147 // no map type is present.
23148 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
23149 if (DKind == OMPD_target_enter_data &&
23150 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
23151 SemaRef.getLangOpts().OpenMP >= 52)) {
23152 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23153 << (IsMapTypeImplicit ? 1 : 0)
23154 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23155 << getOpenMPDirectiveName(DKind, OMPVersion);
23156 continue;
23157 }
23158
23159 // target exit_data
23160 // OpenMP [2.10.3, Restrictions, p. 102]
23161 // A map-type must be specified in all map clauses and must be either
23162 // from, release, or delete. Starting with OpenMP 5.2 the default map
23163 // type is `from` if no map type is present.
23164 if (DKind == OMPD_target_exit_data &&
23165 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
23166 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
23167 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23168 << (IsMapTypeImplicit ? 1 : 0)
23169 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23170 << getOpenMPDirectiveName(DKind, OMPVersion);
23171 continue;
23172 }
23173
23174 // The 'ompx_hold' modifier is specifically intended to be used on a
23175 // 'target' or 'target data' directive to prevent data from being unmapped
23176 // during the associated statement. It is not permitted on a 'target
23177 // enter data' or 'target exit data' directive, which have no associated
23178 // statement.
23179 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
23180 HasHoldModifier) {
23181 SemaRef.Diag(StartLoc,
23182 diag::err_omp_invalid_map_type_modifier_for_directive)
23184 OMPC_MAP_MODIFIER_ompx_hold)
23185 << getOpenMPDirectiveName(DKind, OMPVersion);
23186 continue;
23187 }
23188
23189 // target, target data
23190 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
23191 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
23192 // A map-type in a map clause must be to, from, tofrom or alloc
23193 if ((DKind == OMPD_target_data ||
23195 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
23196 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
23197 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23198 << (IsMapTypeImplicit ? 1 : 0)
23199 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23200 << getOpenMPDirectiveName(DKind, OMPVersion);
23201 continue;
23202 }
23203
23204 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
23205 // A list item cannot appear in both a map clause and a data-sharing
23206 // attribute clause on the same construct
23207 //
23208 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
23209 // A list item cannot appear in both a map clause and a data-sharing
23210 // attribute clause on the same construct unless the construct is a
23211 // combined construct.
23212 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
23214 DKind == OMPD_target)) {
23215 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
23216 if (isOpenMPPrivate(DVar.CKind)) {
23217 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23218 << getOpenMPClauseNameForDiag(DVar.CKind)
23219 << getOpenMPClauseNameForDiag(OMPC_map)
23220 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
23221 OMPVersion);
23222 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
23223 continue;
23224 }
23225 }
23226 }
23227
23228 // Try to find the associated user-defined mapper.
23230 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23231 Type.getCanonicalType(), UnresolvedMapper);
23232 if (ER.isInvalid())
23233 continue;
23234
23235 // If no user-defined mapper is found, we need to create an implicit one for
23236 // arrays/array-sections on structs that have members that have
23237 // user-defined mappers. This is needed to ensure that the mapper for the
23238 // member is invoked when mapping each element of the array/array-section.
23239 if (!ER.get()) {
23240 QualType BaseType;
23241
23243 BaseType = VE->getType().getCanonicalType();
23244 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
23245 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
23246 QualType BType =
23248 QualType ElemType;
23249 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
23250 ElemType = ATy->getElementType();
23251 else
23252 ElemType = BType->getPointeeType();
23253 BaseType = ElemType.getCanonicalType();
23254 }
23255 } else if (VE->getType()->isArrayType()) {
23256 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
23257 const QualType ElemType = AT->getElementType();
23258 BaseType = ElemType.getCanonicalType();
23259 }
23260
23261 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
23262 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
23263 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
23264 }
23265 }
23266 MVLI.UDMapperList.push_back(ER.get());
23267
23268 // Save the current expression.
23269 MVLI.ProcessedVarList.push_back(RE);
23270
23271 // Store the components in the stack so that they can be used to check
23272 // against other clauses later on.
23273 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
23274 /*WhereFoundClauseKind=*/OMPC_map);
23275
23276 // Save the components and declaration to create the clause. For purposes of
23277 // the clause creation, any component list that has base 'this' uses
23278 // null as base declaration.
23279 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23280 MVLI.VarComponents.back().append(CurComponents.begin(),
23281 CurComponents.end());
23282 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
23283 : CurDeclaration);
23284 }
23285}
23286
23288 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
23289 ArrayRef<SourceLocation> MapTypeModifiersLoc,
23290 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23291 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
23292 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23293 const OMPVarListLocTy &Locs, bool NoDiagnose,
23294 ArrayRef<Expr *> UnresolvedMappers) {
23295 OpenMPMapModifierKind Modifiers[] = {
23301
23302 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
23303 BuiltinType::OMPIterator))
23304 Diag(IteratorModifier->getExprLoc(),
23305 diag::err_omp_map_modifier_not_iterator);
23306
23307 // Process map-type-modifiers, flag errors for duplicate modifiers.
23308 unsigned Count = 0;
23309 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
23310 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
23311 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
23312 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
23313 continue;
23314 }
23315 assert(Count < NumberOfOMPMapClauseModifiers &&
23316 "Modifiers exceed the allowed number of map type modifiers");
23317 Modifiers[Count] = MapTypeModifiers[I];
23318 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
23319 ++Count;
23320 }
23321
23322 MappableVarListInfo MVLI(VarList);
23324 MapperIdScopeSpec, MapperId, UnresolvedMappers,
23325 MapType, Modifiers, IsMapTypeImplicit,
23326 NoDiagnose);
23327
23328 // We need to produce a map clause even if we don't have variables so that
23329 // other diagnostics related with non-existing map clauses are accurate.
23330 return OMPMapClause::Create(
23331 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23332 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
23333 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
23334 MapperId, MapType, IsMapTypeImplicit, MapLoc);
23335}
23336
23339 assert(ParsedType.isUsable());
23340
23341 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
23342 if (ReductionType.isNull())
23343 return QualType();
23344
23345 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
23346 // A type name in a declare reduction directive cannot be a function type, an
23347 // array type, a reference type, or a type qualified with const, volatile or
23348 // restrict.
23349 if (ReductionType.hasQualifiers()) {
23350 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
23351 return QualType();
23352 }
23353
23354 if (ReductionType->isFunctionType()) {
23355 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
23356 return QualType();
23357 }
23358 if (ReductionType->isReferenceType()) {
23359 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
23360 return QualType();
23361 }
23362 if (ReductionType->isArrayType()) {
23363 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
23364 return QualType();
23365 }
23366 return ReductionType;
23367}
23368
23371 Scope *S, DeclContext *DC, DeclarationName Name,
23372 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
23373 AccessSpecifier AS, Decl *PrevDeclInScope) {
23375 Decls.reserve(ReductionTypes.size());
23376
23377 LookupResult Lookup(SemaRef, Name, SourceLocation(),
23379 SemaRef.forRedeclarationInCurContext());
23380 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
23381 // A reduction-identifier may not be re-declared in the current scope for the
23382 // same type or for a type that is compatible according to the base language
23383 // rules.
23384 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23385 OMPDeclareReductionDecl *PrevDRD = nullptr;
23386 bool InCompoundScope = true;
23387 if (S != nullptr) {
23388 // Find previous declaration with the same name not referenced in other
23389 // declarations.
23390 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
23391 InCompoundScope =
23392 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
23393 SemaRef.LookupName(Lookup, S);
23394 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
23395 /*AllowInlineNamespace=*/false);
23396 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
23397 LookupResult::Filter Filter = Lookup.makeFilter();
23398 while (Filter.hasNext()) {
23399 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
23400 if (InCompoundScope) {
23401 UsedAsPrevious.try_emplace(PrevDecl, false);
23402 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
23403 UsedAsPrevious[D] = true;
23404 }
23405 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23406 PrevDecl->getLocation();
23407 }
23408 Filter.done();
23409 if (InCompoundScope) {
23410 for (const auto &PrevData : UsedAsPrevious) {
23411 if (!PrevData.second) {
23412 PrevDRD = PrevData.first;
23413 break;
23414 }
23415 }
23416 }
23417 } else if (PrevDeclInScope != nullptr) {
23418 auto *PrevDRDInScope = PrevDRD =
23419 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
23420 do {
23421 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
23422 PrevDRDInScope->getLocation();
23423 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
23424 } while (PrevDRDInScope != nullptr);
23425 }
23426 for (const auto &TyData : ReductionTypes) {
23427 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
23428 bool Invalid = false;
23429 if (I != PreviousRedeclTypes.end()) {
23430 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
23431 << TyData.first;
23432 Diag(I->second, diag::note_previous_definition);
23433 Invalid = true;
23434 }
23435 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
23437 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
23438 DC->addDecl(DRD);
23439 DRD->setAccess(AS);
23440 Decls.push_back(DRD);
23441 if (Invalid)
23442 DRD->setInvalidDecl();
23443 else
23444 PrevDRD = DRD;
23445 }
23446
23447 return DeclGroupPtrTy::make(
23448 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
23449}
23450
23452 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23453
23454 // Enter new function scope.
23455 SemaRef.PushFunctionScope();
23456 SemaRef.setFunctionHasBranchProtectedScope();
23457 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
23458
23459 if (S != nullptr)
23460 SemaRef.PushDeclContext(S, DRD);
23461 else
23462 SemaRef.CurContext = DRD;
23463
23464 SemaRef.PushExpressionEvaluationContext(
23466
23467 QualType ReductionType = DRD->getType();
23468 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
23469 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
23470 // uses semantics of argument handles by value, but it should be passed by
23471 // reference. C lang does not support references, so pass all parameters as
23472 // pointers.
23473 // Create 'T omp_in;' variable.
23474 VarDecl *OmpInParm =
23475 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
23476 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
23477 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
23478 // uses semantics of argument handles by value, but it should be passed by
23479 // reference. C lang does not support references, so pass all parameters as
23480 // pointers.
23481 // Create 'T omp_out;' variable.
23482 VarDecl *OmpOutParm =
23483 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
23484 if (S != nullptr) {
23485 SemaRef.PushOnScopeChains(OmpInParm, S);
23486 SemaRef.PushOnScopeChains(OmpOutParm, S);
23487 } else {
23488 DRD->addDecl(OmpInParm);
23489 DRD->addDecl(OmpOutParm);
23490 }
23491 Expr *InE =
23492 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
23493 Expr *OutE =
23494 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
23495 DRD->setCombinerData(InE, OutE);
23496}
23497
23499 Expr *Combiner) {
23500 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23501 SemaRef.DiscardCleanupsInEvaluationContext();
23502 SemaRef.PopExpressionEvaluationContext();
23503
23504 SemaRef.PopDeclContext();
23505 SemaRef.PopFunctionScopeInfo();
23506
23507 if (Combiner != nullptr)
23508 DRD->setCombiner(Combiner);
23509 else
23510 DRD->setInvalidDecl();
23511}
23512
23514 Decl *D) {
23515 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23516
23517 // Enter new function scope.
23518 SemaRef.PushFunctionScope();
23519 SemaRef.setFunctionHasBranchProtectedScope();
23520
23521 if (S != nullptr)
23522 SemaRef.PushDeclContext(S, DRD);
23523 else
23524 SemaRef.CurContext = DRD;
23525
23526 SemaRef.PushExpressionEvaluationContext(
23528
23529 QualType ReductionType = DRD->getType();
23530 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
23531 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
23532 // uses semantics of argument handles by value, but it should be passed by
23533 // reference. C lang does not support references, so pass all parameters as
23534 // pointers.
23535 // Create 'T omp_priv;' variable.
23536 VarDecl *OmpPrivParm =
23537 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
23538 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
23539 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
23540 // uses semantics of argument handles by value, but it should be passed by
23541 // reference. C lang does not support references, so pass all parameters as
23542 // pointers.
23543 // Create 'T omp_orig;' variable.
23544 VarDecl *OmpOrigParm =
23545 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
23546 if (S != nullptr) {
23547 SemaRef.PushOnScopeChains(OmpPrivParm, S);
23548 SemaRef.PushOnScopeChains(OmpOrigParm, S);
23549 } else {
23550 DRD->addDecl(OmpPrivParm);
23551 DRD->addDecl(OmpOrigParm);
23552 }
23553 Expr *OrigE =
23554 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
23555 Expr *PrivE =
23556 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
23557 DRD->setInitializerData(OrigE, PrivE);
23558 return OmpPrivParm;
23559}
23560
23562 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
23563 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23564 SemaRef.DiscardCleanupsInEvaluationContext();
23565 SemaRef.PopExpressionEvaluationContext();
23566
23567 SemaRef.PopDeclContext();
23568 SemaRef.PopFunctionScopeInfo();
23569
23570 if (Initializer != nullptr) {
23571 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
23572 } else if (OmpPrivParm->hasInit()) {
23573 DRD->setInitializer(OmpPrivParm->getInit(),
23574 OmpPrivParm->isDirectInit()
23577 } else {
23578 DRD->setInvalidDecl();
23579 }
23580}
23581
23583 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
23584 for (Decl *D : DeclReductions.get()) {
23585 if (IsValid) {
23586 if (S)
23587 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
23588 /*AddToContext=*/false);
23589 } else {
23590 D->setInvalidDecl();
23591 }
23592 }
23593 return DeclReductions;
23594}
23595
23597 Declarator &D) {
23598 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
23599 QualType T = TInfo->getType();
23600 if (D.isInvalidType())
23601 return true;
23602
23603 if (getLangOpts().CPlusPlus) {
23604 // Check that there are no default arguments (C++ only).
23605 SemaRef.CheckExtraCXXDefaultArguments(D);
23606 }
23607
23608 return SemaRef.CreateParsedType(T, TInfo);
23609}
23610
23613 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
23614
23615 QualType MapperType = SemaRef.GetTypeFromParser(ParsedType.get());
23616 assert(!MapperType.isNull() && "Expect valid mapper type");
23617
23618 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23619 // The type must be of struct, union or class type in C and C++
23620 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
23621 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
23622 return QualType();
23623 }
23624 return MapperType;
23625}
23626
23628 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
23630 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
23631 LookupResult Lookup(SemaRef, Name, SourceLocation(),
23633 SemaRef.forRedeclarationInCurContext());
23634 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23635 // A mapper-identifier may not be redeclared in the current scope for the
23636 // same type or for a type that is compatible according to the base language
23637 // rules.
23638 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23639 OMPDeclareMapperDecl *PrevDMD = nullptr;
23640 bool InCompoundScope = true;
23641 if (S != nullptr) {
23642 // Find previous declaration with the same name not referenced in other
23643 // declarations.
23644 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
23645 InCompoundScope =
23646 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
23647 SemaRef.LookupName(Lookup, S);
23648 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
23649 /*AllowInlineNamespace=*/false);
23650 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
23651 LookupResult::Filter Filter = Lookup.makeFilter();
23652 while (Filter.hasNext()) {
23653 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
23654 if (InCompoundScope) {
23655 UsedAsPrevious.try_emplace(PrevDecl, false);
23656 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
23657 UsedAsPrevious[D] = true;
23658 }
23659 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23660 PrevDecl->getLocation();
23661 }
23662 Filter.done();
23663 if (InCompoundScope) {
23664 for (const auto &PrevData : UsedAsPrevious) {
23665 if (!PrevData.second) {
23666 PrevDMD = PrevData.first;
23667 break;
23668 }
23669 }
23670 }
23671 } else if (PrevDeclInScope) {
23672 auto *PrevDMDInScope = PrevDMD =
23673 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
23674 do {
23675 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
23676 PrevDMDInScope->getLocation();
23677 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
23678 } while (PrevDMDInScope != nullptr);
23679 }
23680 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
23681 bool Invalid = false;
23682 if (I != PreviousRedeclTypes.end()) {
23683 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
23684 << MapperType << Name;
23685 Diag(I->second, diag::note_previous_definition);
23686 Invalid = true;
23687 }
23688 // Build expressions for implicit maps of data members with 'default'
23689 // mappers.
23690 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
23691 if (getLangOpts().OpenMP >= 50)
23693 ClausesWithImplicit);
23694 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
23695 MapperType, VN, ClausesWithImplicit,
23696 PrevDMD);
23697 if (S)
23698 SemaRef.PushOnScopeChains(DMD, S);
23699 else
23700 DC->addDecl(DMD);
23701 DMD->setAccess(AS);
23702 if (Invalid)
23703 DMD->setInvalidDecl();
23704
23705 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
23706 VD->setDeclContext(DMD);
23707 VD->setLexicalDeclContext(DMD);
23708 DMD->addDecl(VD);
23709 DMD->setMapperVarRef(MapperVarRef);
23710
23712}
23713
23715 Scope *S, QualType MapperType, SourceLocation StartLoc,
23716 DeclarationName VN) {
23717 TypeSourceInfo *TInfo =
23718 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
23719 auto *VD = VarDecl::Create(
23720 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
23721 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
23722 if (S)
23723 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
23724 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
23725 DSAStack->addDeclareMapperVarRef(E);
23726 return E;
23727}
23728
23730 bool IsGlobalVar =
23732 if (DSAStack->getDeclareMapperVarRef()) {
23733 if (IsGlobalVar)
23734 SemaRef.Consumer.HandleTopLevelDecl(DeclGroupRef(VD));
23735 DSAStack->addIteratorVarDecl(VD);
23736 } else {
23737 // Currently, only declare mapper handles global-scope iterator vars.
23738 assert(!IsGlobalVar && "Only declare mapper handles TU-scope iterators.");
23739 }
23740}
23741
23743 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23744 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
23745 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
23746 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
23747 return true;
23749 return true;
23750 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
23751 return true;
23752 return false;
23753 }
23754 return true;
23755}
23756
23758 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23759 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
23760}
23761
23763 SourceLocation StartLoc,
23764 SourceLocation LParenLoc,
23765 SourceLocation EndLoc) {
23766 if (VarList.empty())
23767 return nullptr;
23768
23769 for (Expr *ValExpr : VarList) {
23770 // OpenMP [teams Constrcut, Restrictions]
23771 // The num_teams expression must evaluate to a positive integer value.
23772 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
23773 /*StrictlyPositive=*/true))
23774 return nullptr;
23775 }
23776
23777 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23779 DKind, OMPC_num_teams, getLangOpts().OpenMP);
23780 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
23781 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
23782 LParenLoc, EndLoc, VarList,
23783 /*PreInit=*/nullptr);
23784
23785 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23787 for (Expr *ValExpr : VarList) {
23788 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23789 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23790 Vars.push_back(ValExpr);
23791 }
23792
23793 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
23794 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
23795 LParenLoc, EndLoc, Vars, PreInit);
23796}
23797
23799 SourceLocation StartLoc,
23800 SourceLocation LParenLoc,
23801 SourceLocation EndLoc) {
23802 if (VarList.empty())
23803 return nullptr;
23804
23805 for (Expr *ValExpr : VarList) {
23806 // OpenMP [teams Constrcut, Restrictions]
23807 // The thread_limit expression must evaluate to a positive integer value.
23808 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
23809 /*StrictlyPositive=*/true))
23810 return nullptr;
23811 }
23812
23813 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23815 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
23816 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
23817 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
23818 StartLoc, LParenLoc, EndLoc, VarList,
23819 /*PreInit=*/nullptr);
23820
23821 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23823 for (Expr *ValExpr : VarList) {
23824 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23825 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23826 Vars.push_back(ValExpr);
23827 }
23828
23829 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
23830 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
23831 LParenLoc, EndLoc, Vars, PreInit);
23832}
23833
23835 SourceLocation StartLoc,
23836 SourceLocation LParenLoc,
23837 SourceLocation EndLoc) {
23838 Expr *ValExpr = Priority;
23839 Stmt *HelperValStmt = nullptr;
23840 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23841
23842 // OpenMP [2.9.1, task Constrcut]
23843 // The priority-value is a non-negative numerical scalar expression.
23845 ValExpr, SemaRef, OMPC_priority,
23846 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
23847 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23848 return nullptr;
23849
23850 return new (getASTContext()) OMPPriorityClause(
23851 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23852}
23853
23855 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
23856 SourceLocation StartLoc, SourceLocation LParenLoc,
23857 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23858 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23859 "Unexpected grainsize modifier in OpenMP < 51.");
23860
23861 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
23862 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
23864 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23865 << Values << getOpenMPClauseNameForDiag(OMPC_grainsize);
23866 return nullptr;
23867 }
23868
23869 Expr *ValExpr = Grainsize;
23870 Stmt *HelperValStmt = nullptr;
23871 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23872
23873 // OpenMP [2.9.2, taskloop Constrcut]
23874 // The parameter of the grainsize clause must be a positive integer
23875 // expression.
23876 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
23877 /*StrictlyPositive=*/true,
23878 /*BuildCapture=*/true,
23879 DSAStack->getCurrentDirective(),
23880 &CaptureRegion, &HelperValStmt))
23881 return nullptr;
23882
23883 return new (getASTContext())
23884 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23885 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23886}
23887
23889 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
23890 SourceLocation StartLoc, SourceLocation LParenLoc,
23891 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23892 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23893 "Unexpected num_tasks modifier in OpenMP < 51.");
23894
23895 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
23896 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
23898 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23899 << Values << getOpenMPClauseNameForDiag(OMPC_num_tasks);
23900 return nullptr;
23901 }
23902
23903 Expr *ValExpr = NumTasks;
23904 Stmt *HelperValStmt = nullptr;
23905 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23906
23907 // OpenMP [2.9.2, taskloop Constrcut]
23908 // The parameter of the num_tasks clause must be a positive integer
23909 // expression.
23911 ValExpr, SemaRef, OMPC_num_tasks,
23912 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
23913 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23914 return nullptr;
23915
23916 return new (getASTContext())
23917 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23918 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23919}
23920
23922 SourceLocation StartLoc,
23923 SourceLocation LParenLoc,
23924 SourceLocation EndLoc) {
23925 // OpenMP [2.13.2, critical construct, Description]
23926 // ... where hint-expression is an integer constant expression that evaluates
23927 // to a valid lock hint.
23928 ExprResult HintExpr =
23929 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
23930 if (HintExpr.isInvalid())
23931 return nullptr;
23932 return new (getASTContext())
23933 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
23934}
23935
23936/// Tries to find omp_event_handle_t type.
23938 DSAStackTy *Stack) {
23939 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
23940 if (!OMPEventHandleT.isNull())
23941 return true;
23942 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
23943 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
23944 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23945 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
23946 return false;
23947 }
23948 Stack->setOMPEventHandleT(PT.get());
23949 return true;
23950}
23951
23953 SourceLocation StartLoc,
23954 SourceLocation LParenLoc,
23955 SourceLocation EndLoc) {
23956 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
23957 !Evt->isInstantiationDependent() &&
23960 return nullptr;
23961 // OpenMP 5.0, 2.10.1 task Construct.
23962 // event-handle is a variable of the omp_event_handle_t type.
23963 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
23964 if (!Ref) {
23965 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23966 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23967 return nullptr;
23968 }
23969 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
23970 if (!VD) {
23971 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23972 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23973 return nullptr;
23974 }
23975 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
23976 VD->getType()) ||
23977 VD->getType().isConstant(getASTContext())) {
23978 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23979 << "omp_event_handle_t" << 1 << VD->getType()
23980 << Evt->getSourceRange();
23981 return nullptr;
23982 }
23983 // OpenMP 5.0, 2.10.1 task Construct
23984 // [detach clause]... The event-handle will be considered as if it was
23985 // specified on a firstprivate clause.
23986 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
23987 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
23988 DVar.RefExpr) {
23989 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
23990 << getOpenMPClauseNameForDiag(DVar.CKind)
23991 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
23993 return nullptr;
23994 }
23995 }
23996
23997 return new (getASTContext())
23998 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
23999}
24000
24002 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
24003 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
24004 SourceLocation EndLoc) {
24005 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
24006 std::string Values;
24007 Values += "'";
24008 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
24009 Values += "'";
24010 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24011 << Values << getOpenMPClauseNameForDiag(OMPC_dist_schedule);
24012 return nullptr;
24013 }
24014 Expr *ValExpr = ChunkSize;
24015 Stmt *HelperValStmt = nullptr;
24016 if (ChunkSize) {
24017 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
24018 !ChunkSize->isInstantiationDependent() &&
24019 !ChunkSize->containsUnexpandedParameterPack()) {
24020 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
24021 ExprResult Val =
24022 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
24023 if (Val.isInvalid())
24024 return nullptr;
24025
24026 ValExpr = Val.get();
24027
24028 // OpenMP [2.7.1, Restrictions]
24029 // chunk_size must be a loop invariant integer expression with a positive
24030 // value.
24031 if (std::optional<llvm::APSInt> Result =
24033 if (Result->isSigned() && !Result->isStrictlyPositive()) {
24034 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
24035 << "dist_schedule" << /*strictly positive*/ 1
24036 << ChunkSize->getSourceRange();
24037 return nullptr;
24038 }
24040 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
24041 getLangOpts().OpenMP) != OMPD_unknown &&
24042 !SemaRef.CurContext->isDependentContext()) {
24043 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24044 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24045 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24046 HelperValStmt = buildPreInits(getASTContext(), Captures);
24047 }
24048 }
24049 }
24050
24051 return new (getASTContext())
24052 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
24053 Kind, ValExpr, HelperValStmt);
24054}
24055
24058 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
24059 SourceLocation KindLoc, SourceLocation EndLoc) {
24060 if (getLangOpts().OpenMP < 50) {
24061 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
24062 Kind != OMPC_DEFAULTMAP_scalar) {
24063 std::string Value;
24064 SourceLocation Loc;
24065 Value += "'";
24066 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
24067 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
24068 OMPC_DEFAULTMAP_MODIFIER_tofrom);
24069 Loc = MLoc;
24070 } else {
24071 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
24072 OMPC_DEFAULTMAP_scalar);
24073 Loc = KindLoc;
24074 }
24075 Value += "'";
24076 Diag(Loc, diag::err_omp_unexpected_clause_value)
24077 << Value << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24078 return nullptr;
24079 }
24080 } else {
24081 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
24082 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
24083 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
24084 if (!isDefaultmapKind || !isDefaultmapModifier) {
24085 StringRef KindValue = getLangOpts().OpenMP < 52
24086 ? "'scalar', 'aggregate', 'pointer'"
24087 : "'scalar', 'aggregate', 'pointer', 'all'";
24088 if (getLangOpts().OpenMP == 50) {
24089 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
24090 "'firstprivate', 'none', 'default'";
24091 if (!isDefaultmapKind && isDefaultmapModifier) {
24092 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24093 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24094 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24095 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24096 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24097 } else {
24098 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24099 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24100 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24101 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24102 }
24103 } else {
24104 StringRef ModifierValue =
24105 getLangOpts().OpenMP < 60
24106 ? "'alloc', 'from', 'to', 'tofrom', "
24107 "'firstprivate', 'none', 'default', 'present'"
24108 : "'storage', 'from', 'to', 'tofrom', "
24109 "'firstprivate', 'private', 'none', 'default', 'present'";
24110 if (!isDefaultmapKind && isDefaultmapModifier) {
24111 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24112 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24113 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24114 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24115 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24116 } else {
24117 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24118 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24119 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24120 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24121 }
24122 }
24123 return nullptr;
24124 }
24125
24126 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
24127 // At most one defaultmap clause for each category can appear on the
24128 // directive.
24129 if (DSAStack->checkDefaultmapCategory(Kind)) {
24130 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
24131 return nullptr;
24132 }
24133 }
24134 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
24135 // Variable category is not specified - mark all categories.
24136 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
24137 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
24138 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
24139 } else {
24140 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
24141 }
24142
24143 return new (getASTContext())
24144 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
24145}
24146
24149 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
24150 if (!CurLexicalContext->isFileContext() &&
24151 !CurLexicalContext->isExternCContext() &&
24152 !CurLexicalContext->isExternCXXContext() &&
24153 !isa<CXXRecordDecl>(CurLexicalContext) &&
24154 !isa<ClassTemplateDecl>(CurLexicalContext) &&
24155 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
24156 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
24157 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
24158 return false;
24159 }
24160
24161 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24162 if (getLangOpts().HIP)
24163 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
24164
24165 DeclareTargetNesting.push_back(DTCI);
24166 return true;
24167}
24168
24171 assert(!DeclareTargetNesting.empty() &&
24172 "check isInOpenMPDeclareTargetContext() first!");
24173 return DeclareTargetNesting.pop_back_val();
24174}
24175
24178 for (auto &It : DTCI.ExplicitlyMapped)
24179 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
24180}
24181
24183 if (DeclareTargetNesting.empty())
24184 return;
24185 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
24186 unsigned OMPVersion = getLangOpts().OpenMP;
24187 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
24188 << getOpenMPDirectiveName(DTCI.Kind, OMPVersion);
24189}
24190
24192 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
24194 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
24195 /*ObjectType=*/QualType(),
24196 /*AllowBuiltinCreation=*/true);
24197
24198 if (Lookup.isAmbiguous())
24199 return nullptr;
24200 Lookup.suppressDiagnostics();
24201
24202 if (!Lookup.isSingleResult()) {
24203 VarOrFuncDeclFilterCCC CCC(SemaRef);
24204 if (TypoCorrection Corrected =
24205 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
24207 SemaRef.diagnoseTypo(Corrected,
24208 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
24209 << Id.getName());
24210 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
24211 return nullptr;
24212 }
24213
24214 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
24215 return nullptr;
24216 }
24217
24218 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
24219 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
24221 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
24222 return nullptr;
24223 }
24224 return ND;
24225}
24226
24228 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
24230 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
24232 "Expected variable, function or function template.");
24233
24234 if (auto *VD = dyn_cast<VarDecl>(ND)) {
24235 // Only global variables can be marked as declare target.
24236 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24237 !VD->isStaticDataMember()) {
24238 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
24239 << VD->getNameAsString();
24240 return;
24241 }
24242 }
24243 // Diagnose marking after use as it may lead to incorrect diagnosis and
24244 // codegen.
24245 if (getLangOpts().OpenMP >= 50 &&
24246 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
24247 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
24248
24249 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24250 if (getLangOpts().HIP)
24251 Diag(Loc, diag::warn_hip_omp_target_directives);
24252
24253 // Explicit declare target lists have precedence.
24254 const unsigned Level = -1;
24255
24256 auto *VD = cast<ValueDecl>(ND);
24257 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24258 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24259 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
24260 (*ActiveAttr)->getLevel() == Level) {
24261 Diag(Loc, diag::err_omp_device_type_mismatch)
24262 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
24263 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
24264 (*ActiveAttr)->getDevType());
24265 return;
24266 }
24267 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
24268 (*ActiveAttr)->getLevel() == Level) {
24269 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
24270 return;
24271 }
24272
24273 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
24274 return;
24275
24276 Expr *IndirectE = nullptr;
24277 bool IsIndirect = false;
24278 if (DTCI.Indirect) {
24279 IndirectE = *DTCI.Indirect;
24280 if (!IndirectE)
24281 IsIndirect = true;
24282 }
24283 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24284 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
24285 SourceRange(Loc, Loc));
24286 ND->addAttr(A);
24287 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
24288 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
24289 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
24290 if (auto *VD = dyn_cast<VarDecl>(ND);
24291 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
24292 VD->hasGlobalStorage())
24294}
24295
24297 Sema &SemaRef, Decl *D) {
24298 if (!D || !isa<VarDecl>(D))
24299 return;
24300 auto *VD = cast<VarDecl>(D);
24301 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
24302 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
24303 if (SemaRef.LangOpts.OpenMP >= 50 &&
24304 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
24305 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
24306 VD->hasGlobalStorage()) {
24307 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
24308 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
24309 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
24310 // If a lambda declaration and definition appears between a
24311 // declare target directive and the matching end declare target
24312 // directive, all variables that are captured by the lambda
24313 // expression must also appear in a to clause.
24314 SemaRef.Diag(VD->getLocation(),
24315 diag::err_omp_lambda_capture_in_declare_target_not_to);
24316 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
24317 << VD << 0 << SR;
24318 return;
24319 }
24320 }
24321 if (MapTy)
24322 return;
24323 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
24324 SemaRef.Diag(SL, diag::note_used_here) << SR;
24325}
24326
24328 Sema &SemaRef, DSAStackTy *Stack,
24329 ValueDecl *VD) {
24330 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
24331 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
24332 /*FullCheck=*/false);
24333}
24334
24336 SourceLocation IdLoc) {
24337 if (!D || D->isInvalidDecl())
24338 return;
24339 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
24340 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
24341 if (auto *VD = dyn_cast<VarDecl>(D)) {
24342 // Only global variables can be marked as declare target.
24343 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24344 !VD->isStaticDataMember())
24345 return;
24346 // 2.10.6: threadprivate variable cannot appear in a declare target
24347 // directive.
24348 if (DSAStack->isThreadPrivate(VD)) {
24349 Diag(SL, diag::err_omp_threadprivate_in_target);
24350 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
24351 return;
24352 }
24353 }
24354 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
24355 D = FTD->getTemplatedDecl();
24356 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
24357 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
24358 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
24359 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
24360 Diag(IdLoc, diag::err_omp_function_in_link_clause);
24361 Diag(FD->getLocation(), diag::note_defined_here) << FD;
24362 return;
24363 }
24364 }
24365 if (auto *VD = dyn_cast<ValueDecl>(D)) {
24366 // Problem if any with var declared with incomplete type will be reported
24367 // as normal, so no need to check it here.
24368 if ((E || !VD->getType()->isIncompleteType()) &&
24370 return;
24371 if (!E && isInOpenMPDeclareTargetContext()) {
24372 // Checking declaration inside declare target region.
24373 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
24375 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24376 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24377 unsigned Level = DeclareTargetNesting.size();
24378 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
24379 return;
24380 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
24381 Expr *IndirectE = nullptr;
24382 bool IsIndirect = false;
24383 if (DTCI.Indirect) {
24384 IndirectE = *DTCI.Indirect;
24385 if (!IndirectE)
24386 IsIndirect = true;
24387 }
24388 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24389 getASTContext(),
24390 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
24391 : OMPDeclareTargetDeclAttr::MT_To,
24392 DTCI.DT, IndirectE, IsIndirect, Level,
24393 SourceRange(DTCI.Loc, DTCI.Loc));
24394 D->addAttr(A);
24395 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
24396 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
24397 }
24398 return;
24399 }
24400 }
24401 if (!E)
24402 return;
24404}
24405
24406/// This class visits every VarDecl that the initializer references and adds
24407/// OMPDeclareTargetDeclAttr to each of them.
24408class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
24409 SmallVector<VarDecl *> DeclVector;
24410 Attr *A;
24411
24412public:
24413 /// A StmtVisitor class function that visits all DeclRefExpr and adds
24414 /// OMPDeclareTargetDeclAttr to them.
24416 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
24417 VD->addAttr(A);
24418 DeclVector.push_back(VD);
24419 }
24420 }
24421 /// A function that iterates across each of the Expr's children.
24422 void VisitExpr(Expr *Ex) {
24423 for (auto *Child : Ex->children()) {
24424 Visit(Child);
24425 }
24426 }
24427 /// A function that keeps a record of all the Decls that are variables, has
24428 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
24429 /// each Decl one at a time and use the inherited 'visit' functions to look
24430 /// for DeclRefExpr.
24432 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
24433 DeclVector.push_back(cast<VarDecl>(TD));
24434 llvm::SmallDenseSet<Decl *> Visited;
24435 while (!DeclVector.empty()) {
24436 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
24437 if (!Visited.insert(TargetVarDecl).second)
24438 continue;
24439
24440 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
24441 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
24442 if (Expr *Ex = TargetVarDecl->getInit())
24443 Visit(Ex);
24444 }
24445 }
24446 }
24447};
24448
24449/// Adding OMPDeclareTargetDeclAttr to variables with static storage
24450/// duration that are referenced in the initializer expression list of
24451/// variables with static storage duration in declare target directive.
24453 GlobalDeclRefChecker Checker;
24454 if (isa<VarDecl>(TargetDecl))
24455 Checker.declareTargetInitializer(TargetDecl);
24456}
24457
24459 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
24460 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
24461 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
24462 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
24463 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
24468
24469 // Process motion-modifiers, flag errors for duplicate modifiers.
24470 unsigned Count = 0;
24471 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24472 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
24473 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24474 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24475 continue;
24476 }
24477 assert(Count < NumberOfOMPMotionModifiers &&
24478 "Modifiers exceed the allowed number of motion modifiers");
24479 Modifiers[Count] = MotionModifiers[I];
24480 ModifiersLoc[Count] = MotionModifiersLoc[I];
24481 ++Count;
24482 }
24483
24484 MappableVarListInfo MVLI(VarList);
24486 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24487 if (MVLI.ProcessedVarList.empty())
24488 return nullptr;
24489 if (IteratorExpr)
24490 if (auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24491 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
24492 DSAStack->addIteratorVarDecl(VD);
24493 return OMPToClause::Create(
24494 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24495 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24496 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
24497 MapperId);
24498}
24499
24501 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
24502 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
24503 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
24504 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
24505 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
24510
24511 // Process motion-modifiers, flag errors for duplicate modifiers.
24512 unsigned Count = 0;
24513 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24514 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
24515 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24516 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24517 continue;
24518 }
24519 assert(Count < NumberOfOMPMotionModifiers &&
24520 "Modifiers exceed the allowed number of motion modifiers");
24521 Modifiers[Count] = MotionModifiers[I];
24522 ModifiersLoc[Count] = MotionModifiersLoc[I];
24523 ++Count;
24524 }
24525
24526 MappableVarListInfo MVLI(VarList);
24527 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
24528 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24529 if (MVLI.ProcessedVarList.empty())
24530 return nullptr;
24531 if (IteratorExpr)
24532 if (auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24533 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
24534 DSAStack->addIteratorVarDecl(VD);
24535 return OMPFromClause::Create(
24536 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24537 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24538 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
24539 MapperId);
24540}
24541
24542OMPClause *
24544 const OMPVarListLocTy &Locs) {
24545 MappableVarListInfo MVLI(VarList);
24546 SmallVector<Expr *, 8> PrivateCopies;
24548
24549 for (Expr *RefExpr : VarList) {
24550 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
24551 SourceLocation ELoc;
24552 SourceRange ERange;
24553 Expr *SimpleRefExpr = RefExpr;
24554 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24555 if (Res.second) {
24556 // It will be analyzed later.
24557 MVLI.ProcessedVarList.push_back(RefExpr);
24558 PrivateCopies.push_back(nullptr);
24559 Inits.push_back(nullptr);
24560 }
24561 ValueDecl *D = Res.first;
24562 if (!D)
24563 continue;
24564
24565 QualType Type = D->getType();
24566 Type = Type.getNonReferenceType().getUnqualifiedType();
24567
24568 auto *VD = dyn_cast<VarDecl>(D);
24569
24570 // Item should be a pointer or reference to pointer.
24571 if (!Type->isPointerType()) {
24572 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
24573 << 0 << RefExpr->getSourceRange();
24574 continue;
24575 }
24576
24577 // Build the private variable and the expression that refers to it.
24578 auto VDPrivate =
24579 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
24580 D->hasAttrs() ? &D->getAttrs() : nullptr,
24581 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
24582 if (VDPrivate->isInvalidDecl())
24583 continue;
24584
24585 SemaRef.CurContext->addDecl(VDPrivate);
24586 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
24587 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
24588
24589 // Add temporary variable to initialize the private copy of the pointer.
24590 VarDecl *VDInit =
24591 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
24592 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
24593 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
24594 SemaRef.AddInitializerToDecl(
24595 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
24596 /*DirectInit=*/false);
24597
24598 // If required, build a capture to implement the privatization initialized
24599 // with the current list item value.
24600 DeclRefExpr *Ref = nullptr;
24601 if (!VD)
24602 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24603 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24604 PrivateCopies.push_back(VDPrivateRefExpr);
24605 Inits.push_back(VDInitRefExpr);
24606
24607 // We need to add a data sharing attribute for this variable to make sure it
24608 // is correctly captured. A variable that shows up in a use_device_ptr has
24609 // similar properties of a first private variable.
24610 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24611
24612 // Create a mappable component for the list item. List items in this clause
24613 // only need a component.
24614 MVLI.VarBaseDeclarations.push_back(D);
24615 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24616 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
24617 /*IsNonContiguous=*/false);
24618 }
24619
24620 if (MVLI.ProcessedVarList.empty())
24621 return nullptr;
24622
24624 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
24625 MVLI.VarBaseDeclarations, MVLI.VarComponents);
24626}
24627
24628OMPClause *
24630 const OMPVarListLocTy &Locs) {
24631 MappableVarListInfo MVLI(VarList);
24632
24633 for (Expr *RefExpr : VarList) {
24634 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
24635 SourceLocation ELoc;
24636 SourceRange ERange;
24637 Expr *SimpleRefExpr = RefExpr;
24638 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24639 /*AllowArraySection=*/true,
24640 /*AllowAssumedSizeArray=*/true);
24641 if (Res.second) {
24642 // It will be analyzed later.
24643 MVLI.ProcessedVarList.push_back(RefExpr);
24644 }
24645 ValueDecl *D = Res.first;
24646 if (!D)
24647 continue;
24648 auto *VD = dyn_cast<VarDecl>(D);
24649
24650 // If required, build a capture to implement the privatization initialized
24651 // with the current list item value.
24652 DeclRefExpr *Ref = nullptr;
24653 if (!VD)
24654 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24655 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24656
24657 // We need to add a data sharing attribute for this variable to make sure it
24658 // is correctly captured. A variable that shows up in a use_device_addr has
24659 // similar properties of a first private variable.
24660 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24661
24662 // Create a mappable component for the list item. List items in this clause
24663 // only need a component.
24664 MVLI.VarBaseDeclarations.push_back(D);
24665 MVLI.VarComponents.emplace_back();
24666 Expr *Component = SimpleRefExpr;
24667 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
24668 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
24669 Component =
24670 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
24671 MVLI.VarComponents.back().emplace_back(Component, D,
24672 /*IsNonContiguous=*/false);
24673 }
24674
24675 if (MVLI.ProcessedVarList.empty())
24676 return nullptr;
24677
24679 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24680 MVLI.VarComponents);
24681}
24682
24683OMPClause *
24685 const OMPVarListLocTy &Locs) {
24686 MappableVarListInfo MVLI(VarList);
24687 for (Expr *RefExpr : VarList) {
24688 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
24689 SourceLocation ELoc;
24690 SourceRange ERange;
24691 Expr *SimpleRefExpr = RefExpr;
24692 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24693 if (Res.second) {
24694 // It will be analyzed later.
24695 MVLI.ProcessedVarList.push_back(RefExpr);
24696 }
24697 ValueDecl *D = Res.first;
24698 if (!D)
24699 continue;
24700
24701 QualType Type = D->getType();
24702 // item should be a pointer or array or reference to pointer or array
24703 if (!Type.getNonReferenceType()->isPointerType() &&
24704 !Type.getNonReferenceType()->isArrayType()) {
24705 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
24706 << 0 << RefExpr->getSourceRange();
24707 continue;
24708 }
24709
24710 // Check if the declaration in the clause does not show up in any data
24711 // sharing attribute.
24712 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24713 if (isOpenMPPrivate(DVar.CKind)) {
24714 unsigned OMPVersion = getLangOpts().OpenMP;
24715 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24716 << getOpenMPClauseNameForDiag(DVar.CKind)
24717 << getOpenMPClauseNameForDiag(OMPC_is_device_ptr)
24718 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
24719 OMPVersion);
24721 continue;
24722 }
24723
24724 const Expr *ConflictExpr;
24725 if (DSAStack->checkMappableExprComponentListsForDecl(
24726 D, /*CurrentRegionOnly=*/true,
24727 [&ConflictExpr](
24729 OpenMPClauseKind) -> bool {
24730 ConflictExpr = R.front().getAssociatedExpression();
24731 return true;
24732 })) {
24733 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24734 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24735 << ConflictExpr->getSourceRange();
24736 continue;
24737 }
24738
24739 // Store the components in the stack so that they can be used to check
24740 // against other clauses later on.
24742 SimpleRefExpr, D, /*IsNonContiguous=*/false);
24743 DSAStack->addMappableExpressionComponents(
24744 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
24745
24746 // Record the expression we've just processed.
24747 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
24748
24749 // Create a mappable component for the list item. List items in this clause
24750 // only need a component. We use a null declaration to signal fields in
24751 // 'this'.
24752 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24753 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24754 "Unexpected device pointer expression!");
24755 MVLI.VarBaseDeclarations.push_back(
24756 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
24757 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24758 MVLI.VarComponents.back().push_back(MC);
24759 }
24760
24761 if (MVLI.ProcessedVarList.empty())
24762 return nullptr;
24763
24765 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24766 MVLI.VarComponents);
24767}
24768
24769OMPClause *
24771 const OMPVarListLocTy &Locs) {
24772 MappableVarListInfo MVLI(VarList);
24773 for (Expr *RefExpr : VarList) {
24774 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
24775 SourceLocation ELoc;
24776 SourceRange ERange;
24777 Expr *SimpleRefExpr = RefExpr;
24778 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24779 /*AllowArraySection=*/true);
24780 if (Res.second) {
24781 // It will be analyzed later.
24782 MVLI.ProcessedVarList.push_back(RefExpr);
24783 }
24784 ValueDecl *D = Res.first;
24785 if (!D)
24786 continue;
24787
24788 // Check if the declaration in the clause does not show up in any data
24789 // sharing attribute.
24790 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24791 if (isOpenMPPrivate(DVar.CKind)) {
24792 unsigned OMPVersion = getLangOpts().OpenMP;
24793 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24794 << getOpenMPClauseNameForDiag(DVar.CKind)
24795 << getOpenMPClauseNameForDiag(OMPC_has_device_addr)
24796 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
24797 OMPVersion);
24799 continue;
24800 }
24801
24802 const Expr *ConflictExpr;
24803 if (DSAStack->checkMappableExprComponentListsForDecl(
24804 D, /*CurrentRegionOnly=*/true,
24805 [&ConflictExpr](
24807 OpenMPClauseKind) -> bool {
24808 ConflictExpr = R.front().getAssociatedExpression();
24809 return true;
24810 })) {
24811 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24812 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24813 << ConflictExpr->getSourceRange();
24814 continue;
24815 }
24816
24817 // Store the components in the stack so that they can be used to check
24818 // against other clauses later on.
24819 Expr *Component = SimpleRefExpr;
24820 auto *VD = dyn_cast<VarDecl>(D);
24821 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
24822 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
24823 Component =
24824 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
24826 Component, D, /*IsNonContiguous=*/false);
24827 DSAStack->addMappableExpressionComponents(
24828 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
24829
24830 // Record the expression we've just processed.
24831 if (!VD && !SemaRef.CurContext->isDependentContext()) {
24832 DeclRefExpr *Ref =
24833 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24834 assert(Ref && "has_device_addr capture failed");
24835 MVLI.ProcessedVarList.push_back(Ref);
24836 } else
24837 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
24838
24839 // Create a mappable component for the list item. List items in this clause
24840 // only need a component. We use a null declaration to signal fields in
24841 // 'this'.
24842 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24843 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24844 "Unexpected device pointer expression!");
24845 MVLI.VarBaseDeclarations.push_back(
24846 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
24847 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24848 MVLI.VarComponents.back().push_back(MC);
24849 }
24850
24851 if (MVLI.ProcessedVarList.empty())
24852 return nullptr;
24853
24855 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24856 MVLI.VarComponents);
24857}
24858
24860 Expr *Allocator, Expr *Alignment,
24861 OpenMPAllocateClauseModifier FirstAllocateModifier,
24862 SourceLocation FirstAllocateModifierLoc,
24863 OpenMPAllocateClauseModifier SecondAllocateModifier,
24864 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
24865 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24866 SourceLocation EndLoc) {
24867 if (Allocator) {
24868 // Allocator expression is dependent - skip it for now and build the
24869 // allocator when instantiated.
24870 bool AllocDependent =
24871 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
24872 Allocator->isInstantiationDependent() ||
24873 Allocator->containsUnexpandedParameterPack());
24874 if (!AllocDependent) {
24875 // OpenMP [2.11.4 allocate Clause, Description]
24876 // allocator is an expression of omp_allocator_handle_t type.
24878 return nullptr;
24879
24880 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
24881 if (AllocatorRes.isInvalid())
24882 return nullptr;
24883 AllocatorRes = SemaRef.PerformImplicitConversion(
24884 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
24886 /*AllowExplicit=*/true);
24887 if (AllocatorRes.isInvalid())
24888 return nullptr;
24889 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
24890 }
24891 } else {
24892 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
24893 // allocate clauses that appear on a target construct or on constructs in a
24894 // target region must specify an allocator expression unless a requires
24895 // directive with the dynamic_allocators clause is present in the same
24896 // compilation unit.
24897 if (getLangOpts().OpenMPIsTargetDevice &&
24898 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
24899 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
24900 }
24901 if (Alignment) {
24902 bool AlignmentDependent = Alignment->isTypeDependent() ||
24903 Alignment->isValueDependent() ||
24904 Alignment->isInstantiationDependent() ||
24906 if (!AlignmentDependent) {
24907 ExprResult AlignResult =
24908 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
24909 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
24910 }
24911 }
24912 // Analyze and build list of variables.
24914 for (Expr *RefExpr : VarList) {
24915 assert(RefExpr && "NULL expr in OpenMP allocate clause.");
24916 SourceLocation ELoc;
24917 SourceRange ERange;
24918 Expr *SimpleRefExpr = RefExpr;
24919 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24920 if (Res.second) {
24921 // It will be analyzed later.
24922 Vars.push_back(RefExpr);
24923 }
24924 ValueDecl *D = Res.first;
24925 if (!D)
24926 continue;
24927
24928 auto *VD = dyn_cast<VarDecl>(D);
24929 DeclRefExpr *Ref = nullptr;
24930 if (!VD && !SemaRef.CurContext->isDependentContext())
24931 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
24932 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
24933 ? RefExpr->IgnoreParens()
24934 : Ref);
24935 }
24936
24937 if (Vars.empty())
24938 return nullptr;
24939
24940 if (Allocator)
24941 DSAStack->addInnerAllocatorExpr(Allocator);
24942
24944 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
24945 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
24946 SecondAllocateModifierLoc, EndLoc, Vars);
24947}
24948
24950 SourceLocation StartLoc,
24951 SourceLocation LParenLoc,
24952 SourceLocation EndLoc) {
24954 for (Expr *RefExpr : VarList) {
24955 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24956 SourceLocation ELoc;
24957 SourceRange ERange;
24958 Expr *SimpleRefExpr = RefExpr;
24959 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24960 if (Res.second)
24961 // It will be analyzed later.
24962 Vars.push_back(RefExpr);
24963 ValueDecl *D = Res.first;
24964 if (!D)
24965 continue;
24966
24967 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
24968 // A list-item cannot appear in more than one nontemporal clause.
24969 if (const Expr *PrevRef =
24970 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
24971 Diag(ELoc, diag::err_omp_used_in_clause_twice)
24972 << 0 << getOpenMPClauseNameForDiag(OMPC_nontemporal) << ERange;
24973 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
24974 << getOpenMPClauseNameForDiag(OMPC_nontemporal);
24975 continue;
24976 }
24977
24978 Vars.push_back(RefExpr);
24979 }
24980
24981 if (Vars.empty())
24982 return nullptr;
24983
24984 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
24985 EndLoc, Vars);
24986}
24987
24989 Stmt *AStmt,
24990 SourceLocation StartLoc,
24991 SourceLocation EndLoc) {
24992 if (!AStmt)
24993 return StmtError();
24994
24995 SemaRef.setFunctionHasBranchProtectedScope();
24996
24997 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
24998 AStmt);
24999}
25000
25002 SourceLocation StartLoc,
25003 SourceLocation LParenLoc,
25004 SourceLocation EndLoc) {
25006 for (Expr *RefExpr : VarList) {
25007 assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
25008 SourceLocation ELoc;
25009 SourceRange ERange;
25010 Expr *SimpleRefExpr = RefExpr;
25011 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25012 /*AllowArraySection=*/true);
25013 if (Res.second)
25014 // It will be analyzed later.
25015 Vars.push_back(RefExpr);
25016 ValueDecl *D = Res.first;
25017 if (!D)
25018 continue;
25019
25020 const DSAStackTy::DSAVarData DVar =
25021 DSAStack->getTopDSA(D, /*FromParent=*/true);
25022 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
25023 // A list item that appears in the inclusive or exclusive clause must appear
25024 // in a reduction clause with the inscan modifier on the enclosing
25025 // worksharing-loop, worksharing-loop SIMD, or simd construct.
25026 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
25027 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25028 << RefExpr->getSourceRange();
25029
25030 if (DSAStack->getParentDirective() != OMPD_unknown)
25031 DSAStack->markDeclAsUsedInScanDirective(D);
25032 Vars.push_back(RefExpr);
25033 }
25034
25035 if (Vars.empty())
25036 return nullptr;
25037
25038 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
25039 EndLoc, Vars);
25040}
25041
25043 SourceLocation StartLoc,
25044 SourceLocation LParenLoc,
25045 SourceLocation EndLoc) {
25047 for (Expr *RefExpr : VarList) {
25048 assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
25049 SourceLocation ELoc;
25050 SourceRange ERange;
25051 Expr *SimpleRefExpr = RefExpr;
25052 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25053 /*AllowArraySection=*/true);
25054 if (Res.second)
25055 // It will be analyzed later.
25056 Vars.push_back(RefExpr);
25057 ValueDecl *D = Res.first;
25058 if (!D)
25059 continue;
25060
25061 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
25062 DSAStackTy::DSAVarData DVar;
25063 if (ParentDirective != OMPD_unknown)
25064 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
25065 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
25066 // A list item that appears in the inclusive or exclusive clause must appear
25067 // in a reduction clause with the inscan modifier on the enclosing
25068 // worksharing-loop, worksharing-loop SIMD, or simd construct.
25069 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
25070 DVar.Modifier != OMPC_REDUCTION_inscan) {
25071 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25072 << RefExpr->getSourceRange();
25073 } else {
25074 DSAStack->markDeclAsUsedInScanDirective(D);
25075 }
25076 Vars.push_back(RefExpr);
25077 }
25078
25079 if (Vars.empty())
25080 return nullptr;
25081
25082 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
25083 EndLoc, Vars);
25084}
25085
25086/// Tries to find omp_alloctrait_t type.
25087static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
25088 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
25089 if (!OMPAlloctraitT.isNull())
25090 return true;
25091 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
25092 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
25093 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
25094 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
25095 return false;
25096 }
25097 Stack->setOMPAlloctraitT(PT.get());
25098 return true;
25099}
25100
25102 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
25104 ASTContext &Context = getASTContext();
25105 // OpenMP [2.12.5, target Construct]
25106 // allocator is an identifier of omp_allocator_handle_t type.
25107 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
25108 return nullptr;
25109 // OpenMP [2.12.5, target Construct]
25110 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
25111 if (llvm::any_of(
25112 Data,
25113 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
25114 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
25115 return nullptr;
25116 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
25117 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
25118 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
25119 StringRef Allocator =
25120 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
25121 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
25122 PredefinedAllocators.insert(SemaRef.LookupSingleName(
25123 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
25124 }
25125
25127 for (const UsesAllocatorsData &D : Data) {
25128 Expr *AllocatorExpr = nullptr;
25129 // Check allocator expression.
25130 if (D.Allocator->isTypeDependent()) {
25131 AllocatorExpr = D.Allocator;
25132 } else {
25133 // Traits were specified - need to assign new allocator to the specified
25134 // allocator, so it must be an lvalue.
25135 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
25136 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
25137 bool IsPredefinedAllocator = false;
25138 if (DRE) {
25139 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
25140 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
25141 IsPredefinedAllocator =
25142 AllocatorTy !=
25143 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
25144 }
25145 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
25146 QualType AllocatorExprType = AllocatorExpr->getType();
25147 bool IsTypeCompatible = IsPredefinedAllocator;
25148 IsTypeCompatible = IsTypeCompatible ||
25149 Context.hasSameUnqualifiedType(AllocatorExprType,
25150 OMPAllocatorHandleT);
25151 IsTypeCompatible =
25152 IsTypeCompatible ||
25153 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
25154 bool IsNonConstantLValue =
25155 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
25156 if (!DRE || !IsTypeCompatible ||
25157 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
25158 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
25159 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
25160 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
25161 continue;
25162 }
25163 // OpenMP [2.12.5, target Construct]
25164 // Predefined allocators appearing in a uses_allocators clause cannot have
25165 // traits specified.
25166 if (IsPredefinedAllocator && D.AllocatorTraits) {
25168 diag::err_omp_predefined_allocator_with_traits)
25170 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
25171 << cast<NamedDecl>(DRE->getDecl())->getName()
25172 << D.Allocator->getSourceRange();
25173 continue;
25174 }
25175 // OpenMP [2.12.5, target Construct]
25176 // Non-predefined allocators appearing in a uses_allocators clause must
25177 // have traits specified.
25178 if (getLangOpts().OpenMP < 52) {
25179 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
25181 diag::err_omp_nonpredefined_allocator_without_traits);
25182 continue;
25183 }
25184 }
25185 // No allocator traits - just convert it to rvalue.
25186 if (!D.AllocatorTraits)
25187 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
25188 DSAStack->addUsesAllocatorsDecl(
25189 DRE->getDecl(),
25190 IsPredefinedAllocator
25191 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
25192 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
25193 }
25194 Expr *AllocatorTraitsExpr = nullptr;
25195 if (D.AllocatorTraits) {
25197 AllocatorTraitsExpr = D.AllocatorTraits;
25198 } else {
25199 // OpenMP [2.12.5, target Construct]
25200 // Arrays that contain allocator traits that appear in a uses_allocators
25201 // clause must be constant arrays, have constant values and be defined
25202 // in the same scope as the construct in which the clause appears.
25203 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
25204 // Check that traits expr is a constant array.
25205 QualType TraitTy;
25206 if (const ArrayType *Ty =
25207 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
25208 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
25209 TraitTy = ConstArrayTy->getElementType();
25210 if (TraitTy.isNull() ||
25211 !(Context.hasSameUnqualifiedType(TraitTy,
25212 DSAStack->getOMPAlloctraitT()) ||
25213 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
25214 /*CompareUnqualified=*/true))) {
25216 diag::err_omp_expected_array_alloctraits)
25217 << AllocatorTraitsExpr->getType();
25218 continue;
25219 }
25220 // Do not map by default allocator traits if it is a standalone
25221 // variable.
25222 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
25223 DSAStack->addUsesAllocatorsDecl(
25224 DRE->getDecl(),
25225 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
25226 }
25227 }
25228 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
25229 NewD.Allocator = AllocatorExpr;
25230 NewD.AllocatorTraits = AllocatorTraitsExpr;
25231 NewD.LParenLoc = D.LParenLoc;
25232 NewD.RParenLoc = D.RParenLoc;
25233 }
25234 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
25235 EndLoc, NewData);
25236}
25237
25239 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
25240 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
25242 for (Expr *RefExpr : Locators) {
25243 assert(RefExpr && "NULL expr in OpenMP affinity clause.");
25244 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
25245 // It will be analyzed later.
25246 Vars.push_back(RefExpr);
25247 continue;
25248 }
25249
25250 SourceLocation ELoc = RefExpr->getExprLoc();
25251 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
25252
25253 if (!SimpleExpr->isLValue()) {
25254 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25255 << 1 << 0 << RefExpr->getSourceRange();
25256 continue;
25257 }
25258
25259 ExprResult Res;
25260 {
25262 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
25263 }
25264 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
25266 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25267 << 1 << 0 << RefExpr->getSourceRange();
25268 continue;
25269 }
25270 Vars.push_back(SimpleExpr);
25271 }
25272
25273 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
25274 ColonLoc, EndLoc, Modifier, Vars);
25275}
25276
25278 SourceLocation KindLoc,
25279 SourceLocation StartLoc,
25280 SourceLocation LParenLoc,
25281 SourceLocation EndLoc) {
25282 if (Kind == OMPC_BIND_unknown) {
25283 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
25284 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
25285 /*Last=*/unsigned(OMPC_BIND_unknown))
25286 << getOpenMPClauseNameForDiag(OMPC_bind);
25287 return nullptr;
25288 }
25289
25290 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
25291 LParenLoc, EndLoc);
25292}
25293
25295 SourceLocation StartLoc,
25296 SourceLocation LParenLoc,
25297 SourceLocation EndLoc) {
25298 Expr *ValExpr = Size;
25299 Stmt *HelperValStmt = nullptr;
25300
25301 // OpenMP [2.5, Restrictions]
25302 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
25303 // value.
25304 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
25305 /*StrictlyPositive=*/false))
25306 return nullptr;
25307
25308 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
25310 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
25311 if (CaptureRegion != OMPD_unknown &&
25312 !SemaRef.CurContext->isDependentContext()) {
25313 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
25314 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25315 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
25316 HelperValStmt = buildPreInits(getASTContext(), Captures);
25317 }
25318
25320 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
25321}
25322
25326 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
25327 SourceLocation M2Loc, SourceLocation EndLoc) {
25328
25329 if ((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ||
25331 std::string Values = getListOfPossibleValues(
25332 OMPC_dyn_groupprivate, /*First=*/0, OMPC_DYN_GROUPPRIVATE_unknown);
25333 Diag((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ? M1Loc
25334 : M2Loc,
25335 diag::err_omp_unexpected_clause_value)
25336 << Values << getOpenMPClauseName(OMPC_dyn_groupprivate);
25337 return nullptr;
25338 }
25339
25340 Expr *ValExpr = Size;
25341 Stmt *HelperValStmt = nullptr;
25342
25343 // OpenMP [2.5, Restrictions]
25344 // The dyn_groupprivate expression must evaluate to a positive integer
25345 // value.
25346 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_dyn_groupprivate,
25347 /*StrictlyPositive=*/false))
25348 return nullptr;
25349
25350 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
25352 DKind, OMPC_dyn_groupprivate, getLangOpts().OpenMP);
25353 if (CaptureRegion != OMPD_unknown &&
25354 !SemaRef.CurContext->isDependentContext()) {
25355 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
25356 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25357 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
25358 HelperValStmt = buildPreInits(getASTContext(), Captures);
25359 }
25360
25362 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
25363 M1Loc, M2, M2Loc);
25364}
25365
25368 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
25369 SourceLocation LParenLoc, SourceLocation EndLoc) {
25370
25371 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
25372 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
25373 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
25374 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
25375 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
25376 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_doacross);
25377 return nullptr;
25378 }
25379
25381 DSAStackTy::OperatorOffsetTy OpsOffs;
25382 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
25383 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
25384 SemaRef,
25385 DepType == OMPC_DOACROSS_source ||
25386 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
25387 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
25388 VarList, DSAStack, EndLoc);
25389 Vars = VarOffset.Vars;
25390 OpsOffs = VarOffset.OpsOffs;
25391 TotalDepCount = VarOffset.TotalDepCount;
25392 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
25393 EndLoc, DepType, DepLoc, ColonLoc, Vars,
25394 TotalDepCount.getZExtValue());
25395 if (DSAStack->isParentOrderedRegion())
25396 DSAStack->addDoacrossDependClause(C, OpsOffs);
25397 return C;
25398}
25399
25401 SourceLocation StartLoc,
25402 SourceLocation LParenLoc,
25403 SourceLocation EndLoc) {
25404 return new (getASTContext())
25405 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
25406}
25407
25409 SourceLocation EndLoc) {
25410 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
25411}
25412
25414 SourceLocation LParenLoc,
25415 SourceLocation EndLoc) {
25416 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
25417}
25418
25422 switch (CK) {
25423 case OMPC_absent:
25424 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
25425 case OMPC_contains:
25426 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
25427 default:
25428 llvm_unreachable("Unexpected OpenMP clause");
25429 }
25430}
25431
25433 SourceLocation Loc,
25434 SourceLocation RLoc) {
25435 switch (CK) {
25436 case OMPC_no_openmp:
25437 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
25438 case OMPC_no_openmp_routines:
25439 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
25440 case OMPC_no_parallelism:
25441 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
25442 case OMPC_no_openmp_constructs:
25443 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
25444 default:
25445 llvm_unreachable("Unexpected OpenMP clause");
25446 }
25447}
25448
25450 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
25451 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
25452 Expr *Stride, SourceLocation RBLoc) {
25453 ASTContext &Context = getASTContext();
25454 if (Base->hasPlaceholderType() &&
25455 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25456 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
25457 if (Result.isInvalid())
25458 return ExprError();
25459 Base = Result.get();
25460 }
25461 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
25462 ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
25463 if (Result.isInvalid())
25464 return ExprError();
25465 Result = SemaRef.DefaultLvalueConversion(Result.get());
25466 if (Result.isInvalid())
25467 return ExprError();
25468 LowerBound = Result.get();
25469 }
25470 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
25471 ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
25472 if (Result.isInvalid())
25473 return ExprError();
25474 Result = SemaRef.DefaultLvalueConversion(Result.get());
25475 if (Result.isInvalid())
25476 return ExprError();
25477 Length = Result.get();
25478 }
25479 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
25480 ExprResult Result = SemaRef.CheckPlaceholderExpr(Stride);
25481 if (Result.isInvalid())
25482 return ExprError();
25483 Result = SemaRef.DefaultLvalueConversion(Result.get());
25484 if (Result.isInvalid())
25485 return ExprError();
25486 Stride = Result.get();
25487 }
25488
25489 // Build an unanalyzed expression if either operand is type-dependent.
25490 if (Base->isTypeDependent() ||
25491 (LowerBound &&
25492 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
25493 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
25494 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
25495 return new (Context) ArraySectionExpr(
25496 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
25497 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25498 }
25499
25500 // Perform default conversions.
25502 QualType ResultTy;
25503 if (OriginalTy->isAnyPointerType()) {
25504 ResultTy = OriginalTy->getPointeeType();
25505 } else if (OriginalTy->isArrayType()) {
25506 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
25507 } else {
25508 return ExprError(
25509 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
25510 << Base->getSourceRange());
25511 }
25512 // C99 6.5.2.1p1
25513 if (LowerBound) {
25514 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
25515 LowerBound);
25516 if (Res.isInvalid())
25517 return ExprError(Diag(LowerBound->getExprLoc(),
25518 diag::err_omp_typecheck_section_not_integer)
25519 << 0 << LowerBound->getSourceRange());
25520 LowerBound = Res.get();
25521
25522 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25523 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25524 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
25525 << 0 << LowerBound->getSourceRange();
25526 }
25527 if (Length) {
25528 auto Res =
25529 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
25530 if (Res.isInvalid())
25531 return ExprError(Diag(Length->getExprLoc(),
25532 diag::err_omp_typecheck_section_not_integer)
25533 << 1 << Length->getSourceRange());
25534 Length = Res.get();
25535
25536 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25537 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25538 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
25539 << 1 << Length->getSourceRange();
25540 }
25541 if (Stride) {
25542 ExprResult Res =
25544 if (Res.isInvalid())
25545 return ExprError(Diag(Stride->getExprLoc(),
25546 diag::err_omp_typecheck_section_not_integer)
25547 << 1 << Stride->getSourceRange());
25548 Stride = Res.get();
25549
25550 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25551 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25552 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
25553 << 1 << Stride->getSourceRange();
25554 }
25555
25556 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
25557 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
25558 // type. Note that functions are not objects, and that (in C99 parlance)
25559 // incomplete types are not object types.
25560 if (ResultTy->isFunctionType()) {
25561 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
25562 << ResultTy << Base->getSourceRange();
25563 return ExprError();
25564 }
25565
25566 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
25567 diag::err_omp_section_incomplete_type, Base))
25568 return ExprError();
25569
25570 if (LowerBound && !OriginalTy->isAnyPointerType()) {
25572 if (LowerBound->EvaluateAsInt(Result, Context)) {
25573 // OpenMP 5.0, [2.1.5 Array Sections]
25574 // The array section must be a subset of the original array.
25575 llvm::APSInt LowerBoundValue = Result.Val.getInt();
25576 if (LowerBoundValue.isNegative()) {
25577 Diag(LowerBound->getExprLoc(),
25578 diag::err_omp_section_not_subset_of_array)
25579 << LowerBound->getSourceRange();
25580 return ExprError();
25581 }
25582 }
25583 }
25584
25585 if (Length) {
25587 if (Length->EvaluateAsInt(Result, Context)) {
25588 // OpenMP 5.0, [2.1.5 Array Sections]
25589 // The length must evaluate to non-negative integers.
25590 llvm::APSInt LengthValue = Result.Val.getInt();
25591 if (LengthValue.isNegative()) {
25592 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
25593 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
25594 << Length->getSourceRange();
25595 return ExprError();
25596 }
25597 }
25598 } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
25599 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
25600 !OriginalTy->isVariableArrayType()))) {
25601 // OpenMP 5.0, [2.1.5 Array Sections]
25602 // When the size of the array dimension is not known, the length must be
25603 // specified explicitly.
25604 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
25605 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
25606 return ExprError();
25607 }
25608
25609 if (Stride) {
25611 if (Stride->EvaluateAsInt(Result, Context)) {
25612 // OpenMP 5.0, [2.1.5 Array Sections]
25613 // The stride must evaluate to a positive integer.
25614 llvm::APSInt StrideValue = Result.Val.getInt();
25615 if (!StrideValue.isStrictlyPositive()) {
25616 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
25617 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
25618 << Stride->getSourceRange();
25619 return ExprError();
25620 }
25621 }
25622 }
25623
25624 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25625 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
25626 if (Result.isInvalid())
25627 return ExprError();
25628 Base = Result.get();
25629 }
25630 return new (Context) ArraySectionExpr(
25631 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
25632 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25633}
25634
25636 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
25637 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
25638 ASTContext &Context = getASTContext();
25639 if (Base->hasPlaceholderType()) {
25640 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
25641 if (Result.isInvalid())
25642 return ExprError();
25643 Result = SemaRef.DefaultLvalueConversion(Result.get());
25644 if (Result.isInvalid())
25645 return ExprError();
25646 Base = Result.get();
25647 }
25648 QualType BaseTy = Base->getType();
25649 // Delay analysis of the types/expressions if instantiation/specialization is
25650 // required.
25651 if (!BaseTy->isPointerType() && Base->isTypeDependent())
25652 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
25653 LParenLoc, RParenLoc, Dims, Brackets);
25654 if (!BaseTy->isPointerType() ||
25655 (!Base->isTypeDependent() &&
25656 BaseTy->getPointeeType()->isIncompleteType()))
25657 return ExprError(Diag(Base->getExprLoc(),
25658 diag::err_omp_non_pointer_type_array_shaping_base)
25659 << Base->getSourceRange());
25660
25661 SmallVector<Expr *, 4> NewDims;
25662 bool ErrorFound = false;
25663 for (Expr *Dim : Dims) {
25664 if (Dim->hasPlaceholderType()) {
25665 ExprResult Result = SemaRef.CheckPlaceholderExpr(Dim);
25666 if (Result.isInvalid()) {
25667 ErrorFound = true;
25668 continue;
25669 }
25670 Result = SemaRef.DefaultLvalueConversion(Result.get());
25671 if (Result.isInvalid()) {
25672 ErrorFound = true;
25673 continue;
25674 }
25675 Dim = Result.get();
25676 }
25677 if (!Dim->isTypeDependent()) {
25680 if (Result.isInvalid()) {
25681 ErrorFound = true;
25682 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
25683 << Dim->getSourceRange();
25684 continue;
25685 }
25686 Dim = Result.get();
25687 Expr::EvalResult EvResult;
25688 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
25689 // OpenMP 5.0, [2.1.4 Array Shaping]
25690 // Each si is an integral type expression that must evaluate to a
25691 // positive integer.
25692 llvm::APSInt Value = EvResult.Val.getInt();
25693 if (!Value.isStrictlyPositive()) {
25694 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
25695 << toString(Value, /*Radix=*/10, /*Signed=*/true)
25696 << Dim->getSourceRange();
25697 ErrorFound = true;
25698 continue;
25699 }
25700 }
25701 }
25702 NewDims.push_back(Dim);
25703 }
25704 if (ErrorFound)
25705 return ExprError();
25706 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
25707 LParenLoc, RParenLoc, NewDims, Brackets);
25708}
25709
25711 SourceLocation IteratorKwLoc,
25712 SourceLocation LLoc,
25713 SourceLocation RLoc,
25715 ASTContext &Context = getASTContext();
25717 bool IsCorrect = true;
25718 for (const OMPIteratorData &D : Data) {
25719 TypeSourceInfo *TInfo = nullptr;
25720 SourceLocation StartLoc;
25721 QualType DeclTy;
25722 if (!D.Type.getAsOpaquePtr()) {
25723 // OpenMP 5.0, 2.1.6 Iterators
25724 // In an iterator-specifier, if the iterator-type is not specified then
25725 // the type of that iterator is of int type.
25726 DeclTy = Context.IntTy;
25727 StartLoc = D.DeclIdentLoc;
25728 } else {
25729 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
25730 StartLoc = TInfo->getTypeLoc().getBeginLoc();
25731 }
25732
25733 bool IsDeclTyDependent = DeclTy->isDependentType() ||
25734 DeclTy->containsUnexpandedParameterPack() ||
25735 DeclTy->isInstantiationDependentType();
25736 if (!IsDeclTyDependent) {
25737 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
25738 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
25739 // The iterator-type must be an integral or pointer type.
25740 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25741 << DeclTy;
25742 IsCorrect = false;
25743 continue;
25744 }
25745 if (DeclTy.isConstant(Context)) {
25746 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
25747 // The iterator-type must not be const qualified.
25748 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25749 << DeclTy;
25750 IsCorrect = false;
25751 continue;
25752 }
25753 }
25754
25755 // Iterator declaration.
25756 assert(D.DeclIdent && "Identifier expected.");
25757 // Always try to create iterator declarator to avoid extra error messages
25758 // about unknown declarations use.
25759 auto *VD =
25760 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
25761 D.DeclIdent, DeclTy, TInfo, SC_None);
25762 VD->setImplicit();
25763 if (S) {
25764 // Check for conflicting previous declaration.
25765 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
25768 Previous.suppressDiagnostics();
25769 SemaRef.LookupName(Previous, S);
25770
25771 SemaRef.FilterLookupForScope(Previous, SemaRef.CurContext, S,
25772 /*ConsiderLinkage=*/false,
25773 /*AllowInlineNamespace=*/false);
25774 if (!Previous.empty()) {
25775 NamedDecl *Old = Previous.getRepresentativeDecl();
25776 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
25777 Diag(Old->getLocation(), diag::note_previous_definition);
25778 } else {
25779 SemaRef.PushOnScopeChains(VD, S);
25780 }
25781 } else {
25782 SemaRef.CurContext->addDecl(VD);
25783 }
25784
25785 /// Act on the iterator variable declaration.
25787
25788 Expr *Begin = D.Range.Begin;
25789 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
25790 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
25791 Begin, DeclTy, AssignmentAction::Converting);
25792 Begin = BeginRes.get();
25793 }
25794 Expr *End = D.Range.End;
25795 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
25796 ExprResult EndRes = SemaRef.PerformImplicitConversion(
25797 End, DeclTy, AssignmentAction::Converting);
25798 End = EndRes.get();
25799 }
25800 Expr *Step = D.Range.Step;
25801 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
25802 if (!Step->getType()->isIntegralType(Context)) {
25803 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
25804 << Step << Step->getSourceRange();
25805 IsCorrect = false;
25806 continue;
25807 }
25808 std::optional<llvm::APSInt> Result =
25809 Step->getIntegerConstantExpr(Context);
25810 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
25811 // If the step expression of a range-specification equals zero, the
25812 // behavior is unspecified.
25813 if (Result && Result->isZero()) {
25814 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
25815 << Step << Step->getSourceRange();
25816 IsCorrect = false;
25817 continue;
25818 }
25819 }
25820 if (!Begin || !End || !IsCorrect) {
25821 IsCorrect = false;
25822 continue;
25823 }
25824 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
25825 IDElem.IteratorDecl = VD;
25826 IDElem.AssignmentLoc = D.AssignLoc;
25827 IDElem.Range.Begin = Begin;
25828 IDElem.Range.End = End;
25829 IDElem.Range.Step = Step;
25830 IDElem.ColonLoc = D.ColonLoc;
25831 IDElem.SecondColonLoc = D.SecColonLoc;
25832 }
25833 if (!IsCorrect) {
25834 // Invalidate all created iterator declarations if error is found.
25835 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
25836 if (Decl *ID = D.IteratorDecl)
25837 ID->setInvalidDecl();
25838 }
25839 return ExprError();
25840 }
25842 if (!SemaRef.CurContext->isDependentContext()) {
25843 // Build number of ityeration for each iteration range.
25844 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
25845 // ((Begini-Stepi-1-Endi) / -Stepi);
25847 // (Endi - Begini)
25848 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
25849 D.Range.End, D.Range.Begin);
25850 if (!Res.isUsable()) {
25851 IsCorrect = false;
25852 continue;
25853 }
25854 ExprResult St, St1;
25855 if (D.Range.Step) {
25856 St = D.Range.Step;
25857 // (Endi - Begini) + Stepi
25858 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
25859 St.get());
25860 if (!Res.isUsable()) {
25861 IsCorrect = false;
25862 continue;
25863 }
25864 // (Endi - Begini) + Stepi - 1
25865 Res = SemaRef.CreateBuiltinBinOp(
25866 D.AssignmentLoc, BO_Sub, Res.get(),
25867 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25868 if (!Res.isUsable()) {
25869 IsCorrect = false;
25870 continue;
25871 }
25872 // ((Endi - Begini) + Stepi - 1) / Stepi
25873 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
25874 St.get());
25875 if (!Res.isUsable()) {
25876 IsCorrect = false;
25877 continue;
25878 }
25879 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
25880 D.Range.Step);
25881 // (Begini - Endi)
25882 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
25883 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
25884 if (!Res1.isUsable()) {
25885 IsCorrect = false;
25886 continue;
25887 }
25888 // (Begini - Endi) - Stepi
25889 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
25890 St1.get());
25891 if (!Res1.isUsable()) {
25892 IsCorrect = false;
25893 continue;
25894 }
25895 // (Begini - Endi) - Stepi - 1
25896 Res1 = SemaRef.CreateBuiltinBinOp(
25897 D.AssignmentLoc, BO_Sub, Res1.get(),
25898 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25899 if (!Res1.isUsable()) {
25900 IsCorrect = false;
25901 continue;
25902 }
25903 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
25904 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
25905 St1.get());
25906 if (!Res1.isUsable()) {
25907 IsCorrect = false;
25908 continue;
25909 }
25910 // Stepi > 0.
25911 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
25912 D.AssignmentLoc, BO_GT, D.Range.Step,
25913 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
25914 if (!CmpRes.isUsable()) {
25915 IsCorrect = false;
25916 continue;
25917 }
25918 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
25919 CmpRes.get(), Res.get(), Res1.get());
25920 if (!Res.isUsable()) {
25921 IsCorrect = false;
25922 continue;
25923 }
25924 }
25925 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
25926 if (!Res.isUsable()) {
25927 IsCorrect = false;