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
14#include "clang/Sema/SemaOpenMP.h"
15#include "clang/AST/ASTConsumer.h"
16
17#include "TreeTransform.h"
18#include "clang/AST/ASTContext.h"
19#include "clang/AST/ASTMutationListener.h"
20#include "clang/AST/Attr.h"
21#include "clang/AST/CXXInheritance.h"
22#include "clang/AST/Decl.h"
23#include "clang/AST/DeclCXX.h"
24#include "clang/AST/DeclOpenMP.h"
25#include "clang/AST/DynamicRecursiveASTVisitor.h"
26#include "clang/AST/OpenMPClause.h"
27#include "clang/AST/RecursiveASTVisitor.h"
28#include "clang/AST/Stmt.h"
29#include "clang/AST/StmtCXX.h"
30#include "clang/AST/StmtOpenMP.h"
31#include "clang/AST/StmtVisitor.h"
32#include "clang/Basic/DiagnosticSema.h"
33#include "clang/Basic/OpenMPKinds.h"
34#include "clang/Basic/PartialDiagnostic.h"
35#include "clang/Basic/TargetInfo.h"
36#include "clang/Sema/EnterExpressionEvaluationContext.h"
37#include "clang/Sema/Initialization.h"
38#include "clang/Sema/Lookup.h"
39#include "clang/Sema/ParsedAttr.h"
40#include "clang/Sema/Scope.h"
41#include "clang/Sema/ScopeInfo.h"
42#include "clang/Sema/Sema.h"
43#include "llvm/ADT/IndexedMap.h"
44#include "llvm/ADT/PointerEmbeddedInt.h"
45#include "llvm/ADT/STLExtras.h"
46#include "llvm/ADT/Sequence.h"
47#include "llvm/ADT/SetVector.h"
48#include "llvm/ADT/SmallSet.h"
49#include "llvm/ADT/StringExtras.h"
50#include "llvm/Frontend/OpenMP/OMPAssume.h"
51#include "llvm/Frontend/OpenMP/OMPConstants.h"
52#include "llvm/Frontend/OpenMP/OMPVersion.h"
53#include "llvm/IR/Assumptions.h"
54#include <limits>
55#include <optional>
56
57using namespace clang;
58using namespace llvm::omp;
59
60//===----------------------------------------------------------------------===//
61// Stack of data-sharing attributes for variables
62//===----------------------------------------------------------------------===//
63
64static const Expr *checkMapClauseExpressionBase(
65 Sema &SemaRef, Expr *E,
66 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
67 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
68
69static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C);
70
71namespace {
72/// Default data sharing attributes, which can be applied to directive.
73enum DefaultDataSharingAttributes {
74 DSA_unspecified = 0, /// Data sharing attribute not specified.
75 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
76 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
77 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
78 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
79};
80
81/// Variable Category attributes to restrict the modifier of the
82/// default clause (DefaultDataSharingAttributes)
83/// Not mentioning any Variable category attribute indicates
84/// the modifier (DefaultDataSharingAttributes) is for all variables.
85enum DefaultDataSharingVCAttributes {
86 DSA_VC_all = 0, /// for all variables.
87 DSA_VC_aggregate, /// for aggregate variables.
88 DSA_VC_pointer, /// for pointer variables.
89 DSA_VC_scalar, /// for scalar variables.
90};
91
92/// Stack for tracking declarations used in OpenMP directives and
93/// clauses and their data-sharing attributes.
94class DSAStackTy {
95public:
96 struct DSAVarData {
97 OpenMPDirectiveKind DKind = OMPD_unknown;
98 OpenMPClauseKind CKind = OMPC_unknown;
99 unsigned Modifier = 0;
100 const Expr *RefExpr = nullptr;
101 DeclRefExpr *PrivateCopy = nullptr;
102 SourceLocation ImplicitDSALoc;
103 bool AppliedToPointee = false;
104 DSAVarData() = default;
105 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
106 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
107 SourceLocation ImplicitDSALoc, unsigned Modifier,
108 bool AppliedToPointee)
109 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
110 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
111 AppliedToPointee(AppliedToPointee) {}
112 };
113 using OperatorOffsetTy =
114 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
115 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
116 /// Kind of the declaration used in the uses_allocators clauses.
117 enum class UsesAllocatorsDeclKind {
118 /// Predefined allocator
119 PredefinedAllocator,
120 /// User-defined allocator
121 UserDefinedAllocator,
122 /// The declaration that represent allocator trait
123 AllocatorTrait,
124 };
125
126private:
127 struct DSAInfo {
128 OpenMPClauseKind Attributes = OMPC_unknown;
129 unsigned Modifier = 0;
130 /// Pointer to a reference expression and a flag which shows that the
131 /// variable is marked as lastprivate(true) or not (false).
132 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
133 DeclRefExpr *PrivateCopy = nullptr;
134 /// true if the attribute is applied to the pointee, not the variable
135 /// itself.
136 bool AppliedToPointee = false;
137 };
138 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
139 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
140 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
141 using LoopControlVariablesMapTy =
142 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
143 /// Struct that associates a component with the clause kind where they are
144 /// found.
145 struct MappedExprComponentTy {
146 OMPClauseMappableExprCommon::MappableExprComponentLists Components;
147 OpenMPClauseKind Kind = OMPC_unknown;
148 };
149 using MappedExprComponentsTy =
150 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
151 using CriticalsWithHintsTy =
152 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
153 struct ReductionData {
154 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
155 SourceRange ReductionRange;
156 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
157 ReductionData() = default;
158 void set(BinaryOperatorKind BO, SourceRange RR) {
159 ReductionRange = RR;
160 ReductionOp = BO;
161 }
162 void set(const Expr *RefExpr, SourceRange RR) {
163 ReductionRange = RR;
164 ReductionOp = RefExpr;
165 }
166 };
167 using DeclReductionMapTy =
168 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
169 struct DefaultmapInfo {
170 OpenMPDefaultmapClauseModifier ImplicitBehavior =
171 OMPC_DEFAULTMAP_MODIFIER_unknown;
172 SourceLocation SLoc;
173 DefaultmapInfo() = default;
174 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
175 : ImplicitBehavior(M), SLoc(Loc) {}
176 };
177
178 struct SharingMapTy {
179 DeclSAMapTy SharingMap;
180 DeclReductionMapTy ReductionMap;
181 UsedRefMapTy AlignedMap;
182 UsedRefMapTy NontemporalMap;
183 MappedExprComponentsTy MappedExprComponents;
184 LoopControlVariablesMapTy LCVMap;
185 /// Track DecompositionDecls and their data-sharing attributes to detect
186 /// conflicting clauses on bindings from the same decomposition.
187 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
188 SourceLocation DefaultAttrLoc;
189 DefaultDataSharingVCAttributes DefaultVCAttr = DSA_VC_all;
190 SourceLocation DefaultAttrVCLoc;
191 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
192 OpenMPDirectiveKind Directive = OMPD_unknown;
193 DeclarationNameInfo DirectiveName;
194 Scope *CurScope = nullptr;
195 DeclContext *Context = nullptr;
196 SourceLocation ConstructLoc;
197 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
198 /// get the data (loop counters etc.) about enclosing loop-based construct.
199 /// This data is required during codegen.
200 DoacrossClauseMapTy DoacrossDepends;
201 /// First argument (Expr *) contains optional argument of the
202 /// 'ordered' clause, the second one is true if the regions has 'ordered'
203 /// clause, false otherwise.
204 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
205 bool RegionHasOrderConcurrent = false;
206 unsigned AssociatedLoops = 1;
207 bool HasMutipleLoops = false;
208 const Decl *PossiblyLoopCounter = nullptr;
209 bool NowaitRegion = false;
210 bool UntiedRegion = false;
211 bool CancelRegion = false;
212 bool LoopStart = false;
213 bool BodyComplete = false;
214 SourceLocation PrevScanLocation;
215 SourceLocation PrevOrderedLocation;
216 SourceLocation InnerTeamsRegionLoc;
217 /// Reference to the taskgroup task_reduction reference expression.
218 Expr *TaskgroupReductionRef = nullptr;
219 llvm::DenseSet<QualType> MappedClassesQualTypes;
220 SmallVector<Expr *, 4> InnerUsedAllocators;
221 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
222 /// List of globals marked as declare target link in this target region
223 /// (isOpenMPTargetExecutionDirective(Directive) == true).
224 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
225 /// List of decls used in inclusive/exclusive clauses of the scan directive.
226 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
227 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
228 UsesAllocatorsDecls;
229 /// Data is required on creating capture fields for implicit
230 /// default first|private clause.
231 struct ImplicitDefaultFDInfoTy {
232 /// Field decl.
233 const FieldDecl *FD = nullptr;
234 /// Nesting stack level
235 size_t StackLevel = 0;
236 /// Capture variable decl.
237 VarDecl *VD = nullptr;
238 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
239 VarDecl *VD)
240 : FD(FD), StackLevel(StackLevel), VD(VD) {}
241 };
242 /// List of captured fields
243 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
244 ImplicitDefaultFirstprivateFDs;
245 Expr *DeclareMapperVar = nullptr;
246 SmallVector<VarDecl *, 16> IteratorVarDecls;
247 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
248 Scope *CurScope, SourceLocation Loc)
249 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
250 ConstructLoc(Loc) {}
251 SharingMapTy() = default;
252 };
253
254 using StackTy = SmallVector<SharingMapTy, 4>;
255
256 /// Stack of used declaration and their data-sharing attributes.
257 DeclSAMapTy Threadprivates;
258 DeclSAMapTy Groupprivates;
259 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
260 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
261 /// true, if check for DSA must be from parent directive, false, if
262 /// from current directive.
263 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
264 Sema &SemaRef;
265 bool ForceCapturing = false;
266 /// true if all the variables in the target executable directives must be
267 /// captured by reference.
268 bool ForceCaptureByReferenceInTargetExecutable = false;
269 CriticalsWithHintsTy Criticals;
270 unsigned IgnoredStackElements = 0;
271
272 /// Iterators over the stack iterate in order from innermost to outermost
273 /// directive.
274 using const_iterator = StackTy::const_reverse_iterator;
275 const_iterator begin() const {
276 return Stack.empty() ? const_iterator()
277 : Stack.back().first.rbegin() + IgnoredStackElements;
278 }
279 const_iterator end() const {
280 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
281 }
282 using iterator = StackTy::reverse_iterator;
283 iterator begin() {
284 return Stack.empty() ? iterator()
285 : Stack.back().first.rbegin() + IgnoredStackElements;
286 }
287 iterator end() {
288 return Stack.empty() ? iterator() : Stack.back().first.rend();
289 }
290
291 // Convenience operations to get at the elements of the stack.
292
293 bool isStackEmpty() const {
294 return Stack.empty() ||
295 Stack.back().second != CurrentNonCapturingFunctionScope ||
296 Stack.back().first.size() <= IgnoredStackElements;
297 }
298 size_t getStackSize() const {
299 return isStackEmpty() ? 0
300 : Stack.back().first.size() - IgnoredStackElements;
301 }
302
303 SharingMapTy *getTopOfStackOrNull() {
304 size_t Size = getStackSize();
305 if (Size == 0)
306 return nullptr;
307 return &Stack.back().first[Size - 1];
308 }
309 const SharingMapTy *getTopOfStackOrNull() const {
310 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
311 }
312 SharingMapTy &getTopOfStack() {
313 assert(!isStackEmpty() && "no current directive");
314 return *getTopOfStackOrNull();
315 }
316 const SharingMapTy &getTopOfStack() const {
317 return const_cast<DSAStackTy &>(*this).getTopOfStack();
318 }
319
320 SharingMapTy *getSecondOnStackOrNull() {
321 size_t Size = getStackSize();
322 if (Size <= 1)
323 return nullptr;
324 return &Stack.back().first[Size - 2];
325 }
326 const SharingMapTy *getSecondOnStackOrNull() const {
327 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
328 }
329
330 /// Get the stack element at a certain level (previously returned by
331 /// \c getNestingLevel).
332 ///
333 /// Note that nesting levels count from outermost to innermost, and this is
334 /// the reverse of our iteration order where new inner levels are pushed at
335 /// the front of the stack.
336 SharingMapTy &getStackElemAtLevel(unsigned Level) {
337 assert(Level < getStackSize() && "no such stack element");
338 return Stack.back().first[Level];
339 }
340 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
341 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
342 }
343
344 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
345
346 /// Checks if the variable is a local for OpenMP region.
347 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
348
349 /// Vector of previously declared requires directives
350 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
351 /// omp_allocator_handle_t type.
352 QualType OMPAllocatorHandleT;
353 /// omp_depend_t type.
354 QualType OMPDependT;
355 /// omp_event_handle_t type.
356 QualType OMPEventHandleT;
357 /// omp_alloctrait_t type.
358 QualType OMPAlloctraitT;
359 /// Expression for the predefined allocators.
360 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
361 nullptr};
362 /// Vector of previously encountered target directives
363 SmallVector<SourceLocation, 2> TargetLocations;
364 SourceLocation AtomicLocation;
365 /// Vector of declare variant construct traits.
366 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
367
368public:
369 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
370
371 /// Sets omp_allocator_handle_t type.
372 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
373 /// Gets omp_allocator_handle_t type.
374 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
375 /// Sets omp_alloctrait_t type.
376 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
377 /// Gets omp_alloctrait_t type.
378 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
379 /// Sets the given default allocator.
380 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
381 Expr *Allocator) {
382 OMPPredefinedAllocators[AllocatorKind] = Allocator;
383 }
384 /// Returns the specified default allocator.
385 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
386 return OMPPredefinedAllocators[AllocatorKind];
387 }
388 /// Sets omp_depend_t type.
389 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
390 /// Gets omp_depend_t type.
391 QualType getOMPDependT() const { return OMPDependT; }
392
393 /// Sets omp_event_handle_t type.
394 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
395 /// Gets omp_event_handle_t type.
396 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
397
398 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
399 OpenMPClauseKind getClauseParsingMode() const {
400 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
401 return ClauseKindMode;
402 }
403 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
404
405 bool isBodyComplete() const {
406 const SharingMapTy *Top = getTopOfStackOrNull();
407 return Top && Top->BodyComplete;
408 }
409 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
410
411 bool isForceVarCapturing() const { return ForceCapturing; }
412 void setForceVarCapturing(bool V) { ForceCapturing = V; }
413
414 void setForceCaptureByReferenceInTargetExecutable(bool V) {
415 ForceCaptureByReferenceInTargetExecutable = V;
416 }
417 bool isForceCaptureByReferenceInTargetExecutable() const {
418 return ForceCaptureByReferenceInTargetExecutable;
419 }
420
421 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
422 Scope *CurScope, SourceLocation Loc) {
423 assert(!IgnoredStackElements &&
424 "cannot change stack while ignoring elements");
425 if (Stack.empty() ||
426 Stack.back().second != CurrentNonCapturingFunctionScope)
427 Stack.emplace_back(Args: StackTy(), Args&: CurrentNonCapturingFunctionScope);
428 Stack.back().first.emplace_back(Args&: DKind, Args: DirName, Args&: CurScope, Args&: Loc);
429 Stack.back().first.back().DefaultAttrLoc = Loc;
430 }
431
432 void pop() {
433 assert(!IgnoredStackElements &&
434 "cannot change stack while ignoring elements");
435 assert(!Stack.back().first.empty() &&
436 "Data-sharing attributes stack is empty!");
437 Stack.back().first.pop_back();
438 }
439
440 /// RAII object to temporarily leave the scope of a directive when we want to
441 /// logically operate in its parent.
442 class ParentDirectiveScope {
443 DSAStackTy &Self;
444 bool Active;
445
446 public:
447 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
448 : Self(Self), Active(false) {
449 if (Activate)
450 enable();
451 }
452 ~ParentDirectiveScope() { disable(); }
453 void disable() {
454 if (Active) {
455 --Self.IgnoredStackElements;
456 Active = false;
457 }
458 }
459 void enable() {
460 if (!Active) {
461 ++Self.IgnoredStackElements;
462 Active = true;
463 }
464 }
465 };
466
467 /// Marks that we're started loop parsing.
468 void loopInit() {
469 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
470 "Expected loop-based directive.");
471 getTopOfStack().LoopStart = true;
472 }
473 /// Start capturing of the variables in the loop context.
474 void loopStart() {
475 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
476 "Expected loop-based directive.");
477 getTopOfStack().LoopStart = false;
478 }
479 /// true, if variables are captured, false otherwise.
480 bool isLoopStarted() const {
481 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
482 "Expected loop-based directive.");
483 return !getTopOfStack().LoopStart;
484 }
485 /// Marks (or clears) declaration as possibly loop counter.
486 void resetPossibleLoopCounter(const Decl *D = nullptr) {
487 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
488 }
489 /// Gets the possible loop counter decl.
490 const Decl *getPossiblyLoopCounter() const {
491 return getTopOfStack().PossiblyLoopCounter;
492 }
493 /// Start new OpenMP region stack in new non-capturing function.
494 void pushFunction() {
495 assert(!IgnoredStackElements &&
496 "cannot change stack while ignoring elements");
497 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
498 assert(!isa<CapturingScopeInfo>(CurFnScope));
499 CurrentNonCapturingFunctionScope = CurFnScope;
500 }
501 /// Pop region stack for non-capturing function.
502 void popFunction(const FunctionScopeInfo *OldFSI) {
503 assert(!IgnoredStackElements &&
504 "cannot change stack while ignoring elements");
505 if (!Stack.empty() && Stack.back().second == OldFSI) {
506 assert(Stack.back().first.empty());
507 Stack.pop_back();
508 }
509 CurrentNonCapturingFunctionScope = nullptr;
510 for (const FunctionScopeInfo *FSI : llvm::reverse(C&: SemaRef.FunctionScopes)) {
511 if (!isa<CapturingScopeInfo>(Val: FSI)) {
512 CurrentNonCapturingFunctionScope = FSI;
513 break;
514 }
515 }
516 }
517
518 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
519 Criticals.try_emplace(Key: D->getDirectiveName().getAsString(), Args&: D, Args&: Hint);
520 }
521 std::pair<const OMPCriticalDirective *, llvm::APSInt>
522 getCriticalWithHint(const DeclarationNameInfo &Name) const {
523 auto I = Criticals.find(Key: Name.getAsString());
524 if (I != Criticals.end())
525 return I->second;
526 return std::make_pair(x: nullptr, y: llvm::APSInt());
527 }
528 /// If 'aligned' declaration for given variable \a D was not seen yet,
529 /// add it and return NULL; otherwise return previous occurrence's expression
530 /// for diagnostics.
531 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
532 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
533 /// add it and return NULL; otherwise return previous occurrence's expression
534 /// for diagnostics.
535 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
536
537 /// Register specified variable as loop control variable.
538 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
539 /// Check if the specified variable is a loop control variable for
540 /// current region.
541 /// \return The index of the loop control variable in the list of associated
542 /// for-loops (from outer to inner).
543 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
544 /// Check if the specified variable is a loop control variable for
545 /// parent region.
546 /// \return The index of the loop control variable in the list of associated
547 /// for-loops (from outer to inner).
548 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
549 /// Check if the specified variable is a loop control variable for
550 /// current region.
551 /// \return The index of the loop control variable in the list of associated
552 /// for-loops (from outer to inner).
553 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
554 unsigned Level) const;
555 /// Get the loop control variable for the I-th loop (or nullptr) in
556 /// parent directive.
557 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
558
559 /// Marks the specified decl \p D as used in scan directive.
560 void markDeclAsUsedInScanDirective(ValueDecl *D) {
561 if (SharingMapTy *Stack = getSecondOnStackOrNull())
562 Stack->UsedInScanDirective.insert(V: D);
563 }
564
565 /// Checks if the specified declaration was used in the inner scan directive.
566 bool isUsedInScanDirective(ValueDecl *D) const {
567 if (const SharingMapTy *Stack = getTopOfStackOrNull())
568 return Stack->UsedInScanDirective.contains(V: D);
569 return false;
570 }
571
572 /// Adds explicit data sharing attribute to the specified declaration.
573 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
574 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
575 bool AppliedToPointee = false);
576
577 /// Adds additional information for the reduction items with the reduction id
578 /// represented as an operator.
579 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
580 BinaryOperatorKind BOK);
581 /// Adds additional information for the reduction items with the reduction id
582 /// represented as reduction identifier.
583 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
584 const Expr *ReductionRef);
585 /// Returns the location and reduction operation from the innermost parent
586 /// region for the given \p D.
587 const DSAVarData
588 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
589 BinaryOperatorKind &BOK,
590 Expr *&TaskgroupDescriptor) const;
591 /// Returns the location and reduction operation from the innermost parent
592 /// region for the given \p D.
593 const DSAVarData
594 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
595 const Expr *&ReductionRef,
596 Expr *&TaskgroupDescriptor) const;
597 /// Return reduction reference expression for the current taskgroup or
598 /// parallel/worksharing directives with task reductions.
599 Expr *getTaskgroupReductionRef() const {
600 assert((getTopOfStack().Directive == OMPD_taskgroup ||
601 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
602 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
603 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
604 "taskgroup reference expression requested for non taskgroup or "
605 "parallel/worksharing directive.");
606 return getTopOfStack().TaskgroupReductionRef;
607 }
608 /// Checks if the given \p VD declaration is actually a taskgroup reduction
609 /// descriptor variable at the \p Level of OpenMP regions.
610 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
611 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
612 cast<DeclRefExpr>(Val: getStackElemAtLevel(Level).TaskgroupReductionRef)
613 ->getDecl() == VD;
614 }
615
616 /// Returns data sharing attributes from top of the stack for the
617 /// specified declaration.
618 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
619 /// Returns data-sharing attributes for the specified declaration.
620 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
621 /// Returns data-sharing attributes for the specified declaration.
622 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
623 /// Checks if the specified variables has data-sharing attributes which
624 /// match specified \a CPred predicate in any directive which matches \a DPred
625 /// predicate.
626 const DSAVarData
627 hasDSA(ValueDecl *D,
628 const llvm::function_ref<bool(OpenMPClauseKind, bool,
629 DefaultDataSharingAttributes)>
630 CPred,
631 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
632 bool FromParent) const;
633 /// Checks if the specified variables has data-sharing attributes which
634 /// match specified \a CPred predicate in any innermost directive which
635 /// matches \a DPred predicate.
636 const DSAVarData
637 hasInnermostDSA(ValueDecl *D,
638 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
639 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
640 bool FromParent) const;
641 /// Checks if the specified variables has explicit data-sharing
642 /// attributes which match specified \a CPred predicate at the specified
643 /// OpenMP region.
644 bool
645 hasExplicitDSA(const ValueDecl *D,
646 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
647 unsigned Level, bool NotLastprivate = false) const;
648
649 /// Returns true if the directive at level \Level matches in the
650 /// specified \a DPred predicate.
651 bool hasExplicitDirective(
652 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
653 unsigned Level) const;
654
655 /// Finds a directive which matches specified \a DPred predicate.
656 bool hasDirective(
657 const llvm::function_ref<bool(
658 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
659 DPred,
660 bool FromParent) const;
661
662 /// Returns currently analyzed directive.
663 OpenMPDirectiveKind getCurrentDirective() const {
664 const SharingMapTy *Top = getTopOfStackOrNull();
665 return Top ? Top->Directive : OMPD_unknown;
666 }
667 /// Returns directive kind at specified level.
668 OpenMPDirectiveKind getDirective(unsigned Level) const {
669 assert(!isStackEmpty() && "No directive at specified level.");
670 return getStackElemAtLevel(Level).Directive;
671 }
672 /// Returns the capture region at the specified level.
673 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
674 unsigned OpenMPCaptureLevel) const {
675 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
676 getOpenMPCaptureRegions(CaptureRegions, DKind: getDirective(Level));
677 return CaptureRegions[OpenMPCaptureLevel];
678 }
679 /// Returns parent directive.
680 OpenMPDirectiveKind getParentDirective() const {
681 const SharingMapTy *Parent = getSecondOnStackOrNull();
682 return Parent ? Parent->Directive : OMPD_unknown;
683 }
684
685 /// Add requires decl to internal vector
686 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(Elt: RD); }
687
688 ArrayRef<const OMPRequiresDecl *> getRequiresDecls() const {
689 return RequiresDecls;
690 }
691
692 /// Checks if the defined 'requires' directive has specified type of clause.
693 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
694 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
695 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
696 return isa<ClauseType>(C);
697 });
698 });
699 }
700
701 /// Checks for a duplicate clause amongst previously declared requires
702 /// directives
703 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
704 bool IsDuplicate = false;
705 for (OMPClause *CNew : ClauseList) {
706 for (const OMPRequiresDecl *D : RequiresDecls) {
707 for (const OMPClause *CPrev : D->clauselists()) {
708 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
709 SemaRef.Diag(Loc: CNew->getBeginLoc(),
710 DiagID: diag::err_omp_requires_clause_redeclaration)
711 << getOpenMPClauseNameForDiag(C: CNew->getClauseKind());
712 SemaRef.Diag(Loc: CPrev->getBeginLoc(),
713 DiagID: diag::note_omp_requires_previous_clause)
714 << getOpenMPClauseNameForDiag(C: CPrev->getClauseKind());
715 IsDuplicate = true;
716 }
717 }
718 }
719 }
720 return IsDuplicate;
721 }
722
723 /// Add location of previously encountered target to internal vector
724 void addTargetDirLocation(SourceLocation LocStart) {
725 TargetLocations.push_back(Elt: LocStart);
726 }
727
728 /// Add location for the first encountered atomic directive.
729 void addAtomicDirectiveLoc(SourceLocation Loc) {
730 if (AtomicLocation.isInvalid())
731 AtomicLocation = Loc;
732 }
733
734 /// Returns the location of the first encountered atomic directive in the
735 /// module.
736 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
737
738 // Return previously encountered target region locations.
739 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
740 return TargetLocations;
741 }
742
743 /// Set default data sharing attribute to none.
744 void setDefaultDSANone(SourceLocation Loc) {
745 getTopOfStack().DefaultAttr = DSA_none;
746 getTopOfStack().DefaultAttrLoc = Loc;
747 }
748 /// Set default data sharing attribute to shared.
749 void setDefaultDSAShared(SourceLocation Loc) {
750 getTopOfStack().DefaultAttr = DSA_shared;
751 getTopOfStack().DefaultAttrLoc = Loc;
752 }
753 /// Set default data sharing attribute to private.
754 void setDefaultDSAPrivate(SourceLocation Loc) {
755 getTopOfStack().DefaultAttr = DSA_private;
756 getTopOfStack().DefaultAttrLoc = Loc;
757 }
758 /// Set default data sharing attribute to firstprivate.
759 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
760 getTopOfStack().DefaultAttr = DSA_firstprivate;
761 getTopOfStack().DefaultAttrLoc = Loc;
762 }
763 /// Set default data sharing variable category attribute to aggregate.
764 void setDefaultDSAVCAggregate(SourceLocation VCLoc) {
765 getTopOfStack().DefaultVCAttr = DSA_VC_aggregate;
766 getTopOfStack().DefaultAttrVCLoc = VCLoc;
767 }
768 /// Set default data sharing variable category attribute to all.
769 void setDefaultDSAVCAll(SourceLocation VCLoc) {
770 getTopOfStack().DefaultVCAttr = DSA_VC_all;
771 getTopOfStack().DefaultAttrVCLoc = VCLoc;
772 }
773 /// Set default data sharing variable category attribute to pointer.
774 void setDefaultDSAVCPointer(SourceLocation VCLoc) {
775 getTopOfStack().DefaultVCAttr = DSA_VC_pointer;
776 getTopOfStack().DefaultAttrVCLoc = VCLoc;
777 }
778 /// Set default data sharing variable category attribute to scalar.
779 void setDefaultDSAVCScalar(SourceLocation VCLoc) {
780 getTopOfStack().DefaultVCAttr = DSA_VC_scalar;
781 getTopOfStack().DefaultAttrVCLoc = VCLoc;
782 }
783 /// Set default data mapping attribute to Modifier:Kind
784 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
785 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
786 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
787 DMI.ImplicitBehavior = M;
788 DMI.SLoc = Loc;
789 }
790 /// Check whether the implicit-behavior has been set in defaultmap
791 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
792 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
793 return getTopOfStack()
794 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
795 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
796 getTopOfStack()
797 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
798 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
799 getTopOfStack()
800 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
801 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
802 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
803 OMPC_DEFAULTMAP_MODIFIER_unknown;
804 }
805
806 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
807 return ConstructTraits;
808 }
809 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
810 bool ScopeEntry) {
811 if (ScopeEntry)
812 ConstructTraits.append(in_start: Traits.begin(), in_end: Traits.end());
813 else
814 for (llvm::omp::TraitProperty Trait : llvm::reverse(C&: Traits)) {
815 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
816 assert(Top == Trait && "Something left a trait on the stack!");
817 (void)Trait;
818 (void)Top;
819 }
820 }
821
822 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
823 return getStackSize() <= Level ? DSA_unspecified
824 : getStackElemAtLevel(Level).DefaultAttr;
825 }
826 DefaultDataSharingAttributes getDefaultDSA() const {
827 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
828 }
829 SourceLocation getDefaultDSALocation() const {
830 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
831 }
832 OpenMPDefaultmapClauseModifier
833 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
834 return isStackEmpty()
835 ? OMPC_DEFAULTMAP_MODIFIER_unknown
836 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
837 }
838 OpenMPDefaultmapClauseModifier
839 getDefaultmapModifierAtLevel(unsigned Level,
840 OpenMPDefaultmapClauseKind Kind) const {
841 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
842 }
843 bool isDefaultmapCapturedByRef(unsigned Level,
844 OpenMPDefaultmapClauseKind Kind) const {
845 OpenMPDefaultmapClauseModifier M =
846 getDefaultmapModifierAtLevel(Level, Kind);
847 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
848 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
849 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
850 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
851 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
852 (M == OMPC_DEFAULTMAP_MODIFIER_present) ||
853 (M == OMPC_DEFAULTMAP_MODIFIER_storage);
854 }
855 return true;
856 }
857 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
858 OpenMPDefaultmapClauseKind Kind) {
859 switch (Kind) {
860 case OMPC_DEFAULTMAP_scalar:
861 case OMPC_DEFAULTMAP_pointer:
862 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
863 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
864 (M == OMPC_DEFAULTMAP_MODIFIER_default);
865 case OMPC_DEFAULTMAP_aggregate:
866 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
867 default:
868 break;
869 }
870 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
871 }
872 bool mustBeFirstprivateAtLevel(unsigned Level,
873 OpenMPDefaultmapClauseKind Kind) const {
874 OpenMPDefaultmapClauseModifier M =
875 getDefaultmapModifierAtLevel(Level, Kind);
876 return mustBeFirstprivateBase(M, Kind);
877 }
878 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
879 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
880 return mustBeFirstprivateBase(M, Kind);
881 }
882
883 /// Checks if the specified variable is a threadprivate.
884 bool isThreadPrivate(VarDecl *D) {
885 const DSAVarData DVar = getTopDSA(D, FromParent: false);
886 return isOpenMPThreadPrivate(Kind: DVar.CKind);
887 }
888
889 /// Marks current region as ordered (it has an 'ordered' clause).
890 void setOrderedRegion(bool IsOrdered, const Expr *Param,
891 OMPOrderedClause *Clause) {
892 if (IsOrdered)
893 getTopOfStack().OrderedRegion.emplace(args&: Param, args&: Clause);
894 else
895 getTopOfStack().OrderedRegion.reset();
896 }
897 /// Returns true, if region is ordered (has associated 'ordered' clause),
898 /// false - otherwise.
899 bool isOrderedRegion() const {
900 if (const SharingMapTy *Top = getTopOfStackOrNull())
901 return Top->OrderedRegion.has_value();
902 return false;
903 }
904 /// Returns optional parameter for the ordered region.
905 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
906 if (const SharingMapTy *Top = getTopOfStackOrNull())
907 if (Top->OrderedRegion)
908 return *Top->OrderedRegion;
909 return std::make_pair(x: nullptr, y: nullptr);
910 }
911 /// Returns true, if parent region is ordered (has associated
912 /// 'ordered' clause), false - otherwise.
913 bool isParentOrderedRegion() const {
914 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
915 return Parent->OrderedRegion.has_value();
916 return false;
917 }
918 /// Returns optional parameter for the ordered region.
919 std::pair<const Expr *, OMPOrderedClause *>
920 getParentOrderedRegionParam() const {
921 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
922 if (Parent->OrderedRegion)
923 return *Parent->OrderedRegion;
924 return std::make_pair(x: nullptr, y: nullptr);
925 }
926 /// Marks current region as having an 'order' clause.
927 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
928 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
929 }
930 /// Returns true, if parent region is order (has associated
931 /// 'order' clause), false - otherwise.
932 bool isParentOrderConcurrent() const {
933 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
934 return Parent->RegionHasOrderConcurrent;
935 return false;
936 }
937 /// Marks current region as nowait (it has a 'nowait' clause).
938 void setNowaitRegion(bool IsNowait = true) {
939 getTopOfStack().NowaitRegion = IsNowait;
940 }
941 /// Returns true, if parent region is nowait (has associated
942 /// 'nowait' clause), false - otherwise.
943 bool isParentNowaitRegion() const {
944 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
945 return Parent->NowaitRegion;
946 return false;
947 }
948 /// Marks current region as untied (it has a 'untied' clause).
949 void setUntiedRegion(bool IsUntied = true) {
950 getTopOfStack().UntiedRegion = IsUntied;
951 }
952 /// Return true if current region is untied.
953 bool isUntiedRegion() const {
954 const SharingMapTy *Top = getTopOfStackOrNull();
955 return Top ? Top->UntiedRegion : false;
956 }
957 /// Marks parent region as cancel region.
958 void setParentCancelRegion(bool Cancel = true) {
959 if (SharingMapTy *Parent = getSecondOnStackOrNull())
960 Parent->CancelRegion |= Cancel;
961 }
962 /// Return true if current region has inner cancel construct.
963 bool isCancelRegion() const {
964 const SharingMapTy *Top = getTopOfStackOrNull();
965 return Top ? Top->CancelRegion : false;
966 }
967
968 /// Mark that parent region already has scan directive.
969 void setParentHasScanDirective(SourceLocation Loc) {
970 if (SharingMapTy *Parent = getSecondOnStackOrNull())
971 Parent->PrevScanLocation = Loc;
972 }
973 /// Return true if current region has inner cancel construct.
974 bool doesParentHasScanDirective() const {
975 const SharingMapTy *Top = getSecondOnStackOrNull();
976 return Top ? Top->PrevScanLocation.isValid() : false;
977 }
978 /// Return true if current region has inner cancel construct.
979 SourceLocation getParentScanDirectiveLoc() const {
980 const SharingMapTy *Top = getSecondOnStackOrNull();
981 return Top ? Top->PrevScanLocation : SourceLocation();
982 }
983 /// Mark that parent region already has ordered directive.
984 void setParentHasOrderedDirective(SourceLocation Loc) {
985 if (SharingMapTy *Parent = getSecondOnStackOrNull())
986 Parent->PrevOrderedLocation = Loc;
987 }
988 /// Return true if current region has inner ordered construct.
989 bool doesParentHasOrderedDirective() const {
990 const SharingMapTy *Top = getSecondOnStackOrNull();
991 return Top ? Top->PrevOrderedLocation.isValid() : false;
992 }
993 /// Returns the location of the previously specified ordered directive.
994 SourceLocation getParentOrderedDirectiveLoc() const {
995 const SharingMapTy *Top = getSecondOnStackOrNull();
996 return Top ? Top->PrevOrderedLocation : SourceLocation();
997 }
998
999 /// Set collapse value for the region.
1000 void setAssociatedLoops(unsigned Val) {
1001 getTopOfStack().AssociatedLoops = Val;
1002 if (Val > 1)
1003 getTopOfStack().HasMutipleLoops = true;
1004 }
1005 /// Return collapse value for region.
1006 unsigned getAssociatedLoops() const {
1007 const SharingMapTy *Top = getTopOfStackOrNull();
1008 return Top ? Top->AssociatedLoops : 0;
1009 }
1010 /// Returns true if the construct is associated with multiple loops.
1011 bool hasMutipleLoops() const {
1012 const SharingMapTy *Top = getTopOfStackOrNull();
1013 return Top ? Top->HasMutipleLoops : false;
1014 }
1015
1016 /// Marks current target region as one with closely nested teams
1017 /// region.
1018 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
1019 if (SharingMapTy *Parent = getSecondOnStackOrNull())
1020 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
1021 }
1022 /// Returns true, if current region has closely nested teams region.
1023 bool hasInnerTeamsRegion() const {
1024 return getInnerTeamsRegionLoc().isValid();
1025 }
1026 /// Returns location of the nested teams region (if any).
1027 SourceLocation getInnerTeamsRegionLoc() const {
1028 const SharingMapTy *Top = getTopOfStackOrNull();
1029 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1030 }
1031
1032 Scope *getCurScope() const {
1033 const SharingMapTy *Top = getTopOfStackOrNull();
1034 return Top ? Top->CurScope : nullptr;
1035 }
1036 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1037 SourceLocation getConstructLoc() const {
1038 const SharingMapTy *Top = getTopOfStackOrNull();
1039 return Top ? Top->ConstructLoc : SourceLocation();
1040 }
1041
1042 /// Do the check specified in \a Check to all component lists and return true
1043 /// if any issue is found.
1044 bool checkMappableExprComponentListsForDecl(
1045 const ValueDecl *VD, bool CurrentRegionOnly,
1046 const llvm::function_ref<
1047 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1048 OpenMPClauseKind)>
1049 Check) const {
1050 if (isStackEmpty())
1051 return false;
1052 auto SI = begin();
1053 auto SE = end();
1054
1055 if (SI == SE)
1056 return false;
1057
1058 if (CurrentRegionOnly)
1059 SE = std::next(x: SI);
1060 else
1061 std::advance(i&: SI, n: 1);
1062
1063 for (; SI != SE; ++SI) {
1064 auto MI = SI->MappedExprComponents.find(Val: VD);
1065 if (MI != SI->MappedExprComponents.end())
1066 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1067 MI->second.Components)
1068 if (Check(L, MI->second.Kind))
1069 return true;
1070 }
1071 return false;
1072 }
1073
1074 /// Do the check specified in \a Check to all component lists at a given level
1075 /// and return true if any issue is found.
1076 bool checkMappableExprComponentListsForDeclAtLevel(
1077 const ValueDecl *VD, unsigned Level,
1078 const llvm::function_ref<
1079 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1080 OpenMPClauseKind)>
1081 Check) const {
1082 if (getStackSize() <= Level)
1083 return false;
1084
1085 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1086 auto MI = StackElem.MappedExprComponents.find(Val: VD);
1087 if (MI != StackElem.MappedExprComponents.end())
1088 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1089 MI->second.Components)
1090 if (Check(L, MI->second.Kind))
1091 return true;
1092 return false;
1093 }
1094
1095 /// Create a new mappable expression component list associated with a given
1096 /// declaration and initialize it with the provided list of components.
1097 void addMappableExpressionComponents(
1098 const ValueDecl *VD,
1099 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
1100 OpenMPClauseKind WhereFoundClauseKind) {
1101 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1102 // Create new entry and append the new components there.
1103 MEC.Components.resize(N: MEC.Components.size() + 1);
1104 MEC.Components.back().append(in_start: Components.begin(), in_end: Components.end());
1105 MEC.Kind = WhereFoundClauseKind;
1106 }
1107
1108 unsigned getNestingLevel() const {
1109 assert(!isStackEmpty());
1110 return getStackSize() - 1;
1111 }
1112 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1113 SharingMapTy *Parent = getSecondOnStackOrNull();
1114 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1115 Parent->DoacrossDepends.try_emplace(Key: C, Args: OpsOffs);
1116 }
1117 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1118 getDoacrossDependClauses() const {
1119 const SharingMapTy &StackElem = getTopOfStack();
1120 if (isOpenMPWorksharingDirective(DKind: StackElem.Directive)) {
1121 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1122 return llvm::make_range(x: Ref.begin(), y: Ref.end());
1123 }
1124 return llvm::make_range(x: StackElem.DoacrossDepends.end(),
1125 y: StackElem.DoacrossDepends.end());
1126 }
1127
1128 // Store types of classes which have been explicitly mapped
1129 void addMappedClassesQualTypes(QualType QT) {
1130 SharingMapTy &StackElem = getTopOfStack();
1131 StackElem.MappedClassesQualTypes.insert(V: QT);
1132 }
1133
1134 // Return set of mapped classes types
1135 bool isClassPreviouslyMapped(QualType QT) const {
1136 const SharingMapTy &StackElem = getTopOfStack();
1137 return StackElem.MappedClassesQualTypes.contains(V: QT);
1138 }
1139
1140 /// Adds global declare target to the parent target region.
1141 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1142 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1143 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1144 "Expected declare target link global.");
1145 for (auto &Elem : *this) {
1146 if (isOpenMPTargetExecutionDirective(DKind: Elem.Directive)) {
1147 Elem.DeclareTargetLinkVarDecls.push_back(Elt: E);
1148 return;
1149 }
1150 }
1151 }
1152
1153 /// Returns the list of globals with declare target link if current directive
1154 /// is target.
1155 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1156 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1157 "Expected target executable directive.");
1158 return getTopOfStack().DeclareTargetLinkVarDecls;
1159 }
1160
1161 /// Adds list of allocators expressions.
1162 void addInnerAllocatorExpr(Expr *E) {
1163 getTopOfStack().InnerUsedAllocators.push_back(Elt: E);
1164 }
1165 /// Return list of used allocators.
1166 ArrayRef<Expr *> getInnerAllocators() const {
1167 return getTopOfStack().InnerUsedAllocators;
1168 }
1169 /// Marks the declaration as implicitly firstprivate nin the task-based
1170 /// regions.
1171 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1172 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(V: D);
1173 }
1174 /// Checks if the decl is implicitly firstprivate in the task-based region.
1175 bool isImplicitTaskFirstprivate(Decl *D) const {
1176 return getTopOfStack().ImplicitTaskFirstprivates.contains(V: D);
1177 }
1178
1179 /// Marks decl as used in uses_allocators clause as the allocator.
1180 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1181 getTopOfStack().UsesAllocatorsDecls.try_emplace(Key: D, Args&: Kind);
1182 }
1183 /// Checks if specified decl is used in uses allocator clause as the
1184 /// allocator.
1185 std::optional<UsesAllocatorsDeclKind>
1186 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1187 const SharingMapTy &StackElem = getTopOfStack();
1188 auto I = StackElem.UsesAllocatorsDecls.find(Val: D);
1189 if (I == StackElem.UsesAllocatorsDecls.end())
1190 return std::nullopt;
1191 return I->getSecond();
1192 }
1193 std::optional<UsesAllocatorsDeclKind>
1194 isUsesAllocatorsDecl(const Decl *D) const {
1195 const SharingMapTy &StackElem = getTopOfStack();
1196 auto I = StackElem.UsesAllocatorsDecls.find(Val: D);
1197 if (I == StackElem.UsesAllocatorsDecls.end())
1198 return std::nullopt;
1199 return I->getSecond();
1200 }
1201
1202 void addDeclareMapperVarRef(Expr *Ref) {
1203 SharingMapTy &StackElem = getTopOfStack();
1204 StackElem.DeclareMapperVar = Ref;
1205 }
1206 const Expr *getDeclareMapperVarRef() const {
1207 const SharingMapTy *Top = getTopOfStackOrNull();
1208 return Top ? Top->DeclareMapperVar : nullptr;
1209 }
1210
1211 /// Add a new iterator variable.
1212 void addIteratorVarDecl(VarDecl *VD) {
1213 SharingMapTy &StackElem = getTopOfStack();
1214 StackElem.IteratorVarDecls.push_back(Elt: VD->getCanonicalDecl());
1215 }
1216 /// Check if variable declaration is an iterator VarDecl.
1217 bool isIteratorVarDecl(const VarDecl *VD) const {
1218 const SharingMapTy *Top = getTopOfStackOrNull();
1219 if (!Top)
1220 return false;
1221
1222 return llvm::is_contained(Range: Top->IteratorVarDecls, Element: VD->getCanonicalDecl());
1223 }
1224 /// get captured field from ImplicitDefaultFirstprivateFDs
1225 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1226 const_iterator I = begin();
1227 const_iterator EndI = end();
1228 size_t StackLevel = getStackSize();
1229 for (; I != EndI; ++I) {
1230 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1231 break;
1232 StackLevel--;
1233 }
1234 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1235 if (I == EndI)
1236 return nullptr;
1237 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1238 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1239 return IFD.VD;
1240 return nullptr;
1241 }
1242 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1243 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1244 const_iterator I = begin();
1245 const_iterator EndI = end();
1246 for (; I != EndI; ++I)
1247 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1248 break;
1249 if (I == EndI)
1250 return false;
1251 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1252 if (IFD.VD == VD)
1253 return true;
1254 return false;
1255 }
1256 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1257 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1258 iterator I = begin();
1259 const_iterator EndI = end();
1260 size_t StackLevel = getStackSize();
1261 for (; I != EndI; ++I) {
1262 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1263 I->ImplicitDefaultFirstprivateFDs.emplace_back(Args&: FD, Args&: StackLevel, Args&: VD);
1264 break;
1265 }
1266 StackLevel--;
1267 }
1268 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1269 }
1270 void setOrderedToBlockAssociated() {
1271 assert(getCurrentDirective() == OMPD_ordered_standalone);
1272 getTopOfStack().Directive = OMPD_ordered_blockassoc;
1273 }
1274};
1275
1276bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1277 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1278}
1279
1280bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1281 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(Kind: DKind) ||
1282 DKind == OMPD_unknown;
1283}
1284
1285} // namespace
1286
1287static const Expr *getExprAsWritten(const Expr *E) {
1288 if (const auto *FE = dyn_cast<FullExpr>(Val: E))
1289 E = FE->getSubExpr();
1290
1291 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Val: E))
1292 E = MTE->getSubExpr();
1293
1294 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(Val: E))
1295 E = Binder->getSubExpr();
1296
1297 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(Val: E))
1298 E = ICE->getSubExprAsWritten();
1299 return E->IgnoreParens();
1300}
1301
1302static Expr *getExprAsWritten(Expr *E) {
1303 return const_cast<Expr *>(getExprAsWritten(E: const_cast<const Expr *>(E)));
1304}
1305
1306static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1307 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: D))
1308 if (const auto *ME = dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit())))
1309 D = ME->getMemberDecl();
1310
1311 D = cast<ValueDecl>(Val: D->getCanonicalDecl());
1312 return D;
1313}
1314
1315static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1316 return const_cast<ValueDecl *>(
1317 getCanonicalDecl(D: const_cast<const ValueDecl *>(D)));
1318}
1319
1320static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C) {
1321 if (C == OMPC_threadprivate)
1322 return getOpenMPClauseName(C).str() + " or thread local";
1323 return getOpenMPClauseName(C).str();
1324}
1325
1326DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1327 ValueDecl *D) const {
1328 D = getCanonicalDecl(D);
1329 auto *VD = dyn_cast<VarDecl>(Val: D);
1330 const auto *FD = dyn_cast<FieldDecl>(Val: D);
1331 DSAVarData DVar;
1332 if (Iter == end()) {
1333 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1334 // in a region but not in construct]
1335 // File-scope or namespace-scope variables referenced in called routines
1336 // in the region are shared unless they appear in a threadprivate
1337 // directive.
1338 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(Val: VD))
1339 DVar.CKind = OMPC_shared;
1340
1341 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1342 // in a region but not in construct]
1343 // Variables with static storage duration that are declared in called
1344 // routines in the region are shared.
1345 if (VD && VD->hasGlobalStorage())
1346 DVar.CKind = OMPC_shared;
1347
1348 // Non-static data members are shared by default.
1349 if (FD)
1350 DVar.CKind = OMPC_shared;
1351
1352 return DVar;
1353 }
1354
1355 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1356 // in a Construct, C/C++, predetermined, p.1]
1357 // Variables with automatic storage duration that are declared in a scope
1358 // inside the construct are private.
1359 if (VD && isOpenMPLocal(D: VD, Iter) && VD->isLocalVarDecl() &&
1360 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1361 DVar.CKind = OMPC_private;
1362 return DVar;
1363 }
1364
1365 DVar.DKind = Iter->Directive;
1366 // Explicitly specified attributes and local variables with predetermined
1367 // attributes.
1368 if (Iter->SharingMap.count(Val: D)) {
1369 const DSAInfo &Data = Iter->SharingMap.lookup(Val: D);
1370 DVar.RefExpr = Data.RefExpr.getPointer();
1371 DVar.PrivateCopy = Data.PrivateCopy;
1372 DVar.CKind = Data.Attributes;
1373 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1374 DVar.Modifier = Data.Modifier;
1375 DVar.AppliedToPointee = Data.AppliedToPointee;
1376 // For BindingDecls with OMPC_unknown, fall through to implicit DSA logic
1377 // instead of treating them as explicitly specified.
1378 if (!(isa<BindingDecl>(Val: D) && DVar.CKind == OMPC_unknown)) {
1379 return DVar;
1380 }
1381 }
1382
1383 DefaultDataSharingAttributes IterDA = Iter->DefaultAttr;
1384 switch (Iter->DefaultVCAttr) {
1385 case DSA_VC_aggregate:
1386 if (!D->getType()->isAggregateType())
1387 IterDA = DSA_none;
1388 break;
1389 case DSA_VC_pointer:
1390 if (!D->getType()->isPointerType())
1391 IterDA = DSA_none;
1392 break;
1393 case DSA_VC_scalar:
1394 if (!D->getType()->isScalarType())
1395 IterDA = DSA_none;
1396 break;
1397 case DSA_VC_all:
1398 break;
1399 }
1400
1401 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1402 // in a Construct, C/C++, implicitly determined, p.1]
1403 // In a parallel or task construct, the data-sharing attributes of these
1404 // variables are determined by the default clause, if present.
1405 switch (IterDA) {
1406 case DSA_shared:
1407 DVar.CKind = OMPC_shared;
1408 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1409 return DVar;
1410 case DSA_none:
1411 return DVar;
1412 case DSA_firstprivate:
1413 if (VD && VD->getStorageDuration() == SD_Static &&
1414 VD->getDeclContext()->isFileContext()) {
1415 DVar.CKind = OMPC_unknown;
1416 } else {
1417 DVar.CKind = OMPC_firstprivate;
1418 }
1419 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1420 return DVar;
1421 case DSA_private:
1422 // each variable with static storage duration that is declared
1423 // in a namespace or global scope and referenced in the construct,
1424 // and that does not have a predetermined data-sharing attribute
1425 if (VD && VD->getStorageDuration() == SD_Static &&
1426 VD->getDeclContext()->isFileContext()) {
1427 DVar.CKind = OMPC_unknown;
1428 } else {
1429 DVar.CKind = OMPC_private;
1430 }
1431 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1432 return DVar;
1433 case DSA_unspecified:
1434 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1435 // in a Construct, implicitly determined, p.2]
1436 // In a parallel construct, if no default clause is present, these
1437 // variables are shared.
1438 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1439 if ((isOpenMPParallelDirective(DKind: DVar.DKind) &&
1440 !isOpenMPTaskLoopDirective(DKind: DVar.DKind)) ||
1441 isOpenMPTeamsDirective(DKind: DVar.DKind)) {
1442 DVar.CKind = OMPC_shared;
1443 return DVar;
1444 }
1445
1446 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1447 // in a Construct, implicitly determined, p.4]
1448 // In a task construct, if no default clause is present, a variable that in
1449 // the enclosing context is determined to be shared by all implicit tasks
1450 // bound to the current team is shared.
1451 if (isOpenMPTaskingDirective(Kind: DVar.DKind)) {
1452 DSAVarData DVarTemp;
1453 const_iterator I = Iter, E = end();
1454 do {
1455 ++I;
1456 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1457 // Referenced in a Construct, implicitly determined, p.6]
1458 // In a task construct, if no default clause is present, a variable
1459 // whose data-sharing attribute is not determined by the rules above is
1460 // firstprivate.
1461 DVarTemp = getDSA(Iter&: I, D);
1462 if (DVarTemp.CKind != OMPC_shared) {
1463 DVar.RefExpr = nullptr;
1464 DVar.CKind = OMPC_firstprivate;
1465 return DVar;
1466 }
1467 } while (I != E && !isImplicitTaskingRegion(DKind: I->Directive));
1468 DVar.CKind =
1469 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1470 return DVar;
1471 }
1472 }
1473 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1474 // in a Construct, implicitly determined, p.3]
1475 // For constructs other than task, if no default clause is present, these
1476 // variables inherit their data-sharing attributes from the enclosing
1477 // context.
1478 return getDSA(Iter&: ++Iter, D);
1479}
1480
1481const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1482 const Expr *NewDE) {
1483 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1484 D = getCanonicalDecl(D);
1485 SharingMapTy &StackElem = getTopOfStack();
1486 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(Key: D, Args&: NewDE);
1487 if (Inserted) {
1488 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1489 return nullptr;
1490 }
1491 assert(It->second && "Unexpected nullptr expr in the aligned map");
1492 return It->second;
1493}
1494
1495const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1496 const Expr *NewDE) {
1497 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1498 D = getCanonicalDecl(D);
1499 SharingMapTy &StackElem = getTopOfStack();
1500 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(Key: D, Args&: NewDE);
1501 if (Inserted) {
1502 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1503 return nullptr;
1504 }
1505 assert(It->second && "Unexpected nullptr expr in the aligned map");
1506 return It->second;
1507}
1508
1509void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1510 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1511 D = getCanonicalDecl(D);
1512 SharingMapTy &StackElem = getTopOfStack();
1513 StackElem.LCVMap.try_emplace(
1514 Key: D, Args: LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1515}
1516
1517const DSAStackTy::LCDeclInfo
1518DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1519 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1520 D = getCanonicalDecl(D);
1521 const SharingMapTy &StackElem = getTopOfStack();
1522 auto It = StackElem.LCVMap.find(Val: D);
1523 if (It != StackElem.LCVMap.end())
1524 return It->second;
1525 return {0, nullptr};
1526}
1527
1528const DSAStackTy::LCDeclInfo
1529DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1530 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1531 D = getCanonicalDecl(D);
1532 for (unsigned I = Level + 1; I > 0; --I) {
1533 const SharingMapTy &StackElem = getStackElemAtLevel(Level: I - 1);
1534 auto It = StackElem.LCVMap.find(Val: D);
1535 if (It != StackElem.LCVMap.end())
1536 return It->second;
1537 }
1538 return {0, nullptr};
1539}
1540
1541const DSAStackTy::LCDeclInfo
1542DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1543 const SharingMapTy *Parent = getSecondOnStackOrNull();
1544 assert(Parent && "Data-sharing attributes stack is empty");
1545 D = getCanonicalDecl(D);
1546 auto It = Parent->LCVMap.find(Val: D);
1547 if (It != Parent->LCVMap.end())
1548 return It->second;
1549 return {0, nullptr};
1550}
1551
1552const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1553 const SharingMapTy *Parent = getSecondOnStackOrNull();
1554 assert(Parent && "Data-sharing attributes stack is empty");
1555 if (Parent->LCVMap.size() < I)
1556 return nullptr;
1557 for (const auto &Pair : Parent->LCVMap)
1558 if (Pair.second.first == I)
1559 return Pair.first;
1560 return nullptr;
1561}
1562
1563void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1564 DeclRefExpr *PrivateCopy, unsigned Modifier,
1565 bool AppliedToPointee) {
1566 D = getCanonicalDecl(D);
1567 if (A == OMPC_threadprivate) {
1568 DSAInfo &Data = Threadprivates[D];
1569 Data.Attributes = A;
1570 Data.RefExpr.setPointer(E);
1571 Data.PrivateCopy = nullptr;
1572 Data.Modifier = Modifier;
1573 } else if (A == OMPC_groupprivate) {
1574 DSAInfo &Data = Groupprivates[D];
1575 Data.Attributes = A;
1576 Data.RefExpr.setPointer(E);
1577 Data.PrivateCopy = nullptr;
1578 Data.Modifier = Modifier;
1579 } else {
1580 DSAInfo &Data = getTopOfStack().SharingMap[D];
1581 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1582 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1583 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1584 (isLoopControlVariable(D).first && A == OMPC_private));
1585 Data.Modifier = Modifier;
1586 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1587 Data.RefExpr.setInt(/*IntVal=*/true);
1588 return;
1589 }
1590 const bool IsLastprivate =
1591 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1592 Data.Attributes = A;
1593 Data.RefExpr.setPointerAndInt(PtrVal: E, IntVal: IsLastprivate);
1594 Data.PrivateCopy = PrivateCopy;
1595 Data.AppliedToPointee = AppliedToPointee;
1596 if (PrivateCopy) {
1597 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1598 Data.Modifier = Modifier;
1599 Data.Attributes = A;
1600 Data.RefExpr.setPointerAndInt(PtrVal: PrivateCopy, IntVal: IsLastprivate);
1601 Data.PrivateCopy = nullptr;
1602 Data.AppliedToPointee = AppliedToPointee;
1603 }
1604 }
1605}
1606
1607/// Build a variable declaration for OpenMP loop iteration variable.
1608static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
1609 StringRef Name, const AttrVec *Attrs = nullptr,
1610 DeclRefExpr *OrigRef = nullptr) {
1611 DeclContext *DC = SemaRef.CurContext;
1612 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1613 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(T: Type, Loc);
1614 auto *Decl =
1615 VarDecl::Create(C&: SemaRef.Context, DC, StartLoc: Loc, IdLoc: Loc, Id: II, T: Type, TInfo, S: SC_None);
1616 if (Attrs) {
1617 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1618 I != E; ++I)
1619 Decl->addAttr(A: *I);
1620 }
1621 Decl->setImplicit();
1622 if (OrigRef) {
1623 Decl->addAttr(
1624 A: OMPReferencedVarAttr::CreateImplicit(Ctx&: SemaRef.Context, Ref: OrigRef));
1625 }
1626 return Decl;
1627}
1628
1629static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
1630 SourceLocation Loc,
1631 bool RefersToCapture = false) {
1632 D->setReferenced();
1633 D->markUsed(C&: S.Context);
1634 return DeclRefExpr::Create(Context: S.getASTContext(), QualifierLoc: NestedNameSpecifierLoc(),
1635 TemplateKWLoc: SourceLocation(), D, RefersToEnclosingVariableOrCapture: RefersToCapture, NameLoc: Loc, T: Ty,
1636 VK: VK_LValue);
1637}
1638
1639void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1640 BinaryOperatorKind BOK) {
1641 D = getCanonicalDecl(D);
1642 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1643 assert(
1644 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1645 "Additional reduction info may be specified only for reduction items.");
1646 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1647 assert(ReductionData.ReductionRange.isInvalid() &&
1648 (getTopOfStack().Directive == OMPD_taskgroup ||
1649 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1650 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1651 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1652 "Additional reduction info may be specified only once for reduction "
1653 "items.");
1654 ReductionData.set(BO: BOK, RR: SR);
1655 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1656 if (!TaskgroupReductionRef) {
1657 VarDecl *VD = buildVarDecl(SemaRef, Loc: SR.getBegin(),
1658 Type: SemaRef.Context.VoidPtrTy, Name: ".task_red.");
1659 TaskgroupReductionRef =
1660 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: SemaRef.Context.VoidPtrTy, Loc: SR.getBegin());
1661 }
1662}
1663
1664void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1665 const Expr *ReductionRef) {
1666 D = getCanonicalDecl(D);
1667 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1668 assert(
1669 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1670 "Additional reduction info may be specified only for reduction items.");
1671 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1672 assert(ReductionData.ReductionRange.isInvalid() &&
1673 (getTopOfStack().Directive == OMPD_taskgroup ||
1674 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1675 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1676 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1677 "Additional reduction info may be specified only once for reduction "
1678 "items.");
1679 ReductionData.set(RefExpr: ReductionRef, RR: SR);
1680 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1681 if (!TaskgroupReductionRef) {
1682 VarDecl *VD = buildVarDecl(SemaRef, Loc: SR.getBegin(),
1683 Type: SemaRef.Context.VoidPtrTy, Name: ".task_red.");
1684 TaskgroupReductionRef =
1685 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: SemaRef.Context.VoidPtrTy, Loc: SR.getBegin());
1686 }
1687}
1688
1689const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1690 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1691 Expr *&TaskgroupDescriptor) const {
1692 D = getCanonicalDecl(D);
1693 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1694 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1695 const DSAInfo &Data = I->SharingMap.lookup(Val: D);
1696 if (Data.Attributes != OMPC_reduction ||
1697 Data.Modifier != OMPC_REDUCTION_task)
1698 continue;
1699 const ReductionData &ReductionData = I->ReductionMap.lookup(Val: D);
1700 if (!ReductionData.ReductionOp ||
1701 isa<const Expr *>(Val: ReductionData.ReductionOp))
1702 return DSAVarData();
1703 SR = ReductionData.ReductionRange;
1704 BOK = cast<ReductionData::BOKPtrType>(Val: ReductionData.ReductionOp);
1705 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1706 "expression for the descriptor is not "
1707 "set.");
1708 TaskgroupDescriptor = I->TaskgroupReductionRef;
1709 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1710 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1711 /*AppliedToPointee=*/false);
1712 }
1713 return DSAVarData();
1714}
1715
1716const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1717 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1718 Expr *&TaskgroupDescriptor) const {
1719 D = getCanonicalDecl(D);
1720 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1721 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1722 const DSAInfo &Data = I->SharingMap.lookup(Val: D);
1723 if (Data.Attributes != OMPC_reduction ||
1724 Data.Modifier != OMPC_REDUCTION_task)
1725 continue;
1726 const ReductionData &ReductionData = I->ReductionMap.lookup(Val: D);
1727 if (!ReductionData.ReductionOp ||
1728 !isa<const Expr *>(Val: ReductionData.ReductionOp))
1729 return DSAVarData();
1730 SR = ReductionData.ReductionRange;
1731 ReductionRef = cast<const Expr *>(Val: ReductionData.ReductionOp);
1732 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1733 "expression for the descriptor is not "
1734 "set.");
1735 TaskgroupDescriptor = I->TaskgroupReductionRef;
1736 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1737 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1738 /*AppliedToPointee=*/false);
1739 }
1740 return DSAVarData();
1741}
1742
1743bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1744 D = D->getCanonicalDecl();
1745 for (const_iterator E = end(); I != E; ++I) {
1746 if (isImplicitOrExplicitTaskingRegion(DKind: I->Directive) ||
1747 isOpenMPTargetExecutionDirective(DKind: I->Directive)) {
1748 if (I->CurScope) {
1749 Scope *TopScope = I->CurScope->getParent();
1750 Scope *CurScope = getCurScope();
1751 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1752 CurScope = CurScope->getParent();
1753 return CurScope != TopScope;
1754 }
1755 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1756 if (I->Context == DC)
1757 return true;
1758 return false;
1759 }
1760 }
1761 return false;
1762}
1763
1764static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
1765 bool AcceptIfMutable = true,
1766 bool *IsClassType = nullptr) {
1767 ASTContext &Context = SemaRef.getASTContext();
1768 Type = Type.getNonReferenceType().getCanonicalType();
1769 bool IsConstant = Type.isConstant(Ctx: Context);
1770 Type = Context.getBaseElementType(QT: Type);
1771 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1772 ? Type->getAsCXXRecordDecl()
1773 : nullptr;
1774 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(Val: RD))
1775 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1776 RD = CTD->getTemplatedDecl();
1777 if (IsClassType)
1778 *IsClassType = RD;
1779 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1780 RD->hasDefinition() && RD->hasMutableFields());
1781}
1782
1783static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1784 QualType Type, OpenMPClauseKind CKind,
1785 SourceLocation ELoc,
1786 bool AcceptIfMutable = true,
1787 bool ListItemNotVar = false) {
1788 ASTContext &Context = SemaRef.getASTContext();
1789 bool IsClassType;
1790 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, IsClassType: &IsClassType)) {
1791 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1792 : IsClassType ? diag::err_omp_const_not_mutable_variable
1793 : diag::err_omp_const_variable;
1794 SemaRef.Diag(Loc: ELoc, DiagID: Diag) << getOpenMPClauseNameForDiag(C: CKind);
1795 if (!ListItemNotVar && D) {
1796 const VarDecl *VD = dyn_cast<VarDecl>(Val: D);
1797 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1798 VarDecl::DeclarationOnly;
1799 SemaRef.Diag(Loc: D->getLocation(),
1800 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1801 << D;
1802 }
1803 return true;
1804 }
1805 return false;
1806}
1807
1808const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1809 bool FromParent) {
1810 D = getCanonicalDecl(D);
1811 DSAVarData DVar;
1812
1813 auto *VD = dyn_cast<VarDecl>(Val: D);
1814 auto TI = Threadprivates.find(Val: D);
1815 if (TI != Threadprivates.end()) {
1816 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1817 DVar.CKind = OMPC_threadprivate;
1818 DVar.Modifier = TI->getSecond().Modifier;
1819 return DVar;
1820 }
1821 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1822 DVar.RefExpr = buildDeclRefExpr(
1823 S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1824 Loc: VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1825 DVar.CKind = OMPC_threadprivate;
1826 addDSA(D, E: DVar.RefExpr, A: OMPC_threadprivate);
1827 return DVar;
1828 }
1829 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1830 // in a Construct, C/C++, predetermined, p.1]
1831 // Variables appearing in threadprivate directives are threadprivate.
1832 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1833 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1834 SemaRef.getLangOpts().OpenMPUseTLS &&
1835 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1836 (VD && VD->getStorageClass() == SC_Register &&
1837 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1838 DVar.RefExpr = buildDeclRefExpr(
1839 S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(), Loc: D->getLocation());
1840 DVar.CKind = OMPC_threadprivate;
1841 addDSA(D, E: DVar.RefExpr, A: OMPC_threadprivate);
1842 return DVar;
1843 }
1844 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1845 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1846 !isLoopControlVariable(D).first) {
1847 const_iterator IterTarget =
1848 std::find_if(first: begin(), last: end(), pred: [](const SharingMapTy &Data) {
1849 return isOpenMPTargetExecutionDirective(DKind: Data.Directive);
1850 });
1851 if (IterTarget != end()) {
1852 const_iterator ParentIterTarget = IterTarget + 1;
1853 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1854 if (isOpenMPLocal(D: VD, I: Iter)) {
1855 DVar.RefExpr =
1856 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1857 Loc: D->getLocation());
1858 DVar.CKind = OMPC_threadprivate;
1859 return DVar;
1860 }
1861 }
1862 if (!isClauseParsingMode() || IterTarget != begin()) {
1863 auto DSAIter = IterTarget->SharingMap.find(Val: D);
1864 if (DSAIter != IterTarget->SharingMap.end() &&
1865 isOpenMPPrivate(Kind: DSAIter->getSecond().Attributes)) {
1866 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1867 DVar.CKind = OMPC_threadprivate;
1868 return DVar;
1869 }
1870 const_iterator End = end();
1871 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1872 D, Level: std::distance(first: ParentIterTarget, last: End),
1873 /*OpenMPCaptureLevel=*/0)) {
1874 DVar.RefExpr =
1875 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1876 Loc: IterTarget->ConstructLoc);
1877 DVar.CKind = OMPC_threadprivate;
1878 return DVar;
1879 }
1880 }
1881 }
1882 }
1883
1884 if (isStackEmpty())
1885 // Not in OpenMP execution region and top scope was already checked.
1886 return DVar;
1887
1888 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1889 // in a Construct, C/C++, predetermined, p.4]
1890 // Static data members are shared.
1891 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1892 // in a Construct, C/C++, predetermined, p.7]
1893 // Variables with static storage duration that are declared in a scope
1894 // inside the construct are shared.
1895 if (VD && VD->isStaticDataMember()) {
1896 // Check for explicitly specified attributes.
1897 const_iterator I = begin();
1898 const_iterator EndI = end();
1899 if (FromParent && I != EndI)
1900 ++I;
1901 if (I != EndI) {
1902 auto It = I->SharingMap.find(Val: D);
1903 if (It != I->SharingMap.end()) {
1904 const DSAInfo &Data = It->getSecond();
1905 DVar.RefExpr = Data.RefExpr.getPointer();
1906 DVar.PrivateCopy = Data.PrivateCopy;
1907 DVar.CKind = Data.Attributes;
1908 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1909 DVar.DKind = I->Directive;
1910 DVar.Modifier = Data.Modifier;
1911 DVar.AppliedToPointee = Data.AppliedToPointee;
1912 return DVar;
1913 }
1914 }
1915
1916 DVar.CKind = OMPC_shared;
1917 return DVar;
1918 }
1919
1920 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1921 // The predetermined shared attribute for const-qualified types having no
1922 // mutable members was removed after OpenMP 3.1.
1923 if (SemaRef.LangOpts.OpenMP <= 31) {
1924 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1925 // in a Construct, C/C++, predetermined, p.6]
1926 // Variables with const qualified type having no mutable member are
1927 // shared.
1928 if (isConstNotMutableType(SemaRef, Type: D->getType())) {
1929 // Variables with const-qualified type having no mutable member may be
1930 // listed in a firstprivate clause, even if they are static data members.
1931 DSAVarData DVarTemp = hasInnermostDSA(
1932 D,
1933 CPred: [](OpenMPClauseKind C, bool) {
1934 return C == OMPC_firstprivate || C == OMPC_shared;
1935 },
1936 DPred: MatchesAlways, FromParent);
1937 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1938 return DVarTemp;
1939
1940 DVar.CKind = OMPC_shared;
1941 return DVar;
1942 }
1943 }
1944
1945 // Explicitly specified attributes and local variables with predetermined
1946 // attributes.
1947 const_iterator I = begin();
1948 const_iterator EndI = end();
1949 if (FromParent && I != EndI)
1950 ++I;
1951 if (I == EndI)
1952 return DVar;
1953 auto It = I->SharingMap.find(Val: D);
1954 if (It != I->SharingMap.end()) {
1955 const DSAInfo &Data = It->getSecond();
1956 DVar.RefExpr = Data.RefExpr.getPointer();
1957 DVar.PrivateCopy = Data.PrivateCopy;
1958 DVar.CKind = Data.Attributes;
1959 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1960 DVar.DKind = I->Directive;
1961 DVar.Modifier = Data.Modifier;
1962 DVar.AppliedToPointee = Data.AppliedToPointee;
1963 }
1964
1965 return DVar;
1966}
1967
1968const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1969 bool FromParent) const {
1970 if (isStackEmpty()) {
1971 const_iterator I;
1972 return getDSA(Iter&: I, D);
1973 }
1974 D = getCanonicalDecl(D);
1975 const_iterator StartI = begin();
1976 const_iterator EndI = end();
1977 if (FromParent && StartI != EndI)
1978 ++StartI;
1979 return getDSA(Iter&: StartI, D);
1980}
1981
1982const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1983 unsigned Level) const {
1984 if (getStackSize() <= Level)
1985 return DSAVarData();
1986 D = getCanonicalDecl(D);
1987 const_iterator StartI = std::next(x: begin(), n: getStackSize() - 1 - Level);
1988 return getDSA(Iter&: StartI, D);
1989}
1990
1991const DSAStackTy::DSAVarData
1992DSAStackTy::hasDSA(ValueDecl *D,
1993 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1994 DefaultDataSharingAttributes)>
1995 CPred,
1996 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1997 bool FromParent) const {
1998 if (isStackEmpty())
1999 return {};
2000 D = getCanonicalDecl(D);
2001 const_iterator I = begin();
2002 const_iterator EndI = end();
2003 if (FromParent && I != EndI)
2004 ++I;
2005 for (; I != EndI; ++I) {
2006 if (!DPred(I->Directive) &&
2007 !isImplicitOrExplicitTaskingRegion(DKind: I->Directive))
2008 continue;
2009 const_iterator NewI = I;
2010 DSAVarData DVar = getDSA(Iter&: NewI, D);
2011 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
2012 return DVar;
2013 }
2014 return {};
2015}
2016
2017const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
2018 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2019 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2020 bool FromParent) const {
2021 if (isStackEmpty())
2022 return {};
2023 D = getCanonicalDecl(D);
2024 const_iterator StartI = begin();
2025 const_iterator EndI = end();
2026 if (FromParent && StartI != EndI)
2027 ++StartI;
2028 if (StartI == EndI || !DPred(StartI->Directive))
2029 return {};
2030 const_iterator NewI = StartI;
2031 DSAVarData DVar = getDSA(Iter&: NewI, D);
2032 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
2033 ? DVar
2034 : DSAVarData();
2035}
2036
2037bool DSAStackTy::hasExplicitDSA(
2038 const ValueDecl *D,
2039 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2040 unsigned Level, bool NotLastprivate) const {
2041 if (getStackSize() <= Level)
2042 return false;
2043 D = getCanonicalDecl(D);
2044 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2045 auto I = StackElem.SharingMap.find(Val: D);
2046 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
2047 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
2048 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
2049 return true;
2050 // Check predetermined rules for the loop control variables.
2051 auto LI = StackElem.LCVMap.find(Val: D);
2052 if (LI != StackElem.LCVMap.end())
2053 return CPred(OMPC_private, /*AppliedToPointee=*/false);
2054 return false;
2055}
2056
2057bool DSAStackTy::hasExplicitDirective(
2058 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2059 unsigned Level) const {
2060 if (getStackSize() <= Level)
2061 return false;
2062 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2063 return DPred(StackElem.Directive);
2064}
2065
2066bool DSAStackTy::hasDirective(
2067 const llvm::function_ref<bool(OpenMPDirectiveKind,
2068 const DeclarationNameInfo &, SourceLocation)>
2069 DPred,
2070 bool FromParent) const {
2071 // We look only in the enclosing region.
2072 size_t Skip = FromParent ? 2 : 1;
2073 for (const_iterator I = begin() + std::min(a: Skip, b: getStackSize()), E = end();
2074 I != E; ++I) {
2075 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2076 return true;
2077 }
2078 return false;
2079}
2080
2081void SemaOpenMP::InitDataSharingAttributesStack() {
2082 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2083}
2084
2085#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2086
2087void SemaOpenMP::addRequiresDecl(OMPRequiresDecl *D) {
2088 DSAStack->addRequiresDecl(RD: D);
2089}
2090
2091ArrayRef<const OMPRequiresDecl *> SemaOpenMP::getRequiresDecls() const {
2092 return DSAStack->getRequiresDecls();
2093}
2094
2095void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2096
2097void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2098 DSAStack->popFunction(OldFSI);
2099}
2100
2101static bool isOpenMPDeviceDelayedContext(Sema &S) {
2102 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2103 "Expected OpenMP device compilation.");
2104 return !S.OpenMP().isInOpenMPTargetExecutionDirective();
2105}
2106
2107namespace {
2108/// Status of the function emission on the host/device.
2109enum class FunctionEmissionStatus {
2110 Emitted,
2111 Discarded,
2112 Unknown,
2113};
2114} // anonymous namespace
2115
2116SemaBase::SemaDiagnosticBuilder
2117SemaOpenMP::diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID,
2118 const FunctionDecl *FD) {
2119 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2120 "Expected OpenMP device compilation.");
2121
2122 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2123 if (FD) {
2124 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(Decl: FD);
2125 switch (FES) {
2126 case Sema::FunctionEmissionStatus::Emitted:
2127 Kind = SemaDiagnosticBuilder::K_Immediate;
2128 break;
2129 case Sema::FunctionEmissionStatus::Unknown:
2130 // TODO: We should always delay diagnostics here in case a target
2131 // region is in a function we do not emit. However, as the
2132 // current diagnostics are associated with the function containing
2133 // the target region and we do not emit that one, we would miss out
2134 // on diagnostics for the target region itself. We need to anchor
2135 // the diagnostics with the new generated function *or* ensure we
2136 // emit diagnostics associated with the surrounding function.
2137 Kind = isOpenMPDeviceDelayedContext(S&: SemaRef)
2138 ? SemaDiagnosticBuilder::K_Deferred
2139 : SemaDiagnosticBuilder::K_Immediate;
2140 break;
2141 case Sema::FunctionEmissionStatus::TemplateDiscarded:
2142 case Sema::FunctionEmissionStatus::OMPDiscarded:
2143 Kind = SemaDiagnosticBuilder::K_Nop;
2144 break;
2145 case Sema::FunctionEmissionStatus::CUDADiscarded:
2146 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2147 break;
2148 }
2149 }
2150
2151 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2152}
2153
2154SemaBase::SemaDiagnosticBuilder
2155SemaOpenMP::diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID,
2156 const FunctionDecl *FD) {
2157 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2158 "Expected OpenMP host compilation.");
2159
2160 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2161 if (FD) {
2162 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(Decl: FD);
2163 switch (FES) {
2164 case Sema::FunctionEmissionStatus::Emitted:
2165 Kind = SemaDiagnosticBuilder::K_Immediate;
2166 break;
2167 case Sema::FunctionEmissionStatus::Unknown:
2168 Kind = SemaDiagnosticBuilder::K_Deferred;
2169 break;
2170 case Sema::FunctionEmissionStatus::TemplateDiscarded:
2171 case Sema::FunctionEmissionStatus::OMPDiscarded:
2172 case Sema::FunctionEmissionStatus::CUDADiscarded:
2173 Kind = SemaDiagnosticBuilder::K_Nop;
2174 break;
2175 }
2176 }
2177
2178 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2179}
2180
2181static OpenMPDefaultmapClauseKind
2182getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) {
2183 if (LO.OpenMP <= 45) {
2184 if (VD->getType().getNonReferenceType()->isScalarType())
2185 return OMPC_DEFAULTMAP_scalar;
2186 return OMPC_DEFAULTMAP_aggregate;
2187 }
2188 if (VD->getType().getNonReferenceType()->isAnyPointerType())
2189 return OMPC_DEFAULTMAP_pointer;
2190 if (VD->getType().getNonReferenceType()->isScalarType())
2191 return OMPC_DEFAULTMAP_scalar;
2192 return OMPC_DEFAULTMAP_aggregate;
2193}
2194
2195bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2196 unsigned OpenMPCaptureLevel) const {
2197 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2198
2199 ASTContext &Ctx = getASTContext();
2200 bool IsByRef = true;
2201
2202 // Find the directive that is associated with the provided scope.
2203 D = cast<ValueDecl>(Val: D->getCanonicalDecl());
2204 QualType Ty = D->getType();
2205 if (const auto *BD = dyn_cast<BindingDecl>(Val: D))
2206 Ty = BD->getDecomposedDecl()->getType();
2207
2208 bool IsVariableUsedInMapClause = false;
2209 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective, Level)) {
2210 // This table summarizes how a given variable should be passed to the device
2211 // given its type and the clauses where it appears. This table is based on
2212 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2213 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2214 //
2215 // =========================================================================
2216 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2217 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2218 // =========================================================================
2219 // | scl | | | | - | | bycopy|
2220 // | scl | | - | x | - | - | bycopy|
2221 // | scl | | x | - | - | - | null |
2222 // | scl | x | | | - | | byref |
2223 // | scl | x | - | x | - | - | bycopy|
2224 // | scl | x | x | - | - | - | null |
2225 // | scl | | - | - | - | x | byref |
2226 // | scl | x | - | - | - | x | byref |
2227 //
2228 // | agg | n.a. | | | - | | byref |
2229 // | agg | n.a. | - | x | - | - | byref |
2230 // | agg | n.a. | x | - | - | - | null |
2231 // | agg | n.a. | - | - | - | x | byref |
2232 // | agg | n.a. | - | - | - | x[] | byref |
2233 //
2234 // | ptr | n.a. | | | - | | bycopy|
2235 // | ptr | n.a. | - | x | - | - | bycopy|
2236 // | ptr | n.a. | x | - | - | - | null |
2237 // | ptr | n.a. | - | - | - | x | byref |
2238 // | ptr | n.a. | - | - | - | x, x[] | bycopy|
2239 // | ptr | n.a. | - | - | - | x[] | bycopy|
2240 // | ptr | n.a. | - | - | x | | bycopy|
2241 // | ptr | n.a. | - | - | x | x | bycopy|
2242 // | ptr | n.a. | - | - | x | x[] | bycopy|
2243 // =========================================================================
2244 // Legend:
2245 // scl - scalar
2246 // ptr - pointer
2247 // agg - aggregate
2248 // x - applies
2249 // - - invalid in this combination
2250 // [] - mapped with an array section
2251 // byref - should be mapped by reference
2252 // byval - should be mapped by value
2253 // null - initialize a local variable to null on the device
2254 //
2255 // Observations:
2256 // - All scalar declarations that show up in a map clause have to be passed
2257 // by reference, because they may have been mapped in the enclosing data
2258 // environment.
2259 // - If the scalar value does not fit the size of uintptr, it has to be
2260 // passed by reference, regardless the result in the table above.
2261 // - For pointers mapped by value that have either an implicit map or an
2262 // array section, the runtime library may pass the NULL value to the
2263 // device instead of the value passed to it by the compiler.
2264 // - If both a pointer and a dereference of it are mapped, then the pointer
2265 // should be passed by reference.
2266
2267 if (Ty->isReferenceType())
2268 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2269
2270 // Locate map clauses and see if the variable being captured is mapped by
2271 // itself, or referred to, in any of those clauses. Here we only care about
2272 // variables, not fields, because fields are part of aggregates.
2273 bool IsVariableAssociatedWithSection = false;
2274 bool IsVariableItselfMapped = false;
2275
2276 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2277 VD: D, Level,
2278 Check: [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2279 &IsVariableItselfMapped,
2280 D](OMPClauseMappableExprCommon::MappableExprComponentListRef
2281 MapExprComponents,
2282 OpenMPClauseKind WhereFoundClauseKind) {
2283 // Both map and has_device_addr clauses information influences how a
2284 // variable is captured. E.g. is_device_ptr does not require changing
2285 // the default behavior.
2286 if (WhereFoundClauseKind != OMPC_map &&
2287 WhereFoundClauseKind != OMPC_has_device_addr)
2288 return false;
2289
2290 auto EI = MapExprComponents.rbegin();
2291 auto EE = MapExprComponents.rend();
2292
2293 assert(EI != EE && "Invalid map expression!");
2294
2295 if (isa<DeclRefExpr>(Val: EI->getAssociatedExpression()) &&
2296 EI->getAssociatedDeclaration() == D) {
2297 IsVariableUsedInMapClause = true;
2298
2299 // If the component list has only one element, it's for mapping the
2300 // variable itself, like map(p). This takes precedence in
2301 // determining how it's captured, so we don't need to look further
2302 // for any other maps that use the variable (like map(p[0]) etc.)
2303 if (MapExprComponents.size() == 1) {
2304 IsVariableItselfMapped = true;
2305 return true;
2306 }
2307 }
2308
2309 ++EI;
2310 if (EI == EE)
2311 return false;
2312 auto Last = std::prev(x: EE);
2313 const auto *UO =
2314 dyn_cast<UnaryOperator>(Val: Last->getAssociatedExpression());
2315 if ((UO && UO->getOpcode() == UO_Deref) ||
2316 isa<ArraySubscriptExpr>(Val: Last->getAssociatedExpression()) ||
2317 isa<ArraySectionExpr>(Val: Last->getAssociatedExpression()) ||
2318 isa<MemberExpr>(Val: EI->getAssociatedExpression()) ||
2319 isa<OMPArrayShapingExpr>(Val: Last->getAssociatedExpression())) {
2320 IsVariableAssociatedWithSection = true;
2321 // We've found a case like map(p[0]) or map(p->a) or map(*p),
2322 // so we are done with this particular map, but we need to keep
2323 // looking in case we find a map(p).
2324 return false;
2325 }
2326
2327 // Keep looking for more map info.
2328 return false;
2329 });
2330
2331 if (IsVariableUsedInMapClause) {
2332 // If variable is identified in a map clause it is always captured by
2333 // reference except if it is a pointer that is dereferenced somehow, but
2334 // not itself mapped.
2335 //
2336 // OpenMP 6.0, 7.1.1: Data sharing attribute rules, variables referenced
2337 // in a construct::
2338 // If a list item in a has_device_addr clause or in a map clause on the
2339 // target construct has a base pointer, and the base pointer is a scalar
2340 // variable *that is not a list item in a map clause on the construct*,
2341 // the base pointer is firstprivate.
2342 //
2343 // OpenMP 4.5, 2.15.1.1: Data-sharing Attribute Rules for Variables
2344 // Referenced in a Construct:
2345 // If an array section is a list item in a map clause on the target
2346 // construct and the array section is derived from a variable for which
2347 // the type is pointer then that variable is firstprivate.
2348 IsByRef = IsVariableItselfMapped ||
2349 !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2350 } else {
2351 // By default, all the data that has a scalar type is mapped by copy
2352 // (except for reduction variables).
2353 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2354 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2355 !Ty->isAnyPointerType()) ||
2356 !Ty->isScalarType() ||
2357 DSAStack->isDefaultmapCapturedByRef(
2358 Level, Kind: getVariableCategoryFromDecl(LO: getLangOpts(), VD: D)) ||
2359 DSAStack->hasExplicitDSA(
2360 D,
2361 CPred: [](OpenMPClauseKind K, bool AppliedToPointee) {
2362 return K == OMPC_reduction && !AppliedToPointee;
2363 },
2364 Level);
2365 }
2366 }
2367
2368 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2369 IsByRef =
2370 ((IsVariableUsedInMapClause &&
2371 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2372 OMPD_target) ||
2373 !(DSAStack->hasExplicitDSA(
2374 D,
2375 CPred: [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2376 return K == OMPC_firstprivate ||
2377 (K == OMPC_reduction && AppliedToPointee);
2378 },
2379 Level, /*NotLastprivate=*/true) ||
2380 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2381 // If the variable is artificial and must be captured by value - try to
2382 // capture by value.
2383 !(isa<OMPCapturedExprDecl>(Val: D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2384 !cast<OMPCapturedExprDecl>(Val: D)->getInit()->isGLValue()) &&
2385 // If the variable is implicitly firstprivate and scalar - capture by
2386 // copy
2387 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2388 DSAStack->getDefaultDSA() == DSA_private) &&
2389 !DSAStack->hasExplicitDSA(
2390 D, CPred: [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2391 Level) &&
2392 !DSAStack->isLoopControlVariable(D, Level).first);
2393 }
2394
2395 // When passing data by copy, we need to make sure it fits the uintptr size
2396 // and alignment, because the runtime library only deals with uintptr types.
2397 // If it does not fit the uintptr size, we need to pass the data by reference
2398 // instead.
2399 if (!IsByRef && (Ctx.getTypeSizeInChars(T: Ty) >
2400 Ctx.getTypeSizeInChars(T: Ctx.getUIntPtrType()) ||
2401 Ctx.getAlignOfGlobalVarInChars(T: Ty, VD: dyn_cast<VarDecl>(Val: D)) >
2402 Ctx.getTypeAlignInChars(T: Ctx.getUIntPtrType()))) {
2403 IsByRef = true;
2404 }
2405
2406 return IsByRef;
2407}
2408
2409unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2410 assert(getLangOpts().OpenMP);
2411 return DSAStack->getNestingLevel();
2412}
2413
2414bool SemaOpenMP::isInOpenMPTaskUntiedContext() const {
2415 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2416 DSAStack->isUntiedRegion();
2417}
2418
2419bool SemaOpenMP::isInOpenMPTargetExecutionDirective() const {
2420 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2421 !DSAStack->isClauseParsingMode()) ||
2422 DSAStack->hasDirective(
2423 DPred: [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2424 SourceLocation) -> bool {
2425 return isOpenMPTargetExecutionDirective(DKind: K);
2426 },
2427 FromParent: false);
2428}
2429
2430bool SemaOpenMP::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2431 // Only rebuild for Field.
2432 if (!isa<FieldDecl>(Val: D))
2433 return false;
2434 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2435 D,
2436 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2437 DefaultDataSharingAttributes DefaultAttr) {
2438 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2439 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2440 },
2441 DPred: [](OpenMPDirectiveKind) { return true; },
2442 DSAStack->isClauseParsingMode());
2443 if (DVarPrivate.CKind != OMPC_unknown)
2444 return true;
2445 return false;
2446}
2447
2448static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
2449 Expr *CaptureExpr, bool WithInit,
2450 DeclContext *CurContext,
2451 bool AsExpression);
2452
2453VarDecl *SemaOpenMP::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2454 unsigned StopAt) {
2455 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2456 D = getCanonicalDecl(D);
2457
2458 if (auto *BD = dyn_cast<BindingDecl>(Val: D)) {
2459 if (!BD->getHoldingVar())
2460 D = cast<VarDecl>(Val: BD->getDecomposedDecl());
2461 }
2462 auto *VD = dyn_cast<VarDecl>(Val: D);
2463 // Do not capture constexpr variables.
2464 if (VD && VD->isConstexpr())
2465 return nullptr;
2466
2467 // If we want to determine whether the variable should be captured from the
2468 // perspective of the current capturing scope, and we've already left all the
2469 // capturing scopes of the top directive on the stack, check from the
2470 // perspective of its parent directive (if any) instead.
2471 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2472 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2473
2474 // If we are attempting to capture a global variable in a directive with
2475 // 'target' we return true so that this global is also mapped to the device.
2476 //
2477 if (VD && !VD->hasLocalStorage() &&
2478 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2479 SemaRef.getCurLambda())) {
2480 if (isInOpenMPTargetExecutionDirective()) {
2481 DSAStackTy::DSAVarData DVarTop =
2482 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2483 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2484 return VD;
2485 // If the declaration is enclosed in a 'declare target' directive,
2486 // then it should not be captured.
2487 //
2488 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2489 return nullptr;
2490 CapturedRegionScopeInfo *CSI = nullptr;
2491 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2492 RangeOrContainer: llvm::reverse(C&: SemaRef.FunctionScopes),
2493 N: CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2494 : 0)) {
2495 if (!isa<CapturingScopeInfo>(Val: FSI))
2496 return nullptr;
2497 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(Val: FSI))
2498 if (RSI->CapRegionKind == CR_OpenMP) {
2499 CSI = RSI;
2500 break;
2501 }
2502 }
2503 // Lambdas and blocks at namespace scope have no enclosing function scope.
2504 if (!CSI)
2505 return nullptr;
2506 SmallVector<OpenMPDirectiveKind, 4> Regions;
2507 getOpenMPCaptureRegions(CaptureRegions&: Regions,
2508 DSAStack->getDirective(Level: CSI->OpenMPLevel));
2509 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2510 return VD;
2511 }
2512 if (isInOpenMPDeclareTargetContext()) {
2513 // Try to mark variable as declare target if it is used in capturing
2514 // regions.
2515 if (getLangOpts().OpenMP <= 45 &&
2516 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2517 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: VD);
2518 return nullptr;
2519 }
2520 }
2521
2522 if (CheckScopeInfo) {
2523 bool OpenMPFound = false;
2524 for (unsigned I = StopAt + 1; I > 0; --I) {
2525 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2526 if (!isa<CapturingScopeInfo>(Val: FSI))
2527 return nullptr;
2528 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(Val: FSI))
2529 if (RSI->CapRegionKind == CR_OpenMP) {
2530 OpenMPFound = true;
2531 break;
2532 }
2533 }
2534 if (!OpenMPFound)
2535 return nullptr;
2536 }
2537
2538 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2539 (!DSAStack->isClauseParsingMode() ||
2540 DSAStack->getParentDirective() != OMPD_unknown)) {
2541 auto &&Info = DSAStack->isLoopControlVariable(D);
2542 if (Info.first ||
2543 (VD && VD->hasLocalStorage() &&
2544 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2545 (VD && DSAStack->isForceVarCapturing()))
2546 return VD ? VD : Info.second;
2547 DSAStackTy::DSAVarData DVarTop =
2548 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2549 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(Kind: DVarTop.CKind) &&
2550 (!VD || VD->hasLocalStorage() ||
2551 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2552 return VD ? VD : cast<VarDecl>(Val: DVarTop.PrivateCopy->getDecl());
2553 // Threadprivate variables must not be captured.
2554 if (isOpenMPThreadPrivate(Kind: DVarTop.CKind))
2555 return nullptr;
2556 // The variable is not private or it is the variable in the directive with
2557 // default(none) clause and not used in any clause.
2558 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2559 D,
2560 CPred: [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2561 return isOpenMPPrivate(Kind: C) && !AppliedToPointee;
2562 },
2563 DPred: [](OpenMPDirectiveKind) { return true; },
2564 DSAStack->isClauseParsingMode());
2565 // Global shared must not be captured.
2566 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2567 ((DSAStack->getDefaultDSA() != DSA_none &&
2568 DSAStack->getDefaultDSA() != DSA_private &&
2569 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2570 DVarTop.CKind == OMPC_shared))
2571 return nullptr;
2572 auto *FD = dyn_cast<FieldDecl>(Val: D);
2573 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2574 !DVarPrivate.PrivateCopy) {
2575 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2576 D,
2577 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2578 DefaultDataSharingAttributes DefaultAttr) {
2579 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2580 (DefaultAttr == DSA_firstprivate ||
2581 DefaultAttr == DSA_private);
2582 },
2583 DPred: [](OpenMPDirectiveKind) { return true; },
2584 DSAStack->isClauseParsingMode());
2585 if (DVarPrivate.CKind == OMPC_unknown)
2586 return nullptr;
2587
2588 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2589 if (VD)
2590 return VD;
2591 if (SemaRef.getCurrentThisType().isNull())
2592 return nullptr;
2593 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(Loc: SourceLocation(),
2594 Type: SemaRef.getCurrentThisType(),
2595 /*IsImplicit=*/true);
2596 const CXXScopeSpec CS = CXXScopeSpec();
2597 Expr *ME = SemaRef.BuildMemberExpr(
2598 Base: ThisExpr, /*IsArrow=*/true, OpLoc: SourceLocation(),
2599 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: FD,
2600 FoundDecl: DeclAccessPair::make(D: FD, AS: FD->getAccess()),
2601 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(), Ty: FD->getType(),
2602 VK: VK_LValue, OK: OK_Ordinary);
2603 OMPCapturedExprDecl *CD = buildCaptureDecl(
2604 S&: SemaRef, Id: FD->getIdentifier(), CaptureExpr: ME, WithInit: DVarPrivate.CKind != OMPC_private,
2605 CurContext: SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2606 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2607 S&: SemaRef, D: CD, Ty: CD->getType().getNonReferenceType(), Loc: SourceLocation());
2608 VD = cast<VarDecl>(Val: VDPrivateRefExpr->getDecl());
2609 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2610 return VD;
2611 }
2612 if (DVarPrivate.CKind != OMPC_unknown ||
2613 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2614 DSAStack->getDefaultDSA() == DSA_private ||
2615 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2616 return VD ? VD : cast<VarDecl>(Val: DVarPrivate.PrivateCopy->getDecl());
2617 }
2618 return nullptr;
2619}
2620
2621void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2622 unsigned Level) const {
2623 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2624}
2625
2626void SemaOpenMP::startOpenMPLoop() {
2627 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2628 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2629 DSAStack->loopInit();
2630}
2631
2632void SemaOpenMP::startOpenMPCXXRangeFor() {
2633 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2634 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2635 DSAStack->resetPossibleLoopCounter();
2636 DSAStack->loopStart();
2637 }
2638}
2639
2640OpenMPClauseKind SemaOpenMP::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2641 unsigned CapLevel) const {
2642 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2643 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2644 (!DSAStack->isClauseParsingMode() ||
2645 DSAStack->getParentDirective() != OMPD_unknown)) {
2646 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2647 D,
2648 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2649 DefaultDataSharingAttributes DefaultAttr) {
2650 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2651 DefaultAttr == DSA_private;
2652 },
2653 DPred: [](OpenMPDirectiveKind) { return true; },
2654 DSAStack->isClauseParsingMode());
2655 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(Val: D) &&
2656 DSAStack->isImplicitDefaultFirstprivateFD(VD: cast<VarDecl>(Val: D)) &&
2657 !DSAStack->isLoopControlVariable(D).first)
2658 return OMPC_private;
2659 }
2660 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTaskingDirective, Level)) {
2661 bool IsTriviallyCopyable =
2662 D->getType().getNonReferenceType().isTriviallyCopyableType(
2663 Context: getASTContext()) &&
2664 !D->getType()
2665 .getNonReferenceType()
2666 .getCanonicalType()
2667 ->getAsCXXRecordDecl();
2668 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2669 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2670 getOpenMPCaptureRegions(CaptureRegions, DKind);
2671 if (isOpenMPTaskingDirective(Kind: CaptureRegions[CapLevel]) &&
2672 (IsTriviallyCopyable ||
2673 !isOpenMPTaskLoopDirective(DKind: CaptureRegions[CapLevel]))) {
2674 if (DSAStack->hasExplicitDSA(
2675 D,
2676 CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2677 Level, /*NotLastprivate=*/true))
2678 return OMPC_firstprivate;
2679 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2680 if (DVar.CKind != OMPC_shared &&
2681 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2682 DSAStack->addImplicitTaskFirstprivate(Level, D);
2683 return OMPC_firstprivate;
2684 }
2685 }
2686 }
2687 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2688 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2689 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2690 DSAStack->resetPossibleLoopCounter(D);
2691 DSAStack->loopStart();
2692 return OMPC_private;
2693 }
2694 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2695 DSAStack->isLoopControlVariable(D).first) &&
2696 !DSAStack->hasExplicitDSA(
2697 D, CPred: [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2698 Level) &&
2699 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2700 return OMPC_private;
2701 }
2702 if (const auto *VD = dyn_cast<VarDecl>(Val: D)) {
2703 if (DSAStack->isThreadPrivate(D: const_cast<VarDecl *>(VD)) &&
2704 DSAStack->isForceVarCapturing() &&
2705 !DSAStack->hasExplicitDSA(
2706 D, CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2707 Level))
2708 return OMPC_private;
2709 }
2710 // User-defined allocators are private since they must be defined in the
2711 // context of target region.
2712 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective, Level) &&
2713 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2714 u: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2715 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2716 return OMPC_private;
2717 return (DSAStack->hasExplicitDSA(
2718 D, CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2719 Level) ||
2720 (DSAStack->isClauseParsingMode() &&
2721 DSAStack->getClauseParsingMode() == OMPC_private) ||
2722 // Consider taskgroup reduction descriptor variable a private
2723 // to avoid possible capture in the region.
2724 (DSAStack->hasExplicitDirective(
2725 DPred: [](OpenMPDirectiveKind K) {
2726 return K == OMPD_taskgroup ||
2727 ((isOpenMPParallelDirective(DKind: K) ||
2728 isOpenMPWorksharingDirective(DKind: K)) &&
2729 !isOpenMPSimdDirective(DKind: K));
2730 },
2731 Level) &&
2732 DSAStack->isTaskgroupReductionRef(VD: D, Level)))
2733 ? OMPC_private
2734 : OMPC_unknown;
2735}
2736
2737void SemaOpenMP::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2738 unsigned Level) {
2739 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2740 D = getCanonicalDecl(D);
2741 OpenMPClauseKind OMPC = OMPC_unknown;
2742 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2743 const unsigned NewLevel = I - 1;
2744 if (DSAStack->hasExplicitDSA(
2745 D,
2746 CPred: [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2747 if (isOpenMPPrivate(Kind: K) && !AppliedToPointee) {
2748 OMPC = K;
2749 return true;
2750 }
2751 return false;
2752 },
2753 Level: NewLevel))
2754 break;
2755 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2756 VD: D, Level: NewLevel,
2757 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2758 OpenMPClauseKind) { return true; })) {
2759 OMPC = OMPC_map;
2760 break;
2761 }
2762 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective,
2763 Level: NewLevel)) {
2764 OMPC = OMPC_map;
2765 if (DSAStack->mustBeFirstprivateAtLevel(
2766 Level: NewLevel, Kind: getVariableCategoryFromDecl(LO: getLangOpts(), VD: D)))
2767 OMPC = OMPC_firstprivate;
2768 break;
2769 }
2770 }
2771 if (OMPC != OMPC_unknown)
2772 FD->addAttr(
2773 A: OMPCaptureKindAttr::CreateImplicit(Ctx&: getASTContext(), CaptureKindVal: unsigned(OMPC)));
2774}
2775
2776bool SemaOpenMP::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2777 unsigned CaptureLevel) const {
2778 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2779 // Return true if the current level is no longer enclosed in a target region.
2780
2781 SmallVector<OpenMPDirectiveKind, 4> Regions;
2782 getOpenMPCaptureRegions(CaptureRegions&: Regions, DSAStack->getDirective(Level));
2783 const auto *VD = dyn_cast<VarDecl>(Val: D);
2784 return VD && !VD->hasLocalStorage() &&
2785 DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective,
2786 Level) &&
2787 Regions[CaptureLevel] != OMPD_task;
2788}
2789
2790bool SemaOpenMP::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2791 unsigned CaptureLevel) const {
2792 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2793 // Return true if the current level is no longer enclosed in a target region.
2794
2795 if (const auto *VD = dyn_cast<VarDecl>(Val: D)) {
2796 if (!VD->hasLocalStorage()) {
2797 if (isInOpenMPTargetExecutionDirective())
2798 return true;
2799 DSAStackTy::DSAVarData TopDVar =
2800 DSAStack->getTopDSA(D, /*FromParent=*/false);
2801 unsigned NumLevels =
2802 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2803 if (Level == 0)
2804 // non-file scope static variable with default(firstprivate)
2805 // should be global captured.
2806 return (NumLevels == CaptureLevel + 1 &&
2807 (TopDVar.CKind != OMPC_shared ||
2808 DSAStack->getDefaultDSA() == DSA_firstprivate));
2809 do {
2810 --Level;
2811 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2812 if (DVar.CKind != OMPC_shared)
2813 return true;
2814 } while (Level > 0);
2815 }
2816 }
2817 return true;
2818}
2819
2820void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2821
2822void SemaOpenMP::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2823 OMPTraitInfo &TI) {
2824 OMPDeclareVariantScopes.push_back(Elt: OMPDeclareVariantScope(TI));
2825}
2826
2827void SemaOpenMP::ActOnOpenMPEndDeclareVariant() {
2828 assert(isInOpenMPDeclareVariantScope() &&
2829 "Not in OpenMP declare variant scope!");
2830
2831 OMPDeclareVariantScopes.pop_back();
2832}
2833
2834void SemaOpenMP::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2835 const FunctionDecl *Callee,
2836 SourceLocation Loc) {
2837 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2838 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2839 OMPDeclareTargetDeclAttr::getDeviceType(VD: Caller->getMostRecentDecl());
2840 // Ignore host functions during device analysis.
2841 if (getLangOpts().OpenMPIsTargetDevice &&
2842 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2843 return;
2844 // Ignore nohost functions during host analysis.
2845 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2846 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2847 return;
2848 const FunctionDecl *FD = Callee->getMostRecentDecl();
2849 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(VD: FD);
2850 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2851 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2852 // Diagnose host function called during device codegen.
2853 StringRef HostDevTy =
2854 getOpenMPSimpleClauseTypeName(Kind: OMPC_device_type, Type: OMPC_DEVICE_TYPE_host);
2855 Diag(Loc, DiagID: diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2856 Diag(Loc: *OMPDeclareTargetDeclAttr::getLocation(VD: FD),
2857 DiagID: diag::note_omp_marked_device_type_here)
2858 << HostDevTy;
2859 return;
2860 }
2861 if (!getLangOpts().OpenMPIsTargetDevice &&
2862 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2863 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2864 // In OpenMP 5.2 or later, if the function has a host variant then allow
2865 // that to be called instead
2866 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2867 for (OMPDeclareVariantAttr *A :
2868 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2869 auto *DeclRefVariant = cast<DeclRefExpr>(Val: A->getVariantFuncRef());
2870 auto *VariantFD = cast<FunctionDecl>(Val: DeclRefVariant->getDecl());
2871 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2872 OMPDeclareTargetDeclAttr::getDeviceType(
2873 VD: VariantFD->getMostRecentDecl());
2874 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2875 return true;
2876 }
2877 return false;
2878 };
2879 if (getLangOpts().OpenMP >= 52 &&
2880 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2881 return;
2882 // Diagnose nohost function called during host codegen.
2883 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2884 Kind: OMPC_device_type, Type: OMPC_DEVICE_TYPE_nohost);
2885 Diag(Loc, DiagID: diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2886 Diag(Loc: *OMPDeclareTargetDeclAttr::getLocation(VD: FD),
2887 DiagID: diag::note_omp_marked_device_type_here)
2888 << NoHostDevTy;
2889 }
2890}
2891
2892void SemaOpenMP::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2893 const DeclarationNameInfo &DirName,
2894 Scope *CurScope, SourceLocation Loc) {
2895 DSAStack->push(DKind, DirName, CurScope, Loc);
2896 SemaRef.PushExpressionEvaluationContext(
2897 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
2898}
2899
2900void SemaOpenMP::StartOpenMPClause(OpenMPClauseKind K) {
2901 DSAStack->setClauseParsingMode(K);
2902}
2903
2904void SemaOpenMP::EndOpenMPClause() {
2905 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2906 SemaRef.CleanupVarDeclMarking();
2907}
2908
2909static std::pair<ValueDecl *, bool>
2910getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2911 SourceRange &ERange, bool AllowArraySection = false,
2912 bool AllowAssumedSizeArray = false, StringRef DiagType = "");
2913
2914/// Check consistency of the reduction clauses.
2915static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2916 ArrayRef<OMPClause *> Clauses) {
2917 bool InscanFound = false;
2918 SourceLocation InscanLoc;
2919 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2920 // A reduction clause without the inscan reduction-modifier may not appear on
2921 // a construct on which a reduction clause with the inscan reduction-modifier
2922 // appears.
2923 for (OMPClause *C : Clauses) {
2924 if (C->getClauseKind() != OMPC_reduction)
2925 continue;
2926 auto *RC = cast<OMPReductionClause>(Val: C);
2927 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2928 InscanFound = true;
2929 InscanLoc = RC->getModifierLoc();
2930 continue;
2931 }
2932 if (RC->getModifier() == OMPC_REDUCTION_task) {
2933 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2934 // A reduction clause with the task reduction-modifier may only appear on
2935 // a parallel construct, a worksharing construct or a combined or
2936 // composite construct for which any of the aforementioned constructs is a
2937 // constituent construct and simd or loop are not constituent constructs.
2938 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2939 if (!(isOpenMPParallelDirective(DKind: CurDir) ||
2940 isOpenMPWorksharingDirective(DKind: CurDir)) ||
2941 isOpenMPSimdDirective(DKind: CurDir))
2942 S.Diag(Loc: RC->getModifierLoc(),
2943 DiagID: diag::err_omp_reduction_task_not_parallel_or_worksharing);
2944 continue;
2945 }
2946 }
2947 if (InscanFound) {
2948 for (OMPClause *C : Clauses) {
2949 if (C->getClauseKind() != OMPC_reduction)
2950 continue;
2951 auto *RC = cast<OMPReductionClause>(Val: C);
2952 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2953 S.Diag(Loc: RC->getModifier() == OMPC_REDUCTION_unknown
2954 ? RC->getBeginLoc()
2955 : RC->getModifierLoc(),
2956 DiagID: diag::err_omp_inscan_reduction_expected);
2957 S.Diag(Loc: InscanLoc, DiagID: diag::note_omp_previous_inscan_reduction);
2958 continue;
2959 }
2960 for (Expr *Ref : RC->varlist()) {
2961 assert(Ref && "NULL expr in OpenMP reduction clause.");
2962 SourceLocation ELoc;
2963 SourceRange ERange;
2964 Expr *SimpleRefExpr = Ref;
2965 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
2966 /*AllowArraySection=*/true);
2967 ValueDecl *D = Res.first;
2968 if (!D)
2969 continue;
2970 if (!Stack->isUsedInScanDirective(D: getCanonicalDecl(D))) {
2971 S.Diag(Loc: Ref->getExprLoc(),
2972 DiagID: diag::err_omp_reduction_not_inclusive_exclusive)
2973 << Ref->getSourceRange();
2974 }
2975 }
2976 }
2977 }
2978}
2979
2980static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2981 ArrayRef<OMPClause *> Clauses);
2982static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2983 bool WithInit);
2984
2985static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2986 const ValueDecl *D,
2987 const DSAStackTy::DSAVarData &DVar,
2988 bool IsLoopIterVar = false);
2989
2990void SemaOpenMP::EndOpenMPDSABlock(Stmt *CurDirective) {
2991 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2992 // A variable of class type (or array thereof) that appears in a lastprivate
2993 // clause requires an accessible, unambiguous default constructor for the
2994 // class type, unless the list item is also specified in a firstprivate
2995 // clause.
2996
2997 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2998 SmallVector<Expr *, 8> PrivateCopies;
2999 for (Expr *DE : Clause->varlist()) {
3000 if (DE->isValueDependent() || DE->isTypeDependent()) {
3001 PrivateCopies.push_back(Elt: nullptr);
3002 continue;
3003 }
3004 auto *DRE = cast<DeclRefExpr>(Val: DE->IgnoreParens());
3005 auto *D = DRE->getDecl();
3006 if (auto *BD = dyn_cast<BindingDecl>(Val: D)) {
3007 QualType Type = BD->getType().getNonReferenceType();
3008 const DSAStackTy::DSAVarData DVar =
3009 DSAStack->getTopDSA(D: BD, /*FromParent=*/false);
3010 if (DVar.CKind != OMPC_lastprivate) {
3011 // The variable is also a firstprivate, so initialization sequence
3012 // for private copy is generated already.
3013 PrivateCopies.push_back(Elt: nullptr);
3014 continue;
3015 }
3016 VarDecl *VDPrivate = buildVarDecl(
3017 SemaRef, Loc: DE->getExprLoc(), Type: Type.getUnqualifiedType(), Name: BD->getName(),
3018 Attrs: BD->hasAttrs() ? &BD->getAttrs() : nullptr, OrigRef: DRE);
3019 SemaRef.ActOnUninitializedDecl(dcl: VDPrivate);
3020 if (VDPrivate->isInvalidDecl()) {
3021 PrivateCopies.push_back(Elt: nullptr);
3022 continue;
3023 }
3024 PrivateCopies.push_back(Elt: buildDeclRefExpr(
3025 S&: SemaRef, D: VDPrivate, Ty: DE->getType(), Loc: DE->getExprLoc()));
3026 continue;
3027 }
3028 auto *VD = cast<VarDecl>(Val: D);
3029 QualType Type = VD->getType().getNonReferenceType();
3030 const DSAStackTy::DSAVarData DVar =
3031 DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
3032 if (DVar.CKind != OMPC_lastprivate) {
3033 // The variable is also a firstprivate, so initialization sequence
3034 // for private copy is generated already.
3035 PrivateCopies.push_back(Elt: nullptr);
3036 continue;
3037 }
3038 // Generate helper private variable and initialize it with the
3039 // default value. The address of the original variable is replaced
3040 // by the address of the new private variable in CodeGen. This new
3041 // variable is not added to IdResolver, so the code in the OpenMP
3042 // region uses original variable for proper diagnostics.
3043 VarDecl *VDPrivate = buildVarDecl(
3044 SemaRef, Loc: DE->getExprLoc(), Type: Type.getUnqualifiedType(), Name: VD->getName(),
3045 Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr, OrigRef: DRE);
3046 SemaRef.ActOnUninitializedDecl(dcl: VDPrivate);
3047 if (VDPrivate->isInvalidDecl()) {
3048 PrivateCopies.push_back(Elt: nullptr);
3049 continue;
3050 }
3051 PrivateCopies.push_back(Elt: buildDeclRefExpr(
3052 S&: SemaRef, D: VDPrivate, Ty: DE->getType(), Loc: DE->getExprLoc()));
3053 }
3054 Clause->setPrivateCopies(PrivateCopies);
3055 };
3056
3057 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
3058 // Finalize nontemporal clause by handling private copies, if any.
3059 SmallVector<Expr *, 8> PrivateRefs;
3060 for (Expr *RefExpr : Clause->varlist()) {
3061 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
3062 SourceLocation ELoc;
3063 SourceRange ERange;
3064 Expr *SimpleRefExpr = RefExpr;
3065 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
3066 if (Res.second)
3067 // It will be analyzed later.
3068 PrivateRefs.push_back(Elt: RefExpr);
3069 ValueDecl *D = Res.first;
3070 if (!D)
3071 continue;
3072
3073 const DSAStackTy::DSAVarData DVar =
3074 DSAStack->getTopDSA(D, /*FromParent=*/false);
3075 PrivateRefs.push_back(Elt: DVar.PrivateCopy ? DVar.PrivateCopy
3076 : SimpleRefExpr);
3077 }
3078 Clause->setPrivateRefs(PrivateRefs);
3079 };
3080
3081 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
3082 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3083 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
3084 auto *DRE = dyn_cast<DeclRefExpr>(Val: D.Allocator->IgnoreParenImpCasts());
3085 if (!DRE)
3086 continue;
3087 ValueDecl *VD = DRE->getDecl();
3088 if (!VD || !isa<VarDecl>(Val: VD))
3089 continue;
3090 DSAStackTy::DSAVarData DVar =
3091 DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
3092 // OpenMP [2.12.5, target Construct]
3093 // Memory allocators that appear in a uses_allocators clause cannot
3094 // appear in other data-sharing attribute clauses or data-mapping
3095 // attribute clauses in the same construct.
3096 Expr *MapExpr = nullptr;
3097 if (DVar.RefExpr ||
3098 DSAStack->checkMappableExprComponentListsForDecl(
3099 VD, /*CurrentRegionOnly=*/true,
3100 Check: [VD, &MapExpr](
3101 OMPClauseMappableExprCommon::MappableExprComponentListRef
3102 MapExprComponents,
3103 OpenMPClauseKind C) {
3104 auto MI = MapExprComponents.rbegin();
3105 auto ME = MapExprComponents.rend();
3106 if (MI != ME &&
3107 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3108 VD->getCanonicalDecl()) {
3109 MapExpr = MI->getAssociatedExpression();
3110 return true;
3111 }
3112 return false;
3113 })) {
3114 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::err_omp_allocator_used_in_clauses)
3115 << D.Allocator->getSourceRange();
3116 if (DVar.RefExpr)
3117 reportOriginalDsa(SemaRef, DSAStack, D: VD, DVar);
3118 else
3119 Diag(Loc: MapExpr->getExprLoc(), DiagID: diag::note_used_here)
3120 << MapExpr->getSourceRange();
3121 }
3122 }
3123 };
3124
3125 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(Val: CurDirective)) {
3126 for (OMPClause *C : D->clauses()) {
3127 if (auto *Clause = dyn_cast<OMPLastprivateClause>(Val: C)) {
3128 FinalizeLastprivate(Clause);
3129 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(Val: C)) {
3130 FinalizeNontemporal(Clause);
3131 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(Val: C)) {
3132 FinalizeAllocators(Clause);
3133 }
3134 }
3135 // Check allocate clauses.
3136 if (!SemaRef.CurContext->isDependentContext())
3137 checkAllocateClauses(S&: SemaRef, DSAStack, Clauses: D->clauses());
3138 checkReductionClauses(S&: SemaRef, DSAStack, Clauses: D->clauses());
3139 }
3140
3141 DSAStack->pop();
3142 SemaRef.DiscardCleanupsInEvaluationContext();
3143 SemaRef.PopExpressionEvaluationContext();
3144}
3145
3146static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3147 Expr *NumIterations, Sema &SemaRef,
3148 Scope *S, DSAStackTy *Stack);
3149
3150static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
3151 OMPLoopBasedDirective::HelperExprs &B,
3152 DSAStackTy *Stack) {
3153 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3154 "loop exprs were not built");
3155
3156 if (SemaRef.CurContext->isDependentContext())
3157 return false;
3158
3159 // Finalize the clauses that need pre-built expressions for CodeGen.
3160 for (OMPClause *C : Clauses) {
3161 auto *LC = dyn_cast<OMPLinearClause>(Val: C);
3162 if (!LC)
3163 continue;
3164 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
3165 NumIterations: B.NumIterations, SemaRef,
3166 S: SemaRef.getCurScope(), Stack))
3167 return true;
3168 }
3169
3170 return false;
3171}
3172
3173namespace {
3174
3175class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3176private:
3177 Sema &SemaRef;
3178
3179public:
3180 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3181 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3182 NamedDecl *ND = Candidate.getCorrectionDecl();
3183 if (const auto *VD = dyn_cast_or_null<VarDecl>(Val: ND)) {
3184 return VD->hasGlobalStorage() &&
3185 SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(),
3186 S: SemaRef.getCurScope());
3187 }
3188 return false;
3189 }
3190
3191 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3192 return std::make_unique<VarDeclFilterCCC>(args&: *this);
3193 }
3194};
3195
3196class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3197private:
3198 Sema &SemaRef;
3199
3200public:
3201 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3202 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3203 NamedDecl *ND = Candidate.getCorrectionDecl();
3204 if (ND && ((isa<VarDecl>(Val: ND) && ND->getKind() == Decl::Var) ||
3205 isa<FunctionDecl>(Val: ND))) {
3206 return SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(),
3207 S: SemaRef.getCurScope());
3208 }
3209 return false;
3210 }
3211
3212 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3213 return std::make_unique<VarOrFuncDeclFilterCCC>(args&: *this);
3214 }
3215};
3216
3217} // namespace
3218
3219ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope,
3220 CXXScopeSpec &ScopeSpec,
3221 const DeclarationNameInfo &Id,
3222 OpenMPDirectiveKind Kind) {
3223 ASTContext &Context = getASTContext();
3224 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
3225 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
3226 SemaRef.LookupParsedName(R&: Lookup, S: CurScope, SS: &ScopeSpec,
3227 /*ObjectType=*/QualType(),
3228 /*AllowBuiltinCreation=*/true);
3229
3230 if (Lookup.isAmbiguous())
3231 return ExprError();
3232
3233 VarDecl *VD;
3234 if (!Lookup.isSingleResult()) {
3235 VarDeclFilterCCC CCC(SemaRef);
3236 if (TypoCorrection Corrected =
3237 SemaRef.CorrectTypo(Typo: Id, LookupKind: Sema::LookupOrdinaryName, S: CurScope, SS: nullptr,
3238 CCC, Mode: CorrectTypoKind::ErrorRecovery)) {
3239 SemaRef.diagnoseTypo(
3240 Correction: Corrected,
3241 TypoDiag: SemaRef.PDiag(DiagID: Lookup.empty() ? diag::err_undeclared_var_use_suggest
3242 : diag::err_omp_expected_var_arg_suggest)
3243 << Id.getName());
3244 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3245 } else {
3246 Diag(Loc: Id.getLoc(), DiagID: Lookup.empty() ? diag::err_undeclared_var_use
3247 : diag::err_omp_expected_var_arg)
3248 << Id.getName();
3249 return ExprError();
3250 }
3251 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3252 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_expected_var_arg) << Id.getName();
3253 Diag(Loc: Lookup.getFoundDecl()->getLocation(), DiagID: diag::note_declared_at);
3254 return ExprError();
3255 }
3256 Lookup.suppressDiagnostics();
3257
3258 // OpenMP [2.9.2, Syntax, C/C++]
3259 // Variables must be file-scope, namespace-scope, or static block-scope.
3260 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3261 !VD->hasGlobalStorage()) {
3262 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_global_var_arg)
3263 << getOpenMPDirectiveName(D: Kind, V: OMPVersion) << !VD->isStaticLocal();
3264 bool IsDecl =
3265 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3266 Diag(Loc: VD->getLocation(),
3267 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3268 << VD;
3269 return ExprError();
3270 }
3271
3272 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3273 NamedDecl *ND = CanonicalVD;
3274 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3275 // A threadprivate or groupprivate directive for file-scope variables must
3276 // appear outside any definition or declaration.
3277 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3278 !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3279 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3280 << getOpenMPDirectiveName(D: Kind, V: OMPVersion) << VD;
3281 bool IsDecl =
3282 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3283 Diag(Loc: VD->getLocation(),
3284 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3285 << VD;
3286 return ExprError();
3287 }
3288 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3289 // A threadprivate or groupprivate directive for static class member
3290 // variables must appear in the class definition, in the same scope in which
3291 // the member variables are declared.
3292 if (CanonicalVD->isStaticDataMember() &&
3293 !CanonicalVD->getDeclContext()->Equals(DC: SemaRef.getCurLexicalContext())) {
3294 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3295 << getOpenMPDirectiveName(D: Kind, V: OMPVersion) << VD;
3296 bool IsDecl =
3297 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3298 Diag(Loc: VD->getLocation(),
3299 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3300 << VD;
3301 return ExprError();
3302 }
3303 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3304 // A threadprivate or groupprivate directive for namespace-scope variables
3305 // must appear outside any definition or declaration other than the
3306 // namespace definition itself.
3307 if (CanonicalVD->getDeclContext()->isNamespace() &&
3308 (!SemaRef.getCurLexicalContext()->isFileContext() ||
3309 !SemaRef.getCurLexicalContext()->Encloses(
3310 DC: CanonicalVD->getDeclContext()))) {
3311 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3312 << getOpenMPDirectiveName(D: Kind, V: OMPVersion) << VD;
3313 bool IsDecl =
3314 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3315 Diag(Loc: VD->getLocation(),
3316 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3317 << VD;
3318 return ExprError();
3319 }
3320 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3321 // A threadprivate or groupprivate directive for static block-scope
3322 // variables must appear in the scope of the variable and not in a nested
3323 // scope.
3324 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3325 !SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(), S: CurScope)) {
3326 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3327 << getOpenMPDirectiveName(D: Kind, V: OMPVersion) << VD;
3328 bool IsDecl =
3329 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3330 Diag(Loc: VD->getLocation(),
3331 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3332 << VD;
3333 return ExprError();
3334 }
3335
3336 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3337 // A threadprivate or groupprivate directive must lexically precede all
3338 // references to any of the variables in its list.
3339 if ((Kind == OMPD_threadprivate && VD->isUsed() &&
3340 !DSAStack->isThreadPrivate(D: VD)) ||
3341 (Kind == OMPD_groupprivate && VD->isUsed())) {
3342 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_used)
3343 << getOpenMPDirectiveName(D: Kind, V: OMPVersion) << VD;
3344 return ExprError();
3345 }
3346
3347 QualType ExprType = VD->getType().getNonReferenceType();
3348 return DeclRefExpr::Create(Context, QualifierLoc: NestedNameSpecifierLoc(),
3349 TemplateKWLoc: SourceLocation(), D: VD,
3350 /*RefersToEnclosingVariableOrCapture=*/false,
3351 NameLoc: Id.getLoc(), T: ExprType, VK: VK_LValue);
3352}
3353
3354SemaOpenMP::DeclGroupPtrTy
3355SemaOpenMP::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3356 ArrayRef<Expr *> VarList) {
3357 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3358 SemaRef.CurContext->addDecl(D);
3359 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3360 }
3361 return nullptr;
3362}
3363
3364SemaOpenMP::DeclGroupPtrTy
3365SemaOpenMP::ActOnOpenMPGroupPrivateDirective(SourceLocation Loc,
3366 ArrayRef<Expr *> VarList) {
3367 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
3368 if (!OMPVersion || OMPVersion < 60) {
3369 Diag(Loc, DiagID: diag::err_omp_unexpected_directive)
3370 << getOpenMPDirectiveName(D: OMPD_groupprivate, V: OMPVersion);
3371 return nullptr;
3372 }
3373 if (OMPGroupPrivateDecl *D = CheckOMPGroupPrivateDecl(Loc, VarList)) {
3374 SemaRef.CurContext->addDecl(D);
3375 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3376 }
3377 return nullptr;
3378}
3379
3380namespace {
3381class LocalVarRefChecker final
3382 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3383 Sema &SemaRef;
3384
3385public:
3386 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3387 if (const auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
3388 if (VD->hasLocalStorage()) {
3389 SemaRef.Diag(Loc: E->getBeginLoc(),
3390 DiagID: diag::err_omp_local_var_in_threadprivate_init)
3391 << E->getSourceRange();
3392 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::note_defined_here)
3393 << VD << VD->getSourceRange();
3394 return true;
3395 }
3396 }
3397 return false;
3398 }
3399 bool VisitStmt(const Stmt *S) {
3400 for (const Stmt *Child : S->children()) {
3401 if (Child && Visit(S: Child))
3402 return true;
3403 }
3404 return false;
3405 }
3406 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3407};
3408} // namespace
3409
3410OMPThreadPrivateDecl *
3411SemaOpenMP::CheckOMPThreadPrivateDecl(SourceLocation Loc,
3412 ArrayRef<Expr *> VarList) {
3413 ASTContext &Context = getASTContext();
3414 SmallVector<Expr *, 8> Vars;
3415 for (Expr *RefExpr : VarList) {
3416 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3417 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3418 SourceLocation ILoc = DE->getExprLoc();
3419
3420 // Mark variable as used.
3421 VD->setReferenced();
3422 VD->markUsed(C&: Context);
3423
3424 QualType QType = VD->getType();
3425 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3426 // It will be analyzed later.
3427 Vars.push_back(Elt: DE);
3428 continue;
3429 }
3430
3431 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3432 // A threadprivate variable must not have an incomplete type.
3433 if (SemaRef.RequireCompleteType(
3434 Loc: ILoc, T: VD->getType(), DiagID: diag::err_omp_threadprivate_incomplete_type)) {
3435 continue;
3436 }
3437
3438 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3439 // A threadprivate variable must not have a reference type.
3440 if (VD->getType()->isReferenceType()) {
3441 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
3442 Diag(Loc: ILoc, DiagID: diag::err_omp_ref_type_arg)
3443 << getOpenMPDirectiveName(D: OMPD_threadprivate, V: OMPVersion)
3444 << VD->getType();
3445 bool IsDecl =
3446 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3447 Diag(Loc: VD->getLocation(),
3448 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3449 << VD;
3450 continue;
3451 }
3452
3453 // Check if this is a TLS variable. If TLS is not being supported, produce
3454 // the corresponding diagnostic.
3455 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3456 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3457 getLangOpts().OpenMPUseTLS &&
3458 getASTContext().getTargetInfo().isTLSSupported())) ||
3459 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3460 !VD->isLocalVarDecl())) {
3461 Diag(Loc: ILoc, DiagID: diag::err_omp_var_thread_local)
3462 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3463 bool IsDecl =
3464 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3465 Diag(Loc: VD->getLocation(),
3466 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3467 << VD;
3468 continue;
3469 }
3470
3471 // Check if initial value of threadprivate variable reference variable with
3472 // local storage (it is not supported by runtime).
3473 if (const Expr *Init = VD->getAnyInitializer()) {
3474 LocalVarRefChecker Checker(SemaRef);
3475 if (Checker.Visit(S: Init))
3476 continue;
3477 }
3478
3479 Vars.push_back(Elt: RefExpr);
3480 DSAStack->addDSA(D: VD, E: DE, A: OMPC_threadprivate);
3481 VD->addAttr(A: OMPThreadPrivateDeclAttr::CreateImplicit(
3482 Ctx&: Context, Range: SourceRange(Loc, Loc)));
3483 if (ASTMutationListener *ML = Context.getASTMutationListener())
3484 ML->DeclarationMarkedOpenMPThreadPrivate(D: VD);
3485 }
3486 OMPThreadPrivateDecl *D = nullptr;
3487 if (!Vars.empty()) {
3488 D = OMPThreadPrivateDecl::Create(C&: Context, DC: SemaRef.getCurLexicalContext(),
3489 L: Loc, VL: Vars);
3490 D->setAccess(AS_public);
3491 }
3492 return D;
3493}
3494
3495OMPGroupPrivateDecl *
3496SemaOpenMP::CheckOMPGroupPrivateDecl(SourceLocation Loc,
3497 ArrayRef<Expr *> VarList) {
3498 ASTContext &Context = getASTContext();
3499 SmallVector<Expr *, 8> Vars;
3500 for (Expr *RefExpr : VarList) {
3501 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3502 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3503 SourceLocation ILoc = DE->getExprLoc();
3504
3505 // Mark variable as used.
3506 VD->setReferenced();
3507 VD->markUsed(C&: Context);
3508
3509 QualType QType = VD->getType();
3510 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3511 // It will be analyzed later.
3512 Vars.push_back(Elt: DE);
3513 continue;
3514 }
3515
3516 // OpenMP groupprivate restrictions:
3517 // A groupprivate variable must not have an incomplete type.
3518 if (SemaRef.RequireCompleteType(
3519 Loc: ILoc, T: VD->getType(), DiagID: diag::err_omp_groupprivate_incomplete_type)) {
3520 continue;
3521 }
3522
3523 // A groupprivate variable must not have a reference type.
3524 if (VD->getType()->isReferenceType()) {
3525 Diag(Loc: ILoc, DiagID: diag::err_omp_ref_type_arg)
3526 << getOpenMPDirectiveName(D: OMPD_groupprivate) << VD->getType();
3527 bool IsDecl =
3528 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3529 Diag(Loc: VD->getLocation(),
3530 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3531 << VD;
3532 continue;
3533 }
3534
3535 // A variable that is declared with an initializer must not appear in a
3536 // groupprivate directive.
3537 if (VD->getAnyInitializer()) {
3538 Diag(Loc: ILoc, DiagID: diag::err_omp_groupprivate_with_initializer)
3539 << VD->getDeclName();
3540 bool IsDecl =
3541 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3542 Diag(Loc: VD->getLocation(),
3543 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3544 << VD;
3545 continue;
3546 }
3547
3548 Vars.push_back(Elt: RefExpr);
3549 DSAStack->addDSA(D: VD, E: DE, A: OMPC_groupprivate);
3550 VD->addAttr(A: OMPGroupPrivateDeclAttr::CreateImplicit(Ctx&: Context,
3551 Range: SourceRange(Loc, Loc)));
3552 if (ASTMutationListener *ML = Context.getASTMutationListener())
3553 ML->DeclarationMarkedOpenMPGroupPrivate(D: VD);
3554 }
3555 OMPGroupPrivateDecl *D = nullptr;
3556 if (!Vars.empty()) {
3557 D = OMPGroupPrivateDecl::Create(C&: Context, DC: SemaRef.getCurLexicalContext(),
3558 L: Loc, VL: Vars);
3559 D->setAccess(AS_public);
3560 }
3561 return D;
3562}
3563
3564static OMPAllocateDeclAttr::AllocatorTypeTy
3565getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3566 if (!Allocator)
3567 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3568 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3569 Allocator->isInstantiationDependent() ||
3570 Allocator->containsUnexpandedParameterPack())
3571 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3572 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3573 llvm::FoldingSetNodeID AEId;
3574 const Expr *AE = Allocator->IgnoreParenImpCasts();
3575 AE->IgnoreImpCasts()->Profile(ID&: AEId, Context: S.getASTContext(), /*Canonical=*/true);
3576 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3577 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3578 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3579 llvm::FoldingSetNodeID DAEId;
3580 DefAllocator->IgnoreImpCasts()->Profile(ID&: DAEId, Context: S.getASTContext(),
3581 /*Canonical=*/true);
3582 if (AEId == DAEId) {
3583 AllocatorKindRes = AllocatorKind;
3584 break;
3585 }
3586 }
3587 return AllocatorKindRes;
3588}
3589
3590static bool checkPreviousOMPAllocateAttribute(
3591 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3592 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3593 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3594 return false;
3595 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3596 Expr *PrevAllocator = A->getAllocator();
3597 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3598 getAllocatorKind(S, Stack, Allocator: PrevAllocator);
3599 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3600 if (AllocatorsMatch &&
3601 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3602 Allocator && PrevAllocator) {
3603 const Expr *AE = Allocator->IgnoreParenImpCasts();
3604 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3605 llvm::FoldingSetNodeID AEId, PAEId;
3606 AE->Profile(ID&: AEId, Context: S.Context, /*Canonical=*/true);
3607 PAE->Profile(ID&: PAEId, Context: S.Context, /*Canonical=*/true);
3608 AllocatorsMatch = AEId == PAEId;
3609 }
3610 if (!AllocatorsMatch) {
3611 SmallString<256> AllocatorBuffer;
3612 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3613 if (Allocator)
3614 Allocator->printPretty(OS&: AllocatorStream, Helper: nullptr, Policy: S.getPrintingPolicy());
3615 SmallString<256> PrevAllocatorBuffer;
3616 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3617 if (PrevAllocator)
3618 PrevAllocator->printPretty(OS&: PrevAllocatorStream, Helper: nullptr,
3619 Policy: S.getPrintingPolicy());
3620
3621 SourceLocation AllocatorLoc =
3622 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3623 SourceRange AllocatorRange =
3624 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3625 SourceLocation PrevAllocatorLoc =
3626 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3627 SourceRange PrevAllocatorRange =
3628 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3629 S.Diag(Loc: AllocatorLoc, DiagID: diag::warn_omp_used_different_allocator)
3630 << (Allocator ? 1 : 0) << AllocatorStream.str()
3631 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3632 << AllocatorRange;
3633 S.Diag(Loc: PrevAllocatorLoc, DiagID: diag::note_omp_previous_allocator)
3634 << PrevAllocatorRange;
3635 return true;
3636 }
3637 return false;
3638}
3639
3640static void
3641applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3642 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3643 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3644 if (VD->hasAttr<OMPAllocateDeclAttr>())
3645 return;
3646 if (Alignment &&
3647 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3648 Alignment->isInstantiationDependent() ||
3649 Alignment->containsUnexpandedParameterPack()))
3650 // Apply later when we have a usable value.
3651 return;
3652 if (Allocator &&
3653 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3654 Allocator->isInstantiationDependent() ||
3655 Allocator->containsUnexpandedParameterPack()))
3656 return;
3657 auto *A = OMPAllocateDeclAttr::CreateImplicit(Ctx&: S.Context, AllocatorType: AllocatorKind,
3658 Allocator, Alignment, Range: SR);
3659 VD->addAttr(A);
3660 if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3661 ML->DeclarationMarkedOpenMPAllocate(D: VD, A);
3662}
3663
3664SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPAllocateDirective(
3665 SourceLocation Loc, ArrayRef<Expr *> VarList, ArrayRef<OMPClause *> Clauses,
3666 DeclContext *Owner) {
3667 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3668 Expr *Alignment = nullptr;
3669 Expr *Allocator = nullptr;
3670 if (Clauses.empty()) {
3671 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3672 // allocate directives that appear in a target region must specify an
3673 // allocator clause unless a requires directive with the dynamic_allocators
3674 // clause is present in the same compilation unit.
3675 if (getLangOpts().OpenMPIsTargetDevice &&
3676 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3677 SemaRef.targetDiag(Loc, DiagID: diag::err_expected_allocator_clause);
3678 } else {
3679 for (const OMPClause *C : Clauses)
3680 if (const auto *AC = dyn_cast<OMPAllocatorClause>(Val: C))
3681 Allocator = AC->getAllocator();
3682 else if (const auto *AC = dyn_cast<OMPAlignClause>(Val: C))
3683 Alignment = AC->getAlignment();
3684 else
3685 llvm_unreachable("Unexpected clause on allocate directive");
3686 }
3687 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3688 getAllocatorKind(S&: SemaRef, DSAStack, Allocator);
3689 SmallVector<Expr *, 8> Vars;
3690 for (Expr *RefExpr : VarList) {
3691 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3692 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3693
3694 // Check if this is a TLS variable or global register.
3695 if (VD->getTLSKind() != VarDecl::TLS_None ||
3696 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3697 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3698 !VD->isLocalVarDecl()))
3699 continue;
3700
3701 // If the used several times in the allocate directive, the same allocator
3702 // must be used.
3703 if (checkPreviousOMPAllocateAttribute(S&: SemaRef, DSAStack, RefExpr, VD,
3704 AllocatorKind, Allocator))
3705 continue;
3706
3707 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3708 // If a list item has a static storage type, the allocator expression in the
3709 // allocator clause must be a constant expression that evaluates to one of
3710 // the predefined memory allocator values.
3711 if (Allocator && VD->hasGlobalStorage()) {
3712 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3713 Diag(Loc: Allocator->getExprLoc(),
3714 DiagID: diag::err_omp_expected_predefined_allocator)
3715 << Allocator->getSourceRange();
3716 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3717 VarDecl::DeclarationOnly;
3718 Diag(Loc: VD->getLocation(),
3719 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3720 << VD;
3721 continue;
3722 }
3723 }
3724
3725 Vars.push_back(Elt: RefExpr);
3726 applyOMPAllocateAttribute(S&: SemaRef, VD, AllocatorKind, Allocator, Alignment,
3727 SR: DE->getSourceRange());
3728 }
3729 if (Vars.empty())
3730 return nullptr;
3731 if (!Owner)
3732 Owner = SemaRef.getCurLexicalContext();
3733 auto *D = OMPAllocateDecl::Create(C&: getASTContext(), DC: Owner, L: Loc, VL: Vars, CL: Clauses);
3734 D->setAccess(AS_public);
3735 Owner->addDecl(D);
3736 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3737}
3738
3739SemaOpenMP::DeclGroupPtrTy
3740SemaOpenMP::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3741 ArrayRef<OMPClause *> ClauseList) {
3742 OMPRequiresDecl *D = nullptr;
3743 if (!SemaRef.CurContext->isFileContext()) {
3744 Diag(Loc, DiagID: diag::err_omp_invalid_scope) << "requires";
3745 } else {
3746 D = CheckOMPRequiresDecl(Loc, Clauses: ClauseList);
3747 if (D) {
3748 SemaRef.CurContext->addDecl(D);
3749 DSAStack->addRequiresDecl(RD: D);
3750 }
3751 }
3752 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3753}
3754
3755void SemaOpenMP::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3756 OpenMPDirectiveKind DKind,
3757 ArrayRef<std::string> Assumptions,
3758 bool SkippedClauses) {
3759 if (!SkippedClauses && Assumptions.empty()) {
3760 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
3761 Diag(Loc, DiagID: diag::err_omp_no_clause_for_directive)
3762 << llvm::omp::getAllAssumeClauseOptions()
3763 << llvm::omp::getOpenMPDirectiveName(D: DKind, V: OMPVersion);
3764 }
3765
3766 auto *AA =
3767 OMPAssumeAttr::Create(Ctx&: getASTContext(), Assumption: llvm::join(R&: Assumptions, Separator: ","), Range: Loc);
3768 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3769 OMPAssumeScoped.push_back(Elt: AA);
3770 return;
3771 }
3772
3773 // Global assumes without assumption clauses are ignored.
3774 if (Assumptions.empty())
3775 return;
3776
3777 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3778 "Unexpected omp assumption directive!");
3779 OMPAssumeGlobal.push_back(Elt: AA);
3780
3781 // The OMPAssumeGlobal scope above will take care of new declarations but
3782 // we also want to apply the assumption to existing ones, e.g., to
3783 // declarations in included headers. To this end, we traverse all existing
3784 // declaration contexts and annotate function declarations here.
3785 SmallVector<DeclContext *, 8> DeclContexts;
3786 auto *Ctx = SemaRef.CurContext;
3787 while (Ctx->getLexicalParent())
3788 Ctx = Ctx->getLexicalParent();
3789 DeclContexts.push_back(Elt: Ctx);
3790 while (!DeclContexts.empty()) {
3791 DeclContext *DC = DeclContexts.pop_back_val();
3792 for (auto *SubDC : DC->decls()) {
3793 if (SubDC->isInvalidDecl())
3794 continue;
3795 if (auto *CTD = dyn_cast<ClassTemplateDecl>(Val: SubDC)) {
3796 DeclContexts.push_back(Elt: CTD->getTemplatedDecl());
3797 llvm::append_range(C&: DeclContexts, R: CTD->specializations());
3798 continue;
3799 }
3800 if (auto *DC = dyn_cast<DeclContext>(Val: SubDC))
3801 DeclContexts.push_back(Elt: DC);
3802 if (auto *F = dyn_cast<FunctionDecl>(Val: SubDC)) {
3803 F->addAttr(A: AA);
3804 continue;
3805 }
3806 }
3807 }
3808}
3809
3810void SemaOpenMP::ActOnOpenMPEndAssumesDirective() {
3811 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3812 OMPAssumeScoped.pop_back();
3813}
3814
3815StmtResult SemaOpenMP::ActOnOpenMPAssumeDirective(ArrayRef<OMPClause *> Clauses,
3816 Stmt *AStmt,
3817 SourceLocation StartLoc,
3818 SourceLocation EndLoc) {
3819 if (!AStmt)
3820 return StmtError();
3821
3822 return OMPAssumeDirective::Create(Ctx: getASTContext(), StartLoc, EndLoc, Clauses,
3823 AStmt);
3824}
3825
3826OMPRequiresDecl *
3827SemaOpenMP::CheckOMPRequiresDecl(SourceLocation Loc,
3828 ArrayRef<OMPClause *> ClauseList) {
3829 /// For target specific clauses, the requires directive cannot be
3830 /// specified after the handling of any of the target regions in the
3831 /// current compilation unit.
3832 ArrayRef<SourceLocation> TargetLocations =
3833 DSAStack->getEncounteredTargetLocs();
3834 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3835 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3836 for (const OMPClause *CNew : ClauseList) {
3837 // Check if any of the requires clauses affect target regions.
3838 if (isa<OMPUnifiedSharedMemoryClause>(Val: CNew) ||
3839 isa<OMPUnifiedAddressClause>(Val: CNew) ||
3840 isa<OMPReverseOffloadClause>(Val: CNew) ||
3841 isa<OMPDynamicAllocatorsClause>(Val: CNew)) {
3842 Diag(Loc, DiagID: diag::err_omp_directive_before_requires)
3843 << "target" << getOpenMPClauseNameForDiag(C: CNew->getClauseKind());
3844 for (SourceLocation TargetLoc : TargetLocations) {
3845 Diag(Loc: TargetLoc, DiagID: diag::note_omp_requires_encountered_directive)
3846 << "target";
3847 }
3848 } else if (!AtomicLoc.isInvalid() &&
3849 isa<OMPAtomicDefaultMemOrderClause>(Val: CNew)) {
3850 Diag(Loc, DiagID: diag::err_omp_directive_before_requires)
3851 << "atomic" << getOpenMPClauseNameForDiag(C: CNew->getClauseKind());
3852 Diag(Loc: AtomicLoc, DiagID: diag::note_omp_requires_encountered_directive)
3853 << "atomic";
3854 }
3855 }
3856 }
3857
3858 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3859 return OMPRequiresDecl::Create(
3860 C&: getASTContext(), DC: SemaRef.getCurLexicalContext(), L: Loc, CL: ClauseList);
3861 return nullptr;
3862}
3863
3864static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3865 const ValueDecl *D,
3866 const DSAStackTy::DSAVarData &DVar,
3867 bool IsLoopIterVar) {
3868 if (DVar.RefExpr) {
3869 SemaRef.Diag(Loc: DVar.RefExpr->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
3870 << getOpenMPClauseNameForDiag(C: DVar.CKind);
3871 return;
3872 }
3873 enum {
3874 PDSA_StaticMemberShared,
3875 PDSA_StaticLocalVarShared,
3876 PDSA_LoopIterVarPrivate,
3877 PDSA_LoopIterVarLinear,
3878 PDSA_LoopIterVarLastprivate,
3879 PDSA_ConstVarShared,
3880 PDSA_GlobalVarShared,
3881 PDSA_TaskVarFirstprivate,
3882 PDSA_LocalVarPrivate,
3883 PDSA_Implicit
3884 } Reason = PDSA_Implicit;
3885 bool ReportHint = false;
3886 auto ReportLoc = D->getLocation();
3887 auto *VD = dyn_cast<VarDecl>(Val: D);
3888 if (IsLoopIterVar) {
3889 if (DVar.CKind == OMPC_private)
3890 Reason = PDSA_LoopIterVarPrivate;
3891 else if (DVar.CKind == OMPC_lastprivate)
3892 Reason = PDSA_LoopIterVarLastprivate;
3893 else
3894 Reason = PDSA_LoopIterVarLinear;
3895 } else if (isOpenMPTaskingDirective(Kind: DVar.DKind) &&
3896 DVar.CKind == OMPC_firstprivate) {
3897 Reason = PDSA_TaskVarFirstprivate;
3898 ReportLoc = DVar.ImplicitDSALoc;
3899 } else if (VD && VD->isStaticLocal())
3900 Reason = PDSA_StaticLocalVarShared;
3901 else if (VD && VD->isStaticDataMember())
3902 Reason = PDSA_StaticMemberShared;
3903 else if (VD && VD->isFileVarDecl())
3904 Reason = PDSA_GlobalVarShared;
3905 else if (D->getType().isConstant(Ctx: SemaRef.getASTContext()))
3906 Reason = PDSA_ConstVarShared;
3907 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3908 ReportHint = true;
3909 Reason = PDSA_LocalVarPrivate;
3910 }
3911 if (Reason != PDSA_Implicit) {
3912 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
3913 SemaRef.Diag(Loc: ReportLoc, DiagID: diag::note_omp_predetermined_dsa)
3914 << Reason << ReportHint
3915 << getOpenMPDirectiveName(D: Stack->getCurrentDirective(), V: OMPVersion);
3916 } else if (DVar.ImplicitDSALoc.isValid()) {
3917 SemaRef.Diag(Loc: DVar.ImplicitDSALoc, DiagID: diag::note_omp_implicit_dsa)
3918 << getOpenMPClauseNameForDiag(C: DVar.CKind);
3919 }
3920}
3921
3922namespace {
3923/// Visitor to collect variables used in a statement.
3924class VarUsageVisitor : public DynamicRecursiveASTVisitor {
3925 llvm::SmallPtrSet<const VarDecl *, 8> &UsedVars;
3926 llvm::SmallPtrSet<const BindingDecl *, 8> &UsedBindings;
3927
3928public:
3929 VarUsageVisitor(llvm::SmallPtrSet<const VarDecl *, 8> &UsedVars,
3930 llvm::SmallPtrSet<const BindingDecl *, 8> &UsedBindings)
3931 : UsedVars(UsedVars), UsedBindings(UsedBindings) {}
3932
3933 bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
3934 if (auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
3935 UsedVars.insert(Ptr: cast<VarDecl>(Val: VD->getCanonicalDecl()));
3936 else if (auto *BD = dyn_cast<BindingDecl>(Val: DRE->getDecl()))
3937 UsedBindings.insert(Ptr: cast<BindingDecl>(Val: BD->getCanonicalDecl()));
3938 return true;
3939 }
3940};
3941} // namespace
3942
3943/// Check if bindings from the same structured binding have conflicting
3944/// capture kinds (by-ref vs by-copy). Bindings share the underlying
3945/// DecompositionDecl storage, so mixing by-ref and by-copy clauses on
3946/// different bindings from the same decomposition is not representable.
3947/// For example: map(a) creates by-ref, firstprivate(b) creates by-copy.
3948static bool checkDecompositionCaptureConflict(
3949 Sema &SemaRef, OpenMPDirectiveKind DKind,
3950 llvm::SmallDenseMap<const DecompositionDecl *,
3951 std::pair<bool, SourceLocation>, 4> &SeenDecompositions,
3952 const ValueDecl *D, SourceLocation ELoc, OpenMPClauseKind ClauseKind) {
3953 const auto *BD = dyn_cast<BindingDecl>(Val: D);
3954 if (!BD)
3955 return false;
3956
3957 const auto *DD = dyn_cast<DecompositionDecl>(Val: BD->getDecomposedDecl());
3958 if (!DD)
3959 return false;
3960
3961 // Determine if this clause creates by-ref or by-copy capture.
3962 bool IsByRef = false;
3963 switch (ClauseKind) {
3964 case OMPC_map:
3965 case OMPC_shared:
3966 // Map and shared clauses are by-reference.
3967 IsByRef = true;
3968 break;
3969 case OMPC_firstprivate:
3970 case OMPC_private:
3971 case OMPC_lastprivate:
3972 // These are by-copy.
3973 IsByRef = false;
3974 break;
3975 default:
3976 // Other clauses don't create capture conflicts.
3977 return false;
3978 }
3979 auto [It, Inserted] = SeenDecompositions.insert(KV: {DD, {IsByRef, ELoc}});
3980 if (!Inserted && It->second.first != IsByRef) {
3981 // Conflict: same DecompositionDecl needs both by-ref and by-copy
3982 // Emit diagnostic showing the binding name, not the decomposition.
3983 SemaRef.Diag(Loc: ELoc,
3984 DiagID: diag::err_omp_decomposition_bindings_different_capture_kinds)
3985 << BD;
3986 return true;
3987 }
3988 return false;
3989}
3990
3991/// Helper to check all clauses in a directive for structured binding
3992/// capture conflicts. Returns true if an error was found. If Body is
3993/// provided and the directive has default(shared), bindings used in the
3994/// body but not listed in explicit clauses are treated as implicit
3995/// shared (by-reference).
3996static bool checkClausesForDecompositionConflicts(Sema &SemaRef,
3997 OpenMPDirectiveKind DKind,
3998 ArrayRef<OMPClause *> Clauses,
3999 Stmt *Body = nullptr) {
4000 llvm::SmallDenseMap<const DecompositionDecl *,
4001 std::pair<bool, SourceLocation>, 4>
4002 SeenDecompositions;
4003 llvm::SmallPtrSet<const BindingDecl *, 8> ExplicitBindings;
4004 bool HasError = false;
4005 bool HasDefaultShared = false;
4006 SourceLocation DefaultSharedLoc;
4007 for (OMPClause *C : Clauses) {
4008 if (auto *DC = dyn_cast<OMPDefaultClause>(Val: C)) {
4009 if (DC->getDefaultKind() == llvm::omp::DefaultKind::OMP_DEFAULT_shared) {
4010 HasDefaultShared = true;
4011 DefaultSharedLoc = DC->getBeginLoc();
4012 }
4013 continue;
4014 }
4015 OpenMPClauseKind CK = C->getClauseKind();
4016 if (CK != OMPC_map && CK != OMPC_firstprivate && CK != OMPC_private &&
4017 CK != OMPC_shared && CK != OMPC_lastprivate)
4018 continue;
4019 ArrayRef<Expr *> Varlist;
4020 if (auto *MPC = dyn_cast<OMPMapClause>(Val: C))
4021 Varlist = MPC->varlist();
4022 else if (auto *FPC = dyn_cast<OMPFirstprivateClause>(Val: C))
4023 Varlist = FPC->varlist();
4024 else if (auto *PC = dyn_cast<OMPPrivateClause>(Val: C))
4025 Varlist = PC->varlist();
4026 else if (auto *SC = dyn_cast<OMPSharedClause>(Val: C))
4027 Varlist = SC->varlist();
4028 else if (auto *LPC = dyn_cast<OMPLastprivateClause>(Val: C))
4029 Varlist = LPC->varlist();
4030
4031 for (Expr *VE : Varlist) {
4032 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: VE->IgnoreParenImpCasts())) {
4033 ValueDecl *D = DRE->getDecl();
4034 // Look through OMPCapturedExprDecl (used when clauses reference
4035 // variables from an enclosing captured region) to find the
4036 // underlying BindingDecl.
4037 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: D)) {
4038 if (auto *InitDRE =
4039 dyn_cast<DeclRefExpr>(Val: CED->getInit()->IgnoreParenImpCasts()))
4040 D = InitDRE->getDecl();
4041 }
4042 if (auto *BD = dyn_cast<BindingDecl>(Val: D))
4043 ExplicitBindings.insert(Ptr: cast<BindingDecl>(Val: BD->getCanonicalDecl()));
4044 if (checkDecompositionCaptureConflict(
4045 SemaRef, DKind, SeenDecompositions, D, ELoc: VE->getExprLoc(), ClauseKind: CK))
4046 HasError = true;
4047 }
4048 }
4049 }
4050
4051 // With default(shared), bindings used in the body but not in an explicit
4052 // clause become implicit shared (by-reference). Check those for conflicts
4053 // with explicit by-copy clauses on the same decomposition.
4054 if (HasDefaultShared && Body) {
4055 llvm::SmallPtrSet<const VarDecl *, 8> UsedVars;
4056 llvm::SmallPtrSet<const BindingDecl *, 8> UsedBindings;
4057 VarUsageVisitor Visitor(UsedVars, UsedBindings);
4058 Visitor.TraverseStmt(S: Body);
4059 for (const BindingDecl *BD : UsedBindings) {
4060 if (ExplicitBindings.contains(Ptr: BD))
4061 continue;
4062 if (checkDecompositionCaptureConflict(SemaRef, DKind, SeenDecompositions,
4063 D: BD, ELoc: DefaultSharedLoc, ClauseKind: OMPC_shared))
4064 HasError = true;
4065 }
4066 }
4067 return HasError;
4068}
4069
4070/// Check if original variable is explicitly mapped but only bindings are used.
4071/// Returns true if an error was found.
4072static bool checkOriginalVarMappedButOnlyBindingsUsed(
4073 Sema &SemaRef, ArrayRef<OMPClause *> Clauses, Stmt *Body) {
4074 llvm::SmallDenseMap<const VarDecl *, SourceLocation, 4> MappedOrigVars;
4075
4076 for (OMPClause *C : Clauses) {
4077 if (auto *MPC = dyn_cast<OMPMapClause>(Val: C)) {
4078 for (Expr *VE : MPC->varlist()) {
4079 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: VE->IgnoreParenImpCasts())) {
4080 if (auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl())) {
4081 MappedOrigVars[VD->getCanonicalDecl()] = VE->getExprLoc();
4082 }
4083 }
4084 }
4085 }
4086 }
4087 if (MappedOrigVars.empty())
4088 return false;
4089
4090 llvm::SmallPtrSet<const VarDecl *, 8> UsedVars;
4091 llvm::SmallPtrSet<const BindingDecl *, 8> UsedBindings;
4092 VarUsageVisitor Visitor(UsedVars, UsedBindings);
4093 Visitor.TraverseStmt(S: Body);
4094 bool HasError = false;
4095 for (const auto &Entry : MappedOrigVars) {
4096 const VarDecl *OrigVar = Entry.first;
4097 SourceLocation Loc = Entry.second;
4098
4099 // Check if this original variable has bindings that are used.
4100 // For reference bindings (`auto &[a, b] = p`), the bindings alias the
4101 // original variable, so mapping `p` covers them correctly.
4102 bool BindingsFromThisVarUsed = false;
4103 for (const BindingDecl *BD : UsedBindings) {
4104 if (auto *DD = dyn_cast<DecompositionDecl>(Val: BD->getDecomposedDecl())) {
4105 if (DD->getType()->isReferenceType())
4106 continue;
4107 if (auto *OrigFromDD = DD->getOriginalVar().Var) {
4108 if (OrigFromDD->getCanonicalDecl() == OrigVar) {
4109 BindingsFromThisVarUsed = true;
4110 break;
4111 }
4112 }
4113 }
4114 }
4115
4116 // Error if: original is mapped, bindings are used, but original is not
4117 // used.
4118 if (BindingsFromThisVarUsed && !UsedVars.count(Ptr: OrigVar)) {
4119 SemaRef.Diag(Loc, DiagID: diag::err_omp_original_var_mapped_bindings_only_used)
4120 << OrigVar;
4121 HasError = true;
4122 }
4123 }
4124
4125 return HasError;
4126}
4127
4128static OpenMPMapClauseKind
4129getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
4130 bool IsAggregateOrDeclareTarget,
4131 bool HasConstQualifier) {
4132 OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
4133 switch (M) {
4134 case OMPC_DEFAULTMAP_MODIFIER_alloc:
4135 case OMPC_DEFAULTMAP_MODIFIER_storage:
4136 Kind = OMPC_MAP_alloc;
4137 break;
4138 case OMPC_DEFAULTMAP_MODIFIER_to:
4139 Kind = OMPC_MAP_to;
4140 break;
4141 case OMPC_DEFAULTMAP_MODIFIER_from:
4142 Kind = OMPC_MAP_from;
4143 break;
4144 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
4145 Kind = OMPC_MAP_tofrom;
4146 break;
4147 case OMPC_DEFAULTMAP_MODIFIER_present:
4148 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
4149 // If implicit-behavior is present, each variable referenced in the
4150 // construct in the category specified by variable-category is treated as if
4151 // it had been listed in a map clause with the map-type of alloc and
4152 // map-type-modifier of present.
4153 Kind = OMPC_MAP_alloc;
4154 break;
4155 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
4156 case OMPC_DEFAULTMAP_MODIFIER_private:
4157 case OMPC_DEFAULTMAP_MODIFIER_last:
4158 llvm_unreachable("Unexpected defaultmap implicit behavior");
4159 case OMPC_DEFAULTMAP_MODIFIER_none:
4160 case OMPC_DEFAULTMAP_MODIFIER_default:
4161 case OMPC_DEFAULTMAP_MODIFIER_unknown:
4162 // IsAggregateOrDeclareTarget could be true if:
4163 // 1. the implicit behavior for aggregate is tofrom
4164 // 2. it's a declare target link
4165 if (IsAggregateOrDeclareTarget) {
4166 if (HasConstQualifier)
4167 Kind = OMPC_MAP_to;
4168 else
4169 Kind = OMPC_MAP_tofrom;
4170 break;
4171 }
4172 llvm_unreachable("Unexpected defaultmap implicit behavior");
4173 }
4174 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
4175 return Kind;
4176}
4177
4178static bool hasNoMutableFields(const CXXRecordDecl *RD) {
4179 for (const auto *FD : RD->fields()) {
4180 if (FD->isMutable())
4181 return false;
4182 QualType FT = FD->getType();
4183 while (FT->isArrayType())
4184 FT = FT->getAsArrayTypeUnsafe()->getElementType();
4185 if (const auto *NestedRD = FT->getAsCXXRecordDecl())
4186 if (!hasNoMutableFields(RD: NestedRD))
4187 return false;
4188 }
4189 return true;
4190}
4191
4192static bool hasConstQualifiedMappingType(QualType T) {
4193 while (T->isArrayType())
4194 T = T->getAsArrayTypeUnsafe()->getElementType();
4195 if (!T.isConstQualified())
4196 return false;
4197 if (const auto *RD = T->getAsCXXRecordDecl())
4198 // TODO : Per OpenMP 6.0 p299 lines 3-4, non-mutable members of a
4199 // const-qualified struct should also be ignored for 'from'. This
4200 // requires per-member mapping granularity via compiler-generated
4201 // default mappers and a mechanism to ensure constness to the mapper.
4202 // For now we conservatively treat any struct with mutable members as
4203 // requiring full 'tofrom'.
4204 return hasNoMutableFields(RD);
4205 return true;
4206}
4207
4208namespace {
4209/// Try to extract the original variable from a DecompositionDecl.
4210/// If extraction fails, emit a diagnostic. Returns the original VarDecl* on
4211/// success, nullptr on failure.
4212static const VarDecl *getOriginalVarOrDiagnose(Sema &S,
4213 const DecompositionDecl *DD,
4214 SourceLocation Loc) {
4215 auto Result = DD->getOriginalVar();
4216 if (!Result.Var)
4217 S.Diag(Loc, DiagID: diag::err_omp_unsupported_structured_binding_init)
4218 << Result.DiagKind;
4219 return Result.Var;
4220}
4221
4222struct VariableImplicitInfo {
4223 static const unsigned MapKindNum = OMPC_MAP_unknown;
4224 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
4225
4226 llvm::SetVector<Expr *> Privates;
4227 llvm::SetVector<Expr *> Firstprivates;
4228 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
4229 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
4230 MapModifiers[DefaultmapKindNum];
4231};
4232
4233class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
4234 DSAStackTy *Stack;
4235 Sema &SemaRef;
4236 OpenMPDirectiveKind DKind = OMPD_unknown;
4237 bool ErrorFound = false;
4238 bool TryCaptureCXXThisMembers = false;
4239 CapturedStmt *CS = nullptr;
4240
4241 VariableImplicitInfo ImpInfo;
4242 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
4243 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
4244
4245 void VisitSubCaptures(OMPExecutableDirective *S) {
4246 // Check implicitly captured variables.
4247 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
4248 return;
4249 if (S->getDirectiveKind() == OMPD_atomic ||
4250 S->getDirectiveKind() == OMPD_critical ||
4251 S->getDirectiveKind() == OMPD_section ||
4252 S->getDirectiveKind() == OMPD_master ||
4253 S->getDirectiveKind() == OMPD_masked ||
4254 S->getDirectiveKind() == OMPD_scope ||
4255 S->getDirectiveKind() == OMPD_assume ||
4256 isOpenMPLoopTransformationDirective(DKind: S->getDirectiveKind())) {
4257 Visit(S: S->getAssociatedStmt());
4258 return;
4259 }
4260 visitSubCaptures(S: S->getInnermostCapturedStmt());
4261 // Try to capture inner this->member references to generate correct mappings
4262 // and diagnostics.
4263 if (TryCaptureCXXThisMembers ||
4264 (isOpenMPTargetExecutionDirective(DKind) &&
4265 llvm::any_of(Range: S->getInnermostCapturedStmt()->captures(),
4266 P: [](const CapturedStmt::Capture &C) {
4267 return C.capturesThis();
4268 }))) {
4269 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
4270 TryCaptureCXXThisMembers = true;
4271 Visit(S: S->getInnermostCapturedStmt()->getCapturedStmt());
4272 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
4273 }
4274 // In tasks firstprivates are not captured anymore, need to analyze them
4275 // explicitly.
4276 if (isOpenMPTaskingDirective(Kind: S->getDirectiveKind()) &&
4277 !isOpenMPTaskLoopDirective(DKind: S->getDirectiveKind())) {
4278 for (OMPClause *C : S->clauses())
4279 if (auto *FC = dyn_cast<OMPFirstprivateClause>(Val: C)) {
4280 for (Expr *Ref : FC->varlist())
4281 Visit(S: Ref);
4282 }
4283 }
4284 }
4285
4286public:
4287 void VisitDeclRefExpr(DeclRefExpr *E) {
4288 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
4289 E->isValueDependent() || E->containsUnexpandedParameterPack() ||
4290 E->isInstantiationDependent() ||
4291 E->isNonOdrUse() == clang::NOUR_Unevaluated)
4292 return;
4293 ValueDecl *D = const_cast<ValueDecl *>(E->getDecl());
4294 BindingDecl *BD = dyn_cast<BindingDecl>(Val: D);
4295 if (BD)
4296 D = BD->getDecomposedDecl();
4297 if (auto *VD = dyn_cast<VarDecl>(Val: D)) {
4298 // For BindingDecls, use the original binding for DSA lookups;
4299 // fall back to DecompositionDecl if lookup fails.
4300 ValueDecl *LookupDecl = BD ? static_cast<ValueDecl *>(BD) : VD;
4301 // Check the datasharing rules for the expressions in the clauses.
4302 if (!CS || (isa<OMPCapturedExprDecl>(Val: VD) && !CS->capturesVariable(Var: VD) &&
4303 !Stack->getTopDSA(D: LookupDecl, /*FromParent=*/false).RefExpr &&
4304 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
4305 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: VD))
4306 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
4307 Visit(S: const_cast<Expr *>(CED->getInit()));
4308 return;
4309 }
4310 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(Val: VD))
4311 // Do not analyze internal variables and do not enclose them into
4312 // implicit clauses.
4313 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
4314 return;
4315 VD = VD->getCanonicalDecl();
4316 // Skip DecompositionDecls (but not BindingDecls in DSA contexts) -
4317 // they should be handled through explicit mapping of the original
4318 // variable or as member expressions. When bindings are captured,
4319 // the original variable is what needs to be mapped, not the
4320 // decomposition itself. However, BindingDecls need DSA checking for
4321 // default(none)/private/firstprivate contexts, but NOT in target
4322 // offloading contexts (where map clause handles them).
4323 if (isa<DecompositionDecl>(Val: VD)) {
4324 // For BindingDecls, continue checking only if:
4325 // - We are in a DSA context (tasking/parallel/worksharing/teams), or
4326 // - We are in a target context and the binding is scalar (implicit
4327 // firstprivate).
4328 bool InTargetAndScalar = BD &&
4329 isOpenMPTargetExecutionDirective(DKind) &&
4330 BD->getType()->isScalarType();
4331 if (!BD ||
4332 (isOpenMPTargetExecutionDirective(DKind) && !InTargetAndScalar) ||
4333 (!InTargetAndScalar && !isImplicitOrExplicitTaskingRegion(DKind) &&
4334 !isOpenMPParallelDirective(DKind) &&
4335 !isOpenMPWorksharingDirective(DKind) &&
4336 !isOpenMPTeamsDirective(DKind)))
4337 return;
4338 }
4339 // Skip internally declared variables.
4340 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(Var: VD) &&
4341 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4342 !Stack->isImplicitTaskFirstprivate(D: VD))
4343 return;
4344 // Skip allocators in uses_allocators clauses.
4345 if (Stack->isUsesAllocatorsDecl(D: VD))
4346 return;
4347
4348 DSAStackTy::DSAVarData DVar =
4349 Stack->getTopDSA(D: LookupDecl, /*FromParent=*/false);
4350 // If lookup on BindingDecl failed, try on DecompositionDecl.
4351 if (BD && !DVar.RefExpr)
4352 DVar = Stack->getTopDSA(D: VD, /*FromParent=*/false);
4353 // Check if the variable has explicit DSA set and stop analysis if it so.
4354 if (DVar.RefExpr ||
4355 !ImplicitDeclarations
4356 .insert(V: cast<ValueDecl>(Val: LookupDecl->getCanonicalDecl()))
4357 .second)
4358 return;
4359
4360 // Skip internally declared static variables.
4361 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
4362 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
4363 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(Var: VD) &&
4364 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
4365 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
4366 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4367 !Stack->isImplicitTaskFirstprivate(D: VD))
4368 return;
4369
4370 SourceLocation ELoc = E->getExprLoc();
4371 // The default(none) clause requires that each variable that is referenced
4372 // in the construct, and does not have a predetermined data-sharing
4373 // attribute, must have its data-sharing attribute explicitly determined
4374 // by being listed in a data-sharing attribute clause.
4375 if (DVar.CKind == OMPC_unknown &&
4376 (Stack->getDefaultDSA() == DSA_none ||
4377 Stack->getDefaultDSA() == DSA_private ||
4378 Stack->getDefaultDSA() == DSA_firstprivate) &&
4379 isImplicitOrExplicitTaskingRegion(DKind) &&
4380 VarsWithInheritedDSA.count(Val: VD) == 0) {
4381 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4382 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4383 Stack->getDefaultDSA() == DSA_private)) {
4384 DSAStackTy::DSAVarData DVar =
4385 Stack->getImplicitDSA(D: LookupDecl, /*FromParent=*/false);
4386 if (BD && DVar.CKind == OMPC_unknown)
4387 DVar = Stack->getImplicitDSA(D: VD, /*FromParent=*/false);
4388 InheritedDSA = DVar.CKind == OMPC_unknown;
4389 }
4390 if (InheritedDSA)
4391 VarsWithInheritedDSA[cast<ValueDecl>(
4392 Val: LookupDecl->getCanonicalDecl())] = E;
4393 if (Stack->getDefaultDSA() == DSA_none)
4394 return;
4395 }
4396
4397 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
4398 // If implicit-behavior is none, each variable referenced in the
4399 // construct that does not have a predetermined data-sharing attribute
4400 // and does not appear in a to or link clause on a declare target
4401 // directive must be listed in a data-mapping attribute clause, a
4402 // data-sharing attribute clause (including a data-sharing attribute
4403 // clause on a combined construct where target. is one of the
4404 // constituent constructs), or an is_device_ptr clause.
4405 // For BindingDecls, use the binding's type to determine category.
4406 OpenMPDefaultmapClauseKind ClauseKind = getVariableCategoryFromDecl(
4407 LO: SemaRef.getLangOpts(), VD: BD ? static_cast<const ValueDecl *>(BD)
4408 : static_cast<const ValueDecl *>(VD));
4409 if (SemaRef.getLangOpts().OpenMP >= 50) {
4410 bool IsModifierNone = Stack->getDefaultmapModifier(Kind: ClauseKind) ==
4411 OMPC_DEFAULTMAP_MODIFIER_none;
4412 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4413 VarsWithInheritedDSA.count(Val: VD) == 0 && !Res) {
4414 // Only check for data-mapping attribute and is_device_ptr here
4415 // since we have already make sure that the declaration does not
4416 // have a data-sharing attribute above
4417 if (!Stack->checkMappableExprComponentListsForDecl(
4418 VD, /*CurrentRegionOnly=*/true,
4419 Check: [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
4420 MapExprComponents,
4421 OpenMPClauseKind) {
4422 auto MI = MapExprComponents.rbegin();
4423 auto ME = MapExprComponents.rend();
4424 return MI != ME && MI->getAssociatedDeclaration() == VD;
4425 })) {
4426 VarsWithInheritedDSA[cast<ValueDecl>(
4427 Val: LookupDecl->getCanonicalDecl())] = E;
4428 return;
4429 }
4430 }
4431 }
4432 if (SemaRef.getLangOpts().OpenMP > 50) {
4433 bool IsModifierPresent = Stack->getDefaultmapModifier(Kind: ClauseKind) ==
4434 OMPC_DEFAULTMAP_MODIFIER_present;
4435 if (IsModifierPresent) {
4436 if (!llvm::is_contained(Range&: ImpInfo.MapModifiers[ClauseKind],
4437 Element: OMPC_MAP_MODIFIER_present)) {
4438 ImpInfo.MapModifiers[ClauseKind].push_back(
4439 Elt: OMPC_MAP_MODIFIER_present);
4440 }
4441 }
4442 }
4443
4444 if (isOpenMPTargetExecutionDirective(DKind) &&
4445 !Stack->isLoopControlVariable(D: VD).first) {
4446 // Check if VD is already mapped. For DecompositionDecls, also check if
4447 // the original variable they decompose has been mapped (via BindingDecl
4448 // map clauses).
4449 bool AlreadyMapped = Stack->checkMappableExprComponentListsForDecl(
4450 VD, /*CurrentRegionOnly=*/true, Check: [this](auto StackComponents, auto) {
4451 if (SemaRef.LangOpts.OpenMP >= 50)
4452 return !StackComponents.empty();
4453 // Variable is used if it has been marked as an array, array
4454 // section, array shaping or the variable itself.
4455 return StackComponents.size() == 1 ||
4456 llvm::all_of(
4457 llvm::drop_begin(llvm::reverse(StackComponents)),
4458 [](const auto &MC) {
4459 return MC.getAssociatedDeclaration() == nullptr &&
4460 (isa<ArraySectionExpr>(
4461 MC.getAssociatedExpression()) ||
4462 isa<OMPArrayShapingExpr>(
4463 MC.getAssociatedExpression()) ||
4464 isa<ArraySubscriptExpr>(
4465 MC.getAssociatedExpression()));
4466 });
4467 });
4468
4469 // For DecompositionDecls, check if the original variable has been
4470 // mapped.
4471 const auto *DD = dyn_cast<DecompositionDecl>(Val: VD);
4472 if (!AlreadyMapped && DD) {
4473 // Don't diagnose here. Just check if we can extract the original
4474 // var. Diagnostics happen when processing explicit map clauses.
4475 if (const VarDecl *OrigVar = DD->getOriginalVar().Var) {
4476 AlreadyMapped = Stack->checkMappableExprComponentListsForDecl(
4477 VD: OrigVar, /*CurrentRegionOnly=*/true,
4478 Check: [this](auto StackComponents, auto) {
4479 if (SemaRef.LangOpts.OpenMP >= 50)
4480 return !StackComponents.empty();
4481 return StackComponents.size() == 1;
4482 });
4483 }
4484 }
4485 if (!AlreadyMapped) {
4486 bool IsFirstprivate = false;
4487 // By default lambdas are captured as firstprivates.
4488 QualType CheckType = BD ? BD->getType() : VD->getType();
4489 if (const auto *RD =
4490 CheckType.getNonReferenceType()->getAsCXXRecordDecl())
4491 IsFirstprivate = RD->isLambda();
4492 IsFirstprivate =
4493 IsFirstprivate || (Stack->mustBeFirstprivate(Kind: ClauseKind) && !Res);
4494 if (IsFirstprivate) {
4495 ImpInfo.Firstprivates.insert(X: E);
4496 } else {
4497 OpenMPDefaultmapClauseModifier M =
4498 Stack->getDefaultmapModifier(Kind: ClauseKind);
4499 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4500 ImpInfo.Privates.insert(X: E);
4501 } else {
4502 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
4503 M, IsAggregateOrDeclareTarget: ClauseKind == OMPC_DEFAULTMAP_aggregate || Res,
4504 HasConstQualifier: hasConstQualifiedMappingType(T: E->getType()));
4505 ImpInfo.Mappings[ClauseKind][Kind].insert(X: E);
4506 }
4507 }
4508 return;
4509 }
4510 }
4511
4512 // OpenMP [2.9.3.6, Restrictions, p.2]
4513 // A list item that appears in a reduction clause of the innermost
4514 // enclosing worksharing or parallel construct may not be accessed in an
4515 // explicit task.
4516 DVar = Stack->hasInnermostDSA(
4517 D: LookupDecl,
4518 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
4519 return C == OMPC_reduction && !AppliedToPointee;
4520 },
4521 DPred: [](OpenMPDirectiveKind K) {
4522 return isOpenMPParallelDirective(DKind: K) ||
4523 isOpenMPWorksharingDirective(DKind: K) || isOpenMPTeamsDirective(DKind: K);
4524 },
4525 /*FromParent=*/true);
4526 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind == OMPC_reduction) {
4527 ErrorFound = true;
4528 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_in_task);
4529 reportOriginalDsa(SemaRef, Stack, D: BD ? LookupDecl : VD, DVar);
4530 return;
4531 }
4532
4533 // Define implicit data-sharing attributes for task.
4534 DVar = Stack->getImplicitDSA(D: LookupDecl, /*FromParent=*/false);
4535 if (BD && DVar.CKind == OMPC_unknown)
4536 DVar = Stack->getImplicitDSA(D: VD, /*FromParent=*/false);
4537 if (((isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind != OMPC_shared) ||
4538 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4539 DVar.CKind == OMPC_firstprivate) ||
4540 (Stack->getDefaultDSA() == DSA_private &&
4541 DVar.CKind == OMPC_private)) &&
4542 !DVar.RefExpr)) &&
4543 !Stack->isLoopControlVariable(D: VD).first) {
4544 if (Stack->getDefaultDSA() == DSA_private)
4545 ImpInfo.Privates.insert(X: E);
4546 else
4547 ImpInfo.Firstprivates.insert(X: E);
4548 return;
4549 }
4550
4551 // Store implicitly used globals with declare target link for parent
4552 // target.
4553 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
4554 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4555 Stack->addToParentTargetRegionLinkGlobals(E);
4556 return;
4557 }
4558 }
4559 }
4560 void VisitMemberExpr(MemberExpr *E) {
4561 if (E->isTypeDependent() || E->isValueDependent() ||
4562 E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
4563 return;
4564 auto *FD = dyn_cast<FieldDecl>(Val: E->getMemberDecl());
4565 if (auto *TE = dyn_cast<CXXThisExpr>(Val: E->getBase()->IgnoreParenCasts())) {
4566 if (!FD)
4567 return;
4568 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D: FD, /*FromParent=*/false);
4569 // Check if the variable has explicit DSA set and stop analysis if it
4570 // so.
4571 if (DVar.RefExpr || !ImplicitDeclarations.insert(V: FD).second)
4572 return;
4573
4574 if (isOpenMPTargetExecutionDirective(DKind) &&
4575 !Stack->isLoopControlVariable(D: FD).first &&
4576 !Stack->checkMappableExprComponentListsForDecl(
4577 VD: FD, /*CurrentRegionOnly=*/true,
4578 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef
4579 StackComponents,
4580 OpenMPClauseKind) {
4581 return isa<CXXThisExpr>(
4582 Val: cast<MemberExpr>(
4583 Val: StackComponents.back().getAssociatedExpression())
4584 ->getBase()
4585 ->IgnoreParens());
4586 })) {
4587 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4588 // A bit-field cannot appear in a map clause.
4589 //
4590 if (FD->isBitField())
4591 return;
4592
4593 // Check to see if the member expression is referencing a class that
4594 // has already been explicitly mapped
4595 if (Stack->isClassPreviouslyMapped(QT: TE->getType()))
4596 return;
4597
4598 OpenMPDefaultmapClauseModifier Modifier =
4599 Stack->getDefaultmapModifier(Kind: OMPC_DEFAULTMAP_aggregate);
4600 OpenMPDefaultmapClauseKind ClauseKind =
4601 getVariableCategoryFromDecl(LO: SemaRef.getLangOpts(), VD: FD);
4602 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
4603 M: Modifier, /*IsAggregateOrDeclareTarget=*/true,
4604 /*HasConstQualifier=*/false);
4605 ImpInfo.Mappings[ClauseKind][Kind].insert(X: E);
4606 return;
4607 }
4608
4609 SourceLocation ELoc = E->getExprLoc();
4610 // OpenMP [2.9.3.6, Restrictions, p.2]
4611 // A list item that appears in a reduction clause of the innermost
4612 // enclosing worksharing or parallel construct may not be accessed in
4613 // an explicit task.
4614 DVar = Stack->hasInnermostDSA(
4615 D: FD,
4616 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
4617 return C == OMPC_reduction && !AppliedToPointee;
4618 },
4619 DPred: [](OpenMPDirectiveKind K) {
4620 return isOpenMPParallelDirective(DKind: K) ||
4621 isOpenMPWorksharingDirective(DKind: K) || isOpenMPTeamsDirective(DKind: K);
4622 },
4623 /*FromParent=*/true);
4624 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind == OMPC_reduction) {
4625 ErrorFound = true;
4626 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_in_task);
4627 reportOriginalDsa(SemaRef, Stack, D: FD, DVar);
4628 return;
4629 }
4630
4631 // Define implicit data-sharing attributes for task.
4632 DVar = Stack->getImplicitDSA(D: FD, /*FromParent=*/false);
4633 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind != OMPC_shared &&
4634 !Stack->isLoopControlVariable(D: FD).first) {
4635 // Check if there is a captured expression for the current field in the
4636 // region. Do not mark it as firstprivate unless there is no captured
4637 // expression.
4638 // TODO: try to make it firstprivate.
4639 if (DVar.CKind != OMPC_unknown)
4640 ImpInfo.Firstprivates.insert(X: E);
4641 }
4642 return;
4643 }
4644 if (isOpenMPTargetExecutionDirective(DKind)) {
4645 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
4646 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, CKind: OMPC_map,
4647 DKind, /*NoDiagnose=*/true))
4648 return;
4649 const auto *VD = cast<ValueDecl>(
4650 Val: CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4651 if (!Stack->checkMappableExprComponentListsForDecl(
4652 VD, /*CurrentRegionOnly=*/true,
4653 Check: [&CurComponents](
4654 OMPClauseMappableExprCommon::MappableExprComponentListRef
4655 StackComponents,
4656 OpenMPClauseKind) {
4657 auto CCI = CurComponents.rbegin();
4658 auto CCE = CurComponents.rend();
4659 for (const auto &SC : llvm::reverse(C&: StackComponents)) {
4660 // Do both expressions have the same kind?
4661 if (CCI->getAssociatedExpression()->getStmtClass() !=
4662 SC.getAssociatedExpression()->getStmtClass())
4663 if (!((isa<ArraySectionExpr>(
4664 Val: SC.getAssociatedExpression()) ||
4665 isa<OMPArrayShapingExpr>(
4666 Val: SC.getAssociatedExpression())) &&
4667 isa<ArraySubscriptExpr>(
4668 Val: CCI->getAssociatedExpression())))
4669 return false;
4670
4671 const Decl *CCD = CCI->getAssociatedDeclaration();
4672 const Decl *SCD = SC.getAssociatedDeclaration();
4673 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4674 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4675 if (SCD != CCD)
4676 return false;
4677 std::advance(i&: CCI, n: 1);
4678 if (CCI == CCE)
4679 break;
4680 }
4681 return true;
4682 })) {
4683 Visit(S: E->getBase());
4684 }
4685 } else if (!TryCaptureCXXThisMembers) {
4686 Visit(S: E->getBase());
4687 }
4688 }
4689 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4690 for (OMPClause *C : S->clauses()) {
4691 // Skip analysis of arguments of private clauses for task|target
4692 // directives.
4693 if (isa_and_nonnull<OMPPrivateClause>(Val: C))
4694 continue;
4695 // Skip analysis of arguments of implicitly defined firstprivate clause
4696 // for task|target directives.
4697 // Skip analysis of arguments of implicitly defined map clause for target
4698 // directives.
4699 if (C && !((isa<OMPFirstprivateClause>(Val: C) || isa<OMPMapClause>(Val: C)) &&
4700 C->isImplicit() && !isOpenMPTaskingDirective(Kind: DKind))) {
4701 for (Stmt *CC : C->children()) {
4702 if (CC)
4703 Visit(S: CC);
4704 }
4705 }
4706 }
4707 // Check implicitly captured variables.
4708 VisitSubCaptures(S);
4709 }
4710
4711 void VisitOMPCanonicalLoopNestTransformationDirective(
4712 OMPCanonicalLoopNestTransformationDirective *S) {
4713 // Loop transformation directives do not introduce data sharing
4714 VisitStmt(S);
4715 }
4716
4717 void VisitCallExpr(CallExpr *S) {
4718 for (Stmt *C : S->arguments()) {
4719 if (C) {
4720 // Check implicitly captured variables in the task-based directives to
4721 // check if they must be firstprivatized.
4722 Visit(S: C);
4723 }
4724 }
4725 if (Expr *Callee = S->getCallee()) {
4726 auto *CI = Callee->IgnoreParenImpCasts();
4727 if (auto *CE = dyn_cast<MemberExpr>(Val: CI))
4728 Visit(S: CE->getBase());
4729 else if (auto *CE = dyn_cast<DeclRefExpr>(Val: CI))
4730 Visit(S: CE);
4731 }
4732 }
4733 void VisitStmt(Stmt *S) {
4734 for (Stmt *C : S->children()) {
4735 if (C) {
4736 // Check implicitly captured variables in the task-based directives to
4737 // check if they must be firstprivatized.
4738 Visit(S: C);
4739 }
4740 }
4741 }
4742
4743 void visitSubCaptures(CapturedStmt *S) {
4744 for (const CapturedStmt::Capture &Cap : S->captures()) {
4745 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4746 continue;
4747 VarDecl *VD = Cap.getCapturedVar();
4748 // Do not try to map the variable if it or its sub-component was mapped
4749 // already.
4750 if (isOpenMPTargetExecutionDirective(DKind) &&
4751 Stack->checkMappableExprComponentListsForDecl(
4752 VD, /*CurrentRegionOnly=*/true,
4753 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4754 OpenMPClauseKind) { return true; }))
4755 continue;
4756 DeclRefExpr *DRE = buildDeclRefExpr(
4757 S&: SemaRef, D: VD, Ty: VD->getType().getNonLValueExprType(Context: SemaRef.Context),
4758 Loc: Cap.getLocation(), /*RefersToCapture=*/true);
4759 Visit(S: DRE);
4760 }
4761 }
4762 bool isErrorFound() const { return ErrorFound; }
4763 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4764 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4765 return VarsWithInheritedDSA;
4766 }
4767
4768 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4769 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4770 DKind = S->getCurrentDirective();
4771 // Process declare target link variables for the target directives.
4772 if (isOpenMPTargetExecutionDirective(DKind)) {
4773 for (DeclRefExpr *E : Stack->getLinkGlobals())
4774 Visit(S: E);
4775 }
4776 }
4777};
4778} // namespace
4779
4780static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4781 OpenMPDirectiveKind DKind,
4782 bool ScopeEntry) {
4783 SmallVector<llvm::omp::TraitProperty, 8> Traits;
4784 if (isOpenMPTargetExecutionDirective(DKind))
4785 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_target_target);
4786 if (isOpenMPTeamsDirective(DKind))
4787 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_teams_teams);
4788 if (isOpenMPParallelDirective(DKind))
4789 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_parallel_parallel);
4790 if (isOpenMPWorksharingDirective(DKind))
4791 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_for_for);
4792 if (isOpenMPSimdDirective(DKind))
4793 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_simd_simd);
4794 Stack->handleConstructTrait(Traits, ScopeEntry);
4795}
4796
4797static SmallVector<SemaOpenMP::CapturedParamNameType>
4798getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4799 ASTContext &Context = SemaRef.getASTContext();
4800 QualType KmpInt32Ty =
4801 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4802 QualType KmpInt32PtrTy =
4803 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4804 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4805 std::make_pair(x: ".global_tid.", y&: KmpInt32PtrTy),
4806 std::make_pair(x: ".bound_tid.", y&: KmpInt32PtrTy),
4807 };
4808 if (LoopBoundSharing) {
4809 QualType KmpSizeTy = Context.getSizeType().withConst();
4810 Params.push_back(Elt: std::make_pair(x: ".previous.lb.", y&: KmpSizeTy));
4811 Params.push_back(Elt: std::make_pair(x: ".previous.ub.", y&: KmpSizeTy));
4812 }
4813
4814 // __context with shared vars
4815 Params.push_back(Elt: std::make_pair(x: StringRef(), y: QualType()));
4816 return Params;
4817}
4818
4819static SmallVector<SemaOpenMP::CapturedParamNameType>
4820getTeamsRegionParams(Sema &SemaRef) {
4821 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4822}
4823
4824static SmallVector<SemaOpenMP::CapturedParamNameType>
4825getTaskRegionParams(Sema &SemaRef) {
4826 ASTContext &Context = SemaRef.getASTContext();
4827 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(DestWidth: 32, Signed: 1).withConst();
4828 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4829 QualType KmpInt32PtrTy =
4830 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4831 QualType Args[] = {VoidPtrTy};
4832 FunctionProtoType::ExtProtoInfo EPI;
4833 EPI.Variadic = true;
4834 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4835 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4836 std::make_pair(x: ".global_tid.", y&: KmpInt32Ty),
4837 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4838 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4839 std::make_pair(
4840 x: ".copy_fn.",
4841 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4842 std::make_pair(x: ".task_t.", y: Context.VoidPtrTy.withConst()),
4843 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4844 };
4845 return Params;
4846}
4847
4848static SmallVector<SemaOpenMP::CapturedParamNameType>
4849getTargetRegionParams(Sema &SemaRef) {
4850 ASTContext &Context = SemaRef.getASTContext();
4851 SmallVector<SemaOpenMP::CapturedParamNameType> Params;
4852 // __context with shared vars
4853 Params.push_back(Elt: std::make_pair(x: StringRef(), y: QualType()));
4854 // Implicit dyn_ptr argument, appended as the last parameter. Present on both
4855 // host and device so argument counts match without runtime manipulation.
4856 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4857 Params.push_back(Elt: std::make_pair(x: StringRef("dyn_ptr"), y&: VoidPtrTy));
4858 return Params;
4859}
4860
4861static SmallVector<SemaOpenMP::CapturedParamNameType>
4862getUnknownRegionParams(Sema &SemaRef) {
4863 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4864 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4865 };
4866 return Params;
4867}
4868
4869static SmallVector<SemaOpenMP::CapturedParamNameType>
4870getTaskloopRegionParams(Sema &SemaRef) {
4871 ASTContext &Context = SemaRef.getASTContext();
4872 QualType KmpInt32Ty =
4873 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4874 QualType KmpUInt64Ty =
4875 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4876 QualType KmpInt64Ty =
4877 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4878 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4879 QualType KmpInt32PtrTy =
4880 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4881 QualType Args[] = {VoidPtrTy};
4882 FunctionProtoType::ExtProtoInfo EPI;
4883 EPI.Variadic = true;
4884 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4885 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4886 std::make_pair(x: ".global_tid.", y&: KmpInt32Ty),
4887 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4888 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4889 std::make_pair(
4890 x: ".copy_fn.",
4891 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4892 std::make_pair(x: ".task_t.", y: Context.VoidPtrTy.withConst()),
4893 std::make_pair(x: ".lb.", y&: KmpUInt64Ty),
4894 std::make_pair(x: ".ub.", y&: KmpUInt64Ty),
4895 std::make_pair(x: ".st.", y&: KmpInt64Ty),
4896 std::make_pair(x: ".liter.", y&: KmpInt32Ty),
4897 std::make_pair(x: ".reductions.", y&: VoidPtrTy),
4898 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4899 };
4900 return Params;
4901}
4902
4903static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind,
4904 Scope *CurScope, SourceLocation Loc) {
4905 SmallVector<OpenMPDirectiveKind> Regions;
4906 getOpenMPCaptureRegions(CaptureRegions&: Regions, DKind);
4907
4908 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(Kind: DKind);
4909
4910 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4911 CSI->TheCapturedDecl->addAttr(A: AlwaysInlineAttr::CreateImplicit(
4912 Ctx&: SemaRef.getASTContext(), Range: {}, S: AlwaysInlineAttr::Keyword_forceinline));
4913 };
4914
4915 for (auto [Level, RKind] : llvm::enumerate(First&: Regions)) {
4916 switch (RKind) {
4917 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4918 // are listed here.
4919 case OMPD_parallel:
4920 SemaRef.ActOnCapturedRegionStart(
4921 Loc, CurScope, Kind: CR_OpenMP,
4922 Params: getParallelRegionParams(SemaRef, LoopBoundSharing), OpenMPCaptureLevel: Level);
4923 break;
4924 case OMPD_teams:
4925 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4926 Params: getTeamsRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4927 break;
4928 case OMPD_task:
4929 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4930 Params: getTaskRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4931 // Mark this captured region as inlined, because we don't use outlined
4932 // function directly.
4933 MarkAsInlined(SemaRef.getCurCapturedRegion());
4934 break;
4935 case OMPD_taskloop:
4936 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4937 Params: getTaskloopRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4938 // Mark this captured region as inlined, because we don't use outlined
4939 // function directly.
4940 MarkAsInlined(SemaRef.getCurCapturedRegion());
4941 break;
4942 case OMPD_target:
4943 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4944 Params: getTargetRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4945 break;
4946 case OMPD_unknown:
4947 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4948 Params: getUnknownRegionParams(SemaRef));
4949 break;
4950 case OMPD_metadirective:
4951 case OMPD_nothing:
4952 default:
4953 llvm_unreachable("Unexpected capture region");
4954 }
4955 }
4956}
4957
4958void SemaOpenMP::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,
4959 Scope *CurScope) {
4960 if (DKind == OMPD_ordered_blockassoc &&
4961 DSAStack->getCurrentDirective() == OMPD_ordered_standalone) {
4962 DSAStack->setOrderedToBlockAssociated();
4963 }
4964 switch (DKind) {
4965 case OMPD_atomic:
4966 case OMPD_critical:
4967 case OMPD_masked:
4968 case OMPD_master:
4969 case OMPD_section:
4970 case OMPD_tile:
4971 case OMPD_stripe:
4972 case OMPD_unroll:
4973 case OMPD_reverse:
4974 case OMPD_split:
4975 case OMPD_interchange:
4976 case OMPD_flatten:
4977 case OMPD_fuse:
4978 case OMPD_assume:
4979 break;
4980 default:
4981 processCapturedRegions(SemaRef, DKind, CurScope,
4982 DSAStack->getConstructLoc());
4983 break;
4984 }
4985
4986 DSAStack->setContext(SemaRef.CurContext);
4987 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4988}
4989
4990int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4991 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4992}
4993
4994int SemaOpenMP::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4995 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4996 getOpenMPCaptureRegions(CaptureRegions, DKind);
4997 return CaptureRegions.size();
4998}
4999
5000static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
5001 Expr *CaptureExpr, bool WithInit,
5002 DeclContext *CurContext,
5003 bool AsExpression) {
5004 assert(CaptureExpr);
5005 ASTContext &C = S.getASTContext();
5006 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
5007 QualType Ty = Init->getType();
5008 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
5009 if (S.getLangOpts().CPlusPlus) {
5010 Ty = C.getLValueReferenceType(T: Ty);
5011 } else {
5012 Ty = C.getPointerType(T: Ty);
5013 ExprResult Res =
5014 S.CreateBuiltinUnaryOp(OpLoc: CaptureExpr->getExprLoc(), Opc: UO_AddrOf, InputExpr: Init);
5015 if (!Res.isUsable())
5016 return nullptr;
5017 Init = Res.get();
5018 }
5019 WithInit = true;
5020 }
5021 auto *CED = OMPCapturedExprDecl::Create(C, DC: CurContext, Id, T: Ty,
5022 StartLoc: CaptureExpr->getBeginLoc());
5023 if (!WithInit)
5024 CED->addAttr(A: OMPCaptureNoInitAttr::CreateImplicit(Ctx&: C));
5025 CurContext->addHiddenDecl(D: CED);
5026 Sema::TentativeAnalysisScope Trap(S);
5027 S.AddInitializerToDecl(dcl: CED, init: Init, /*DirectInit=*/false);
5028 return CED;
5029}
5030
5031static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
5032 bool WithInit) {
5033 OMPCapturedExprDecl *CD;
5034 // For BindingDecls, always create a new capture instead of reusing the
5035 // decomposed decl, since the decomposed decl is a regular VarDecl, not an
5036 // OMPCapturedExprDecl.
5037 if (!isa<BindingDecl>(Val: D)) {
5038 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
5039 CD = cast<OMPCapturedExprDecl>(Val: VD);
5040 else
5041 CD = buildCaptureDecl(S, Id: D->getIdentifier(), CaptureExpr, WithInit,
5042 CurContext: S.CurContext,
5043 /*AsExpression=*/false);
5044 } else {
5045 CD = buildCaptureDecl(S, Id: D->getIdentifier(), CaptureExpr, WithInit,
5046 CurContext: S.CurContext,
5047 /*AsExpression=*/false);
5048 }
5049 return buildDeclRefExpr(S, D: CD, Ty: CD->getType().getNonReferenceType(),
5050 Loc: CaptureExpr->getExprLoc());
5051}
5052
5053static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
5054 StringRef Name) {
5055 CaptureExpr = S.DefaultLvalueConversion(E: CaptureExpr).get();
5056 if (!Ref) {
5057 OMPCapturedExprDecl *CD = buildCaptureDecl(
5058 S, Id: &S.getASTContext().Idents.get(Name), CaptureExpr,
5059 /*WithInit=*/true, CurContext: S.CurContext, /*AsExpression=*/true);
5060 Ref = buildDeclRefExpr(S, D: CD, Ty: CD->getType().getNonReferenceType(),
5061 Loc: CaptureExpr->getExprLoc());
5062 }
5063 ExprResult Res = Ref;
5064 if (!S.getLangOpts().CPlusPlus &&
5065 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
5066 Ref->getType()->isPointerType()) {
5067 Res = S.CreateBuiltinUnaryOp(OpLoc: CaptureExpr->getExprLoc(), Opc: UO_Deref, InputExpr: Ref);
5068 if (!Res.isUsable())
5069 return ExprError();
5070 }
5071 return S.DefaultLvalueConversion(E: Res.get());
5072}
5073
5074namespace {
5075// OpenMP directives parsed in this section are represented as a
5076// CapturedStatement with an associated statement. If a syntax error
5077// is detected during the parsing of the associated statement, the
5078// compiler must abort processing and close the CapturedStatement.
5079//
5080// Combined directives such as 'target parallel' have more than one
5081// nested CapturedStatements. This RAII ensures that we unwind out
5082// of all the nested CapturedStatements when an error is found.
5083class CaptureRegionUnwinderRAII {
5084private:
5085 Sema &S;
5086 bool &ErrorFound;
5087 OpenMPDirectiveKind DKind = OMPD_unknown;
5088
5089public:
5090 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
5091 OpenMPDirectiveKind DKind)
5092 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
5093 ~CaptureRegionUnwinderRAII() {
5094 if (ErrorFound) {
5095 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
5096 while (--ThisCaptureLevel >= 0)
5097 S.ActOnCapturedRegionError();
5098 }
5099 }
5100};
5101} // namespace
5102
5103void SemaOpenMP::tryCaptureOpenMPLambdas(ValueDecl *V) {
5104 // Capture variables captured by reference in lambdas for target-based
5105 // directives.
5106 if (!SemaRef.CurContext->isDependentContext() &&
5107 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
5108 isOpenMPTargetDataManagementDirective(
5109 DSAStack->getCurrentDirective()))) {
5110 QualType Type = V->getType();
5111 if (const auto *RD = Type.getCanonicalType()
5112 .getNonReferenceType()
5113 ->getAsCXXRecordDecl()) {
5114 bool SavedForceCaptureByReferenceInTargetExecutable =
5115 DSAStack->isForceCaptureByReferenceInTargetExecutable();
5116 DSAStack->setForceCaptureByReferenceInTargetExecutable(
5117 /*V=*/true);
5118 if (RD->isLambda()) {
5119 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
5120 FieldDecl *ThisCapture;
5121 RD->getCaptureFields(Captures, ThisCapture);
5122 for (const LambdaCapture &LC : RD->captures()) {
5123 if (LC.getCaptureKind() == LCK_ByRef) {
5124 VarDecl *VD = cast<VarDecl>(Val: LC.getCapturedVar());
5125 DeclContext *VDC = VD->getDeclContext();
5126 if (!VDC->Encloses(DC: SemaRef.CurContext))
5127 continue;
5128 SemaRef.MarkVariableReferenced(Loc: LC.getLocation(), Var: VD);
5129 } else if (LC.getCaptureKind() == LCK_This) {
5130 QualType ThisTy = SemaRef.getCurrentThisType();
5131 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
5132 T1: ThisTy, T2: ThisCapture->getType()))
5133 SemaRef.CheckCXXThisCapture(Loc: LC.getLocation());
5134 }
5135 }
5136 }
5137 DSAStack->setForceCaptureByReferenceInTargetExecutable(
5138 SavedForceCaptureByReferenceInTargetExecutable);
5139 }
5140 }
5141}
5142
5143static bool checkOrderedOrderSpecified(Sema &S,
5144 const ArrayRef<OMPClause *> Clauses) {
5145 const OMPOrderedClause *Ordered = nullptr;
5146 const OMPOrderClause *Order = nullptr;
5147
5148 for (const OMPClause *Clause : Clauses) {
5149 if (Clause->getClauseKind() == OMPC_ordered)
5150 Ordered = cast<OMPOrderedClause>(Val: Clause);
5151 else if (Clause->getClauseKind() == OMPC_order) {
5152 Order = cast<OMPOrderClause>(Val: Clause);
5153 if (Order->getKind() != OMPC_ORDER_concurrent)
5154 Order = nullptr;
5155 }
5156 if (Ordered && Order)
5157 break;
5158 }
5159
5160 if (Ordered && Order) {
5161 S.Diag(Loc: Order->getKindKwLoc(),
5162 DiagID: diag::err_omp_simple_clause_incompatible_with_ordered)
5163 << getOpenMPClauseNameForDiag(C: OMPC_order)
5164 << getOpenMPSimpleClauseTypeName(Kind: OMPC_order, Type: OMPC_ORDER_concurrent)
5165 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
5166 S.Diag(Loc: Ordered->getBeginLoc(), DiagID: diag::note_omp_ordered_param)
5167 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
5168 return true;
5169 }
5170 return false;
5171}
5172
5173StmtResult SemaOpenMP::ActOnOpenMPRegionEnd(StmtResult S,
5174 ArrayRef<OMPClause *> Clauses) {
5175 handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(),
5176 /*ScopeEntry=*/false);
5177 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
5178 return S;
5179
5180 bool ErrorFound = false;
5181 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
5182 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
5183 if (!S.isUsable()) {
5184 ErrorFound = true;
5185 return StmtError();
5186 }
5187
5188 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
5189 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
5190 OMPOrderedClause *OC = nullptr;
5191 OMPScheduleClause *SC = nullptr;
5192 SmallVector<const OMPLinearClause *, 4> LCs;
5193 SmallVector<const OMPClauseWithPreInit *, 4> PICs;
5194 // This is required for proper codegen.
5195 for (OMPClause *Clause : Clauses) {
5196 if (!getLangOpts().OpenMPSimd &&
5197 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
5198 DSAStack->getCurrentDirective() == OMPD_target) &&
5199 Clause->getClauseKind() == OMPC_in_reduction) {
5200 // Capture taskgroup task_reduction descriptors inside the tasking regions
5201 // with the corresponding in_reduction items.
5202 auto *IRC = cast<OMPInReductionClause>(Val: Clause);
5203 for (Expr *E : IRC->taskgroup_descriptors())
5204 if (E)
5205 SemaRef.MarkDeclarationsReferencedInExpr(E);
5206 }
5207 if (isOpenMPPrivate(Kind: Clause->getClauseKind()) ||
5208 Clause->getClauseKind() == OMPC_copyprivate ||
5209 (getLangOpts().OpenMPUseTLS &&
5210 getASTContext().getTargetInfo().isTLSSupported() &&
5211 Clause->getClauseKind() == OMPC_copyin)) {
5212 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
5213 // Mark all variables in private list clauses as used in inner region.
5214 for (Stmt *VarRef : Clause->children()) {
5215 if (auto *E = cast_or_null<Expr>(Val: VarRef)) {
5216 SemaRef.MarkDeclarationsReferencedInExpr(E);
5217 }
5218 }
5219 DSAStack->setForceVarCapturing(/*V=*/false);
5220 } else if (CaptureRegions.size() > 1 ||
5221 CaptureRegions.back() != OMPD_unknown) {
5222 if (auto *C = OMPClauseWithPreInit::get(C: Clause))
5223 PICs.push_back(Elt: C);
5224 if (auto *C = OMPClauseWithPostUpdate::get(C: Clause)) {
5225 if (Expr *E = C->getPostUpdateExpr())
5226 SemaRef.MarkDeclarationsReferencedInExpr(E);
5227 }
5228 }
5229 if (Clause->getClauseKind() == OMPC_schedule)
5230 SC = cast<OMPScheduleClause>(Val: Clause);
5231 else if (Clause->getClauseKind() == OMPC_ordered)
5232 OC = cast<OMPOrderedClause>(Val: Clause);
5233 else if (Clause->getClauseKind() == OMPC_linear)
5234 LCs.push_back(Elt: cast<OMPLinearClause>(Val: Clause));
5235 }
5236 // Capture allocator expressions if used.
5237 for (Expr *E : DSAStack->getInnerAllocators())
5238 SemaRef.MarkDeclarationsReferencedInExpr(E);
5239 // OpenMP, 2.7.1 Loop Construct, Restrictions
5240 // The nonmonotonic modifier cannot be specified if an ordered clause is
5241 // specified.
5242 if (SC &&
5243 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
5244 SC->getSecondScheduleModifier() ==
5245 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
5246 OC) {
5247 Diag(Loc: SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
5248 ? SC->getFirstScheduleModifierLoc()
5249 : SC->getSecondScheduleModifierLoc(),
5250 DiagID: diag::err_omp_simple_clause_incompatible_with_ordered)
5251 << getOpenMPClauseNameForDiag(C: OMPC_schedule)
5252 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule,
5253 Type: OMPC_SCHEDULE_MODIFIER_nonmonotonic)
5254 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
5255 ErrorFound = true;
5256 }
5257 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
5258 // If an order(concurrent) clause is present, an ordered clause may not appear
5259 // on the same directive.
5260 if (checkOrderedOrderSpecified(S&: SemaRef, Clauses))
5261 ErrorFound = true;
5262 if (!LCs.empty() && OC && OC->getNumForLoops()) {
5263 for (const OMPLinearClause *C : LCs) {
5264 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_linear_ordered)
5265 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
5266 }
5267 ErrorFound = true;
5268 }
5269 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
5270 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
5271 OC->getNumForLoops()) {
5272 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
5273 Diag(Loc: OC->getBeginLoc(), DiagID: diag::err_omp_ordered_simd)
5274 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), V: OMPVersion);
5275 ErrorFound = true;
5276 }
5277 if (ErrorFound) {
5278 return StmtError();
5279 }
5280 StmtResult SR = S;
5281 unsigned CompletedRegions = 0;
5282 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(C&: CaptureRegions)) {
5283 // Mark all variables in private list clauses as used in inner region.
5284 // Required for proper codegen of combined directives.
5285 // TODO: add processing for other clauses.
5286 if (ThisCaptureRegion != OMPD_unknown) {
5287 for (const clang::OMPClauseWithPreInit *C : PICs) {
5288 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
5289 // Find the particular capture region for the clause if the
5290 // directive is a combined one with multiple capture regions.
5291 // If the directive is not a combined one, the capture region
5292 // associated with the clause is OMPD_unknown and is generated
5293 // only once.
5294 if (CaptureRegion == ThisCaptureRegion ||
5295 CaptureRegion == OMPD_unknown) {
5296 if (auto *DS = cast_or_null<DeclStmt>(Val: C->getPreInitStmt())) {
5297 for (Decl *D : DS->decls())
5298 SemaRef.MarkVariableReferenced(Loc: D->getLocation(),
5299 Var: cast<VarDecl>(Val: D));
5300 }
5301 }
5302 }
5303 }
5304 if (ThisCaptureRegion == OMPD_target) {
5305 // Capture allocator traits in the target region. They are used implicitly
5306 // and, thus, are not captured by default.
5307 for (OMPClause *C : Clauses) {
5308 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(Val: C)) {
5309 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
5310 ++I) {
5311 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
5312 if (Expr *E = D.AllocatorTraits)
5313 SemaRef.MarkDeclarationsReferencedInExpr(E);
5314 }
5315 continue;
5316 }
5317 }
5318 }
5319 if (ThisCaptureRegion == OMPD_parallel) {
5320 // Capture temp arrays for inscan reductions and locals in aligned
5321 // clauses.
5322 for (OMPClause *C : Clauses) {
5323 if (auto *RC = dyn_cast<OMPReductionClause>(Val: C)) {
5324 if (RC->getModifier() != OMPC_REDUCTION_inscan)
5325 continue;
5326 for (Expr *E : RC->copy_array_temps())
5327 if (E)
5328 SemaRef.MarkDeclarationsReferencedInExpr(E);
5329 }
5330 if (auto *AC = dyn_cast<OMPAlignedClause>(Val: C)) {
5331 for (Expr *E : AC->varlist())
5332 SemaRef.MarkDeclarationsReferencedInExpr(E);
5333 }
5334 }
5335 }
5336 if (++CompletedRegions == CaptureRegions.size())
5337 DSAStack->setBodyComplete();
5338 SR = SemaRef.ActOnCapturedRegionEnd(S: SR.get());
5339 }
5340 return SR;
5341}
5342
5343static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
5344 OpenMPDirectiveKind CancelRegion,
5345 SourceLocation StartLoc) {
5346 // CancelRegion is only needed for cancel and cancellation_point.
5347 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
5348 return false;
5349
5350 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
5351 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
5352 return false;
5353
5354 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
5355 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_wrong_cancel_region)
5356 << getOpenMPDirectiveName(D: CancelRegion, V: OMPVersion);
5357 return true;
5358}
5359
5360static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
5361 OpenMPDirectiveKind CurrentRegion,
5362 const DeclarationNameInfo &CurrentName,
5363 OpenMPDirectiveKind CancelRegion,
5364 OpenMPBindClauseKind BindKind,
5365 SourceLocation StartLoc) {
5366 if (!Stack->getCurScope())
5367 return false;
5368
5369 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
5370 OpenMPDirectiveKind OffendingRegion = ParentRegion;
5371 bool NestingProhibited = false;
5372 bool CloseNesting = true;
5373 bool OrphanSeen = false;
5374 enum {
5375 NoRecommend,
5376 ShouldBeInParallelRegion,
5377 ShouldBeInOrderedRegion,
5378 ShouldBeInTargetRegion,
5379 ShouldBeInTeamsRegion,
5380 ShouldBeInLoopSimdRegion,
5381 } Recommend = NoRecommend;
5382
5383 SmallVector<OpenMPDirectiveKind, 4> LeafOrComposite;
5384 ArrayRef<OpenMPDirectiveKind> ParentLOC =
5385 getLeafOrCompositeConstructs(D: ParentRegion, Output&: LeafOrComposite);
5386 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
5387 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
5388
5389 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
5390 !isOpenMPOrderConcurrentNestableDirective(DKind: CurrentRegion,
5391 LangOpts: SemaRef.LangOpts)) {
5392 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_order)
5393 << getOpenMPDirectiveName(D: CurrentRegion, V: OMPVersion);
5394 return true;
5395 }
5396 if (isOpenMPSimdDirective(DKind: ParentRegion) &&
5397 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered_blockassoc) ||
5398 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered_blockassoc &&
5399 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5400 CurrentRegion != OMPD_scan))) {
5401 // OpenMP [2.16, Nesting of Regions]
5402 // OpenMP constructs may not be nested inside a simd region.
5403 // OpenMP [2.8.1,simd Construct, Restrictions]
5404 // An ordered construct with the simd clause is the only OpenMP
5405 // construct that can appear in the simd region.
5406 // Allowing a SIMD construct nested in another SIMD construct is an
5407 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5408 // message.
5409 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5410 // The only OpenMP constructs that can be encountered during execution of
5411 // a simd region are the atomic construct, the loop construct, the simd
5412 // construct and the ordered construct with the simd clause.
5413 SemaRef.Diag(Loc: StartLoc, DiagID: (CurrentRegion != OMPD_simd)
5414 ? diag::err_omp_prohibited_region_simd
5415 : diag::warn_omp_nesting_simd)
5416 << (OMPVersion >= 50 ? 1 : 0);
5417 return CurrentRegion != OMPD_simd;
5418 }
5419 if (EnclosingConstruct == OMPD_atomic) {
5420 // OpenMP [2.16, Nesting of Regions]
5421 // OpenMP constructs may not be nested inside an atomic region.
5422 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_atomic);
5423 return true;
5424 }
5425 if (CurrentRegion == OMPD_section) {
5426 // OpenMP [2.7.2, sections Construct, Restrictions]
5427 // Orphaned section directives are prohibited. That is, the section
5428 // directives must appear within the sections construct and must not be
5429 // encountered elsewhere in the sections region.
5430 if (EnclosingConstruct != OMPD_sections) {
5431 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_section_directive)
5432 << (ParentRegion != OMPD_unknown)
5433 << getOpenMPDirectiveName(D: ParentRegion, V: OMPVersion);
5434 return true;
5435 }
5436 return false;
5437 }
5438 // Allow some constructs (except teams and cancellation constructs) to be
5439 // orphaned (they could be used in functions, called from OpenMP regions
5440 // with the required preconditions).
5441 if (ParentRegion == OMPD_unknown &&
5442 !isOpenMPNestingTeamsDirective(DKind: CurrentRegion) &&
5443 CurrentRegion != OMPD_cancellation_point &&
5444 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5445 return false;
5446 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5447 // for a detailed explanation
5448 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5449 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5450 (isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5451 EnclosingConstruct == OMPD_loop)) {
5452 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5453 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region)
5454 << true << getOpenMPDirectiveName(D: ParentRegion, V: OMPVersion)
5455 << ErrorMsgNumber << getOpenMPDirectiveName(D: CurrentRegion, V: OMPVersion);
5456 return true;
5457 }
5458 if (CurrentRegion == OMPD_cancellation_point ||
5459 CurrentRegion == OMPD_cancel) {
5460 // OpenMP [2.16, Nesting of Regions]
5461 // A cancellation point construct for which construct-type-clause is
5462 // taskgroup must be nested inside a task construct. A cancellation
5463 // point construct for which construct-type-clause is not taskgroup must
5464 // be closely nested inside an OpenMP construct that matches the type
5465 // specified in construct-type-clause.
5466 // A cancel construct for which construct-type-clause is taskgroup must be
5467 // nested inside a task construct. A cancel construct for which
5468 // construct-type-clause is not taskgroup must be closely nested inside an
5469 // OpenMP construct that matches the type specified in
5470 // construct-type-clause.
5471 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(D: ParentRegion);
5472 if (CancelRegion == OMPD_taskgroup) {
5473 NestingProhibited =
5474 EnclosingConstruct != OMPD_task &&
5475 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5476 } else if (CancelRegion == OMPD_sections) {
5477 NestingProhibited = EnclosingConstruct != OMPD_section &&
5478 EnclosingConstruct != OMPD_sections;
5479 } else {
5480 NestingProhibited = CancelRegion != Leafs.back();
5481 }
5482 OrphanSeen = ParentRegion == OMPD_unknown;
5483 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5484 // OpenMP 5.1 [2.22, Nesting of Regions]
5485 // A masked region may not be closely nested inside a worksharing, loop,
5486 // atomic, task, or taskloop region.
5487 NestingProhibited = isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5488 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
5489 isOpenMPTaskingDirective(Kind: ParentRegion);
5490 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5491 // OpenMP [2.16, Nesting of Regions]
5492 // A critical region may not be nested (closely or otherwise) inside a
5493 // critical region with the same name. Note that this restriction is not
5494 // sufficient to prevent deadlock.
5495 SourceLocation PreviousCriticalLoc;
5496 bool DeadLock = Stack->hasDirective(
5497 DPred: [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5498 const DeclarationNameInfo &DNI,
5499 SourceLocation Loc) {
5500 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5501 PreviousCriticalLoc = Loc;
5502 return true;
5503 }
5504 return false;
5505 },
5506 FromParent: false /* skip top directive */);
5507 if (DeadLock) {
5508 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_critical_same_name)
5509 << CurrentName.getName();
5510 if (PreviousCriticalLoc.isValid())
5511 SemaRef.Diag(Loc: PreviousCriticalLoc,
5512 DiagID: diag::note_omp_previous_critical_region);
5513 return true;
5514 }
5515 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5516 // OpenMP 5.1 [2.22, Nesting of Regions]
5517 // A scope region may not be closely nested inside a worksharing, loop,
5518 // task, taskloop, critical, ordered, atomic, or masked region.
5519 // OpenMP 5.1 [2.22, Nesting of Regions]
5520 // A barrier region may not be closely nested inside a worksharing, loop,
5521 // task, taskloop, critical, ordered, atomic, or masked region.
5522 NestingProhibited =
5523 isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5524 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
5525 isOpenMPTaskingDirective(Kind: ParentRegion) ||
5526 llvm::is_contained(
5527 Set: {OMPD_masked, OMPD_master, OMPD_critical, OMPD_ordered_blockassoc},
5528 Element: EnclosingConstruct);
5529 } else if (isOpenMPWorksharingDirective(DKind: CurrentRegion) &&
5530 !isOpenMPParallelDirective(DKind: CurrentRegion) &&
5531 !isOpenMPTeamsDirective(DKind: CurrentRegion)) {
5532 // OpenMP 5.1 [2.22, Nesting of Regions]
5533 // A loop region that binds to a parallel region or a worksharing region
5534 // may not be closely nested inside a worksharing, loop, task, taskloop,
5535 // critical, ordered, atomic, or masked region.
5536 NestingProhibited =
5537 isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5538 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
5539 isOpenMPTaskingDirective(Kind: ParentRegion) ||
5540 llvm::is_contained(
5541 Set: {OMPD_masked, OMPD_master, OMPD_critical, OMPD_ordered_blockassoc},
5542 Element: EnclosingConstruct);
5543 Recommend = ShouldBeInParallelRegion;
5544 } else if (CurrentRegion == OMPD_ordered_blockassoc ||
5545 CurrentRegion == OMPD_ordered_standalone) {
5546 // OpenMP [2.16, Nesting of Regions]
5547 // An ordered region may not be closely nested inside a critical,
5548 // atomic, or explicit task region.
5549 // An ordered region must be closely nested inside a loop region (or
5550 // parallel loop region) with an ordered clause.
5551 // OpenMP [2.8.1,simd Construct, Restrictions]
5552 // An ordered construct with the simd clause is the only OpenMP construct
5553 // that can appear in the simd region.
5554 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5555 isOpenMPTaskingDirective(Kind: ParentRegion) ||
5556 !(isOpenMPSimdDirective(DKind: ParentRegion) ||
5557 Stack->isParentOrderedRegion());
5558 Recommend = ShouldBeInOrderedRegion;
5559 } else if (isOpenMPNestingTeamsDirective(DKind: CurrentRegion)) {
5560 // OpenMP [2.16, Nesting of Regions]
5561 // If specified, a teams construct must be contained within a target
5562 // construct.
5563 NestingProhibited =
5564 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5565 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5566 EnclosingConstruct != OMPD_target);
5567 OrphanSeen = ParentRegion == OMPD_unknown;
5568 Recommend = ShouldBeInTargetRegion;
5569 } else if (CurrentRegion == OMPD_scan) {
5570 if (OMPVersion >= 50) {
5571 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
5572 // simd, or for simd. This has to take into account combined directives.
5573 // In 5.2 this seems to be implied by the fact that the specified
5574 // separated constructs are do, for, and simd.
5575 NestingProhibited = !llvm::is_contained(
5576 Set: {OMPD_for, OMPD_simd, OMPD_for_simd}, Element: EnclosingConstruct);
5577 } else {
5578 NestingProhibited = true;
5579 }
5580 OrphanSeen = ParentRegion == OMPD_unknown;
5581 Recommend = ShouldBeInLoopSimdRegion;
5582 }
5583 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(DKind: CurrentRegion) &&
5584 !isOpenMPTargetDataManagementDirective(DKind: CurrentRegion) &&
5585 EnclosingConstruct == OMPD_teams) {
5586 // OpenMP [5.1, 2.22, Nesting of Regions]
5587 // distribute, distribute simd, distribute parallel worksharing-loop,
5588 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5589 // including any parallel regions arising from combined constructs,
5590 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5591 // only OpenMP regions that may be strictly nested inside the teams
5592 // region.
5593 //
5594 // As an extension, we permit atomic within teams as well.
5595 NestingProhibited = !isOpenMPParallelDirective(DKind: CurrentRegion) &&
5596 !isOpenMPDistributeDirective(DKind: CurrentRegion) &&
5597 CurrentRegion != OMPD_loop &&
5598 !(SemaRef.getLangOpts().OpenMPExtensions &&
5599 CurrentRegion == OMPD_atomic);
5600 Recommend = ShouldBeInParallelRegion;
5601 }
5602 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5603 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5604 // If the bind clause is present on the loop construct and binding is
5605 // teams then the corresponding loop region must be strictly nested inside
5606 // a teams region.
5607 NestingProhibited =
5608 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5609 Recommend = ShouldBeInTeamsRegion;
5610 }
5611 if (!NestingProhibited && isOpenMPNestingDistributeDirective(DKind: CurrentRegion)) {
5612 // OpenMP 4.5 [2.17 Nesting of Regions]
5613 // The region associated with the distribute construct must be strictly
5614 // nested inside a teams region
5615 NestingProhibited = EnclosingConstruct != OMPD_teams;
5616 Recommend = ShouldBeInTeamsRegion;
5617 }
5618 if (!NestingProhibited &&
5619 (isOpenMPTargetExecutionDirective(DKind: CurrentRegion) ||
5620 isOpenMPTargetDataManagementDirective(DKind: CurrentRegion))) {
5621 // OpenMP 4.5 [2.17 Nesting of Regions]
5622 // If a target, target update, target data, target enter data, or
5623 // target exit data construct is encountered during execution of a
5624 // target region, the behavior is unspecified.
5625 NestingProhibited = Stack->hasDirective(
5626 DPred: [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5627 SourceLocation) {
5628 if (isOpenMPTargetExecutionDirective(DKind: K)) {
5629 OffendingRegion = K;
5630 return true;
5631 }
5632 return false;
5633 },
5634 FromParent: false /* don't skip top directive */);
5635 CloseNesting = false;
5636 }
5637 if (NestingProhibited) {
5638 if (OrphanSeen) {
5639 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_device_directive)
5640 << getOpenMPDirectiveName(D: CurrentRegion, V: OMPVersion) << Recommend;
5641 } else {
5642 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region)
5643 << CloseNesting << getOpenMPDirectiveName(D: OffendingRegion, V: OMPVersion)
5644 << Recommend << getOpenMPDirectiveName(D: CurrentRegion, V: OMPVersion);
5645 }
5646 return true;
5647 }
5648 return false;
5649}
5650
5651struct Kind2Unsigned {
5652 using argument_type = OpenMPDirectiveKind;
5653 unsigned operator()(argument_type DK) { return unsigned(DK); }
5654};
5655static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5656 ArrayRef<OMPClause *> Clauses,
5657 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5658 bool ErrorFound = false;
5659 unsigned NamedModifiersNumber = 0;
5660 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5661 FoundNameModifiers.resize(S: llvm::omp::Directive_enumSize + 1);
5662 SmallVector<SourceLocation, 4> NameModifierLoc;
5663 llvm::omp::Version OMPVersion = S.getLangOpts().getOpenMPVersion();
5664 for (const OMPClause *C : Clauses) {
5665 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(Val: C)) {
5666 // At most one if clause without a directive-name-modifier can appear on
5667 // the directive.
5668 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5669 auto &FNM = FoundNameModifiers[CurNM];
5670 if (FNM) {
5671 S.Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_more_one_clause)
5672 << getOpenMPDirectiveName(D: Kind, V: OMPVersion)
5673 << getOpenMPClauseNameForDiag(C: OMPC_if) << (CurNM != OMPD_unknown)
5674 << getOpenMPDirectiveName(D: CurNM, V: OMPVersion);
5675 ErrorFound = true;
5676 } else if (CurNM != OMPD_unknown) {
5677 NameModifierLoc.push_back(Elt: IC->getNameModifierLoc());
5678 ++NamedModifiersNumber;
5679 }
5680 FNM = IC;
5681 if (CurNM == OMPD_unknown)
5682 continue;
5683 // Check if the specified name modifier is allowed for the current
5684 // directive.
5685 // At most one if clause with the particular directive-name-modifier can
5686 // appear on the directive.
5687 if (!llvm::is_contained(Range&: AllowedNameModifiers, Element: CurNM)) {
5688 S.Diag(Loc: IC->getNameModifierLoc(),
5689 DiagID: diag::err_omp_wrong_if_directive_name_modifier)
5690 << getOpenMPDirectiveName(D: CurNM, V: OMPVersion)
5691 << getOpenMPDirectiveName(D: Kind, V: OMPVersion);
5692 ErrorFound = true;
5693 }
5694 }
5695 }
5696 // If any if clause on the directive includes a directive-name-modifier then
5697 // all if clauses on the directive must include a directive-name-modifier.
5698 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5699 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5700 S.Diag(Loc: FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5701 DiagID: diag::err_omp_no_more_if_clause);
5702 } else {
5703 std::string Values;
5704 std::string Sep(", ");
5705 unsigned AllowedCnt = 0;
5706 unsigned TotalAllowedNum =
5707 AllowedNameModifiers.size() - NamedModifiersNumber;
5708 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5709 ++Cnt) {
5710 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5711 if (!FoundNameModifiers[NM]) {
5712 Values += "'";
5713 Values += getOpenMPDirectiveName(D: NM, V: OMPVersion);
5714 Values += "'";
5715 if (AllowedCnt + 2 == TotalAllowedNum)
5716 Values += " or ";
5717 else if (AllowedCnt + 1 != TotalAllowedNum)
5718 Values += Sep;
5719 ++AllowedCnt;
5720 }
5721 }
5722 S.Diag(Loc: FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5723 DiagID: diag::err_omp_unnamed_if_clause)
5724 << (TotalAllowedNum > 1) << Values;
5725 }
5726 for (SourceLocation Loc : NameModifierLoc) {
5727 S.Diag(Loc, DiagID: diag::note_omp_previous_named_if_clause);
5728 }
5729 ErrorFound = true;
5730 }
5731 return ErrorFound;
5732}
5733
5734static std::pair<ValueDecl *, bool>
5735getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
5736 SourceRange &ERange, bool AllowArraySection,
5737 bool AllowAssumedSizeArray, StringRef DiagType) {
5738 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5739 RefExpr->containsUnexpandedParameterPack())
5740 return std::make_pair(x: nullptr, y: true);
5741
5742 // OpenMP [3.1, C/C++]
5743 // A list item is a variable name.
5744 // OpenMP [2.9.3.3, Restrictions, p.1]
5745 // A variable that is part of another variable (as an array or
5746 // structure element) cannot appear in a private clause.
5747 //
5748 // OpenMP [6.0]
5749 // 5.2.5 Array Sections, p. 166, L28-29
5750 // When the length is absent and the size of the dimension is not known,
5751 // the array section is an assumed-size array.
5752 // 2 Glossary, p. 23, L4-6
5753 // assumed-size array
5754 // For C/C++, an array section for which the length is absent and the
5755 // size of the dimensions is not known.
5756 // 5.2.5 Array Sections, p. 168, L11
5757 // An assumed-size array can appear only in clauses for which it is
5758 // explicitly allowed.
5759 // 7.4 List Item Privatization, Restrictions, p. 222, L15
5760 // Assumed-size arrays must not be privatized.
5761 RefExpr = RefExpr->IgnoreParens();
5762 enum {
5763 NoArrayExpr = -1,
5764 ArraySubscript = 0,
5765 OMPArraySection = 1
5766 } IsArrayExpr = NoArrayExpr;
5767 if (AllowArraySection) {
5768 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(Val: RefExpr)) {
5769 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5770 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base))
5771 Base = TempASE->getBase()->IgnoreParenImpCasts();
5772 RefExpr = Base;
5773 IsArrayExpr = ArraySubscript;
5774 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(Val: RefExpr)) {
5775 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5776 if (S.getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5777 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5778 QualType BaseType = ArraySectionExpr::getBaseOriginalType(Base);
5779 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5780 !BaseType->isVariableArrayType())) {
5781 S.Diag(Loc: OASE->getColonLocFirst(),
5782 DiagID: diag::err_omp_section_length_undefined)
5783 << (!BaseType.isNull() && BaseType->isArrayType());
5784 return std::make_pair(x: nullptr, y: false);
5785 }
5786 }
5787 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Val: Base))
5788 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5789 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base))
5790 Base = TempASE->getBase()->IgnoreParenImpCasts();
5791 RefExpr = Base;
5792 IsArrayExpr = OMPArraySection;
5793 }
5794 }
5795 ELoc = RefExpr->getExprLoc();
5796 ERange = RefExpr->getSourceRange();
5797 RefExpr = RefExpr->IgnoreParenImpCasts();
5798 auto *DE = dyn_cast_or_null<DeclRefExpr>(Val: RefExpr);
5799 auto *ME = dyn_cast_or_null<MemberExpr>(Val: RefExpr);
5800 if ((!DE || !isa<VarDecl, BindingDecl>(Val: DE->getDecl())) &&
5801 (S.getCurrentThisType().isNull() || !ME ||
5802 !isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()) ||
5803 !isa<FieldDecl>(Val: ME->getMemberDecl()))) {
5804 if (IsArrayExpr != NoArrayExpr) {
5805 S.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
5806 << IsArrayExpr << ERange;
5807 } else if (!DiagType.empty()) {
5808 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5809 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5810 : 0;
5811 S.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_var_name_member_expr_with_type)
5812 << DiagSelect << DiagType << ERange;
5813 } else {
5814 S.Diag(Loc: ELoc,
5815 DiagID: AllowArraySection
5816 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5817 : diag::err_omp_expected_var_name_member_expr)
5818 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5819 }
5820 return std::make_pair(x: nullptr, y: false);
5821 }
5822 return std::make_pair(
5823 x: getCanonicalDecl(D: DE ? DE->getDecl() : ME->getMemberDecl()), y: false);
5824}
5825
5826namespace {
5827/// Checks if the allocator is used in uses_allocators clause to be allowed in
5828/// target regions.
5829class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5830 DSAStackTy *S = nullptr;
5831
5832public:
5833 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5834 return S->isUsesAllocatorsDecl(D: E->getDecl())
5835 .value_or(u: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5836 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5837 }
5838 bool VisitStmt(const Stmt *S) {
5839 for (const Stmt *Child : S->children()) {
5840 if (Child && Visit(S: Child))
5841 return true;
5842 }
5843 return false;
5844 }
5845 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5846};
5847} // namespace
5848
5849static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5850 ArrayRef<OMPClause *> Clauses) {
5851 assert(!S.CurContext->isDependentContext() &&
5852 "Expected non-dependent context.");
5853 auto AllocateRange =
5854 llvm::make_filter_range(Range&: Clauses, Pred: OMPAllocateClause::classof);
5855 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5856 auto PrivateRange = llvm::make_filter_range(Range&: Clauses, Pred: [](const OMPClause *C) {
5857 return isOpenMPPrivate(Kind: C->getClauseKind());
5858 });
5859 for (OMPClause *Cl : PrivateRange) {
5860 MutableArrayRef<Expr *>::iterator I, It, Et;
5861 if (Cl->getClauseKind() == OMPC_private) {
5862 auto *PC = cast<OMPPrivateClause>(Val: Cl);
5863 I = PC->private_copies().begin();
5864 It = PC->varlist_begin();
5865 Et = PC->varlist_end();
5866 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5867 auto *PC = cast<OMPFirstprivateClause>(Val: Cl);
5868 I = PC->private_copies().begin();
5869 It = PC->varlist_begin();
5870 Et = PC->varlist_end();
5871 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5872 auto *PC = cast<OMPLastprivateClause>(Val: Cl);
5873 I = PC->private_copies().begin();
5874 It = PC->varlist_begin();
5875 Et = PC->varlist_end();
5876 } else if (Cl->getClauseKind() == OMPC_linear) {
5877 auto *PC = cast<OMPLinearClause>(Val: Cl);
5878 I = PC->privates().begin();
5879 It = PC->varlist_begin();
5880 Et = PC->varlist_end();
5881 } else if (Cl->getClauseKind() == OMPC_reduction) {
5882 auto *PC = cast<OMPReductionClause>(Val: Cl);
5883 I = PC->privates().begin();
5884 It = PC->varlist_begin();
5885 Et = PC->varlist_end();
5886 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5887 auto *PC = cast<OMPTaskReductionClause>(Val: Cl);
5888 I = PC->privates().begin();
5889 It = PC->varlist_begin();
5890 Et = PC->varlist_end();
5891 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5892 auto *PC = cast<OMPInReductionClause>(Val: Cl);
5893 I = PC->privates().begin();
5894 It = PC->varlist_begin();
5895 Et = PC->varlist_end();
5896 } else {
5897 llvm_unreachable("Expected private clause.");
5898 }
5899 for (Expr *E : llvm::make_range(x: It, y: Et)) {
5900 if (!*I) {
5901 ++I;
5902 continue;
5903 }
5904 SourceLocation ELoc;
5905 SourceRange ERange;
5906 Expr *SimpleRefExpr = E;
5907 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
5908 /*AllowArraySection=*/true);
5909 DeclToCopy.try_emplace(Key: Res.first,
5910 Args: cast<VarDecl>(Val: cast<DeclRefExpr>(Val: *I)->getDecl()));
5911 ++I;
5912 }
5913 }
5914 for (OMPClause *C : AllocateRange) {
5915 auto *AC = cast<OMPAllocateClause>(Val: C);
5916 if (S.getLangOpts().OpenMP >= 50 &&
5917 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5918 isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective()) &&
5919 AC->getAllocator()) {
5920 Expr *Allocator = AC->getAllocator();
5921 // OpenMP, 2.12.5 target Construct
5922 // Memory allocators that do not appear in a uses_allocators clause cannot
5923 // appear as an allocator in an allocate clause or be used in the target
5924 // region unless a requires directive with the dynamic_allocators clause
5925 // is present in the same compilation unit.
5926 AllocatorChecker Checker(Stack);
5927 if (Checker.Visit(S: Allocator))
5928 S.Diag(Loc: Allocator->getExprLoc(),
5929 DiagID: diag::err_omp_allocator_not_in_uses_allocators)
5930 << Allocator->getSourceRange();
5931 }
5932 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5933 getAllocatorKind(S, Stack, Allocator: AC->getAllocator());
5934 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5935 // For task, taskloop or target directives, allocation requests to memory
5936 // allocators with the trait access set to thread result in unspecified
5937 // behavior.
5938 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5939 (isOpenMPTaskingDirective(Kind: Stack->getCurrentDirective()) ||
5940 isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective()))) {
5941 llvm::omp::Version OMPVersion = S.getLangOpts().getOpenMPVersion();
5942 S.Diag(Loc: AC->getAllocator()->getExprLoc(),
5943 DiagID: diag::warn_omp_allocate_thread_on_task_target_directive)
5944 << getOpenMPDirectiveName(D: Stack->getCurrentDirective(), V: OMPVersion);
5945 }
5946 for (Expr *E : AC->varlist()) {
5947 SourceLocation ELoc;
5948 SourceRange ERange;
5949 Expr *SimpleRefExpr = E;
5950 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange);
5951 ValueDecl *VD = Res.first;
5952 if (!VD)
5953 continue;
5954 DSAStackTy::DSAVarData Data = Stack->getTopDSA(D: VD, /*FromParent=*/false);
5955 if (!isOpenMPPrivate(Kind: Data.CKind)) {
5956 S.Diag(Loc: E->getExprLoc(),
5957 DiagID: diag::err_omp_expected_private_copy_for_allocate);
5958 continue;
5959 }
5960 VarDecl *PrivateVD = DeclToCopy[VD];
5961 if (checkPreviousOMPAllocateAttribute(S, Stack, RefExpr: E, VD: PrivateVD,
5962 AllocatorKind, Allocator: AC->getAllocator()))
5963 continue;
5964 applyOMPAllocateAttribute(S, VD: PrivateVD, AllocatorKind, Allocator: AC->getAllocator(),
5965 Alignment: AC->getAlignment(), SR: E->getSourceRange());
5966 }
5967 }
5968}
5969
5970namespace {
5971/// Rewrite statements and expressions for Sema \p Actions CurContext.
5972///
5973/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5974/// context. DeclRefExpr used inside the new context are changed to refer to the
5975/// captured variable instead.
5976class CaptureVars : public TreeTransform<CaptureVars> {
5977 using BaseTransform = TreeTransform<CaptureVars>;
5978
5979public:
5980 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5981
5982 bool AlwaysRebuild() { return true; }
5983};
5984} // namespace
5985
5986/// Like ASTContext::getIntTypeForBitwidth, but falls back to a _BitInt type
5987/// when no standard integer type has the requested width.
5988static QualType getIntTypeForBitwidthOrBitInt(ASTContext &C, unsigned Bits,
5989 bool Signed) {
5990 QualType Ty = C.getIntTypeForBitwidth(DestWidth: Bits, Signed);
5991 if (Ty.isNull())
5992 Ty = C.getBitIntType(/*IsUnsigned=*/Unsigned: !Signed, NumBits: Bits);
5993 return Ty;
5994}
5995
5996static VarDecl *precomputeExpr(Sema &Actions,
5997 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5998 StringRef Name) {
5999 Expr *NewE = AssertSuccess(R: CaptureVars(Actions).TransformExpr(E));
6000 VarDecl *NewVar = buildVarDecl(SemaRef&: Actions, Loc: {}, Type: NewE->getType(), Name, Attrs: nullptr,
6001 OrigRef: dyn_cast<DeclRefExpr>(Val: E->IgnoreImplicit()));
6002 auto *NewDeclStmt = cast<DeclStmt>(Val: AssertSuccess(
6003 R: Actions.ActOnDeclStmt(Decl: Actions.ConvertDeclToDeclGroup(Ptr: NewVar), StartLoc: {}, EndLoc: {})));
6004 Actions.AddInitializerToDecl(dcl: NewDeclStmt->getSingleDecl(), init: NewE, DirectInit: false);
6005 BodyStmts.push_back(Elt: NewDeclStmt);
6006 return NewVar;
6007}
6008
6009/// Create a closure that computes the number of iterations of a loop.
6010///
6011/// \param Actions The Sema object.
6012/// \param LogicalTy Type for the logical iteration number.
6013/// \param Rel Comparison operator of the loop condition.
6014/// \param StartExpr Value of the loop counter at the first iteration.
6015/// \param StopExpr Expression the loop counter is compared against in the loop
6016/// condition. \param StepExpr Amount of increment after each iteration.
6017///
6018/// \return Closure (CapturedStmt) of the distance calculation.
6019static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
6020 BinaryOperator::Opcode Rel,
6021 Expr *StartExpr, Expr *StopExpr,
6022 Expr *StepExpr) {
6023 ASTContext &Ctx = Actions.getASTContext();
6024 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(T: LogicalTy);
6025
6026 // Captured regions currently don't support return values, we use an
6027 // out-parameter instead. All inputs are implicit captures.
6028 // TODO: Instead of capturing each DeclRefExpr occurring in
6029 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
6030 QualType ResultTy = Ctx.getLValueReferenceType(T: LogicalTy);
6031 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
6032 {StringRef(), QualType()}};
6033 Actions.ActOnCapturedRegionStart(Loc: {}, CurScope: nullptr, Kind: CR_Default, Params);
6034
6035 Stmt *Body;
6036 {
6037 Sema::CompoundScopeRAII CompoundScope(Actions);
6038 CapturedDecl *CS = cast<CapturedDecl>(Val: Actions.CurContext);
6039
6040 // Get the LValue expression for the result.
6041 ImplicitParamDecl *DistParam = CS->getParam(i: 0);
6042 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
6043 D: DistParam, Ty: LogicalTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
6044
6045 SmallVector<Stmt *, 4> BodyStmts;
6046
6047 // Capture all referenced variable references.
6048 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
6049 // CapturedStmt, we could compute them before and capture the result, to be
6050 // used jointly with the LoopVar function.
6051 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, E: StartExpr, Name: ".start");
6052 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, E: StopExpr, Name: ".stop");
6053 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, E: StepExpr, Name: ".step");
6054 auto BuildVarRef = [&](VarDecl *VD) {
6055 return buildDeclRefExpr(S&: Actions, D: VD, Ty: VD->getType(), Loc: {});
6056 };
6057
6058 IntegerLiteral *Zero = IntegerLiteral::Create(
6059 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 0), type: LogicalTy, l: {});
6060 IntegerLiteral *One = IntegerLiteral::Create(
6061 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 1), type: LogicalTy, l: {});
6062 Expr *Dist;
6063 if (Rel == BO_NE) {
6064 // When using a != comparison, the increment can be +1 or -1. This can be
6065 // dynamic at runtime, so we need to check for the direction.
6066 Expr *IsNegStep = AssertSuccess(
6067 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_LT, LHSExpr: BuildVarRef(NewStep), RHSExpr: Zero));
6068
6069 // Positive increment.
6070 Expr *ForwardRange = AssertSuccess(R: Actions.BuildBinOp(
6071 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStop), RHSExpr: BuildVarRef(NewStart)));
6072 ForwardRange = AssertSuccess(
6073 R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: ForwardRange));
6074 Expr *ForwardDist = AssertSuccess(R: Actions.BuildBinOp(
6075 S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: ForwardRange, RHSExpr: BuildVarRef(NewStep)));
6076
6077 // Negative increment.
6078 Expr *BackwardRange = AssertSuccess(R: Actions.BuildBinOp(
6079 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
6080 BackwardRange = AssertSuccess(
6081 R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: BackwardRange));
6082 Expr *NegIncAmount = AssertSuccess(
6083 R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: BuildVarRef(NewStep)));
6084 Expr *BackwardDist = AssertSuccess(
6085 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: BackwardRange, RHSExpr: NegIncAmount));
6086
6087 // Use the appropriate case.
6088 Dist = AssertSuccess(R: Actions.ActOnConditionalOp(
6089 QuestionLoc: {}, ColonLoc: {}, CondExpr: IsNegStep, LHSExpr: BackwardDist, RHSExpr: ForwardDist));
6090 } else {
6091 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
6092 "Expected one of these relational operators");
6093
6094 // We can derive the direction from any other comparison operator. It is
6095 // non well-formed OpenMP if Step increments/decrements in the other
6096 // directions. Whether at least the first iteration passes the loop
6097 // condition.
6098 Expr *HasAnyIteration = AssertSuccess(R: Actions.BuildBinOp(
6099 S: nullptr, OpLoc: {}, Opc: Rel, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
6100
6101 // Compute the range between first and last counter value.
6102 Expr *Range;
6103 if (Rel == BO_GE || Rel == BO_GT)
6104 Range = AssertSuccess(R: Actions.BuildBinOp(
6105 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
6106 else
6107 Range = AssertSuccess(R: Actions.BuildBinOp(
6108 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStop), RHSExpr: BuildVarRef(NewStart)));
6109
6110 // Ensure unsigned range space.
6111 Range =
6112 AssertSuccess(R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: Range));
6113
6114 if (Rel == BO_LE || Rel == BO_GE) {
6115 // Add one to the range if the relational operator is inclusive.
6116 Range =
6117 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: Range, RHSExpr: One));
6118 }
6119
6120 // Divide by the absolute step amount. If the range is not a multiple of
6121 // the step size, rounding-up the effective upper bound ensures that the
6122 // last iteration is included.
6123 // Note that the rounding-up may cause an overflow in a temporary that
6124 // could be avoided, but would have occurred in a C-style for-loop as
6125 // well.
6126 Expr *Divisor = BuildVarRef(NewStep);
6127 if (Rel == BO_GE || Rel == BO_GT)
6128 Divisor =
6129 AssertSuccess(R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: Divisor));
6130 Expr *DivisorMinusOne =
6131 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: Divisor, RHSExpr: One));
6132 Expr *RangeRoundUp = AssertSuccess(
6133 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: Range, RHSExpr: DivisorMinusOne));
6134 Dist = AssertSuccess(
6135 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: RangeRoundUp, RHSExpr: Divisor));
6136
6137 // If there is not at least one iteration, the range contains garbage. Fix
6138 // to zero in this case.
6139 Dist = AssertSuccess(
6140 R: Actions.ActOnConditionalOp(QuestionLoc: {}, ColonLoc: {}, CondExpr: HasAnyIteration, LHSExpr: Dist, RHSExpr: Zero));
6141 }
6142
6143 // Assign the result to the out-parameter.
6144 Stmt *ResultAssign = AssertSuccess(R: Actions.BuildBinOp(
6145 S: Actions.getCurScope(), OpLoc: {}, Opc: BO_Assign, LHSExpr: DistRef, RHSExpr: Dist));
6146 BodyStmts.push_back(Elt: ResultAssign);
6147
6148 Body = AssertSuccess(R: Actions.ActOnCompoundStmt(L: {}, R: {}, Elts: BodyStmts, isStmtExpr: false));
6149 }
6150
6151 return cast<CapturedStmt>(
6152 Val: AssertSuccess(R: Actions.ActOnCapturedRegionEnd(S: Body)));
6153}
6154
6155/// Create a closure that computes the loop variable from the logical iteration
6156/// number.
6157///
6158/// \param Actions The Sema object.
6159/// \param LoopVarTy Type for the loop variable used for result value.
6160/// \param LogicalTy Type for the logical iteration number.
6161/// \param StartExpr Value of the loop counter at the first iteration.
6162/// \param Step Amount of increment after each iteration.
6163/// \param Deref Whether the loop variable is a dereference of the loop
6164/// counter variable.
6165///
6166/// \return Closure (CapturedStmt) of the loop value calculation.
6167static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
6168 QualType LogicalTy,
6169 DeclRefExpr *StartExpr, Expr *Step,
6170 bool Deref) {
6171 ASTContext &Ctx = Actions.getASTContext();
6172
6173 // Pass the result as an out-parameter. Passing as return value would require
6174 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
6175 // invoke a copy constructor.
6176 QualType TargetParamTy = Ctx.getLValueReferenceType(T: LoopVarTy);
6177 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
6178 {"Logical", LogicalTy},
6179 {StringRef(), QualType()}};
6180 Actions.ActOnCapturedRegionStart(Loc: {}, CurScope: nullptr, Kind: CR_Default, Params);
6181
6182 // Capture the initial iterator which represents the LoopVar value at the
6183 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
6184 // it in every iteration, capture it by value before it is modified.
6185 VarDecl *StartVar = cast<VarDecl>(Val: StartExpr->getDecl());
6186 bool Invalid = Actions.tryCaptureVariable(Var: StartVar, Loc: {},
6187 Kind: TryCaptureKind::ExplicitByVal, EllipsisLoc: {});
6188 (void)Invalid;
6189 assert(!Invalid && "Expecting capture-by-value to work.");
6190
6191 Expr *Body;
6192 {
6193 Sema::CompoundScopeRAII CompoundScope(Actions);
6194 auto *CS = cast<CapturedDecl>(Val: Actions.CurContext);
6195
6196 ImplicitParamDecl *TargetParam = CS->getParam(i: 0);
6197 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
6198 D: TargetParam, Ty: LoopVarTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
6199 ImplicitParamDecl *IndvarParam = CS->getParam(i: 1);
6200 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
6201 D: IndvarParam, Ty: LogicalTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
6202
6203 // Capture the Start expression.
6204 CaptureVars Recap(Actions);
6205 Expr *NewStart = AssertSuccess(R: Recap.TransformExpr(E: StartExpr));
6206 Expr *NewStep = AssertSuccess(R: Recap.TransformExpr(E: Step));
6207
6208 Expr *Skip = AssertSuccess(
6209 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Mul, LHSExpr: NewStep, RHSExpr: LogicalRef));
6210 // TODO: Explicitly cast to the iterator's difference_type instead of
6211 // relying on implicit conversion.
6212 Expr *Advanced =
6213 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: NewStart, RHSExpr: Skip));
6214
6215 if (Deref) {
6216 // For range-based for-loops convert the loop counter value to a concrete
6217 // loop variable value by dereferencing the iterator.
6218 Advanced =
6219 AssertSuccess(R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Deref, Input: Advanced));
6220 }
6221
6222 // Assign the result to the output parameter.
6223 Body = AssertSuccess(R: Actions.BuildBinOp(S: Actions.getCurScope(), OpLoc: {},
6224 Opc: BO_Assign, LHSExpr: TargetRef, RHSExpr: Advanced));
6225 }
6226 return cast<CapturedStmt>(
6227 Val: AssertSuccess(R: Actions.ActOnCapturedRegionEnd(S: Body)));
6228}
6229
6230StmtResult SemaOpenMP::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
6231 ASTContext &Ctx = getASTContext();
6232
6233 // Extract the common elements of ForStmt and CXXForRangeStmt:
6234 // Loop variable, repeat condition, increment
6235 Expr *Cond, *Inc;
6236 VarDecl *LIVDecl, *LUVDecl;
6237 if (auto *For = dyn_cast<ForStmt>(Val: AStmt)) {
6238 Stmt *Init = For->getInit();
6239 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Val: Init)) {
6240 // For statement declares loop variable.
6241 LIVDecl = cast<VarDecl>(Val: LCVarDeclStmt->getSingleDecl());
6242 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Val: Init)) {
6243 // For statement reuses variable.
6244 assert(LCAssign->getOpcode() == BO_Assign &&
6245 "init part must be a loop variable assignment");
6246 auto *CounterRef = cast<DeclRefExpr>(Val: LCAssign->getLHS());
6247 LIVDecl = cast<VarDecl>(Val: CounterRef->getDecl());
6248 } else
6249 llvm_unreachable("Cannot determine loop variable");
6250 LUVDecl = LIVDecl;
6251
6252 Cond = For->getCond();
6253 Inc = For->getInc();
6254 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(Val: AStmt)) {
6255 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
6256 LIVDecl = cast<VarDecl>(Val: BeginStmt->getSingleDecl());
6257 LUVDecl = RangeFor->getLoopVariable();
6258
6259 Cond = RangeFor->getCond();
6260 Inc = RangeFor->getInc();
6261 } else
6262 llvm_unreachable("unhandled kind of loop");
6263
6264 QualType CounterTy = LIVDecl->getType();
6265 QualType LVTy = LUVDecl->getType();
6266
6267 // Analyze the loop condition.
6268 Expr *LHS, *RHS;
6269 BinaryOperator::Opcode CondRel;
6270 Cond = Cond->IgnoreImplicit();
6271 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Val: Cond)) {
6272 LHS = CondBinExpr->getLHS();
6273 RHS = CondBinExpr->getRHS();
6274 CondRel = CondBinExpr->getOpcode();
6275 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Val: Cond)) {
6276 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
6277 LHS = CondCXXOp->getArg(Arg: 0);
6278 RHS = CondCXXOp->getArg(Arg: 1);
6279 switch (CondCXXOp->getOperator()) {
6280 case OO_ExclaimEqual:
6281 CondRel = BO_NE;
6282 break;
6283 case OO_Less:
6284 CondRel = BO_LT;
6285 break;
6286 case OO_LessEqual:
6287 CondRel = BO_LE;
6288 break;
6289 case OO_Greater:
6290 CondRel = BO_GT;
6291 break;
6292 case OO_GreaterEqual:
6293 CondRel = BO_GE;
6294 break;
6295 default:
6296 llvm_unreachable("unexpected iterator operator");
6297 }
6298 } else
6299 llvm_unreachable("unexpected loop condition");
6300
6301 // Normalize such that the loop counter is on the LHS.
6302 if (!isa<DeclRefExpr>(Val: LHS->IgnoreImplicit()) ||
6303 cast<DeclRefExpr>(Val: LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
6304 std::swap(a&: LHS, b&: RHS);
6305 CondRel = BinaryOperator::reverseComparisonOp(Opc: CondRel);
6306 }
6307 auto *CounterRef = cast<DeclRefExpr>(Val: LHS->IgnoreImplicit());
6308
6309 // Decide the bit width for the logical iteration counter. By default use the
6310 // unsigned ptrdiff_t integer size (for iterators and pointers).
6311 // TODO: For iterators, use iterator::difference_type,
6312 // std::iterator_traits<>::difference_type or decltype(it - end).
6313 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
6314 if (CounterTy->isIntegerType()) {
6315 unsigned BitWidth = Ctx.getIntWidth(T: CounterTy);
6316 LogicalTy = getIntTypeForBitwidthOrBitInt(C&: Ctx, Bits: BitWidth, /*Signed=*/false);
6317 }
6318
6319 // Analyze the loop increment.
6320 Expr *Step;
6321 if (auto *IncUn = dyn_cast<UnaryOperator>(Val: Inc)) {
6322 int Direction;
6323 switch (IncUn->getOpcode()) {
6324 case UO_PreInc:
6325 case UO_PostInc:
6326 Direction = 1;
6327 break;
6328 case UO_PreDec:
6329 case UO_PostDec:
6330 Direction = -1;
6331 break;
6332 default:
6333 llvm_unreachable("unhandled unary increment operator");
6334 }
6335 Step = IntegerLiteral::Create(
6336 C: Ctx,
6337 V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), Direction, /*isSigned=*/true),
6338 type: LogicalTy, l: {});
6339 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Val: Inc)) {
6340 if (IncBin->getOpcode() == BO_AddAssign) {
6341 Step = IncBin->getRHS();
6342 } else if (IncBin->getOpcode() == BO_SubAssign) {
6343 Step = AssertSuccess(
6344 R: SemaRef.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: IncBin->getRHS()));
6345 } else
6346 llvm_unreachable("unhandled binary increment operator");
6347 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Val: Inc)) {
6348 switch (CondCXXOp->getOperator()) {
6349 case OO_PlusPlus:
6350 Step = IntegerLiteral::Create(
6351 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 1), type: LogicalTy, l: {});
6352 break;
6353 case OO_MinusMinus:
6354 Step = IntegerLiteral::Create(
6355 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), -1), type: LogicalTy, l: {});
6356 break;
6357 case OO_PlusEqual:
6358 Step = CondCXXOp->getArg(Arg: 1);
6359 break;
6360 case OO_MinusEqual:
6361 Step = AssertSuccess(
6362 R: SemaRef.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: CondCXXOp->getArg(Arg: 1)));
6363 break;
6364 default:
6365 llvm_unreachable("unhandled overloaded increment operator");
6366 }
6367 } else
6368 llvm_unreachable("unknown increment expression");
6369
6370 CapturedStmt *DistanceFunc =
6371 buildDistanceFunc(Actions&: SemaRef, LogicalTy, Rel: CondRel, StartExpr: LHS, StopExpr: RHS, StepExpr: Step);
6372 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
6373 Actions&: SemaRef, LoopVarTy: LVTy, LogicalTy, StartExpr: CounterRef, Step, Deref: isa<CXXForRangeStmt>(Val: AStmt));
6374 DeclRefExpr *LVRef =
6375 SemaRef.BuildDeclRefExpr(D: LUVDecl, Ty: LUVDecl->getType(), VK: VK_LValue, NameInfo: {},
6376 SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
6377 return OMPCanonicalLoop::create(Ctx: getASTContext(), LoopStmt: AStmt, DistanceFunc,
6378 LoopVarFunc, LoopVarRef: LVRef);
6379}
6380
6381StmtResult SemaOpenMP::ActOnOpenMPLoopnest(Stmt *AStmt) {
6382 // Handle a literal loop.
6383 if (isa<ForStmt>(Val: AStmt) || isa<CXXForRangeStmt>(Val: AStmt))
6384 return ActOnOpenMPCanonicalLoop(AStmt);
6385
6386 // If not a literal loop, it must be the result of a loop transformation.
6387 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(Val: AStmt);
6388 assert(
6389 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
6390 "Loop transformation directive expected");
6391 return LoopTransform;
6392}
6393
6394static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
6395 CXXScopeSpec &MapperIdScopeSpec,
6396 const DeclarationNameInfo &MapperId,
6397 QualType Type,
6398 Expr *UnresolvedMapper,
6399 SourceLocation ItemLoc);
6400
6401/// Perform DFS through the structure/class data members trying to find
6402/// member(s) with user-defined 'default' mapper and generate implicit map
6403/// clauses for such members with the found 'default' mapper.
6404static void
6405processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
6406 SmallVectorImpl<OMPClause *> &Clauses) {
6407 // Check for the default mapper for data members.
6408 if (S.getLangOpts().OpenMP < 50)
6409 return;
6410 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6411 auto *C = dyn_cast<OMPMapClause>(Val: Clauses[Cnt]);
6412 if (!C)
6413 continue;
6414 SmallVector<Expr *, 4> SubExprs;
6415 auto *MI = C->mapperlist_begin();
6416 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
6417 ++I, ++MI) {
6418 // Expression is mapped using mapper - skip it.
6419 if (*MI)
6420 continue;
6421 Expr *E = *I;
6422 // Expression is dependent - skip it, build the mapper when it gets
6423 // instantiated.
6424 if (E->isTypeDependent() || E->isValueDependent() ||
6425 E->containsUnexpandedParameterPack())
6426 continue;
6427 // Array section - need to check for the mapping of the array section
6428 // element.
6429 QualType CanonType = E->getType().getCanonicalType();
6430 if (CanonType->isSpecificBuiltinType(K: BuiltinType::ArraySection)) {
6431 const auto *OASE = cast<ArraySectionExpr>(Val: E->IgnoreParenImpCasts());
6432 QualType BaseType =
6433 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
6434 QualType ElemType;
6435 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6436 ElemType = ATy->getElementType();
6437 else
6438 ElemType = BaseType->getPointeeType();
6439 CanonType = ElemType;
6440 }
6441
6442 // DFS over data members in structures/classes.
6443 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
6444 1, {CanonType, nullptr});
6445 llvm::DenseMap<const Type *, Expr *> Visited;
6446 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
6447 1, {nullptr, 1});
6448 while (!Types.empty()) {
6449 QualType BaseType;
6450 FieldDecl *CurFD;
6451 std::tie(args&: BaseType, args&: CurFD) = Types.pop_back_val();
6452 while (ParentChain.back().second == 0)
6453 ParentChain.pop_back();
6454 --ParentChain.back().second;
6455 if (BaseType.isNull())
6456 continue;
6457 // Only structs/classes are allowed to have mappers.
6458 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6459 if (!RD)
6460 continue;
6461 auto It = Visited.find(Val: BaseType.getTypePtr());
6462 if (It == Visited.end()) {
6463 // Try to find the associated user-defined mapper.
6464 CXXScopeSpec MapperIdScopeSpec;
6465 DeclarationNameInfo DefaultMapperId;
6466 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
6467 ID: &S.Context.Idents.get(Name: "default")));
6468 DefaultMapperId.setLoc(E->getExprLoc());
6469 ExprResult ER = buildUserDefinedMapperRef(
6470 SemaRef&: S, S: Stack->getCurScope(), MapperIdScopeSpec, MapperId: DefaultMapperId,
6471 Type: BaseType, /*UnresolvedMapper=*/nullptr, ItemLoc: E->getExprLoc());
6472 if (ER.isInvalid())
6473 continue;
6474 It = Visited.try_emplace(Key: BaseType.getTypePtr(), Args: ER.get()).first;
6475 }
6476 // Found default mapper.
6477 if (It->second) {
6478 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6479 VK_LValue, OK_Ordinary, E);
6480 OE->setIsUnique(/*V=*/true);
6481 Expr *BaseExpr = OE;
6482 for (const auto &P : ParentChain) {
6483 if (P.first) {
6484 BaseExpr = S.BuildMemberExpr(
6485 Base: BaseExpr, /*IsArrow=*/false, OpLoc: E->getExprLoc(),
6486 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: P.first,
6487 FoundDecl: DeclAccessPair::make(D: P.first, AS: P.first->getAccess()),
6488 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(),
6489 Ty: P.first->getType(), VK: VK_LValue, OK: OK_Ordinary);
6490 BaseExpr = S.DefaultLvalueConversion(E: BaseExpr).get();
6491 }
6492 }
6493 if (CurFD)
6494 BaseExpr = S.BuildMemberExpr(
6495 Base: BaseExpr, /*IsArrow=*/false, OpLoc: E->getExprLoc(),
6496 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: CurFD,
6497 FoundDecl: DeclAccessPair::make(D: CurFD, AS: CurFD->getAccess()),
6498 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(),
6499 Ty: CurFD->getType(), VK: VK_LValue, OK: OK_Ordinary);
6500 SubExprs.push_back(Elt: BaseExpr);
6501 continue;
6502 }
6503 // Check for the "default" mapper for data members.
6504 bool FirstIter = true;
6505 for (FieldDecl *FD : RD->fields()) {
6506 if (!FD)
6507 continue;
6508 QualType FieldTy = FD->getType();
6509 if (FieldTy.isNull() ||
6510 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6511 continue;
6512 if (FirstIter) {
6513 FirstIter = false;
6514 ParentChain.emplace_back(Args&: CurFD, Args: 1);
6515 } else {
6516 ++ParentChain.back().second;
6517 }
6518 Types.emplace_back(Args&: FieldTy, Args&: FD);
6519 }
6520 }
6521 }
6522 if (SubExprs.empty())
6523 continue;
6524 CXXScopeSpec MapperIdScopeSpec;
6525 DeclarationNameInfo MapperId;
6526 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
6527 IteratorModifier: nullptr, MapTypeModifiers: C->getMapTypeModifiers(), MapTypeModifiersLoc: C->getMapTypeModifiersLoc(),
6528 MapperIdScopeSpec, MapperId, MapType: C->getMapType(),
6529 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(),
6530 VarList: SubExprs, Locs: OMPVarListLocTy()))
6531 Clauses.push_back(Elt: NewClause);
6532 }
6533}
6534
6535namespace {
6536/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
6537/// call in the associated loop-nest cannot be a 'parallel for'.
6538class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
6539 Sema &SemaRef;
6540
6541public:
6542 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
6543
6544 // Is there a nested OpenMP loop bind(parallel)
6545 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
6546 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6547 if (const auto *C = D->getSingleClause<OMPBindClause>())
6548 if (C->getBindKind() == OMPC_BIND_parallel) {
6549 TeamsLoopCanBeParallelFor = false;
6550 // No need to continue visiting any more
6551 return;
6552 }
6553 }
6554 for (const Stmt *Child : D->children())
6555 if (Child)
6556 Visit(S: Child);
6557 }
6558
6559 void VisitCallExpr(const CallExpr *C) {
6560 // Function calls inhibit parallel loop translation of 'target teams loop'
6561 // unless the assume-no-nested-parallelism flag has been specified.
6562 // OpenMP API runtime library calls do not inhibit parallel loop
6563 // translation, regardless of the assume-no-nested-parallelism.
6564 bool IsOpenMPAPI = false;
6565 auto *FD = dyn_cast_or_null<FunctionDecl>(Val: C->getCalleeDecl());
6566 if (FD) {
6567 std::string Name = FD->getNameInfo().getAsString();
6568 IsOpenMPAPI = Name.find(s: "omp_") == 0;
6569 }
6570 TeamsLoopCanBeParallelFor =
6571 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6572 if (!TeamsLoopCanBeParallelFor)
6573 return;
6574
6575 for (const Stmt *Child : C->children())
6576 if (Child)
6577 Visit(S: Child);
6578 }
6579
6580 void VisitCapturedStmt(const CapturedStmt *S) {
6581 if (!S)
6582 return;
6583 Visit(S: S->getCapturedDecl()->getBody());
6584 }
6585
6586 void VisitStmt(const Stmt *S) {
6587 if (!S)
6588 return;
6589 for (const Stmt *Child : S->children())
6590 if (Child)
6591 Visit(S: Child);
6592 }
6593 explicit TeamsLoopChecker(Sema &SemaRef)
6594 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
6595
6596private:
6597 bool TeamsLoopCanBeParallelFor;
6598};
6599} // namespace
6600
6601static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
6602 TeamsLoopChecker Checker(SemaRef);
6603 Checker.Visit(S: AStmt);
6604 return Checker.teamsLoopCanBeParallelFor();
6605}
6606
6607StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective(
6608 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6609 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6610 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6611 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
6612
6613 StmtResult Res = StmtError();
6614 OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
6615 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6616
6617 if (const OMPBindClause *BC =
6618 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6619 BindKind = BC->getBindKind();
6620
6621 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6622 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6623
6624 // Setting the enclosing teams or parallel construct for the loop
6625 // directive without bind clause.
6626 // [5.0:129:25-28] If the bind clause is not present on the construct and
6627 // the loop construct is closely nested inside a teams or parallel
6628 // construct, the binding region is the corresponding teams or parallel
6629 // region. If none of those conditions hold, the binding region is not
6630 // defined.
6631 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6632 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6633 getLeafConstructsOrSelf(D: ParentDirective);
6634
6635 if (ParentDirective == OMPD_unknown) {
6636 Diag(DSAStack->getDefaultDSALocation(),
6637 DiagID: diag::err_omp_bind_required_on_loop);
6638 } else if (ParentLeafs.back() == OMPD_parallel) {
6639 BindKind = OMPC_BIND_parallel;
6640 } else if (ParentLeafs.back() == OMPD_teams) {
6641 BindKind = OMPC_BIND_teams;
6642 }
6643
6644 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6645
6646 OMPClause *C =
6647 ActOnOpenMPBindClause(Kind: BindKind, KindLoc: SourceLocation(), StartLoc: SourceLocation(),
6648 LParenLoc: SourceLocation(), EndLoc: SourceLocation());
6649 ClausesWithImplicit.push_back(Elt: C);
6650 }
6651
6652 // Diagnose "loop bind(teams)" with "reduction".
6653 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6654 for (OMPClause *C : Clauses) {
6655 if (C->getClauseKind() == OMPC_reduction)
6656 Diag(DSAStack->getDefaultDSALocation(),
6657 DiagID: diag::err_omp_loop_reduction_clause);
6658 }
6659 }
6660
6661 // First check CancelRegion which is then used in checkNestingOfRegions.
6662 if (checkCancelRegion(SemaRef, CurrentRegion: Kind, CancelRegion, StartLoc) ||
6663 checkNestingOfRegions(SemaRef, DSAStack, CurrentRegion: Kind, CurrentName: DirName, CancelRegion,
6664 BindKind, StartLoc)) {
6665 return StmtError();
6666 }
6667
6668 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6669 if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(DKind: Kind) ||
6670 isOpenMPTargetDataManagementDirective(DKind: Kind)))
6671 Diag(Loc: StartLoc, DiagID: diag::warn_hip_omp_target_directives);
6672
6673 VarsWithInheritedDSAType VarsWithInheritedDSA;
6674 bool ErrorFound = false;
6675 ClausesWithImplicit.append(in_start: Clauses.begin(), in_end: Clauses.end());
6676
6677 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6678 isOpenMPCapturingDirective(DKind: Kind)) {
6679 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6680
6681 // Check default data sharing attributes for referenced variables.
6682 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(Val: AStmt));
6683 int ThisCaptureLevel = getOpenMPCaptureLevels(DKind: Kind);
6684 Stmt *S = AStmt;
6685 while (--ThisCaptureLevel >= 0)
6686 S = cast<CapturedStmt>(Val: S)->getCapturedStmt();
6687 DSAChecker.Visit(S);
6688 if (!isOpenMPTargetDataManagementDirective(DKind: Kind) &&
6689 !isOpenMPTaskingDirective(Kind)) {
6690 // Visit subcaptures to generate implicit clauses for captured vars.
6691 auto *CS = cast<CapturedStmt>(Val: AStmt);
6692 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
6693 getOpenMPCaptureRegions(CaptureRegions, DKind: Kind);
6694 // Ignore outer tasking regions for target directives.
6695 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6696 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
6697 DSAChecker.visitSubCaptures(S: CS);
6698 }
6699 if (DSAChecker.isErrorFound())
6700 return StmtError();
6701 // Generate list of implicitly defined firstprivate variables.
6702 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6703 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6704
6705 SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
6706 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6707 // Get the original location of present modifier from Defaultmap clause.
6708 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6709 for (OMPClause *C : Clauses) {
6710 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(Val: C))
6711 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6712 PresentModifierLocs[DMC->getDefaultmapKind()] =
6713 DMC->getDefaultmapModifierLoc();
6714 }
6715
6716 for (OpenMPDefaultmapClauseKind K :
6717 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6718 Begin: OpenMPDefaultmapClauseKind(), End: OMPC_DEFAULTMAP_unknown)) {
6719 std::fill_n(first: std::back_inserter(x&: ImplicitMapModifiersLoc[K]),
6720 n: ImpInfo.MapModifiers[K].size(), value: PresentModifierLocs[K]);
6721 }
6722 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6723 for (OMPClause *C : Clauses) {
6724 if (auto *IRC = dyn_cast<OMPInReductionClause>(Val: C)) {
6725 for (Expr *E : IRC->taskgroup_descriptors())
6726 if (E)
6727 ImpInfo.Firstprivates.insert(X: E);
6728 }
6729 // OpenMP 5.0, 2.10.1 task Construct
6730 // [detach clause]... The event-handle will be considered as if it was
6731 // specified on a firstprivate clause.
6732 if (auto *DC = dyn_cast<OMPDetachClause>(Val: C))
6733 ImpInfo.Firstprivates.insert(X: DC->getEventHandler());
6734 }
6735 if (!ImpInfo.Firstprivates.empty()) {
6736 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6737 VarList: ImpInfo.Firstprivates.getArrayRef(), StartLoc: SourceLocation(),
6738 LParenLoc: SourceLocation(), EndLoc: SourceLocation())) {
6739 ClausesWithImplicit.push_back(Elt: Implicit);
6740 ErrorFound = cast<OMPFirstprivateClause>(Val: Implicit)->varlist_size() !=
6741 ImpInfo.Firstprivates.size();
6742 } else {
6743 ErrorFound = true;
6744 }
6745 }
6746 if (!ImpInfo.Privates.empty()) {
6747 if (OMPClause *Implicit = ActOnOpenMPPrivateClause(
6748 VarList: ImpInfo.Privates.getArrayRef(), StartLoc: SourceLocation(),
6749 LParenLoc: SourceLocation(), EndLoc: SourceLocation())) {
6750 ClausesWithImplicit.push_back(Elt: Implicit);
6751 ErrorFound = cast<OMPPrivateClause>(Val: Implicit)->varlist_size() !=
6752 ImpInfo.Privates.size();
6753 } else {
6754 ErrorFound = true;
6755 }
6756 }
6757 // OpenMP 5.0 [2.19.7]
6758 // If a list item appears in a reduction, lastprivate or linear
6759 // clause on a combined target construct then it is treated as
6760 // if it also appears in a map clause with a map-type of tofrom
6761 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6762 isOpenMPTargetExecutionDirective(DKind: Kind)) {
6763 SmallVector<Expr *, 4> ImplicitExprs;
6764 for (OMPClause *C : Clauses) {
6765 if (auto *RC = dyn_cast<OMPReductionClause>(Val: C))
6766 for (Expr *E : RC->varlist())
6767 if (!isa<DeclRefExpr>(Val: E->IgnoreParenImpCasts()))
6768 ImplicitExprs.emplace_back(Args&: E);
6769 }
6770 if (!ImplicitExprs.empty()) {
6771 ArrayRef<Expr *> Exprs = ImplicitExprs;
6772 CXXScopeSpec MapperIdScopeSpec;
6773 DeclarationNameInfo MapperId;
6774 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6775 IteratorModifier: nullptr, MapTypeModifiers: OMPC_MAP_MODIFIER_unknown, MapTypeModifiersLoc: SourceLocation(),
6776 MapperIdScopeSpec, MapperId, MapType: OMPC_MAP_tofrom,
6777 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(),
6778 VarList: Exprs, Locs: OMPVarListLocTy(), /*NoDiagnose=*/true))
6779 ClausesWithImplicit.emplace_back(Args&: Implicit);
6780 }
6781 }
6782 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6783 int ClauseKindCnt = -1;
6784 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6785 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6786 ++ClauseKindCnt;
6787 if (ImplicitMap.empty())
6788 continue;
6789 CXXScopeSpec MapperIdScopeSpec;
6790 DeclarationNameInfo MapperId;
6791 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6792 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6793 IteratorModifier: nullptr, MapTypeModifiers: ImpInfo.MapModifiers[I], MapTypeModifiersLoc: ImplicitMapModifiersLoc[I],
6794 MapperIdScopeSpec, MapperId, MapType: K, /*IsMapTypeImplicit=*/true,
6795 MapLoc: SourceLocation(), ColonLoc: SourceLocation(), VarList: ImplicitMap,
6796 Locs: OMPVarListLocTy())) {
6797 ClausesWithImplicit.emplace_back(Args&: Implicit);
6798 ErrorFound |= cast<OMPMapClause>(Val: Implicit)->varlist_size() !=
6799 ImplicitMap.size();
6800 } else {
6801 ErrorFound = true;
6802 }
6803 }
6804 }
6805 // Build expressions for implicit maps of data members with 'default'
6806 // mappers.
6807 if (getLangOpts().OpenMP >= 50)
6808 processImplicitMapsWithDefaultMappers(S&: SemaRef, DSAStack,
6809 Clauses&: ClausesWithImplicit);
6810 }
6811
6812 switch (Kind) {
6813 case OMPD_parallel:
6814 Res = ActOnOpenMPParallelDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6815 EndLoc);
6816 break;
6817 case OMPD_simd:
6818 Res = ActOnOpenMPSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6819 VarsWithImplicitDSA&: VarsWithInheritedDSA);
6820 break;
6821 case OMPD_tile:
6822 Res =
6823 ActOnOpenMPTileDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6824 break;
6825 case OMPD_stripe:
6826 Res = ActOnOpenMPStripeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6827 EndLoc);
6828 break;
6829 case OMPD_unroll:
6830 Res = ActOnOpenMPUnrollDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6831 EndLoc);
6832 break;
6833 case OMPD_reverse:
6834 assert(ClausesWithImplicit.empty() &&
6835 "reverse directive does not support any clauses");
6836 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6837 break;
6838 case OMPD_split:
6839 Res =
6840 ActOnOpenMPSplitDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6841 break;
6842 case OMPD_interchange:
6843 Res = ActOnOpenMPInterchangeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6844 EndLoc);
6845 break;
6846 case OMPD_flatten:
6847 Res = ActOnOpenMPFlattenDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6848 EndLoc);
6849 break;
6850 case OMPD_fuse:
6851 Res =
6852 ActOnOpenMPFuseDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6853 break;
6854 case OMPD_for:
6855 Res = ActOnOpenMPForDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6856 VarsWithImplicitDSA&: VarsWithInheritedDSA);
6857 break;
6858 case OMPD_for_simd:
6859 Res = ActOnOpenMPForSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6860 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6861 break;
6862 case OMPD_sections:
6863 Res = ActOnOpenMPSectionsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6864 EndLoc);
6865 break;
6866 case OMPD_section:
6867 assert(ClausesWithImplicit.empty() &&
6868 "No clauses are allowed for 'omp section' directive");
6869 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6870 break;
6871 case OMPD_single:
6872 Res = ActOnOpenMPSingleDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6873 EndLoc);
6874 break;
6875 case OMPD_master:
6876 assert(ClausesWithImplicit.empty() &&
6877 "No clauses are allowed for 'omp master' directive");
6878 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6879 break;
6880 case OMPD_masked:
6881 Res = ActOnOpenMPMaskedDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6882 EndLoc);
6883 break;
6884 case OMPD_critical:
6885 Res = ActOnOpenMPCriticalDirective(DirName, Clauses: ClausesWithImplicit, AStmt,
6886 StartLoc, EndLoc);
6887 break;
6888 case OMPD_parallel_for:
6889 Res = ActOnOpenMPParallelForDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6890 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6891 break;
6892 case OMPD_parallel_for_simd:
6893 Res = ActOnOpenMPParallelForSimdDirective(
6894 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6895 break;
6896 case OMPD_scope:
6897 Res =
6898 ActOnOpenMPScopeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6899 break;
6900 case OMPD_parallel_master:
6901 Res = ActOnOpenMPParallelMasterDirective(Clauses: ClausesWithImplicit, AStmt,
6902 StartLoc, EndLoc);
6903 break;
6904 case OMPD_parallel_masked:
6905 Res = ActOnOpenMPParallelMaskedDirective(Clauses: ClausesWithImplicit, AStmt,
6906 StartLoc, EndLoc);
6907 break;
6908 case OMPD_parallel_sections:
6909 Res = ActOnOpenMPParallelSectionsDirective(Clauses: ClausesWithImplicit, AStmt,
6910 StartLoc, EndLoc);
6911 break;
6912 case OMPD_task:
6913 Res =
6914 ActOnOpenMPTaskDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6915 break;
6916 case OMPD_taskyield:
6917 assert(ClausesWithImplicit.empty() &&
6918 "No clauses are allowed for 'omp taskyield' directive");
6919 assert(AStmt == nullptr &&
6920 "No associated statement allowed for 'omp taskyield' directive");
6921 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6922 break;
6923 case OMPD_error:
6924 assert(AStmt == nullptr &&
6925 "No associated statement allowed for 'omp error' directive");
6926 Res = ActOnOpenMPErrorDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6927 break;
6928 case OMPD_barrier:
6929 assert(ClausesWithImplicit.empty() &&
6930 "No clauses are allowed for 'omp barrier' directive");
6931 assert(AStmt == nullptr &&
6932 "No associated statement allowed for 'omp barrier' directive");
6933 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6934 break;
6935 case OMPD_taskwait:
6936 assert(AStmt == nullptr &&
6937 "No associated statement allowed for 'omp taskwait' directive");
6938 Res = ActOnOpenMPTaskwaitDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6939 break;
6940 case OMPD_taskgroup:
6941 Res = ActOnOpenMPTaskgroupDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6942 EndLoc);
6943 break;
6944 case OMPD_flush:
6945 assert(AStmt == nullptr &&
6946 "No associated statement allowed for 'omp flush' directive");
6947 Res = ActOnOpenMPFlushDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6948 break;
6949 case OMPD_depobj:
6950 assert(AStmt == nullptr &&
6951 "No associated statement allowed for 'omp depobj' directive");
6952 Res = ActOnOpenMPDepobjDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6953 break;
6954 case OMPD_scan:
6955 assert(AStmt == nullptr &&
6956 "No associated statement allowed for 'omp scan' directive");
6957 Res = ActOnOpenMPScanDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6958 break;
6959 case OMPD_ordered_blockassoc:
6960 case OMPD_ordered_standalone:
6961 Res = ActOnOpenMPOrderedDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6962 EndLoc);
6963 break;
6964 case OMPD_atomic:
6965 Res = ActOnOpenMPAtomicDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6966 EndLoc);
6967 break;
6968 case OMPD_teams:
6969 Res =
6970 ActOnOpenMPTeamsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6971 break;
6972 case OMPD_target:
6973 Res = ActOnOpenMPTargetDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6974 EndLoc);
6975 break;
6976 case OMPD_target_parallel:
6977 Res = ActOnOpenMPTargetParallelDirective(Clauses: ClausesWithImplicit, AStmt,
6978 StartLoc, EndLoc);
6979 break;
6980 case OMPD_target_parallel_for:
6981 Res = ActOnOpenMPTargetParallelForDirective(
6982 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6983 break;
6984 case OMPD_cancellation_point:
6985 assert(ClausesWithImplicit.empty() &&
6986 "No clauses are allowed for 'omp cancellation point' directive");
6987 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6988 "cancellation point' directive");
6989 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6990 break;
6991 case OMPD_cancel:
6992 assert(AStmt == nullptr &&
6993 "No associated statement allowed for 'omp cancel' directive");
6994 Res = ActOnOpenMPCancelDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc,
6995 CancelRegion);
6996 break;
6997 case OMPD_target_data:
6998 Res = ActOnOpenMPTargetDataDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6999 EndLoc);
7000 break;
7001 case OMPD_target_enter_data:
7002 Res = ActOnOpenMPTargetEnterDataDirective(Clauses: ClausesWithImplicit, StartLoc,
7003 EndLoc, AStmt);
7004 break;
7005 case OMPD_target_exit_data:
7006 Res = ActOnOpenMPTargetExitDataDirective(Clauses: ClausesWithImplicit, StartLoc,
7007 EndLoc, AStmt);
7008 break;
7009 case OMPD_taskloop:
7010 Res = ActOnOpenMPTaskLoopDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
7011 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7012 break;
7013 case OMPD_taskloop_simd:
7014 Res = ActOnOpenMPTaskLoopSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
7015 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7016 break;
7017 case OMPD_master_taskloop:
7018 Res = ActOnOpenMPMasterTaskLoopDirective(
7019 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7020 break;
7021 case OMPD_masked_taskloop:
7022 Res = ActOnOpenMPMaskedTaskLoopDirective(
7023 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7024 break;
7025 case OMPD_master_taskloop_simd:
7026 Res = ActOnOpenMPMasterTaskLoopSimdDirective(
7027 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7028 break;
7029 case OMPD_masked_taskloop_simd:
7030 Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
7031 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7032 break;
7033 case OMPD_parallel_master_taskloop:
7034 Res = ActOnOpenMPParallelMasterTaskLoopDirective(
7035 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7036 break;
7037 case OMPD_parallel_masked_taskloop:
7038 Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
7039 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7040 break;
7041 case OMPD_parallel_master_taskloop_simd:
7042 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
7043 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7044 break;
7045 case OMPD_parallel_masked_taskloop_simd:
7046 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
7047 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7048 break;
7049 case OMPD_distribute:
7050 Res = ActOnOpenMPDistributeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
7051 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7052 break;
7053 case OMPD_target_update:
7054 Res = ActOnOpenMPTargetUpdateDirective(Clauses: ClausesWithImplicit, StartLoc,
7055 EndLoc, AStmt);
7056 break;
7057 case OMPD_distribute_parallel_for:
7058 Res = ActOnOpenMPDistributeParallelForDirective(
7059 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7060 break;
7061 case OMPD_distribute_parallel_for_simd:
7062 Res = ActOnOpenMPDistributeParallelForSimdDirective(
7063 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7064 break;
7065 case OMPD_distribute_simd:
7066 Res = ActOnOpenMPDistributeSimdDirective(
7067 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7068 break;
7069 case OMPD_target_parallel_for_simd:
7070 Res = ActOnOpenMPTargetParallelForSimdDirective(
7071 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7072 break;
7073 case OMPD_target_simd:
7074 Res = ActOnOpenMPTargetSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
7075 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7076 break;
7077 case OMPD_teams_distribute:
7078 Res = ActOnOpenMPTeamsDistributeDirective(
7079 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7080 break;
7081 case OMPD_teams_distribute_simd:
7082 Res = ActOnOpenMPTeamsDistributeSimdDirective(
7083 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7084 break;
7085 case OMPD_teams_distribute_parallel_for_simd:
7086 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
7087 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7088 break;
7089 case OMPD_teams_distribute_parallel_for:
7090 Res = ActOnOpenMPTeamsDistributeParallelForDirective(
7091 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7092 break;
7093 case OMPD_target_teams:
7094 Res = ActOnOpenMPTargetTeamsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
7095 EndLoc);
7096 break;
7097 case OMPD_target_teams_distribute:
7098 Res = ActOnOpenMPTargetTeamsDistributeDirective(
7099 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7100 break;
7101 case OMPD_target_teams_distribute_parallel_for:
7102 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
7103 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7104 break;
7105 case OMPD_target_teams_distribute_parallel_for_simd:
7106 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
7107 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7108 break;
7109 case OMPD_target_teams_distribute_simd:
7110 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
7111 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7112 break;
7113 case OMPD_interop:
7114 assert(AStmt == nullptr &&
7115 "No associated statement allowed for 'omp interop' directive");
7116 Res = ActOnOpenMPInteropDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
7117 break;
7118 case OMPD_dispatch:
7119 Res = ActOnOpenMPDispatchDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
7120 EndLoc);
7121 break;
7122 case OMPD_loop:
7123 Res = ActOnOpenMPGenericLoopDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
7124 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7125 break;
7126 case OMPD_teams_loop:
7127 Res = ActOnOpenMPTeamsGenericLoopDirective(
7128 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7129 break;
7130 case OMPD_target_teams_loop:
7131 Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
7132 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7133 break;
7134 case OMPD_parallel_loop:
7135 Res = ActOnOpenMPParallelGenericLoopDirective(
7136 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7137 break;
7138 case OMPD_target_parallel_loop:
7139 Res = ActOnOpenMPTargetParallelGenericLoopDirective(
7140 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
7141 break;
7142 case OMPD_declare_target:
7143 case OMPD_end_declare_target:
7144 case OMPD_threadprivate:
7145 case OMPD_allocate:
7146 case OMPD_declare_reduction:
7147 case OMPD_declare_mapper:
7148 case OMPD_declare_simd:
7149 case OMPD_requires:
7150 case OMPD_declare_variant:
7151 case OMPD_begin_declare_variant:
7152 case OMPD_end_declare_variant:
7153 llvm_unreachable("OpenMP Directive is not allowed");
7154 case OMPD_taskgraph:
7155 Diag(Loc: StartLoc, DiagID: diag::err_omp_unexpected_directive)
7156 << 1 << getOpenMPDirectiveName(D: OMPD_taskgraph);
7157 return StmtError();
7158 case OMPD_unknown:
7159 default:
7160 llvm_unreachable("Unknown OpenMP directive");
7161 }
7162
7163 ErrorFound = Res.isInvalid() || ErrorFound;
7164
7165 // Check variables in the clauses if default(none) or
7166 // default(firstprivate) was specified.
7167 if (DSAStack->getDefaultDSA() == DSA_none ||
7168 DSAStack->getDefaultDSA() == DSA_private ||
7169 DSAStack->getDefaultDSA() == DSA_firstprivate) {
7170 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
7171 for (OMPClause *C : Clauses) {
7172 switch (C->getClauseKind()) {
7173 case OMPC_num_threads:
7174 case OMPC_dist_schedule:
7175 // Do not analyze if no parent teams directive.
7176 if (isOpenMPTeamsDirective(DKind: Kind))
7177 break;
7178 continue;
7179 case OMPC_if:
7180 if (isOpenMPTeamsDirective(DKind: Kind) &&
7181 cast<OMPIfClause>(Val: C)->getNameModifier() != OMPD_target)
7182 break;
7183 if (isOpenMPParallelDirective(DKind: Kind) &&
7184 isOpenMPTaskLoopDirective(DKind: Kind) &&
7185 cast<OMPIfClause>(Val: C)->getNameModifier() != OMPD_parallel)
7186 break;
7187 continue;
7188 case OMPC_schedule:
7189 case OMPC_detach:
7190 break;
7191 case OMPC_grainsize:
7192 case OMPC_num_tasks:
7193 case OMPC_final:
7194 case OMPC_priority:
7195 case OMPC_novariants:
7196 case OMPC_nocontext:
7197 // Do not analyze if no parent parallel directive.
7198 if (isOpenMPParallelDirective(DKind: Kind))
7199 break;
7200 continue;
7201 case OMPC_ordered:
7202 case OMPC_device:
7203 case OMPC_num_teams:
7204 case OMPC_thread_limit:
7205 case OMPC_hint:
7206 case OMPC_collapse:
7207 case OMPC_safelen:
7208 case OMPC_simdlen:
7209 case OMPC_sizes:
7210 case OMPC_depth:
7211 case OMPC_default:
7212 case OMPC_proc_bind:
7213 case OMPC_private:
7214 case OMPC_firstprivate:
7215 case OMPC_lastprivate:
7216 case OMPC_shared:
7217 case OMPC_reduction:
7218 case OMPC_task_reduction:
7219 case OMPC_in_reduction:
7220 case OMPC_linear:
7221 case OMPC_aligned:
7222 case OMPC_copyin:
7223 case OMPC_copyprivate:
7224 case OMPC_nowait:
7225 case OMPC_untied:
7226 case OMPC_mergeable:
7227 case OMPC_allocate:
7228 case OMPC_read:
7229 case OMPC_write:
7230 case OMPC_update:
7231 case OMPC_capture:
7232 case OMPC_compare:
7233 case OMPC_seq_cst:
7234 case OMPC_acq_rel:
7235 case OMPC_acquire:
7236 case OMPC_release:
7237 case OMPC_relaxed:
7238 case OMPC_depend:
7239 case OMPC_threads:
7240 case OMPC_simd:
7241 case OMPC_map:
7242 case OMPC_nogroup:
7243 case OMPC_defaultmap:
7244 case OMPC_to:
7245 case OMPC_from:
7246 case OMPC_use_device_ptr:
7247 case OMPC_use_device_addr:
7248 case OMPC_is_device_ptr:
7249 case OMPC_has_device_addr:
7250 case OMPC_nontemporal:
7251 case OMPC_order:
7252 case OMPC_destroy:
7253 case OMPC_inclusive:
7254 case OMPC_exclusive:
7255 case OMPC_uses_allocators:
7256 case OMPC_affinity:
7257 case OMPC_bind:
7258 case OMPC_filter:
7259 case OMPC_severity:
7260 case OMPC_message:
7261 continue;
7262 case OMPC_allocator:
7263 case OMPC_flush:
7264 case OMPC_depobj:
7265 case OMPC_threadprivate:
7266 case OMPC_groupprivate:
7267 case OMPC_uniform:
7268 case OMPC_unknown:
7269 case OMPC_unified_address:
7270 case OMPC_unified_shared_memory:
7271 case OMPC_reverse_offload:
7272 case OMPC_dynamic_allocators:
7273 case OMPC_atomic_default_mem_order:
7274 case OMPC_self_maps:
7275 case OMPC_device_type:
7276 case OMPC_match:
7277 case OMPC_when:
7278 case OMPC_at:
7279 default:
7280 llvm_unreachable("Unexpected clause");
7281 }
7282 for (Stmt *CC : C->children()) {
7283 if (CC)
7284 DSAChecker.Visit(S: CC);
7285 }
7286 }
7287 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
7288 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
7289 }
7290 for (const auto &P : VarsWithInheritedDSA) {
7291 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(Val: P.getFirst()))
7292 continue;
7293 ErrorFound = true;
7294 if (DSAStack->getDefaultDSA() == DSA_none ||
7295 DSAStack->getDefaultDSA() == DSA_private ||
7296 DSAStack->getDefaultDSA() == DSA_firstprivate) {
7297 Diag(Loc: P.second->getExprLoc(), DiagID: diag::err_omp_no_dsa_for_variable)
7298 << P.first << P.second->getSourceRange();
7299 Diag(DSAStack->getDefaultDSALocation(), DiagID: diag::note_omp_default_dsa_none);
7300 } else if (getLangOpts().OpenMP >= 50) {
7301 Diag(Loc: P.second->getExprLoc(),
7302 DiagID: diag::err_omp_defaultmap_no_attr_for_variable)
7303 << P.first << P.second->getSourceRange();
7304 Diag(DSAStack->getDefaultDSALocation(),
7305 DiagID: diag::note_omp_defaultmap_attr_none);
7306 }
7307 }
7308
7309 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
7310 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(D: Kind)) {
7311 if (isAllowedClauseForDirective(D, C: OMPC_if,
7312 V: getLangOpts().getOpenMPVersion()))
7313 AllowedNameModifiers.push_back(Elt: D);
7314 }
7315 if (!AllowedNameModifiers.empty())
7316 ErrorFound = checkIfClauses(S&: SemaRef, Kind, Clauses, AllowedNameModifiers) ||
7317 ErrorFound;
7318
7319 if (ErrorFound)
7320 return StmtError();
7321
7322 if (!SemaRef.CurContext->isDependentContext() &&
7323 isOpenMPTargetExecutionDirective(DKind: Kind) &&
7324 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
7325 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
7326 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
7327 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
7328 // Register target to DSA Stack.
7329 DSAStack->addTargetDirLocation(LocStart: StartLoc);
7330 }
7331
7332 return Res;
7333}
7334
7335SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareSimdDirective(
7336 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
7337 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
7338 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
7339 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
7340 assert(Aligneds.size() == Alignments.size());
7341 assert(Linears.size() == LinModifiers.size());
7342 assert(Linears.size() == Steps.size());
7343 if (!DG || DG.get().isNull())
7344 return DeclGroupPtrTy();
7345
7346 const int SimdId = 0;
7347 if (!DG.get().isSingleDecl()) {
7348 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_single_decl_in_declare_simd_variant)
7349 << SimdId;
7350 return DG;
7351 }
7352 Decl *ADecl = DG.get().getSingleDecl();
7353 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: ADecl))
7354 ADecl = FTD->getTemplatedDecl();
7355
7356 auto *FD = dyn_cast<FunctionDecl>(Val: ADecl);
7357 if (!FD) {
7358 Diag(Loc: ADecl->getLocation(), DiagID: diag::err_omp_function_expected) << SimdId;
7359 return DeclGroupPtrTy();
7360 }
7361
7362 // OpenMP [2.8.2, declare simd construct, Description]
7363 // The parameter of the simdlen clause must be a constant positive integer
7364 // expression.
7365 ExprResult SL;
7366 if (Simdlen)
7367 SL = VerifyPositiveIntegerConstantInClause(Op: Simdlen, CKind: OMPC_simdlen);
7368 // OpenMP [2.8.2, declare simd construct, Description]
7369 // The special this pointer can be used as if was one of the arguments to the
7370 // function in any of the linear, aligned, or uniform clauses.
7371 // The uniform clause declares one or more arguments to have an invariant
7372 // value for all concurrent invocations of the function in the execution of a
7373 // single SIMD loop.
7374 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
7375 const Expr *UniformedLinearThis = nullptr;
7376 for (const Expr *E : Uniforms) {
7377 E = E->IgnoreParenImpCasts();
7378 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7379 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl()))
7380 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7381 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7382 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
7383 UniformedArgs.try_emplace(Key: PVD->getCanonicalDecl(), Args&: E);
7384 continue;
7385 }
7386 if (isa<CXXThisExpr>(Val: E)) {
7387 UniformedLinearThis = E;
7388 continue;
7389 }
7390 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
7391 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
7392 }
7393 // OpenMP [2.8.2, declare simd construct, Description]
7394 // The aligned clause declares that the object to which each list item points
7395 // is aligned to the number of bytes expressed in the optional parameter of
7396 // the aligned clause.
7397 // The special this pointer can be used as if was one of the arguments to the
7398 // function in any of the linear, aligned, or uniform clauses.
7399 // The type of list items appearing in the aligned clause must be array,
7400 // pointer, reference to array, or reference to pointer.
7401 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
7402 const Expr *AlignedThis = nullptr;
7403 for (const Expr *E : Aligneds) {
7404 E = E->IgnoreParenImpCasts();
7405 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7406 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7407 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7408 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7409 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7410 ->getCanonicalDecl() == CanonPVD) {
7411 // OpenMP [2.8.1, simd construct, Restrictions]
7412 // A list-item cannot appear in more than one aligned clause.
7413 auto [It, Inserted] = AlignedArgs.try_emplace(Key: CanonPVD, Args&: E);
7414 if (!Inserted) {
7415 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_used_in_clause_twice)
7416 << 1 << getOpenMPClauseNameForDiag(C: OMPC_aligned)
7417 << E->getSourceRange();
7418 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7419 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
7420 continue;
7421 }
7422 QualType QTy = PVD->getType()
7423 .getNonReferenceType()
7424 .getUnqualifiedType()
7425 .getCanonicalType();
7426 const Type *Ty = QTy.getTypePtrOrNull();
7427 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
7428 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_aligned_expected_array_or_ptr)
7429 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
7430 Diag(Loc: PVD->getLocation(), DiagID: diag::note_previous_decl) << PVD;
7431 }
7432 continue;
7433 }
7434 }
7435 if (isa<CXXThisExpr>(Val: E)) {
7436 if (AlignedThis) {
7437 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_used_in_clause_twice)
7438 << 2 << getOpenMPClauseNameForDiag(C: OMPC_aligned)
7439 << E->getSourceRange();
7440 Diag(Loc: AlignedThis->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7441 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
7442 }
7443 AlignedThis = E;
7444 continue;
7445 }
7446 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
7447 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
7448 }
7449 // The optional parameter of the aligned clause, alignment, must be a constant
7450 // positive integer expression. If no optional parameter is specified,
7451 // implementation-defined default alignments for SIMD instructions on the
7452 // target platforms are assumed.
7453 SmallVector<const Expr *, 4> NewAligns;
7454 for (Expr *E : Alignments) {
7455 ExprResult Align;
7456 if (E)
7457 Align = VerifyPositiveIntegerConstantInClause(Op: E, CKind: OMPC_aligned);
7458 NewAligns.push_back(Elt: Align.get());
7459 }
7460 // OpenMP [2.8.2, declare simd construct, Description]
7461 // The linear clause declares one or more list items to be private to a SIMD
7462 // lane and to have a linear relationship with respect to the iteration space
7463 // of a loop.
7464 // The special this pointer can be used as if was one of the arguments to the
7465 // function in any of the linear, aligned, or uniform clauses.
7466 // When a linear-step expression is specified in a linear clause it must be
7467 // either a constant integer expression or an integer-typed parameter that is
7468 // specified in a uniform clause on the directive.
7469 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7470 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7471 auto MI = LinModifiers.begin();
7472 for (const Expr *E : Linears) {
7473 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7474 ++MI;
7475 E = E->IgnoreParenImpCasts();
7476 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7477 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7478 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7479 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7480 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7481 ->getCanonicalDecl() == CanonPVD) {
7482 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7483 // A list-item cannot appear in more than one linear clause.
7484 if (auto It = LinearArgs.find(Val: CanonPVD); It != LinearArgs.end()) {
7485 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
7486 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7487 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7488 << E->getSourceRange();
7489 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7490 << getOpenMPClauseNameForDiag(C: OMPC_linear);
7491 continue;
7492 }
7493 // Each argument can appear in at most one uniform or linear clause.
7494 if (auto It = UniformedArgs.find(Val: CanonPVD);
7495 It != UniformedArgs.end()) {
7496 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
7497 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7498 << getOpenMPClauseNameForDiag(C: OMPC_uniform)
7499 << E->getSourceRange();
7500 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7501 << getOpenMPClauseNameForDiag(C: OMPC_uniform);
7502 continue;
7503 }
7504 LinearArgs[CanonPVD] = E;
7505 if (E->isValueDependent() || E->isTypeDependent() ||
7506 E->isInstantiationDependent() ||
7507 E->containsUnexpandedParameterPack())
7508 continue;
7509 (void)CheckOpenMPLinearDecl(D: CanonPVD, ELoc: E->getExprLoc(), LinKind,
7510 Type: PVD->getOriginalType(),
7511 /*IsDeclareSimd=*/true);
7512 continue;
7513 }
7514 }
7515 if (isa<CXXThisExpr>(Val: E)) {
7516 if (UniformedLinearThis) {
7517 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
7518 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7519 << getOpenMPClauseNameForDiag(C: IsUniformedThis ? OMPC_uniform
7520 : OMPC_linear)
7521 << E->getSourceRange();
7522 Diag(Loc: UniformedLinearThis->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7523 << getOpenMPClauseNameForDiag(C: IsUniformedThis ? OMPC_uniform
7524 : OMPC_linear);
7525 continue;
7526 }
7527 UniformedLinearThis = E;
7528 if (E->isValueDependent() || E->isTypeDependent() ||
7529 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
7530 continue;
7531 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, ELoc: E->getExprLoc(), LinKind,
7532 Type: E->getType(), /*IsDeclareSimd=*/true);
7533 continue;
7534 }
7535 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
7536 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
7537 }
7538 Expr *Step = nullptr;
7539 Expr *NewStep = nullptr;
7540 SmallVector<Expr *, 4> NewSteps;
7541 for (Expr *E : Steps) {
7542 // Skip the same step expression, it was checked already.
7543 if (Step == E || !E) {
7544 NewSteps.push_back(Elt: E ? NewStep : nullptr);
7545 continue;
7546 }
7547 Step = E;
7548 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: Step))
7549 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7550 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7551 if (UniformedArgs.count(Val: CanonPVD) == 0) {
7552 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_expected_uniform_param)
7553 << Step->getSourceRange();
7554 } else if (E->isValueDependent() || E->isTypeDependent() ||
7555 E->isInstantiationDependent() ||
7556 E->containsUnexpandedParameterPack() ||
7557 CanonPVD->getType()->hasIntegerRepresentation()) {
7558 NewSteps.push_back(Elt: Step);
7559 } else {
7560 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_expected_int_param)
7561 << Step->getSourceRange();
7562 }
7563 continue;
7564 }
7565 NewStep = Step;
7566 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7567 !Step->isInstantiationDependent() &&
7568 !Step->containsUnexpandedParameterPack()) {
7569 NewStep = PerformOpenMPImplicitIntegerConversion(OpLoc: Step->getExprLoc(), Op: Step)
7570 .get();
7571 if (NewStep)
7572 NewStep = SemaRef
7573 .VerifyIntegerConstantExpression(
7574 E: NewStep, /*FIXME*/ CanFold: AllowFoldKind::Allow)
7575 .get();
7576 }
7577 NewSteps.push_back(Elt: NewStep);
7578 }
7579 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7580 Ctx&: getASTContext(), BranchState: BS, Simdlen: SL.get(), Uniforms: const_cast<Expr **>(Uniforms.data()),
7581 UniformsSize: Uniforms.size(), Aligneds: const_cast<Expr **>(Aligneds.data()), AlignedsSize: Aligneds.size(),
7582 Alignments: const_cast<Expr **>(NewAligns.data()), AlignmentsSize: NewAligns.size(),
7583 Linears: const_cast<Expr **>(Linears.data()), LinearsSize: Linears.size(),
7584 Modifiers: const_cast<unsigned *>(LinModifiers.data()), ModifiersSize: LinModifiers.size(),
7585 Steps: NewSteps.data(), StepsSize: NewSteps.size(), Range: SR);
7586 ADecl->addAttr(A: NewAttr);
7587 return DG;
7588}
7589
7590StmtResult SemaOpenMP::ActOnOpenMPInformationalDirective(
7591 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
7592 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
7593 SourceLocation EndLoc) {
7594 assert(isOpenMPInformationalDirective(Kind) &&
7595 "Unexpected directive category");
7596
7597 StmtResult Res = StmtError();
7598
7599 switch (Kind) {
7600 case OMPD_assume:
7601 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
7602 break;
7603 default:
7604 llvm_unreachable("Unknown OpenMP directive");
7605 }
7606
7607 return Res;
7608}
7609
7610static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7611 QualType NewType) {
7612 assert(NewType->isFunctionProtoType() &&
7613 "Expected function type with prototype.");
7614 assert(FD->getType()->isFunctionNoProtoType() &&
7615 "Expected function with type with no prototype.");
7616 assert(FDWithProto->getType()->isFunctionProtoType() &&
7617 "Expected function with prototype.");
7618 // Synthesize parameters with the same types.
7619 FD->setType(NewType);
7620 SmallVector<ParmVarDecl *, 16> Params;
7621 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7622 auto *Param = ParmVarDecl::Create(C&: S.getASTContext(), DC: FD, StartLoc: SourceLocation(),
7623 IdLoc: SourceLocation(), Id: nullptr, T: P->getType(),
7624 /*TInfo=*/nullptr, S: SC_None, DefArg: nullptr);
7625 Param->setScopeInfo(scopeDepth: 0, parameterIndex: Params.size());
7626 Param->setImplicit();
7627 Params.push_back(Elt: Param);
7628 }
7629
7630 FD->setParams(Params);
7631}
7632
7633void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
7634 if (D->isInvalidDecl())
7635 return;
7636 FunctionDecl *FD = nullptr;
7637 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(Val: D))
7638 FD = UTemplDecl->getTemplatedDecl();
7639 else
7640 FD = cast<FunctionDecl>(Val: D);
7641 assert(FD && "Expected a function declaration!");
7642
7643 // If we are instantiating templates we do *not* apply scoped assumptions but
7644 // only global ones. We apply scoped assumption to the template definition
7645 // though.
7646 if (!SemaRef.inTemplateInstantiation()) {
7647 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7648 FD->addAttr(A: AA);
7649 }
7650 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7651 FD->addAttr(A: AA);
7652}
7653
7654SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7655 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7656
7657void SemaOpenMP::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7658 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7659 SmallVectorImpl<FunctionDecl *> &Bases) {
7660 if (!D.getIdentifier())
7661 return;
7662
7663 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7664
7665 // Template specialization is an extension, check if we do it.
7666 bool IsTemplated = !TemplateParamLists.empty();
7667 if (IsTemplated &&
7668 !DVScope.TI->isExtensionActive(
7669 TP: llvm::omp::TraitProperty::implementation_extension_allow_templates))
7670 return;
7671
7672 const IdentifierInfo *BaseII = D.getIdentifier();
7673 LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(),
7674 Sema::LookupOrdinaryName);
7675 SemaRef.LookupParsedName(R&: Lookup, S, SS: &D.getCXXScopeSpec(),
7676 /*ObjectType=*/QualType());
7677
7678 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7679 QualType FType = TInfo->getType();
7680
7681 bool IsConstexpr =
7682 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7683 bool IsConsteval =
7684 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7685
7686 for (auto *Candidate : Lookup) {
7687 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7688 FunctionDecl *UDecl = nullptr;
7689 if (IsTemplated && isa<FunctionTemplateDecl>(Val: CandidateDecl)) {
7690 auto *FTD = cast<FunctionTemplateDecl>(Val: CandidateDecl);
7691 // FIXME: Should this compare the template parameter lists on all levels?
7692 if (SemaRef.Context.isSameTemplateParameterList(
7693 X: FTD->getTemplateParameters(), Y: TemplateParamLists.back()))
7694 UDecl = FTD->getTemplatedDecl();
7695 } else if (!IsTemplated)
7696 UDecl = dyn_cast<FunctionDecl>(Val: CandidateDecl);
7697 if (!UDecl)
7698 continue;
7699
7700 // Don't specialize constexpr/consteval functions with
7701 // non-constexpr/consteval functions.
7702 if (UDecl->isConstexpr() && !IsConstexpr)
7703 continue;
7704 if (UDecl->isConsteval() && !IsConsteval)
7705 continue;
7706
7707 QualType UDeclTy = UDecl->getType();
7708 if (!UDeclTy->isDependentType()) {
7709 QualType NewType = getASTContext().mergeFunctionTypes(
7710 FType, UDeclTy, /*OfBlockPointer=*/false,
7711 /*Unqualified=*/false, /*AllowCXX=*/true);
7712 if (NewType.isNull())
7713 continue;
7714 }
7715
7716 // Found a base!
7717 Bases.push_back(Elt: UDecl);
7718 }
7719
7720 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7721 TP: llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7722 // If no base was found we create a declaration that we use as base.
7723 if (Bases.empty() && UseImplicitBase) {
7724 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7725 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParameterLists: TemplateParamLists);
7726 BaseD->setImplicit(true);
7727 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(Val: BaseD))
7728 Bases.push_back(Elt: BaseTemplD->getTemplatedDecl());
7729 else
7730 Bases.push_back(Elt: cast<FunctionDecl>(Val: BaseD));
7731 }
7732
7733 std::string MangledName;
7734 MangledName += D.getIdentifier()->getName();
7735 MangledName += getOpenMPVariantManglingSeparatorStr();
7736 MangledName += DVScope.NameSuffix;
7737 IdentifierInfo &VariantII = getASTContext().Idents.get(Name: MangledName);
7738
7739 VariantII.setMangledOpenMPVariantName(true);
7740 D.SetIdentifier(Id: &VariantII, IdLoc: D.getBeginLoc());
7741}
7742
7743void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7744 Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
7745 // Do not mark function as is used to prevent its emission if this is the
7746 // only place where it is used.
7747 EnterExpressionEvaluationContext Unevaluated(
7748 SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);
7749
7750 FunctionDecl *FD = nullptr;
7751 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(Val: D))
7752 FD = UTemplDecl->getTemplatedDecl();
7753 else
7754 FD = cast<FunctionDecl>(Val: D);
7755 auto *VariantFuncRef = DeclRefExpr::Create(
7756 Context: getASTContext(), QualifierLoc: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), D: FD,
7757 /*RefersToEnclosingVariableOrCapture=*/false,
7758 /*NameLoc=*/FD->getLocation(), T: FD->getType(), VK: ExprValueKind::VK_PRValue);
7759
7760 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7761 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7762 Ctx&: getASTContext(), VariantFuncRef, TraitInfos: DVScope.TI,
7763 /*NothingArgs=*/AdjustArgsNothing: nullptr, /*NothingArgsSize=*/AdjustArgsNothingSize: 0,
7764 /*NeedDevicePtrArgs=*/AdjustArgsNeedDevicePtr: nullptr, /*NeedDevicePtrArgsSize=*/AdjustArgsNeedDevicePtrSize: 0,
7765 /*NeedDeviceAddrArgs=*/AdjustArgsNeedDeviceAddr: nullptr, /*NeedDeviceAddrArgsSize=*/AdjustArgsNeedDeviceAddrSize: 0,
7766 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7767 for (FunctionDecl *BaseFD : Bases)
7768 BaseFD->addAttr(A: OMPDeclareVariantA);
7769}
7770
7771ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
7772 SourceLocation LParenLoc,
7773 MultiExprArg ArgExprs,
7774 SourceLocation RParenLoc,
7775 Expr *ExecConfig) {
7776 // The common case is a regular call we do not want to specialize at all. Try
7777 // to make that case fast by bailing early.
7778 CallExpr *CE = dyn_cast<CallExpr>(Val: Call.get());
7779 if (!CE)
7780 return Call;
7781
7782 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7783
7784 // Mark indirect calls inside target regions, to allow for insertion of
7785 // __llvm_omp_indirect_call_lookup calls during codegen.
7786 if (!CalleeFnDecl) {
7787 if (isInOpenMPTargetExecutionDirective()) {
7788 Expr *E = CE->getCallee()->IgnoreParenImpCasts();
7789 DeclRefExpr *DRE = nullptr;
7790 while (E) {
7791 if ((DRE = dyn_cast<DeclRefExpr>(Val: E)))
7792 break;
7793 if (auto *ME = dyn_cast<MemberExpr>(Val: E))
7794 E = ME->getBase()->IgnoreParenImpCasts();
7795 else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: E))
7796 E = ASE->getBase()->IgnoreParenImpCasts();
7797 else
7798 break;
7799 }
7800 VarDecl *VD = DRE ? dyn_cast<VarDecl>(Val: DRE->getDecl()) : nullptr;
7801 if (VD && !VD->hasAttr<OMPTargetIndirectCallAttr>()) {
7802 VD->addAttr(A: OMPTargetIndirectCallAttr::CreateImplicit(Ctx&: getASTContext()));
7803 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
7804 ML->DeclarationMarkedOpenMPIndirectCall(D: VD);
7805 }
7806 }
7807
7808 return Call;
7809 }
7810
7811 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7812 CalleeFnDecl->getIdentifier() &&
7813 CalleeFnDecl->getName().starts_with_insensitive(Prefix: "omp_")) {
7814 // checking for any calls inside an Order region
7815 if (Scope && Scope->isOpenMPOrderClauseScope())
7816 Diag(Loc: LParenLoc, DiagID: diag::err_omp_unexpected_call_to_omp_runtime_api);
7817 }
7818
7819 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7820 return Call;
7821
7822 ASTContext &Context = getASTContext();
7823 std::function<void(StringRef)> DiagUnknownTrait = [this,
7824 CE](StringRef ISATrait) {
7825 // TODO Track the selector locations in a way that is accessible here to
7826 // improve the diagnostic location.
7827 Diag(Loc: CE->getBeginLoc(), DiagID: diag::warn_unknown_declare_variant_isa_trait)
7828 << ISATrait;
7829 };
7830 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7831 SemaRef.getCurFunctionDecl(),
7832 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7833
7834 QualType CalleeFnType = CalleeFnDecl->getType();
7835
7836 SmallVector<Expr *, 4> Exprs;
7837 SmallVector<VariantMatchInfo, 4> VMIs;
7838 while (CalleeFnDecl) {
7839 for (OMPDeclareVariantAttr *A :
7840 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7841 Expr *VariantRef = A->getVariantFuncRef();
7842
7843 VariantMatchInfo VMI;
7844 OMPTraitInfo &TI = A->getTraitInfo();
7845 TI.getAsVariantMatchInfo(ASTCtx&: Context, VMI);
7846 if (!isVariantApplicableInContext(VMI, Ctx: OMPCtx,
7847 /*DeviceSetOnly=*/DeviceOrImplementationSetOnly: false))
7848 continue;
7849
7850 VMIs.push_back(Elt: VMI);
7851 Exprs.push_back(Elt: VariantRef);
7852 }
7853
7854 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7855 }
7856
7857 ExprResult NewCall;
7858 do {
7859 int BestIdx = getBestVariantMatchForContext(VMIs, Ctx: OMPCtx);
7860 if (BestIdx < 0)
7861 return Call;
7862 Expr *BestExpr = cast<DeclRefExpr>(Val: Exprs[BestIdx]);
7863 Decl *BestDecl = cast<DeclRefExpr>(Val: BestExpr)->getDecl();
7864
7865 {
7866 // Try to build a (member) call expression for the current best applicable
7867 // variant expression. We allow this to fail in which case we continue
7868 // with the next best variant expression. The fail case is part of the
7869 // implementation defined behavior in the OpenMP standard when it talks
7870 // about what differences in the function prototypes: "Any differences
7871 // that the specific OpenMP context requires in the prototype of the
7872 // variant from the base function prototype are implementation defined."
7873 // This wording is there to allow the specialized variant to have a
7874 // different type than the base function. This is intended and OK but if
7875 // we cannot create a call the difference is not in the "implementation
7876 // defined range" we allow.
7877 Sema::TentativeAnalysisScope Trap(SemaRef);
7878
7879 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(Val: BestDecl)) {
7880 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(Val: CE);
7881 BestExpr = MemberExpr::CreateImplicit(
7882 C: Context, Base: MemberCall->getImplicitObjectArgument(),
7883 /*IsArrow=*/false, MemberDecl: SpecializedMethod, T: Context.BoundMemberTy,
7884 VK: MemberCall->getValueKind(), OK: MemberCall->getObjectKind());
7885 }
7886 NewCall = SemaRef.BuildCallExpr(S: Scope, Fn: BestExpr, LParenLoc, ArgExprs,
7887 RParenLoc, ExecConfig);
7888 if (NewCall.isUsable()) {
7889 if (CallExpr *NCE = dyn_cast<CallExpr>(Val: NewCall.get())) {
7890 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7891 QualType NewType = getASTContext().mergeFunctionTypes(
7892 CalleeFnType, NewCalleeFnDecl->getType(),
7893 /*OfBlockPointer=*/false,
7894 /*Unqualified=*/false, /*AllowCXX=*/true);
7895 if (!NewType.isNull())
7896 break;
7897 // Don't use the call if the function type was not compatible.
7898 NewCall = nullptr;
7899 }
7900 }
7901 }
7902
7903 VMIs.erase(CI: VMIs.begin() + BestIdx);
7904 Exprs.erase(CI: Exprs.begin() + BestIdx);
7905 } while (!VMIs.empty());
7906
7907 if (!NewCall.isUsable())
7908 return Call;
7909 return PseudoObjectExpr::Create(Context: getASTContext(), syntactic: CE, semantic: {NewCall.get()}, resultIndex: 0);
7910}
7911
7912std::optional<std::pair<FunctionDecl *, Expr *>>
7913SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG,
7914 Expr *VariantRef,
7915 OMPTraitInfo &TI,
7916 unsigned NumAppendArgs,
7917 SourceRange SR) {
7918 ASTContext &Context = getASTContext();
7919 if (!DG || DG.get().isNull())
7920 return std::nullopt;
7921
7922 const int VariantId = 1;
7923 // Must be applied only to single decl.
7924 if (!DG.get().isSingleDecl()) {
7925 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_single_decl_in_declare_simd_variant)
7926 << VariantId << SR;
7927 return std::nullopt;
7928 }
7929 Decl *ADecl = DG.get().getSingleDecl();
7930 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: ADecl))
7931 ADecl = FTD->getTemplatedDecl();
7932
7933 // Decl must be a function.
7934 auto *FD = dyn_cast<FunctionDecl>(Val: ADecl);
7935 if (!FD) {
7936 Diag(Loc: ADecl->getLocation(), DiagID: diag::err_omp_function_expected)
7937 << VariantId << SR;
7938 return std::nullopt;
7939 }
7940
7941 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7942 // The 'target' attribute needs to be separately checked because it does
7943 // not always signify a multiversion function declaration.
7944 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7945 };
7946 // OpenMP is not compatible with multiversion function attributes.
7947 if (HasMultiVersionAttributes(FD)) {
7948 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_incompat_attributes)
7949 << SR;
7950 return std::nullopt;
7951 }
7952
7953 // Allow #pragma omp declare variant only if the function is not used.
7954 if (FD->isUsed(CheckUsedAttr: false))
7955 Diag(Loc: SR.getBegin(), DiagID: diag::warn_omp_declare_variant_after_used)
7956 << FD->getLocation();
7957
7958 // Check if the function was emitted already.
7959 const FunctionDecl *Definition;
7960 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7961 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(D: Definition)))
7962 Diag(Loc: SR.getBegin(), DiagID: diag::warn_omp_declare_variant_after_emitted)
7963 << FD->getLocation();
7964
7965 // The VariantRef must point to function.
7966 if (!VariantRef) {
7967 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_function_expected) << VariantId;
7968 return std::nullopt;
7969 }
7970
7971 auto ShouldDelayChecks = [](Expr *&E, bool) {
7972 return E && (E->isTypeDependent() || E->isValueDependent() ||
7973 E->containsUnexpandedParameterPack() ||
7974 E->isInstantiationDependent());
7975 };
7976 // Do not check templates, wait until instantiation.
7977 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7978 TI.anyScoreOrCondition(Cond: ShouldDelayChecks))
7979 return std::make_pair(x&: FD, y&: VariantRef);
7980
7981 // Deal with non-constant score and user condition expressions.
7982 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7983 bool IsScore) -> bool {
7984 if (!E || E->isIntegerConstantExpr(Ctx: getASTContext()))
7985 return false;
7986
7987 if (IsScore) {
7988 // We warn on non-constant scores and pretend they were not present.
7989 Diag(Loc: E->getExprLoc(), DiagID: diag::warn_omp_declare_variant_score_not_constant)
7990 << E;
7991 E = nullptr;
7992 } else {
7993 // We could replace a non-constant user condition with "false" but we
7994 // will soon need to handle these anyway for the dynamic version of
7995 // OpenMP context selectors.
7996 Diag(Loc: E->getExprLoc(),
7997 DiagID: diag::err_omp_declare_variant_user_condition_not_constant)
7998 << E;
7999 }
8000 return true;
8001 };
8002 if (TI.anyScoreOrCondition(Cond: HandleNonConstantScoresAndConditions))
8003 return std::nullopt;
8004
8005 QualType AdjustedFnType = FD->getType();
8006 if (NumAppendArgs) {
8007 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
8008 if (!PTy) {
8009 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_prototype_required)
8010 << SR;
8011 return std::nullopt;
8012 }
8013 // Adjust the function type to account for an extra omp_interop_t for each
8014 // specified in the append_args clause.
8015 const TypeDecl *TD = nullptr;
8016 LookupResult Result(SemaRef, &Context.Idents.get(Name: "omp_interop_t"),
8017 SR.getBegin(), Sema::LookupOrdinaryName);
8018 if (SemaRef.LookupName(R&: Result, S: SemaRef.getCurScope())) {
8019 NamedDecl *ND = Result.getFoundDecl();
8020 TD = dyn_cast_or_null<TypeDecl>(Val: ND);
8021 }
8022 if (!TD) {
8023 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_interop_type_not_found) << SR;
8024 return std::nullopt;
8025 }
8026 QualType InteropType =
8027 Context.getTypeDeclType(Keyword: ElaboratedTypeKeyword::None,
8028 /*Qualifier=*/std::nullopt, Decl: TD);
8029 if (PTy->isVariadic()) {
8030 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_append_args_with_varargs) << SR;
8031 return std::nullopt;
8032 }
8033 llvm::SmallVector<QualType, 8> Params;
8034 Params.append(in_start: PTy->param_type_begin(), in_end: PTy->param_type_end());
8035 Params.insert(I: Params.end(), NumToInsert: NumAppendArgs, Elt: InteropType);
8036 AdjustedFnType = Context.getFunctionType(ResultTy: PTy->getReturnType(), Args: Params,
8037 EPI: PTy->getExtProtoInfo());
8038 }
8039
8040 // Convert VariantRef expression to the type of the original function to
8041 // resolve possible conflicts.
8042 ExprResult VariantRefCast = VariantRef;
8043 if (getLangOpts().CPlusPlus) {
8044 QualType FnPtrType;
8045 auto *Method = dyn_cast<CXXMethodDecl>(Val: FD);
8046 if (Method && !Method->isStatic()) {
8047 FnPtrType = Context.getMemberPointerType(
8048 T: AdjustedFnType, /*Qualifier=*/std::nullopt, Cls: Method->getParent());
8049 ExprResult ER;
8050 {
8051 // Build addr_of unary op to correctly handle type checks for member
8052 // functions.
8053 Sema::TentativeAnalysisScope Trap(SemaRef);
8054 ER = SemaRef.CreateBuiltinUnaryOp(OpLoc: VariantRef->getBeginLoc(), Opc: UO_AddrOf,
8055 InputExpr: VariantRef);
8056 }
8057 if (!ER.isUsable()) {
8058 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
8059 << VariantId << VariantRef->getSourceRange();
8060 return std::nullopt;
8061 }
8062 VariantRef = ER.get();
8063 } else {
8064 FnPtrType = Context.getPointerType(T: AdjustedFnType);
8065 }
8066 QualType VarianPtrType = Context.getPointerType(T: VariantRef->getType());
8067 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
8068 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
8069 From: VariantRef, ToType: FnPtrType.getUnqualifiedType(),
8070 /*SuppressUserConversions=*/false, AllowExplicit: Sema::AllowedExplicit::None,
8071 /*InOverloadResolution=*/false,
8072 /*CStyle=*/false,
8073 /*AllowObjCWritebackConversion=*/false);
8074 if (ICS.isFailure()) {
8075 Diag(Loc: VariantRef->getExprLoc(),
8076 DiagID: diag::err_omp_declare_variant_incompat_types)
8077 << VariantRef->getType()
8078 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
8079 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
8080 return std::nullopt;
8081 }
8082 VariantRefCast = SemaRef.PerformImplicitConversion(
8083 From: VariantRef, ToType: FnPtrType.getUnqualifiedType(),
8084 Action: AssignmentAction::Converting);
8085 if (!VariantRefCast.isUsable())
8086 return std::nullopt;
8087 }
8088 // Drop previously built artificial addr_of unary op for member functions.
8089 if (Method && !Method->isStatic()) {
8090 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
8091 if (auto *UO = dyn_cast<UnaryOperator>(
8092 Val: PossibleAddrOfVariantRef->IgnoreImplicit()))
8093 VariantRefCast = UO->getSubExpr();
8094 }
8095 }
8096
8097 ExprResult ER = SemaRef.CheckPlaceholderExpr(E: VariantRefCast.get());
8098 if (!ER.isUsable() ||
8099 !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
8100 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
8101 << VariantId << VariantRef->getSourceRange();
8102 return std::nullopt;
8103 }
8104
8105 // The VariantRef must point to function.
8106 auto *DRE = dyn_cast<DeclRefExpr>(Val: ER.get()->IgnoreParenImpCasts());
8107 if (!DRE) {
8108 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
8109 << VariantId << VariantRef->getSourceRange();
8110 return std::nullopt;
8111 }
8112 auto *NewFD = dyn_cast_or_null<FunctionDecl>(Val: DRE->getDecl());
8113 if (!NewFD) {
8114 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
8115 << VariantId << VariantRef->getSourceRange();
8116 return std::nullopt;
8117 }
8118
8119 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
8120 Diag(Loc: VariantRef->getExprLoc(),
8121 DiagID: diag::err_omp_declare_variant_same_base_function)
8122 << VariantRef->getSourceRange();
8123 return std::nullopt;
8124 }
8125
8126 // Check if function types are compatible in C.
8127 if (!getLangOpts().CPlusPlus) {
8128 QualType NewType =
8129 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
8130 if (NewType.isNull()) {
8131 Diag(Loc: VariantRef->getExprLoc(),
8132 DiagID: diag::err_omp_declare_variant_incompat_types)
8133 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
8134 << VariantRef->getSourceRange();
8135 return std::nullopt;
8136 }
8137 if (NewType->isFunctionProtoType()) {
8138 if (FD->getType()->isFunctionNoProtoType())
8139 setPrototype(S&: SemaRef, FD, FDWithProto: NewFD, NewType);
8140 else if (NewFD->getType()->isFunctionNoProtoType())
8141 setPrototype(S&: SemaRef, FD: NewFD, FDWithProto: FD, NewType);
8142 }
8143 }
8144
8145 // Check if variant function is not marked with declare variant directive.
8146 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
8147 Diag(Loc: VariantRef->getExprLoc(),
8148 DiagID: diag::warn_omp_declare_variant_marked_as_declare_variant)
8149 << VariantRef->getSourceRange();
8150 SourceRange SR =
8151 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
8152 Diag(Loc: SR.getBegin(), DiagID: diag::note_omp_marked_declare_variant_here) << SR;
8153 return std::nullopt;
8154 }
8155
8156 enum DoesntSupport {
8157 VirtFuncs = 1,
8158 Constructors = 3,
8159 Destructors = 4,
8160 DeletedFuncs = 5,
8161 DefaultedFuncs = 6,
8162 ConstexprFuncs = 7,
8163 ConstevalFuncs = 8,
8164 };
8165 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(Val: FD)) {
8166 if (CXXFD->isVirtual()) {
8167 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
8168 << VirtFuncs;
8169 return std::nullopt;
8170 }
8171
8172 if (isa<CXXConstructorDecl>(Val: FD)) {
8173 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
8174 << Constructors;
8175 return std::nullopt;
8176 }
8177
8178 if (isa<CXXDestructorDecl>(Val: FD)) {
8179 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
8180 << Destructors;
8181 return std::nullopt;
8182 }
8183 }
8184
8185 if (FD->isDeleted()) {
8186 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
8187 << DeletedFuncs;
8188 return std::nullopt;
8189 }
8190
8191 if (FD->isDefaulted()) {
8192 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
8193 << DefaultedFuncs;
8194 return std::nullopt;
8195 }
8196
8197 if (FD->isConstexpr()) {
8198 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
8199 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
8200 return std::nullopt;
8201 }
8202
8203 // Check general compatibility.
8204 if (SemaRef.areMultiversionVariantFunctionsCompatible(
8205 OldFD: FD, NewFD, NoProtoDiagID: PartialDiagnostic::NullDiagnostic(),
8206 NoteCausedDiagIDAt: PartialDiagnosticAt(SourceLocation(),
8207 PartialDiagnostic::NullDiagnostic()),
8208 NoSupportDiagIDAt: PartialDiagnosticAt(
8209 VariantRef->getExprLoc(),
8210 SemaRef.PDiag(DiagID: diag::err_omp_declare_variant_doesnt_support)),
8211 DiffDiagIDAt: PartialDiagnosticAt(VariantRef->getExprLoc(),
8212 SemaRef.PDiag(DiagID: diag::err_omp_declare_variant_diff)
8213 << FD->getLocation()),
8214 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
8215 /*CLinkageMayDiffer=*/true))
8216 return std::nullopt;
8217 return std::make_pair(x&: FD, y: cast<Expr>(Val: DRE));
8218}
8219
8220/// Validate prefer_type fr() and attr() arguments in an OMPInteropInfo.
8221/// fr() must be a string literal or constant integer expression.
8222/// attr() must be a string literal starting with "ompx_" and containing no
8223/// commas. Returns true if valid; emits diagnostic and returns false on first
8224/// error.
8225static bool checkPreferTypeArgs(SemaOpenMP &S, const OMPInteropInfo &Info) {
8226 auto isDependent = [](const Expr *E) {
8227 return E->isValueDependent() || E->isTypeDependent() ||
8228 E->isInstantiationDependent() ||
8229 E->containsUnexpandedParameterPack();
8230 };
8231 for (const OMPInteropPref &P : Info.Prefs) {
8232 const Expr *E = P.Fr;
8233 if (!E) {
8234 assert(Info.HasPreferAttrs && "null Fr requires OMP 6.0 syntax");
8235 } else if (!isDependent(E)) {
8236 if (!E->isIntegerConstantExpr(Ctx: S.getASTContext()) &&
8237 !isa<StringLiteral>(Val: E)) {
8238 S.Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_interop_prefer_type);
8239 return false;
8240 }
8241 }
8242 for (const Expr *A : P.Attrs) {
8243 if (isDependent(A))
8244 continue;
8245 const auto *SL = dyn_cast<StringLiteral>(Val: A);
8246 if (!SL) {
8247 S.Diag(Loc: A->getExprLoc(), DiagID: diag::err_omp_interop_attr_not_string);
8248 return false;
8249 }
8250 StringRef Str = SL->getString();
8251 if (!Str.starts_with(Prefix: "ompx_")) {
8252 S.Diag(Loc: A->getExprLoc(), DiagID: diag::err_omp_interop_attr_missing_ompx_prefix)
8253 << Str;
8254 return false;
8255 }
8256 if (Str.contains(C: ',')) {
8257 S.Diag(Loc: A->getExprLoc(), DiagID: diag::err_omp_interop_attr_contains_comma)
8258 << Str;
8259 return false;
8260 }
8261 }
8262 }
8263 return true;
8264}
8265
8266void SemaOpenMP::ActOnOpenMPDeclareVariantDirective(
8267 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
8268 ArrayRef<Expr *> AdjustArgsNothing,
8269 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
8270 ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
8271 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
8272 SourceLocation AppendArgsLoc, SourceRange SR) {
8273
8274 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
8275 // An adjust_args clause or append_args clause can only be specified if the
8276 // dispatch selector of the construct selector set appears in the match
8277 // clause.
8278
8279 SmallVector<Expr *, 8> AllAdjustArgs;
8280 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNothing);
8281 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNeedDevicePtr);
8282 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNeedDeviceAddr);
8283
8284 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
8285 VariantMatchInfo VMI;
8286 TI.getAsVariantMatchInfo(ASTCtx&: getASTContext(), VMI);
8287 if (!llvm::is_contained(
8288 Range&: VMI.ConstructTraits,
8289 Element: llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
8290 if (!AllAdjustArgs.empty())
8291 Diag(Loc: AdjustArgsLoc, DiagID: diag::err_omp_clause_requires_dispatch_construct)
8292 << getOpenMPClauseNameForDiag(C: OMPC_adjust_args);
8293 if (!AppendArgs.empty())
8294 Diag(Loc: AppendArgsLoc, DiagID: diag::err_omp_clause_requires_dispatch_construct)
8295 << getOpenMPClauseNameForDiag(C: OMPC_append_args);
8296 return;
8297 }
8298 }
8299
8300 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
8301 // Each argument can only appear in a single adjust_args clause for each
8302 // declare variant directive.
8303 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
8304
8305 for (Expr *E : AllAdjustArgs) {
8306 E = E->IgnoreParenImpCasts();
8307 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E)) {
8308 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
8309 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
8310 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
8311 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
8312 ->getCanonicalDecl() == CanonPVD) {
8313 // It's a parameter of the function, check duplicates.
8314 if (!AdjustVars.insert(Ptr: CanonPVD).second) {
8315 Diag(Loc: DRE->getLocation(), DiagID: diag::err_omp_adjust_arg_multiple_clauses)
8316 << PVD;
8317 return;
8318 }
8319 continue;
8320 }
8321 }
8322 }
8323 // Anything that is not a function parameter is an error.
8324 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause) << FD << 0;
8325 return;
8326 }
8327
8328 // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
8329 // If the `need_device_addr` adjust-op modifier is present, each list item
8330 // that appears in the clause must refer to an argument in the declaration of
8331 // the function variant that has a reference type
8332 if (getLangOpts().OpenMP >= 60) {
8333 for (Expr *E : AdjustArgsNeedDeviceAddr) {
8334 E = E->IgnoreParenImpCasts();
8335 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E)) {
8336 if (const auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl())) {
8337 if (!VD->getType()->isReferenceType())
8338 Diag(Loc: E->getExprLoc(),
8339 DiagID: diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
8340 }
8341 }
8342 }
8343 }
8344
8345 // OpenMP 6.0 [16.1.3] Check prefer_type fr()/attr() arguments in
8346 // append_args.
8347 for (const OMPInteropInfo &Info : AppendArgs) {
8348 if (!checkPreferTypeArgs(S&: *this, Info))
8349 return;
8350 }
8351
8352 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
8353 Ctx&: getASTContext(), VariantFuncRef: VariantRef, TraitInfos: &TI,
8354 AdjustArgsNothing: const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothingSize: AdjustArgsNothing.size(),
8355 AdjustArgsNeedDevicePtr: const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
8356 AdjustArgsNeedDevicePtrSize: AdjustArgsNeedDevicePtr.size(),
8357 AdjustArgsNeedDeviceAddr: const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
8358 AdjustArgsNeedDeviceAddrSize: AdjustArgsNeedDeviceAddr.size(),
8359 AppendArgs: const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgsSize: AppendArgs.size(), Range: SR);
8360 FD->addAttr(A: NewAttr);
8361}
8362
8363static CapturedStmt *
8364setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt) {
8365 auto *CS = dyn_cast<CapturedStmt>(Val: AStmt);
8366 assert(CS && "Captured statement expected");
8367 // 1.2.2 OpenMP Language Terminology
8368 // Structured block - An executable statement with a single entry at the
8369 // top and a single exit at the bottom.
8370 // The point of exit cannot be a branch out of the structured block.
8371 // longjmp() and throw() must not violate the entry/exit criteria.
8372 CS->getCapturedDecl()->setNothrow();
8373
8374 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
8375 ThisCaptureLevel > 1; --ThisCaptureLevel) {
8376 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
8377 // 1.2.2 OpenMP Language Terminology
8378 // Structured block - An executable statement with a single entry at the
8379 // top and a single exit at the bottom.
8380 // The point of exit cannot be a branch out of the structured block.
8381 // longjmp() and throw() must not violate the entry/exit criteria.
8382 CS->getCapturedDecl()->setNothrow();
8383 }
8384 SemaRef.setFunctionHasBranchProtectedScope();
8385 return CS;
8386}
8387
8388StmtResult
8389SemaOpenMP::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
8390 Stmt *AStmt, SourceLocation StartLoc,
8391 SourceLocation EndLoc) {
8392 if (!AStmt)
8393 return StmtError();
8394
8395 // Check for conflicting capture kinds on structured bindings.
8396 if (checkClausesForDecompositionConflicts(SemaRef, DKind: OMPD_parallel, Clauses,
8397 Body: AStmt))
8398 return StmtError();
8399
8400 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel, AStmt);
8401
8402 return OMPParallelDirective::Create(
8403 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
8404 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
8405}
8406
8407namespace {
8408/// Iteration space of a single for loop.
8409struct LoopIterationSpace final {
8410 /// True if the condition operator is the strict compare operator (<, > or
8411 /// !=).
8412 bool IsStrictCompare = false;
8413 /// Condition of the loop.
8414 Expr *PreCond = nullptr;
8415 /// This expression calculates the number of iterations in the loop.
8416 /// It is always possible to calculate it before starting the loop.
8417 Expr *NumIterations = nullptr;
8418 /// The loop counter variable.
8419 Expr *CounterVar = nullptr;
8420 /// Private loop counter variable.
8421 Expr *PrivateCounterVar = nullptr;
8422 /// This is initializer for the initial value of #CounterVar.
8423 Expr *CounterInit = nullptr;
8424 /// This is step for the #CounterVar used to generate its update:
8425 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
8426 Expr *CounterStep = nullptr;
8427 /// Should step be subtracted?
8428 bool Subtract = false;
8429 /// Source range of the loop init.
8430 SourceRange InitSrcRange;
8431 /// Source range of the loop condition.
8432 SourceRange CondSrcRange;
8433 /// Source range of the loop increment.
8434 SourceRange IncSrcRange;
8435 /// Minimum value that can have the loop control variable. Used to support
8436 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
8437 /// since only such variables can be used in non-loop invariant expressions.
8438 Expr *MinValue = nullptr;
8439 /// Maximum value that can have the loop control variable. Used to support
8440 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
8441 /// since only such variables can be used in non-loop invariant expressions.
8442 Expr *MaxValue = nullptr;
8443 /// true, if the lower bound depends on the outer loop control var.
8444 bool IsNonRectangularLB = false;
8445 /// true, if the upper bound depends on the outer loop control var.
8446 bool IsNonRectangularUB = false;
8447 /// Index of the loop this loop depends on and forms non-rectangular loop
8448 /// nest.
8449 unsigned LoopDependentIdx = 0;
8450 /// Final condition for the non-rectangular loop nest support. It is used to
8451 /// check that the number of iterations for this particular counter must be
8452 /// finished.
8453 Expr *FinalCondition = nullptr;
8454};
8455
8456/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
8457/// set are referenced. Used for verifying loop nest structure before
8458/// performing a loop collapse operation.
8459class ForSubExprChecker : public DynamicRecursiveASTVisitor {
8460 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8461 VarDecl *ForbiddenVar = nullptr;
8462 SourceRange ErrLoc;
8463
8464public:
8465 explicit ForSubExprChecker(
8466 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
8467 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
8468 // We want to visit implicit code, i.e. synthetic initialisation statements
8469 // created during range-for lowering.
8470 ShouldVisitImplicitCode = true;
8471 }
8472
8473 bool VisitDeclRefExpr(DeclRefExpr *E) override {
8474 ValueDecl *VD = E->getDecl();
8475 if (!isa<VarDecl, BindingDecl>(Val: VD))
8476 return true;
8477 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
8478 if (V->getType()->isReferenceType()) {
8479 VarDecl *VD = V->getDefinition();
8480 if (VD && VD->hasInit()) {
8481 Expr *I = VD->getInit();
8482 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Val: I);
8483 if (!DRE)
8484 return true;
8485 V = DRE->getDecl()->getPotentiallyDecomposedVarDecl();
8486 }
8487 }
8488 Decl *Canon = V->getCanonicalDecl();
8489 if (CollapsedLoopVarDecls.contains(Ptr: Canon)) {
8490 ForbiddenVar = V;
8491 ErrLoc = E->getSourceRange();
8492 return false;
8493 }
8494
8495 return true;
8496 }
8497
8498 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
8499 SourceRange getErrRange() const { return ErrLoc; }
8500};
8501
8502/// Helper class for checking canonical form of the OpenMP loops and
8503/// extracting iteration space of each loop in the loop nest, that will be used
8504/// for IR generation.
8505class OpenMPIterationSpaceChecker {
8506 /// Reference to Sema.
8507 Sema &SemaRef;
8508 /// Does the loop associated directive support non-rectangular loops?
8509 bool SupportsNonRectangular;
8510 /// Data-sharing stack.
8511 DSAStackTy &Stack;
8512 /// A location for diagnostics (when there is no some better location).
8513 SourceLocation DefaultLoc;
8514 /// A location for diagnostics (when increment is not compatible).
8515 SourceLocation ConditionLoc;
8516 /// The set of variables declared within the (to be collapsed) loop nest.
8517 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8518 /// The set of induction variables from outer collapsed loops.
8519 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars;
8520 /// A source location for referring to loop init later.
8521 SourceRange InitSrcRange;
8522 /// A source location for referring to condition later.
8523 SourceRange ConditionSrcRange;
8524 /// A source location for referring to increment later.
8525 SourceRange IncrementSrcRange;
8526 /// Loop variable.
8527 ValueDecl *LCDecl = nullptr;
8528 /// Reference to loop variable.
8529 Expr *LCRef = nullptr;
8530 /// Lower bound (initializer for the var).
8531 Expr *LB = nullptr;
8532 /// Upper bound.
8533 Expr *UB = nullptr;
8534 /// Loop step (increment).
8535 Expr *Step = nullptr;
8536 /// This flag is true when condition is one of:
8537 /// Var < UB
8538 /// Var <= UB
8539 /// UB > Var
8540 /// UB >= Var
8541 /// This will have no value when the condition is !=
8542 std::optional<bool> TestIsLessOp;
8543 /// This flag is true when condition is strict ( < or > ).
8544 bool TestIsStrictOp = false;
8545 /// This flag is true when step is subtracted on each iteration.
8546 bool SubtractStep = false;
8547 /// The outer loop counter this loop depends on (if any).
8548 const ValueDecl *DepDecl = nullptr;
8549 /// Contains number of loop (starts from 1) on which loop counter init
8550 /// expression of this loop depends on.
8551 std::optional<unsigned> InitDependOnLC;
8552 /// Contains number of loop (starts from 1) on which loop counter condition
8553 /// expression of this loop depends on.
8554 std::optional<unsigned> CondDependOnLC;
8555 /// Checks if the provide statement depends on the loop counter.
8556 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8557 bool IsInitializer);
8558 /// Original condition required for checking of the exit condition for
8559 /// non-rectangular loop.
8560 Expr *Condition = nullptr;
8561
8562public:
8563 OpenMPIterationSpaceChecker(
8564 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
8565 SourceLocation DefaultLoc,
8566 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls,
8567 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars)
8568 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8569 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8570 CollapsedLoopVarDecls(CollapsedLoopDecls),
8571 CollapsedLoopInductionVars(CollapsedLoopInductionVars) {}
8572 /// Check init-expr for canonical loop form and save loop counter
8573 /// variable - #Var and its initialization value - #LB.
8574 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8575 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8576 /// for less/greater and for strict/non-strict comparison.
8577 bool checkAndSetCond(Expr *S);
8578 /// Check incr-expr for canonical loop form and return true if it
8579 /// does not conform, otherwise save loop step (#Step).
8580 bool checkAndSetInc(Expr *S);
8581 /// Return the loop counter variable.
8582 ValueDecl *getLoopDecl() const { return LCDecl; }
8583 /// Return the reference expression to loop counter variable.
8584 Expr *getLoopDeclRefExpr() const { return LCRef; }
8585 /// Source range of the loop init.
8586 SourceRange getInitSrcRange() const { return InitSrcRange; }
8587 /// Source range of the loop condition.
8588 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8589 /// Source range of the loop increment.
8590 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8591 /// True if the step should be subtracted.
8592 bool shouldSubtractStep() const { return SubtractStep; }
8593 /// True, if the compare operator is strict (<, > or !=).
8594 bool isStrictTestOp() const { return TestIsStrictOp; }
8595 /// Build the expression to calculate the number of iterations.
8596 Expr *buildNumIterations(
8597 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8598 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8599 /// Build the precondition expression for the loops.
8600 Expr *
8601 buildPreCond(Scope *S, Expr *Cond,
8602 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8603 /// Build reference expression to the counter be used for codegen.
8604 DeclRefExpr *
8605 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8606 DSAStackTy &DSA) const;
8607 /// Build reference expression to the private counter be used for
8608 /// codegen.
8609 Expr *buildPrivateCounterVar() const;
8610 /// Build initialization of the counter be used for codegen.
8611 Expr *buildCounterInit() const;
8612 /// Build step of the counter be used for codegen.
8613 Expr *buildCounterStep() const;
8614 /// Build loop data with counter value for depend clauses in ordered
8615 /// directives.
8616 Expr *
8617 buildOrderedLoopData(Scope *S, Expr *Counter,
8618 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8619 SourceLocation Loc, Expr *Inc = nullptr,
8620 OverloadedOperatorKind OOK = OO_Amp);
8621 /// Builds the minimum value for the loop counter.
8622 std::pair<Expr *, Expr *> buildMinMaxValues(
8623 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8624 /// Builds final condition for the non-rectangular loops.
8625 Expr *buildFinalCondition(Scope *S) const;
8626 /// Return true if any expression is dependent.
8627 bool dependent() const;
8628 /// Returns true if the initializer forms non-rectangular loop.
8629 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8630 /// Returns true if the condition forms non-rectangular loop.
8631 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8632 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8633 unsigned getLoopDependentIdx() const {
8634 return InitDependOnLC.value_or(u: CondDependOnLC.value_or(u: 0));
8635 }
8636
8637private:
8638 /// Check the right-hand side of an assignment in the increment
8639 /// expression.
8640 bool checkAndSetIncRHS(Expr *RHS);
8641 /// Helper to set loop counter variable and its initializer.
8642 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8643 bool EmitDiags);
8644 /// Helper to set upper bound.
8645 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8646 SourceRange SR, SourceLocation SL);
8647 /// Helper to set loop increment.
8648 bool setStep(Expr *NewStep, bool Subtract);
8649 /// Diagnose a statement expression in a bound of a non-rectangular loop.
8650 bool checkNonRectangularBound(const Expr *E, bool IsInitializer) const;
8651};
8652
8653bool OpenMPIterationSpaceChecker::dependent() const {
8654 if (!LCDecl) {
8655 assert(!LB && !UB && !Step);
8656 return false;
8657 }
8658 return LCDecl->getType()->isDependentType() ||
8659 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8660 (Step && Step->isValueDependent());
8661}
8662
8663/// Find a statement expression in \p E.
8664static const StmtExpr *findStmtExpr(const Expr *E) {
8665 SmallVector<const Stmt *, 8> Worklist{E};
8666 while (!Worklist.empty()) {
8667 const Stmt *S = Worklist.pop_back_val();
8668 if (!S)
8669 continue;
8670 if (const auto *SE = dyn_cast<StmtExpr>(Val: S))
8671 return SE;
8672 llvm::append_range(C&: Worklist, R: S->children());
8673 }
8674 return nullptr;
8675}
8676
8677bool OpenMPIterationSpaceChecker::checkNonRectangularBound(
8678 const Expr *E, bool IsInitializer) const {
8679 // Such a bound is emitted at every use, its declarations cannot be.
8680 const StmtExpr *SE = findStmtExpr(E);
8681 if (!SE)
8682 return false;
8683 SemaRef.Diag(Loc: SE->getBeginLoc(),
8684 DiagID: diag::err_omp_stmt_expr_in_non_rectangular_loop)
8685 << (IsInitializer ? 0 : 1);
8686 return true;
8687}
8688
8689bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8690 Expr *NewLCRefExpr,
8691 Expr *NewLB, bool EmitDiags) {
8692 // State consistency checking to ensure correct usage.
8693 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8694 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8695 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8696 return true;
8697 LCDecl = getCanonicalDecl(D: NewLCDecl);
8698 LCRef = NewLCRefExpr;
8699 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(Val: NewLB))
8700 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8701 if ((Ctor->isCopyOrMoveConstructor() ||
8702 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8703 CE->getNumArgs() > 0 && CE->getArg(Arg: 0) != nullptr)
8704 NewLB = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
8705 LB = NewLB;
8706 if (EmitDiags) {
8707 InitDependOnLC = doesDependOnLoopCounter(S: LB, /*IsInitializer=*/true);
8708 if (InitDependOnLC && checkNonRectangularBound(E: LB, /*IsInitializer=*/true))
8709 return true;
8710 }
8711 return false;
8712}
8713
8714bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8715 bool StrictOp, SourceRange SR,
8716 SourceLocation SL) {
8717 // State consistency checking to ensure correct usage.
8718 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8719 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8720 if (!NewUB || NewUB->containsErrors())
8721 return true;
8722 UB = NewUB;
8723 if (LessOp)
8724 TestIsLessOp = LessOp;
8725 TestIsStrictOp = StrictOp;
8726 ConditionSrcRange = SR;
8727 ConditionLoc = SL;
8728 CondDependOnLC = doesDependOnLoopCounter(S: UB, /*IsInitializer=*/false);
8729 // The condition is also emitted as the body guard of a non-rectangular loop.
8730 if ((InitDependOnLC || CondDependOnLC) &&
8731 checkNonRectangularBound(E: UB, /*IsInitializer=*/false))
8732 return true;
8733 return false;
8734}
8735
8736bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8737 // State consistency checking to ensure correct usage.
8738 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8739 if (!NewStep || NewStep->containsErrors())
8740 return true;
8741 if (!NewStep->isValueDependent()) {
8742 // Check that the step is integer expression.
8743 SourceLocation StepLoc = NewStep->getBeginLoc();
8744 ExprResult Val = SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(
8745 OpLoc: StepLoc, Op: getExprAsWritten(E: NewStep));
8746 if (Val.isInvalid())
8747 return true;
8748 NewStep = Val.get();
8749
8750 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8751 // If test-expr is of form var relational-op b and relational-op is < or
8752 // <= then incr-expr must cause var to increase on each iteration of the
8753 // loop. If test-expr is of form var relational-op b and relational-op is
8754 // > or >= then incr-expr must cause var to decrease on each iteration of
8755 // the loop.
8756 // If test-expr is of form b relational-op var and relational-op is < or
8757 // <= then incr-expr must cause var to decrease on each iteration of the
8758 // loop. If test-expr is of form b relational-op var and relational-op is
8759 // > or >= then incr-expr must cause var to increase on each iteration of
8760 // the loop.
8761 std::optional<llvm::APSInt> Result =
8762 NewStep->getIntegerConstantExpr(Ctx: SemaRef.Context);
8763 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8764 bool IsConstNeg =
8765 Result && Result->isSigned() && (Subtract != Result->isNegative());
8766 bool IsConstPos =
8767 Result && Result->isSigned() && (Subtract == Result->isNegative());
8768 bool IsConstZero = Result && !Result->getBoolValue();
8769
8770 // != with increment is treated as <; != with decrement is treated as >
8771 if (!TestIsLessOp)
8772 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8773 if (UB && (IsConstZero ||
8774 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8775 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8776 SemaRef.Diag(Loc: NewStep->getExprLoc(),
8777 DiagID: diag::err_omp_loop_incr_not_compatible)
8778 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8779 SemaRef.Diag(Loc: ConditionLoc,
8780 DiagID: diag::note_omp_loop_cond_requires_compatible_incr)
8781 << *TestIsLessOp << ConditionSrcRange;
8782 return true;
8783 }
8784 if (*TestIsLessOp == Subtract) {
8785 NewStep =
8786 SemaRef.CreateBuiltinUnaryOp(OpLoc: NewStep->getExprLoc(), Opc: UO_Minus, InputExpr: NewStep)
8787 .get();
8788 Subtract = !Subtract;
8789 }
8790 }
8791
8792 Step = NewStep;
8793 SubtractStep = Subtract;
8794 return false;
8795}
8796
8797namespace {
8798/// Checker for the non-rectangular loops. Checks if the initializer or
8799/// condition expression references loop counter variable.
8800class LoopCounterRefChecker final
8801 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8802 Sema &SemaRef;
8803 DSAStackTy &Stack;
8804 const ValueDecl *CurLCDecl = nullptr;
8805 const ValueDecl *DepDecl = nullptr;
8806 const ValueDecl *PrevDepDecl = nullptr;
8807 bool IsInitializer = true;
8808 bool SupportsNonRectangular;
8809 unsigned BaseLoopId = 0;
8810 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8811 if (getCanonicalDecl(D: VD) == getCanonicalDecl(D: CurLCDecl)) {
8812 SemaRef.Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_stmt_depends_on_loop_counter)
8813 << (IsInitializer ? 0 : 1);
8814 return false;
8815 }
8816 const auto &&Data = Stack.isLoopControlVariable(D: VD);
8817 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8818 // The type of the loop iterator on which we depend may not have a random
8819 // access iterator type.
8820 if (Data.first && VD->getType()->isRecordType()) {
8821 SmallString<128> Name;
8822 llvm::raw_svector_ostream OS(Name);
8823 VD->getNameForDiagnostic(OS, Policy: SemaRef.getPrintingPolicy(),
8824 /*Qualified=*/true);
8825 SemaRef.Diag(Loc: E->getExprLoc(),
8826 DiagID: diag::err_omp_wrong_dependency_iterator_type)
8827 << OS.str();
8828 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::note_previous_decl) << VD;
8829 return false;
8830 }
8831 if (Data.first && !SupportsNonRectangular) {
8832 SemaRef.Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_invariant_dependency);
8833 return false;
8834 }
8835 if (Data.first &&
8836 (DepDecl || (PrevDepDecl &&
8837 getCanonicalDecl(D: VD) != getCanonicalDecl(D: PrevDepDecl)))) {
8838 if (!DepDecl && PrevDepDecl)
8839 DepDecl = PrevDepDecl;
8840 SmallString<128> Name;
8841 llvm::raw_svector_ostream OS(Name);
8842 DepDecl->getNameForDiagnostic(OS, Policy: SemaRef.getPrintingPolicy(),
8843 /*Qualified=*/true);
8844 SemaRef.Diag(Loc: E->getExprLoc(),
8845 DiagID: diag::err_omp_invariant_or_linear_dependency)
8846 << OS.str();
8847 return false;
8848 }
8849 if (Data.first) {
8850 DepDecl = VD;
8851 BaseLoopId = Data.first;
8852 }
8853 return Data.first;
8854 }
8855
8856public:
8857 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8858 const ValueDecl *VD = E->getDecl();
8859 if (isa<VarDecl>(Val: VD))
8860 return checkDecl(E, VD);
8861 return false;
8862 }
8863 bool VisitMemberExpr(const MemberExpr *E) {
8864 if (isa<CXXThisExpr>(Val: E->getBase()->IgnoreParens())) {
8865 const ValueDecl *VD = E->getMemberDecl();
8866 if (isa<VarDecl>(Val: VD) || isa<FieldDecl>(Val: VD))
8867 return checkDecl(E, VD);
8868 }
8869 return false;
8870 }
8871 bool VisitStmt(const Stmt *S) {
8872 bool Res = false;
8873 for (const Stmt *Child : S->children())
8874 Res = (Child && Visit(S: Child)) || Res;
8875 return Res;
8876 }
8877 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8878 const ValueDecl *CurLCDecl, bool IsInitializer,
8879 const ValueDecl *PrevDepDecl = nullptr,
8880 bool SupportsNonRectangular = true)
8881 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8882 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8883 SupportsNonRectangular(SupportsNonRectangular) {}
8884 unsigned getBaseLoopId() const {
8885 assert(CurLCDecl && "Expected loop dependency.");
8886 return BaseLoopId;
8887 }
8888 const ValueDecl *getDepDecl() const {
8889 assert(CurLCDecl && "Expected loop dependency.");
8890 return DepDecl;
8891 }
8892};
8893} // namespace
8894
8895std::optional<unsigned>
8896OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8897 bool IsInitializer) {
8898 // Check for the non-rectangular loops.
8899 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8900 DepDecl, SupportsNonRectangular);
8901 if (LoopStmtChecker.Visit(S)) {
8902 DepDecl = LoopStmtChecker.getDepDecl();
8903 return LoopStmtChecker.getBaseLoopId();
8904 }
8905 return std::nullopt;
8906}
8907
8908bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8909 // Check init-expr for canonical loop form and save loop counter
8910 // variable - #Var and its initialization value - #LB.
8911 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8912 // var = lb
8913 // integer-type var = lb
8914 // random-access-iterator-type var = lb
8915 // pointer-type var = lb
8916 //
8917 if (!S) {
8918 if (EmitDiags) {
8919 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_init);
8920 }
8921 return true;
8922 }
8923 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: S))
8924 if (!ExprTemp->cleanupsHaveSideEffects())
8925 S = ExprTemp->getSubExpr();
8926
8927 if (!CollapsedLoopVarDecls.empty()) {
8928 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8929 if (!FSEC.TraverseStmt(S)) {
8930 SourceRange Range = FSEC.getErrRange();
8931 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
8932 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8933 return true;
8934 }
8935 }
8936
8937 // Helper lambda to reject structured bindings used as OpenMP loop
8938 // control variables. Loop counters are implicitly private, but bindings
8939 // share storage with their decomposition, so this is not representable.
8940 auto CheckBindingAsLoopVar = [&](ValueDecl *LoopVar,
8941 SourceLocation Loc) -> bool {
8942 if (!isa<BindingDecl>(Val: LoopVar))
8943 return false;
8944 if (EmitDiags)
8945 SemaRef.Diag(Loc, DiagID: diag::err_omp_loop_var_is_structured_binding)
8946 << LoopVar;
8947 return true;
8948 };
8949
8950 // Helper lambda to check if a loop variable is already used in an outer
8951 // loop.
8952 auto CheckLoopVarReuse = [&](ValueDecl *LoopVar, SourceLocation Loc) -> bool {
8953 if (EmitDiags &&
8954 CollapsedLoopInductionVars.count(Ptr: LoopVar->getCanonicalDecl())) {
8955 SemaRef.Diag(Loc, DiagID: diag::err_omp_loop_var_reused_in_collapsed_loop)
8956 << LoopVar;
8957 return true;
8958 }
8959 return false;
8960 };
8961
8962 InitSrcRange = S->getSourceRange();
8963 if (Expr *E = dyn_cast<Expr>(Val: S))
8964 S = E->IgnoreParens();
8965 if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8966 if (BO->getOpcode() == BO_Assign) {
8967 Expr *LHS = BO->getLHS()->IgnoreParens();
8968 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS)) {
8969 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: DRE->getDecl()))
8970 if (auto *ME =
8971 dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit()))) {
8972 ValueDecl *LoopVar = ME->getMemberDecl();
8973 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8974 return true;
8975 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: BO->getRHS(), EmitDiags);
8976 }
8977 ValueDecl *LoopVar = DRE->getDecl();
8978 if (CheckBindingAsLoopVar(LoopVar, DRE->getLocation()))
8979 return true;
8980 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8981 return true;
8982 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: DRE, NewLB: BO->getRHS(), EmitDiags);
8983 }
8984 if (auto *ME = dyn_cast<MemberExpr>(Val: LHS)) {
8985 if (ME->isArrow() &&
8986 isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts())) {
8987 ValueDecl *LoopVar = ME->getMemberDecl();
8988 if (CheckLoopVarReuse(LoopVar, LHS->getBeginLoc()))
8989 return true;
8990 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: BO->getRHS(), EmitDiags);
8991 }
8992 }
8993 }
8994 } else if (auto *DS = dyn_cast<DeclStmt>(Val: S)) {
8995 if (DS->isSingleDecl()) {
8996 if (auto *Var = dyn_cast_or_null<VarDecl>(Val: DS->getSingleDecl())) {
8997 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8998 // Accept non-canonical init form here but emit ext. warning.
8999 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
9000 SemaRef.Diag(Loc: S->getBeginLoc(),
9001 DiagID: diag::ext_omp_loop_not_canonical_init)
9002 << S->getSourceRange();
9003 if (CheckLoopVarReuse(Var, Var->getLocation()))
9004 return true;
9005 return setLCDeclAndLB(
9006 NewLCDecl: Var,
9007 NewLCRefExpr: buildDeclRefExpr(S&: SemaRef, D: Var,
9008 Ty: Var->getType().getNonReferenceType(),
9009 Loc: DS->getBeginLoc()),
9010 NewLB: Var->getInit(), EmitDiags);
9011 }
9012 }
9013 }
9014 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
9015 if (CE->getOperator() == OO_Equal) {
9016 Expr *LHS = CE->getArg(Arg: 0);
9017 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS)) {
9018 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: DRE->getDecl()))
9019 if (auto *ME =
9020 dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit()))) {
9021 ValueDecl *LoopVar = ME->getMemberDecl();
9022 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
9023 return true;
9024 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: CE->getArg(Arg: 1), EmitDiags);
9025 }
9026 ValueDecl *LoopVar = DRE->getDecl();
9027 if (CheckBindingAsLoopVar(LoopVar, DRE->getLocation()))
9028 return true;
9029 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
9030 return true;
9031 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: DRE, NewLB: CE->getArg(Arg: 1), EmitDiags);
9032 }
9033 if (auto *ME = dyn_cast<MemberExpr>(Val: LHS)) {
9034 if (ME->isArrow() &&
9035 isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts())) {
9036 ValueDecl *LoopVar = ME->getMemberDecl();
9037 if (CheckLoopVarReuse(LoopVar, LHS->getBeginLoc()))
9038 return true;
9039 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: CE->getArg(Arg: 1), EmitDiags);
9040 }
9041 }
9042 }
9043 }
9044
9045 if (dependent() || SemaRef.CurContext->isDependentContext())
9046 return false;
9047 if (EmitDiags) {
9048 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_init)
9049 << S->getSourceRange();
9050 }
9051 return true;
9052}
9053
9054/// Ignore parenthesizes, implicit casts, copy constructor and return the
9055/// variable (which may be the loop variable) if possible.
9056static const ValueDecl *getInitLCDecl(const Expr *E) {
9057 if (!E)
9058 return nullptr;
9059 E = getExprAsWritten(E);
9060 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(Val: E))
9061 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
9062 if ((Ctor->isCopyOrMoveConstructor() ||
9063 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
9064 CE->getNumArgs() > 0 && CE->getArg(Arg: 0) != nullptr)
9065 E = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
9066 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(Val: E)) {
9067 if (const auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
9068 return getCanonicalDecl(D: VD);
9069 }
9070 if (const auto *ME = dyn_cast_or_null<MemberExpr>(Val: E))
9071 if (ME->isArrow() && isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
9072 return getCanonicalDecl(D: ME->getMemberDecl());
9073 return nullptr;
9074}
9075
9076bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
9077 // Check test-expr for canonical form, save upper-bound UB, flags for
9078 // less/greater and for strict/non-strict comparison.
9079 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
9080 // var relational-op b
9081 // b relational-op var
9082 //
9083 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
9084 if (!S) {
9085 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_cond)
9086 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
9087 return true;
9088 }
9089 Condition = S;
9090 S = getExprAsWritten(E: S);
9091
9092 if (!CollapsedLoopVarDecls.empty()) {
9093 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
9094 if (!FSEC.TraverseStmt(S)) {
9095 SourceRange Range = FSEC.getErrRange();
9096 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
9097 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
9098 return true;
9099 }
9100 }
9101
9102 SourceLocation CondLoc = S->getBeginLoc();
9103 auto &&CheckAndSetCond =
9104 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
9105 const Expr *RHS, SourceRange SR,
9106 SourceLocation OpLoc) -> std::optional<bool> {
9107 if (BinaryOperator::isRelationalOp(Opc: Opcode)) {
9108 if (getInitLCDecl(E: LHS) == LCDecl)
9109 return setUB(NewUB: const_cast<Expr *>(RHS),
9110 LessOp: (Opcode == BO_LT || Opcode == BO_LE),
9111 StrictOp: (Opcode == BO_LT || Opcode == BO_GT), SR, SL: OpLoc);
9112 if (getInitLCDecl(E: RHS) == LCDecl)
9113 return setUB(NewUB: const_cast<Expr *>(LHS),
9114 LessOp: (Opcode == BO_GT || Opcode == BO_GE),
9115 StrictOp: (Opcode == BO_LT || Opcode == BO_GT), SR, SL: OpLoc);
9116 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
9117 return setUB(NewUB: const_cast<Expr *>(getInitLCDecl(E: LHS) == LCDecl ? RHS : LHS),
9118 /*LessOp=*/std::nullopt,
9119 /*StrictOp=*/true, SR, SL: OpLoc);
9120 }
9121 return std::nullopt;
9122 };
9123 std::optional<bool> Res;
9124 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(Val: S)) {
9125 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
9126 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
9127 RBO->getOperatorLoc());
9128 } else if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
9129 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
9130 BO->getSourceRange(), BO->getOperatorLoc());
9131 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
9132 if (CE->getNumArgs() == 2) {
9133 Res = CheckAndSetCond(
9134 BinaryOperator::getOverloadedOpcode(OO: CE->getOperator()), CE->getArg(Arg: 0),
9135 CE->getArg(Arg: 1), CE->getSourceRange(), CE->getOperatorLoc());
9136 }
9137 }
9138 if (Res)
9139 return *Res;
9140 if (dependent() || SemaRef.CurContext->isDependentContext())
9141 return false;
9142 SemaRef.Diag(Loc: CondLoc, DiagID: diag::err_omp_loop_not_canonical_cond)
9143 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
9144 return true;
9145}
9146
9147bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
9148 // RHS of canonical loop form increment can be:
9149 // var + incr
9150 // incr + var
9151 // var - incr
9152 //
9153 RHS = RHS->IgnoreParenImpCasts();
9154 if (auto *BO = dyn_cast<BinaryOperator>(Val: RHS)) {
9155 if (BO->isAdditiveOp()) {
9156 bool IsAdd = BO->getOpcode() == BO_Add;
9157 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
9158 return setStep(NewStep: BO->getRHS(), Subtract: !IsAdd);
9159 if (IsAdd && getInitLCDecl(E: BO->getRHS()) == LCDecl)
9160 return setStep(NewStep: BO->getLHS(), /*Subtract=*/false);
9161 }
9162 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: RHS)) {
9163 bool IsAdd = CE->getOperator() == OO_Plus;
9164 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
9165 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
9166 return setStep(NewStep: CE->getArg(Arg: 1), Subtract: !IsAdd);
9167 if (IsAdd && getInitLCDecl(E: CE->getArg(Arg: 1)) == LCDecl)
9168 return setStep(NewStep: CE->getArg(Arg: 0), /*Subtract=*/false);
9169 }
9170 }
9171 if (dependent() || SemaRef.CurContext->isDependentContext())
9172 return false;
9173 SemaRef.Diag(Loc: RHS->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_incr)
9174 << RHS->getSourceRange() << LCDecl;
9175 return true;
9176}
9177
9178bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
9179 // Check incr-expr for canonical loop form and return true if it
9180 // does not conform.
9181 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
9182 // ++var
9183 // var++
9184 // --var
9185 // var--
9186 // var += incr
9187 // var -= incr
9188 // var = var + incr
9189 // var = incr + var
9190 // var = var - incr
9191 //
9192 if (!S) {
9193 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_incr) << LCDecl;
9194 return true;
9195 }
9196 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: S))
9197 if (!ExprTemp->cleanupsHaveSideEffects())
9198 S = ExprTemp->getSubExpr();
9199
9200 if (!CollapsedLoopVarDecls.empty()) {
9201 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
9202 if (!FSEC.TraverseStmt(S)) {
9203 SourceRange Range = FSEC.getErrRange();
9204 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
9205 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
9206 return true;
9207 }
9208 }
9209
9210 IncrementSrcRange = S->getSourceRange();
9211 S = S->IgnoreParens();
9212 if (auto *UO = dyn_cast<UnaryOperator>(Val: S)) {
9213 if (UO->isIncrementDecrementOp() &&
9214 getInitLCDecl(E: UO->getSubExpr()) == LCDecl)
9215 return setStep(NewStep: SemaRef
9216 .ActOnIntegerConstant(Loc: UO->getBeginLoc(),
9217 Val: (UO->isDecrementOp() ? -1 : 1))
9218 .get(),
9219 /*Subtract=*/false);
9220 } else if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
9221 switch (BO->getOpcode()) {
9222 case BO_AddAssign:
9223 case BO_SubAssign:
9224 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
9225 return setStep(NewStep: BO->getRHS(), Subtract: BO->getOpcode() == BO_SubAssign);
9226 break;
9227 case BO_Assign:
9228 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
9229 return checkAndSetIncRHS(RHS: BO->getRHS());
9230 break;
9231 default:
9232 break;
9233 }
9234 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
9235 switch (CE->getOperator()) {
9236 case OO_PlusPlus:
9237 case OO_MinusMinus:
9238 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
9239 return setStep(NewStep: SemaRef
9240 .ActOnIntegerConstant(
9241 Loc: CE->getBeginLoc(),
9242 Val: ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
9243 .get(),
9244 /*Subtract=*/false);
9245 break;
9246 case OO_PlusEqual:
9247 case OO_MinusEqual:
9248 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
9249 return setStep(NewStep: CE->getArg(Arg: 1), Subtract: CE->getOperator() == OO_MinusEqual);
9250 break;
9251 case OO_Equal:
9252 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
9253 return checkAndSetIncRHS(RHS: CE->getArg(Arg: 1));
9254 break;
9255 default:
9256 break;
9257 }
9258 }
9259 if (dependent() || SemaRef.CurContext->isDependentContext())
9260 return false;
9261 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_incr)
9262 << S->getSourceRange() << LCDecl;
9263 return true;
9264}
9265
9266static ExprResult
9267tryBuildCapture(Sema &SemaRef, Expr *Capture,
9268 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9269 StringRef Name = ".capture_expr.") {
9270 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
9271 return Capture;
9272 // A statement expression must be captured even if it is constant, since the
9273 // declarations inside it can only be emitted once.
9274 if (Capture->isEvaluatable(Ctx: SemaRef.Context, AllowSideEffects: Expr::SE_AllowSideEffects) &&
9275 !findStmtExpr(E: Capture))
9276 return SemaRef.PerformImplicitConversion(From: Capture->IgnoreImpCasts(),
9277 ToType: Capture->getType(),
9278 Action: AssignmentAction::Converting,
9279 /*AllowExplicit=*/true);
9280 auto I = Captures.find(Key: Capture);
9281 if (I != Captures.end())
9282 return buildCapture(S&: SemaRef, CaptureExpr: Capture, Ref&: I->second, Name);
9283 DeclRefExpr *Ref = nullptr;
9284 ExprResult Res = buildCapture(S&: SemaRef, CaptureExpr: Capture, Ref, Name);
9285 Captures[Capture] = Ref;
9286 return Res;
9287}
9288
9289/// Calculate number of iterations, transforming to unsigned, if number of
9290/// iterations may be larger than the original type.
9291static Expr *
9292calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
9293 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
9294 bool TestIsStrictOp, bool RoundToStep,
9295 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9296 std::optional<unsigned> InitDependOnLC,
9297 std::optional<unsigned> CondDependOnLC) {
9298 ExprResult NewStep = tryBuildCapture(SemaRef, Capture: Step, Captures, Name: ".new_step");
9299 if (!NewStep.isUsable())
9300 return nullptr;
9301 llvm::APSInt LRes, SRes;
9302 bool IsLowerConst = false, IsStepConst = false;
9303 if (std::optional<llvm::APSInt> Res =
9304 Lower->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
9305 LRes = *Res;
9306 IsLowerConst = true;
9307 }
9308 if (std::optional<llvm::APSInt> Res =
9309 Step->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
9310 SRes = *Res;
9311 IsStepConst = true;
9312 }
9313 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
9314 ((!TestIsStrictOp && LRes.isNonNegative()) ||
9315 (TestIsStrictOp && LRes.isStrictlyPositive()));
9316 bool NeedToReorganize = false;
9317 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
9318 if (!NoNeedToConvert && IsLowerConst &&
9319 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
9320 NoNeedToConvert = true;
9321 if (RoundToStep) {
9322 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
9323 ? LRes.getBitWidth()
9324 : SRes.getBitWidth();
9325 LRes = LRes.extend(width: BW + 1);
9326 LRes.setIsSigned(true);
9327 SRes = SRes.extend(width: BW + 1);
9328 SRes.setIsSigned(true);
9329 LRes -= SRes;
9330 NoNeedToConvert = LRes.trunc(width: BW).extend(width: BW + 1) == LRes;
9331 LRes = LRes.trunc(width: BW);
9332 }
9333 if (TestIsStrictOp) {
9334 unsigned BW = LRes.getBitWidth();
9335 LRes = LRes.extend(width: BW + 1);
9336 LRes.setIsSigned(true);
9337 ++LRes;
9338 NoNeedToConvert =
9339 NoNeedToConvert && LRes.trunc(width: BW).extend(width: BW + 1) == LRes;
9340 // truncate to the original bitwidth.
9341 LRes = LRes.trunc(width: BW);
9342 }
9343 NeedToReorganize = NoNeedToConvert;
9344 }
9345 llvm::APSInt URes;
9346 bool IsUpperConst = false;
9347 if (std::optional<llvm::APSInt> Res =
9348 Upper->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
9349 URes = *Res;
9350 IsUpperConst = true;
9351 }
9352 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
9353 (!RoundToStep || IsStepConst)) {
9354 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
9355 : URes.getBitWidth();
9356 LRes = LRes.extend(width: BW + 1);
9357 LRes.setIsSigned(true);
9358 URes = URes.extend(width: BW + 1);
9359 URes.setIsSigned(true);
9360 URes -= LRes;
9361 NoNeedToConvert = URes.trunc(width: BW).extend(width: BW + 1) == URes;
9362 NeedToReorganize = NoNeedToConvert;
9363 }
9364 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
9365 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
9366 // unsigned.
9367 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
9368 !LCTy->isDependentType() && LCTy->isIntegerType()) {
9369 QualType LowerTy = Lower->getType();
9370 QualType UpperTy = Upper->getType();
9371 uint64_t LowerSize = SemaRef.Context.getTypeSize(T: LowerTy);
9372 uint64_t UpperSize = SemaRef.Context.getTypeSize(T: UpperTy);
9373 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
9374 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
9375 QualType CastType = getIntTypeForBitwidthOrBitInt(
9376 C&: SemaRef.Context, Bits: LowerSize > UpperSize ? LowerSize : UpperSize,
9377 /*Signed=*/false);
9378 Upper =
9379 SemaRef
9380 .PerformImplicitConversion(
9381 From: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Upper).get(),
9382 ToType: CastType, Action: AssignmentAction::Converting)
9383 .get();
9384 Lower = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Lower).get();
9385 NewStep = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: NewStep.get());
9386 }
9387 }
9388 if (!Lower || !Upper || NewStep.isInvalid())
9389 return nullptr;
9390
9391 ExprResult Diff;
9392
9393 // For nested triangular loops (depth >= 2), use already computed Upper and
9394 // Lower bounds to calculate the number of iterations: Upper - Lower + 1.
9395 // Don't apply to first-level triangular loops as the standard formula handles
9396 // those correctly.
9397 if (TestIsStrictOp && InitDependOnLC.has_value() &&
9398 InitDependOnLC.value() >= 2 && !CondDependOnLC.has_value()) {
9399 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Lower);
9400 if (!Diff.isUsable())
9401 return nullptr;
9402
9403 Diff =
9404 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(),
9405 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: DefaultLoc, Val: 1).get());
9406 if (!Diff.isUsable())
9407 return nullptr;
9408
9409 return Diff.get();
9410 }
9411
9412 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
9413 // 1]).
9414 if (NeedToReorganize) {
9415 Diff = Lower;
9416
9417 if (RoundToStep) {
9418 // Lower - Step
9419 Diff =
9420 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
9421 if (!Diff.isUsable())
9422 return nullptr;
9423 }
9424
9425 // Lower - Step [+ 1]
9426 if (TestIsStrictOp)
9427 Diff = SemaRef.BuildBinOp(
9428 S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(),
9429 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
9430 if (!Diff.isUsable())
9431 return nullptr;
9432
9433 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9434 if (!Diff.isUsable())
9435 return nullptr;
9436
9437 // Upper - (Lower - Step [+ 1]).
9438 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Diff.get());
9439 if (!Diff.isUsable())
9440 return nullptr;
9441 } else {
9442 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Lower);
9443
9444 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
9445 // BuildBinOp already emitted error, this one is to point user to upper
9446 // and lower bound, and to tell what is passed to 'operator-'.
9447 SemaRef.Diag(Loc: Upper->getBeginLoc(), DiagID: diag::err_omp_loop_diff_cxx)
9448 << Upper->getSourceRange() << Lower->getSourceRange();
9449 return nullptr;
9450 }
9451
9452 if (!Diff.isUsable())
9453 return nullptr;
9454
9455 // Upper - Lower [- 1]
9456 if (TestIsStrictOp)
9457 Diff = SemaRef.BuildBinOp(
9458 S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Diff.get(),
9459 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
9460 if (!Diff.isUsable())
9461 return nullptr;
9462
9463 if (RoundToStep) {
9464 // Upper - Lower [- 1] + Step
9465 Diff =
9466 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
9467 if (!Diff.isUsable())
9468 return nullptr;
9469 }
9470 }
9471
9472 // Parentheses (for dumping/debugging purposes only).
9473 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9474 if (!Diff.isUsable())
9475 return nullptr;
9476
9477 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
9478 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Div, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
9479 if (!Diff.isUsable())
9480 return nullptr;
9481
9482 return Diff.get();
9483}
9484
9485/// Build the expression to calculate the number of iterations.
9486Expr *OpenMPIterationSpaceChecker::buildNumIterations(
9487 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
9488 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9489 QualType VarType = LCDecl->getType().getNonReferenceType();
9490 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9491 !SemaRef.getLangOpts().CPlusPlus)
9492 return nullptr;
9493 Expr *LBVal = LB;
9494 Expr *UBVal = UB;
9495 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
9496 // max(LB(MinVal), LB(MaxVal)))
9497 if (InitDependOnLC) {
9498 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
9499 if (!IS.MinValue || !IS.MaxValue)
9500 return nullptr;
9501 // OuterVar = Min
9502 ExprResult MinValue =
9503 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MinValue);
9504 if (!MinValue.isUsable())
9505 return nullptr;
9506
9507 ExprResult LBMinVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9508 LHSExpr: IS.CounterVar, RHSExpr: MinValue.get());
9509 if (!LBMinVal.isUsable())
9510 return nullptr;
9511 // OuterVar = Min, LBVal
9512 LBMinVal =
9513 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: LBMinVal.get(), RHSExpr: LBVal);
9514 if (!LBMinVal.isUsable())
9515 return nullptr;
9516 // (OuterVar = Min, LBVal)
9517 LBMinVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: LBMinVal.get());
9518 if (!LBMinVal.isUsable())
9519 return nullptr;
9520
9521 // OuterVar = Max
9522 ExprResult MaxValue =
9523 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MaxValue);
9524 if (!MaxValue.isUsable())
9525 return nullptr;
9526
9527 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9528 LHSExpr: IS.CounterVar, RHSExpr: MaxValue.get());
9529 if (!LBMaxVal.isUsable())
9530 return nullptr;
9531 // OuterVar = Max, LBVal
9532 LBMaxVal =
9533 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: LBMaxVal.get(), RHSExpr: LBVal);
9534 if (!LBMaxVal.isUsable())
9535 return nullptr;
9536 // (OuterVar = Max, LBVal)
9537 LBMaxVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: LBMaxVal.get());
9538 if (!LBMaxVal.isUsable())
9539 return nullptr;
9540
9541 Expr *LBMin =
9542 tryBuildCapture(SemaRef, Capture: LBMinVal.get(), Captures, Name: ".lb_min").get();
9543 Expr *LBMax =
9544 tryBuildCapture(SemaRef, Capture: LBMaxVal.get(), Captures, Name: ".lb_max").get();
9545 if (!LBMin || !LBMax)
9546 return nullptr;
9547 // LB(MinVal) < LB(MaxVal)
9548 ExprResult MinLessMaxRes =
9549 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_LT, LHSExpr: LBMin, RHSExpr: LBMax);
9550 if (!MinLessMaxRes.isUsable())
9551 return nullptr;
9552 Expr *MinLessMax =
9553 tryBuildCapture(SemaRef, Capture: MinLessMaxRes.get(), Captures, Name: ".min_less_max")
9554 .get();
9555 if (!MinLessMax)
9556 return nullptr;
9557 if (*TestIsLessOp) {
9558 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
9559 // LB(MaxVal))
9560 ExprResult MinLB = SemaRef.ActOnConditionalOp(QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc,
9561 CondExpr: MinLessMax, LHSExpr: LBMin, RHSExpr: LBMax);
9562 if (!MinLB.isUsable())
9563 return nullptr;
9564 LBVal = MinLB.get();
9565 } else {
9566 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
9567 // LB(MaxVal))
9568 ExprResult MaxLB = SemaRef.ActOnConditionalOp(QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc,
9569 CondExpr: MinLessMax, LHSExpr: LBMax, RHSExpr: LBMin);
9570 if (!MaxLB.isUsable())
9571 return nullptr;
9572 LBVal = MaxLB.get();
9573 }
9574 // OuterVar = LB
9575 LBMinVal =
9576 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign, LHSExpr: IS.CounterVar, RHSExpr: LBVal);
9577 if (!LBMinVal.isUsable())
9578 return nullptr;
9579 LBVal = LBMinVal.get();
9580 }
9581 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
9582 // min(UB(MinVal), UB(MaxVal))
9583 if (CondDependOnLC) {
9584 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
9585 if (!IS.MinValue || !IS.MaxValue)
9586 return nullptr;
9587 // OuterVar = Min
9588 ExprResult MinValue =
9589 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MinValue);
9590 if (!MinValue.isUsable())
9591 return nullptr;
9592
9593 ExprResult UBMinVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9594 LHSExpr: IS.CounterVar, RHSExpr: MinValue.get());
9595 if (!UBMinVal.isUsable())
9596 return nullptr;
9597 // OuterVar = Min, UBVal
9598 UBMinVal =
9599 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: UBMinVal.get(), RHSExpr: UBVal);
9600 if (!UBMinVal.isUsable())
9601 return nullptr;
9602 // (OuterVar = Min, UBVal)
9603 UBMinVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: UBMinVal.get());
9604 if (!UBMinVal.isUsable())
9605 return nullptr;
9606
9607 // OuterVar = Max
9608 ExprResult MaxValue =
9609 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MaxValue);
9610 if (!MaxValue.isUsable())
9611 return nullptr;
9612
9613 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9614 LHSExpr: IS.CounterVar, RHSExpr: MaxValue.get());
9615 if (!UBMaxVal.isUsable())
9616 return nullptr;
9617 // OuterVar = Max, UBVal
9618 UBMaxVal =
9619 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: UBMaxVal.get(), RHSExpr: UBVal);
9620 if (!UBMaxVal.isUsable())
9621 return nullptr;
9622 // (OuterVar = Max, UBVal)
9623 UBMaxVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: UBMaxVal.get());
9624 if (!UBMaxVal.isUsable())
9625 return nullptr;
9626
9627 Expr *UBMin =
9628 tryBuildCapture(SemaRef, Capture: UBMinVal.get(), Captures, Name: ".ub_min").get();
9629 Expr *UBMax =
9630 tryBuildCapture(SemaRef, Capture: UBMaxVal.get(), Captures, Name: ".ub_max").get();
9631 if (!UBMin || !UBMax)
9632 return nullptr;
9633 // UB(MinVal) > UB(MaxVal)
9634 ExprResult MinGreaterMaxRes =
9635 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_GT, LHSExpr: UBMin, RHSExpr: UBMax);
9636 if (!MinGreaterMaxRes.isUsable())
9637 return nullptr;
9638 Expr *MinGreaterMax = tryBuildCapture(SemaRef, Capture: MinGreaterMaxRes.get(),
9639 Captures, Name: ".min_greater_max")
9640 .get();
9641 if (!MinGreaterMax)
9642 return nullptr;
9643 if (*TestIsLessOp) {
9644 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
9645 // UB(MaxVal))
9646 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
9647 QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc, CondExpr: MinGreaterMax, LHSExpr: UBMin, RHSExpr: UBMax);
9648 if (!MaxUB.isUsable())
9649 return nullptr;
9650 UBVal = MaxUB.get();
9651 } else {
9652 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9653 // UB(MaxVal))
9654 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9655 QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc, CondExpr: MinGreaterMax, LHSExpr: UBMax, RHSExpr: UBMin);
9656 if (!MinUB.isUsable())
9657 return nullptr;
9658 UBVal = MinUB.get();
9659 }
9660 }
9661 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9662 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9663 Expr *Upper = tryBuildCapture(SemaRef, Capture: UBExpr, Captures, Name: ".upper").get();
9664 Expr *Lower = tryBuildCapture(SemaRef, Capture: LBExpr, Captures, Name: ".lower").get();
9665 if (!Upper || !Lower)
9666 return nullptr;
9667
9668 ExprResult Diff = calculateNumIters(
9669 SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType, TestIsStrictOp,
9670 /*RoundToStep=*/true, Captures, InitDependOnLC, CondDependOnLC);
9671 if (!Diff.isUsable())
9672 return nullptr;
9673
9674 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9675 QualType Type = Diff.get()->getType();
9676 ASTContext &C = SemaRef.Context;
9677 bool UseVarType = VarType->hasIntegerRepresentation() &&
9678 C.getTypeSize(T: Type) > C.getTypeSize(T: VarType);
9679 if (!Type->isIntegerType() || UseVarType) {
9680 unsigned NewSize =
9681 UseVarType ? C.getTypeSize(T: VarType) : C.getTypeSize(T: Type);
9682 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9683 : Type->hasSignedIntegerRepresentation();
9684 Type = getIntTypeForBitwidthOrBitInt(C, Bits: NewSize, Signed: IsSigned);
9685 if (!SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: Type)) {
9686 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: Type,
9687 Action: AssignmentAction::Converting,
9688 /*AllowExplicit=*/true);
9689 if (!Diff.isUsable())
9690 return nullptr;
9691 }
9692 }
9693 if (LimitedType) {
9694 unsigned NewSize = (C.getTypeSize(T: Type) > 32) ? 64 : 32;
9695 if (NewSize != C.getTypeSize(T: Type)) {
9696 if (NewSize < C.getTypeSize(T: Type)) {
9697 assert(NewSize == 64 && "incorrect loop var size");
9698 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::warn_omp_loop_64_bit_var)
9699 << InitSrcRange << ConditionSrcRange;
9700 }
9701 QualType NewType = C.getIntTypeForBitwidth(
9702 DestWidth: NewSize, Signed: Type->hasSignedIntegerRepresentation() ||
9703 C.getTypeSize(T: Type) < NewSize);
9704 if (!SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: NewType)) {
9705 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: NewType,
9706 Action: AssignmentAction::Converting,
9707 /*AllowExplicit=*/true);
9708 if (!Diff.isUsable())
9709 return nullptr;
9710 }
9711 }
9712 }
9713
9714 return Diff.get();
9715}
9716
9717std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9718 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9719 // Do not build for iterators, they cannot be used in non-rectangular loop
9720 // nests.
9721 if (LCDecl->getType()->isRecordType())
9722 return std::make_pair(x: nullptr, y: nullptr);
9723 // If we subtract, the min is in the condition, otherwise the min is in the
9724 // init value.
9725 Expr *MinExpr = nullptr;
9726 Expr *MaxExpr = nullptr;
9727 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9728 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9729 bool LBNonRect =
9730 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9731 bool UBNonRect =
9732 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9733 Expr *Lower =
9734 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, Capture: LBExpr, Captures).get();
9735 Expr *Upper =
9736 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, Capture: UBExpr, Captures).get();
9737 if (!Upper || !Lower)
9738 return std::make_pair(x: nullptr, y: nullptr);
9739
9740 if (*TestIsLessOp)
9741 MinExpr = Lower;
9742 else
9743 MaxExpr = Upper;
9744
9745 // Build minimum/maximum value based on number of iterations.
9746 QualType VarType = LCDecl->getType().getNonReferenceType();
9747
9748 ExprResult Diff = calculateNumIters(
9749 SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType, TestIsStrictOp,
9750 /*RoundToStep=*/false, Captures, InitDependOnLC, CondDependOnLC);
9751
9752 if (!Diff.isUsable())
9753 return std::make_pair(x: nullptr, y: nullptr);
9754
9755 // ((Upper - Lower [- 1]) / Step) * Step
9756 // Parentheses (for dumping/debugging purposes only).
9757 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9758 if (!Diff.isUsable())
9759 return std::make_pair(x: nullptr, y: nullptr);
9760
9761 ExprResult NewStep = tryBuildCapture(SemaRef, Capture: Step, Captures, Name: ".new_step");
9762 if (!NewStep.isUsable())
9763 return std::make_pair(x: nullptr, y: nullptr);
9764 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Mul, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
9765 if (!Diff.isUsable())
9766 return std::make_pair(x: nullptr, y: nullptr);
9767
9768 // Parentheses (for dumping/debugging purposes only).
9769 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9770 if (!Diff.isUsable())
9771 return std::make_pair(x: nullptr, y: nullptr);
9772
9773 // Convert to the ptrdiff_t, if original type is pointer.
9774 if (VarType->isAnyPointerType() &&
9775 !SemaRef.Context.hasSameType(
9776 T1: Diff.get()->getType(),
9777 T2: SemaRef.Context.getUnsignedPointerDiffType())) {
9778 Diff = SemaRef.PerformImplicitConversion(
9779 From: Diff.get(), ToType: SemaRef.Context.getUnsignedPointerDiffType(),
9780 Action: AssignmentAction::Converting, /*AllowExplicit=*/true);
9781 }
9782 if (!Diff.isUsable())
9783 return std::make_pair(x: nullptr, y: nullptr);
9784
9785 if (*TestIsLessOp) {
9786 // MinExpr = Lower;
9787 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9788 Diff = SemaRef.BuildBinOp(
9789 S, OpLoc: DefaultLoc, Opc: BO_Add,
9790 LHSExpr: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Lower).get(),
9791 RHSExpr: Diff.get());
9792 if (!Diff.isUsable())
9793 return std::make_pair(x: nullptr, y: nullptr);
9794 } else {
9795 // MaxExpr = Upper;
9796 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9797 Diff = SemaRef.BuildBinOp(
9798 S, OpLoc: DefaultLoc, Opc: BO_Sub,
9799 LHSExpr: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Upper).get(),
9800 RHSExpr: Diff.get());
9801 if (!Diff.isUsable())
9802 return std::make_pair(x: nullptr, y: nullptr);
9803 }
9804
9805 // Convert to the original type.
9806 if (SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: VarType))
9807 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: VarType,
9808 Action: AssignmentAction::Converting,
9809 /*AllowExplicit=*/true);
9810 if (!Diff.isUsable())
9811 return std::make_pair(x: nullptr, y: nullptr);
9812
9813 Sema::TentativeAnalysisScope Trap(SemaRef);
9814 Diff = SemaRef.ActOnFinishFullExpr(Expr: Diff.get(), /*DiscardedValue=*/false);
9815 if (!Diff.isUsable())
9816 return std::make_pair(x: nullptr, y: nullptr);
9817
9818 if (*TestIsLessOp)
9819 MaxExpr = Diff.get();
9820 else
9821 MinExpr = Diff.get();
9822
9823 return std::make_pair(x&: MinExpr, y&: MaxExpr);
9824}
9825
9826Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9827 if (InitDependOnLC || CondDependOnLC)
9828 return Condition;
9829 return nullptr;
9830}
9831
9832Expr *OpenMPIterationSpaceChecker::buildPreCond(
9833 Scope *S, Expr *Cond,
9834 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9835 // Do not build a precondition when the condition/initialization is dependent
9836 // to prevent pessimistic early loop exit.
9837 // TODO: this can be improved by calculating min/max values but not sure that
9838 // it will be very effective.
9839 if (CondDependOnLC || InitDependOnLC)
9840 return SemaRef
9841 .PerformImplicitConversion(
9842 From: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get(),
9843 ToType: SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
9844 /*AllowExplicit=*/true)
9845 .get();
9846
9847 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9848 Sema::TentativeAnalysisScope Trap(SemaRef);
9849
9850 ExprResult NewLB = tryBuildCapture(SemaRef, Capture: LB, Captures);
9851 ExprResult NewUB = tryBuildCapture(SemaRef, Capture: UB, Captures);
9852 if (!NewLB.isUsable() || !NewUB.isUsable())
9853 return nullptr;
9854
9855 ExprResult CondExpr =
9856 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc,
9857 Opc: *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9858 : (TestIsStrictOp ? BO_GT : BO_GE),
9859 LHSExpr: NewLB.get(), RHSExpr: NewUB.get());
9860 if (CondExpr.isUsable()) {
9861 if (!SemaRef.Context.hasSameUnqualifiedType(T1: CondExpr.get()->getType(),
9862 T2: SemaRef.Context.BoolTy))
9863 CondExpr = SemaRef.PerformImplicitConversion(
9864 From: CondExpr.get(), ToType: SemaRef.Context.BoolTy,
9865 /*Action=*/AssignmentAction::Casting,
9866 /*AllowExplicit=*/true);
9867 }
9868
9869 // Otherwise use original loop condition and evaluate it in runtime.
9870 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9871}
9872
9873/// Build reference expression to the counter be used for codegen.
9874DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9875 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9876 DSAStackTy &DSA) const {
9877 auto *VD = dyn_cast<VarDecl>(Val: LCDecl);
9878 if (!VD) {
9879 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(D: LCDecl);
9880 DeclRefExpr *Ref = buildDeclRefExpr(
9881 S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(), Loc: DefaultLoc);
9882 const DSAStackTy::DSAVarData Data =
9883 DSA.getTopDSA(D: LCDecl, /*FromParent=*/false);
9884 // If the loop control decl is explicitly marked as private, do not mark it
9885 // as captured again.
9886 if (!isOpenMPPrivate(Kind: Data.CKind) || !Data.RefExpr)
9887 Captures.insert(KV: std::make_pair(x: LCRef, y&: Ref));
9888 return Ref;
9889 }
9890 return cast<DeclRefExpr>(Val: LCRef);
9891}
9892
9893Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9894 if (LCDecl && !LCDecl->isInvalidDecl()) {
9895 QualType Type = LCDecl->getType().getNonReferenceType();
9896 VarDecl *PrivateVar = buildVarDecl(
9897 SemaRef, Loc: DefaultLoc, Type, Name: LCDecl->getName(),
9898 Attrs: LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9899 OrigRef: isa<VarDecl>(Val: LCDecl)
9900 ? buildDeclRefExpr(S&: SemaRef, D: cast<VarDecl>(Val: LCDecl), Ty: Type, Loc: DefaultLoc)
9901 : nullptr);
9902 if (PrivateVar->isInvalidDecl())
9903 return nullptr;
9904 return buildDeclRefExpr(S&: SemaRef, D: PrivateVar, Ty: Type, Loc: DefaultLoc);
9905 }
9906 return nullptr;
9907}
9908
9909/// Build initialization of the counter to be used for codegen.
9910Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9911
9912/// Build step of the counter be used for codegen.
9913Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9914
9915Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9916 Scope *S, Expr *Counter,
9917 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9918 Expr *Inc, OverloadedOperatorKind OOK) {
9919 Expr *Cnt = SemaRef.DefaultLvalueConversion(E: Counter).get();
9920 if (!Cnt)
9921 return nullptr;
9922 if (Inc) {
9923 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9924 "Expected only + or - operations for depend clauses.");
9925 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9926 Cnt = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BOK, LHSExpr: Cnt, RHSExpr: Inc).get();
9927 if (!Cnt)
9928 return nullptr;
9929 }
9930 QualType VarType = LCDecl->getType().getNonReferenceType();
9931 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9932 !SemaRef.getLangOpts().CPlusPlus)
9933 return nullptr;
9934 // Upper - Lower
9935 Expr *Upper =
9936 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, Capture: LB, Captures).get();
9937 Expr *Lower =
9938 *TestIsLessOp ? tryBuildCapture(SemaRef, Capture: LB, Captures).get() : Cnt;
9939 if (!Upper || !Lower)
9940 return nullptr;
9941
9942 ExprResult Diff =
9943 calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType,
9944 /*TestIsStrictOp=*/false, /*RoundToStep=*/false,
9945 Captures, InitDependOnLC, CondDependOnLC);
9946 if (!Diff.isUsable())
9947 return nullptr;
9948
9949 return Diff.get();
9950}
9951} // namespace
9952
9953void SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc,
9954 Stmt *Init) {
9955 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9956 assert(Init && "Expected loop in canonical form.");
9957 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9958 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9959 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9960 return;
9961
9962 DSAStack->loopStart();
9963 llvm::SmallPtrSet<const Decl *, 1> EmptyDeclSet;
9964 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9965 *DSAStack, ForLoc, EmptyDeclSet,
9966 EmptyDeclSet);
9967 if (!ISC.checkAndSetInit(S: Init, /*EmitDiags=*/false)) {
9968 if (ValueDecl *D = ISC.getLoopDecl()) {
9969 auto *VD = dyn_cast<VarDecl>(Val: D);
9970 DeclRefExpr *PrivateRef = nullptr;
9971 if (!VD) {
9972 if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9973 VD = Private;
9974 } else {
9975 PrivateRef = buildCapture(S&: SemaRef, D, CaptureExpr: ISC.getLoopDeclRefExpr(),
9976 /*WithInit=*/false);
9977 VD = cast<VarDecl>(Val: PrivateRef->getDecl());
9978 }
9979 }
9980 DSAStack->addLoopControlVariable(D, Capture: VD);
9981 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9982 if (LD != D->getCanonicalDecl()) {
9983 DSAStack->resetPossibleLoopCounter();
9984 if (auto *Var = dyn_cast_or_null<VarDecl>(Val: LD))
9985 SemaRef.MarkDeclarationsReferencedInExpr(E: buildDeclRefExpr(
9986 S&: SemaRef, D: const_cast<VarDecl *>(Var),
9987 Ty: Var->getType().getNonLValueExprType(Context: getASTContext()), Loc: ForLoc,
9988 /*RefersToCapture=*/true));
9989 }
9990 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9991 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9992 // associated for-loop of a simd construct with just one associated
9993 // for-loop may be listed in a linear clause with a constant-linear-step
9994 // that is the increment of the associated for-loop. The loop iteration
9995 // variable(s) in the associated for-loop(s) of a for or parallel for
9996 // construct may be listed in a private or lastprivate clause.
9997 DSAStackTy::DSAVarData DVar =
9998 DSAStack->getTopDSA(D, /*FromParent=*/false);
9999 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
10000 // is declared in the loop and it is predetermined as a private.
10001 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
10002 OpenMPClauseKind PredeterminedCKind =
10003 isOpenMPSimdDirective(DKind)
10004 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
10005 : OMPC_private;
10006 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
10007 return getLeafConstructsOrSelf(D: DK).back() == OMPD_taskloop;
10008 };
10009 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
10010 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
10011 (getLangOpts().OpenMP <= 45 ||
10012 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
10013 ((isOpenMPWorksharingDirective(DKind) ||
10014 IsOpenMPTaskloopDirective(DKind) ||
10015 isOpenMPDistributeDirective(DKind)) &&
10016 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
10017 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
10018 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
10019 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
10020 Diag(Loc: Init->getBeginLoc(), DiagID: diag::err_omp_loop_var_dsa)
10021 << getOpenMPClauseNameForDiag(C: DVar.CKind)
10022 << getOpenMPDirectiveName(D: DKind, V: OMPVersion)
10023 << getOpenMPClauseNameForDiag(C: PredeterminedCKind);
10024 if (DVar.RefExpr == nullptr)
10025 DVar.CKind = PredeterminedCKind;
10026 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
10027 } else if (LoopDeclRefExpr) {
10028 // Make the loop iteration variable private (for worksharing
10029 // constructs), linear (for simd directives with the only one
10030 // associated loop) or lastprivate (for simd directives with several
10031 // collapsed or ordered loops).
10032 if (DVar.CKind == OMPC_unknown)
10033 DSAStack->addDSA(D, E: LoopDeclRefExpr, A: PredeterminedCKind, PrivateCopy: PrivateRef);
10034 }
10035 }
10036 }
10037 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
10038}
10039
10040namespace {
10041// Utility for OpenMP doacross clause kind
10042class OMPDoacrossKind {
10043public:
10044 bool isSource(const OMPDoacrossClause *C) {
10045 return C->getDependenceType() == OMPC_DOACROSS_source ||
10046 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
10047 }
10048 bool isSink(const OMPDoacrossClause *C) {
10049 return C->getDependenceType() == OMPC_DOACROSS_sink;
10050 }
10051 bool isSinkIter(const OMPDoacrossClause *C) {
10052 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
10053 }
10054};
10055} // namespace
10056/// Called on a for stmt to check and extract its iteration space
10057/// for further processing (such as collapsing).
10058static bool checkOpenMPIterationSpace(
10059 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
10060 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
10061 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
10062 Expr *OrderedLoopCountExpr,
10063 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
10064 llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
10065 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
10066 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls,
10067 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars) {
10068 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
10069
10070 // See the tile reinterpretation design note in ActOnOpenMPTileDirective.
10071 // If the loop carries the hint, analyze its rectangular form instead.
10072 //
10073 // Only directives that emit the per-iteration body guard (i.e. those going
10074 // through EmitOMPLoopBody's finals-conditions handling) may reinterpret the
10075 // loop; a loop transformation such as an enclosing 'tile' has nowhere to put
10076 // the overshoot guard, so for those the stored min-bounded form is analyzed
10077 // exactly as it is on a build without this hint.
10078 // OpenMP [2.9.1, Canonical Loop Form]
10079 // for (init-expr; test-expr; incr-expr) structured-block
10080 // for (range-decl: range-expr) structured-block
10081 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(Val: S))
10082 S = CanonLoop->getLoopStmt();
10083 const OMPInvariantPredicateBoundAttr *IntraTileHint =
10084 OMPLoopBasedDirective::getIntraTileHint(S);
10085 if (IntraTileHint)
10086 S = OMPLoopBasedDirective::ignoreIntraTileHint(S);
10087 Expr *TileRectCond = nullptr;
10088 Expr *TileBodyPredicate = nullptr;
10089 Expr *TileTripCount = nullptr;
10090 if (IntraTileHint && !isOpenMPLoopTransformationDirective(DKind)) {
10091 TileRectCond = IntraTileHint->getRectCond();
10092 TileBodyPredicate = IntraTileHint->getPredicate();
10093 TileTripCount = IntraTileHint->getTileSize();
10094 }
10095 auto *For = dyn_cast_or_null<ForStmt>(Val: S);
10096 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(Val: S);
10097 // Ranged for is supported only in OpenMP 5.0.
10098 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
10099 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
10100 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_not_for)
10101 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
10102 << getOpenMPDirectiveName(D: DKind, V: OMPVersion) << TotalNestedLoopCount
10103 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
10104 if (TotalNestedLoopCount > 1) {
10105 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
10106 SemaRef.Diag(Loc: DSA.getConstructLoc(),
10107 DiagID: diag::note_omp_collapse_ordered_expr)
10108 << 2 << CollapseLoopCountExpr->getSourceRange()
10109 << OrderedLoopCountExpr->getSourceRange();
10110 else if (CollapseLoopCountExpr)
10111 SemaRef.Diag(Loc: CollapseLoopCountExpr->getExprLoc(),
10112 DiagID: diag::note_omp_collapse_ordered_expr)
10113 << 0 << CollapseLoopCountExpr->getSourceRange();
10114 else if (OrderedLoopCountExpr)
10115 SemaRef.Diag(Loc: OrderedLoopCountExpr->getExprLoc(),
10116 DiagID: diag::note_omp_collapse_ordered_expr)
10117 << 1 << OrderedLoopCountExpr->getSourceRange();
10118 }
10119 return true;
10120 }
10121 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
10122 "No loop body.");
10123 // Postpone analysis in dependent contexts for ranged for loops.
10124 if (CXXFor && SemaRef.CurContext->isDependentContext())
10125 return false;
10126
10127 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
10128 For ? For->getForLoc() : CXXFor->getForLoc(),
10129 CollapsedLoopVarDecls,
10130 CollapsedLoopInductionVars);
10131
10132 // Check init.
10133 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
10134 if (ISC.checkAndSetInit(S: Init))
10135 return true;
10136
10137 bool HasErrors = false;
10138
10139 // Condition used for iteration-space analysis: the rectangular hint when
10140 // reinterpreting an intra-tile loop, otherwise the loop's own condition.
10141 Expr *EffectiveCond =
10142 TileRectCond ? TileRectCond : (For ? For->getCond() : CXXFor->getCond());
10143
10144 // Check loop variable's type.
10145 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
10146 // OpenMP [2.6, Canonical Loop Form]
10147 // Var is one of the following:
10148 // A variable of signed or unsigned integer type.
10149 // For C++, a variable of a random access iterator type.
10150 // For C, a variable of a pointer type.
10151 QualType VarType = LCDecl->getType().getNonReferenceType();
10152 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
10153 !VarType->isPointerType() &&
10154 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
10155 SemaRef.Diag(Loc: Init->getBeginLoc(), DiagID: diag::err_omp_loop_variable_type)
10156 << SemaRef.getLangOpts().CPlusPlus;
10157 HasErrors = true;
10158 }
10159
10160 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
10161 // a Construct
10162 // The loop iteration variable(s) in the associated for-loop(s) of a for or
10163 // parallel for construct is (are) private.
10164 // The loop iteration variable in the associated for-loop of a simd
10165 // construct with just one associated for-loop is linear with a
10166 // constant-linear-step that is the increment of the associated for-loop.
10167 // Exclude loop var from the list of variables with implicitly defined data
10168 // sharing attributes.
10169 VarsWithImplicitDSA.erase(Val: LCDecl);
10170
10171 assert((isOpenMPLoopDirective(DKind) ||
10172 isOpenMPCanonicalLoopSequenceTransformationDirective(DKind)) &&
10173 "DSA for non-loop vars");
10174
10175 // Check test-expr.
10176 HasErrors |= ISC.checkAndSetCond(S: EffectiveCond);
10177
10178 // Check incr-expr.
10179 HasErrors |= ISC.checkAndSetInc(S: For ? For->getInc() : CXXFor->getInc());
10180 }
10181
10182 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
10183 return HasErrors;
10184
10185 // Build the loop's iteration space representation.
10186 //
10187 // A reinterpreted intra-tile loop takes all three of these from the hint
10188 // instead of deriving them: the precondition is trivially true (the floor
10189 // loop's own precondition already covers an empty iteration space), the trip
10190 // count is the constant tile size, and any overshoot on the remainder tile
10191 // is handled by the body guard.
10192 if (TileRectCond) {
10193 ResultIterSpaces[CurrentNestedLoopCount].PreCond =
10194 SemaRef
10195 .PerformImplicitConversion(
10196 From: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get(),
10197 ToType: SemaRef.Context.BoolTy, Action: AssignmentAction::Casting,
10198 /*AllowExplicit=*/true)
10199 .get();
10200 ResultIterSpaces[CurrentNestedLoopCount].NumIterations = TileTripCount;
10201 } else {
10202 ResultIterSpaces[CurrentNestedLoopCount].PreCond =
10203 ISC.buildPreCond(S: DSA.getCurScope(), Cond: EffectiveCond, Captures);
10204 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
10205 ISC.buildNumIterations(S: DSA.getCurScope(), ResultIterSpaces,
10206 LimitedType: (isOpenMPWorksharingDirective(DKind) ||
10207 isOpenMPGenericLoopDirective(DKind) ||
10208 isOpenMPTaskLoopDirective(DKind) ||
10209 isOpenMPDistributeDirective(DKind) ||
10210 isOpenMPLoopTransformationDirective(DKind)),
10211 Captures);
10212 }
10213 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
10214 ISC.buildCounterVar(Captures, DSA);
10215 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
10216 ISC.buildPrivateCounterVar();
10217 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
10218 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
10219 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
10220 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
10221 ISC.getConditionSrcRange();
10222 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
10223 ISC.getIncrementSrcRange();
10224 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
10225 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
10226 ISC.isStrictTestOp();
10227 std::tie(args&: ResultIterSpaces[CurrentNestedLoopCount].MinValue,
10228 args&: ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
10229 ISC.buildMinMaxValues(S: DSA.getCurScope(), Captures);
10230 if (TileRectCond) {
10231 // Floor is not a registered loop-control variable, so this helper is null.
10232 // Use the overshoot guard only (null when N % T == 0).
10233 assert(!ISC.buildFinalCondition(DSA.getCurScope()) &&
10234 "intra-tile floor is not a registered loop-control variable");
10235 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition = TileBodyPredicate;
10236
10237 // Re-read .floor.iv each outer trip. Match it to an outer collapsed
10238 // counter.
10239 bool FoundFloor = false;
10240 if (Expr *InitExpr = ResultIterSpaces[CurrentNestedLoopCount].CounterInit) {
10241 if (const auto *LBRef =
10242 dyn_cast<DeclRefExpr>(Val: InitExpr->IgnoreParenImpCasts())) {
10243 const Decl *FloorDecl = LBRef->getDecl()->getCanonicalDecl();
10244 for (unsigned K = 0; K < CurrentNestedLoopCount; ++K) {
10245 const auto *CV =
10246 dyn_cast_or_null<DeclRefExpr>(Val: ResultIterSpaces[K].CounterVar);
10247 if (CV && CV->getDecl()->getCanonicalDecl() == FloorDecl) {
10248 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB = true;
10249 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx = K + 1;
10250 FoundFloor = true;
10251 break;
10252 }
10253 }
10254 }
10255 }
10256 if (!FoundFloor) {
10257 // The floor this intra-tile loop starts from is not one of the
10258 // collapsed counters: it is assigned in the body of an enclosing
10259 // transformed loop, so the collapsed nest would read a stale value
10260 // instead of recomputing it per iteration. Diagnose to avoid silently
10261 // producing the wrong iteration space.
10262 SemaRef.Diag(Loc: ISC.getInitSrcRange().getBegin(),
10263 DiagID: diag::err_omp_collapse_stacked_tile)
10264 << /*Collapse=*/0;
10265 return true;
10266 }
10267 } else {
10268 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
10269 ISC.buildFinalCondition(S: DSA.getCurScope());
10270 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
10271 ISC.doesInitDependOnLC();
10272 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
10273 ISC.doesCondDependOnLC();
10274 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
10275 ISC.getLoopDependentIdx();
10276 }
10277
10278 HasErrors |=
10279 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
10280 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
10281 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
10282 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
10283 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
10284 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
10285 if (!HasErrors && DSA.isOrderedRegion()) {
10286 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
10287 if (CurrentNestedLoopCount <
10288 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
10289 DSA.getOrderedRegionParam().second->setLoopNumIterations(
10290 NumLoop: CurrentNestedLoopCount,
10291 NumIterations: ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
10292 DSA.getOrderedRegionParam().second->setLoopCounter(
10293 NumLoop: CurrentNestedLoopCount,
10294 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
10295 }
10296 }
10297 for (auto &Pair : DSA.getDoacrossDependClauses()) {
10298 auto *DependC = dyn_cast<OMPDependClause>(Val: Pair.first);
10299 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Val: Pair.first);
10300 unsigned NumLoops =
10301 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
10302 if (CurrentNestedLoopCount >= NumLoops) {
10303 // Erroneous case - clause has some problems.
10304 continue;
10305 }
10306 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
10307 Pair.second.size() <= CurrentNestedLoopCount) {
10308 // Erroneous case - clause has some problems.
10309 DependC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: nullptr);
10310 continue;
10311 }
10312 OMPDoacrossKind ODK;
10313 if (DoacrossC && ODK.isSink(C: DoacrossC) &&
10314 Pair.second.size() <= CurrentNestedLoopCount) {
10315 // Erroneous case - clause has some problems.
10316 DoacrossC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: nullptr);
10317 continue;
10318 }
10319 Expr *CntValue;
10320 SourceLocation DepLoc =
10321 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
10322 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
10323 (DoacrossC && ODK.isSource(C: DoacrossC)))
10324 CntValue = ISC.buildOrderedLoopData(
10325 S: DSA.getCurScope(),
10326 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
10327 Loc: DepLoc);
10328 else if (DoacrossC && ODK.isSinkIter(C: DoacrossC)) {
10329 Expr *Cnt = SemaRef
10330 .DefaultLvalueConversion(
10331 E: ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
10332 .get();
10333 if (!Cnt)
10334 continue;
10335 // build CounterVar - 1
10336 Expr *Inc =
10337 SemaRef.ActOnIntegerConstant(Loc: DoacrossC->getColonLoc(), /*Val=*/1)
10338 .get();
10339 CntValue = ISC.buildOrderedLoopData(
10340 S: DSA.getCurScope(),
10341 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
10342 Loc: DepLoc, Inc, OOK: clang::OO_Minus);
10343 } else
10344 CntValue = ISC.buildOrderedLoopData(
10345 S: DSA.getCurScope(),
10346 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
10347 Loc: DepLoc, Inc: Pair.second[CurrentNestedLoopCount].first,
10348 OOK: Pair.second[CurrentNestedLoopCount].second);
10349 if (DependC)
10350 DependC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: CntValue);
10351 else
10352 DoacrossC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: CntValue);
10353 }
10354 }
10355 // Record the loop induction variable for nested loop reuse checking.
10356 if (CurrentNestedLoopCount < NestedLoopCount && !HasErrors) {
10357 if (const ValueDecl *LCDecl = ISC.getLoopDecl())
10358 CollapsedLoopInductionVars.insert(Ptr: LCDecl->getCanonicalDecl());
10359 }
10360 return HasErrors;
10361}
10362
10363/// Build 'VarRef = Start.
10364static ExprResult
10365buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
10366 ExprResult Start, bool IsNonRectangularLB,
10367 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
10368 // Build 'VarRef = Start.
10369 ExprResult NewStart = IsNonRectangularLB
10370 ? Start.get()
10371 : tryBuildCapture(SemaRef, Capture: Start.get(), Captures);
10372 if (!NewStart.isUsable())
10373 return ExprError();
10374 if (!SemaRef.Context.hasSameType(T1: NewStart.get()->getType(),
10375 T2: VarRef.get()->getType())) {
10376 NewStart = SemaRef.PerformImplicitConversion(
10377 From: NewStart.get(), ToType: VarRef.get()->getType(), Action: AssignmentAction::Converting,
10378 /*AllowExplicit=*/true);
10379 if (!NewStart.isUsable())
10380 return ExprError();
10381 }
10382
10383 ExprResult Init =
10384 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: NewStart.get());
10385 return Init;
10386}
10387
10388/// Build 'VarRef = Start + Iter * Step'.
10389static ExprResult buildCounterUpdate(
10390 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
10391 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
10392 bool IsNonRectangularLB,
10393 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
10394 // Add parentheses (for debugging purposes only).
10395 Iter = SemaRef.ActOnParenExpr(L: Loc, R: Loc, E: Iter.get());
10396 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
10397 !Step.isUsable())
10398 return ExprError();
10399
10400 ExprResult NewStep = Step;
10401 if (Captures)
10402 NewStep = tryBuildCapture(SemaRef, Capture: Step.get(), Captures&: *Captures);
10403 if (NewStep.isInvalid())
10404 return ExprError();
10405 ExprResult Update =
10406 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Mul, LHSExpr: Iter.get(), RHSExpr: NewStep.get());
10407 if (!Update.isUsable())
10408 return ExprError();
10409
10410 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
10411 // 'VarRef = Start (+|-) Iter * Step'.
10412 if (!Start.isUsable())
10413 return ExprError();
10414 ExprResult NewStart = SemaRef.ActOnParenExpr(L: Loc, R: Loc, E: Start.get());
10415 if (!NewStart.isUsable())
10416 return ExprError();
10417 if (Captures && !IsNonRectangularLB)
10418 NewStart = tryBuildCapture(SemaRef, Capture: Start.get(), Captures&: *Captures);
10419 if (NewStart.isInvalid())
10420 return ExprError();
10421
10422 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
10423 ExprResult SavedUpdate = Update;
10424 ExprResult UpdateVal;
10425 if (VarRef.get()->getType()->isOverloadableType() ||
10426 NewStart.get()->getType()->isOverloadableType() ||
10427 Update.get()->getType()->isOverloadableType()) {
10428 Sema::TentativeAnalysisScope Trap(SemaRef);
10429
10430 Update =
10431 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: NewStart.get());
10432 if (Update.isUsable()) {
10433 UpdateVal =
10434 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: Subtract ? BO_SubAssign : BO_AddAssign,
10435 LHSExpr: VarRef.get(), RHSExpr: SavedUpdate.get());
10436 if (UpdateVal.isUsable()) {
10437 Update = SemaRef.CreateBuiltinBinOp(OpLoc: Loc, Opc: BO_Comma, LHSExpr: Update.get(),
10438 RHSExpr: UpdateVal.get());
10439 }
10440 }
10441 }
10442
10443 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
10444 if (!Update.isUsable() || !UpdateVal.isUsable()) {
10445 Update = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: Subtract ? BO_Sub : BO_Add,
10446 LHSExpr: NewStart.get(), RHSExpr: SavedUpdate.get());
10447 if (!Update.isUsable())
10448 return ExprError();
10449
10450 if (!SemaRef.Context.hasSameType(T1: Update.get()->getType(),
10451 T2: VarRef.get()->getType())) {
10452 Update = SemaRef.PerformImplicitConversion(
10453 From: Update.get(), ToType: VarRef.get()->getType(), Action: AssignmentAction::Converting,
10454 /*AllowExplicit=*/true);
10455 if (!Update.isUsable())
10456 return ExprError();
10457 }
10458
10459 Update = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: Update.get());
10460 }
10461 return Update;
10462}
10463
10464/// Convert integer expression \a E to make it have at least \a Bits
10465/// bits.
10466static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
10467 if (E == nullptr)
10468 return ExprError();
10469 ASTContext &C = SemaRef.Context;
10470 QualType OldType = E->getType();
10471 unsigned HasBits = C.getTypeSize(T: OldType);
10472 if (HasBits >= Bits)
10473 return ExprResult(E);
10474 // OK to convert to signed, because new type has more bits than old.
10475 QualType NewType = C.getIntTypeForBitwidth(DestWidth: Bits, /*Signed=*/true);
10476 return SemaRef.PerformImplicitConversion(
10477 From: E, ToType: NewType, Action: AssignmentAction::Converting, /*AllowExplicit=*/true);
10478}
10479
10480/// Check if the given expression \a E is a constant integer that fits
10481/// into \a Bits bits.
10482static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
10483 if (E == nullptr)
10484 return false;
10485 if (std::optional<llvm::APSInt> Result =
10486 E->getIntegerConstantExpr(Ctx: SemaRef.Context))
10487 return Signed ? Result->isSignedIntN(N: Bits) : Result->isIntN(N: Bits);
10488 return false;
10489}
10490
10491/// Build preinits statement for the given declarations.
10492static Stmt *buildPreInits(ASTContext &Context,
10493 MutableArrayRef<Decl *> PreInits) {
10494 if (!PreInits.empty()) {
10495 return new (Context) DeclStmt(
10496 DeclGroupRef::Create(C&: Context, Decls: PreInits.begin(), NumDecls: PreInits.size()),
10497 SourceLocation(), SourceLocation());
10498 }
10499 return nullptr;
10500}
10501
10502/// Append the \p Item or the content of a CompoundStmt to the list \p
10503/// TargetList.
10504///
10505/// A CompoundStmt is used as container in case multiple statements need to be
10506/// stored in lieu of using an explicit list. Flattening is necessary because
10507/// contained DeclStmts need to be visible after the execution of the list. Used
10508/// for OpenMP pre-init declarations/statements.
10509static void appendFlattenedStmtList(SmallVectorImpl<Stmt *> &TargetList,
10510 Stmt *Item) {
10511 // nullptr represents an empty list.
10512 if (!Item)
10513 return;
10514
10515 if (auto *CS = dyn_cast<CompoundStmt>(Val: Item))
10516 llvm::append_range(C&: TargetList, R: CS->body());
10517 else
10518 TargetList.push_back(Elt: Item);
10519}
10520
10521/// Build preinits statement for the given declarations.
10522static Stmt *
10523buildPreInits(ASTContext &Context,
10524 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
10525 if (!Captures.empty()) {
10526 SmallVector<Decl *, 16> PreInits;
10527 for (const auto &Pair : Captures)
10528 PreInits.push_back(Elt: Pair.second->getDecl());
10529 return buildPreInits(Context, PreInits);
10530 }
10531 return nullptr;
10532}
10533
10534/// Build pre-init statement for the given statements.
10535static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
10536 if (PreInits.empty())
10537 return nullptr;
10538
10539 SmallVector<Stmt *> Stmts;
10540 for (Stmt *S : PreInits)
10541 appendFlattenedStmtList(TargetList&: Stmts, Item: S);
10542 return CompoundStmt::Create(C: Context, Stmts: PreInits, FPFeatures: FPOptionsOverride(), LB: {}, RB: {});
10543}
10544
10545/// Build postupdate expression for the given list of postupdates expressions.
10546static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
10547 Expr *PostUpdate = nullptr;
10548 if (!PostUpdates.empty()) {
10549 for (Expr *E : PostUpdates) {
10550 Expr *ConvE = S.BuildCStyleCastExpr(
10551 LParenLoc: E->getExprLoc(),
10552 Ty: S.Context.getTrivialTypeSourceInfo(T: S.Context.VoidTy),
10553 RParenLoc: E->getExprLoc(), Op: E)
10554 .get();
10555 PostUpdate = PostUpdate
10556 ? S.CreateBuiltinBinOp(OpLoc: ConvE->getExprLoc(), Opc: BO_Comma,
10557 LHSExpr: PostUpdate, RHSExpr: ConvE)
10558 .get()
10559 : ConvE;
10560 }
10561 }
10562 return PostUpdate;
10563}
10564
10565/// Look for variables declared in the body parts of a for-loop nest. Used
10566/// for verifying loop nest structure before performing a loop collapse
10567/// operation.
10568class ForVarDeclFinder : public DynamicRecursiveASTVisitor {
10569 int NestingDepth = 0;
10570 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
10571
10572public:
10573 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
10574 : VarDecls(VD) {}
10575
10576 bool VisitForStmt(ForStmt *F) override {
10577 ++NestingDepth;
10578 TraverseStmt(S: F->getBody());
10579 --NestingDepth;
10580 return false;
10581 }
10582
10583 bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override {
10584 ++NestingDepth;
10585 TraverseStmt(S: RF->getBody());
10586 --NestingDepth;
10587 return false;
10588 }
10589
10590 bool VisitVarDecl(VarDecl *D) override {
10591 Decl *C = D->getCanonicalDecl();
10592 if (NestingDepth > 0)
10593 VarDecls.insert(Ptr: C);
10594 return true;
10595 }
10596};
10597
10598/// Called on a for stmt to check itself and nested loops (if any).
10599/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
10600/// number of collapsed loops otherwise.
10601static unsigned
10602checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
10603 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
10604 DSAStackTy &DSA,
10605 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
10606 OMPLoopBasedDirective::HelperExprs &Built) {
10607 // If either of the loop expressions exist and contain errors, we bail out
10608 // early because diagnostics have already been emitted and we can't reliably
10609 // check more about the loop.
10610 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
10611 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
10612 return 0;
10613
10614 unsigned NestedLoopCount = 1;
10615 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
10616 !isOpenMPLoopTransformationDirective(DKind);
10617 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
10618 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopInductionVars;
10619
10620 if (CollapseLoopCountExpr) {
10621 // Found 'collapse' clause - calculate collapse number.
10622 Expr::EvalResult Result;
10623 if (!CollapseLoopCountExpr->isInstantiationDependent() &&
10624 CollapseLoopCountExpr->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext())) {
10625 NestedLoopCount = Result.Val.getInt().getLimitedValue();
10626
10627 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
10628 FVDF.TraverseStmt(S: AStmt);
10629 } else {
10630 Built.clear(/*Size=*/1);
10631 return 1;
10632 }
10633 }
10634 unsigned OrderedLoopCount = 1;
10635 if (OrderedLoopCountExpr) {
10636 // Found 'ordered' clause - calculate collapse number.
10637 Expr::EvalResult EVResult;
10638 if (!OrderedLoopCountExpr->isInstantiationDependent() &&
10639 OrderedLoopCountExpr->EvaluateAsInt(Result&: EVResult,
10640 Ctx: SemaRef.getASTContext())) {
10641 llvm::APSInt Result = EVResult.Val.getInt();
10642 if (Result.getLimitedValue() < NestedLoopCount) {
10643 SemaRef.Diag(Loc: OrderedLoopCountExpr->getExprLoc(),
10644 DiagID: diag::err_omp_wrong_ordered_loop_count)
10645 << OrderedLoopCountExpr->getSourceRange();
10646 SemaRef.Diag(Loc: CollapseLoopCountExpr->getExprLoc(),
10647 DiagID: diag::note_collapse_loop_count)
10648 << CollapseLoopCountExpr->getSourceRange();
10649 }
10650 OrderedLoopCount = Result.getLimitedValue();
10651 } else {
10652 Built.clear(/*Size=*/1);
10653 return 1;
10654 }
10655 }
10656 // This is helper routine for loop directives (e.g., 'for', 'simd',
10657 // 'for simd', etc.).
10658 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
10659 unsigned NumLoops = std::max(a: OrderedLoopCount, b: NestedLoopCount);
10660 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
10661 if (!OMPLoopBasedDirective::doForAllLoops(
10662 CurStmt: AStmt->IgnoreContainers(
10663 IgnoreCaptured: !isOpenMPCanonicalLoopNestTransformationDirective(DKind)),
10664 TryImperfectlyNestedLoops: SupportsNonPerfectlyNested, NumLoops,
10665 Callback: [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
10666 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
10667 &IterSpaces, &Captures, &CollapsedLoopVarDecls,
10668 &CollapsedLoopInductionVars](unsigned Cnt, Stmt *Loop,
10669 Stmt *HintWrapper) {
10670 Stmt *CurStmt = HintWrapper ? HintWrapper : Loop;
10671 if (checkOpenMPIterationSpace(
10672 DKind, S: CurStmt, SemaRef, DSA, CurrentNestedLoopCount: Cnt, NestedLoopCount,
10673 TotalNestedLoopCount: NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
10674 VarsWithImplicitDSA, ResultIterSpaces: IterSpaces, Captures,
10675 CollapsedLoopVarDecls, CollapsedLoopInductionVars))
10676 return true;
10677 if (Cnt > 0 && Cnt >= NestedLoopCount &&
10678 IterSpaces[Cnt].CounterVar) {
10679 // Handle initialization of captured loop iterator variables.
10680 auto *DRE = cast<DeclRefExpr>(Val: IterSpaces[Cnt].CounterVar);
10681 if (isa<OMPCapturedExprDecl>(Val: DRE->getDecl())) {
10682 Captures[DRE] = DRE;
10683 }
10684 }
10685 return false;
10686 },
10687 OnTransformationCallback: [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
10688 Stmt *DependentPreInits = Transform->getPreInits();
10689 if (!DependentPreInits)
10690 return;
10691
10692 // Search for pre-init declared variables that need to be captured
10693 // to be referenceable inside the directive.
10694 SmallVector<Stmt *> Constituents;
10695 appendFlattenedStmtList(TargetList&: Constituents, Item: DependentPreInits);
10696 for (Stmt *S : Constituents) {
10697 if (auto *DC = dyn_cast<DeclStmt>(Val: S)) {
10698 for (Decl *C : DC->decls()) {
10699 auto *D = cast<VarDecl>(Val: C);
10700 DeclRefExpr *Ref = buildDeclRefExpr(
10701 S&: SemaRef, D, Ty: D->getType().getNonReferenceType(),
10702 Loc: cast<OMPExecutableDirective>(Val: Transform->getDirective())
10703 ->getBeginLoc());
10704 Captures[Ref] = Ref;
10705 }
10706 }
10707 }
10708 }))
10709 return 0;
10710
10711 Built.clear(/*size=*/Size: NestedLoopCount);
10712
10713 if (SemaRef.CurContext->isDependentContext())
10714 return NestedLoopCount;
10715
10716 // An example of what is generated for the following code:
10717 //
10718 // #pragma omp simd collapse(2) ordered(2)
10719 // for (i = 0; i < NI; ++i)
10720 // for (k = 0; k < NK; ++k)
10721 // for (j = J0; j < NJ; j+=2) {
10722 // <loop body>
10723 // }
10724 //
10725 // We generate the code below.
10726 // Note: the loop body may be outlined in CodeGen.
10727 // Note: some counters may be C++ classes, operator- is used to find number of
10728 // iterations and operator+= to calculate counter value.
10729 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
10730 // or i64 is currently supported).
10731 //
10732 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
10733 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
10734 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
10735 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
10736 // // similar updates for vars in clauses (e.g. 'linear')
10737 // <loop body (using local i and j)>
10738 // }
10739 // i = NI; // assign final values of counters
10740 // j = NJ;
10741 //
10742
10743 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
10744 // the iteration counts of the collapsed for loops.
10745 // Precondition tests if there is at least one iteration (all conditions are
10746 // true).
10747 auto PreCond = ExprResult(IterSpaces[0].PreCond);
10748 ASTContext &C = SemaRef.Context;
10749 unsigned FirstCountBits =
10750 C.getTypeSize(T: IterSpaces[0].NumIterations->getType());
10751 bool AllCountsNeedLessThan32Bits = FirstCountBits < 32;
10752
10753 Scope *CurScope = DSA.getCurScope();
10754 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10755 if (PreCond.isUsable()) {
10756 PreCond =
10757 SemaRef.BuildBinOp(S: CurScope, OpLoc: PreCond.get()->getExprLoc(), Opc: BO_LAnd,
10758 LHSExpr: PreCond.get(), RHSExpr: IterSpaces[Cnt].PreCond);
10759 }
10760 Expr *N = IterSpaces[Cnt].NumIterations;
10761 AllCountsNeedLessThan32Bits &= C.getTypeSize(T: N->getType()) < 32;
10762 }
10763
10764 auto BuildLastIteration = [&](unsigned Bits) -> ExprResult {
10765 ExprResult Result;
10766 for (unsigned Cnt : llvm::seq<unsigned>(Size: NestedLoopCount)) {
10767 Expr *N = IterSpaces[Cnt].NumIterations;
10768 ExprResult Count = widenIterationCount(
10769 Bits,
10770 E: SemaRef
10771 .PerformImplicitConversion(From: N->IgnoreImpCasts(), ToType: N->getType(),
10772 Action: AssignmentAction::Converting,
10773 /*AllowExplicit=*/true)
10774 .get(),
10775 SemaRef);
10776 if (!Count.isUsable())
10777 return ExprError();
10778 if (Cnt == 0)
10779 Result = Count;
10780 else
10781 Result = SemaRef.BuildBinOp(S: CurScope, OpLoc: N->getExprLoc(), Opc: BO_Mul,
10782 LHSExpr: Result.get(), RHSExpr: Count.get());
10783 if (!Result.isUsable())
10784 return ExprError();
10785 }
10786 return Result;
10787 };
10788
10789 // Build the 32-bit tree immediately only when it is always selected.
10790 // Otherwise, build the 64-bit tree first and build the 32-bit tree only when
10791 // the constant product may fit.
10792 ExprResult LastIteration;
10793 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
10794 AllCountsNeedLessThan32Bits ||
10795 (NestedLoopCount == 1 && FirstCountBits == 32)) {
10796 LastIteration = BuildLastIteration(/*Bits=*/32);
10797 } else {
10798 ExprResult LastIteration64 = BuildLastIteration(/*Bits=*/64);
10799 if (!LastIteration64.isUsable())
10800 return NestedLoopCount;
10801 LastIteration = LastIteration64;
10802 if (LastIteration64.get()->isIntegerConstantExpr(Ctx: C)) {
10803 ExprResult LastIteration32 = BuildLastIteration(/*Bits=*/32);
10804 if (LastIteration32.isUsable() &&
10805 C.getTypeSize(T: LastIteration32.get()->getType()) == 32 &&
10806 fitsInto(
10807 /*Bits=*/32,
10808 Signed: LastIteration32.get()
10809 ->getType()
10810 ->hasSignedIntegerRepresentation(),
10811 E: LastIteration64.get(), SemaRef))
10812 LastIteration = LastIteration32;
10813 }
10814 }
10815 if (!LastIteration.isUsable())
10816 return NestedLoopCount;
10817
10818 QualType VType = LastIteration.get()->getType();
10819 QualType RealVType = VType;
10820 QualType StrideVType = VType;
10821 if (isOpenMPTaskLoopDirective(DKind)) {
10822 VType =
10823 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
10824 StrideVType =
10825 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
10826 }
10827
10828 // Save the number of iterations.
10829 ExprResult NumIterations = LastIteration;
10830 {
10831 LastIteration = SemaRef.BuildBinOp(
10832 S: CurScope, OpLoc: LastIteration.get()->getExprLoc(), Opc: BO_Sub,
10833 LHSExpr: LastIteration.get(),
10834 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
10835 if (!LastIteration.isUsable())
10836 return 0;
10837 }
10838
10839 // Calculate the last iteration number beforehand instead of doing this on
10840 // each iteration. Do not do this if the number of iterations may be kfold-ed.
10841 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(Ctx: SemaRef.Context);
10842 ExprResult CalcLastIteration;
10843 if (!IsConstant) {
10844 ExprResult SaveRef =
10845 tryBuildCapture(SemaRef, Capture: LastIteration.get(), Captures);
10846 LastIteration = SaveRef;
10847
10848 // Prepare SaveRef + 1.
10849 NumIterations = SemaRef.BuildBinOp(
10850 S: CurScope, OpLoc: SaveRef.get()->getExprLoc(), Opc: BO_Add, LHSExpr: SaveRef.get(),
10851 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
10852 if (!NumIterations.isUsable())
10853 return 0;
10854 }
10855
10856 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
10857
10858 // Build variables passed into runtime, necessary for worksharing directives.
10859 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10860 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
10861 isOpenMPDistributeDirective(DKind) ||
10862 isOpenMPGenericLoopDirective(DKind) ||
10863 isOpenMPLoopTransformationDirective(DKind)) {
10864 // Lower bound variable, initialized with zero.
10865 VarDecl *LBDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.lb");
10866 LB = buildDeclRefExpr(S&: SemaRef, D: LBDecl, Ty: VType, Loc: InitLoc);
10867 SemaRef.AddInitializerToDecl(dcl: LBDecl,
10868 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
10869 /*DirectInit=*/false);
10870
10871 // Upper bound variable, initialized with last iteration number.
10872 VarDecl *UBDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.ub");
10873 UB = buildDeclRefExpr(S&: SemaRef, D: UBDecl, Ty: VType, Loc: InitLoc);
10874 SemaRef.AddInitializerToDecl(dcl: UBDecl, init: LastIteration.get(),
10875 /*DirectInit=*/false);
10876
10877 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
10878 // This will be used to implement clause 'lastprivate'.
10879 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(DestWidth: 32, Signed: true);
10880 VarDecl *ILDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: Int32Ty, Name: ".omp.is_last");
10881 IL = buildDeclRefExpr(S&: SemaRef, D: ILDecl, Ty: Int32Ty, Loc: InitLoc);
10882 SemaRef.AddInitializerToDecl(dcl: ILDecl,
10883 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
10884 /*DirectInit=*/false);
10885
10886 // Stride variable returned by runtime (we initialize it to 1 by default).
10887 VarDecl *STDecl =
10888 buildVarDecl(SemaRef, Loc: InitLoc, Type: StrideVType, Name: ".omp.stride");
10889 ST = buildDeclRefExpr(S&: SemaRef, D: STDecl, Ty: StrideVType, Loc: InitLoc);
10890 SemaRef.AddInitializerToDecl(dcl: STDecl,
10891 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 1).get(),
10892 /*DirectInit=*/false);
10893
10894 // Build expression: UB = min(UB, LastIteration)
10895 // It is necessary for CodeGen of directives with static scheduling.
10896 ExprResult IsUBGreater = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_GT,
10897 LHSExpr: UB.get(), RHSExpr: LastIteration.get());
10898 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10899 QuestionLoc: LastIteration.get()->getExprLoc(), ColonLoc: InitLoc, CondExpr: IsUBGreater.get(),
10900 LHSExpr: LastIteration.get(), RHSExpr: UB.get());
10901 EUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: UB.get(),
10902 RHSExpr: CondOp.get());
10903 EUB = SemaRef.ActOnFinishFullExpr(Expr: EUB.get(), /*DiscardedValue=*/false);
10904
10905 // If we have a combined directive that combines 'distribute', 'for' or
10906 // 'simd' we need to be able to access the bounds of the schedule of the
10907 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10908 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10909 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10910 // Lower bound variable, initialized with zero.
10911 VarDecl *CombLBDecl =
10912 buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.comb.lb");
10913 CombLB = buildDeclRefExpr(S&: SemaRef, D: CombLBDecl, Ty: VType, Loc: InitLoc);
10914 SemaRef.AddInitializerToDecl(
10915 dcl: CombLBDecl, init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
10916 /*DirectInit=*/false);
10917
10918 // Upper bound variable, initialized with last iteration number.
10919 VarDecl *CombUBDecl =
10920 buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.comb.ub");
10921 CombUB = buildDeclRefExpr(S&: SemaRef, D: CombUBDecl, Ty: VType, Loc: InitLoc);
10922 SemaRef.AddInitializerToDecl(dcl: CombUBDecl, init: LastIteration.get(),
10923 /*DirectInit=*/false);
10924
10925 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10926 S: CurScope, OpLoc: InitLoc, Opc: BO_GT, LHSExpr: CombUB.get(), RHSExpr: LastIteration.get());
10927 ExprResult CombCondOp =
10928 SemaRef.ActOnConditionalOp(QuestionLoc: InitLoc, ColonLoc: InitLoc, CondExpr: CombIsUBGreater.get(),
10929 LHSExpr: LastIteration.get(), RHSExpr: CombUB.get());
10930 CombEUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: CombUB.get(),
10931 RHSExpr: CombCondOp.get());
10932 CombEUB =
10933 SemaRef.ActOnFinishFullExpr(Expr: CombEUB.get(), /*DiscardedValue=*/false);
10934
10935 const CapturedDecl *CD = cast<CapturedStmt>(Val: AStmt)->getCapturedDecl();
10936 // We expect to have at least 2 more parameters than the 'parallel'
10937 // directive does - the lower and upper bounds of the previous schedule.
10938 assert(CD->getNumParams() >= 4 &&
10939 "Unexpected number of parameters in loop combined directive");
10940
10941 // Set the proper type for the bounds given what we learned from the
10942 // enclosed loops.
10943 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/i: 2);
10944 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/i: 3);
10945
10946 // Previous lower and upper bounds are obtained from the region
10947 // parameters.
10948 PrevLB =
10949 buildDeclRefExpr(S&: SemaRef, D: PrevLBDecl, Ty: PrevLBDecl->getType(), Loc: InitLoc);
10950 PrevUB =
10951 buildDeclRefExpr(S&: SemaRef, D: PrevUBDecl, Ty: PrevUBDecl->getType(), Loc: InitLoc);
10952 }
10953 }
10954
10955 // Build the iteration variable and its initialization before loop.
10956 ExprResult IV;
10957 ExprResult Init, CombInit;
10958 {
10959 VarDecl *IVDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: RealVType, Name: ".omp.iv");
10960 IV = buildDeclRefExpr(S&: SemaRef, D: IVDecl, Ty: RealVType, Loc: InitLoc);
10961 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10962 isOpenMPGenericLoopDirective(DKind) ||
10963 isOpenMPTaskLoopDirective(DKind) ||
10964 isOpenMPDistributeDirective(DKind) ||
10965 isOpenMPLoopTransformationDirective(DKind))
10966 ? LB.get()
10967 : SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 0).get();
10968 Init = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: RHS);
10969 Init = SemaRef.ActOnFinishFullExpr(Expr: Init.get(), /*DiscardedValue=*/false);
10970
10971 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10972 Expr *CombRHS =
10973 (isOpenMPWorksharingDirective(DKind) ||
10974 isOpenMPGenericLoopDirective(DKind) ||
10975 isOpenMPTaskLoopDirective(DKind) ||
10976 isOpenMPDistributeDirective(DKind))
10977 ? CombLB.get()
10978 : SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 0).get();
10979 CombInit =
10980 SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: CombRHS);
10981 CombInit =
10982 SemaRef.ActOnFinishFullExpr(Expr: CombInit.get(), /*DiscardedValue=*/false);
10983 }
10984 }
10985
10986 bool UseStrictCompare =
10987 RealVType->hasUnsignedIntegerRepresentation() &&
10988 llvm::all_of(Range&: IterSpaces, P: [](const LoopIterationSpace &LIS) {
10989 return LIS.IsStrictCompare;
10990 });
10991 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10992 // unsigned IV)) for worksharing loops.
10993 SourceLocation CondLoc = AStmt->getBeginLoc();
10994 Expr *BoundUB = UB.get();
10995 if (UseStrictCompare) {
10996 BoundUB =
10997 SemaRef
10998 .BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundUB,
10999 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
11000 .get();
11001 BoundUB =
11002 SemaRef.ActOnFinishFullExpr(Expr: BoundUB, /*DiscardedValue=*/false).get();
11003 }
11004 ExprResult Cond =
11005 (isOpenMPWorksharingDirective(DKind) ||
11006 isOpenMPGenericLoopDirective(DKind) ||
11007 isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
11008 isOpenMPLoopTransformationDirective(DKind))
11009 ? SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc,
11010 Opc: UseStrictCompare ? BO_LT : BO_LE, LHSExpr: IV.get(),
11011 RHSExpr: BoundUB)
11012 : SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LT, LHSExpr: IV.get(),
11013 RHSExpr: NumIterations.get());
11014 ExprResult CombDistCond;
11015 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
11016 CombDistCond = SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LT, LHSExpr: IV.get(),
11017 RHSExpr: NumIterations.get());
11018 }
11019
11020 ExprResult CombCond;
11021 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
11022 Expr *BoundCombUB = CombUB.get();
11023 if (UseStrictCompare) {
11024 BoundCombUB =
11025 SemaRef
11026 .BuildBinOp(
11027 S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundCombUB,
11028 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
11029 .get();
11030 BoundCombUB =
11031 SemaRef.ActOnFinishFullExpr(Expr: BoundCombUB, /*DiscardedValue=*/false)
11032 .get();
11033 }
11034 CombCond =
11035 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE,
11036 LHSExpr: IV.get(), RHSExpr: BoundCombUB);
11037 }
11038 // Loop increment (IV = IV + 1)
11039 SourceLocation IncLoc = AStmt->getBeginLoc();
11040 ExprResult Inc =
11041 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: IV.get(),
11042 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: IncLoc, Val: 1).get());
11043 if (!Inc.isUsable())
11044 return 0;
11045 Inc = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: Inc.get());
11046 Inc = SemaRef.ActOnFinishFullExpr(Expr: Inc.get(), /*DiscardedValue=*/false);
11047 if (!Inc.isUsable())
11048 return 0;
11049
11050 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
11051 // Used for directives with static scheduling.
11052 // In combined construct, add combined version that use CombLB and CombUB
11053 // base variables for the update
11054 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
11055 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
11056 isOpenMPGenericLoopDirective(DKind) ||
11057 isOpenMPDistributeDirective(DKind) ||
11058 isOpenMPLoopTransformationDirective(DKind)) {
11059 // LB + ST
11060 NextLB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: LB.get(), RHSExpr: ST.get());
11061 if (!NextLB.isUsable())
11062 return 0;
11063 // LB = LB + ST
11064 NextLB =
11065 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: LB.get(), RHSExpr: NextLB.get());
11066 NextLB =
11067 SemaRef.ActOnFinishFullExpr(Expr: NextLB.get(), /*DiscardedValue=*/false);
11068 if (!NextLB.isUsable())
11069 return 0;
11070 // UB + ST
11071 NextUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: UB.get(), RHSExpr: ST.get());
11072 if (!NextUB.isUsable())
11073 return 0;
11074 // UB = UB + ST
11075 NextUB =
11076 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: UB.get(), RHSExpr: NextUB.get());
11077 NextUB =
11078 SemaRef.ActOnFinishFullExpr(Expr: NextUB.get(), /*DiscardedValue=*/false);
11079 if (!NextUB.isUsable())
11080 return 0;
11081 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
11082 CombNextLB =
11083 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: CombLB.get(), RHSExpr: ST.get());
11084 if (!NextLB.isUsable())
11085 return 0;
11086 // LB = LB + ST
11087 CombNextLB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: CombLB.get(),
11088 RHSExpr: CombNextLB.get());
11089 CombNextLB = SemaRef.ActOnFinishFullExpr(Expr: CombNextLB.get(),
11090 /*DiscardedValue=*/false);
11091 if (!CombNextLB.isUsable())
11092 return 0;
11093 // UB + ST
11094 CombNextUB =
11095 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: CombUB.get(), RHSExpr: ST.get());
11096 if (!CombNextUB.isUsable())
11097 return 0;
11098 // UB = UB + ST
11099 CombNextUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: CombUB.get(),
11100 RHSExpr: CombNextUB.get());
11101 CombNextUB = SemaRef.ActOnFinishFullExpr(Expr: CombNextUB.get(),
11102 /*DiscardedValue=*/false);
11103 if (!CombNextUB.isUsable())
11104 return 0;
11105 }
11106 }
11107
11108 // Create increment expression for distribute loop when combined in a same
11109 // directive with for as IV = IV + ST; ensure upper bound expression based
11110 // on PrevUB instead of NumIterations - used to implement 'for' when found
11111 // in combination with 'distribute', like in 'distribute parallel for'
11112 SourceLocation DistIncLoc = AStmt->getBeginLoc();
11113 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
11114 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
11115 DistCond = SemaRef.BuildBinOp(
11116 S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE, LHSExpr: IV.get(), RHSExpr: BoundUB);
11117 assert(DistCond.isUsable() && "distribute cond expr was not built");
11118
11119 DistInc =
11120 SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Add, LHSExpr: IV.get(), RHSExpr: ST.get());
11121 assert(DistInc.isUsable() && "distribute inc expr was not built");
11122 DistInc = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Assign, LHSExpr: IV.get(),
11123 RHSExpr: DistInc.get());
11124 DistInc =
11125 SemaRef.ActOnFinishFullExpr(Expr: DistInc.get(), /*DiscardedValue=*/false);
11126 assert(DistInc.isUsable() && "distribute inc expr was not built");
11127
11128 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
11129 // construct
11130 ExprResult NewPrevUB = PrevUB;
11131 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
11132 if (!SemaRef.Context.hasSameType(T1: UB.get()->getType(),
11133 T2: PrevUB.get()->getType())) {
11134 NewPrevUB = SemaRef.BuildCStyleCastExpr(
11135 LParenLoc: DistEUBLoc,
11136 Ty: SemaRef.Context.getTrivialTypeSourceInfo(T: UB.get()->getType()),
11137 RParenLoc: DistEUBLoc, Op: NewPrevUB.get());
11138 if (!NewPrevUB.isUsable())
11139 return 0;
11140 }
11141 ExprResult IsUBGreater = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistEUBLoc, Opc: BO_GT,
11142 LHSExpr: UB.get(), RHSExpr: NewPrevUB.get());
11143 ExprResult CondOp = SemaRef.ActOnConditionalOp(
11144 QuestionLoc: DistEUBLoc, ColonLoc: DistEUBLoc, CondExpr: IsUBGreater.get(), LHSExpr: NewPrevUB.get(), RHSExpr: UB.get());
11145 PrevEUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Assign, LHSExpr: UB.get(),
11146 RHSExpr: CondOp.get());
11147 PrevEUB =
11148 SemaRef.ActOnFinishFullExpr(Expr: PrevEUB.get(), /*DiscardedValue=*/false);
11149
11150 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
11151 // parallel for is in combination with a distribute directive with
11152 // schedule(static, 1)
11153 Expr *BoundPrevUB = PrevUB.get();
11154 if (UseStrictCompare) {
11155 BoundPrevUB =
11156 SemaRef
11157 .BuildBinOp(
11158 S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundPrevUB,
11159 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
11160 .get();
11161 BoundPrevUB =
11162 SemaRef.ActOnFinishFullExpr(Expr: BoundPrevUB, /*DiscardedValue=*/false)
11163 .get();
11164 }
11165 ParForInDistCond =
11166 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE,
11167 LHSExpr: IV.get(), RHSExpr: BoundPrevUB);
11168 }
11169
11170 // Build updates and final values of the loop counters.
11171 bool HasErrors = false;
11172 Built.Counters.resize(N: NestedLoopCount);
11173 Built.Inits.resize(N: NestedLoopCount);
11174 Built.Updates.resize(N: NestedLoopCount);
11175 Built.Finals.resize(N: NestedLoopCount);
11176 Built.DependentCounters.resize(N: NestedLoopCount);
11177 Built.DependentInits.resize(N: NestedLoopCount);
11178 Built.FinalsConditions.resize(N: NestedLoopCount);
11179 {
11180 // We implement the following algorithm for obtaining the
11181 // original loop iteration variable values based on the
11182 // value of the collapsed loop iteration variable IV.
11183 //
11184 // Let n+1 be the number of collapsed loops in the nest.
11185 // Iteration variables (I0, I1, .... In)
11186 // Iteration counts (N0, N1, ... Nn)
11187 //
11188 // Acc = IV;
11189 //
11190 // To compute Ik for loop k, 0 <= k <= n, generate:
11191 // Prod = N(k+1) * N(k+2) * ... * Nn;
11192 // Ik = Acc / Prod;
11193 // Acc -= Ik * Prod;
11194 //
11195 ExprResult Acc = IV;
11196 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
11197 LoopIterationSpace &IS = IterSpaces[Cnt];
11198 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
11199 ExprResult Iter;
11200
11201 // Compute prod
11202 ExprResult Prod = SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get();
11203 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
11204 Prod = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Mul, LHSExpr: Prod.get(),
11205 RHSExpr: IterSpaces[K].NumIterations);
11206
11207 // Iter = Acc / Prod
11208 // If there is at least one more inner loop to avoid
11209 // multiplication by 1.
11210 if (Cnt + 1 < NestedLoopCount)
11211 Iter =
11212 SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Div, LHSExpr: Acc.get(), RHSExpr: Prod.get());
11213 else
11214 Iter = Acc;
11215 if (!Iter.isUsable()) {
11216 HasErrors = true;
11217 break;
11218 }
11219
11220 // Update Acc:
11221 // Acc -= Iter * Prod
11222 // Check if there is at least one more inner loop to avoid
11223 // multiplication by 1.
11224 if (Cnt + 1 < NestedLoopCount)
11225 Prod = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Mul, LHSExpr: Iter.get(),
11226 RHSExpr: Prod.get());
11227 else
11228 Prod = Iter;
11229 Acc = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Sub, LHSExpr: Acc.get(), RHSExpr: Prod.get());
11230
11231 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
11232 auto *VD = cast<VarDecl>(Val: cast<DeclRefExpr>(Val: IS.CounterVar)->getDecl());
11233 DeclRefExpr *CounterVar = buildDeclRefExpr(
11234 S&: SemaRef, D: VD, Ty: IS.CounterVar->getType(), Loc: IS.CounterVar->getExprLoc(),
11235 /*RefersToCapture=*/true);
11236 ExprResult Init =
11237 buildCounterInit(SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar,
11238 Start: IS.CounterInit, IsNonRectangularLB: IS.IsNonRectangularLB, Captures);
11239 if (!Init.isUsable()) {
11240 HasErrors = true;
11241 break;
11242 }
11243 ExprResult Update = buildCounterUpdate(
11244 SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar, Start: IS.CounterInit, Iter,
11245 Step: IS.CounterStep, Subtract: IS.Subtract, IsNonRectangularLB: IS.IsNonRectangularLB, Captures: &Captures);
11246 if (!Update.isUsable()) {
11247 HasErrors = true;
11248 break;
11249 }
11250
11251 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
11252 ExprResult Final =
11253 buildCounterUpdate(SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar,
11254 Start: IS.CounterInit, Iter: IS.NumIterations, Step: IS.CounterStep,
11255 Subtract: IS.Subtract, IsNonRectangularLB: IS.IsNonRectangularLB, Captures: &Captures);
11256 if (!Final.isUsable()) {
11257 HasErrors = true;
11258 break;
11259 }
11260
11261 if (!Update.isUsable() || !Final.isUsable()) {
11262 HasErrors = true;
11263 break;
11264 }
11265 // Save results
11266 Built.Counters[Cnt] = IS.CounterVar;
11267 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
11268 Built.Inits[Cnt] = Init.get();
11269 Built.Updates[Cnt] = Update.get();
11270 Built.Finals[Cnt] = Final.get();
11271 Built.DependentCounters[Cnt] = nullptr;
11272 Built.DependentInits[Cnt] = nullptr;
11273 // Transfer the body-guard condition: the loop condition for
11274 // non-rectangular loops, the overshoot predicate for reinterpreted tiles,
11275 // null otherwise.
11276 Built.FinalsConditions[Cnt] = IS.FinalCondition;
11277 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
11278 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
11279 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
11280 }
11281 }
11282 }
11283
11284 if (HasErrors)
11285 return 0;
11286
11287 // Save results
11288 Built.IterationVarRef = IV.get();
11289 Built.LastIteration = LastIteration.get();
11290 Built.NumIterations = NumIterations.get();
11291 Built.CalcLastIteration = SemaRef
11292 .ActOnFinishFullExpr(Expr: CalcLastIteration.get(),
11293 /*DiscardedValue=*/false)
11294 .get();
11295 Built.PreCond = PreCond.get();
11296 Built.PreInits = buildPreInits(Context&: C, Captures);
11297 Built.Cond = Cond.get();
11298 Built.Init = Init.get();
11299 Built.Inc = Inc.get();
11300 Built.LB = LB.get();
11301 Built.UB = UB.get();
11302 Built.IL = IL.get();
11303 Built.ST = ST.get();
11304 Built.EUB = EUB.get();
11305 Built.NLB = NextLB.get();
11306 Built.NUB = NextUB.get();
11307 Built.PrevLB = PrevLB.get();
11308 Built.PrevUB = PrevUB.get();
11309 Built.DistInc = DistInc.get();
11310 Built.PrevEUB = PrevEUB.get();
11311 Built.DistCombinedFields.LB = CombLB.get();
11312 Built.DistCombinedFields.UB = CombUB.get();
11313 Built.DistCombinedFields.EUB = CombEUB.get();
11314 Built.DistCombinedFields.Init = CombInit.get();
11315 Built.DistCombinedFields.Cond = CombCond.get();
11316 Built.DistCombinedFields.NLB = CombNextLB.get();
11317 Built.DistCombinedFields.NUB = CombNextUB.get();
11318 Built.DistCombinedFields.DistCond = CombDistCond.get();
11319 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
11320
11321 return NestedLoopCount;
11322}
11323
11324static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
11325 auto CollapseClauses =
11326 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
11327 if (CollapseClauses.begin() != CollapseClauses.end())
11328 return (*CollapseClauses.begin())->getNumForLoops();
11329 return nullptr;
11330}
11331
11332static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
11333 auto OrderedClauses =
11334 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
11335 if (OrderedClauses.begin() != OrderedClauses.end())
11336 return (*OrderedClauses.begin())->getNumForLoops();
11337 return nullptr;
11338}
11339
11340static bool checkSimdlenSafelenSpecified(Sema &S,
11341 const ArrayRef<OMPClause *> Clauses) {
11342 const OMPSafelenClause *Safelen = nullptr;
11343 const OMPSimdlenClause *Simdlen = nullptr;
11344
11345 for (const OMPClause *Clause : Clauses) {
11346 if (Clause->getClauseKind() == OMPC_safelen)
11347 Safelen = cast<OMPSafelenClause>(Val: Clause);
11348 else if (Clause->getClauseKind() == OMPC_simdlen)
11349 Simdlen = cast<OMPSimdlenClause>(Val: Clause);
11350 if (Safelen && Simdlen)
11351 break;
11352 }
11353
11354 if (Simdlen && Safelen) {
11355 const Expr *SimdlenLength = Simdlen->getSimdlen();
11356 const Expr *SafelenLength = Safelen->getSafelen();
11357 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
11358 SimdlenLength->isInstantiationDependent() ||
11359 SimdlenLength->containsUnexpandedParameterPack())
11360 return false;
11361 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
11362 SafelenLength->isInstantiationDependent() ||
11363 SafelenLength->containsUnexpandedParameterPack())
11364 return false;
11365 Expr::EvalResult SimdlenResult, SafelenResult;
11366 SimdlenLength->EvaluateAsInt(Result&: SimdlenResult, Ctx: S.Context);
11367 SafelenLength->EvaluateAsInt(Result&: SafelenResult, Ctx: S.Context);
11368 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
11369 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
11370 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
11371 // If both simdlen and safelen clauses are specified, the value of the
11372 // simdlen parameter must be less than or equal to the value of the safelen
11373 // parameter.
11374 if (llvm::APSInt::compareValues(I1: SimdlenRes, I2: SafelenRes) > 0) {
11375 S.Diag(Loc: SimdlenLength->getExprLoc(),
11376 DiagID: diag::err_omp_wrong_simdlen_safelen_values)
11377 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
11378 return true;
11379 }
11380 }
11381 return false;
11382}
11383
11384StmtResult SemaOpenMP::ActOnOpenMPSimdDirective(
11385 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11386 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11387 if (!AStmt)
11388 return StmtError();
11389
11390 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_simd, AStmt);
11391
11392 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11393 OMPLoopBasedDirective::HelperExprs B;
11394 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11395 // define the nested loops number.
11396 unsigned NestedLoopCount = checkOpenMPLoop(
11397 DKind: OMPD_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
11398 AStmt: CS, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
11399 if (NestedLoopCount == 0)
11400 return StmtError();
11401
11402 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11403 return StmtError();
11404
11405 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
11406 return StmtError();
11407
11408 auto *SimdDirective = OMPSimdDirective::Create(
11409 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11410 return SimdDirective;
11411}
11412
11413StmtResult SemaOpenMP::ActOnOpenMPForDirective(
11414 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11415 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11416 if (!AStmt)
11417 return StmtError();
11418
11419 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11420 OMPLoopBasedDirective::HelperExprs B;
11421 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11422 // define the nested loops number.
11423 unsigned NestedLoopCount = checkOpenMPLoop(
11424 DKind: OMPD_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
11425 AStmt, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
11426 if (NestedLoopCount == 0)
11427 return StmtError();
11428
11429 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11430 return StmtError();
11431
11432 auto *ForDirective = OMPForDirective::Create(
11433 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
11434 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11435 return ForDirective;
11436}
11437
11438StmtResult SemaOpenMP::ActOnOpenMPForSimdDirective(
11439 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11440 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11441 if (!AStmt)
11442 return StmtError();
11443
11444 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_for_simd, AStmt);
11445
11446 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11447 OMPLoopBasedDirective::HelperExprs B;
11448 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11449 // define the nested loops number.
11450 unsigned NestedLoopCount =
11451 checkOpenMPLoop(DKind: OMPD_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11452 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
11453 VarsWithImplicitDSA, Built&: B);
11454 if (NestedLoopCount == 0)
11455 return StmtError();
11456
11457 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11458 return StmtError();
11459
11460 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
11461 return StmtError();
11462
11463 return OMPForSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11464 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11465}
11466
11467static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind,
11468 Stmt *AStmt, DSAStackTy *Stack) {
11469 if (!AStmt)
11470 return true;
11471
11472 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11473 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
11474 auto BaseStmt = AStmt;
11475 while (auto *CS = dyn_cast_or_null<CapturedStmt>(Val: BaseStmt))
11476 BaseStmt = CS->getCapturedStmt();
11477 if (auto *C = dyn_cast_or_null<CompoundStmt>(Val: BaseStmt)) {
11478 auto S = C->children();
11479 if (S.begin() == S.end())
11480 return true;
11481 // All associated statements must be '#pragma omp section' except for
11482 // the first one.
11483 for (Stmt *SectionStmt : llvm::drop_begin(RangeOrContainer&: S)) {
11484 if (!SectionStmt || !isa<OMPSectionDirective>(Val: SectionStmt)) {
11485 if (SectionStmt)
11486 SemaRef.Diag(Loc: SectionStmt->getBeginLoc(),
11487 DiagID: diag::err_omp_sections_substmt_not_section)
11488 << getOpenMPDirectiveName(D: DKind, V: OMPVersion);
11489 return true;
11490 }
11491 cast<OMPSectionDirective>(Val: SectionStmt)
11492 ->setHasCancel(Stack->isCancelRegion());
11493 }
11494 } else {
11495 SemaRef.Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_sections_not_compound_stmt)
11496 << getOpenMPDirectiveName(D: DKind, V: OMPVersion);
11497 return true;
11498 }
11499 return false;
11500}
11501
11502StmtResult
11503SemaOpenMP::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
11504 Stmt *AStmt, SourceLocation StartLoc,
11505 SourceLocation EndLoc) {
11506 if (checkSectionsDirective(SemaRef, DKind: OMPD_sections, AStmt, DSAStack))
11507 return StmtError();
11508
11509 SemaRef.setFunctionHasBranchProtectedScope();
11510
11511 return OMPSectionsDirective::Create(
11512 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11513 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11514}
11515
11516StmtResult SemaOpenMP::ActOnOpenMPSectionDirective(Stmt *AStmt,
11517 SourceLocation StartLoc,
11518 SourceLocation EndLoc) {
11519 if (!AStmt)
11520 return StmtError();
11521
11522 SemaRef.setFunctionHasBranchProtectedScope();
11523 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
11524
11525 return OMPSectionDirective::Create(C: getASTContext(), StartLoc, EndLoc, AssociatedStmt: AStmt,
11526 DSAStack->isCancelRegion());
11527}
11528
11529static Expr *getDirectCallExpr(Expr *E) {
11530 E = E->IgnoreParenCasts()->IgnoreImplicit();
11531 if (auto *CE = dyn_cast<CallExpr>(Val: E))
11532 if (CE->getDirectCallee())
11533 return E;
11534 return nullptr;
11535}
11536
11537StmtResult
11538SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
11539 Stmt *AStmt, SourceLocation StartLoc,
11540 SourceLocation EndLoc) {
11541 if (!AStmt)
11542 return StmtError();
11543
11544 Stmt *S = cast<CapturedStmt>(Val: AStmt)->getCapturedStmt();
11545
11546 // 5.1 OpenMP
11547 // expression-stmt : an expression statement with one of the following forms:
11548 // expression = target-call ( [expression-list] );
11549 // target-call ( [expression-list] );
11550
11551 SourceLocation TargetCallLoc;
11552
11553 if (!SemaRef.CurContext->isDependentContext()) {
11554 Expr *TargetCall = nullptr;
11555
11556 auto *E = dyn_cast<Expr>(Val: S);
11557 if (!E) {
11558 Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_dispatch_statement_call);
11559 return StmtError();
11560 }
11561
11562 E = E->IgnoreParenCasts()->IgnoreImplicit();
11563
11564 if (auto *BO = dyn_cast<BinaryOperator>(Val: E)) {
11565 if (BO->getOpcode() == BO_Assign)
11566 TargetCall = getDirectCallExpr(E: BO->getRHS());
11567 } else {
11568 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(Val: E))
11569 if (COCE->getOperator() == OO_Equal)
11570 TargetCall = getDirectCallExpr(E: COCE->getArg(Arg: 1));
11571 if (!TargetCall)
11572 TargetCall = getDirectCallExpr(E);
11573 }
11574 if (!TargetCall) {
11575 Diag(Loc: E->getBeginLoc(), DiagID: diag::err_omp_dispatch_statement_call);
11576 return StmtError();
11577 }
11578 TargetCallLoc = TargetCall->getExprLoc();
11579 }
11580
11581 SemaRef.setFunctionHasBranchProtectedScope();
11582
11583 return OMPDispatchDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11584 Clauses, AssociatedStmt: AStmt, TargetCallLoc);
11585}
11586
11587static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
11588 OpenMPDirectiveKind K,
11589 DSAStackTy *Stack) {
11590 bool ErrorFound = false;
11591 for (OMPClause *C : Clauses) {
11592 if (auto *LPC = dyn_cast<OMPLastprivateClause>(Val: C)) {
11593 for (Expr *RefExpr : LPC->varlist()) {
11594 SourceLocation ELoc;
11595 SourceRange ERange;
11596 Expr *SimpleRefExpr = RefExpr;
11597 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange);
11598 if (ValueDecl *D = Res.first) {
11599 auto &&Info = Stack->isLoopControlVariable(D);
11600 if (!Info.first) {
11601 llvm::omp::Version OMPVersion = S.getLangOpts().getOpenMPVersion();
11602 S.Diag(Loc: ELoc, DiagID: diag::err_omp_lastprivate_loop_var_non_loop_iteration)
11603 << getOpenMPDirectiveName(D: K, V: OMPVersion);
11604 ErrorFound = true;
11605 }
11606 }
11607 }
11608 }
11609 }
11610 return ErrorFound;
11611}
11612
11613StmtResult SemaOpenMP::ActOnOpenMPGenericLoopDirective(
11614 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11615 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11616 if (!AStmt)
11617 return StmtError();
11618
11619 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11620 // A list item may not appear in a lastprivate clause unless it is the
11621 // loop iteration variable of a loop that is associated with the construct.
11622 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_loop, DSAStack))
11623 return StmtError();
11624
11625 setBranchProtectedScope(SemaRef, DKind: OMPD_loop, AStmt);
11626
11627 OMPLoopDirective::HelperExprs B;
11628 // In presence of clause 'collapse', it will define the nested loops number.
11629 unsigned NestedLoopCount = checkOpenMPLoop(
11630 DKind: OMPD_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
11631 AStmt, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
11632 if (NestedLoopCount == 0)
11633 return StmtError();
11634
11635 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11636 "omp loop exprs were not built");
11637
11638 return OMPGenericLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11639 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11640}
11641
11642/// Check the number of expressions specified in a multidimensional clause and
11643/// return whether an error was encountered.
11644static bool validateMultidimClauseExprs(
11645 SemaBase &SemaRef, OpenMPClauseKind ClauseKind,
11646 SourceLocation ClauseBeginLoc, ArrayRef<const Expr *> ClauseVarList,
11647 const Expr *DimsModifierExpr, const OMPXBareClause *BareClause = nullptr) {
11648 const uint64_t NumVars = ClauseVarList.size();
11649
11650 // The ompx_bare clause allows up to three expressions.
11651 if (BareClause) {
11652 if (NumVars > 3) {
11653 SemaRef.Diag(Loc: ClauseBeginLoc,
11654 DiagID: diag::err_ompx_more_than_three_expr_not_allowed)
11655 << getOpenMPClauseName(C: ClauseKind);
11656 return true;
11657 }
11658 return false;
11659 }
11660
11661 // By default, only one expression accepted.
11662 uint64_t MaxExprs = 1;
11663 if (DimsModifierExpr) {
11664 // Cannot verify the expected size yet.
11665 if (DimsModifierExpr->isInstantiationDependent())
11666 return false;
11667
11668 // The dims modifier determines the exact number of expressions.
11669 MaxExprs = DimsModifierExpr->EvaluateKnownConstInt(Ctx: SemaRef.getASTContext())
11670 .getExtValue();
11671 }
11672
11673 if (NumVars != MaxExprs) {
11674 SemaRef.Diag(Loc: ClauseBeginLoc, DiagID: diag::err_omp_unexpected_num_exprs)
11675 << getOpenMPClauseName(C: ClauseKind) << MaxExprs << NumVars;
11676 return true;
11677 }
11678 if (NumVars > 3) {
11679 SemaRef.Diag(Loc: ClauseBeginLoc, DiagID: diag::err_omp_max_three_exprs)
11680 << getOpenMPClauseName(C: ClauseKind);
11681 return true;
11682 }
11683 return false;
11684}
11685
11686/// Check the number of expressions specified in a multidimensional clause and
11687/// return whether an error was encountered.
11688template <typename ClauseT>
11689static bool validateMultidimClauseExprs(SemaBase &SemaRef,
11690 const ClauseT *Clause,
11691 const OMPXBareClause *BareClause) {
11692 if (!Clause)
11693 return false;
11694 return validateMultidimClauseExprs(
11695 SemaRef, Clause->getClauseKind(), Clause->getBeginLoc(),
11696 Clause->getVarRefs(), Clause->getDimsModifierExpr(), BareClause);
11697}
11698
11699/// Check the number of expressions specified in clauses that can contain
11700/// multidimensional values, e.g., num_teams and thread_limit. The function
11701/// returns true on error.
11702static bool validateMultidimClauses(SemaBase &SemaRef,
11703 ArrayRef<OMPClause *> Clauses,
11704 bool MayHaveBareClause = false) {
11705 auto BareClauseIt =
11706 MayHaveBareClause ? llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OMPXBareClause>)
11707 : Clauses.end();
11708 auto ThreadLimitIt =
11709 llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OMPThreadLimitClause>);
11710 auto NumTeamsIt = llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OMPNumTeamsClause>);
11711
11712 const auto *BareClause = BareClauseIt != Clauses.end()
11713 ? cast<OMPXBareClause>(Val: *BareClauseIt)
11714 : nullptr;
11715 const auto *ThreadLimitClause =
11716 ThreadLimitIt != Clauses.end()
11717 ? cast<OMPThreadLimitClause>(Val: *ThreadLimitIt)
11718 : nullptr;
11719 const auto *NumTeamsClause = NumTeamsIt != Clauses.end()
11720 ? cast<OMPNumTeamsClause>(Val: *NumTeamsIt)
11721 : nullptr;
11722
11723 if (BareClause) {
11724 if (!NumTeamsClause || !ThreadLimitClause) {
11725 SemaRef.Diag(Loc: BareClause->getBeginLoc(), DiagID: diag::err_ompx_bare_no_grid);
11726 return true;
11727 }
11728 if (ThreadLimitClause->getModifier() == OMPC_THREADLIMIT_dims ||
11729 NumTeamsClause->getModifier() == OMPC_NUMTEAMS_dims) {
11730 SemaRef.Diag(Loc: BareClause->getBeginLoc(), DiagID: diag::err_ompx_bare_no_dims);
11731 return true;
11732 }
11733 }
11734 return validateMultidimClauseExprs(SemaRef, Clause: ThreadLimitClause, BareClause) ||
11735 validateMultidimClauseExprs(SemaRef, Clause: NumTeamsClause, BareClause);
11736}
11737
11738StmtResult SemaOpenMP::ActOnOpenMPTeamsGenericLoopDirective(
11739 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11740 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11741 if (!AStmt)
11742 return StmtError();
11743
11744 if (validateMultidimClauses(SemaRef&: *this, Clauses))
11745 return StmtError();
11746
11747 if (checkClausesForDecompositionConflicts(SemaRef, DKind: OMPD_teams_loop, Clauses))
11748 return StmtError();
11749
11750 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11751 // A list item may not appear in a lastprivate clause unless it is the
11752 // loop iteration variable of a loop that is associated with the construct.
11753 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_teams_loop, DSAStack))
11754 return StmtError();
11755
11756 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_teams_loop, AStmt);
11757
11758 OMPLoopDirective::HelperExprs B;
11759 // In presence of clause 'collapse', it will define the nested loops number.
11760 unsigned NestedLoopCount =
11761 checkOpenMPLoop(DKind: OMPD_teams_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11762 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11763 VarsWithImplicitDSA, Built&: B);
11764 if (NestedLoopCount == 0)
11765 return StmtError();
11766
11767 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11768 "omp loop exprs were not built");
11769
11770 DSAStack->setParentTeamsRegionLoc(StartLoc);
11771
11772 return OMPTeamsGenericLoopDirective::Create(
11773 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11774}
11775
11776StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsGenericLoopDirective(
11777 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11778 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11779 if (!AStmt)
11780 return StmtError();
11781
11782 if (validateMultidimClauses(SemaRef&: *this, Clauses))
11783 return StmtError();
11784
11785 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11786 // A list item may not appear in a lastprivate clause unless it is the
11787 // loop iteration variable of a loop that is associated with the construct.
11788 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_target_teams_loop,
11789 DSAStack))
11790 return StmtError();
11791
11792 if (checkClausesForDecompositionConflicts(SemaRef, DKind: OMPD_target_teams_loop,
11793 Clauses))
11794 return StmtError();
11795
11796 if (checkOriginalVarMappedButOnlyBindingsUsed(SemaRef, Clauses, Body: AStmt))
11797 return StmtError();
11798
11799 CapturedStmt *CS =
11800 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams_loop, AStmt);
11801
11802 OMPLoopDirective::HelperExprs B;
11803 // In presence of clause 'collapse', it will define the nested loops number.
11804 unsigned NestedLoopCount =
11805 checkOpenMPLoop(DKind: OMPD_target_teams_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11806 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11807 VarsWithImplicitDSA, Built&: B);
11808 if (NestedLoopCount == 0)
11809 return StmtError();
11810
11811 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11812 "omp loop exprs were not built");
11813
11814 return OMPTargetTeamsGenericLoopDirective::Create(
11815 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
11816 CanBeParallelFor: teamsLoopCanBeParallelFor(AStmt, SemaRef));
11817}
11818
11819StmtResult SemaOpenMP::ActOnOpenMPParallelGenericLoopDirective(
11820 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11821 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11822 if (!AStmt)
11823 return StmtError();
11824
11825 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11826 // A list item may not appear in a lastprivate clause unless it is the
11827 // loop iteration variable of a loop that is associated with the construct.
11828 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_parallel_loop,
11829 DSAStack))
11830 return StmtError();
11831
11832 CapturedStmt *CS =
11833 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_loop, AStmt);
11834
11835 OMPLoopDirective::HelperExprs B;
11836 // In presence of clause 'collapse', it will define the nested loops number.
11837 unsigned NestedLoopCount =
11838 checkOpenMPLoop(DKind: OMPD_parallel_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11839 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11840 VarsWithImplicitDSA, Built&: B);
11841 if (NestedLoopCount == 0)
11842 return StmtError();
11843
11844 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11845 "omp loop exprs were not built");
11846
11847 return OMPParallelGenericLoopDirective::Create(
11848 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11849}
11850
11851StmtResult SemaOpenMP::ActOnOpenMPTargetParallelGenericLoopDirective(
11852 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11853 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11854 if (!AStmt)
11855 return StmtError();
11856
11857 if (validateMultidimClauses(SemaRef&: *this, Clauses))
11858 return StmtError();
11859
11860 if (checkClausesForDecompositionConflicts(SemaRef, DKind: OMPD_target_parallel_loop,
11861 Clauses))
11862 return StmtError();
11863
11864 if (checkOriginalVarMappedButOnlyBindingsUsed(SemaRef, Clauses, Body: AStmt))
11865 return StmtError();
11866
11867 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11868 // A list item may not appear in a lastprivate clause unless it is the
11869 // loop iteration variable of a loop that is associated with the construct.
11870 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_target_parallel_loop,
11871 DSAStack))
11872 return StmtError();
11873
11874 CapturedStmt *CS =
11875 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_loop, AStmt);
11876
11877 OMPLoopDirective::HelperExprs B;
11878 // In presence of clause 'collapse', it will define the nested loops number.
11879 unsigned NestedLoopCount =
11880 checkOpenMPLoop(DKind: OMPD_target_parallel_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11881 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11882 VarsWithImplicitDSA, Built&: B);
11883 if (NestedLoopCount == 0)
11884 return StmtError();
11885
11886 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11887 "omp loop exprs were not built");
11888
11889 return OMPTargetParallelGenericLoopDirective::Create(
11890 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11891}
11892
11893StmtResult SemaOpenMP::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
11894 Stmt *AStmt,
11895 SourceLocation StartLoc,
11896 SourceLocation EndLoc) {
11897 if (!AStmt)
11898 return StmtError();
11899
11900 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11901
11902 SemaRef.setFunctionHasBranchProtectedScope();
11903
11904 // OpenMP [2.7.3, single Construct, Restrictions]
11905 // The copyprivate clause must not be used with the nowait clause.
11906 const OMPClause *Nowait = nullptr;
11907 const OMPClause *Copyprivate = nullptr;
11908 for (const OMPClause *Clause : Clauses) {
11909 if (Clause->getClauseKind() == OMPC_nowait)
11910 Nowait = Clause;
11911 else if (Clause->getClauseKind() == OMPC_copyprivate)
11912 Copyprivate = Clause;
11913 if (Copyprivate && Nowait) {
11914 Diag(Loc: Copyprivate->getBeginLoc(),
11915 DiagID: diag::err_omp_single_copyprivate_with_nowait);
11916 Diag(Loc: Nowait->getBeginLoc(), DiagID: diag::note_omp_nowait_clause_here);
11917 return StmtError();
11918 }
11919 }
11920
11921 return OMPSingleDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11922 AssociatedStmt: AStmt);
11923}
11924
11925StmtResult SemaOpenMP::ActOnOpenMPMasterDirective(Stmt *AStmt,
11926 SourceLocation StartLoc,
11927 SourceLocation EndLoc) {
11928 if (!AStmt)
11929 return StmtError();
11930
11931 SemaRef.setFunctionHasBranchProtectedScope();
11932
11933 return OMPMasterDirective::Create(C: getASTContext(), StartLoc, EndLoc, AssociatedStmt: AStmt);
11934}
11935
11936StmtResult SemaOpenMP::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
11937 Stmt *AStmt,
11938 SourceLocation StartLoc,
11939 SourceLocation EndLoc) {
11940 if (!AStmt)
11941 return StmtError();
11942
11943 SemaRef.setFunctionHasBranchProtectedScope();
11944
11945 return OMPMaskedDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11946 AssociatedStmt: AStmt);
11947}
11948
11949StmtResult SemaOpenMP::ActOnOpenMPCriticalDirective(
11950 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11951 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11952 if (!AStmt)
11953 return StmtError();
11954
11955 bool ErrorFound = false;
11956 llvm::APSInt Hint;
11957 SourceLocation HintLoc;
11958 bool DependentHint = false;
11959 for (const OMPClause *C : Clauses) {
11960 if (C->getClauseKind() == OMPC_hint) {
11961 if (!DirName.getName()) {
11962 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_hint_clause_no_name);
11963 ErrorFound = true;
11964 }
11965 Expr *E = cast<OMPHintClause>(Val: C)->getHint();
11966 if (E->isTypeDependent() || E->isValueDependent() ||
11967 E->isInstantiationDependent()) {
11968 DependentHint = true;
11969 } else {
11970 Hint = E->EvaluateKnownConstInt(Ctx: getASTContext());
11971 HintLoc = C->getBeginLoc();
11972 }
11973 }
11974 }
11975 if (ErrorFound)
11976 return StmtError();
11977 const auto Pair = DSAStack->getCriticalWithHint(Name: DirName);
11978 if (Pair.first && DirName.getName() && !DependentHint) {
11979 if (llvm::APSInt::compareValues(I1: Hint, I2: Pair.second) != 0) {
11980 Diag(Loc: StartLoc, DiagID: diag::err_omp_critical_with_hint);
11981 if (HintLoc.isValid())
11982 Diag(Loc: HintLoc, DiagID: diag::note_omp_critical_hint_here)
11983 << 0 << toString(I: Hint, /*Radix=*/10, /*Signed=*/false);
11984 else
11985 Diag(Loc: StartLoc, DiagID: diag::note_omp_critical_no_hint) << 0;
11986 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11987 Diag(Loc: C->getBeginLoc(), DiagID: diag::note_omp_critical_hint_here)
11988 << 1
11989 << toString(I: C->getHint()->EvaluateKnownConstInt(Ctx: getASTContext()),
11990 /*Radix=*/10, /*Signed=*/false);
11991 } else {
11992 Diag(Loc: Pair.first->getBeginLoc(), DiagID: diag::note_omp_critical_no_hint) << 1;
11993 }
11994 }
11995 }
11996
11997 SemaRef.setFunctionHasBranchProtectedScope();
11998
11999 auto *Dir = OMPCriticalDirective::Create(C: getASTContext(), Name: DirName, StartLoc,
12000 EndLoc, Clauses, AssociatedStmt: AStmt);
12001 if (!Pair.first && DirName.getName() && !DependentHint)
12002 DSAStack->addCriticalWithHint(D: Dir, Hint);
12003 return Dir;
12004}
12005
12006StmtResult SemaOpenMP::ActOnOpenMPParallelForDirective(
12007 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12008 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12009 if (!AStmt)
12010 return StmtError();
12011
12012 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_for, AStmt);
12013
12014 OMPLoopBasedDirective::HelperExprs B;
12015 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
12016 // define the nested loops number.
12017 unsigned NestedLoopCount =
12018 checkOpenMPLoop(DKind: OMPD_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
12019 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt, SemaRef, DSA&: *DSAStack,
12020 VarsWithImplicitDSA, Built&: B);
12021 if (NestedLoopCount == 0)
12022 return StmtError();
12023
12024 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
12025 return StmtError();
12026
12027 return OMPParallelForDirective::Create(
12028 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
12029 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12030}
12031
12032StmtResult SemaOpenMP::ActOnOpenMPParallelForSimdDirective(
12033 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12034 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12035 if (!AStmt)
12036 return StmtError();
12037
12038 CapturedStmt *CS =
12039 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_for_simd, AStmt);
12040
12041 OMPLoopBasedDirective::HelperExprs B;
12042 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
12043 // define the nested loops number.
12044 unsigned NestedLoopCount =
12045 checkOpenMPLoop(DKind: OMPD_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
12046 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
12047 VarsWithImplicitDSA, Built&: B);
12048 if (NestedLoopCount == 0)
12049 return StmtError();
12050
12051 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
12052 return StmtError();
12053
12054 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
12055 return StmtError();
12056
12057 return OMPParallelForSimdDirective::Create(
12058 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
12059}
12060
12061StmtResult SemaOpenMP::ActOnOpenMPParallelMasterDirective(
12062 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12063 SourceLocation EndLoc) {
12064 if (!AStmt)
12065 return StmtError();
12066
12067 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_master, AStmt);
12068
12069 return OMPParallelMasterDirective::Create(
12070 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
12071 DSAStack->getTaskgroupReductionRef());
12072}
12073
12074StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedDirective(
12075 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12076 SourceLocation EndLoc) {
12077 if (!AStmt)
12078 return StmtError();
12079
12080 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_masked, AStmt);
12081
12082 return OMPParallelMaskedDirective::Create(
12083 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
12084 DSAStack->getTaskgroupReductionRef());
12085}
12086
12087StmtResult SemaOpenMP::ActOnOpenMPParallelSectionsDirective(
12088 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12089 SourceLocation EndLoc) {
12090 if (checkSectionsDirective(SemaRef, DKind: OMPD_parallel_sections, AStmt, DSAStack))
12091 return StmtError();
12092
12093 SemaRef.setFunctionHasBranchProtectedScope();
12094
12095 return OMPParallelSectionsDirective::Create(
12096 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
12097 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12098}
12099
12100/// Find and diagnose mutually exclusive clause kinds.
12101static bool checkMutuallyExclusiveClauses(
12102 Sema &S, ArrayRef<OMPClause *> Clauses,
12103 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
12104 const OMPClause *PrevClause = nullptr;
12105 bool ErrorFound = false;
12106 for (const OMPClause *C : Clauses) {
12107 if (llvm::is_contained(Range&: MutuallyExclusiveClauses, Element: C->getClauseKind())) {
12108 if (!PrevClause) {
12109 PrevClause = C;
12110 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
12111 S.Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_clauses_mutually_exclusive)
12112 << getOpenMPClauseNameForDiag(C: C->getClauseKind())
12113 << getOpenMPClauseNameForDiag(C: PrevClause->getClauseKind());
12114 S.Diag(Loc: PrevClause->getBeginLoc(), DiagID: diag::note_omp_previous_clause)
12115 << getOpenMPClauseNameForDiag(C: PrevClause->getClauseKind());
12116 ErrorFound = true;
12117 }
12118 }
12119 }
12120 return ErrorFound;
12121}
12122
12123StmtResult SemaOpenMP::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
12124 Stmt *AStmt,
12125 SourceLocation StartLoc,
12126 SourceLocation EndLoc) {
12127 if (!AStmt)
12128 return StmtError();
12129
12130 // OpenMP 5.0, 2.10.1 task Construct
12131 // If a detach clause appears on the directive, then a mergeable clause cannot
12132 // appear on the same directive.
12133 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
12134 MutuallyExclusiveClauses: {OMPC_detach, OMPC_mergeable}))
12135 return StmtError();
12136
12137 // Check for conflicting capture kinds on structured bindings.
12138 if (checkClausesForDecompositionConflicts(SemaRef, DKind: OMPD_task, Clauses, Body: AStmt))
12139 return StmtError();
12140
12141 setBranchProtectedScope(SemaRef, DKind: OMPD_task, AStmt);
12142
12143 return OMPTaskDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
12144 AssociatedStmt: AStmt, DSAStack->isCancelRegion());
12145}
12146
12147StmtResult SemaOpenMP::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
12148 SourceLocation EndLoc) {
12149 return OMPTaskyieldDirective::Create(C: getASTContext(), StartLoc, EndLoc);
12150}
12151
12152StmtResult SemaOpenMP::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
12153 SourceLocation EndLoc) {
12154 return OMPBarrierDirective::Create(C: getASTContext(), StartLoc, EndLoc);
12155}
12156
12157StmtResult SemaOpenMP::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
12158 SourceLocation StartLoc,
12159 SourceLocation EndLoc,
12160 bool InExContext) {
12161 const OMPAtClause *AtC =
12162 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
12163
12164 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
12165 Diag(Loc: AtC->getAtKindKwLoc(), DiagID: diag::err_omp_unexpected_execution_modifier);
12166 return StmtError();
12167 }
12168
12169 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
12170 const OMPSeverityClause *SeverityC =
12171 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
12172 const OMPMessageClause *MessageC =
12173 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
12174 std::optional<std::string> SL =
12175 MessageC ? MessageC->tryEvaluateString(Ctx&: getASTContext()) : std::nullopt;
12176
12177 if (MessageC && !SL)
12178 Diag(Loc: MessageC->getMessageString()->getBeginLoc(),
12179 DiagID: diag::warn_clause_expected_string)
12180 << getOpenMPClauseNameForDiag(C: OMPC_message) << 1;
12181 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
12182 Diag(Loc: SeverityC->getSeverityKindKwLoc(), DiagID: diag::warn_diagnose_if_succeeded)
12183 << SL.value_or(u: "WARNING");
12184 else
12185 Diag(Loc: StartLoc, DiagID: diag::err_diagnose_if_succeeded) << SL.value_or(u: "ERROR");
12186 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
12187 return StmtError();
12188 }
12189
12190 return OMPErrorDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
12191}
12192
12193StmtResult
12194SemaOpenMP::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
12195 SourceLocation StartLoc,
12196 SourceLocation EndLoc) {
12197 const OMPNowaitClause *NowaitC =
12198 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
12199 bool HasDependC =
12200 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
12201 .empty();
12202 if (NowaitC && !HasDependC) {
12203 Diag(Loc: StartLoc, DiagID: diag::err_omp_nowait_clause_without_depend);
12204 return StmtError();
12205 }
12206
12207 return OMPTaskwaitDirective::Create(C: getASTContext(), StartLoc, EndLoc,
12208 Clauses);
12209}
12210
12211StmtResult
12212SemaOpenMP::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
12213 Stmt *AStmt, SourceLocation StartLoc,
12214 SourceLocation EndLoc) {
12215 if (!AStmt)
12216 return StmtError();
12217
12218 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
12219
12220 SemaRef.setFunctionHasBranchProtectedScope();
12221
12222 return OMPTaskgroupDirective::Create(C: getASTContext(), StartLoc, EndLoc,
12223 Clauses, AssociatedStmt: AStmt,
12224 DSAStack->getTaskgroupReductionRef());
12225}
12226
12227StmtResult SemaOpenMP::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
12228 SourceLocation StartLoc,
12229 SourceLocation EndLoc) {
12230 OMPFlushClause *FC = nullptr;
12231 OMPClause *OrderClause = nullptr;
12232 for (OMPClause *C : Clauses) {
12233 if (C->getClauseKind() == OMPC_flush)
12234 FC = cast<OMPFlushClause>(Val: C);
12235 else
12236 OrderClause = C;
12237 }
12238 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
12239 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12240 SourceLocation MemOrderLoc;
12241 for (const OMPClause *C : Clauses) {
12242 if (C->getClauseKind() == OMPC_acq_rel ||
12243 C->getClauseKind() == OMPC_acquire ||
12244 C->getClauseKind() == OMPC_release ||
12245 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
12246 if (MemOrderKind != OMPC_unknown) {
12247 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_several_mem_order_clauses)
12248 << getOpenMPDirectiveName(D: OMPD_flush, V: OMPVersion) << 1
12249 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12250 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
12251 << getOpenMPClauseNameForDiag(C: MemOrderKind);
12252 } else {
12253 MemOrderKind = C->getClauseKind();
12254 MemOrderLoc = C->getBeginLoc();
12255 }
12256 }
12257 }
12258 if (FC && OrderClause) {
12259 Diag(Loc: FC->getLParenLoc(), DiagID: diag::err_omp_flush_order_clause_and_list)
12260 << getOpenMPClauseNameForDiag(C: OrderClause->getClauseKind());
12261 Diag(Loc: OrderClause->getBeginLoc(), DiagID: diag::note_omp_flush_order_clause_here)
12262 << getOpenMPClauseNameForDiag(C: OrderClause->getClauseKind());
12263 return StmtError();
12264 }
12265 return OMPFlushDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
12266}
12267
12268StmtResult SemaOpenMP::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
12269 SourceLocation StartLoc,
12270 SourceLocation EndLoc) {
12271 if (Clauses.empty()) {
12272 Diag(Loc: StartLoc, DiagID: diag::err_omp_depobj_expected);
12273 return StmtError();
12274 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
12275 Diag(Loc: Clauses[0]->getBeginLoc(), DiagID: diag::err_omp_depobj_expected);
12276 return StmtError();
12277 }
12278 // Only depobj expression and another single clause is allowed.
12279 if (Clauses.size() > 2) {
12280 Diag(Loc: Clauses[2]->getBeginLoc(),
12281 DiagID: diag::err_omp_depobj_single_clause_expected);
12282 return StmtError();
12283 } else if (Clauses.size() < 1) {
12284 Diag(Loc: Clauses[0]->getEndLoc(), DiagID: diag::err_omp_depobj_single_clause_expected);
12285 return StmtError();
12286 }
12287 return OMPDepobjDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
12288}
12289
12290StmtResult SemaOpenMP::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
12291 SourceLocation StartLoc,
12292 SourceLocation EndLoc) {
12293 // Check that exactly one clause is specified.
12294 if (Clauses.size() != 1) {
12295 Diag(Loc: Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
12296 DiagID: diag::err_omp_scan_single_clause_expected);
12297 return StmtError();
12298 }
12299 // Check that scan directive is used in the scope of the OpenMP loop body.
12300 if (Scope *S = DSAStack->getCurScope()) {
12301 Scope *ParentS = S->getParent();
12302 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
12303 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
12304 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
12305 return StmtError(Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_device_directive)
12306 << getOpenMPDirectiveName(D: OMPD_scan, V: OMPVersion) << 5);
12307 }
12308 }
12309 // Check that only one instance of scan directives is used in the same outer
12310 // region.
12311 if (DSAStack->doesParentHasScanDirective()) {
12312 Diag(Loc: StartLoc, DiagID: diag::err_omp_several_directives_in_region) << "scan";
12313 Diag(DSAStack->getParentScanDirectiveLoc(),
12314 DiagID: diag::note_omp_previous_directive)
12315 << "scan";
12316 return StmtError();
12317 }
12318 DSAStack->setParentHasScanDirective(StartLoc);
12319 return OMPScanDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
12320}
12321
12322StmtResult
12323SemaOpenMP::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
12324 Stmt *AStmt, SourceLocation StartLoc,
12325 SourceLocation EndLoc) {
12326 const OMPClause *DependFound = nullptr;
12327 const OMPClause *DependSourceClause = nullptr;
12328 const OMPClause *DependSinkClause = nullptr;
12329 const OMPClause *DoacrossFound = nullptr;
12330 const OMPClause *DoacrossSourceClause = nullptr;
12331 const OMPClause *DoacrossSinkClause = nullptr;
12332 bool ErrorFound = false;
12333 const OMPThreadsClause *TC = nullptr;
12334 const OMPSIMDClause *SC = nullptr;
12335 for (const OMPClause *C : Clauses) {
12336 auto DOC = dyn_cast<OMPDoacrossClause>(Val: C);
12337 auto DC = dyn_cast<OMPDependClause>(Val: C);
12338 if (DC || DOC) {
12339 DependFound = DC ? C : nullptr;
12340 DoacrossFound = DOC ? C : nullptr;
12341 OMPDoacrossKind ODK;
12342 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
12343 (DOC && (ODK.isSource(C: DOC)))) {
12344 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
12345 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
12346 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_more_one_clause)
12347 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
12348 V: OMPVersion)
12349 << getOpenMPClauseNameForDiag(C: DC ? OMPC_depend : OMPC_doacross)
12350 << 2;
12351 ErrorFound = true;
12352 } else {
12353 if (DC)
12354 DependSourceClause = C;
12355 else
12356 DoacrossSourceClause = C;
12357 }
12358 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
12359 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_sink_and_source_not_allowed)
12360 << (DC ? "depend" : "doacross") << 0;
12361 ErrorFound = true;
12362 }
12363 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
12364 (DOC && (ODK.isSink(C: DOC) || ODK.isSinkIter(C: DOC)))) {
12365 if (DependSourceClause || DoacrossSourceClause) {
12366 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_sink_and_source_not_allowed)
12367 << (DC ? "depend" : "doacross") << 1;
12368 ErrorFound = true;
12369 }
12370 if (DC)
12371 DependSinkClause = C;
12372 else
12373 DoacrossSinkClause = C;
12374 }
12375 } else if (C->getClauseKind() == OMPC_threads) {
12376 TC = cast<OMPThreadsClause>(Val: C);
12377 } else if (C->getClauseKind() == OMPC_simd) {
12378 SC = cast<OMPSIMDClause>(Val: C);
12379 }
12380 }
12381 if (!ErrorFound && !SC &&
12382 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
12383 // OpenMP [2.8.1,simd Construct, Restrictions]
12384 // An ordered construct with the simd clause is the only OpenMP construct
12385 // that can appear in the simd region.
12386 Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_simd)
12387 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
12388 ErrorFound = true;
12389 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
12390 SourceLocation Loc =
12391 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
12392 Diag(Loc, DiagID: diag::err_omp_depend_clause_thread_simd)
12393 << getOpenMPClauseNameForDiag(C: DependFound ? OMPC_depend : OMPC_doacross)
12394 << getOpenMPClauseNameForDiag(C: TC ? TC->getClauseKind()
12395 : SC->getClauseKind());
12396 ErrorFound = true;
12397 } else if ((DependFound || DoacrossFound) &&
12398 !DSAStack->getParentOrderedRegionParam().first) {
12399 SourceLocation Loc =
12400 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
12401 Diag(Loc, DiagID: diag::err_omp_ordered_directive_without_param)
12402 << getOpenMPClauseNameForDiag(C: DependFound ? OMPC_depend
12403 : OMPC_doacross);
12404 ErrorFound = true;
12405 } else if (TC || Clauses.empty()) {
12406 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
12407 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
12408 Diag(Loc: ErrLoc, DiagID: diag::err_omp_ordered_directive_with_param)
12409 << (TC != nullptr);
12410 Diag(Loc: Param->getBeginLoc(), DiagID: diag::note_omp_ordered_param) << 1;
12411 ErrorFound = true;
12412 }
12413 }
12414 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
12415 return StmtError();
12416
12417 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
12418 // During execution of an iteration of a worksharing-loop or a loop nest
12419 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
12420 // must not execute more than one ordered region corresponding to an ordered
12421 // construct without a depend clause.
12422 if (!DependFound && !DoacrossFound) {
12423 if (DSAStack->doesParentHasOrderedDirective()) {
12424 Diag(Loc: StartLoc, DiagID: diag::err_omp_several_directives_in_region) << "ordered";
12425 Diag(DSAStack->getParentOrderedDirectiveLoc(),
12426 DiagID: diag::note_omp_previous_directive)
12427 << "ordered";
12428 return StmtError();
12429 }
12430 DSAStack->setParentHasOrderedDirective(StartLoc);
12431 }
12432
12433 if (AStmt) {
12434 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
12435
12436 SemaRef.setFunctionHasBranchProtectedScope();
12437 }
12438
12439 if (!AStmt)
12440 return OMPOrderedStandaloneDirective::Create(C: getASTContext(), StartLoc,
12441 EndLoc, Clauses);
12442 return OMPOrderedBlockAssocDirective::Create(C: getASTContext(), StartLoc,
12443 EndLoc, Clauses, AssociatedStmt: AStmt);
12444}
12445
12446namespace {
12447/// Helper class for checking expression in 'omp atomic [update]'
12448/// construct.
12449class OpenMPAtomicUpdateChecker {
12450 /// Error results for atomic update expressions.
12451 enum ExprAnalysisErrorCode {
12452 /// A statement is not an expression statement.
12453 NotAnExpression,
12454 /// Expression is not builtin binary or unary operation.
12455 NotABinaryOrUnaryExpression,
12456 /// Unary operation is not post-/pre- increment/decrement operation.
12457 NotAnUnaryIncDecExpression,
12458 /// An expression is not of scalar type.
12459 NotAScalarType,
12460 /// A binary operation is not an assignment operation.
12461 NotAnAssignmentOp,
12462 /// RHS part of the binary operation is not a binary expression.
12463 NotABinaryExpression,
12464 /// RHS part is not additive/multiplicative/shift/bitwise binary
12465 /// expression.
12466 NotABinaryOperator,
12467 /// RHS binary operation does not have reference to the updated LHS
12468 /// part.
12469 NotAnUpdateExpression,
12470 /// An expression contains semantical error not related to
12471 /// 'omp atomic [update]'
12472 NotAValidExpression,
12473 /// No errors is found.
12474 NoError
12475 };
12476 /// Reference to Sema.
12477 Sema &SemaRef;
12478 /// A location for note diagnostics (when error is found).
12479 SourceLocation NoteLoc;
12480 /// 'x' lvalue part of the source atomic expression.
12481 Expr *X;
12482 /// 'expr' rvalue part of the source atomic expression.
12483 Expr *E;
12484 /// Helper expression of the form
12485 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
12486 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
12487 Expr *UpdateExpr;
12488 /// Is 'x' a LHS in a RHS part of full update expression. It is
12489 /// important for non-associative operations.
12490 bool IsXLHSInRHSPart;
12491 BinaryOperatorKind Op;
12492 SourceLocation OpLoc;
12493 /// true if the source expression is a postfix unary operation, false
12494 /// if it is a prefix unary operation.
12495 bool IsPostfixUpdate;
12496
12497public:
12498 OpenMPAtomicUpdateChecker(Sema &SemaRef)
12499 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
12500 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
12501 /// Check specified statement that it is suitable for 'atomic update'
12502 /// constructs and extract 'x', 'expr' and Operation from the original
12503 /// expression. If DiagId and NoteId == 0, then only check is performed
12504 /// without error notification.
12505 /// \param DiagId Diagnostic which should be emitted if error is found.
12506 /// \param NoteId Diagnostic note for the main error message.
12507 /// \return true if statement is not an update expression, false otherwise.
12508 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
12509 /// Return the 'x' lvalue part of the source atomic expression.
12510 Expr *getX() const { return X; }
12511 /// Return the 'expr' rvalue part of the source atomic expression.
12512 Expr *getExpr() const { return E; }
12513 /// Return the update expression used in calculation of the updated
12514 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
12515 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
12516 Expr *getUpdateExpr() const { return UpdateExpr; }
12517 /// Return true if 'x' is LHS in RHS part of full update expression,
12518 /// false otherwise.
12519 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
12520
12521 /// true if the source expression is a postfix unary operation, false
12522 /// if it is a prefix unary operation.
12523 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12524
12525private:
12526 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
12527 unsigned NoteId = 0);
12528};
12529
12530bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
12531 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
12532 ExprAnalysisErrorCode ErrorFound = NoError;
12533 SourceLocation ErrorLoc, NoteLoc;
12534 SourceRange ErrorRange, NoteRange;
12535 // Allowed constructs are:
12536 // x = x binop expr;
12537 // x = expr binop x;
12538 if (AtomicBinOp->getOpcode() == BO_Assign) {
12539 X = AtomicBinOp->getLHS();
12540 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
12541 Val: AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
12542 if (AtomicInnerBinOp->isMultiplicativeOp() ||
12543 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
12544 AtomicInnerBinOp->isBitwiseOp()) {
12545 Op = AtomicInnerBinOp->getOpcode();
12546 OpLoc = AtomicInnerBinOp->getOperatorLoc();
12547 Expr *LHS = AtomicInnerBinOp->getLHS();
12548 Expr *RHS = AtomicInnerBinOp->getRHS();
12549 llvm::FoldingSetNodeID XId, LHSId, RHSId;
12550 X->IgnoreParenImpCasts()->Profile(ID&: XId, Context: SemaRef.getASTContext(),
12551 /*Canonical=*/true);
12552 LHS->IgnoreParenImpCasts()->Profile(ID&: LHSId, Context: SemaRef.getASTContext(),
12553 /*Canonical=*/true);
12554 RHS->IgnoreParenImpCasts()->Profile(ID&: RHSId, Context: SemaRef.getASTContext(),
12555 /*Canonical=*/true);
12556 if (XId == LHSId) {
12557 E = RHS;
12558 IsXLHSInRHSPart = true;
12559 } else if (XId == RHSId) {
12560 E = LHS;
12561 IsXLHSInRHSPart = false;
12562 } else {
12563 ErrorLoc = AtomicInnerBinOp->getExprLoc();
12564 ErrorRange = AtomicInnerBinOp->getSourceRange();
12565 NoteLoc = X->getExprLoc();
12566 NoteRange = X->getSourceRange();
12567 ErrorFound = NotAnUpdateExpression;
12568 }
12569 } else {
12570 ErrorLoc = AtomicInnerBinOp->getExprLoc();
12571 ErrorRange = AtomicInnerBinOp->getSourceRange();
12572 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
12573 NoteRange = SourceRange(NoteLoc, NoteLoc);
12574 ErrorFound = NotABinaryOperator;
12575 }
12576 } else {
12577 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
12578 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
12579 ErrorFound = NotABinaryExpression;
12580 }
12581 } else {
12582 ErrorLoc = AtomicBinOp->getExprLoc();
12583 ErrorRange = AtomicBinOp->getSourceRange();
12584 NoteLoc = AtomicBinOp->getOperatorLoc();
12585 NoteRange = SourceRange(NoteLoc, NoteLoc);
12586 ErrorFound = NotAnAssignmentOp;
12587 }
12588 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
12589 SemaRef.Diag(Loc: ErrorLoc, DiagID: DiagId) << ErrorRange;
12590 SemaRef.Diag(Loc: NoteLoc, DiagID: NoteId) << ErrorFound << NoteRange;
12591 return true;
12592 }
12593 if (SemaRef.CurContext->isDependentContext())
12594 E = X = UpdateExpr = nullptr;
12595 return ErrorFound != NoError;
12596}
12597
12598bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
12599 unsigned NoteId) {
12600 ExprAnalysisErrorCode ErrorFound = NoError;
12601 SourceLocation ErrorLoc, NoteLoc;
12602 SourceRange ErrorRange, NoteRange;
12603 // Allowed constructs are:
12604 // x++;
12605 // x--;
12606 // ++x;
12607 // --x;
12608 // x binop= expr;
12609 // x = x binop expr;
12610 // x = expr binop x;
12611 if (auto *AtomicBody = dyn_cast<Expr>(Val: S)) {
12612 AtomicBody = AtomicBody->IgnoreParenImpCasts();
12613 if (AtomicBody->getType()->isScalarType() ||
12614 AtomicBody->isInstantiationDependent()) {
12615 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
12616 Val: AtomicBody->IgnoreParenImpCasts())) {
12617 // Check for Compound Assignment Operation
12618 Op = BinaryOperator::getOpForCompoundAssignment(
12619 Opc: AtomicCompAssignOp->getOpcode());
12620 OpLoc = AtomicCompAssignOp->getOperatorLoc();
12621 E = AtomicCompAssignOp->getRHS();
12622 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
12623 IsXLHSInRHSPart = true;
12624 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
12625 Val: AtomicBody->IgnoreParenImpCasts())) {
12626 // Check for Binary Operation
12627 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
12628 return true;
12629 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
12630 Val: AtomicBody->IgnoreParenImpCasts())) {
12631 // Check for Unary Operation
12632 if (AtomicUnaryOp->isIncrementDecrementOp()) {
12633 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
12634 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
12635 OpLoc = AtomicUnaryOp->getOperatorLoc();
12636 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
12637 E = SemaRef.ActOnIntegerConstant(Loc: OpLoc, /*uint64_t Val=*/Val: 1).get();
12638 IsXLHSInRHSPart = true;
12639 } else {
12640 ErrorFound = NotAnUnaryIncDecExpression;
12641 ErrorLoc = AtomicUnaryOp->getExprLoc();
12642 ErrorRange = AtomicUnaryOp->getSourceRange();
12643 NoteLoc = AtomicUnaryOp->getOperatorLoc();
12644 NoteRange = SourceRange(NoteLoc, NoteLoc);
12645 }
12646 } else if (!AtomicBody->isInstantiationDependent()) {
12647 ErrorFound = NotABinaryOrUnaryExpression;
12648 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
12649 NoteRange = ErrorRange = AtomicBody->getSourceRange();
12650 } else if (AtomicBody->containsErrors()) {
12651 ErrorFound = NotAValidExpression;
12652 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
12653 NoteRange = ErrorRange = AtomicBody->getSourceRange();
12654 }
12655 } else {
12656 ErrorFound = NotAScalarType;
12657 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
12658 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12659 }
12660 } else {
12661 ErrorFound = NotAnExpression;
12662 NoteLoc = ErrorLoc = S->getBeginLoc();
12663 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12664 }
12665 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
12666 SemaRef.Diag(Loc: ErrorLoc, DiagID: DiagId) << ErrorRange;
12667 SemaRef.Diag(Loc: NoteLoc, DiagID: NoteId) << ErrorFound << NoteRange;
12668 return true;
12669 }
12670 if (SemaRef.CurContext->isDependentContext())
12671 E = X = UpdateExpr = nullptr;
12672 if (ErrorFound == NoError && E && X && !E->containsErrors() &&
12673 !X->containsErrors()) {
12674 // Build an update expression of form 'OpaqueValueExpr(x) binop
12675 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
12676 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
12677 auto *OVEX = new (SemaRef.getASTContext())
12678 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
12679 auto *OVEExpr = new (SemaRef.getASTContext())
12680 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
12681 ExprResult Update =
12682 SemaRef.CreateBuiltinBinOp(OpLoc, Opc: Op, LHSExpr: IsXLHSInRHSPart ? OVEX : OVEExpr,
12683 RHSExpr: IsXLHSInRHSPart ? OVEExpr : OVEX);
12684 if (Update.isInvalid())
12685 return true;
12686 Update = SemaRef.PerformImplicitConversion(From: Update.get(), ToType: X->getType(),
12687 Action: AssignmentAction::Casting);
12688 if (Update.isInvalid())
12689 return true;
12690 UpdateExpr = Update.get();
12691 }
12692 return ErrorFound != NoError;
12693}
12694
12695/// Get the node id of the fixed point of an expression \a S.
12696llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
12697 llvm::FoldingSetNodeID Id;
12698 S->IgnoreParenImpCasts()->Profile(ID&: Id, Context, Canonical: true);
12699 return Id;
12700}
12701
12702/// Check if two expressions are same.
12703bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
12704 const Expr *RHS) {
12705 return getNodeId(Context, S: LHS) == getNodeId(Context, S: RHS);
12706}
12707
12708class OpenMPAtomicCompareChecker {
12709public:
12710 /// All kinds of errors that can occur in `atomic compare`
12711 enum ErrorTy {
12712 /// Empty compound statement.
12713 NoStmt = 0,
12714 /// More than one statement in a compound statement.
12715 MoreThanOneStmt,
12716 /// Not an assignment binary operator.
12717 NotAnAssignment,
12718 /// Not a conditional operator.
12719 NotCondOp,
12720 /// Wrong false expr. According to the spec, 'x' should be at the false
12721 /// expression of a conditional expression.
12722 WrongFalseExpr,
12723 /// The condition of a conditional expression is not a binary operator.
12724 NotABinaryOp,
12725 /// Invalid binary operator (not <, >, or ==).
12726 InvalidBinaryOp,
12727 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
12728 InvalidComparison,
12729 /// X is not a lvalue.
12730 XNotLValue,
12731 /// Not a scalar.
12732 NotScalar,
12733 /// Not an integer.
12734 NotInteger,
12735 /// 'else' statement is not expected.
12736 UnexpectedElse,
12737 /// Not an equality operator.
12738 NotEQ,
12739 /// Invalid assignment (not v == x).
12740 InvalidAssignment,
12741 /// Not if statement
12742 NotIfStmt,
12743 /// More than two statements in a compound statement.
12744 MoreThanTwoStmts,
12745 /// Not a compound statement.
12746 NotCompoundStmt,
12747 /// No else statement.
12748 NoElse,
12749 /// Not 'if (r)'.
12750 InvalidCondition,
12751 /// No error.
12752 NoError,
12753 };
12754
12755 struct ErrorInfoTy {
12756 ErrorTy Error;
12757 SourceLocation ErrorLoc;
12758 SourceRange ErrorRange;
12759 SourceLocation NoteLoc;
12760 SourceRange NoteRange;
12761 };
12762
12763 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
12764
12765 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
12766 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12767
12768 Expr *getX() const { return X; }
12769 Expr *getE() const { return E; }
12770 Expr *getD() const { return D; }
12771 Expr *getCond() const { return C; }
12772 bool isXBinopExpr() const { return IsXBinopExpr; }
12773
12774protected:
12775 /// Reference to ASTContext
12776 ASTContext &ContextRef;
12777 /// 'x' lvalue part of the source atomic expression.
12778 Expr *X = nullptr;
12779 /// 'expr' or 'e' rvalue part of the source atomic expression.
12780 Expr *E = nullptr;
12781 /// 'd' rvalue part of the source atomic expression.
12782 Expr *D = nullptr;
12783 /// 'cond' part of the source atomic expression. It is in one of the following
12784 /// forms:
12785 /// expr ordop x
12786 /// x ordop expr
12787 /// x == e
12788 /// e == x
12789 Expr *C = nullptr;
12790 /// True if the cond expr is in the form of 'x ordop expr'.
12791 bool IsXBinopExpr = true;
12792
12793 /// Check if it is a valid conditional update statement (cond-update-stmt).
12794 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
12795
12796 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
12797 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12798
12799 /// Check if all captured values have right type.
12800 bool checkType(ErrorInfoTy &ErrorInfo) const;
12801
12802 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
12803 bool ShouldBeLValue, bool ShouldBeInteger = false) {
12804 if (E->isInstantiationDependent())
12805 return true;
12806
12807 if (ShouldBeLValue && !E->isLValue()) {
12808 ErrorInfo.Error = ErrorTy::XNotLValue;
12809 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12810 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12811 return false;
12812 }
12813
12814 QualType QTy = E->getType();
12815 if (!QTy->isScalarType()) {
12816 ErrorInfo.Error = ErrorTy::NotScalar;
12817 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12818 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12819 return false;
12820 }
12821 if (ShouldBeInteger && !QTy->isIntegerType()) {
12822 ErrorInfo.Error = ErrorTy::NotInteger;
12823 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12824 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12825 return false;
12826 }
12827
12828 return true;
12829 }
12830};
12831
12832bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
12833 ErrorInfoTy &ErrorInfo) {
12834 auto *Then = S->getThen();
12835 if (auto *CS = dyn_cast<CompoundStmt>(Val: Then)) {
12836 if (CS->body_empty()) {
12837 ErrorInfo.Error = ErrorTy::NoStmt;
12838 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12839 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12840 return false;
12841 }
12842 if (CS->size() > 1) {
12843 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12844 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12845 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12846 return false;
12847 }
12848 Then = CS->body_front();
12849 }
12850
12851 auto *BO = dyn_cast<BinaryOperator>(Val: Then);
12852 if (!BO) {
12853 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12854 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12855 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12856 return false;
12857 }
12858 if (BO->getOpcode() != BO_Assign) {
12859 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12860 ErrorInfo.ErrorLoc = BO->getExprLoc();
12861 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12862 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12863 return false;
12864 }
12865
12866 X = BO->getLHS();
12867
12868 auto *Cond = dyn_cast<BinaryOperator>(Val: S->getCond());
12869 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: S->getCond());
12870 Expr *LHS = nullptr;
12871 Expr *RHS = nullptr;
12872 if (Cond) {
12873 LHS = Cond->getLHS();
12874 RHS = Cond->getRHS();
12875 } else if (Call) {
12876 LHS = Call->getArg(Arg: 0);
12877 RHS = Call->getArg(Arg: 1);
12878 } else {
12879 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12880 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12881 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12882 return false;
12883 }
12884
12885 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12886 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12887 C = S->getCond();
12888 D = BO->getRHS();
12889 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
12890 E = RHS;
12891 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12892 E = LHS;
12893 } else {
12894 ErrorInfo.Error = ErrorTy::InvalidComparison;
12895 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12896 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12897 S->getCond()->getSourceRange();
12898 return false;
12899 }
12900 } else if ((Cond &&
12901 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12902 (Call &&
12903 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12904 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12905 E = BO->getRHS();
12906 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS) &&
12907 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS)) {
12908 C = S->getCond();
12909 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: LHS) &&
12910 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12911 C = S->getCond();
12912 IsXBinopExpr = false;
12913 } else {
12914 ErrorInfo.Error = ErrorTy::InvalidComparison;
12915 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12916 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12917 S->getCond()->getSourceRange();
12918 return false;
12919 }
12920 } else {
12921 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12922 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12923 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12924 return false;
12925 }
12926
12927 if (S->getElse()) {
12928 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12929 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12930 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12931 return false;
12932 }
12933
12934 return true;
12935}
12936
12937bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12938 ErrorInfoTy &ErrorInfo) {
12939 auto *BO = dyn_cast<BinaryOperator>(Val: S);
12940 if (!BO) {
12941 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12942 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12943 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12944 return false;
12945 }
12946 if (BO->getOpcode() != BO_Assign) {
12947 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12948 ErrorInfo.ErrorLoc = BO->getExprLoc();
12949 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12950 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12951 return false;
12952 }
12953
12954 X = BO->getLHS();
12955
12956 auto *CO = dyn_cast<ConditionalOperator>(Val: BO->getRHS()->IgnoreParenImpCasts());
12957 if (!CO) {
12958 ErrorInfo.Error = ErrorTy::NotCondOp;
12959 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12960 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12961 return false;
12962 }
12963
12964 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: CO->getFalseExpr())) {
12965 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12966 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12967 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12968 CO->getFalseExpr()->getSourceRange();
12969 return false;
12970 }
12971
12972 auto *Cond = dyn_cast<BinaryOperator>(Val: CO->getCond());
12973 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: CO->getCond());
12974 Expr *LHS = nullptr;
12975 Expr *RHS = nullptr;
12976 if (Cond) {
12977 LHS = Cond->getLHS();
12978 RHS = Cond->getRHS();
12979 } else if (Call) {
12980 LHS = Call->getArg(Arg: 0);
12981 RHS = Call->getArg(Arg: 1);
12982 } else {
12983 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12984 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12985 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12986 CO->getCond()->getSourceRange();
12987 return false;
12988 }
12989
12990 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12991 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12992 C = CO->getCond();
12993 D = CO->getTrueExpr();
12994 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
12995 E = RHS;
12996 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12997 E = LHS;
12998 } else {
12999 ErrorInfo.Error = ErrorTy::InvalidComparison;
13000 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
13001 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13002 CO->getCond()->getSourceRange();
13003 return false;
13004 }
13005 } else if ((Cond &&
13006 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
13007 (Call &&
13008 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
13009 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
13010
13011 E = CO->getTrueExpr();
13012 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS) &&
13013 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS)) {
13014 C = CO->getCond();
13015 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: LHS) &&
13016 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
13017 C = CO->getCond();
13018 IsXBinopExpr = false;
13019 } else {
13020 ErrorInfo.Error = ErrorTy::InvalidComparison;
13021 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
13022 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13023 CO->getCond()->getSourceRange();
13024 return false;
13025 }
13026 } else {
13027 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
13028 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
13029 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13030 CO->getCond()->getSourceRange();
13031 return false;
13032 }
13033
13034 return true;
13035}
13036
13037bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
13038 // 'x' and 'e' cannot be nullptr
13039 assert(X && E && "X and E cannot be nullptr");
13040
13041 if (!CheckValue(E: X, ErrorInfo, ShouldBeLValue: true))
13042 return false;
13043
13044 if (!CheckValue(E, ErrorInfo, ShouldBeLValue: false))
13045 return false;
13046
13047 if (D && !CheckValue(E: D, ErrorInfo, ShouldBeLValue: false))
13048 return false;
13049
13050 return true;
13051}
13052
13053bool OpenMPAtomicCompareChecker::checkStmt(
13054 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
13055 auto *CS = dyn_cast<CompoundStmt>(Val: S);
13056 if (CS) {
13057 if (CS->body_empty()) {
13058 ErrorInfo.Error = ErrorTy::NoStmt;
13059 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13060 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13061 return false;
13062 }
13063
13064 if (CS->size() != 1) {
13065 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13066 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13067 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13068 return false;
13069 }
13070 S = CS->body_front();
13071 }
13072
13073 auto Res = false;
13074
13075 if (auto *IS = dyn_cast<IfStmt>(Val: S)) {
13076 // Check if the statement is in one of the following forms
13077 // (cond-update-stmt):
13078 // if (expr ordop x) { x = expr; }
13079 // if (x ordop expr) { x = expr; }
13080 // if (x == e) { x = d; }
13081 Res = checkCondUpdateStmt(S: IS, ErrorInfo);
13082 } else {
13083 // Check if the statement is in one of the following forms (cond-expr-stmt):
13084 // x = expr ordop x ? expr : x;
13085 // x = x ordop expr ? expr : x;
13086 // x = x == e ? d : x;
13087 Res = checkCondExprStmt(S, ErrorInfo);
13088 }
13089
13090 if (!Res)
13091 return false;
13092
13093 return checkType(ErrorInfo);
13094}
13095
13096class OpenMPAtomicCompareCaptureChecker final
13097 : public OpenMPAtomicCompareChecker {
13098public:
13099 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
13100
13101 Expr *getV() const { return V; }
13102 Expr *getR() const { return R; }
13103 bool isFailOnly() const { return IsFailOnly; }
13104 bool isPostfixUpdate() const { return IsPostfixUpdate; }
13105
13106 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
13107 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
13108
13109private:
13110 bool checkType(ErrorInfoTy &ErrorInfo);
13111
13112 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
13113 // form of 'conditional-update-capture-atomic' structured block on the v5.2
13114 // spec p.p. 82:
13115 // (1) { v = x; cond-update-stmt }
13116 // (2) { cond-update-stmt v = x; }
13117 // (3) if(x == e) { x = d; } else { v = x; }
13118 // (4) { r = x == e; if(r) { x = d; } }
13119 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
13120
13121 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
13122 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
13123
13124 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
13125 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
13126 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
13127
13128 /// 'v' lvalue part of the source atomic expression.
13129 Expr *V = nullptr;
13130 /// 'r' lvalue part of the source atomic expression.
13131 Expr *R = nullptr;
13132 /// If 'v' is only updated when the comparison fails.
13133 bool IsFailOnly = false;
13134 /// If original value of 'x' must be stored in 'v', not an updated one.
13135 bool IsPostfixUpdate = false;
13136};
13137
13138bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
13139 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
13140 return false;
13141
13142 if (V && !CheckValue(E: V, ErrorInfo, ShouldBeLValue: true))
13143 return false;
13144
13145 if (R && !CheckValue(E: R, ErrorInfo, ShouldBeLValue: true, ShouldBeInteger: true))
13146 return false;
13147
13148 return true;
13149}
13150
13151bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
13152 ErrorInfoTy &ErrorInfo) {
13153 IsFailOnly = true;
13154
13155 auto *Then = S->getThen();
13156 if (auto *CS = dyn_cast<CompoundStmt>(Val: Then)) {
13157 if (CS->body_empty()) {
13158 ErrorInfo.Error = ErrorTy::NoStmt;
13159 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13160 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13161 return false;
13162 }
13163 if (CS->size() > 1) {
13164 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13165 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13166 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13167 return false;
13168 }
13169 Then = CS->body_front();
13170 }
13171
13172 auto *BO = dyn_cast<BinaryOperator>(Val: Then);
13173 if (!BO) {
13174 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13175 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
13176 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
13177 return false;
13178 }
13179 if (BO->getOpcode() != BO_Assign) {
13180 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13181 ErrorInfo.ErrorLoc = BO->getExprLoc();
13182 ErrorInfo.NoteLoc = BO->getOperatorLoc();
13183 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13184 return false;
13185 }
13186
13187 X = BO->getLHS();
13188 D = BO->getRHS();
13189
13190 auto *Cond = dyn_cast<BinaryOperator>(Val: S->getCond());
13191 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: S->getCond());
13192 Expr *LHS = nullptr;
13193 Expr *RHS = nullptr;
13194 if (Cond) {
13195 LHS = Cond->getLHS();
13196 RHS = Cond->getRHS();
13197 } else if (Call) {
13198 LHS = Call->getArg(Arg: 0);
13199 RHS = Call->getArg(Arg: 1);
13200 } else {
13201 ErrorInfo.Error = ErrorTy::NotABinaryOp;
13202 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
13203 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
13204 return false;
13205 }
13206 if ((Cond && Cond->getOpcode() != BO_EQ) ||
13207 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
13208 ErrorInfo.Error = ErrorTy::NotEQ;
13209 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
13210 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
13211 return false;
13212 }
13213
13214 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
13215 E = RHS;
13216 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
13217 E = LHS;
13218 } else {
13219 ErrorInfo.Error = ErrorTy::InvalidComparison;
13220 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
13221 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
13222 return false;
13223 }
13224
13225 C = S->getCond();
13226
13227 if (!S->getElse()) {
13228 ErrorInfo.Error = ErrorTy::NoElse;
13229 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
13230 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
13231 return false;
13232 }
13233
13234 auto *Else = S->getElse();
13235 if (auto *CS = dyn_cast<CompoundStmt>(Val: Else)) {
13236 if (CS->body_empty()) {
13237 ErrorInfo.Error = ErrorTy::NoStmt;
13238 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13239 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13240 return false;
13241 }
13242 if (CS->size() > 1) {
13243 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13244 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13245 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
13246 return false;
13247 }
13248 Else = CS->body_front();
13249 }
13250
13251 auto *ElseBO = dyn_cast<BinaryOperator>(Val: Else);
13252 if (!ElseBO) {
13253 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13254 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
13255 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
13256 return false;
13257 }
13258 if (ElseBO->getOpcode() != BO_Assign) {
13259 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13260 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
13261 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
13262 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
13263 return false;
13264 }
13265
13266 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: ElseBO->getRHS())) {
13267 ErrorInfo.Error = ErrorTy::InvalidAssignment;
13268 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
13269 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13270 ElseBO->getRHS()->getSourceRange();
13271 return false;
13272 }
13273
13274 V = ElseBO->getLHS();
13275
13276 return checkType(ErrorInfo);
13277}
13278
13279bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
13280 ErrorInfoTy &ErrorInfo) {
13281 // We don't check here as they should be already done before call this
13282 // function.
13283 auto *CS = cast<CompoundStmt>(Val: S);
13284 assert(CS->size() == 2 && "CompoundStmt size is not expected");
13285 auto *S1 = cast<BinaryOperator>(Val: CS->body_front());
13286 auto *S2 = cast<IfStmt>(Val: CS->body_back());
13287 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
13288
13289 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: S1->getLHS(), RHS: S2->getCond())) {
13290 ErrorInfo.Error = ErrorTy::InvalidCondition;
13291 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
13292 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
13293 return false;
13294 }
13295
13296 R = S1->getLHS();
13297
13298 auto *Then = S2->getThen();
13299 if (auto *ThenCS = dyn_cast<CompoundStmt>(Val: Then)) {
13300 if (ThenCS->body_empty()) {
13301 ErrorInfo.Error = ErrorTy::NoStmt;
13302 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
13303 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
13304 return false;
13305 }
13306 if (ThenCS->size() > 1) {
13307 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13308 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
13309 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
13310 return false;
13311 }
13312 Then = ThenCS->body_front();
13313 }
13314
13315 auto *ThenBO = dyn_cast<BinaryOperator>(Val: Then);
13316 if (!ThenBO) {
13317 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13318 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
13319 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
13320 return false;
13321 }
13322 if (ThenBO->getOpcode() != BO_Assign) {
13323 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13324 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
13325 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
13326 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
13327 return false;
13328 }
13329
13330 X = ThenBO->getLHS();
13331 D = ThenBO->getRHS();
13332
13333 auto *BO = cast<BinaryOperator>(Val: S1->getRHS()->IgnoreImpCasts());
13334 if (BO->getOpcode() != BO_EQ) {
13335 ErrorInfo.Error = ErrorTy::NotEQ;
13336 ErrorInfo.ErrorLoc = BO->getExprLoc();
13337 ErrorInfo.NoteLoc = BO->getOperatorLoc();
13338 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13339 return false;
13340 }
13341
13342 C = BO;
13343
13344 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: BO->getLHS())) {
13345 E = BO->getRHS();
13346 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: BO->getRHS())) {
13347 E = BO->getLHS();
13348 } else {
13349 ErrorInfo.Error = ErrorTy::InvalidComparison;
13350 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
13351 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13352 return false;
13353 }
13354
13355 if (S2->getElse()) {
13356 IsFailOnly = true;
13357
13358 auto *Else = S2->getElse();
13359 if (auto *ElseCS = dyn_cast<CompoundStmt>(Val: Else)) {
13360 if (ElseCS->body_empty()) {
13361 ErrorInfo.Error = ErrorTy::NoStmt;
13362 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
13363 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
13364 return false;
13365 }
13366 if (ElseCS->size() > 1) {
13367 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13368 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
13369 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
13370 return false;
13371 }
13372 Else = ElseCS->body_front();
13373 }
13374
13375 auto *ElseBO = dyn_cast<BinaryOperator>(Val: Else);
13376 if (!ElseBO) {
13377 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13378 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
13379 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
13380 return false;
13381 }
13382 if (ElseBO->getOpcode() != BO_Assign) {
13383 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13384 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
13385 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
13386 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
13387 return false;
13388 }
13389 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: ElseBO->getRHS())) {
13390 ErrorInfo.Error = ErrorTy::InvalidAssignment;
13391 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
13392 ErrorInfo.NoteLoc = X->getExprLoc();
13393 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
13394 ErrorInfo.NoteRange = X->getSourceRange();
13395 return false;
13396 }
13397
13398 V = ElseBO->getLHS();
13399 }
13400
13401 return checkType(ErrorInfo);
13402}
13403
13404bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
13405 ErrorInfoTy &ErrorInfo) {
13406 // if(x == e) { x = d; } else { v = x; }
13407 if (auto *IS = dyn_cast<IfStmt>(Val: S))
13408 return checkForm3(S: IS, ErrorInfo);
13409
13410 auto *CS = dyn_cast<CompoundStmt>(Val: S);
13411 if (!CS) {
13412 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
13413 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
13414 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
13415 return false;
13416 }
13417 if (CS->body_empty()) {
13418 ErrorInfo.Error = ErrorTy::NoStmt;
13419 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13420 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13421 return false;
13422 }
13423
13424 // { if(x == e) { x = d; } else { v = x; } }
13425 if (CS->size() == 1) {
13426 auto *IS = dyn_cast<IfStmt>(Val: CS->body_front());
13427 if (!IS) {
13428 ErrorInfo.Error = ErrorTy::NotIfStmt;
13429 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
13430 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13431 CS->body_front()->getSourceRange();
13432 return false;
13433 }
13434
13435 return checkForm3(S: IS, ErrorInfo);
13436 } else if (CS->size() == 2) {
13437 auto *S1 = CS->body_front();
13438 auto *S2 = CS->body_back();
13439
13440 Stmt *UpdateStmt = nullptr;
13441 Stmt *CondUpdateStmt = nullptr;
13442 Stmt *CondExprStmt = nullptr;
13443
13444 if (auto *BO = dyn_cast<BinaryOperator>(Val: S1)) {
13445 // It could be one of the following cases:
13446 // { v = x; cond-update-stmt }
13447 // { v = x; cond-expr-stmt }
13448 // { cond-expr-stmt; v = x; }
13449 // form 45
13450 if (isa<BinaryOperator>(Val: BO->getRHS()->IgnoreImpCasts()) ||
13451 isa<ConditionalOperator>(Val: BO->getRHS()->IgnoreImpCasts())) {
13452 // check if form 45
13453 if (isa<IfStmt>(Val: S2))
13454 return checkForm45(S: CS, ErrorInfo);
13455 // { cond-expr-stmt; v = x; }
13456 CondExprStmt = S1;
13457 UpdateStmt = S2;
13458 } else {
13459 IsPostfixUpdate = true;
13460 UpdateStmt = S1;
13461 if (isa<IfStmt>(Val: S2)) {
13462 // { v = x; cond-update-stmt }
13463 CondUpdateStmt = S2;
13464 } else {
13465 // { v = x; cond-expr-stmt }
13466 CondExprStmt = S2;
13467 }
13468 }
13469 } else {
13470 // { cond-update-stmt v = x; }
13471 UpdateStmt = S2;
13472 CondUpdateStmt = S1;
13473 }
13474
13475 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
13476 auto *IS = dyn_cast<IfStmt>(Val: CUS);
13477 if (!IS) {
13478 ErrorInfo.Error = ErrorTy::NotIfStmt;
13479 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
13480 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
13481 return false;
13482 }
13483
13484 return checkCondUpdateStmt(S: IS, ErrorInfo);
13485 };
13486
13487 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
13488 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
13489 auto *BO = dyn_cast<BinaryOperator>(Val: US);
13490 if (!BO) {
13491 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13492 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
13493 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
13494 return false;
13495 }
13496 if (BO->getOpcode() != BO_Assign) {
13497 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13498 ErrorInfo.ErrorLoc = BO->getExprLoc();
13499 ErrorInfo.NoteLoc = BO->getOperatorLoc();
13500 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13501 return false;
13502 }
13503 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: this->X, RHS: BO->getRHS())) {
13504 ErrorInfo.Error = ErrorTy::InvalidAssignment;
13505 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
13506 ErrorInfo.NoteLoc = this->X->getExprLoc();
13507 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
13508 ErrorInfo.NoteRange = this->X->getSourceRange();
13509 return false;
13510 }
13511
13512 this->V = BO->getLHS();
13513
13514 return true;
13515 };
13516
13517 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
13518 return false;
13519 if (CondExprStmt && !checkCondExprStmt(S: CondExprStmt, ErrorInfo))
13520 return false;
13521 if (!CheckUpdateStmt(UpdateStmt))
13522 return false;
13523 } else {
13524 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
13525 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13526 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13527 return false;
13528 }
13529
13530 return checkType(ErrorInfo);
13531}
13532} // namespace
13533
13534StmtResult SemaOpenMP::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
13535 Stmt *AStmt,
13536 SourceLocation StartLoc,
13537 SourceLocation EndLoc) {
13538 ASTContext &Context = getASTContext();
13539 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
13540 // Register location of the first atomic directive.
13541 DSAStack->addAtomicDirectiveLoc(Loc: StartLoc);
13542 if (!AStmt)
13543 return StmtError();
13544
13545 // 1.2.2 OpenMP Language Terminology
13546 // Structured block - An executable statement with a single entry at the
13547 // top and a single exit at the bottom.
13548 // The point of exit cannot be a branch out of the structured block.
13549 // longjmp() and throw() must not violate the entry/exit criteria.
13550 OpenMPClauseKind AtomicKind = OMPC_unknown;
13551 SourceLocation AtomicKindLoc;
13552 OpenMPClauseKind MemOrderKind = OMPC_unknown;
13553 SourceLocation MemOrderLoc;
13554 bool MutexClauseEncountered = false;
13555 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
13556 for (const OMPClause *C : Clauses) {
13557 switch (C->getClauseKind()) {
13558 case OMPC_read:
13559 case OMPC_write:
13560 case OMPC_update:
13561 MutexClauseEncountered = true;
13562 [[fallthrough]];
13563 case OMPC_capture:
13564 case OMPC_compare: {
13565 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
13566 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_several_clauses)
13567 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13568 Diag(Loc: AtomicKindLoc, DiagID: diag::note_omp_previous_mem_order_clause)
13569 << getOpenMPClauseNameForDiag(C: AtomicKind);
13570 } else {
13571 AtomicKind = C->getClauseKind();
13572 AtomicKindLoc = C->getBeginLoc();
13573 if (!EncounteredAtomicKinds.insert(V: C->getClauseKind()).second) {
13574 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_several_clauses)
13575 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13576 Diag(Loc: AtomicKindLoc, DiagID: diag::note_omp_previous_mem_order_clause)
13577 << getOpenMPClauseNameForDiag(C: AtomicKind);
13578 }
13579 }
13580 break;
13581 }
13582 case OMPC_weak:
13583 case OMPC_fail: {
13584 if (!EncounteredAtomicKinds.contains(V: OMPC_compare)) {
13585 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_no_compare)
13586 << getOpenMPClauseNameForDiag(C: C->getClauseKind())
13587 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13588 return StmtError();
13589 }
13590 break;
13591 }
13592 case OMPC_seq_cst:
13593 case OMPC_acq_rel:
13594 case OMPC_acquire:
13595 case OMPC_release:
13596 case OMPC_relaxed: {
13597 if (MemOrderKind != OMPC_unknown) {
13598 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_several_mem_order_clauses)
13599 << getOpenMPDirectiveName(D: OMPD_atomic, V: OMPVersion) << 0
13600 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13601 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
13602 << getOpenMPClauseNameForDiag(C: MemOrderKind);
13603 } else {
13604 MemOrderKind = C->getClauseKind();
13605 MemOrderLoc = C->getBeginLoc();
13606 }
13607 break;
13608 }
13609 // The following clauses are allowed, but we don't need to do anything here.
13610 case OMPC_hint:
13611 break;
13612 default:
13613 llvm_unreachable("unknown clause is encountered");
13614 }
13615 }
13616 bool IsCompareCapture = false;
13617 if (EncounteredAtomicKinds.contains(V: OMPC_compare) &&
13618 EncounteredAtomicKinds.contains(V: OMPC_capture)) {
13619 IsCompareCapture = true;
13620 AtomicKind = OMPC_compare;
13621 }
13622 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
13623 // If atomic-clause is read then memory-order-clause must not be acq_rel or
13624 // release.
13625 // If atomic-clause is write then memory-order-clause must not be acq_rel or
13626 // acquire.
13627 // If atomic-clause is update or not present then memory-order-clause must not
13628 // be acq_rel or acquire.
13629 if ((AtomicKind == OMPC_read &&
13630 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
13631 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
13632 AtomicKind == OMPC_unknown) &&
13633 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
13634 SourceLocation Loc = AtomicKindLoc;
13635 if (AtomicKind == OMPC_unknown)
13636 Loc = StartLoc;
13637 Diag(Loc, DiagID: diag::err_omp_atomic_incompatible_mem_order_clause)
13638 << getOpenMPClauseNameForDiag(C: AtomicKind)
13639 << (AtomicKind == OMPC_unknown ? 1 : 0)
13640 << getOpenMPClauseNameForDiag(C: MemOrderKind);
13641 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
13642 << getOpenMPClauseNameForDiag(C: MemOrderKind);
13643 }
13644
13645 Stmt *Body = AStmt;
13646 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: Body))
13647 Body = EWC->getSubExpr();
13648
13649 Expr *X = nullptr;
13650 Expr *V = nullptr;
13651 Expr *E = nullptr;
13652 Expr *UE = nullptr;
13653 Expr *D = nullptr;
13654 Expr *CE = nullptr;
13655 Expr *R = nullptr;
13656 bool IsXLHSInRHSPart = false;
13657 bool IsPostfixUpdate = false;
13658 bool IsFailOnly = false;
13659 // OpenMP [2.12.6, atomic Construct]
13660 // In the next expressions:
13661 // * x and v (as applicable) are both l-value expressions with scalar type.
13662 // * During the execution of an atomic region, multiple syntactic
13663 // occurrences of x must designate the same storage location.
13664 // * Neither of v and expr (as applicable) may access the storage location
13665 // designated by x.
13666 // * Neither of x and expr (as applicable) may access the storage location
13667 // designated by v.
13668 // * expr is an expression with scalar type.
13669 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
13670 // * binop, binop=, ++, and -- are not overloaded operators.
13671 // * The expression x binop expr must be numerically equivalent to x binop
13672 // (expr). This requirement is satisfied if the operators in expr have
13673 // precedence greater than binop, or by using parentheses around expr or
13674 // subexpressions of expr.
13675 // * The expression expr binop x must be numerically equivalent to (expr)
13676 // binop x. This requirement is satisfied if the operators in expr have
13677 // precedence equal to or greater than binop, or by using parentheses around
13678 // expr or subexpressions of expr.
13679 // * For forms that allow multiple occurrences of x, the number of times
13680 // that x is evaluated is unspecified.
13681 if (AtomicKind == OMPC_read) {
13682 enum {
13683 NotAnExpression,
13684 NotAnAssignmentOp,
13685 NotAScalarType,
13686 NotAnLValue,
13687 NoError
13688 } ErrorFound = NoError;
13689 SourceLocation ErrorLoc, NoteLoc;
13690 SourceRange ErrorRange, NoteRange;
13691 // If clause is read:
13692 // v = x;
13693 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
13694 const auto *AtomicBinOp =
13695 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
13696 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13697 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
13698 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
13699 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
13700 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
13701 if (!X->isLValue() || !V->isLValue()) {
13702 const Expr *NotLValueExpr = X->isLValue() ? V : X;
13703 ErrorFound = NotAnLValue;
13704 ErrorLoc = AtomicBinOp->getExprLoc();
13705 ErrorRange = AtomicBinOp->getSourceRange();
13706 NoteLoc = NotLValueExpr->getExprLoc();
13707 NoteRange = NotLValueExpr->getSourceRange();
13708 }
13709 } else if (!X->isInstantiationDependent() ||
13710 !V->isInstantiationDependent()) {
13711 const Expr *NotScalarExpr =
13712 (X->isInstantiationDependent() || X->getType()->isScalarType())
13713 ? V
13714 : X;
13715 ErrorFound = NotAScalarType;
13716 ErrorLoc = AtomicBinOp->getExprLoc();
13717 ErrorRange = AtomicBinOp->getSourceRange();
13718 NoteLoc = NotScalarExpr->getExprLoc();
13719 NoteRange = NotScalarExpr->getSourceRange();
13720 }
13721 } else if (!AtomicBody->isInstantiationDependent()) {
13722 ErrorFound = NotAnAssignmentOp;
13723 ErrorLoc = AtomicBody->getExprLoc();
13724 ErrorRange = AtomicBody->getSourceRange();
13725 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13726 : AtomicBody->getExprLoc();
13727 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13728 : AtomicBody->getSourceRange();
13729 }
13730 } else {
13731 ErrorFound = NotAnExpression;
13732 NoteLoc = ErrorLoc = Body->getBeginLoc();
13733 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
13734 }
13735 if (ErrorFound != NoError) {
13736 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_read_not_expression_statement)
13737 << ErrorRange;
13738 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_read_write)
13739 << ErrorFound << NoteRange;
13740 return StmtError();
13741 }
13742 if (SemaRef.CurContext->isDependentContext())
13743 V = X = nullptr;
13744 } else if (AtomicKind == OMPC_write) {
13745 enum {
13746 NotAnExpression,
13747 NotAnAssignmentOp,
13748 NotAScalarType,
13749 NotAnLValue,
13750 NoError
13751 } ErrorFound = NoError;
13752 SourceLocation ErrorLoc, NoteLoc;
13753 SourceRange ErrorRange, NoteRange;
13754 // If clause is write:
13755 // x = expr;
13756 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
13757 const auto *AtomicBinOp =
13758 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
13759 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13760 X = AtomicBinOp->getLHS();
13761 E = AtomicBinOp->getRHS();
13762 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
13763 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
13764 if (!X->isLValue()) {
13765 ErrorFound = NotAnLValue;
13766 ErrorLoc = AtomicBinOp->getExprLoc();
13767 ErrorRange = AtomicBinOp->getSourceRange();
13768 NoteLoc = X->getExprLoc();
13769 NoteRange = X->getSourceRange();
13770 }
13771 } else if (!X->isInstantiationDependent() ||
13772 !E->isInstantiationDependent()) {
13773 const Expr *NotScalarExpr =
13774 (X->isInstantiationDependent() || X->getType()->isScalarType())
13775 ? E
13776 : X;
13777 ErrorFound = NotAScalarType;
13778 ErrorLoc = AtomicBinOp->getExprLoc();
13779 ErrorRange = AtomicBinOp->getSourceRange();
13780 NoteLoc = NotScalarExpr->getExprLoc();
13781 NoteRange = NotScalarExpr->getSourceRange();
13782 }
13783 } else if (!AtomicBody->isInstantiationDependent()) {
13784 ErrorFound = NotAnAssignmentOp;
13785 ErrorLoc = AtomicBody->getExprLoc();
13786 ErrorRange = AtomicBody->getSourceRange();
13787 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13788 : AtomicBody->getExprLoc();
13789 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13790 : AtomicBody->getSourceRange();
13791 }
13792 } else {
13793 ErrorFound = NotAnExpression;
13794 NoteLoc = ErrorLoc = Body->getBeginLoc();
13795 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
13796 }
13797 if (ErrorFound != NoError) {
13798 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_write_not_expression_statement)
13799 << ErrorRange;
13800 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_read_write)
13801 << ErrorFound << NoteRange;
13802 return StmtError();
13803 }
13804 if (SemaRef.CurContext->isDependentContext())
13805 E = X = nullptr;
13806 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
13807 // If clause is update:
13808 // x++;
13809 // x--;
13810 // ++x;
13811 // --x;
13812 // x binop= expr;
13813 // x = x binop expr;
13814 // x = expr binop x;
13815 OpenMPAtomicUpdateChecker Checker(SemaRef);
13816 if (Checker.checkStatement(
13817 S: Body,
13818 DiagId: (AtomicKind == OMPC_update)
13819 ? diag::err_omp_atomic_update_not_expression_statement
13820 : diag::err_omp_atomic_not_expression_statement,
13821 NoteId: diag::note_omp_atomic_update))
13822 return StmtError();
13823 if (!SemaRef.CurContext->isDependentContext()) {
13824 E = Checker.getExpr();
13825 X = Checker.getX();
13826 UE = Checker.getUpdateExpr();
13827 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13828 }
13829 } else if (AtomicKind == OMPC_capture) {
13830 enum {
13831 NotAnAssignmentOp,
13832 NotACompoundStatement,
13833 NotTwoSubstatements,
13834 NotASpecificExpression,
13835 NoError
13836 } ErrorFound = NoError;
13837 SourceLocation ErrorLoc, NoteLoc;
13838 SourceRange ErrorRange, NoteRange;
13839 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
13840 // If clause is a capture:
13841 // v = x++;
13842 // v = x--;
13843 // v = ++x;
13844 // v = --x;
13845 // v = x binop= expr;
13846 // v = x = x binop expr;
13847 // v = x = expr binop x;
13848 const auto *AtomicBinOp =
13849 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
13850 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13851 V = AtomicBinOp->getLHS();
13852 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
13853 OpenMPAtomicUpdateChecker Checker(SemaRef);
13854 if (Checker.checkStatement(
13855 S: Body, DiagId: diag::err_omp_atomic_capture_not_expression_statement,
13856 NoteId: diag::note_omp_atomic_update))
13857 return StmtError();
13858 E = Checker.getExpr();
13859 X = Checker.getX();
13860 UE = Checker.getUpdateExpr();
13861 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13862 IsPostfixUpdate = Checker.isPostfixUpdate();
13863 } else if (!AtomicBody->isInstantiationDependent()) {
13864 ErrorLoc = AtomicBody->getExprLoc();
13865 ErrorRange = AtomicBody->getSourceRange();
13866 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13867 : AtomicBody->getExprLoc();
13868 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13869 : AtomicBody->getSourceRange();
13870 ErrorFound = NotAnAssignmentOp;
13871 }
13872 if (ErrorFound != NoError) {
13873 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_capture_not_expression_statement)
13874 << ErrorRange;
13875 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13876 return StmtError();
13877 }
13878 if (SemaRef.CurContext->isDependentContext())
13879 UE = V = E = X = nullptr;
13880 } else {
13881 // If clause is a capture:
13882 // { v = x; x = expr; }
13883 // { v = x; x++; }
13884 // { v = x; x--; }
13885 // { v = x; ++x; }
13886 // { v = x; --x; }
13887 // { v = x; x binop= expr; }
13888 // { v = x; x = x binop expr; }
13889 // { v = x; x = expr binop x; }
13890 // { x++; v = x; }
13891 // { x--; v = x; }
13892 // { ++x; v = x; }
13893 // { --x; v = x; }
13894 // { x binop= expr; v = x; }
13895 // { x = x binop expr; v = x; }
13896 // { x = expr binop x; v = x; }
13897 if (auto *CS = dyn_cast<CompoundStmt>(Val: Body)) {
13898 // Check that this is { expr1; expr2; }
13899 if (CS->size() == 2) {
13900 Stmt *First = CS->body_front();
13901 Stmt *Second = CS->body_back();
13902 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: First))
13903 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13904 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: Second))
13905 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13906 // Need to find what subexpression is 'v' and what is 'x'.
13907 OpenMPAtomicUpdateChecker Checker(SemaRef);
13908 bool IsUpdateExprFound = !Checker.checkStatement(S: Second);
13909 BinaryOperator *BinOp = nullptr;
13910 if (IsUpdateExprFound) {
13911 BinOp = dyn_cast<BinaryOperator>(Val: First);
13912 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13913 }
13914 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
13915 // { v = x; x++; }
13916 // { v = x; x--; }
13917 // { v = x; ++x; }
13918 // { v = x; --x; }
13919 // { v = x; x binop= expr; }
13920 // { v = x; x = x binop expr; }
13921 // { v = x; x = expr binop x; }
13922 // Check that the first expression has form v = x.
13923 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13924 llvm::FoldingSetNodeID XId, PossibleXId;
13925 Checker.getX()->Profile(ID&: XId, Context, /*Canonical=*/true);
13926 PossibleX->Profile(ID&: PossibleXId, Context, /*Canonical=*/true);
13927 IsUpdateExprFound = XId == PossibleXId;
13928 if (IsUpdateExprFound) {
13929 V = BinOp->getLHS();
13930 X = Checker.getX();
13931 E = Checker.getExpr();
13932 UE = Checker.getUpdateExpr();
13933 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13934 IsPostfixUpdate = true;
13935 }
13936 }
13937 if (!IsUpdateExprFound) {
13938 IsUpdateExprFound = !Checker.checkStatement(S: First);
13939 BinOp = nullptr;
13940 if (IsUpdateExprFound) {
13941 BinOp = dyn_cast<BinaryOperator>(Val: Second);
13942 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13943 }
13944 if (IsUpdateExprFound &&
13945 !SemaRef.CurContext->isDependentContext()) {
13946 // { x++; v = x; }
13947 // { x--; v = x; }
13948 // { ++x; v = x; }
13949 // { --x; v = x; }
13950 // { x binop= expr; v = x; }
13951 // { x = x binop expr; v = x; }
13952 // { x = expr binop x; v = x; }
13953 // Check that the second expression has form v = x.
13954 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13955 llvm::FoldingSetNodeID XId, PossibleXId;
13956 Checker.getX()->Profile(ID&: XId, Context, /*Canonical=*/true);
13957 PossibleX->Profile(ID&: PossibleXId, Context, /*Canonical=*/true);
13958 IsUpdateExprFound = XId == PossibleXId;
13959 if (IsUpdateExprFound) {
13960 V = BinOp->getLHS();
13961 X = Checker.getX();
13962 E = Checker.getExpr();
13963 UE = Checker.getUpdateExpr();
13964 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13965 IsPostfixUpdate = false;
13966 }
13967 }
13968 }
13969 if (!IsUpdateExprFound) {
13970 // { v = x; x = expr; }
13971 auto *FirstExpr = dyn_cast<Expr>(Val: First);
13972 auto *SecondExpr = dyn_cast<Expr>(Val: Second);
13973 if (!FirstExpr || !SecondExpr ||
13974 !(FirstExpr->isInstantiationDependent() ||
13975 SecondExpr->isInstantiationDependent())) {
13976 auto *FirstBinOp = dyn_cast<BinaryOperator>(Val: First);
13977 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13978 ErrorFound = NotAnAssignmentOp;
13979 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13980 : First->getBeginLoc();
13981 NoteRange = ErrorRange = FirstBinOp
13982 ? FirstBinOp->getSourceRange()
13983 : SourceRange(ErrorLoc, ErrorLoc);
13984 } else {
13985 auto *SecondBinOp = dyn_cast<BinaryOperator>(Val: Second);
13986 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13987 ErrorFound = NotAnAssignmentOp;
13988 NoteLoc = ErrorLoc = SecondBinOp
13989 ? SecondBinOp->getOperatorLoc()
13990 : Second->getBeginLoc();
13991 NoteRange = ErrorRange =
13992 SecondBinOp ? SecondBinOp->getSourceRange()
13993 : SourceRange(ErrorLoc, ErrorLoc);
13994 } else {
13995 Expr *PossibleXRHSInFirst =
13996 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13997 Expr *PossibleXLHSInSecond =
13998 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13999 llvm::FoldingSetNodeID X1Id, X2Id;
14000 PossibleXRHSInFirst->Profile(ID&: X1Id, Context,
14001 /*Canonical=*/true);
14002 PossibleXLHSInSecond->Profile(ID&: X2Id, Context,
14003 /*Canonical=*/true);
14004 IsUpdateExprFound = X1Id == X2Id;
14005 if (IsUpdateExprFound) {
14006 V = FirstBinOp->getLHS();
14007 X = SecondBinOp->getLHS();
14008 E = SecondBinOp->getRHS();
14009 UE = nullptr;
14010 IsXLHSInRHSPart = false;
14011 IsPostfixUpdate = true;
14012 } else {
14013 ErrorFound = NotASpecificExpression;
14014 ErrorLoc = FirstBinOp->getExprLoc();
14015 ErrorRange = FirstBinOp->getSourceRange();
14016 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
14017 NoteRange = SecondBinOp->getRHS()->getSourceRange();
14018 }
14019 }
14020 }
14021 }
14022 }
14023 } else {
14024 NoteLoc = ErrorLoc = Body->getBeginLoc();
14025 NoteRange = ErrorRange =
14026 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
14027 ErrorFound = NotTwoSubstatements;
14028 }
14029 } else {
14030 NoteLoc = ErrorLoc = Body->getBeginLoc();
14031 NoteRange = ErrorRange =
14032 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
14033 ErrorFound = NotACompoundStatement;
14034 }
14035 }
14036 if (ErrorFound != NoError) {
14037 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_capture_not_compound_statement)
14038 << ErrorRange;
14039 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
14040 return StmtError();
14041 }
14042 if (SemaRef.CurContext->isDependentContext())
14043 UE = V = E = X = nullptr;
14044 } else if (AtomicKind == OMPC_compare) {
14045 if (IsCompareCapture) {
14046 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
14047 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
14048 if (!Checker.checkStmt(S: Body, ErrorInfo)) {
14049 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_compare_capture)
14050 << ErrorInfo.ErrorRange;
14051 Diag(Loc: ErrorInfo.NoteLoc, DiagID: diag::note_omp_atomic_compare)
14052 << ErrorInfo.Error << ErrorInfo.NoteRange;
14053 return StmtError();
14054 }
14055 X = Checker.getX();
14056 E = Checker.getE();
14057 D = Checker.getD();
14058 CE = Checker.getCond();
14059 V = Checker.getV();
14060 R = Checker.getR();
14061 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
14062 IsXLHSInRHSPart = Checker.isXBinopExpr();
14063 IsFailOnly = Checker.isFailOnly();
14064 IsPostfixUpdate = Checker.isPostfixUpdate();
14065 } else {
14066 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
14067 OpenMPAtomicCompareChecker Checker(SemaRef);
14068 if (!Checker.checkStmt(S: Body, ErrorInfo)) {
14069 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_compare)
14070 << ErrorInfo.ErrorRange;
14071 Diag(Loc: ErrorInfo.NoteLoc, DiagID: diag::note_omp_atomic_compare)
14072 << ErrorInfo.Error << ErrorInfo.NoteRange;
14073 return StmtError();
14074 }
14075 X = Checker.getX();
14076 E = Checker.getE();
14077 D = Checker.getD();
14078 CE = Checker.getCond();
14079 // The weak clause may only appear if the resulting atomic operation is
14080 // an atomic conditional update for which the comparison tests for
14081 // equality. It was not possible to do this check in
14082 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
14083 // could not be performed (Clauses are not available).
14084 auto *It = find_if(Range&: Clauses, P: [](OMPClause *C) {
14085 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
14086 });
14087 if (It != Clauses.end()) {
14088 auto *Cond = dyn_cast<BinaryOperator>(Val: CE);
14089 if (Cond->getOpcode() != BO_EQ) {
14090 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
14091 ErrorInfo.ErrorLoc = Cond->getExprLoc();
14092 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
14093 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
14094
14095 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_weak_no_equality)
14096 << ErrorInfo.ErrorRange;
14097 return StmtError();
14098 }
14099 }
14100 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
14101 IsXLHSInRHSPart = Checker.isXBinopExpr();
14102 }
14103 }
14104
14105 SemaRef.setFunctionHasBranchProtectedScope();
14106
14107 return OMPAtomicDirective::Create(
14108 C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
14109 Exprs: {.X: X, .V: V, .R: R, .E: E, .UE: UE, .D: D, .Cond: CE, .IsXLHSInRHSPart: IsXLHSInRHSPart, .IsPostfixUpdate: IsPostfixUpdate, .IsFailOnly: IsFailOnly});
14110}
14111
14112StmtResult SemaOpenMP::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
14113 Stmt *AStmt,
14114 SourceLocation StartLoc,
14115 SourceLocation EndLoc) {
14116 if (!AStmt)
14117 return StmtError();
14118
14119 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14120 return StmtError();
14121
14122 // Check for conflicting capture kinds on structured bindings.
14123 if (checkClausesForDecompositionConflicts(SemaRef, DKind: OMPD_target, Clauses))
14124 return StmtError();
14125
14126 if (checkOriginalVarMappedButOnlyBindingsUsed(SemaRef, Clauses, Body: AStmt))
14127 return StmtError();
14128
14129 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_target, AStmt);
14130
14131 // OpenMP [2.16, Nesting of Regions]
14132 // If specified, a teams construct must be contained within a target
14133 // construct. That target construct must contain no statements or directives
14134 // outside of the teams construct.
14135 if (DSAStack->hasInnerTeamsRegion()) {
14136 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
14137 bool OMPTeamsFound = true;
14138 if (const auto *CS = dyn_cast<CompoundStmt>(Val: S)) {
14139 auto I = CS->body_begin();
14140 while (I != CS->body_end()) {
14141 const auto *OED = dyn_cast<OMPExecutableDirective>(Val: *I);
14142 bool IsTeams = OED && isOpenMPTeamsDirective(DKind: OED->getDirectiveKind());
14143 if (!IsTeams || I != CS->body_begin()) {
14144 OMPTeamsFound = false;
14145 if (IsTeams && I != CS->body_begin()) {
14146 // This is the two teams case. Since the InnerTeamsRegionLoc will
14147 // point to this second one reset the iterator to the other teams.
14148 --I;
14149 }
14150 break;
14151 }
14152 ++I;
14153 }
14154 assert(I != CS->body_end() && "Not found statement");
14155 S = *I;
14156 } else {
14157 const auto *OED = dyn_cast<OMPExecutableDirective>(Val: S);
14158 OMPTeamsFound = OED && isOpenMPTeamsDirective(DKind: OED->getDirectiveKind());
14159 }
14160 if (!OMPTeamsFound) {
14161 Diag(Loc: StartLoc, DiagID: diag::err_omp_target_contains_not_only_teams);
14162 Diag(DSAStack->getInnerTeamsRegionLoc(),
14163 DiagID: diag::note_omp_nested_teams_construct_here);
14164 Diag(Loc: S->getBeginLoc(), DiagID: diag::note_omp_nested_statement_here)
14165 << isa<OMPExecutableDirective>(Val: S);
14166 return StmtError();
14167 }
14168 }
14169
14170 return OMPTargetDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
14171 AssociatedStmt: AStmt);
14172}
14173
14174StmtResult SemaOpenMP::ActOnOpenMPTargetParallelDirective(
14175 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14176 SourceLocation EndLoc) {
14177 if (!AStmt)
14178 return StmtError();
14179
14180 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14181 return StmtError();
14182
14183 // Check for conflicting capture kinds on structured bindings.
14184 if (checkClausesForDecompositionConflicts(SemaRef, DKind: OMPD_target_parallel,
14185 Clauses))
14186 return StmtError();
14187
14188 if (checkOriginalVarMappedButOnlyBindingsUsed(SemaRef, Clauses, Body: AStmt))
14189 return StmtError();
14190
14191 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel, AStmt);
14192
14193 return OMPTargetParallelDirective::Create(
14194 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
14195 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14196}
14197
14198StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForDirective(
14199 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14200 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14201 if (!AStmt)
14202 return StmtError();
14203
14204 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14205 return StmtError();
14206
14207 if (checkClausesForDecompositionConflicts(SemaRef, DKind: OMPD_target_parallel_for,
14208 Clauses))
14209 return StmtError();
14210
14211 if (checkOriginalVarMappedButOnlyBindingsUsed(SemaRef, Clauses, Body: AStmt))
14212 return StmtError();
14213
14214 CapturedStmt *CS =
14215 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_for, AStmt);
14216
14217 OMPLoopBasedDirective::HelperExprs B;
14218 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14219 // define the nested loops number.
14220 unsigned NestedLoopCount =
14221 checkOpenMPLoop(DKind: OMPD_target_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14222 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
14223 VarsWithImplicitDSA, Built&: B);
14224 if (NestedLoopCount == 0)
14225 return StmtError();
14226
14227 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14228 return StmtError();
14229
14230 return OMPTargetParallelForDirective::Create(
14231 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14232 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14233}
14234
14235/// Check for existence of a map clause in the list of clauses.
14236static bool hasClauses(ArrayRef<OMPClause *> Clauses,
14237 const OpenMPClauseKind K) {
14238 return llvm::any_of(
14239 Range&: Clauses, P: [K](const OMPClause *C) { return C->getClauseKind() == K; });
14240}
14241
14242template <typename... Params>
14243static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
14244 const Params... ClauseTypes) {
14245 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
14246}
14247
14248/// Check if the variables in the mapping clause are externally visible.
14249static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
14250 for (const OMPClause *C : Clauses) {
14251 if (auto *TC = dyn_cast<OMPToClause>(Val: C))
14252 return llvm::all_of(Range: TC->all_decls(), P: [](ValueDecl *VD) {
14253 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
14254 (VD->isExternallyVisible() &&
14255 VD->getVisibility() != HiddenVisibility);
14256 });
14257 else if (auto *FC = dyn_cast<OMPFromClause>(Val: C))
14258 return llvm::all_of(Range: FC->all_decls(), P: [](ValueDecl *VD) {
14259 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
14260 (VD->isExternallyVisible() &&
14261 VD->getVisibility() != HiddenVisibility);
14262 });
14263 }
14264
14265 return true;
14266}
14267
14268StmtResult
14269SemaOpenMP::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
14270 Stmt *AStmt, SourceLocation StartLoc,
14271 SourceLocation EndLoc) {
14272 if (!AStmt)
14273 return StmtError();
14274
14275 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14276
14277 // OpenMP [2.12.2, target data Construct, Restrictions]
14278 // At least one map, use_device_addr or use_device_ptr clause must appear on
14279 // the directive.
14280 if (!hasClauses(Clauses, K: OMPC_map, ClauseTypes: OMPC_use_device_ptr) &&
14281 (getLangOpts().OpenMP < 50 ||
14282 !hasClauses(Clauses, K: OMPC_use_device_addr))) {
14283 StringRef Expected;
14284 if (getLangOpts().OpenMP < 50)
14285 Expected = "'map' or 'use_device_ptr'";
14286 else
14287 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
14288 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
14289 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
14290 << Expected << getOpenMPDirectiveName(D: OMPD_target_data, V: OMPVersion);
14291 return StmtError();
14292 }
14293
14294 SemaRef.setFunctionHasBranchProtectedScope();
14295
14296 return OMPTargetDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14297 Clauses, AssociatedStmt: AStmt);
14298}
14299
14300StmtResult SemaOpenMP::ActOnOpenMPTargetEnterDataDirective(
14301 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
14302 SourceLocation EndLoc, Stmt *AStmt) {
14303 if (!AStmt)
14304 return StmtError();
14305
14306 setBranchProtectedScope(SemaRef, DKind: OMPD_target_enter_data, AStmt);
14307
14308 // OpenMP [2.10.2, Restrictions, p. 99]
14309 // At least one map clause must appear on the directive.
14310 if (!hasClauses(Clauses, K: OMPC_map)) {
14311 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
14312 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
14313 << "'map'"
14314 << getOpenMPDirectiveName(D: OMPD_target_enter_data, V: OMPVersion);
14315 return StmtError();
14316 }
14317
14318 return OMPTargetEnterDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14319 Clauses, AssociatedStmt: AStmt);
14320}
14321
14322StmtResult SemaOpenMP::ActOnOpenMPTargetExitDataDirective(
14323 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
14324 SourceLocation EndLoc, Stmt *AStmt) {
14325 if (!AStmt)
14326 return StmtError();
14327
14328 setBranchProtectedScope(SemaRef, DKind: OMPD_target_exit_data, AStmt);
14329
14330 // OpenMP [2.10.3, Restrictions, p. 102]
14331 // At least one map clause must appear on the directive.
14332 if (!hasClauses(Clauses, K: OMPC_map)) {
14333 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
14334 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
14335 << "'map'" << getOpenMPDirectiveName(D: OMPD_target_exit_data, V: OMPVersion);
14336 return StmtError();
14337 }
14338
14339 return OMPTargetExitDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14340 Clauses, AssociatedStmt: AStmt);
14341}
14342
14343StmtResult SemaOpenMP::ActOnOpenMPTargetUpdateDirective(
14344 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
14345 SourceLocation EndLoc, Stmt *AStmt) {
14346 if (!AStmt)
14347 return StmtError();
14348
14349 setBranchProtectedScope(SemaRef, DKind: OMPD_target_update, AStmt);
14350
14351 if (!hasClauses(Clauses, K: OMPC_to, ClauseTypes: OMPC_from)) {
14352 Diag(Loc: StartLoc, DiagID: diag::err_omp_at_least_one_motion_clause_required);
14353 return StmtError();
14354 }
14355
14356 if (!isClauseMappable(Clauses)) {
14357 Diag(Loc: StartLoc, DiagID: diag::err_omp_cannot_update_with_internal_linkage);
14358 return StmtError();
14359 }
14360
14361 return OMPTargetUpdateDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14362 Clauses, AssociatedStmt: AStmt);
14363}
14364
14365StmtResult SemaOpenMP::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
14366 Stmt *AStmt,
14367 SourceLocation StartLoc,
14368 SourceLocation EndLoc) {
14369 if (!AStmt)
14370 return StmtError();
14371
14372 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14373 return StmtError();
14374
14375 if (checkClausesForDecompositionConflicts(SemaRef, DKind: OMPD_teams, Clauses))
14376 return StmtError();
14377
14378 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
14379 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
14380 Diag(Loc: StartLoc, DiagID: diag::warn_hip_omp_target_directives);
14381
14382 setBranchProtectedScope(SemaRef, DKind: OMPD_teams, AStmt);
14383
14384 DSAStack->setParentTeamsRegionLoc(StartLoc);
14385
14386 return OMPTeamsDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
14387 AssociatedStmt: AStmt);
14388}
14389
14390StmtResult SemaOpenMP::ActOnOpenMPCancellationPointDirective(
14391 SourceLocation StartLoc, SourceLocation EndLoc,
14392 OpenMPDirectiveKind CancelRegion) {
14393 if (DSAStack->isParentNowaitRegion()) {
14394 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_nowait) << 0;
14395 return StmtError();
14396 }
14397 if (DSAStack->isParentOrderedRegion()) {
14398 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_ordered) << 0;
14399 return StmtError();
14400 }
14401 return OMPCancellationPointDirective::Create(C: getASTContext(), StartLoc,
14402 EndLoc, CancelRegion);
14403}
14404
14405StmtResult SemaOpenMP::ActOnOpenMPCancelDirective(
14406 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
14407 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
14408 if (DSAStack->isParentNowaitRegion()) {
14409 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_nowait) << 1;
14410 return StmtError();
14411 }
14412 if (DSAStack->isParentOrderedRegion()) {
14413 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_ordered) << 1;
14414 return StmtError();
14415 }
14416 DSAStack->setParentCancelRegion(/*Cancel=*/true);
14417 return OMPCancelDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
14418 CancelRegion);
14419}
14420
14421static bool checkReductionClauseWithNogroup(Sema &S,
14422 ArrayRef<OMPClause *> Clauses) {
14423 const OMPClause *ReductionClause = nullptr;
14424 const OMPClause *NogroupClause = nullptr;
14425 for (const OMPClause *C : Clauses) {
14426 if (C->getClauseKind() == OMPC_reduction) {
14427 ReductionClause = C;
14428 if (NogroupClause)
14429 break;
14430 continue;
14431 }
14432 if (C->getClauseKind() == OMPC_nogroup) {
14433 NogroupClause = C;
14434 if (ReductionClause)
14435 break;
14436 continue;
14437 }
14438 }
14439 if (ReductionClause && NogroupClause) {
14440 S.Diag(Loc: ReductionClause->getBeginLoc(), DiagID: diag::err_omp_reduction_with_nogroup)
14441 << SourceRange(NogroupClause->getBeginLoc(),
14442 NogroupClause->getEndLoc());
14443 return true;
14444 }
14445 return false;
14446}
14447
14448StmtResult SemaOpenMP::ActOnOpenMPTaskLoopDirective(
14449 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14450 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14451 if (!AStmt)
14452 return StmtError();
14453
14454 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14455 OMPLoopBasedDirective::HelperExprs B;
14456 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14457 // define the nested loops number.
14458 unsigned NestedLoopCount =
14459 checkOpenMPLoop(DKind: OMPD_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14460 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
14461 DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14462 if (NestedLoopCount == 0)
14463 return StmtError();
14464
14465 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14466 "omp for loop exprs were not built");
14467
14468 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14469 // The grainsize clause and num_tasks clause are mutually exclusive and may
14470 // not appear on the same taskloop directive.
14471 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14472 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14473 return StmtError();
14474 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14475 // If a reduction clause is present on the taskloop directive, the nogroup
14476 // clause must not be specified.
14477 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14478 return StmtError();
14479
14480 SemaRef.setFunctionHasBranchProtectedScope();
14481 return OMPTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14482 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14483 DSAStack->isCancelRegion());
14484}
14485
14486StmtResult SemaOpenMP::ActOnOpenMPTaskLoopSimdDirective(
14487 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14488 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14489 if (!AStmt)
14490 return StmtError();
14491
14492 CapturedStmt *CS =
14493 setBranchProtectedScope(SemaRef, DKind: OMPD_taskloop_simd, AStmt);
14494
14495 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14496 OMPLoopBasedDirective::HelperExprs B;
14497 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14498 // define the nested loops number.
14499 unsigned NestedLoopCount =
14500 checkOpenMPLoop(DKind: OMPD_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14501 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14502 VarsWithImplicitDSA, Built&: B);
14503 if (NestedLoopCount == 0)
14504 return StmtError();
14505
14506 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14507 return StmtError();
14508
14509 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14510 // The grainsize clause and num_tasks clause are mutually exclusive and may
14511 // not appear on the same taskloop directive.
14512 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14513 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14514 return StmtError();
14515 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14516 // If a reduction clause is present on the taskloop directive, the nogroup
14517 // clause must not be specified.
14518 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14519 return StmtError();
14520 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14521 return StmtError();
14522
14523 return OMPTaskLoopSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14524 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14525}
14526
14527StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopDirective(
14528 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14529 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14530 if (!AStmt)
14531 return StmtError();
14532
14533 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14534 OMPLoopBasedDirective::HelperExprs B;
14535 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14536 // define the nested loops number.
14537 unsigned NestedLoopCount =
14538 checkOpenMPLoop(DKind: OMPD_master_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14539 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
14540 DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14541 if (NestedLoopCount == 0)
14542 return StmtError();
14543
14544 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14545 "omp for loop exprs were not built");
14546
14547 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14548 // The grainsize clause and num_tasks clause are mutually exclusive and may
14549 // not appear on the same taskloop directive.
14550 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14551 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14552 return StmtError();
14553 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14554 // If a reduction clause is present on the taskloop directive, the nogroup
14555 // clause must not be specified.
14556 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14557 return StmtError();
14558
14559 SemaRef.setFunctionHasBranchProtectedScope();
14560 return OMPMasterTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14561 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14562 DSAStack->isCancelRegion());
14563}
14564
14565StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopDirective(
14566 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14567 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14568 if (!AStmt)
14569 return StmtError();
14570
14571 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14572 OMPLoopBasedDirective::HelperExprs B;
14573 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14574 // define the nested loops number.
14575 unsigned NestedLoopCount =
14576 checkOpenMPLoop(DKind: OMPD_masked_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14577 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
14578 DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14579 if (NestedLoopCount == 0)
14580 return StmtError();
14581
14582 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14583 "omp for loop exprs were not built");
14584
14585 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14586 // The grainsize clause and num_tasks clause are mutually exclusive and may
14587 // not appear on the same taskloop directive.
14588 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14589 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14590 return StmtError();
14591 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14592 // If a reduction clause is present on the taskloop directive, the nogroup
14593 // clause must not be specified.
14594 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14595 return StmtError();
14596
14597 SemaRef.setFunctionHasBranchProtectedScope();
14598 return OMPMaskedTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14599 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14600 DSAStack->isCancelRegion());
14601}
14602
14603StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopSimdDirective(
14604 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14605 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14606 if (!AStmt)
14607 return StmtError();
14608
14609 CapturedStmt *CS =
14610 setBranchProtectedScope(SemaRef, DKind: OMPD_master_taskloop_simd, AStmt);
14611
14612 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14613 OMPLoopBasedDirective::HelperExprs B;
14614 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14615 // define the nested loops number.
14616 unsigned NestedLoopCount =
14617 checkOpenMPLoop(DKind: OMPD_master_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14618 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14619 VarsWithImplicitDSA, Built&: B);
14620 if (NestedLoopCount == 0)
14621 return StmtError();
14622
14623 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14624 return StmtError();
14625
14626 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14627 // The grainsize clause and num_tasks clause are mutually exclusive and may
14628 // not appear on the same taskloop directive.
14629 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14630 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14631 return StmtError();
14632 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14633 // If a reduction clause is present on the taskloop directive, the nogroup
14634 // clause must not be specified.
14635 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14636 return StmtError();
14637 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14638 return StmtError();
14639
14640 return OMPMasterTaskLoopSimdDirective::Create(
14641 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14642}
14643
14644StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopSimdDirective(
14645 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14646 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14647 if (!AStmt)
14648 return StmtError();
14649
14650 CapturedStmt *CS =
14651 setBranchProtectedScope(SemaRef, DKind: OMPD_masked_taskloop_simd, AStmt);
14652
14653 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14654 OMPLoopBasedDirective::HelperExprs B;
14655 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14656 // define the nested loops number.
14657 unsigned NestedLoopCount =
14658 checkOpenMPLoop(DKind: OMPD_masked_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14659 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14660 VarsWithImplicitDSA, Built&: B);
14661 if (NestedLoopCount == 0)
14662 return StmtError();
14663
14664 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14665 return StmtError();
14666
14667 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14668 // The grainsize clause and num_tasks clause are mutually exclusive and may
14669 // not appear on the same taskloop directive.
14670 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14671 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14672 return StmtError();
14673 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14674 // If a reduction clause is present on the taskloop directive, the nogroup
14675 // clause must not be specified.
14676 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14677 return StmtError();
14678 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14679 return StmtError();
14680
14681 return OMPMaskedTaskLoopSimdDirective::Create(
14682 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14683}
14684
14685StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopDirective(
14686 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14687 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14688 if (!AStmt)
14689 return StmtError();
14690
14691 CapturedStmt *CS =
14692 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_master_taskloop, AStmt);
14693
14694 OMPLoopBasedDirective::HelperExprs B;
14695 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14696 // define the nested loops number.
14697 unsigned NestedLoopCount = checkOpenMPLoop(
14698 DKind: OMPD_parallel_master_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14699 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14700 VarsWithImplicitDSA, Built&: B);
14701 if (NestedLoopCount == 0)
14702 return StmtError();
14703
14704 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14705 "omp for loop exprs were not built");
14706
14707 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14708 // The grainsize clause and num_tasks clause are mutually exclusive and may
14709 // not appear on the same taskloop directive.
14710 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14711 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14712 return StmtError();
14713 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14714 // If a reduction clause is present on the taskloop directive, the nogroup
14715 // clause must not be specified.
14716 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14717 return StmtError();
14718
14719 return OMPParallelMasterTaskLoopDirective::Create(
14720 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14721 DSAStack->isCancelRegion());
14722}
14723
14724StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopDirective(
14725 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14726 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14727 if (!AStmt)
14728 return StmtError();
14729
14730 CapturedStmt *CS =
14731 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_masked_taskloop, AStmt);
14732
14733 OMPLoopBasedDirective::HelperExprs B;
14734 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14735 // define the nested loops number.
14736 unsigned NestedLoopCount = checkOpenMPLoop(
14737 DKind: OMPD_parallel_masked_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14738 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14739 VarsWithImplicitDSA, Built&: B);
14740 if (NestedLoopCount == 0)
14741 return StmtError();
14742
14743 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14744 "omp for loop exprs were not built");
14745
14746 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14747 // The grainsize clause and num_tasks clause are mutually exclusive and may
14748 // not appear on the same taskloop directive.
14749 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14750 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14751 return StmtError();
14752 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14753 // If a reduction clause is present on the taskloop directive, the nogroup
14754 // clause must not be specified.
14755 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14756 return StmtError();
14757
14758 return OMPParallelMaskedTaskLoopDirective::Create(
14759 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14760 DSAStack->isCancelRegion());
14761}
14762
14763StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
14764 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14765 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14766 if (!AStmt)
14767 return StmtError();
14768
14769 CapturedStmt *CS = setBranchProtectedScope(
14770 SemaRef, DKind: OMPD_parallel_master_taskloop_simd, AStmt);
14771
14772 OMPLoopBasedDirective::HelperExprs B;
14773 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14774 // define the nested loops number.
14775 unsigned NestedLoopCount = checkOpenMPLoop(
14776 DKind: OMPD_parallel_master_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14777 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14778 VarsWithImplicitDSA, Built&: B);
14779 if (NestedLoopCount == 0)
14780 return StmtError();
14781
14782 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14783 return StmtError();
14784
14785 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14786 // The grainsize clause and num_tasks clause are mutually exclusive and may
14787 // not appear on the same taskloop directive.
14788 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14789 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14790 return StmtError();
14791 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14792 // If a reduction clause is present on the taskloop directive, the nogroup
14793 // clause must not be specified.
14794 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14795 return StmtError();
14796 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14797 return StmtError();
14798
14799 return OMPParallelMasterTaskLoopSimdDirective::Create(
14800 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14801}
14802
14803StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
14804 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14805 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14806 if (!AStmt)
14807 return StmtError();
14808
14809 CapturedStmt *CS = setBranchProtectedScope(
14810 SemaRef, DKind: OMPD_parallel_masked_taskloop_simd, AStmt);
14811
14812 OMPLoopBasedDirective::HelperExprs B;
14813 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14814 // define the nested loops number.
14815 unsigned NestedLoopCount = checkOpenMPLoop(
14816 DKind: OMPD_parallel_masked_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14817 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14818 VarsWithImplicitDSA, Built&: B);
14819 if (NestedLoopCount == 0)
14820 return StmtError();
14821
14822 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14823 return StmtError();
14824
14825 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14826 // The grainsize clause and num_tasks clause are mutually exclusive and may
14827 // not appear on the same taskloop directive.
14828 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14829 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14830 return StmtError();
14831 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14832 // If a reduction clause is present on the taskloop directive, the nogroup
14833 // clause must not be specified.
14834 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14835 return StmtError();
14836 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14837 return StmtError();
14838
14839 return OMPParallelMaskedTaskLoopSimdDirective::Create(
14840 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14841}
14842
14843StmtResult SemaOpenMP::ActOnOpenMPDistributeDirective(
14844 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14845 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14846 if (!AStmt)
14847 return StmtError();
14848
14849 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14850 OMPLoopBasedDirective::HelperExprs B;
14851 // In presence of clause 'collapse' with number of loops, it will
14852 // define the nested loops number.
14853 unsigned NestedLoopCount =
14854 checkOpenMPLoop(DKind: OMPD_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14855 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt,
14856 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14857 if (NestedLoopCount == 0)
14858 return StmtError();
14859
14860 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14861 "omp for loop exprs were not built");
14862
14863 SemaRef.setFunctionHasBranchProtectedScope();
14864 auto *DistributeDirective = OMPDistributeDirective::Create(
14865 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14866 return DistributeDirective;
14867}
14868
14869StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForDirective(
14870 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14871 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14872 if (!AStmt)
14873 return StmtError();
14874
14875 CapturedStmt *CS =
14876 setBranchProtectedScope(SemaRef, DKind: OMPD_distribute_parallel_for, AStmt);
14877
14878 OMPLoopBasedDirective::HelperExprs B;
14879 // In presence of clause 'collapse' with number of loops, it will
14880 // define the nested loops number.
14881 unsigned NestedLoopCount = checkOpenMPLoop(
14882 DKind: OMPD_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14883 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14884 VarsWithImplicitDSA, Built&: B);
14885 if (NestedLoopCount == 0)
14886 return StmtError();
14887
14888 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14889 "omp for loop exprs were not built");
14890
14891 return OMPDistributeParallelForDirective::Create(
14892 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14893 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14894}
14895
14896StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForSimdDirective(
14897 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14898 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14899 if (!AStmt)
14900 return StmtError();
14901
14902 CapturedStmt *CS = setBranchProtectedScope(
14903 SemaRef, DKind: OMPD_distribute_parallel_for_simd, AStmt);
14904
14905 OMPLoopBasedDirective::HelperExprs B;
14906 // In presence of clause 'collapse' with number of loops, it will
14907 // define the nested loops number.
14908 unsigned NestedLoopCount = checkOpenMPLoop(
14909 DKind: OMPD_distribute_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14910 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14911 VarsWithImplicitDSA, Built&: B);
14912 if (NestedLoopCount == 0)
14913 return StmtError();
14914
14915 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14916 return StmtError();
14917
14918 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14919 return StmtError();
14920
14921 return OMPDistributeParallelForSimdDirective::Create(
14922 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14923}
14924
14925StmtResult SemaOpenMP::ActOnOpenMPDistributeSimdDirective(
14926 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14927 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14928 if (!AStmt)
14929 return StmtError();
14930
14931 CapturedStmt *CS =
14932 setBranchProtectedScope(SemaRef, DKind: OMPD_distribute_simd, AStmt);
14933
14934 OMPLoopBasedDirective::HelperExprs B;
14935 // In presence of clause 'collapse' with number of loops, it will
14936 // define the nested loops number.
14937 unsigned NestedLoopCount =
14938 checkOpenMPLoop(DKind: OMPD_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14939 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
14940 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14941 if (NestedLoopCount == 0)
14942 return StmtError();
14943
14944 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14945 return StmtError();
14946
14947 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14948 return StmtError();
14949
14950 return OMPDistributeSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14951 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14952}
14953
14954StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForSimdDirective(
14955 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14956 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14957 if (!AStmt)
14958 return StmtError();
14959
14960 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14961 return StmtError();
14962
14963 if (checkClausesForDecompositionConflicts(
14964 SemaRef, DKind: OMPD_target_parallel_for_simd, Clauses))
14965 return StmtError();
14966
14967 if (checkOriginalVarMappedButOnlyBindingsUsed(SemaRef, Clauses, Body: AStmt))
14968 return StmtError();
14969
14970 CapturedStmt *CS =
14971 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_for_simd, AStmt);
14972
14973 OMPLoopBasedDirective::HelperExprs B;
14974 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14975 // define the nested loops number.
14976 unsigned NestedLoopCount = checkOpenMPLoop(
14977 DKind: OMPD_target_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14978 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
14979 VarsWithImplicitDSA, Built&: B);
14980 if (NestedLoopCount == 0)
14981 return StmtError();
14982
14983 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14984 return StmtError();
14985
14986 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14987 return StmtError();
14988
14989 return OMPTargetParallelForSimdDirective::Create(
14990 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14991}
14992
14993StmtResult SemaOpenMP::ActOnOpenMPTargetSimdDirective(
14994 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14995 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14996 if (!AStmt)
14997 return StmtError();
14998
14999 if (validateMultidimClauses(SemaRef&: *this, Clauses))
15000 return StmtError();
15001
15002 if (checkClausesForDecompositionConflicts(SemaRef, DKind: OMPD_target_simd, Clauses))
15003 return StmtError();
15004
15005 if (checkOriginalVarMappedButOnlyBindingsUsed(SemaRef, Clauses, Body: AStmt))
15006 return StmtError();
15007
15008 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_target_simd, AStmt);
15009
15010 OMPLoopBasedDirective::HelperExprs B;
15011 // In presence of clause 'collapse' with number of loops, it will define the
15012 // nested loops number.
15013 unsigned NestedLoopCount =
15014 checkOpenMPLoop(DKind: OMPD_target_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
15015 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
15016 VarsWithImplicitDSA, Built&: B);
15017 if (NestedLoopCount == 0)
15018 return StmtError();
15019
15020 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15021 return StmtError();
15022
15023 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
15024 return StmtError();
15025
15026 return OMPTargetSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
15027 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
15028}
15029
15030StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeDirective(
15031 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15032 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15033 if (!AStmt)
15034 return StmtError();
15035
15036 if (validateMultidimClauses(SemaRef&: *this, Clauses))
15037 return StmtError();
15038
15039 if (checkClausesForDecompositionConflicts(SemaRef, DKind: OMPD_teams_distribute,
15040 Clauses))
15041 return StmtError();
15042
15043 CapturedStmt *CS =
15044 setBranchProtectedScope(SemaRef, DKind: OMPD_teams_distribute, AStmt);
15045
15046 OMPLoopBasedDirective::HelperExprs B;
15047 // In presence of clause 'collapse' with number of loops, it will
15048 // define the nested loops number.
15049 unsigned NestedLoopCount =
15050 checkOpenMPLoop(DKind: OMPD_teams_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
15051 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
15052 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
15053 if (NestedLoopCount == 0)
15054 return StmtError();
15055
15056 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15057 "omp teams distribute loop exprs were not built");
15058
15059 DSAStack->setParentTeamsRegionLoc(StartLoc);
15060
15061 return OMPTeamsDistributeDirective::Create(
15062 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
15063}
15064
15065StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeSimdDirective(
15066 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15067 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15068 if (!AStmt)
15069 return StmtError();
15070
15071 if (validateMultidimClauses(SemaRef&: *this, Clauses))
15072 return StmtError();
15073 if (checkClausesForDecompositionConflicts(SemaRef, DKind: OMPD_teams_distribute_simd,
15074 Clauses))
15075 return StmtError();
15076
15077 CapturedStmt *CS =
15078 setBranchProtectedScope(SemaRef, DKind: OMPD_teams_distribute_simd, AStmt);
15079
15080 OMPLoopBasedDirective::HelperExprs B;
15081 // In presence of clause 'collapse' with number of loops, it will
15082 // define the nested loops number.
15083 unsigned NestedLoopCount = checkOpenMPLoop(
15084 DKind: OMPD_teams_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
15085 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
15086 VarsWithImplicitDSA, Built&: B);
15087 if (NestedLoopCount == 0)
15088 return StmtError();
15089
15090 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15091 return StmtError();
15092
15093 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
15094 return StmtError();
15095
15096 DSAStack->setParentTeamsRegionLoc(StartLoc);
15097
15098 return OMPTeamsDistributeSimdDirective::Create(
15099 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
15100}
15101
15102StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
15103 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15104 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15105 if (!AStmt)
15106 return StmtError();
15107
15108 if (validateMultidimClauses(SemaRef&: *this, Clauses))
15109 return StmtError();
15110
15111 if (checkClausesForDecompositionConflicts(
15112 SemaRef, DKind: OMPD_teams_distribute_parallel_for_simd, Clauses))
15113 return StmtError();
15114
15115 CapturedStmt *CS = setBranchProtectedScope(
15116 SemaRef, DKind: OMPD_teams_distribute_parallel_for_simd, AStmt);
15117
15118 OMPLoopBasedDirective::HelperExprs B;
15119 // In presence of clause 'collapse' with number of loops, it will
15120 // define the nested loops number.
15121 unsigned NestedLoopCount = checkOpenMPLoop(
15122 DKind: OMPD_teams_distribute_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
15123 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
15124 VarsWithImplicitDSA, Built&: B);
15125 if (NestedLoopCount == 0)
15126 return StmtError();
15127
15128 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15129 return StmtError();
15130
15131 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
15132 return StmtError();
15133
15134 DSAStack->setParentTeamsRegionLoc(StartLoc);
15135
15136 return OMPTeamsDistributeParallelForSimdDirective::Create(
15137 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
15138}
15139
15140StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForDirective(
15141 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15142 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15143 if (!AStmt)
15144 return StmtError();
15145
15146 if (validateMultidimClauses(SemaRef&: *this, Clauses))
15147 return StmtError();
15148
15149 if (checkClausesForDecompositionConflicts(
15150 SemaRef, DKind: OMPD_teams_distribute_parallel_for, Clauses))
15151 return StmtError();
15152
15153 CapturedStmt *CS = setBranchProtectedScope(
15154 SemaRef, DKind: OMPD_teams_distribute_parallel_for, AStmt);
15155
15156 OMPLoopBasedDirective::HelperExprs B;
15157 // In presence of clause 'collapse' with number of loops, it will
15158 // define the nested loops number.
15159 unsigned NestedLoopCount = checkOpenMPLoop(
15160 DKind: OMPD_teams_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
15161 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
15162 VarsWithImplicitDSA, Built&: B);
15163
15164 if (NestedLoopCount == 0)
15165 return StmtError();
15166
15167 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15168 "omp for loop exprs were not built");
15169
15170 DSAStack->setParentTeamsRegionLoc(StartLoc);
15171
15172 return OMPTeamsDistributeParallelForDirective::Create(
15173 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
15174 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
15175}
15176
15177StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDirective(
15178 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15179 SourceLocation EndLoc) {
15180 if (!AStmt)
15181 return StmtError();
15182
15183 if (checkClausesForDecompositionConflicts(SemaRef, DKind: OMPD_target_teams,
15184 Clauses))
15185 return StmtError();
15186
15187 if (checkOriginalVarMappedButOnlyBindingsUsed(SemaRef, Clauses, Body: AStmt))
15188 return StmtError();
15189
15190 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams, AStmt);
15191
15192 if (validateMultidimClauses(SemaRef&: *this, Clauses, /*MayHaveBareClause=*/true))
15193 return StmtError();
15194
15195 return OMPTargetTeamsDirective::Create(C: getASTContext(), StartLoc, EndLoc,
15196 Clauses, AssociatedStmt: AStmt);
15197}
15198
15199StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeDirective(
15200 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15201 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15202 if (!AStmt)
15203 return StmtError();
15204
15205 if (validateMultidimClauses(SemaRef&: *this, Clauses))
15206 return StmtError();
15207
15208 if (checkClausesForDecompositionConflicts(
15209 SemaRef, DKind: OMPD_target_teams_distribute, Clauses))
15210 return StmtError();
15211
15212 if (checkOriginalVarMappedButOnlyBindingsUsed(SemaRef, Clauses, Body: AStmt))
15213 return StmtError();
15214
15215 CapturedStmt *CS =
15216 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams_distribute, AStmt);
15217
15218 OMPLoopBasedDirective::HelperExprs B;
15219 // In presence of clause 'collapse' with number of loops, it will
15220 // define the nested loops number.
15221 unsigned NestedLoopCount = checkOpenMPLoop(
15222 DKind: OMPD_target_teams_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
15223 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
15224 VarsWithImplicitDSA, Built&: B);
15225 if (NestedLoopCount == 0)
15226 return StmtError();
15227
15228 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15229 "omp target teams distribute loop exprs were not built");
15230
15231 return OMPTargetTeamsDistributeDirective::Create(
15232 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
15233}
15234
15235StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
15236 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15237 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15238 if (!AStmt)
15239 return StmtError();
15240
15241 if (validateMultidimClauses(SemaRef&: *this, Clauses))
15242 return StmtError();
15243
15244 if (checkClausesForDecompositionConflicts(
15245 SemaRef, DKind: OMPD_target_teams_distribute_parallel_for, Clauses))
15246 return StmtError();
15247
15248 if (checkOriginalVarMappedButOnlyBindingsUsed(SemaRef, Clauses, Body: AStmt))
15249 return StmtError();
15250
15251 CapturedStmt *CS = setBranchProtectedScope(
15252 SemaRef, DKind: OMPD_target_teams_distribute_parallel_for, AStmt);
15253
15254 OMPLoopBasedDirective::HelperExprs B;
15255 // In presence of clause 'collapse' with number of loops, it will
15256 // define the nested loops number.
15257 unsigned NestedLoopCount = checkOpenMPLoop(
15258 DKind: OMPD_target_teams_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
15259 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
15260 VarsWithImplicitDSA, Built&: B);
15261 if (NestedLoopCount == 0)
15262 return StmtError();
15263
15264 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15265 return StmtError();
15266
15267 return OMPTargetTeamsDistributeParallelForDirective::Create(
15268 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
15269 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
15270}
15271
15272StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
15273 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15274 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15275 if (!AStmt)
15276 return StmtError();
15277
15278 if (validateMultidimClauses(SemaRef&: *this, Clauses))
15279 return StmtError();
15280
15281 if (checkClausesForDecompositionConflicts(
15282 SemaRef, DKind: OMPD_target_teams_distribute_parallel_for_simd, Clauses))
15283 return StmtError();
15284
15285 if (checkOriginalVarMappedButOnlyBindingsUsed(SemaRef, Clauses, Body: AStmt))
15286 return StmtError();
15287
15288 CapturedStmt *CS = setBranchProtectedScope(
15289 SemaRef, DKind: OMPD_target_teams_distribute_parallel_for_simd, AStmt);
15290
15291 OMPLoopBasedDirective::HelperExprs B;
15292 // In presence of clause 'collapse' with number of loops, it will
15293 // define the nested loops number.
15294 unsigned NestedLoopCount =
15295 checkOpenMPLoop(DKind: OMPD_target_teams_distribute_parallel_for_simd,
15296 CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
15297 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
15298 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
15299 if (NestedLoopCount == 0)
15300 return StmtError();
15301
15302 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15303 return StmtError();
15304
15305 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
15306 return StmtError();
15307
15308 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
15309 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
15310}
15311
15312StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective(
15313 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15314 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15315 if (!AStmt)
15316 return StmtError();
15317
15318 if (validateMultidimClauses(SemaRef&: *this, Clauses))
15319 return StmtError();
15320
15321 if (checkClausesForDecompositionConflicts(
15322 SemaRef, DKind: OMPD_target_teams_distribute_simd, Clauses))
15323 return StmtError();
15324
15325 if (checkOriginalVarMappedButOnlyBindingsUsed(SemaRef, Clauses, Body: AStmt))
15326 return StmtError();
15327
15328 CapturedStmt *CS = setBranchProtectedScope(
15329 SemaRef, DKind: OMPD_target_teams_distribute_simd, AStmt);
15330
15331 OMPLoopBasedDirective::HelperExprs B;
15332 // In presence of clause 'collapse' with number of loops, it will
15333 // define the nested loops number.
15334 unsigned NestedLoopCount = checkOpenMPLoop(
15335 DKind: OMPD_target_teams_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
15336 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
15337 VarsWithImplicitDSA, Built&: B);
15338 if (NestedLoopCount == 0)
15339 return StmtError();
15340
15341 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15342 return StmtError();
15343
15344 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
15345 return StmtError();
15346
15347 return OMPTargetTeamsDistributeSimdDirective::Create(
15348 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
15349}
15350
15351/// Updates OriginalInits by checking Transform against loop transformation
15352/// directives and appending their pre-inits if a match is found.
15353static void updatePreInits(OMPLoopTransformationDirective *Transform,
15354 SmallVectorImpl<Stmt *> &PreInits) {
15355 Stmt *Dir = Transform->getDirective();
15356 switch (Dir->getStmtClass()) {
15357#define STMT(CLASS, PARENT)
15358#define ABSTRACT_STMT(CLASS)
15359#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
15360 case Stmt::CLASS##Class: \
15361 appendFlattenedStmtList(PreInits, \
15362 static_cast<const CLASS *>(Dir)->getPreInits()); \
15363 break;
15364#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
15365 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
15366#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
15367 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
15368#include "clang/AST/StmtNodes.inc"
15369#undef COMMON_OMP_LOOP_TRANSFORMATION
15370 default:
15371 llvm_unreachable("Not a loop transformation");
15372 }
15373}
15374
15375bool SemaOpenMP::checkTransformableLoopNest(
15376 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
15377 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
15378 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *>> &OriginalInits) {
15379 OriginalInits.emplace_back();
15380 // Only tile and stripe re-emit the statements before the nested loop in a
15381 // nested transformation's generated loop (see appendStmtsBeforeNestedLoop);
15382 // other constructs would silently drop them.
15383 bool RelaxNestForPeeledTransformation =
15384 Kind == OMPD_tile || Kind == OMPD_stripe;
15385 bool Result = OMPLoopBasedDirective::doForAllLoops(
15386 CurStmt: AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
15387 Callback: [this, &LoopHelpers, &Body, &OriginalInits,
15388 Kind](unsigned Cnt, Stmt *CurStmt, Stmt *HintWrapper) {
15389 // The start of this loop is a floor set in the enclosing tile's body.
15390 // Loop analysis reads a start only once, so the nest would repeat the
15391 // first tile. Reject instead of emitting wrong loops.
15392 if (HintWrapper) {
15393 SemaRef.Diag(Loc: CurStmt->getBeginLoc(),
15394 DiagID: diag::err_omp_collapse_stacked_tile)
15395 << /*LoopTransform=*/1;
15396 return true;
15397 }
15398 VarsWithInheritedDSAType TmpDSA;
15399 unsigned SingleNumLoops =
15400 checkOpenMPLoop(DKind: Kind, CollapseLoopCountExpr: nullptr, OrderedLoopCountExpr: nullptr, AStmt: CurStmt, SemaRef, DSA&: *DSAStack,
15401 VarsWithImplicitDSA&: TmpDSA, Built&: LoopHelpers[Cnt]);
15402 if (SingleNumLoops == 0)
15403 return true;
15404 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
15405 if (auto *For = dyn_cast<ForStmt>(Val: CurStmt)) {
15406 OriginalInits.back().push_back(Elt: For->getInit());
15407 Body = For->getBody();
15408 } else {
15409 assert(isa<CXXForRangeStmt>(CurStmt) &&
15410 "Expected canonical for or range-based for loops.");
15411 auto *CXXFor = cast<CXXForRangeStmt>(Val: CurStmt);
15412 OriginalInits.back().push_back(Elt: CXXFor->getBeginStmt());
15413 Body = CXXFor->getBody();
15414 }
15415 OriginalInits.emplace_back();
15416 return false;
15417 },
15418 OnTransformationCallback: [&OriginalInits](OMPLoopTransformationDirective *Transform) {
15419 updatePreInits(Transform, PreInits&: OriginalInits.back());
15420 },
15421 RelaxNestForPeeledTransformation);
15422 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
15423 OriginalInits.pop_back();
15424 return Result;
15425}
15426
15427/// Counts the total number of OpenMP canonical nested loops, including the
15428/// outermost loop (the original loop). PRECONDITION of this visitor is that it
15429/// must be invoked from the original loop to be analyzed. The traversal stops
15430/// for Decl's and Expr's given that they may contain inner loops that must not
15431/// be counted.
15432///
15433/// Example AST structure for the code:
15434///
15435/// int main() {
15436/// #pragma omp fuse
15437/// {
15438/// for (int i = 0; i < 100; i++) { <-- Outer loop
15439/// []() {
15440/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (1)
15441/// };
15442/// for(int j = 0; j < 5; ++j) {} <-- Inner loop
15443/// }
15444/// for (int r = 0; i < 100; i++) { <-- Outer loop
15445/// struct LocalClass {
15446/// void bar() {
15447/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (2)
15448/// }
15449/// };
15450/// for(int k = 0; k < 10; ++k) {} <-- Inner loop
15451/// {x = 5; for(k = 0; k < 10; ++k) x += k; x}; <-- NOT A LOOP (3)
15452/// }
15453/// }
15454/// }
15455/// (1) because in a different function (here: a lambda)
15456/// (2) because in a different function (here: class method)
15457/// (3) because considered to be intervening-code of non-perfectly nested loop
15458/// Result: Loop 'i' contains 2 loops, Loop 'r' also contains 2 loops.
15459class NestedLoopCounterVisitor final : public DynamicRecursiveASTVisitor {
15460private:
15461 unsigned NestedLoopCount = 0;
15462
15463public:
15464 explicit NestedLoopCounterVisitor() = default;
15465
15466 unsigned getNestedLoopCount() const { return NestedLoopCount; }
15467
15468 bool VisitForStmt(ForStmt *FS) override {
15469 ++NestedLoopCount;
15470 return true;
15471 }
15472
15473 bool VisitCXXForRangeStmt(CXXForRangeStmt *FRS) override {
15474 ++NestedLoopCount;
15475 return true;
15476 }
15477
15478 bool TraverseStmt(Stmt *S) override {
15479 if (!S)
15480 return true;
15481
15482 // Skip traversal of all expressions, including special cases like
15483 // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
15484 // may contain inner statements (and even loops), but they are not part
15485 // of the syntactic body of the surrounding loop structure.
15486 // Therefore must not be counted.
15487 if (isa<Expr>(Val: S))
15488 return true;
15489
15490 // Only recurse into CompoundStmt (block {}) and loop bodies.
15491 if (isa<CompoundStmt, ForStmt, CXXForRangeStmt>(Val: S)) {
15492 return DynamicRecursiveASTVisitor::TraverseStmt(S);
15493 }
15494
15495 // Stop traversal of the rest of statements, that break perfect
15496 // loop nesting, such as control flow (IfStmt, SwitchStmt...).
15497 return true;
15498 }
15499
15500 bool TraverseDecl(Decl *D) override {
15501 // Stop in the case of finding a declaration, it is not important
15502 // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
15503 // FunctionDecl...).
15504 return true;
15505 }
15506};
15507
15508bool SemaOpenMP::analyzeLoopSequence(Stmt *LoopSeqStmt,
15509 LoopSequenceAnalysis &SeqAnalysis,
15510 ASTContext &Context,
15511 OpenMPDirectiveKind Kind) {
15512 VarsWithInheritedDSAType TmpDSA;
15513 // Helper Lambda to handle storing initialization and body statements for
15514 // both ForStmt and CXXForRangeStmt.
15515 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
15516 if (auto *For = dyn_cast<ForStmt>(Val: LoopStmt)) {
15517 Analysis.OriginalInits.push_back(Elt: For->getInit());
15518 Analysis.TheForStmt = For;
15519 } else {
15520 auto *CXXFor = cast<CXXForRangeStmt>(Val: LoopStmt);
15521 Analysis.OriginalInits.push_back(Elt: CXXFor->getBeginStmt());
15522 Analysis.TheForStmt = CXXFor;
15523 }
15524 };
15525
15526 // Helper lambda functions to encapsulate the processing of different
15527 // derivations of the canonical loop sequence grammar
15528 // Modularized code for handling loop generation and transformations.
15529 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
15530 auto *LoopTransform = cast<OMPLoopTransformationDirective>(Val: Child);
15531 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
15532 unsigned NumGeneratedTopLevelLoops =
15533 LoopTransform->getNumGeneratedTopLevelLoops();
15534 // Handle the case where transformed statement is not available due to
15535 // dependent contexts
15536 if (!TransformedStmt) {
15537 if (NumGeneratedTopLevelLoops > 0) {
15538 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
15539 return true;
15540 }
15541 // Unroll full (0 loops produced)
15542 Diag(Loc: Child->getBeginLoc(), DiagID: diag::err_omp_not_for)
15543 << 0 << getOpenMPDirectiveName(D: Kind);
15544 return false;
15545 }
15546 // Handle loop transformations with multiple loop nests
15547 // Unroll full
15548 if (!NumGeneratedTopLevelLoops) {
15549 Diag(Loc: Child->getBeginLoc(), DiagID: diag::err_omp_not_for)
15550 << 0 << getOpenMPDirectiveName(D: Kind);
15551 return false;
15552 }
15553 // Loop transformatons such as split or loopranged fuse
15554 if (NumGeneratedTopLevelLoops > 1) {
15555 // Get the preinits related to this loop sequence generating
15556 // loop transformation (i.e loopranged fuse, split...)
15557 // These preinits differ slightly from regular inits/pre-inits related
15558 // to single loop generating loop transformations (interchange, unroll)
15559 // given that they are not bounded to a particular loop nest
15560 // so they need to be treated independently
15561 updatePreInits(Transform: LoopTransform, PreInits&: SeqAnalysis.LoopSequencePreInits);
15562 return analyzeLoopSequence(LoopSeqStmt: TransformedStmt, SeqAnalysis, Context, Kind);
15563 }
15564 // Vast majority: (Tile, Unroll, Stripe, Reverse, Interchange, Fuse all)
15565 // Process the transformed loop statement
15566 LoopAnalysis &NewTransformedSingleLoop =
15567 SeqAnalysis.Loops.emplace_back(Args&: Child);
15568 unsigned IsCanonical = checkOpenMPLoop(
15569 DKind: Kind, CollapseLoopCountExpr: nullptr, OrderedLoopCountExpr: nullptr, AStmt: TransformedStmt, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA&: TmpDSA,
15570 Built&: NewTransformedSingleLoop.HelperExprs);
15571
15572 if (!IsCanonical)
15573 return false;
15574
15575 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
15576 updatePreInits(Transform: LoopTransform, PreInits&: NewTransformedSingleLoop.TransformsPreInits);
15577
15578 SeqAnalysis.LoopSeqSize++;
15579 return true;
15580 };
15581
15582 // Modularized code for handling regular canonical loops.
15583 auto AnalyzeRegularLoop = [&](Stmt *Child) {
15584 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Args&: Child);
15585 unsigned IsCanonical =
15586 checkOpenMPLoop(DKind: Kind, CollapseLoopCountExpr: nullptr, OrderedLoopCountExpr: nullptr, AStmt: Child, SemaRef, DSA&: *DSAStack,
15587 VarsWithImplicitDSA&: TmpDSA, Built&: NewRegularLoop.HelperExprs);
15588
15589 if (!IsCanonical)
15590 return false;
15591
15592 StoreLoopStatements(NewRegularLoop, Child);
15593 NestedLoopCounterVisitor NLCV;
15594 NLCV.TraverseStmt(S: Child);
15595 return true;
15596 };
15597
15598 // High level grammar validation.
15599 for (Stmt *Child : LoopSeqStmt->children()) {
15600 if (!Child)
15601 continue;
15602 // Skip over non-loop-sequence statements.
15603 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(S: Child)) {
15604 Child = Child->IgnoreContainers();
15605 // Ignore empty compound statement.
15606 if (!Child)
15607 continue;
15608 // In the case of a nested loop sequence ignoring containers would not
15609 // be enough, a recurisve transversal of the loop sequence is required.
15610 if (isa<CompoundStmt>(Val: Child)) {
15611 if (!analyzeLoopSequence(LoopSeqStmt: Child, SeqAnalysis, Context, Kind))
15612 return false;
15613 // Already been treated, skip this children
15614 continue;
15615 }
15616 }
15617 // Regular loop sequence handling.
15618 if (LoopSequenceAnalysis::isLoopSequenceDerivation(S: Child)) {
15619 if (LoopAnalysis::isLoopTransformation(S: Child)) {
15620 if (!AnalyzeLoopGeneration(Child))
15621 return false;
15622 // AnalyzeLoopGeneration updates SeqAnalysis.LoopSeqSize accordingly.
15623 } else {
15624 if (!AnalyzeRegularLoop(Child))
15625 return false;
15626 SeqAnalysis.LoopSeqSize++;
15627 }
15628 } else {
15629 // Report error for invalid statement inside canonical loop sequence.
15630 Diag(Loc: Child->getBeginLoc(), DiagID: diag::err_omp_not_for)
15631 << 0 << getOpenMPDirectiveName(D: Kind);
15632 return false;
15633 }
15634 }
15635 return true;
15636}
15637
15638bool SemaOpenMP::checkTransformableLoopSequence(
15639 OpenMPDirectiveKind Kind, Stmt *AStmt, LoopSequenceAnalysis &SeqAnalysis,
15640 ASTContext &Context) {
15641 // Following OpenMP 6.0 API Specification, a Canonical Loop Sequence follows
15642 // the grammar:
15643 //
15644 // canonical-loop-sequence:
15645 // {
15646 // loop-sequence+
15647 // }
15648 // where loop-sequence can be any of the following:
15649 // 1. canonical-loop-sequence
15650 // 2. loop-nest
15651 // 3. loop-sequence-generating-construct (i.e OMPLoopTransformationDirective)
15652 //
15653 // To recognise and traverse this structure the helper function
15654 // analyzeLoopSequence serves as the recurisve entry point
15655 // and tries to match the input AST to the canonical loop sequence grammar
15656 // structure. This function will perform both a semantic and syntactical
15657 // analysis of the given statement according to OpenMP 6.0 definition of
15658 // the aforementioned canonical loop sequence.
15659
15660 // We expect an outer compound statement.
15661 if (!isa<CompoundStmt>(Val: AStmt)) {
15662 Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_not_a_loop_sequence)
15663 << getOpenMPDirectiveName(D: Kind);
15664 return false;
15665 }
15666
15667 // Recursive entry point to process the main loop sequence
15668 if (!analyzeLoopSequence(LoopSeqStmt: AStmt, SeqAnalysis, Context, Kind))
15669 return false;
15670
15671 // Diagnose an empty loop sequence.
15672 if (!SeqAnalysis.LoopSeqSize) {
15673 Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_empty_loop_sequence)
15674 << getOpenMPDirectiveName(D: Kind);
15675 return false;
15676 }
15677 return true;
15678}
15679
15680/// Add preinit statements that need to be propagated from the selected loop.
15681static void addLoopPreInits(ASTContext &Context,
15682 OMPLoopBasedDirective::HelperExprs &LoopHelper,
15683 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
15684 SmallVectorImpl<Stmt *> &PreInits) {
15685
15686 // For range-based for-statements, ensure that their syntactic sugar is
15687 // executed by adding them as pre-init statements.
15688 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt)) {
15689 Stmt *RangeInit = CXXRangeFor->getInit();
15690 if (RangeInit)
15691 PreInits.push_back(Elt: RangeInit);
15692
15693 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
15694 PreInits.push_back(Elt: new (Context) DeclStmt(RangeStmt->getDeclGroup(),
15695 RangeStmt->getBeginLoc(),
15696 RangeStmt->getEndLoc()));
15697
15698 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
15699 PreInits.push_back(Elt: new (Context) DeclStmt(RangeEnd->getDeclGroup(),
15700 RangeEnd->getBeginLoc(),
15701 RangeEnd->getEndLoc()));
15702 }
15703
15704 llvm::append_range(C&: PreInits, R&: OriginalInit);
15705
15706 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
15707 if (auto *PI = cast_or_null<DeclStmt>(Val: LoopHelper.PreInits)) {
15708 PreInits.push_back(Elt: new (Context) DeclStmt(
15709 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
15710 }
15711
15712 // Gather declarations for the data members used as counters.
15713 for (Expr *CounterRef : LoopHelper.Counters) {
15714 auto *CounterDecl = cast<DeclRefExpr>(Val: CounterRef)->getDecl();
15715 if (isa<OMPCapturedExprDecl>(Val: CounterDecl))
15716 PreInits.push_back(Elt: new (Context) DeclStmt(
15717 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
15718 }
15719}
15720
15721/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
15722/// loop of a construct.
15723static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts,
15724 bool RelaxNestForPeeledTransformation = false) {
15725 size_t NumLoops = LoopStmts.size();
15726 OMPLoopBasedDirective::doForAllLoops(
15727 CurStmt: AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
15728 Callback: [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
15729 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
15730 LoopStmts[Cnt] = CurStmt;
15731 return false;
15732 },
15733 RelaxNestForPeeledTransformation);
15734 assert(!is_contained(LoopStmts, nullptr) &&
15735 "Expecting a loop statement for each affected loop");
15736}
15737
15738/// A non-innermost affected loop generated by a nested loop transformation
15739/// (e.g. `omp reverse`) computes the user counter in statements ahead of the
15740/// next loop. A construct that rebuilds the nest only keeps the innermost
15741/// body, so it must re-emit these statements in the matching loop.
15742static void appendStmtsBeforeNestedLoop(Stmt *LoopStmt,
15743 SmallVectorImpl<Stmt *> &BodyParts) {
15744 Stmt *Body = isa<ForStmt>(Val: LoopStmt)
15745 ? cast<ForStmt>(Val: LoopStmt)->getBody()
15746 : cast<CXXForRangeStmt>(Val: LoopStmt)->getBody();
15747 llvm::append_range(C&: BodyParts,
15748 R: OMPLoopBasedDirective::getStmtsBeforeNestedLoop(Body));
15749}
15750
15751/// Build and return a DeclRefExpr for the floor induction variable using the
15752/// SemaRef and the provided parameters.
15753static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
15754 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
15755 return buildDeclRefExpr(S&: SemaRef, D: FloorIndVars[I], Ty: IVTy,
15756 Loc: OrigCntVar->getExprLoc());
15757}
15758
15759StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
15760 Stmt *AStmt,
15761 SourceLocation StartLoc,
15762 SourceLocation EndLoc) {
15763 ASTContext &Context = getASTContext();
15764 Scope *CurScope = SemaRef.getCurScope();
15765
15766 const auto *SizesClause =
15767 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15768 if (!SizesClause ||
15769 llvm::any_of(Range: SizesClause->getSizesRefs(), P: [](Expr *E) { return !E; }))
15770 return StmtError();
15771 unsigned NumLoops = SizesClause->getNumSizes();
15772
15773 // Empty statement should only be possible if there already was an error.
15774 if (!AStmt)
15775 return StmtError();
15776
15777 // Verify and diagnose loop nest.
15778 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
15779 Stmt *Body = nullptr;
15780 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
15781 if (!checkTransformableLoopNest(Kind: OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
15782 OriginalInits))
15783 return StmtError();
15784
15785 // Delay tiling to when template is completely instantiated.
15786 if (SemaRef.CurContext->isDependentContext())
15787 return OMPTileDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15788 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
15789
15790 assert(LoopHelpers.size() == NumLoops &&
15791 "Expecting loop iteration space dimensionality to match number of "
15792 "affected loops");
15793 assert(OriginalInits.size() == NumLoops &&
15794 "Expecting loop iteration space dimensionality to match number of "
15795 "affected loops");
15796
15797 // Collect all affected loop statements.
15798 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15799 collectLoopStmts(AStmt, LoopStmts, /*RelaxNestForPeeledTransformation=*/true);
15800
15801 SmallVector<Stmt *, 4> PreInits;
15802 CaptureVars CopyTransformer(SemaRef);
15803
15804 // Create iteration variables for the generated loops.
15805 SmallVector<VarDecl *, 4> FloorIndVars;
15806 SmallVector<VarDecl *, 4> TileIndVars;
15807 FloorIndVars.resize(N: NumLoops);
15808 TileIndVars.resize(N: NumLoops);
15809 for (unsigned I = 0; I < NumLoops; ++I) {
15810 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15811
15812 assert(LoopHelper.Counters.size() == 1 &&
15813 "Expect single-dimensional loop iteration space");
15814 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15815 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15816 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15817 QualType CntTy = IterVarRef->getType();
15818
15819 // Iteration variable for the floor (i.e. outer) loop.
15820 {
15821 std::string FloorCntName =
15822 (Twine(".floor_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15823 VarDecl *FloorCntDecl =
15824 buildVarDecl(SemaRef, Loc: {}, Type: CntTy, Name: FloorCntName, Attrs: nullptr, OrigRef: OrigCntVar);
15825 FloorIndVars[I] = FloorCntDecl;
15826 }
15827
15828 // Iteration variable for the tile (i.e. inner) loop.
15829 {
15830 std::string TileCntName =
15831 (Twine(".tile_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15832
15833 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15834 // used by the expressions to derive the original iteration variable's
15835 // value from the logical iteration number.
15836 auto *TileCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
15837 TileCntDecl->setDeclName(
15838 &SemaRef.PP.getIdentifierTable().get(Name: TileCntName));
15839 TileIndVars[I] = TileCntDecl;
15840 }
15841
15842 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
15843 PreInits);
15844 }
15845
15846 // Once the original iteration values are set, append the innermost body.
15847 Stmt *Inner = Body;
15848
15849 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
15850 SizesClause, CurScope](int I) -> Expr * {
15851 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
15852
15853 if (DimTileSizeExpr->containsErrors())
15854 return nullptr;
15855
15856 if (isa<ConstantExpr>(Val: DimTileSizeExpr))
15857 return AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr));
15858
15859 // When the tile size is not a constant but a variable, it is possible to
15860 // pass non-positive numbers. For instance:
15861 // \code{c}
15862 // int a = 0;
15863 // #pragma omp tile sizes(a)
15864 // for (int i = 0; i < 42; ++i)
15865 // body(i);
15866 // \endcode
15867 // Although there is no meaningful interpretation of the tile size, the body
15868 // should still be executed 42 times to avoid surprises. To preserve the
15869 // invariant that every loop iteration is executed exactly once and not
15870 // cause an infinite loop, apply a minimum tile size of one.
15871 // Build expr:
15872 // \code{c}
15873 // (TS <= 0) ? 1 : TS
15874 // \endcode
15875 QualType DimTy = DimTileSizeExpr->getType();
15876 uint64_t DimWidth = Context.getTypeSize(T: DimTy);
15877 IntegerLiteral *Zero = IntegerLiteral::Create(
15878 C: Context, V: llvm::APInt::getZero(numBits: DimWidth), type: DimTy, l: {});
15879 IntegerLiteral *One =
15880 IntegerLiteral::Create(C: Context, V: llvm::APInt(DimWidth, 1), type: DimTy, l: {});
15881 Expr *Cond = AssertSuccess(R: SemaRef.BuildBinOp(
15882 S: CurScope, OpLoc: {}, Opc: BO_LE,
15883 LHSExpr: AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr)), RHSExpr: Zero));
15884 Expr *MinOne = new (Context) ConditionalOperator(
15885 Cond, {}, One, {},
15886 AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr)), DimTy,
15887 VK_PRValue, OK_Ordinary);
15888 return MinOne;
15889 };
15890
15891 // Create tile loops from the inside to the outside.
15892 //
15893 // Each intra-tile loop is emitted in its natural min-bounded form, which has
15894 // no per-iteration body predicate and vectorizes well when run directly:
15895 // for (.tile.iv = .floor.iv; .tile.iv < min(.floor.iv + T, N); ++.tile.iv)
15896 //
15897 // A loop-associated directive that *consumes* this loop (e.g. `collapse`)
15898 // instead needs a constant, floor-independent trip count to linearize the
15899 // nest, which the min() bound cannot give it. Rather than change the
15900 // emitted loop, we attach a droppable OMPInvariantPredicateBoundAttr hint
15901 // below carrying an equivalent rectangular reinterpretation:
15902 // RectCond : .tile.iv < .floor.iv + T -- rectangular bound, analyzed by
15903 // checkOpenMPIterationSpace in place of the stored condition
15904 // TileSize : T -- constant per-tile trip count
15905 // Predicate : .tile.iv < N -- remainder-tile overshoot,
15906 // applied as a body guard instead of shortening the trip count;
15907 // omitted when N is known to be a multiple of T, as there is
15908 // then no partial tile to guard against
15909 // Because the reinterpreted lower bound is still `.floor.iv`,
15910 // checkOpenMPIterationSpace sets IsNonRectangularLB on the matching floor
15911 // counter, so a collapsed `.tile.iv` re-reads the floor's current value
15912 // instead of a stale preheader snapshot. Collapsing through stacked tiles
15913 // (tile-of-tile) is not supported: the inner floor is not itself a collapsed
15914 // counter.
15915 for (int I = NumLoops - 1; I >= 0; --I) {
15916 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15917 Expr *NumIterations = LoopHelper.NumIterations;
15918 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15919 QualType IVTy = NumIterations->getType();
15920 Stmt *LoopStmt = LoopStmts[I];
15921
15922 // Commonly used variables. One of the constraints of an AST is that every
15923 // node object must appear at most once, hence we define a lambda that
15924 // creates a new AST node at every use.
15925 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
15926 OrigCntVar]() {
15927 return buildDeclRefExpr(S&: SemaRef, D: TileIndVars[I], Ty: IVTy,
15928 Loc: OrigCntVar->getExprLoc());
15929 };
15930
15931 // For init-statement: auto .tile.iv = .floor.iv
15932 SemaRef.AddInitializerToDecl(
15933 dcl: TileIndVars[I],
15934 init: SemaRef
15935 .DefaultLvalueConversion(
15936 E: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15937 .get(),
15938 /*DirectInit=*/false);
15939 Decl *CounterDecl = TileIndVars[I];
15940 StmtResult InitStmt = new (Context)
15941 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15942 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15943 if (!InitStmt.isUsable())
15944 return StmtError();
15945
15946 // For cond-expression:
15947 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
15948 Expr *DimTileSize = MakeDimTileSize(I);
15949 if (!DimTileSize)
15950 return StmtError();
15951 ExprResult EndOfTile = SemaRef.BuildBinOp(
15952 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
15953 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15954 RHSExpr: DimTileSize);
15955 if (!EndOfTile.isUsable())
15956 return StmtError();
15957 ExprResult IsPartialTile =
15958 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15959 LHSExpr: NumIterations, RHSExpr: EndOfTile.get());
15960 if (!IsPartialTile.isUsable())
15961 return StmtError();
15962 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
15963 QuestionLoc: LoopHelper.Cond->getBeginLoc(), ColonLoc: LoopHelper.Cond->getEndLoc(),
15964 CondExpr: IsPartialTile.get(), LHSExpr: NumIterations, RHSExpr: EndOfTile.get());
15965 if (!MinTileAndIterSpace.isUsable())
15966 return StmtError();
15967 ExprResult CondExpr =
15968 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15969 LHSExpr: MakeTileIVRef(), RHSExpr: MinTileAndIterSpace.get());
15970 if (!CondExpr.isUsable())
15971 return StmtError();
15972
15973 // For incr-statement: ++.tile.iv
15974 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15975 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeTileIVRef());
15976 if (!IncrStmt.isUsable())
15977 return StmtError();
15978
15979 // Build OMPInvariantPredicateBoundAttr hint (RectCond, TileSize,
15980 // Predicate).
15981 Expr *RectDimTileSize = MakeDimTileSize(I);
15982 if (!RectDimTileSize)
15983 return StmtError();
15984 ExprResult RectEndOfTile = SemaRef.BuildBinOp(
15985 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
15986 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15987 RHSExpr: RectDimTileSize);
15988 if (!RectEndOfTile.isUsable())
15989 return StmtError();
15990 ExprResult RectCond =
15991 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15992 LHSExpr: MakeTileIVRef(), RHSExpr: RectEndOfTile.get());
15993 Expr *TileSizeExpr = MakeDimTileSize(I);
15994 if (!TileSizeExpr)
15995 return StmtError();
15996 ExprResult TileSize = SemaRef.PerformImplicitConversion(
15997 From: TileSizeExpr, ToType: IVTy, Action: AssignmentAction::Converting,
15998 /*AllowExplicit=*/true);
15999 if (!RectCond.isUsable() || !TileSize.isUsable())
16000 return StmtError();
16001
16002 // The overshoot guard is only needed if the last tile can be partial. When
16003 // both the trip count and the tile size are known at compile time and the
16004 // former is a multiple of the latter, every tile is full, so leave the
16005 // predicate out. A dependent or run-time value makes
16006 // the evaluation fail, which keeps the guard.
16007 bool NoPartialTile = false;
16008 Expr::EvalResult TileSizeVal, NumIterationsVal;
16009 if (TileSizeExpr->EvaluateAsInt(Result&: TileSizeVal, Ctx: Context) &&
16010 NumIterations->EvaluateAsInt(Result&: NumIterationsVal, Ctx: Context)) {
16011 llvm::APSInt TS = TileSizeVal.Val.getInt();
16012 llvm::APSInt N = NumIterationsVal.Val.getInt();
16013 unsigned Width = std::max(a: TS.getBitWidth(), b: N.getBitWidth());
16014 TS = TS.extend(width: Width);
16015 N = N.extend(width: Width);
16016 NoPartialTile =
16017 TS.isStrictlyPositive() && N.isStrictlyPositive() && N.urem(RHS: TS) == 0;
16018 }
16019
16020 ExprResult Predicate;
16021 if (!NoPartialTile) {
16022 Predicate = SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(),
16023 Opc: BO_LT, LHSExpr: MakeTileIVRef(), RHSExpr: NumIterations);
16024 if (!Predicate.isUsable())
16025 return StmtError();
16026 }
16027
16028 // Statements to set the original iteration variable's value from the
16029 // logical iteration number.
16030 // Generated for loop is:
16031 // \code
16032 // Original_for_init;
16033 // for (auto .tile.iv = .floor.iv;
16034 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
16035 // ++.tile.iv) {
16036 // Original_Body;
16037 // Original_counter_update;
16038 // }
16039 // \endcode
16040 // FIXME: If the innermost body is an loop itself, inserting these
16041 // statements stops it being recognized as a perfectly nested loop (e.g.
16042 // for applying tiling again). If this is the case, sink the expressions
16043 // further into the inner loop.
16044 SmallVector<Stmt *, 4> BodyParts;
16045 BodyParts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
16046 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
16047 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
16048 if (static_cast<unsigned>(I) + 1 < NumLoops)
16049 appendStmtsBeforeNestedLoop(LoopStmt, BodyParts);
16050 BodyParts.push_back(Elt: Inner);
16051 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
16052 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
16053 Inner = new (Context)
16054 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
16055 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
16056 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16057
16058 // Attach the droppable reinterpretation attribute to the intra-tile loop.
16059 auto *Hint = OMPInvariantPredicateBoundAttr::CreateImplicit(
16060 Ctx&: Context, RectCond: RectCond.get(), TileSize: TileSize.get(),
16061 Predicate: Predicate.isUsable() ? Predicate.get() : nullptr,
16062 Range: Inner->getSourceRange());
16063 Inner =
16064 AttributedStmt::Create(C: Context, Loc: Inner->getBeginLoc(), Attrs: {Hint}, SubStmt: Inner);
16065 }
16066
16067 // Create floor loops from the inside to the outside.
16068 for (int I = NumLoops - 1; I >= 0; --I) {
16069 auto &LoopHelper = LoopHelpers[I];
16070 Expr *NumIterations = LoopHelper.NumIterations;
16071 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
16072 QualType IVTy = NumIterations->getType();
16073
16074 // For init-statement: auto .floor.iv = 0
16075 SemaRef.AddInitializerToDecl(
16076 dcl: FloorIndVars[I],
16077 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
16078 /*DirectInit=*/false);
16079 Decl *CounterDecl = FloorIndVars[I];
16080 StmtResult InitStmt = new (Context)
16081 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
16082 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
16083 if (!InitStmt.isUsable())
16084 return StmtError();
16085
16086 // For cond-expression: .floor.iv < NumIterations
16087 ExprResult CondExpr = SemaRef.BuildBinOp(
16088 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
16089 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
16090 RHSExpr: NumIterations);
16091 if (!CondExpr.isUsable())
16092 return StmtError();
16093
16094 // For incr-statement: .floor.iv += DimTileSize
16095 Expr *DimTileSize = MakeDimTileSize(I);
16096 if (!DimTileSize)
16097 return StmtError();
16098 ExprResult IncrStmt = SemaRef.BuildBinOp(
16099 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
16100 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
16101 RHSExpr: DimTileSize);
16102 if (!IncrStmt.isUsable())
16103 return StmtError();
16104
16105 Inner = new (Context)
16106 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
16107 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
16108 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16109 }
16110
16111 return OMPTileDirective::Create(C: Context, StartLoc, EndLoc, Clauses, NumLoops,
16112 AssociatedStmt: AStmt, TransformedStmt: Inner,
16113 PreInits: buildPreInits(Context, PreInits));
16114}
16115
16116StmtResult SemaOpenMP::ActOnOpenMPStripeDirective(ArrayRef<OMPClause *> Clauses,
16117 Stmt *AStmt,
16118 SourceLocation StartLoc,
16119 SourceLocation EndLoc) {
16120 ASTContext &Context = getASTContext();
16121 Scope *CurScope = SemaRef.getCurScope();
16122
16123 const auto *SizesClause =
16124 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
16125 if (!SizesClause ||
16126 llvm::any_of(Range: SizesClause->getSizesRefs(), P: [](const Expr *SizeExpr) {
16127 return !SizeExpr || SizeExpr->containsErrors();
16128 }))
16129 return StmtError();
16130 unsigned NumLoops = SizesClause->getNumSizes();
16131
16132 // Empty statement should only be possible if there already was an error.
16133 if (!AStmt)
16134 return StmtError();
16135
16136 // Verify and diagnose loop nest.
16137 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
16138 Stmt *Body = nullptr;
16139 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
16140 if (!checkTransformableLoopNest(Kind: OMPD_stripe, AStmt, NumLoops, LoopHelpers,
16141 Body, OriginalInits))
16142 return StmtError();
16143
16144 // Delay striping to when template is completely instantiated.
16145 if (SemaRef.CurContext->isDependentContext())
16146 return OMPStripeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16147 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16148
16149 assert(LoopHelpers.size() == NumLoops &&
16150 "Expecting loop iteration space dimensionality to match number of "
16151 "affected loops");
16152 assert(OriginalInits.size() == NumLoops &&
16153 "Expecting loop iteration space dimensionality to match number of "
16154 "affected loops");
16155
16156 // Collect all affected loop statements.
16157 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
16158 collectLoopStmts(AStmt, LoopStmts, /*RelaxNestForPeeledTransformation=*/true);
16159
16160 SmallVector<Stmt *, 4> PreInits;
16161 CaptureVars CopyTransformer(SemaRef);
16162
16163 // Create iteration variables for the generated loops.
16164 SmallVector<VarDecl *, 4> FloorIndVars;
16165 SmallVector<VarDecl *, 4> StripeIndVars;
16166 FloorIndVars.resize(N: NumLoops);
16167 StripeIndVars.resize(N: NumLoops);
16168 for (unsigned I : llvm::seq<unsigned>(Size: NumLoops)) {
16169 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16170
16171 assert(LoopHelper.Counters.size() == 1 &&
16172 "Expect single-dimensional loop iteration space");
16173 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
16174 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
16175 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
16176 QualType CntTy = IterVarRef->getType();
16177
16178 // Iteration variable for the stripe (i.e. outer) loop.
16179 {
16180 std::string FloorCntName =
16181 (Twine(".floor_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
16182 VarDecl *FloorCntDecl =
16183 buildVarDecl(SemaRef, Loc: {}, Type: CntTy, Name: FloorCntName, Attrs: nullptr, OrigRef: OrigCntVar);
16184 FloorIndVars[I] = FloorCntDecl;
16185 }
16186
16187 // Iteration variable for the stripe (i.e. inner) loop.
16188 {
16189 std::string StripeCntName =
16190 (Twine(".stripe_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
16191
16192 // Reuse the iteration variable created by checkOpenMPLoop. It is also
16193 // used by the expressions to derive the original iteration variable's
16194 // value from the logical iteration number.
16195 auto *StripeCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
16196 StripeCntDecl->setDeclName(
16197 &SemaRef.PP.getIdentifierTable().get(Name: StripeCntName));
16198 StripeIndVars[I] = StripeCntDecl;
16199 }
16200
16201 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
16202 PreInits);
16203 }
16204
16205 // Once the original iteration values are set, append the innermost body.
16206 Stmt *Inner = Body;
16207
16208 auto MakeDimStripeSize = [&](int I) -> Expr * {
16209 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
16210 if (isa<ConstantExpr>(Val: DimStripeSizeExpr))
16211 return AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr));
16212
16213 // When the stripe size is not a constant but a variable, it is possible to
16214 // pass non-positive numbers. For instance:
16215 // \code{c}
16216 // int a = 0;
16217 // #pragma omp stripe sizes(a)
16218 // for (int i = 0; i < 42; ++i)
16219 // body(i);
16220 // \endcode
16221 // Although there is no meaningful interpretation of the stripe size, the
16222 // body should still be executed 42 times to avoid surprises. To preserve
16223 // the invariant that every loop iteration is executed exactly once and not
16224 // cause an infinite loop, apply a minimum stripe size of one.
16225 // Build expr:
16226 // \code{c}
16227 // (TS <= 0) ? 1 : TS
16228 // \endcode
16229 QualType DimTy = DimStripeSizeExpr->getType();
16230 uint64_t DimWidth = Context.getTypeSize(T: DimTy);
16231 IntegerLiteral *Zero = IntegerLiteral::Create(
16232 C: Context, V: llvm::APInt::getZero(numBits: DimWidth), type: DimTy, l: {});
16233 IntegerLiteral *One =
16234 IntegerLiteral::Create(C: Context, V: llvm::APInt(DimWidth, 1), type: DimTy, l: {});
16235 Expr *Cond = AssertSuccess(R: SemaRef.BuildBinOp(
16236 S: CurScope, OpLoc: {}, Opc: BO_LE,
16237 LHSExpr: AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr)), RHSExpr: Zero));
16238 Expr *MinOne = new (Context) ConditionalOperator(
16239 Cond, {}, One, {},
16240 AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr)), DimTy,
16241 VK_PRValue, OK_Ordinary);
16242 return MinOne;
16243 };
16244
16245 // Create stripe loops from the inside to the outside.
16246 for (int I = NumLoops - 1; I >= 0; --I) {
16247 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16248 Expr *NumIterations = LoopHelper.NumIterations;
16249 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
16250 QualType IVTy = NumIterations->getType();
16251 Stmt *LoopStmt = LoopStmts[I];
16252
16253 // For init-statement: auto .stripe.iv = .floor.iv
16254 SemaRef.AddInitializerToDecl(
16255 dcl: StripeIndVars[I],
16256 init: SemaRef
16257 .DefaultLvalueConversion(
16258 E: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
16259 .get(),
16260 /*DirectInit=*/false);
16261 Decl *CounterDecl = StripeIndVars[I];
16262 StmtResult InitStmt = new (Context)
16263 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
16264 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
16265 if (!InitStmt.isUsable())
16266 return StmtError();
16267
16268 // For cond-expression:
16269 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
16270 ExprResult EndOfStripe = SemaRef.BuildBinOp(
16271 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
16272 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
16273 RHSExpr: MakeDimStripeSize(I));
16274 if (!EndOfStripe.isUsable())
16275 return StmtError();
16276 ExprResult IsPartialStripe =
16277 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
16278 LHSExpr: NumIterations, RHSExpr: EndOfStripe.get());
16279 if (!IsPartialStripe.isUsable())
16280 return StmtError();
16281 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
16282 QuestionLoc: LoopHelper.Cond->getBeginLoc(), ColonLoc: LoopHelper.Cond->getEndLoc(),
16283 CondExpr: IsPartialStripe.get(), LHSExpr: NumIterations, RHSExpr: EndOfStripe.get());
16284 if (!MinStripeAndIterSpace.isUsable())
16285 return StmtError();
16286 ExprResult CondExpr = SemaRef.BuildBinOp(
16287 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
16288 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars: StripeIndVars, I, IVTy, OrigCntVar),
16289 RHSExpr: MinStripeAndIterSpace.get());
16290 if (!CondExpr.isUsable())
16291 return StmtError();
16292
16293 // For incr-statement: ++.stripe.iv
16294 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
16295 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc,
16296 Input: makeFloorIVRef(SemaRef, FloorIndVars: StripeIndVars, I, IVTy, OrigCntVar));
16297 if (!IncrStmt.isUsable())
16298 return StmtError();
16299
16300 // Statements to set the original iteration variable's value from the
16301 // logical iteration number.
16302 // Generated for loop is:
16303 // \code
16304 // Original_for_init;
16305 // for (auto .stripe.iv = .floor.iv;
16306 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
16307 // ++.stripe.iv) {
16308 // Original_Body;
16309 // Original_counter_update;
16310 // }
16311 // \endcode
16312 // FIXME: If the innermost body is a loop itself, inserting these
16313 // statements stops it being recognized as a perfectly nested loop (e.g.
16314 // for applying another loop transformation). If this is the case, sink the
16315 // expressions further into the inner loop.
16316 SmallVector<Stmt *, 4> BodyParts;
16317 BodyParts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
16318 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
16319 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
16320 if (static_cast<unsigned>(I) + 1 < NumLoops)
16321 appendStmtsBeforeNestedLoop(LoopStmt, BodyParts);
16322 BodyParts.push_back(Elt: Inner);
16323 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
16324 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
16325 Inner = new (Context)
16326 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
16327 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
16328 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16329 }
16330
16331 // Create grid loops from the inside to the outside.
16332 for (int I = NumLoops - 1; I >= 0; --I) {
16333 auto &LoopHelper = LoopHelpers[I];
16334 Expr *NumIterations = LoopHelper.NumIterations;
16335 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
16336 QualType IVTy = NumIterations->getType();
16337
16338 // For init-statement: auto .grid.iv = 0
16339 SemaRef.AddInitializerToDecl(
16340 dcl: FloorIndVars[I],
16341 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
16342 /*DirectInit=*/false);
16343 Decl *CounterDecl = FloorIndVars[I];
16344 StmtResult InitStmt = new (Context)
16345 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
16346 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
16347 if (!InitStmt.isUsable())
16348 return StmtError();
16349
16350 // For cond-expression: .floor.iv < NumIterations
16351 ExprResult CondExpr = SemaRef.BuildBinOp(
16352 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
16353 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
16354 RHSExpr: NumIterations);
16355 if (!CondExpr.isUsable())
16356 return StmtError();
16357
16358 // For incr-statement: .floor.iv += DimStripeSize
16359 ExprResult IncrStmt = SemaRef.BuildBinOp(
16360 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
16361 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
16362 RHSExpr: MakeDimStripeSize(I));
16363 if (!IncrStmt.isUsable())
16364 return StmtError();
16365
16366 Inner = new (Context)
16367 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
16368 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
16369 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16370 }
16371
16372 return OMPStripeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16373 NumLoops, AssociatedStmt: AStmt, TransformedStmt: Inner,
16374 PreInits: buildPreInits(Context, PreInits));
16375}
16376
16377StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
16378 Stmt *AStmt,
16379 SourceLocation StartLoc,
16380 SourceLocation EndLoc) {
16381 ASTContext &Context = getASTContext();
16382 Scope *CurScope = SemaRef.getCurScope();
16383 // Empty statement should only be possible if there already was an error.
16384 if (!AStmt)
16385 return StmtError();
16386
16387 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
16388 MutuallyExclusiveClauses: {OMPC_partial, OMPC_full}))
16389 return StmtError();
16390
16391 const OMPFullClause *FullClause =
16392 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
16393 const OMPPartialClause *PartialClause =
16394 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
16395 assert(!(FullClause && PartialClause) &&
16396 "mutual exclusivity must have been checked before");
16397
16398 constexpr unsigned NumLoops = 1;
16399 Stmt *Body = nullptr;
16400 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
16401 NumLoops);
16402 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
16403 if (!checkTransformableLoopNest(Kind: OMPD_unroll, AStmt, NumLoops, LoopHelpers,
16404 Body, OriginalInits))
16405 return StmtError();
16406
16407 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
16408
16409 // Delay unrolling to when template is completely instantiated.
16410 if (SemaRef.CurContext->isDependentContext())
16411 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
16412 NumGeneratedTopLevelLoops, TransformedStmt: nullptr,
16413 PreInits: nullptr);
16414
16415 assert(LoopHelpers.size() == NumLoops &&
16416 "Expecting a single-dimensional loop iteration space");
16417 assert(OriginalInits.size() == NumLoops &&
16418 "Expecting a single-dimensional loop iteration space");
16419 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
16420
16421 if (FullClause) {
16422 if (!VerifyPositiveIntegerConstantInClause(
16423 Op: LoopHelper.NumIterations, CKind: OMPC_full, /*StrictlyPositive=*/false,
16424 /*SuppressExprDiags=*/true)
16425 .isUsable()) {
16426 Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_unroll_full_variable_trip_count);
16427 Diag(Loc: FullClause->getBeginLoc(), DiagID: diag::note_omp_directive_here)
16428 << "#pragma omp unroll full";
16429 return StmtError();
16430 }
16431 }
16432
16433 // The generated loop may only be passed to other loop-associated directive
16434 // when a partial clause is specified. Without the requirement it is
16435 // sufficient to generate loop unroll metadata at code-generation.
16436 if (NumGeneratedTopLevelLoops == 0)
16437 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
16438 NumGeneratedTopLevelLoops, TransformedStmt: nullptr,
16439 PreInits: nullptr);
16440
16441 // Otherwise, we need to provide a de-sugared/transformed AST that can be
16442 // associated with another loop directive.
16443 //
16444 // The canonical loop analysis return by checkTransformableLoopNest assumes
16445 // the following structure to be the same loop without transformations or
16446 // directives applied: \code OriginalInits; LoopHelper.PreInits;
16447 // LoopHelper.Counters;
16448 // for (; IV < LoopHelper.NumIterations; ++IV) {
16449 // LoopHelper.Updates;
16450 // Body;
16451 // }
16452 // \endcode
16453 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
16454 // and referenced by LoopHelper.IterationVarRef.
16455 //
16456 // The unrolling directive transforms this into the following loop:
16457 // \code
16458 // OriginalInits; \
16459 // LoopHelper.PreInits; > NewPreInits
16460 // LoopHelper.Counters; /
16461 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
16462 // #pragma clang loop unroll_count(Factor)
16463 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
16464 // {
16465 // LoopHelper.Updates;
16466 // Body;
16467 // }
16468 // }
16469 // \endcode
16470 // where UIV is a new logical iteration counter. IV must be the same VarDecl
16471 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
16472 // references it. If the partially unrolled loop is associated with another
16473 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
16474 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
16475 // OpenMP canonical loop. The inner loop is not an associable canonical loop
16476 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
16477 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
16478 // property of the OMPLoopBasedDirective instead of statements in
16479 // CompoundStatement. This is to allow the loop to become a non-outermost loop
16480 // of a canonical loop nest where these PreInits are emitted before the
16481 // outermost directive.
16482
16483 // Find the loop statement.
16484 Stmt *LoopStmt = nullptr;
16485 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
16486
16487 // Determine the PreInit declarations.
16488 SmallVector<Stmt *, 4> PreInits;
16489 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
16490
16491 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
16492 QualType IVTy = IterationVarRef->getType();
16493 assert(LoopHelper.Counters.size() == 1 &&
16494 "Expecting a single-dimensional loop iteration space");
16495 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
16496
16497 // Determine the unroll factor.
16498 uint64_t Factor;
16499 SourceLocation FactorLoc;
16500 if (Expr *FactorVal = PartialClause->getFactor();
16501 FactorVal && !FactorVal->containsErrors()) {
16502 Factor = FactorVal->getIntegerConstantExpr(Ctx: Context)->getLimitedValue();
16503 FactorLoc = FactorVal->getExprLoc();
16504 } else {
16505 // TODO: Use a better profitability model.
16506 Factor = 2;
16507 }
16508 assert(Factor > 0 && "Expected positive unroll factor");
16509 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
16510 return IntegerLiteral::Create(
16511 C: getASTContext(), V: llvm::APInt(getASTContext().getIntWidth(T: IVTy), Factor),
16512 type: IVTy, l: FactorLoc);
16513 };
16514
16515 // Iteration variable SourceLocations.
16516 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
16517 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
16518 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
16519
16520 // Internal variable names.
16521 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
16522 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
16523 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
16524
16525 // Create the iteration variable for the unrolled loop.
16526 VarDecl *OuterIVDecl =
16527 buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: OuterIVName, Attrs: nullptr, OrigRef: OrigVar);
16528 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
16529 return buildDeclRefExpr(S&: SemaRef, D: OuterIVDecl, Ty: IVTy, Loc: OrigVarLoc);
16530 };
16531
16532 // Iteration variable for the inner loop: Reuse the iteration variable created
16533 // by checkOpenMPLoop.
16534 auto *InnerIVDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
16535 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name: InnerIVName));
16536 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
16537 return buildDeclRefExpr(S&: SemaRef, D: InnerIVDecl, Ty: IVTy, Loc: OrigVarLoc);
16538 };
16539
16540 // Make a copy of the NumIterations expression for each use: By the AST
16541 // constraints, every expression object in a DeclContext must be unique.
16542 CaptureVars CopyTransformer(SemaRef);
16543 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
16544 return AssertSuccess(
16545 R: CopyTransformer.TransformExpr(E: LoopHelper.NumIterations));
16546 };
16547
16548 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
16549 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(E: MakeOuterRef());
16550 SemaRef.AddInitializerToDecl(dcl: InnerIVDecl, init: LValueConv.get(),
16551 /*DirectInit=*/false);
16552 StmtResult InnerInit = new (Context)
16553 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
16554 if (!InnerInit.isUsable())
16555 return StmtError();
16556
16557 // Inner For cond-expression:
16558 // \code
16559 // .unroll_inner.iv < .unrolled.iv + Factor &&
16560 // .unroll_inner.iv < NumIterations
16561 // \endcode
16562 // This conjunction of two conditions allows ScalarEvolution to derive the
16563 // maximum trip count of the inner loop.
16564 ExprResult EndOfTile =
16565 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
16566 LHSExpr: MakeOuterRef(), RHSExpr: MakeFactorExpr());
16567 if (!EndOfTile.isUsable())
16568 return StmtError();
16569 ExprResult InnerCond1 =
16570 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
16571 LHSExpr: MakeInnerRef(), RHSExpr: EndOfTile.get());
16572 if (!InnerCond1.isUsable())
16573 return StmtError();
16574 ExprResult InnerCond2 =
16575 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
16576 LHSExpr: MakeInnerRef(), RHSExpr: MakeNumIterations());
16577 if (!InnerCond2.isUsable())
16578 return StmtError();
16579 ExprResult InnerCond =
16580 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LAnd,
16581 LHSExpr: InnerCond1.get(), RHSExpr: InnerCond2.get());
16582 if (!InnerCond.isUsable())
16583 return StmtError();
16584
16585 // Inner For incr-statement: ++.unroll_inner.iv
16586 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
16587 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeInnerRef());
16588 if (!InnerIncr.isUsable())
16589 return StmtError();
16590
16591 // Inner For statement.
16592 SmallVector<Stmt *> InnerBodyStmts;
16593 InnerBodyStmts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
16594 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
16595 InnerBodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
16596 InnerBodyStmts.push_back(Elt: Body);
16597 CompoundStmt *InnerBody =
16598 CompoundStmt::Create(C: getASTContext(), Stmts: InnerBodyStmts, FPFeatures: FPOptionsOverride(),
16599 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
16600 ForStmt *InnerFor = new (Context)
16601 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
16602 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
16603 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16604
16605 // Unroll metadata for the inner loop.
16606 // This needs to take into account the remainder portion of the unrolled loop,
16607 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
16608 // supports multiple loop exits. Instead, unroll using a factor equivalent to
16609 // the maximum trip count, which will also generate a remainder loop. Just
16610 // `unroll(enable)` (which could have been useful if the user has not
16611 // specified a concrete factor; even though the outer loop cannot be
16612 // influenced anymore, would avoid more code bloat than necessary) will refuse
16613 // the loop because "Won't unroll; remainder loop could not be generated when
16614 // assuming runtime trip count". Even if it did work, it must not choose a
16615 // larger unroll factor than the maximum loop length, or it would always just
16616 // execute the remainder loop.
16617 LoopHintAttr *UnrollHintAttr =
16618 LoopHintAttr::CreateImplicit(Ctx&: Context, Option: LoopHintAttr::UnrollCount,
16619 State: LoopHintAttr::Numeric, Value: MakeFactorExpr());
16620 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
16621 C: getASTContext(), Loc: StartLoc, Attrs: {UnrollHintAttr}, SubStmt: InnerFor);
16622
16623 // Outer For init-statement: auto .unrolled.iv = 0
16624 SemaRef.AddInitializerToDecl(
16625 dcl: OuterIVDecl,
16626 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
16627 /*DirectInit=*/false);
16628 StmtResult OuterInit = new (Context)
16629 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
16630 if (!OuterInit.isUsable())
16631 return StmtError();
16632
16633 // Outer For cond-expression: .unrolled.iv < NumIterations
16634 ExprResult OuterConde =
16635 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
16636 LHSExpr: MakeOuterRef(), RHSExpr: MakeNumIterations());
16637 if (!OuterConde.isUsable())
16638 return StmtError();
16639
16640 // Outer For incr-statement: .unrolled.iv += Factor
16641 ExprResult OuterIncr =
16642 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
16643 LHSExpr: MakeOuterRef(), RHSExpr: MakeFactorExpr());
16644 if (!OuterIncr.isUsable())
16645 return StmtError();
16646
16647 // Outer For statement.
16648 ForStmt *OuterFor = new (Context)
16649 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
16650 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
16651 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16652
16653 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
16654 NumGeneratedTopLevelLoops, TransformedStmt: OuterFor,
16655 PreInits: buildPreInits(Context, PreInits));
16656}
16657
16658StmtResult SemaOpenMP::ActOnOpenMPReverseDirective(Stmt *AStmt,
16659 SourceLocation StartLoc,
16660 SourceLocation EndLoc) {
16661 ASTContext &Context = getASTContext();
16662 Scope *CurScope = SemaRef.getCurScope();
16663
16664 // Empty statement should only be possible if there already was an error.
16665 if (!AStmt)
16666 return StmtError();
16667
16668 constexpr unsigned NumLoops = 1;
16669 Stmt *Body = nullptr;
16670 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
16671 NumLoops);
16672 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
16673 if (!checkTransformableLoopNest(Kind: OMPD_reverse, AStmt, NumLoops, LoopHelpers,
16674 Body, OriginalInits))
16675 return StmtError();
16676
16677 // Delay applying the transformation to when template is completely
16678 // instantiated.
16679 if (SemaRef.CurContext->isDependentContext())
16680 return OMPReverseDirective::Create(C: Context, StartLoc, EndLoc, AssociatedStmt: AStmt,
16681 NumLoops, TransformedStmt: nullptr, PreInits: nullptr);
16682
16683 assert(LoopHelpers.size() == NumLoops &&
16684 "Expecting a single-dimensional loop iteration space");
16685 assert(OriginalInits.size() == NumLoops &&
16686 "Expecting a single-dimensional loop iteration space");
16687 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
16688
16689 // Find the loop statement.
16690 Stmt *LoopStmt = nullptr;
16691 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
16692
16693 // Determine the PreInit declarations.
16694 SmallVector<Stmt *> PreInits;
16695 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
16696
16697 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
16698 QualType IVTy = IterationVarRef->getType();
16699 uint64_t IVWidth = Context.getTypeSize(T: IVTy);
16700 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
16701
16702 // Iteration variable SourceLocations.
16703 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
16704 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
16705 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
16706
16707 // Locations pointing to the transformation.
16708 SourceLocation TransformLoc = StartLoc;
16709 SourceLocation TransformLocBegin = StartLoc;
16710 SourceLocation TransformLocEnd = EndLoc;
16711
16712 // Internal variable names.
16713 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
16714 SmallString<64> ForwardIVName(".forward.iv.");
16715 ForwardIVName += OrigVarName;
16716 SmallString<64> ReversedIVName(".reversed.iv.");
16717 ReversedIVName += OrigVarName;
16718
16719 // LoopHelper.Updates will read the logical iteration number from
16720 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
16721 // that logical iteration from it, then assign it to the user loop counter
16722 // variable. We cannot directly use LoopHelper.IterationVarRef as the
16723 // induction variable of the generated loop because it may cause an underflow:
16724 // \code{.c}
16725 // for (unsigned i = 0; i < n; ++i)
16726 // body(i);
16727 // \endcode
16728 //
16729 // Naive reversal:
16730 // \code{.c}
16731 // for (unsigned i = n-1; i >= 0; --i)
16732 // body(i);
16733 // \endcode
16734 //
16735 // Instead, we introduce a new iteration variable representing the logical
16736 // iteration counter of the original loop, convert it to the logical iteration
16737 // number of the reversed loop, then let LoopHelper.Updates compute the user's
16738 // loop iteration variable from it.
16739 // \code{.cpp}
16740 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
16741 // auto .reversed.iv = n - .forward.iv - 1;
16742 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
16743 // body(i); // Body
16744 // }
16745 // \endcode
16746
16747 // Subexpressions with more than one use. One of the constraints of an AST is
16748 // that every node object must appear at most once, hence we define a lambda
16749 // that creates a new AST node at every use.
16750 CaptureVars CopyTransformer(SemaRef);
16751 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
16752 return AssertSuccess(
16753 R: CopyTransformer.TransformExpr(E: LoopHelper.NumIterations));
16754 };
16755
16756 // Create the iteration variable for the forward loop (from 0 to n-1).
16757 VarDecl *ForwardIVDecl =
16758 buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: ForwardIVName, Attrs: nullptr, OrigRef: OrigVar);
16759 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
16760 OrigVarLoc]() {
16761 return buildDeclRefExpr(S&: SemaRef, D: ForwardIVDecl, Ty: IVTy, Loc: OrigVarLoc);
16762 };
16763
16764 // Iteration variable for the reversed induction variable (from n-1 downto 0):
16765 // Reuse the iteration variable created by checkOpenMPLoop.
16766 auto *ReversedIVDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
16767 ReversedIVDecl->setDeclName(
16768 &SemaRef.PP.getIdentifierTable().get(Name: ReversedIVName));
16769
16770 // For init-statement:
16771 // \code{.cpp}
16772 // auto .forward.iv = 0;
16773 // \endcode
16774 auto *Zero = IntegerLiteral::Create(C: Context, V: llvm::APInt::getZero(numBits: IVWidth),
16775 type: ForwardIVDecl->getType(), l: OrigVarLoc);
16776 SemaRef.AddInitializerToDecl(dcl: ForwardIVDecl, init: Zero, /*DirectInit=*/false);
16777 StmtResult Init = new (Context)
16778 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
16779 if (!Init.isUsable())
16780 return StmtError();
16781
16782 // Forward iv cond-expression:
16783 // \code{.cpp}
16784 // .forward.iv < MakeNumIterations()
16785 // \endcode
16786 ExprResult Cond =
16787 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
16788 LHSExpr: MakeForwardRef(), RHSExpr: MakeNumIterations());
16789 if (!Cond.isUsable())
16790 return StmtError();
16791
16792 // Forward incr-statement:
16793 // \code{.c}
16794 // ++.forward.iv
16795 // \endcode
16796 ExprResult Incr = SemaRef.BuildUnaryOp(S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(),
16797 Opc: UO_PreInc, Input: MakeForwardRef());
16798 if (!Incr.isUsable())
16799 return StmtError();
16800
16801 // Reverse the forward-iv:
16802 // \code{.cpp}
16803 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
16804 // \endcode
16805 auto *One = IntegerLiteral::Create(C: Context, V: llvm::APInt(IVWidth, 1), type: IVTy,
16806 l: TransformLoc);
16807 ExprResult Minus = SemaRef.BuildBinOp(S: CurScope, OpLoc: TransformLoc, Opc: BO_Sub,
16808 LHSExpr: MakeNumIterations(), RHSExpr: One);
16809 if (!Minus.isUsable())
16810 return StmtError();
16811 Minus = SemaRef.BuildBinOp(S: CurScope, OpLoc: TransformLoc, Opc: BO_Sub, LHSExpr: Minus.get(),
16812 RHSExpr: MakeForwardRef());
16813 if (!Minus.isUsable())
16814 return StmtError();
16815 StmtResult InitReversed = new (Context) DeclStmt(
16816 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
16817 if (!InitReversed.isUsable())
16818 return StmtError();
16819 SemaRef.AddInitializerToDecl(dcl: ReversedIVDecl, init: Minus.get(),
16820 /*DirectInit=*/false);
16821
16822 // The new loop body.
16823 SmallVector<Stmt *, 4> BodyStmts;
16824 BodyStmts.reserve(N: LoopHelper.Updates.size() + 2 +
16825 (isa<CXXForRangeStmt>(Val: LoopStmt) ? 1 : 0));
16826 BodyStmts.push_back(Elt: InitReversed.get());
16827 llvm::append_range(C&: BodyStmts, R&: LoopHelper.Updates);
16828 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
16829 BodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
16830 BodyStmts.push_back(Elt: Body);
16831 auto *ReversedBody =
16832 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
16833 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
16834
16835 // Finally create the reversed For-statement.
16836 auto *ReversedFor = new (Context)
16837 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
16838 ReversedBody, LoopHelper.Init->getBeginLoc(),
16839 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16840 return OMPReverseDirective::Create(C: Context, StartLoc, EndLoc, AssociatedStmt: AStmt, NumLoops,
16841 TransformedStmt: ReversedFor,
16842 PreInits: buildPreInits(Context, PreInits));
16843}
16844
16845/// Build the AST for \#pragma omp split counts(c1, c2, ...).
16846///
16847/// Splits the single associated loop into N consecutive loops, where N is the
16848/// number of count expressions.
16849StmtResult SemaOpenMP::ActOnOpenMPSplitDirective(ArrayRef<OMPClause *> Clauses,
16850 Stmt *AStmt,
16851 SourceLocation StartLoc,
16852 SourceLocation EndLoc) {
16853 ASTContext &Context = getASTContext();
16854 Scope *CurScope = SemaRef.getCurScope();
16855
16856 // Empty statement should only be possible if there already was an error.
16857 if (!AStmt)
16858 return StmtError();
16859
16860 const auto *CountsClause =
16861 OMPExecutableDirective::getSingleClause<OMPCountsClause>(Clauses);
16862 if (!CountsClause)
16863 return StmtError();
16864
16865 // Split applies to a single loop; check it is transformable and get helpers.
16866 constexpr unsigned NumLoops = 1;
16867 Stmt *Body = nullptr;
16868 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
16869 NumLoops);
16870 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
16871 if (!checkTransformableLoopNest(Kind: OMPD_split, AStmt, NumLoops, LoopHelpers,
16872 Body, OriginalInits))
16873 return StmtError();
16874
16875 // Delay applying the transformation to when template is completely
16876 // instantiated.
16877 if (SemaRef.CurContext->isDependentContext())
16878 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16879 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16880
16881 assert(LoopHelpers.size() == NumLoops &&
16882 "Expecting a single-dimensional loop iteration space");
16883 assert(OriginalInits.size() == NumLoops &&
16884 "Expecting a single-dimensional loop iteration space");
16885 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
16886
16887 // Find the loop statement.
16888 Stmt *LoopStmt = nullptr;
16889 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
16890
16891 // Determine the PreInit declarations.
16892 SmallVector<Stmt *> PreInits;
16893 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
16894
16895 // Type and name of the original loop variable; we create one IV per segment
16896 // and assign it to the original var so the body sees the same name.
16897 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
16898 QualType IVTy = IterationVarRef->getType();
16899 uint64_t IVWidth = Context.getTypeSize(T: IVTy);
16900 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
16901
16902 // Iteration variable SourceLocations.
16903 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
16904 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
16905 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
16906 // Internal variable names.
16907 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
16908
16909 if (!CountsClause->hasOmpFill())
16910 return StmtError();
16911 unsigned FillIdx = *CountsClause->getOmpFillIndex();
16912
16913 unsigned NumItems = CountsClause->getNumCounts();
16914 SmallVector<uint64_t, 4> CountValues(NumItems, 0);
16915 ArrayRef<Expr *> Refs = CountsClause->getCountsRefs();
16916 for (unsigned I = 0; I < NumItems; ++I) {
16917 if (I == FillIdx)
16918 continue;
16919 Expr *CountExpr = Refs[I];
16920 if (!CountExpr)
16921 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16922 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16923 std::optional<llvm::APSInt> OptVal =
16924 CountExpr->getIntegerConstantExpr(Ctx: Context);
16925 if (!OptVal || OptVal->isNegative())
16926 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16927 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16928 CountValues[I] = OptVal->getLimitedValue();
16929 }
16930
16931 Expr *NumIterExpr = LoopHelper.NumIterations;
16932
16933 uint64_t RightSum = 0;
16934 for (unsigned I = FillIdx + 1; I < NumItems; ++I)
16935 RightSum += CountValues[I];
16936
16937 auto MakeIntLit = [&](uint64_t Val) {
16938 return IntegerLiteral::Create(C: Context, V: llvm::APInt(IVWidth, Val), type: IVTy,
16939 l: OrigVarLoc);
16940 };
16941
16942 size_t NumSegments = NumItems;
16943 SmallVector<Stmt *, 4> SplitLoops;
16944
16945 auto *IterVarDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
16946 SplitLoops.push_back(Elt: new (Context) DeclStmt(DeclGroupRef(IterVarDecl),
16947 IterationVarRef->getBeginLoc(),
16948 IterationVarRef->getEndLoc()));
16949
16950 uint64_t LeftAccum = 0;
16951 uint64_t RightRemaining = RightSum;
16952
16953 for (size_t Seg = 0; Seg < NumSegments; ++Seg) {
16954 Expr *StartExpr = nullptr;
16955 Expr *EndExpr = nullptr;
16956
16957 if (Seg < FillIdx) {
16958 StartExpr = MakeIntLit(LeftAccum);
16959 LeftAccum += CountValues[Seg];
16960 EndExpr = MakeIntLit(LeftAccum);
16961 } else if (Seg == FillIdx) {
16962 StartExpr = MakeIntLit(LeftAccum);
16963 if (RightRemaining == 0) {
16964 EndExpr = NumIterExpr;
16965 } else {
16966 ExprResult Sub =
16967 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16968 RHSExpr: MakeIntLit(RightRemaining));
16969 if (!Sub.isUsable())
16970 return StmtError();
16971 EndExpr = Sub.get();
16972 }
16973 } else {
16974 if (RightRemaining == RightSum) {
16975 if (RightSum == 0)
16976 StartExpr = NumIterExpr;
16977 else {
16978 ExprResult Sub =
16979 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16980 RHSExpr: MakeIntLit(RightRemaining));
16981 if (!Sub.isUsable())
16982 return StmtError();
16983 StartExpr = Sub.get();
16984 }
16985 } else {
16986 ExprResult Sub =
16987 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16988 RHSExpr: MakeIntLit(RightRemaining));
16989 if (!Sub.isUsable())
16990 return StmtError();
16991 StartExpr = Sub.get();
16992 }
16993 RightRemaining -= CountValues[Seg];
16994 if (RightRemaining == 0)
16995 EndExpr = NumIterExpr;
16996 else {
16997 ExprResult Sub =
16998 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16999 RHSExpr: MakeIntLit(RightRemaining));
17000 if (!Sub.isUsable())
17001 return StmtError();
17002 EndExpr = Sub.get();
17003 }
17004 }
17005
17006 SmallString<64> IVName(".split.iv.");
17007 IVName += (Twine(Seg) + "." + OrigVarName).str();
17008 VarDecl *IVDecl = buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: IVName, Attrs: nullptr, OrigRef: OrigVar);
17009 auto MakeIVRef = [&SemaRef = this->SemaRef, IVDecl, IVTy, OrigVarLoc]() {
17010 return buildDeclRefExpr(S&: SemaRef, D: IVDecl, Ty: IVTy, Loc: OrigVarLoc);
17011 };
17012
17013 SemaRef.AddInitializerToDecl(dcl: IVDecl, init: StartExpr, /*DirectInit=*/false);
17014 StmtResult InitStmt = new (Context)
17015 DeclStmt(DeclGroupRef(IVDecl), OrigVarLocBegin, OrigVarLocEnd);
17016 if (!InitStmt.isUsable())
17017 return StmtError();
17018
17019 ExprResult CondExpr = SemaRef.BuildBinOp(
17020 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT, LHSExpr: MakeIVRef(), RHSExpr: EndExpr);
17021 if (!CondExpr.isUsable())
17022 return StmtError();
17023
17024 ExprResult IncrExpr = SemaRef.BuildUnaryOp(
17025 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeIVRef());
17026 if (!IncrExpr.isUsable())
17027 return StmtError();
17028
17029 ExprResult IVAssign = SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Assign,
17030 LHSExpr: IterationVarRef, RHSExpr: MakeIVRef());
17031 if (!IVAssign.isUsable())
17032 return StmtError();
17033
17034 SmallVector<Stmt *, 4> BodyStmts;
17035 BodyStmts.push_back(Elt: IVAssign.get());
17036 BodyStmts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
17037 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt)) {
17038 if (Seg == 0) {
17039 BodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
17040 } else {
17041 VarDecl *LoopVar = CXXRangeFor->getLoopVariable();
17042 DeclRefExpr *LVRef = buildDeclRefExpr(
17043 S&: SemaRef, D: LoopVar, Ty: LoopVar->getType().getNonReferenceType(),
17044 Loc: OrigVarLoc);
17045 ExprResult LVAssign = SemaRef.BuildBinOp(
17046 S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Assign, LHSExpr: LVRef, RHSExpr: LoopVar->getInit());
17047 if (!LVAssign.isUsable())
17048 return StmtError();
17049 BodyStmts.push_back(Elt: LVAssign.get());
17050 }
17051 }
17052 BodyStmts.push_back(Elt: Body);
17053
17054 auto *LoopBody =
17055 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
17056 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
17057
17058 auto *For = new (Context)
17059 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
17060 IncrExpr.get(), LoopBody, LoopHelper.Init->getBeginLoc(),
17061 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
17062 SplitLoops.push_back(Elt: For);
17063 }
17064
17065 auto *SplitStmt = CompoundStmt::Create(
17066 C: Context, Stmts: SplitLoops, FPFeatures: FPOptionsOverride(),
17067 LB: SplitLoops.front()->getBeginLoc(), RB: SplitLoops.back()->getEndLoc());
17068
17069 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses, NumLoops,
17070 AssociatedStmt: AStmt, TransformedStmt: SplitStmt,
17071 PreInits: buildPreInits(Context, PreInits));
17072}
17073
17074StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
17075 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
17076 SourceLocation EndLoc) {
17077 ASTContext &Context = getASTContext();
17078 DeclContext *CurContext = SemaRef.CurContext;
17079 Scope *CurScope = SemaRef.getCurScope();
17080
17081 // Empty statement should only be possible if there already was an error.
17082 if (!AStmt)
17083 return StmtError();
17084
17085 // interchange without permutation clause swaps two loops.
17086 const OMPPermutationClause *PermutationClause =
17087 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
17088 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
17089
17090 // Verify and diagnose loop nest.
17091 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
17092 Stmt *Body = nullptr;
17093 SmallVector<SmallVector<Stmt *>, 2> OriginalInits;
17094 if (!checkTransformableLoopNest(Kind: OMPD_interchange, AStmt, NumLoops,
17095 LoopHelpers, Body, OriginalInits))
17096 return StmtError();
17097
17098 // Delay interchange to when template is completely instantiated.
17099 if (CurContext->isDependentContext())
17100 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
17101 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
17102
17103 // An invalid expression in the permutation clause is set to nullptr in
17104 // ActOnOpenMPPermutationClause.
17105 if (PermutationClause &&
17106 llvm::is_contained(Range: PermutationClause->getArgsRefs(), Element: nullptr))
17107 return StmtError();
17108
17109 assert(LoopHelpers.size() == NumLoops &&
17110 "Expecting loop iteration space dimensionaly to match number of "
17111 "affected loops");
17112 assert(OriginalInits.size() == NumLoops &&
17113 "Expecting loop iteration space dimensionaly to match number of "
17114 "affected loops");
17115
17116 // Decode the permutation clause.
17117 SmallVector<uint64_t, 2> Permutation;
17118 if (!PermutationClause) {
17119 Permutation = {1, 0};
17120 } else {
17121 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
17122 llvm::BitVector Flags(PermArgs.size());
17123 for (Expr *PermArg : PermArgs) {
17124 std::optional<llvm::APSInt> PermCstExpr =
17125 PermArg->getIntegerConstantExpr(Ctx: Context);
17126 if (!PermCstExpr)
17127 continue;
17128 uint64_t PermInt = PermCstExpr->getLimitedValue();
17129 assert(1 <= PermInt && PermInt <= NumLoops &&
17130 "Must be a permutation; diagnostic emitted in "
17131 "ActOnOpenMPPermutationClause");
17132 if (Flags[PermInt - 1]) {
17133 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
17134 Diag(Loc: PermArg->getExprLoc(),
17135 DiagID: diag::err_omp_interchange_permutation_value_repeated)
17136 << PermInt << ExprRange;
17137 continue;
17138 }
17139 Flags[PermInt - 1] = true;
17140
17141 Permutation.push_back(Elt: PermInt - 1);
17142 }
17143
17144 if (Permutation.size() != NumLoops)
17145 return StmtError();
17146 }
17147
17148 // Nothing to transform with trivial permutation.
17149 if (NumLoops <= 1 || llvm::all_of(Range: llvm::enumerate(First&: Permutation), P: [](auto P) {
17150 auto [Idx, Arg] = P;
17151 return Idx == Arg;
17152 }))
17153 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
17154 NumLoops, AssociatedStmt: AStmt, TransformedStmt: AStmt, PreInits: nullptr);
17155
17156 // Find the affected loops.
17157 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
17158 collectLoopStmts(AStmt, LoopStmts);
17159
17160 // Collect pre-init statements on the order before the permuation.
17161 SmallVector<Stmt *> PreInits;
17162 for (auto I : llvm::seq<int>(Size: NumLoops)) {
17163 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
17164
17165 assert(LoopHelper.Counters.size() == 1 &&
17166 "Single-dimensional loop iteration space expected");
17167
17168 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
17169 PreInits);
17170 }
17171
17172 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
17173 CaptureVars CopyTransformer(SemaRef);
17174
17175 // Create the permuted loops from the inside to the outside of the
17176 // interchanged loop nest. Body of the innermost new loop is the original
17177 // innermost body.
17178 Stmt *Inner = Body;
17179 for (auto TargetIdx : llvm::reverse(C: llvm::seq<int>(Size: NumLoops))) {
17180 // Get the original loop that belongs to this new position.
17181 uint64_t SourceIdx = Permutation[TargetIdx];
17182 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
17183 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
17184 assert(SourceHelper.Counters.size() == 1 &&
17185 "Single-dimensional loop iteration space expected");
17186 auto *OrigCntVar = cast<DeclRefExpr>(Val: SourceHelper.Counters.front());
17187
17188 // Normalized loop counter variable: From 0 to n-1, always an integer type.
17189 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: SourceHelper.IterationVarRef);
17190 QualType IVTy = IterVarRef->getType();
17191 assert(IVTy->isIntegerType() &&
17192 "Expected the logical iteration counter to be an integer");
17193
17194 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
17195 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
17196
17197 // Make a copy of the NumIterations expression for each use: By the AST
17198 // constraints, every expression object in a DeclContext must be unique.
17199 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
17200 return AssertSuccess(
17201 R: CopyTransformer.TransformExpr(E: SourceHelper.NumIterations));
17202 };
17203
17204 // Iteration variable for the permuted loop. Reuse the one from
17205 // checkOpenMPLoop which will also be used to update the original loop
17206 // variable.
17207 SmallString<64> PermutedCntName(".permuted_");
17208 PermutedCntName.append(Refs: {llvm::utostr(X: TargetIdx), ".iv.", OrigVarName});
17209 auto *PermutedCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
17210 PermutedCntDecl->setDeclName(
17211 &SemaRef.PP.getIdentifierTable().get(Name: PermutedCntName));
17212 PermutedIndVars[TargetIdx] = PermutedCntDecl;
17213 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
17214 return buildDeclRefExpr(S&: SemaRef, D: PermutedCntDecl, Ty: IVTy, Loc: OrigVarLoc);
17215 };
17216
17217 // For init-statement:
17218 // \code
17219 // auto .permuted_{target}.iv = 0
17220 // \endcode
17221 ExprResult Zero = SemaRef.ActOnIntegerConstant(Loc: OrigVarLoc, Val: 0);
17222 if (!Zero.isUsable())
17223 return StmtError();
17224 SemaRef.AddInitializerToDecl(dcl: PermutedCntDecl, init: Zero.get(),
17225 /*DirectInit=*/false);
17226 StmtResult InitStmt = new (Context)
17227 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
17228 OrigCntVar->getEndLoc());
17229 if (!InitStmt.isUsable())
17230 return StmtError();
17231
17232 // For cond-expression:
17233 // \code
17234 // .permuted_{target}.iv < MakeNumIterations()
17235 // \endcode
17236 ExprResult CondExpr =
17237 SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceHelper.Cond->getExprLoc(), Opc: BO_LT,
17238 LHSExpr: MakePermutedRef(), RHSExpr: MakeNumIterations());
17239 if (!CondExpr.isUsable())
17240 return StmtError();
17241
17242 // For incr-statement:
17243 // \code
17244 // ++.tile.iv
17245 // \endcode
17246 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
17247 S: CurScope, OpLoc: SourceHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakePermutedRef());
17248 if (!IncrStmt.isUsable())
17249 return StmtError();
17250
17251 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
17252 SourceHelper.Updates.end());
17253 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: SourceLoopStmt))
17254 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
17255 BodyParts.push_back(Elt: Inner);
17256 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
17257 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
17258 Inner = new (Context) ForStmt(
17259 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
17260 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
17261 SourceHelper.Inc->getEndLoc());
17262 }
17263
17264 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
17265 NumLoops, AssociatedStmt: AStmt, TransformedStmt: Inner,
17266 PreInits: buildPreInits(Context, PreInits));
17267}
17268
17269StmtResult
17270SemaOpenMP::ActOnOpenMPFlattenDirective(ArrayRef<OMPClause *> Clauses,
17271 Stmt *AStmt, SourceLocation StartLoc,
17272 SourceLocation EndLoc) {
17273 ASTContext &Context = getASTContext();
17274 DeclContext *CurContext = SemaRef.CurContext;
17275 Scope *CurScope = SemaRef.getCurScope();
17276
17277 // Empty statement should only be possible if there already was an error.
17278 if (!AStmt)
17279 return StmtError();
17280
17281 // flatten without 'depth' clause combines two loops; 'depth(k)' selects k.
17282 unsigned NumLoops = 2;
17283 bool DepthIsDependent = false;
17284 const auto *DepthClause =
17285 OMPExecutableDirective::getSingleClause<OMPDepthClause>(Clauses);
17286 if (DepthClause) {
17287 Expr *DepthExpr = DepthClause->getDepth();
17288 if (DepthExpr && DepthExpr->isInstantiationDependent()) {
17289 DepthIsDependent = true;
17290 } else if (DepthExpr) {
17291 Expr::EvalResult EvalResult;
17292 if (DepthExpr->EvaluateAsInt(Result&: EvalResult, Ctx: Context))
17293 NumLoops = EvalResult.Val.getInt().getLimitedValue(
17294 Limit: std::numeric_limits<unsigned>::max());
17295 }
17296 }
17297
17298 // Count perfectly nested loops with doForAllLoops. When 'depth' is present,
17299 // walk NumLoops iterations to diagnose an insufficient nest. When it is
17300 // omitted, walk one extra loop (3 total) so we can warn that default
17301 // flatten only combines 2 of a deeper nest.
17302 if (!DepthIsDependent) {
17303 unsigned WalkLimit = DepthClause ? NumLoops : 3;
17304 unsigned Found = 0;
17305 bool Enough = OMPLoopBasedDirective::doForAllLoops(
17306 CurStmt: AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false,
17307 NumLoops: WalkLimit, Callback: [&](unsigned Cnt, Stmt *S) {
17308 if (!isa<ForStmt>(Val: S) && !isa<CXXForRangeStmt>(Val: S))
17309 return true;
17310 Found = Cnt + 1;
17311 return false;
17312 });
17313 if (DepthClause && !Enough) {
17314 Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_not_for)
17315 << /*expected N for loops form=*/1
17316 << getOpenMPDirectiveName(D: OMPD_flatten) << NumLoops << (Found > 0)
17317 << Found;
17318 return StmtError();
17319 }
17320 if (!DepthClause && Found >= 3) {
17321 Diag(Loc: StartLoc, DiagID: diag::warn_omp_flatten_omitted_depth);
17322 if (SemaRef.getLangOpts().OpenMP >= 61)
17323 Diag(Loc: StartLoc, DiagID: diag::note_omp_flatten_insert_depth)
17324 << FixItHint::CreateInsertion(InsertionLoc: EndLoc, Code: " depth(2)");
17325 }
17326 }
17327
17328 // Defer when 'depth' is instantiation-dependent (concrete k unknown until
17329 // instantiation).
17330 if (DepthIsDependent)
17331 return OMPFlattenDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
17332 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr,
17333 Finals: nullptr);
17334
17335 // Verify and diagnose loop nest.
17336 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
17337 Stmt *Body = nullptr;
17338 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
17339 if (!checkTransformableLoopNest(Kind: OMPD_flatten, AStmt, NumLoops, LoopHelpers,
17340 Body, OriginalInits))
17341 return StmtError();
17342
17343 // Delay flattening to when template is completely instantiated.
17344 if (CurContext->isDependentContext())
17345 return OMPFlattenDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
17346 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr,
17347 Finals: nullptr);
17348
17349 assert(LoopHelpers.size() == NumLoops &&
17350 "Expecting loop iteration space dimensionality to match number of "
17351 "affected loops");
17352 assert(OriginalInits.size() == NumLoops &&
17353 "Expecting loop iteration space dimensionality to match number of "
17354 "affected loops");
17355
17356 // Find the affected loops.
17357 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
17358 collectLoopStmts(AStmt, LoopStmts);
17359
17360 // Collect pre-init statements in outer-to-inner order.
17361 SmallVector<Stmt *> PreInits;
17362 for (auto I : llvm::seq<unsigned>(Size: NumLoops)) {
17363 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
17364 assert(LoopHelper.Counters.size() == 1 &&
17365 "Single-dimensional loop iteration space expected");
17366 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
17367 PreInits);
17368 }
17369
17370 CaptureVars CopyTransformer(SemaRef);
17371 auto MakeNumIterations = [&CopyTransformer,
17372 &LoopHelpers](unsigned I) -> Expr * {
17373 return AssertSuccess(
17374 R: CopyTransformer.TransformExpr(E: LoopHelpers[I].NumIterations));
17375 };
17376
17377 OMPLoopBasedDirective::HelperExprs &OutermostHelper = LoopHelpers[0];
17378 auto *OutermostCntVar = cast<DeclRefExpr>(Val: OutermostHelper.Counters.front());
17379 SourceLocation OrigVarLoc = OutermostCntVar->getExprLoc();
17380 SourceLocation OrigVarLocBegin = OutermostCntVar->getBeginLoc();
17381 SourceLocation OrigVarLocEnd = OutermostCntVar->getEndLoc();
17382 SourceLocation CondLoc = OutermostHelper.Cond->getExprLoc();
17383
17384 // Product of trip counts; mirror 'collapse' IV-width selection to avoid
17385 // overflow when several counts are multiplied.
17386 auto BuildTripCount = [&](unsigned Bits) -> ExprResult {
17387 ExprResult Product;
17388 for (unsigned I = 0; I < NumLoops; ++I) {
17389 ExprResult N = widenIterationCount(Bits, E: MakeNumIterations(I), SemaRef);
17390 if (!N.isUsable())
17391 return ExprError();
17392 if (I == 0)
17393 Product = N;
17394 else
17395 Product = SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_Mul, LHSExpr: Product.get(),
17396 RHSExpr: N.get());
17397 if (!Product.isUsable())
17398 return ExprError();
17399 }
17400 return Product;
17401 };
17402
17403 bool AllCountsLessThan32Bits =
17404 llvm::all_of(Range: llvm::seq<unsigned>(Size: NumLoops), P: [&](unsigned I) {
17405 return Context.getTypeSize(T: LoopHelpers[I].NumIterations->getType()) <
17406 32;
17407 });
17408
17409 ExprResult TripCount;
17410 if (AllCountsLessThan32Bits || NumLoops == 1) {
17411 TripCount = BuildTripCount(/*Bits=*/32);
17412 } else {
17413 ExprResult TripCount64 = BuildTripCount(/*Bits=*/64);
17414 if (!TripCount64.isUsable())
17415 return StmtError();
17416 TripCount = TripCount64;
17417 if (TripCount64.get()->isIntegerConstantExpr(Ctx: Context)) {
17418 ExprResult TripCount32 = BuildTripCount(/*Bits=*/32);
17419 if (TripCount32.isUsable() &&
17420 Context.getTypeSize(T: TripCount32.get()->getType()) == 32 &&
17421 fitsInto(
17422 /*Bits=*/32,
17423 Signed: TripCount32.get()->getType()->hasSignedIntegerRepresentation(),
17424 E: TripCount64.get(), SemaRef))
17425 TripCount = TripCount32;
17426 }
17427 }
17428 if (!TripCount.isUsable())
17429 return StmtError();
17430
17431 QualType IVTy = TripCount.get()->getType();
17432 uint64_t IVWidth = Context.getTypeSize(T: IVTy);
17433
17434 // Build a condition that is true if the outermost \p Count loops all have at
17435 // least one iteration.
17436 auto BuildHasIterations = [&](unsigned Count) -> ExprResult {
17437 ExprResult Result;
17438 for (unsigned I = 0; I < Count; ++I) {
17439 ExprResult LoopPreCond =
17440 CopyTransformer.TransformExpr(E: LoopHelpers[I].PreCond);
17441 if (!LoopPreCond.isUsable())
17442 return ExprError();
17443 if (I == 0)
17444 Result = LoopPreCond;
17445 else
17446 Result = SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LAnd, LHSExpr: Result.get(),
17447 RHSExpr: LoopPreCond.get());
17448 if (!Result.isUsable())
17449 return ExprError();
17450 }
17451 return Result;
17452 };
17453
17454 // NumIterations may wrap or overflow when an empty loop has extreme runtime
17455 // bounds. Test whether every original loop has at least one iteration before
17456 // evaluating their product.
17457 ExprResult HasIterations = BuildHasIterations(NumLoops);
17458 if (!HasIterations.isUsable())
17459 return StmtError();
17460 Expr *ZeroTripCount = IntegerLiteral::Create(
17461 C: Context, V: llvm::APInt::getZero(numBits: IVWidth), type: IVTy, l: CondLoc);
17462 TripCount = SemaRef.ActOnConditionalOp(QuestionLoc: CondLoc, ColonLoc: CondLoc, CondExpr: HasIterations.get(),
17463 LHSExpr: TripCount.get(), RHSExpr: ZeroTripCount);
17464 if (!TripCount.isUsable())
17465 return StmtError();
17466
17467 auto MakeNumIterationsInIVTy = [&](unsigned I) -> Expr * {
17468 return AssertSuccess(R: SemaRef.PerformImplicitConversion(
17469 From: MakeNumIterations(I), ToType: IVTy, Action: AssignmentAction::Converting,
17470 /*AllowExplicit=*/true));
17471 };
17472
17473 // Divisors in index recovery use (N == 0 ? 1 : N) so a zero trip count does
17474 // not warn.
17475 auto MakeDivisorInIVTy = [&](unsigned I) -> Expr * {
17476 Expr *N = MakeNumIterationsInIVTy(I);
17477 Expr *NCmp = MakeNumIterationsInIVTy(I);
17478 auto MakeCst = [&](uint64_t V) -> Expr * {
17479 return IntegerLiteral::Create(C: Context, V: llvm::APInt(IVWidth, V), type: IVTy,
17480 l: CondLoc);
17481 };
17482 ExprResult IsZero =
17483 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_EQ, LHSExpr: NCmp, RHSExpr: MakeCst(0));
17484 if (!IsZero.isUsable())
17485 return N;
17486 return AssertSuccess(R: SemaRef.ActOnConditionalOp(
17487 QuestionLoc: CondLoc, ColonLoc: CondLoc, CondExpr: IsZero.get(), LHSExpr: MakeCst(1), RHSExpr: N));
17488 };
17489
17490 // \code{.cpp}
17491 // for (auto .flatten.iv = 0; .flatten.iv < n0 * n1 * ...; ++.flatten.iv) {
17492 // .flatten.iv.0 = .flatten.iv / (n1 * ...);
17493 // i0 = ...; // Updates[0]
17494 // .flatten.iv.1 = (.flatten.iv / ...) % n1;
17495 // i1 = ...; // Updates[1]
17496 // ...
17497 // body(i0, i1, ...);
17498 // }
17499 // \endcode
17500 SmallString<64> FlattenedIVName(".flatten.iv");
17501 VarDecl *FlattenedIVDecl = buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: FlattenedIVName,
17502 Attrs: nullptr, OrigRef: OutermostCntVar);
17503 auto MakeFlattenedRef = [&SemaRef = this->SemaRef, FlattenedIVDecl, IVTy,
17504 OrigVarLoc]() {
17505 return buildDeclRefExpr(S&: SemaRef, D: FlattenedIVDecl, Ty: IVTy, Loc: OrigVarLoc);
17506 };
17507
17508 // For init-statement:
17509 // \code{.cpp}
17510 // auto .flatten.iv = 0;
17511 // \endcode
17512 auto *Zero = IntegerLiteral::Create(C: Context, V: llvm::APInt::getZero(numBits: IVWidth),
17513 type: IVTy, l: OrigVarLoc);
17514 SemaRef.AddInitializerToDecl(dcl: FlattenedIVDecl, init: Zero, /*DirectInit=*/false);
17515 StmtResult Init = new (Context)
17516 DeclStmt(DeclGroupRef(FlattenedIVDecl), OrigVarLocBegin, OrigVarLocEnd);
17517 if (!Init.isUsable())
17518 return StmtError();
17519
17520 // For cond-expression:
17521 // \code{.cpp}
17522 // .flatten.iv < n0 * n1 * ... * n(k-1)
17523 // \endcode
17524 ExprResult Cond = SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LT,
17525 LHSExpr: MakeFlattenedRef(), RHSExpr: TripCount.get());
17526 if (!Cond.isUsable())
17527 return StmtError();
17528
17529 // For incr-statement:
17530 // \code{.cpp}
17531 // ++.flatten.iv
17532 // \endcode
17533 ExprResult Incr =
17534 SemaRef.BuildUnaryOp(S: CurScope, OpLoc: OutermostHelper.Inc->getExprLoc(),
17535 Opc: UO_PreInc, Input: MakeFlattenedRef());
17536 if (!Incr.isUsable())
17537 return StmtError();
17538
17539 // Recover each logical iteration counter via mixed-radix div/mod; reuse the
17540 // iteration variables from checkOpenMPLoop so Updates compute user counters.
17541 SmallVector<Stmt *, 8> BodyStmts;
17542 for (unsigned I = 0; I < NumLoops; ++I) {
17543 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
17544 auto *IVRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
17545 auto *IVDecl = cast<VarDecl>(Val: IVRef->getDecl());
17546 std::string IVName = (".flatten.iv." + llvm::Twine(I)).str();
17547 IVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name: IVName));
17548
17549 ExprResult Value = MakeFlattenedRef();
17550 if (I + 1 < NumLoops) {
17551 ExprResult Divisor = MakeDivisorInIVTy(I + 1);
17552 for (unsigned J = I + 2; J < NumLoops; ++J) {
17553 Divisor = SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Mul,
17554 LHSExpr: Divisor.get(), RHSExpr: MakeDivisorInIVTy(J));
17555 if (!Divisor.isUsable())
17556 return StmtError();
17557 }
17558 Value = SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Div, LHSExpr: Value.get(),
17559 RHSExpr: Divisor.get());
17560 if (!Value.isUsable())
17561 return StmtError();
17562 }
17563 if (I > 0) {
17564 Value = SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Rem, LHSExpr: Value.get(),
17565 RHSExpr: MakeDivisorInIVTy(I));
17566 if (!Value.isUsable())
17567 return StmtError();
17568 }
17569
17570 SemaRef.AddInitializerToDecl(dcl: IVDecl, init: Value.get(), /*DirectInit=*/false);
17571 StmtResult IVStmt = new (Context)
17572 DeclStmt(DeclGroupRef(IVDecl), OrigVarLocBegin, OrigVarLocEnd);
17573 if (!IVStmt.isUsable())
17574 return StmtError();
17575
17576 BodyStmts.push_back(Elt: IVStmt.get());
17577 llvm::append_range(C&: BodyStmts, R&: LoopHelper.Updates);
17578 if (auto *CXXFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmts[I]))
17579 BodyStmts.push_back(Elt: CXXFor->getLoopVarStmt());
17580 }
17581 BodyStmts.push_back(Elt: Body);
17582 auto *FlattenedBody =
17583 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
17584 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
17585
17586 auto *FlattenedFor = new (Context) ForStmt(
17587 Context, Init.get(), Cond.get(), nullptr, Incr.get(), FlattenedBody,
17588 OutermostHelper.Init->getBeginLoc(), OutermostHelper.Init->getBeginLoc(),
17589 OutermostHelper.Inc->getEndLoc());
17590
17591 // A counter only reaches its final value if its own loop and all enclosing
17592 // loops execute at least one iteration; otherwise it keeps the value assigned
17593 // by the pre-inits. Guarding also avoids evaluating 'start + n * step' for an
17594 // empty loop, whose trip count may have wrapped.
17595 SmallVector<Stmt *, 4> Finals;
17596 for (unsigned I = 0; I < NumLoops; ++I) {
17597 assert(LoopHelpers[I].Finals.size() == 1 &&
17598 "Single-dimensional loop iteration space expected");
17599 ExprResult Final =
17600 CopyTransformer.TransformExpr(E: LoopHelpers[I].Finals.front());
17601 if (!Final.isUsable())
17602 return StmtError();
17603 ExprResult FinalCond = BuildHasIterations(/*Count=*/I + 1);
17604 if (!FinalCond.isUsable())
17605 return StmtError();
17606 Finals.push_back(Elt: IfStmt::Create(Ctx: Context, IL: CondLoc, Kind: IfStatementKind::Ordinary,
17607 Init: nullptr, Var: nullptr, Cond: FinalCond.get(), LPL: CondLoc,
17608 RPL: CondLoc, Then: Final.get(), EL: SourceLocation(),
17609 Else: nullptr));
17610 }
17611 Stmt *FinalsStmt = CompoundStmt::Create(C: Context, Stmts: Finals, FPFeatures: FPOptionsOverride(),
17612 LB: FlattenedFor->getBeginLoc(),
17613 RB: FlattenedFor->getEndLoc());
17614
17615 return OMPFlattenDirective::Create(
17616 C: Context, StartLoc, EndLoc, Clauses, NumLoops, AssociatedStmt: AStmt, TransformedStmt: FlattenedFor,
17617 PreInits: buildPreInits(Context, PreInits), Finals: FinalsStmt);
17618}
17619
17620StmtResult SemaOpenMP::ActOnOpenMPFuseDirective(ArrayRef<OMPClause *> Clauses,
17621 Stmt *AStmt,
17622 SourceLocation StartLoc,
17623 SourceLocation EndLoc) {
17624
17625 ASTContext &Context = getASTContext();
17626 DeclContext *CurrContext = SemaRef.CurContext;
17627 Scope *CurScope = SemaRef.getCurScope();
17628 CaptureVars CopyTransformer(SemaRef);
17629
17630 // Ensure the structured block is not empty
17631 if (!AStmt)
17632 return StmtError();
17633
17634 if (const auto *DepthC =
17635 OMPExecutableDirective::getSingleClause<OMPDepthClause>(Clauses)) {
17636 Diag(Loc: DepthC->getBeginLoc(), DiagID: diag::err_omp_clause_not_supported_yet)
17637 << "depth" << getOpenMPDirectiveName(D: OMPD_fuse);
17638 return StmtError();
17639 }
17640
17641 // Defer transformation in dependent contexts
17642 // The NumLoopNests argument is set to a placeholder 1 (even though
17643 // using looprange fuse could yield up to 3 top level loop nests)
17644 // because a dependent context could prevent determining its true value
17645 if (CurrContext->isDependentContext())
17646 return OMPFuseDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
17647 /* NumLoops */ NumGeneratedTopLevelLoops: 1, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
17648
17649 // Validate that the potential loop sequence is transformable for fusion
17650 // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops
17651 LoopSequenceAnalysis SeqAnalysis;
17652 if (!checkTransformableLoopSequence(Kind: OMPD_fuse, AStmt, SeqAnalysis, Context))
17653 return StmtError();
17654
17655 // SeqAnalysis.LoopSeqSize exists mostly to handle dependent contexts,
17656 // otherwise it must be the same as SeqAnalysis.Loops.size().
17657 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
17658 "Inconsistent size of the loop sequence and the number of loops "
17659 "found in the sequence");
17660
17661 // Handle clauses, which can be any of the following: [looprange, apply]
17662 const auto *LRC =
17663 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
17664
17665 // The clause arguments are invalidated if any error arises
17666 // such as non-constant or non-positive arguments
17667 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
17668 return StmtError();
17669
17670 // Delayed semantic check of LoopRange constraint
17671 // Evaluates the loop range arguments and returns the first and count values
17672 auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count,
17673 uint64_t &FirstVal,
17674 uint64_t &CountVal) {
17675 llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Ctx: Context);
17676 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Ctx: Context);
17677 FirstVal = FirstInt.getLimitedValue();
17678 CountVal = CountInt.getLimitedValue();
17679 };
17680
17681 // OpenMP [6.0, Restrictions]
17682 // first + count - 1 must not evaluate to a value greater than the
17683 // loop sequence length of the associated canonical loop sequence.
17684 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
17685 unsigned NumLoops) -> bool {
17686 return FirstVal + CountVal - 1 <= NumLoops;
17687 };
17688 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
17689
17690 // Validates the loop range after evaluating the semantic information
17691 // and ensures that the range is valid for the given loop sequence size.
17692 // Expressions are evaluated at compile time to obtain constant values.
17693 if (LRC) {
17694 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
17695 CountVal);
17696 if (CountVal == 1)
17697 SemaRef.Diag(Loc: LRC->getCountLoc(), DiagID: diag::warn_omp_redundant_fusion)
17698 << getOpenMPDirectiveName(D: OMPD_fuse);
17699
17700 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
17701 SemaRef.Diag(Loc: LRC->getFirstLoc(), DiagID: diag::err_omp_invalid_looprange)
17702 << getOpenMPDirectiveName(D: OMPD_fuse) << FirstVal
17703 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
17704 return StmtError();
17705 }
17706
17707 LastVal = FirstVal + CountVal - 1;
17708 }
17709
17710 // Complete fusion generates a single canonical loop nest
17711 // However looprange clause may generate several loop nests
17712 unsigned NumGeneratedTopLevelLoops =
17713 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
17714
17715 // Emit a warning for redundant loop fusion when the sequence contains only
17716 // one loop.
17717 if (SeqAnalysis.LoopSeqSize == 1)
17718 SemaRef.Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::warn_omp_redundant_fusion)
17719 << getOpenMPDirectiveName(D: OMPD_fuse);
17720
17721 // Select the type with the largest bit width among all induction variables
17722 QualType IVType =
17723 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
17724 for (unsigned I : llvm::seq<unsigned>(Begin: FirstVal, End: LastVal)) {
17725 QualType CurrentIVType =
17726 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
17727 if (Context.getTypeSize(T: CurrentIVType) > Context.getTypeSize(T: IVType)) {
17728 IVType = CurrentIVType;
17729 }
17730 }
17731 uint64_t IVBitWidth = Context.getIntWidth(T: IVType);
17732
17733 // Create pre-init declarations for all loops lower bounds, upper bounds,
17734 // strides and num-iterations for every top level loop in the fusion
17735 SmallVector<VarDecl *, 4> LBVarDecls;
17736 SmallVector<VarDecl *, 4> STVarDecls;
17737 SmallVector<VarDecl *, 4> NIVarDecls;
17738 SmallVector<VarDecl *, 4> UBVarDecls;
17739 SmallVector<VarDecl *, 4> IVVarDecls;
17740
17741 // Helper lambda to create variables for bounds, strides, and other
17742 // expressions. Generates both the variable declaration and the corresponding
17743 // initialization statement.
17744 auto CreateHelperVarAndStmt =
17745 [&, &SemaRef = SemaRef](Expr *ExprToCopy, const std::string &BaseName,
17746 unsigned I, bool NeedsNewVD = false) {
17747 Expr *TransformedExpr =
17748 AssertSuccess(R: CopyTransformer.TransformExpr(E: ExprToCopy));
17749 if (!TransformedExpr)
17750 return std::pair<VarDecl *, StmtResult>(nullptr, StmtError());
17751
17752 auto Name = (Twine(".omp.") + BaseName + std::to_string(val: I)).str();
17753
17754 VarDecl *VD;
17755 if (NeedsNewVD) {
17756 VD = buildVarDecl(SemaRef, Loc: SourceLocation(), Type: IVType, Name);
17757 SemaRef.AddInitializerToDecl(dcl: VD, init: TransformedExpr, DirectInit: false);
17758 } else {
17759 // Create a unique variable name
17760 DeclRefExpr *DRE = cast<DeclRefExpr>(Val: TransformedExpr);
17761 VD = cast<VarDecl>(Val: DRE->getDecl());
17762 VD->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name));
17763 }
17764 // Create the corresponding declaration statement
17765 StmtResult DeclStmt = new (Context) class DeclStmt(
17766 DeclGroupRef(VD), SourceLocation(), SourceLocation());
17767 return std::make_pair(x&: VD, y&: DeclStmt);
17768 };
17769
17770 // PreInits hold a sequence of variable declarations that must be executed
17771 // before the fused loop begins. These include bounds, strides, and other
17772 // helper variables required for the transformation. Other loop transforms
17773 // also contain their own preinits
17774 SmallVector<Stmt *> PreInits;
17775
17776 // Update the general preinits using the preinits generated by loop sequence
17777 // generating loop transformations. These preinits differ slightly from
17778 // single-loop transformation preinits, as they can be detached from a
17779 // specific loop inside multiple generated loop nests. This happens
17780 // because certain helper variables, like '.omp.fuse.max', are introduced to
17781 // handle fused iteration spaces and may not be directly tied to a single
17782 // original loop. The preinit structure must ensure that hidden variables
17783 // like '.omp.fuse.max' are still properly handled.
17784 // Transformations that apply this concept: Loopranged Fuse, Split
17785 llvm::append_range(C&: PreInits, R&: SeqAnalysis.LoopSequencePreInits);
17786
17787 // Process each single loop to generate and collect declarations
17788 // and statements for all helper expressions related to
17789 // particular single loop nests
17790
17791 // Also In the case of the fused loops, we keep track of their original
17792 // inits by appending them to their preinits statement, and in the case of
17793 // transformations, also append their preinits (which contain the original
17794 // loop initialization statement or other statements)
17795
17796 // Firstly we need to set TransformIndex to match the begining of the
17797 // looprange section
17798 unsigned int TransformIndex = 0;
17799 for (unsigned I : llvm::seq<unsigned>(Size: FirstVal - 1)) {
17800 if (SeqAnalysis.Loops[I].isLoopTransformation())
17801 ++TransformIndex;
17802 }
17803
17804 for (unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
17805 if (SeqAnalysis.Loops[I].isRegularLoop()) {
17806 addLoopPreInits(Context, LoopHelper&: SeqAnalysis.Loops[I].HelperExprs,
17807 LoopStmt: SeqAnalysis.Loops[I].TheForStmt,
17808 OriginalInit: SeqAnalysis.Loops[I].OriginalInits, PreInits);
17809 } else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
17810 // For transformed loops, insert both pre-inits and original inits.
17811 // Order matters: pre-inits may define variables used in the original
17812 // inits such as upper bounds...
17813 SmallVector<Stmt *> &TransformPreInit =
17814 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
17815 llvm::append_range(C&: PreInits, R&: TransformPreInit);
17816
17817 addLoopPreInits(Context, LoopHelper&: SeqAnalysis.Loops[I].HelperExprs,
17818 LoopStmt: SeqAnalysis.Loops[I].TheForStmt,
17819 OriginalInit: SeqAnalysis.Loops[I].OriginalInits, PreInits);
17820 }
17821 auto [UBVD, UBDStmt] =
17822 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB, "ub", J);
17823 auto [LBVD, LBDStmt] =
17824 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB, "lb", J);
17825 auto [STVD, STDStmt] =
17826 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST, "st", J);
17827 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
17828 SeqAnalysis.Loops[I].HelperExprs.NumIterations, "ni", J, true);
17829 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
17830 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef, "iv", J);
17831
17832 assert(LBVD && STVD && NIVD && IVVD &&
17833 "OpenMP Fuse Helper variables creation failed");
17834
17835 UBVarDecls.push_back(Elt: UBVD);
17836 LBVarDecls.push_back(Elt: LBVD);
17837 STVarDecls.push_back(Elt: STVD);
17838 NIVarDecls.push_back(Elt: NIVD);
17839 IVVarDecls.push_back(Elt: IVVD);
17840
17841 PreInits.push_back(Elt: LBDStmt.get());
17842 PreInits.push_back(Elt: STDStmt.get());
17843 PreInits.push_back(Elt: NIDStmt.get());
17844 PreInits.push_back(Elt: IVDStmt.get());
17845 }
17846
17847 auto MakeVarDeclRef = [&SemaRef = this->SemaRef](VarDecl *VD) {
17848 return buildDeclRefExpr(S&: SemaRef, D: VD, Ty: VD->getType(), Loc: VD->getLocation(),
17849 RefersToCapture: false);
17850 };
17851
17852 // Following up the creation of the final fused loop will be performed
17853 // which has the following shape (considering the selected loops):
17854 //
17855 // for (fuse.index = 0; fuse.index < max(ni0, ni1..., nik); ++fuse.index) {
17856 // if (fuse.index < ni0){
17857 // iv0 = lb0 + st0 * fuse.index;
17858 // original.index0 = iv0
17859 // body(0);
17860 // }
17861 // if (fuse.index < ni1){
17862 // iv1 = lb1 + st1 * fuse.index;
17863 // original.index1 = iv1
17864 // body(1);
17865 // }
17866 //
17867 // ...
17868 //
17869 // if (fuse.index < nik){
17870 // ivk = lbk + stk * fuse.index;
17871 // original.indexk = ivk
17872 // body(k); Expr *InitVal = IntegerLiteral::Create(Context,
17873 // llvm::APInt(IVWidth, 0),
17874 // }
17875
17876 // 1. Create the initialized fuse index
17877 StringRef IndexName = ".omp.fuse.index";
17878 Expr *InitVal = IntegerLiteral::Create(C: Context, V: llvm::APInt(IVBitWidth, 0),
17879 type: IVType, l: SourceLocation());
17880 VarDecl *IndexDecl =
17881 buildVarDecl(SemaRef, Loc: {}, Type: IVType, Name: IndexName, Attrs: nullptr, OrigRef: nullptr);
17882 SemaRef.AddInitializerToDecl(dcl: IndexDecl, init: InitVal, DirectInit: false);
17883 StmtResult InitStmt = new (Context)
17884 DeclStmt(DeclGroupRef(IndexDecl), SourceLocation(), SourceLocation());
17885
17886 if (!InitStmt.isUsable())
17887 return StmtError();
17888
17889 auto MakeIVRef = [&SemaRef = this->SemaRef, IndexDecl, IVType,
17890 Loc = InitVal->getExprLoc()]() {
17891 return buildDeclRefExpr(S&: SemaRef, D: IndexDecl, Ty: IVType, Loc, RefersToCapture: false);
17892 };
17893
17894 // 2. Iteratively compute the max number of logical iterations Max(NI_1, NI_2,
17895 // ..., NI_k)
17896 //
17897 // This loop accumulates the maximum value across multiple expressions,
17898 // ensuring each step constructs a unique AST node for correctness. By using
17899 // intermediate temporary variables and conditional operators, we maintain
17900 // distinct nodes and avoid duplicating subtrees, For instance, max(a,b,c):
17901 // omp.temp0 = max(a, b)
17902 // omp.temp1 = max(omp.temp0, c)
17903 // omp.fuse.max = max(omp.temp1, omp.temp0)
17904
17905 ExprResult MaxExpr;
17906 // I is the range of loops in the sequence that we fuse.
17907 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
17908 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
17909 QualType NITy = NIRef->getType();
17910
17911 if (MaxExpr.isUnset()) {
17912 // Initialize MaxExpr with the first NI expression
17913 MaxExpr = NIRef;
17914 } else {
17915 // Create a new acummulator variable t_i = MaxExpr
17916 std::string TempName = (Twine(".omp.temp.") + Twine(J)).str();
17917 VarDecl *TempDecl =
17918 buildVarDecl(SemaRef, Loc: {}, Type: NITy, Name: TempName, Attrs: nullptr, OrigRef: nullptr);
17919 TempDecl->setInit(MaxExpr.get());
17920 DeclRefExpr *TempRef =
17921 buildDeclRefExpr(S&: SemaRef, D: TempDecl, Ty: NITy, Loc: SourceLocation(), RefersToCapture: false);
17922 DeclRefExpr *TempRef2 =
17923 buildDeclRefExpr(S&: SemaRef, D: TempDecl, Ty: NITy, Loc: SourceLocation(), RefersToCapture: false);
17924 // Add a DeclStmt to PreInits to ensure the variable is declared.
17925 StmtResult TempStmt = new (Context)
17926 DeclStmt(DeclGroupRef(TempDecl), SourceLocation(), SourceLocation());
17927
17928 if (!TempStmt.isUsable())
17929 return StmtError();
17930 PreInits.push_back(Elt: TempStmt.get());
17931
17932 // Build MaxExpr <-(MaxExpr > NIRef ? MaxExpr : NIRef)
17933 ExprResult Comparison =
17934 SemaRef.BuildBinOp(S: nullptr, OpLoc: SourceLocation(), Opc: BO_GT, LHSExpr: TempRef, RHSExpr: NIRef);
17935 // Handle any errors in Comparison creation
17936 if (!Comparison.isUsable())
17937 return StmtError();
17938
17939 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
17940 // Update MaxExpr using a conditional expression to hold the max value
17941 MaxExpr = new (Context) ConditionalOperator(
17942 Comparison.get(), SourceLocation(), TempRef2, SourceLocation(),
17943 NIRef2->getExprStmt(), NITy, VK_LValue, OK_Ordinary);
17944
17945 if (!MaxExpr.isUsable())
17946 return StmtError();
17947 }
17948 }
17949 if (!MaxExpr.isUsable())
17950 return StmtError();
17951
17952 // 3. Declare the max variable
17953 const std::string MaxName = Twine(".omp.fuse.max").str();
17954 VarDecl *MaxDecl =
17955 buildVarDecl(SemaRef, Loc: {}, Type: IVType, Name: MaxName, Attrs: nullptr, OrigRef: nullptr);
17956 MaxDecl->setInit(MaxExpr.get());
17957 DeclRefExpr *MaxRef = buildDeclRefExpr(S&: SemaRef, D: MaxDecl, Ty: IVType, Loc: {}, RefersToCapture: false);
17958 StmtResult MaxStmt = new (Context)
17959 DeclStmt(DeclGroupRef(MaxDecl), SourceLocation(), SourceLocation());
17960
17961 if (MaxStmt.isInvalid())
17962 return StmtError();
17963 PreInits.push_back(Elt: MaxStmt.get());
17964
17965 // 4. Create condition Expr: index < n_max
17966 ExprResult CondExpr = SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_LT,
17967 LHSExpr: MakeIVRef(), RHSExpr: MaxRef);
17968 if (!CondExpr.isUsable())
17969 return StmtError();
17970
17971 // 5. Increment Expr: ++index
17972 ExprResult IncrExpr =
17973 SemaRef.BuildUnaryOp(S: CurScope, OpLoc: SourceLocation(), Opc: UO_PreInc, Input: MakeIVRef());
17974 if (!IncrExpr.isUsable())
17975 return StmtError();
17976
17977 // 6. Build the Fused Loop Body
17978 // The final fused loop iterates over the maximum logical range. Inside the
17979 // loop, each original loop's index is calculated dynamically, and its body
17980 // is executed conditionally.
17981 //
17982 // Each sub-loop's body is guarded by a conditional statement to ensure
17983 // it executes only within its logical iteration range:
17984 //
17985 // if (fuse.index < ni_k){
17986 // iv_k = lb_k + st_k * fuse.index;
17987 // original.index = iv_k
17988 // body(k);
17989 // }
17990
17991 CompoundStmt *FusedBody = nullptr;
17992 SmallVector<Stmt *, 4> FusedBodyStmts;
17993 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
17994 // Assingment of the original sub-loop index to compute the logical index
17995 // IV_k = LB_k + omp.fuse.index * ST_k
17996 ExprResult IdxExpr =
17997 SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_Mul,
17998 LHSExpr: MakeVarDeclRef(STVarDecls[J]), RHSExpr: MakeIVRef());
17999 if (!IdxExpr.isUsable())
18000 return StmtError();
18001 IdxExpr = SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_Add,
18002 LHSExpr: MakeVarDeclRef(LBVarDecls[J]), RHSExpr: IdxExpr.get());
18003
18004 if (!IdxExpr.isUsable())
18005 return StmtError();
18006 IdxExpr = SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_Assign,
18007 LHSExpr: MakeVarDeclRef(IVVarDecls[J]), RHSExpr: IdxExpr.get());
18008 if (!IdxExpr.isUsable())
18009 return StmtError();
18010
18011 // Update the original i_k = IV_k
18012 SmallVector<Stmt *, 4> BodyStmts;
18013 BodyStmts.push_back(Elt: IdxExpr.get());
18014 llvm::append_range(C&: BodyStmts, R&: SeqAnalysis.Loops[I].HelperExprs.Updates);
18015
18016 // If the loop is a CXXForRangeStmt then the iterator variable is needed
18017 if (auto *SourceCXXFor =
18018 dyn_cast<CXXForRangeStmt>(Val: SeqAnalysis.Loops[I].TheForStmt))
18019 BodyStmts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
18020
18021 Stmt *Body =
18022 (isa<ForStmt>(Val: SeqAnalysis.Loops[I].TheForStmt))
18023 ? cast<ForStmt>(Val: SeqAnalysis.Loops[I].TheForStmt)->getBody()
18024 : cast<CXXForRangeStmt>(Val: SeqAnalysis.Loops[I].TheForStmt)->getBody();
18025 BodyStmts.push_back(Elt: Body);
18026
18027 CompoundStmt *CombinedBody =
18028 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
18029 LB: SourceLocation(), RB: SourceLocation());
18030 ExprResult Condition =
18031 SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_LT, LHSExpr: MakeIVRef(),
18032 RHSExpr: MakeVarDeclRef(NIVarDecls[J]));
18033
18034 if (!Condition.isUsable())
18035 return StmtError();
18036
18037 IfStmt *IfStatement = IfStmt::Create(
18038 Ctx: Context, IL: SourceLocation(), Kind: IfStatementKind::Ordinary, Init: nullptr, Var: nullptr,
18039 Cond: Condition.get(), LPL: SourceLocation(), RPL: SourceLocation(), Then: CombinedBody,
18040 EL: SourceLocation(), Else: nullptr);
18041
18042 FusedBodyStmts.push_back(Elt: IfStatement);
18043 }
18044 FusedBody = CompoundStmt::Create(C: Context, Stmts: FusedBodyStmts, FPFeatures: FPOptionsOverride(),
18045 LB: SourceLocation(), RB: SourceLocation());
18046
18047 // 7. Construct the final fused loop
18048 ForStmt *FusedForStmt = new (Context)
18049 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, IncrExpr.get(),
18050 FusedBody, InitStmt.get()->getBeginLoc(), SourceLocation(),
18051 IncrExpr.get()->getEndLoc());
18052
18053 // In the case of looprange, the result of fuse won't simply
18054 // be a single loop (ForStmt), but rather a loop sequence
18055 // (CompoundStmt) of 3 parts: the pre-fusion loops, the fused loop
18056 // and the post-fusion loops, preserving its original order.
18057 //
18058 // Note: If looprange clause produces a single fused loop nest then
18059 // this compound statement wrapper is unnecessary (Therefore this
18060 // treatment is skipped)
18061
18062 Stmt *FusionStmt = FusedForStmt;
18063 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
18064 SmallVector<Stmt *, 4> FinalLoops;
18065
18066 // Reset the transform index
18067 TransformIndex = 0;
18068
18069 // Collect all non-fused loops before and after the fused region.
18070 // Pre-fusion and post-fusion loops are inserted in order exploiting their
18071 // symmetry, along with their corresponding transformation pre-inits if
18072 // needed. The fused loop is added between the two regions.
18073 for (unsigned I : llvm::seq<unsigned>(Size: SeqAnalysis.LoopSeqSize)) {
18074 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
18075 // Update the Transformation counter to skip already treated
18076 // loop transformations
18077 if (!SeqAnalysis.Loops[I].isLoopTransformation())
18078 ++TransformIndex;
18079 continue;
18080 }
18081
18082 // No need to handle:
18083 // Regular loops: they are kept intact as-is.
18084 // Loop-sequence-generating transformations: already handled earlier.
18085 // Only TransformSingleLoop requires inserting pre-inits here
18086 if (SeqAnalysis.Loops[I].isRegularLoop()) {
18087 const auto &TransformPreInit =
18088 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
18089 if (!TransformPreInit.empty())
18090 llvm::append_range(C&: PreInits, R: TransformPreInit);
18091 }
18092
18093 FinalLoops.push_back(Elt: SeqAnalysis.Loops[I].TheForStmt);
18094 }
18095
18096 FinalLoops.insert(I: FinalLoops.begin() + (FirstVal - 1), Elt: FusedForStmt);
18097 FusionStmt = CompoundStmt::Create(C: Context, Stmts: FinalLoops, FPFeatures: FPOptionsOverride(),
18098 LB: SourceLocation(), RB: SourceLocation());
18099 }
18100 return OMPFuseDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
18101 NumGeneratedTopLevelLoops, AssociatedStmt: AStmt, TransformedStmt: FusionStmt,
18102 PreInits: buildPreInits(Context, PreInits));
18103}
18104
18105OMPClause *SemaOpenMP::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
18106 Expr *Expr,
18107 SourceLocation StartLoc,
18108 SourceLocation LParenLoc,
18109 SourceLocation EndLoc) {
18110 OMPClause *Res = nullptr;
18111 switch (Kind) {
18112 case OMPC_final:
18113 Res = ActOnOpenMPFinalClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
18114 break;
18115 case OMPC_safelen:
18116 Res = ActOnOpenMPSafelenClause(Length: Expr, StartLoc, LParenLoc, EndLoc);
18117 break;
18118 case OMPC_simdlen:
18119 Res = ActOnOpenMPSimdlenClause(Length: Expr, StartLoc, LParenLoc, EndLoc);
18120 break;
18121 case OMPC_allocator:
18122 Res = ActOnOpenMPAllocatorClause(Allocator: Expr, StartLoc, LParenLoc, EndLoc);
18123 break;
18124 case OMPC_collapse:
18125 Res = ActOnOpenMPCollapseClause(NumForLoops: Expr, StartLoc, LParenLoc, EndLoc);
18126 break;
18127 case OMPC_ordered:
18128 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, NumForLoops: Expr);
18129 break;
18130 case OMPC_nowait:
18131 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc, LParenLoc, Condition: Expr);
18132 break;
18133 case OMPC_priority:
18134 Res = ActOnOpenMPPriorityClause(Priority: Expr, StartLoc, LParenLoc, EndLoc);
18135 break;
18136 case OMPC_hint:
18137 Res = ActOnOpenMPHintClause(Hint: Expr, StartLoc, LParenLoc, EndLoc);
18138 break;
18139 case OMPC_depobj:
18140 Res = ActOnOpenMPDepobjClause(Depobj: Expr, StartLoc, LParenLoc, EndLoc);
18141 break;
18142 case OMPC_detach:
18143 Res = ActOnOpenMPDetachClause(Evt: Expr, StartLoc, LParenLoc, EndLoc);
18144 break;
18145 case OMPC_novariants:
18146 Res = ActOnOpenMPNovariantsClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
18147 break;
18148 case OMPC_nocontext:
18149 Res = ActOnOpenMPNocontextClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
18150 break;
18151 case OMPC_filter:
18152 Res = ActOnOpenMPFilterClause(ThreadID: Expr, StartLoc, LParenLoc, EndLoc);
18153 break;
18154 case OMPC_partial:
18155 Res = ActOnOpenMPPartialClause(FactorExpr: Expr, StartLoc, LParenLoc, EndLoc);
18156 break;
18157 case OMPC_depth:
18158 Res = ActOnOpenMPDepthClause(DepthExpr: Expr, StartLoc, LParenLoc, EndLoc);
18159 break;
18160 case OMPC_message:
18161 Res = ActOnOpenMPMessageClause(MS: Expr, StartLoc, LParenLoc, EndLoc);
18162 break;
18163 case OMPC_align:
18164 Res = ActOnOpenMPAlignClause(Alignment: Expr, StartLoc, LParenLoc, EndLoc);
18165 break;
18166 case OMPC_ompx_dyn_cgroup_mem:
18167 Res = ActOnOpenMPXDynCGroupMemClause(Size: Expr, StartLoc, LParenLoc, EndLoc);
18168 break;
18169 case OMPC_holds:
18170 Res = ActOnOpenMPHoldsClause(E: Expr, StartLoc, LParenLoc, EndLoc);
18171 break;
18172 case OMPC_transparent:
18173 Res = ActOnOpenMPTransparentClause(Transparent: Expr, StartLoc, LParenLoc, EndLoc);
18174 break;
18175 case OMPC_dyn_groupprivate:
18176 case OMPC_grainsize:
18177 case OMPC_num_tasks:
18178 case OMPC_num_threads:
18179 case OMPC_device:
18180 case OMPC_if:
18181 case OMPC_default:
18182 case OMPC_proc_bind:
18183 case OMPC_schedule:
18184 case OMPC_private:
18185 case OMPC_firstprivate:
18186 case OMPC_lastprivate:
18187 case OMPC_shared:
18188 case OMPC_reduction:
18189 case OMPC_task_reduction:
18190 case OMPC_in_reduction:
18191 case OMPC_linear:
18192 case OMPC_aligned:
18193 case OMPC_copyin:
18194 case OMPC_copyprivate:
18195 case OMPC_untied:
18196 case OMPC_mergeable:
18197 case OMPC_threadprivate:
18198 case OMPC_groupprivate:
18199 case OMPC_sizes:
18200 case OMPC_allocate:
18201 case OMPC_flush:
18202 case OMPC_read:
18203 case OMPC_write:
18204 case OMPC_update:
18205 case OMPC_capture:
18206 case OMPC_compare:
18207 case OMPC_seq_cst:
18208 case OMPC_acq_rel:
18209 case OMPC_acquire:
18210 case OMPC_release:
18211 case OMPC_relaxed:
18212 case OMPC_depend:
18213 case OMPC_threads:
18214 case OMPC_simd:
18215 case OMPC_map:
18216 case OMPC_nogroup:
18217 case OMPC_dist_schedule:
18218 case OMPC_defaultmap:
18219 case OMPC_unknown:
18220 case OMPC_uniform:
18221 case OMPC_to:
18222 case OMPC_from:
18223 case OMPC_use_device_ptr:
18224 case OMPC_use_device_addr:
18225 case OMPC_is_device_ptr:
18226 case OMPC_unified_address:
18227 case OMPC_unified_shared_memory:
18228 case OMPC_reverse_offload:
18229 case OMPC_dynamic_allocators:
18230 case OMPC_atomic_default_mem_order:
18231 case OMPC_self_maps:
18232 case OMPC_device_type:
18233 case OMPC_match:
18234 case OMPC_nontemporal:
18235 case OMPC_order:
18236 case OMPC_at:
18237 case OMPC_severity:
18238 case OMPC_destroy:
18239 case OMPC_inclusive:
18240 case OMPC_exclusive:
18241 case OMPC_uses_allocators:
18242 case OMPC_affinity:
18243 case OMPC_when:
18244 case OMPC_bind:
18245 case OMPC_num_teams:
18246 case OMPC_thread_limit:
18247 default:
18248 llvm_unreachable("Clause is not allowed.");
18249 }
18250 return Res;
18251}
18252
18253// An OpenMP directive such as 'target parallel' has two captured regions:
18254// for the 'target' and 'parallel' respectively. This function returns
18255// the region in which to capture expressions associated with a clause.
18256// A return value of OMPD_unknown signifies that the expression should not
18257// be captured.
18258static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
18259 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
18260 llvm::omp::Version OMPVersion,
18261 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
18262 assert(isAllowedClauseForDirective(DKind, CKind, OMPVersion) &&
18263 "Invalid directive with CKind-clause");
18264
18265 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
18266 if (NameModifier != OMPD_unknown &&
18267 !isAllowedClauseForDirective(D: NameModifier, C: CKind, V: OMPVersion))
18268 return OMPD_unknown;
18269
18270 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(D: DKind);
18271
18272 // [5.2:341:24-30]
18273 // If the clauses have expressions on them, such as for various clauses where
18274 // the argument of the clause is an expression, or lower-bound, length, or
18275 // stride expressions inside array sections (or subscript and stride
18276 // expressions in subscript-triplet for Fortran), or linear-step or alignment
18277 // expressions, the expressions are evaluated immediately before the construct
18278 // to which the clause has been split or duplicated per the above rules
18279 // (therefore inside of the outer leaf constructs). However, the expressions
18280 // inside the num_teams and thread_limit clauses are always evaluated before
18281 // the outermost leaf construct.
18282
18283 // Process special cases first.
18284 switch (CKind) {
18285 case OMPC_if:
18286 switch (DKind) {
18287 case OMPD_teams_loop:
18288 case OMPD_target_teams_loop:
18289 // For [target] teams loop, assume capture region is 'teams' so it's
18290 // available for codegen later to use if/when necessary.
18291 return OMPD_teams;
18292 case OMPD_target_update:
18293 case OMPD_target_enter_data:
18294 case OMPD_target_exit_data:
18295 return OMPD_task;
18296 default:
18297 break;
18298 }
18299 break;
18300 case OMPC_num_teams:
18301 case OMPC_thread_limit:
18302 case OMPC_ompx_dyn_cgroup_mem:
18303 case OMPC_dyn_groupprivate:
18304 // TODO: This may need to consider teams too.
18305 if (Leafs[0] == OMPD_target)
18306 return OMPD_target;
18307 break;
18308 case OMPC_device:
18309 if (Leafs[0] == OMPD_target ||
18310 llvm::is_contained(Set: {OMPD_dispatch, OMPD_target_update,
18311 OMPD_target_enter_data, OMPD_target_exit_data},
18312 Element: DKind))
18313 return OMPD_task;
18314 break;
18315 case OMPC_novariants:
18316 case OMPC_nocontext:
18317 if (DKind == OMPD_dispatch)
18318 return OMPD_task;
18319 break;
18320 case OMPC_when:
18321 if (DKind == OMPD_metadirective)
18322 return OMPD_metadirective;
18323 break;
18324 case OMPC_filter:
18325 return OMPD_unknown;
18326 default:
18327 break;
18328 }
18329
18330 // If none of the special cases above applied, and DKind is a capturing
18331 // directive, find the innermost enclosing leaf construct that allows the
18332 // clause, and returns the corresponding capture region.
18333
18334 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
18335 // Find the index in "Leafs" of the last leaf that allows the given
18336 // clause. The search will only include indexes [0, EndIdx).
18337 // EndIdx may be set to the index of the NameModifier, if present.
18338 int InnermostIdx = [&]() {
18339 for (int I = EndIdx - 1; I >= 0; --I) {
18340 if (isAllowedClauseForDirective(D: Leafs[I], C: Clause, V: OMPVersion))
18341 return I;
18342 }
18343 return -1;
18344 }();
18345
18346 // Find the nearest enclosing capture region.
18347 SmallVector<OpenMPDirectiveKind, 2> Regions;
18348 for (int I = InnermostIdx - 1; I >= 0; --I) {
18349 if (!isOpenMPCapturingDirective(DKind: Leafs[I]))
18350 continue;
18351 Regions.clear();
18352 getOpenMPCaptureRegions(CaptureRegions&: Regions, DKind: Leafs[I]);
18353 if (Regions[0] != OMPD_unknown)
18354 return Regions.back();
18355 }
18356 return OMPD_unknown;
18357 };
18358
18359 if (isOpenMPCapturingDirective(DKind)) {
18360 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
18361 for (int I = 0, E = Leafs.size(); I != E; ++I) {
18362 if (Leafs[I] == Dir)
18363 return I + 1;
18364 }
18365 return 0;
18366 };
18367
18368 int End = NameModifier == OMPD_unknown ? Leafs.size()
18369 : GetLeafIndex(NameModifier);
18370 return GetEnclosingRegion(End, CKind);
18371 }
18372
18373 return OMPD_unknown;
18374}
18375
18376OMPClause *SemaOpenMP::ActOnOpenMPIfClause(
18377 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
18378 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
18379 SourceLocation ColonLoc, SourceLocation EndLoc) {
18380 Expr *ValExpr = Condition;
18381 Stmt *HelperValStmt = nullptr;
18382 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18383 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18384 !Condition->isInstantiationDependent() &&
18385 !Condition->containsUnexpandedParameterPack()) {
18386 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
18387 if (Val.isInvalid())
18388 return nullptr;
18389
18390 ValExpr = Val.get();
18391
18392 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18393 CaptureRegion = getOpenMPCaptureRegionForClause(
18394 DKind, CKind: OMPC_if, OMPVersion: getLangOpts().getOpenMPVersion(), NameModifier);
18395 if (CaptureRegion != OMPD_unknown &&
18396 !SemaRef.CurContext->isDependentContext()) {
18397 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
18398 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18399 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
18400 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
18401 }
18402 }
18403
18404 return new (getASTContext())
18405 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
18406 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
18407}
18408
18409OMPClause *SemaOpenMP::ActOnOpenMPFinalClause(Expr *Condition,
18410 SourceLocation StartLoc,
18411 SourceLocation LParenLoc,
18412 SourceLocation EndLoc) {
18413 Expr *ValExpr = Condition;
18414 Stmt *HelperValStmt = nullptr;
18415 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18416 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18417 !Condition->isInstantiationDependent() &&
18418 !Condition->containsUnexpandedParameterPack()) {
18419 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
18420 if (Val.isInvalid())
18421 return nullptr;
18422
18423 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
18424
18425 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18426 CaptureRegion = getOpenMPCaptureRegionForClause(
18427 DKind, CKind: OMPC_final, OMPVersion: getLangOpts().getOpenMPVersion());
18428 if (CaptureRegion != OMPD_unknown &&
18429 !SemaRef.CurContext->isDependentContext()) {
18430 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
18431 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18432 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
18433 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
18434 }
18435 }
18436
18437 return new (getASTContext()) OMPFinalClause(
18438 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18439}
18440
18441ExprResult
18442SemaOpenMP::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
18443 Expr *Op) {
18444 if (!Op)
18445 return ExprError();
18446
18447 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
18448 public:
18449 IntConvertDiagnoser()
18450 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
18451 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
18452 QualType T) override {
18453 return S.Diag(Loc, DiagID: diag::err_omp_not_integral) << T;
18454 }
18455 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
18456 QualType T) override {
18457 return S.Diag(Loc, DiagID: diag::err_omp_incomplete_type) << T;
18458 }
18459 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
18460 QualType T,
18461 QualType ConvTy) override {
18462 return S.Diag(Loc, DiagID: diag::err_omp_explicit_conversion) << T << ConvTy;
18463 }
18464 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
18465 QualType ConvTy) override {
18466 return S.Diag(Loc: Conv->getLocation(), DiagID: diag::note_omp_conversion_here)
18467 << ConvTy->isEnumeralType() << ConvTy;
18468 }
18469 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
18470 QualType T) override {
18471 return S.Diag(Loc, DiagID: diag::err_omp_ambiguous_conversion) << T;
18472 }
18473 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
18474 QualType ConvTy) override {
18475 return S.Diag(Loc: Conv->getLocation(), DiagID: diag::note_omp_conversion_here)
18476 << ConvTy->isEnumeralType() << ConvTy;
18477 }
18478 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
18479 QualType) override {
18480 llvm_unreachable("conversion functions are permitted");
18481 }
18482 } ConvertDiagnoser;
18483 return SemaRef.PerformContextualImplicitConversion(Loc, FromE: Op, Converter&: ConvertDiagnoser);
18484}
18485
18486static bool
18487isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
18488 bool StrictlyPositive, bool BuildCapture = false,
18489 OpenMPDirectiveKind DKind = OMPD_unknown,
18490 OpenMPDirectiveKind *CaptureRegion = nullptr,
18491 Stmt **HelperValStmt = nullptr) {
18492 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
18493 !ValExpr->isInstantiationDependent()) {
18494 SourceLocation Loc = ValExpr->getExprLoc();
18495 ExprResult Value =
18496 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, Op: ValExpr);
18497 if (Value.isInvalid())
18498 return false;
18499
18500 ValExpr = Value.get();
18501 // The expression must evaluate to a non-negative integer value.
18502 if (std::optional<llvm::APSInt> Result =
18503 ValExpr->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
18504 if (Result->isSigned() &&
18505 !((!StrictlyPositive && Result->isNonNegative()) ||
18506 (StrictlyPositive && Result->isStrictlyPositive()))) {
18507 SemaRef.Diag(Loc, DiagID: diag::err_omp_negative_expression_in_clause)
18508 << getOpenMPClauseNameForDiag(C: CKind) << (StrictlyPositive ? 1 : 0)
18509 << ValExpr->getSourceRange();
18510 return false;
18511 }
18512 }
18513 if (!BuildCapture)
18514 return true;
18515 *CaptureRegion = getOpenMPCaptureRegionForClause(
18516 DKind, CKind, OMPVersion: SemaRef.getLangOpts().getOpenMPVersion());
18517 if (*CaptureRegion != OMPD_unknown &&
18518 !SemaRef.CurContext->isDependentContext()) {
18519 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
18520 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18521 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
18522 *HelperValStmt = buildPreInits(Context&: SemaRef.Context, Captures);
18523 }
18524 }
18525 return true;
18526}
18527
18528static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
18529 unsigned Last,
18530 ArrayRef<unsigned> Exclude = {}) {
18531 SmallString<256> Buffer;
18532 llvm::raw_svector_ostream Out(Buffer);
18533 unsigned Skipped = Exclude.size();
18534 for (unsigned I = First; I < Last; ++I) {
18535 if (llvm::is_contained(Range&: Exclude, Element: I)) {
18536 --Skipped;
18537 continue;
18538 }
18539 Out << "'" << getOpenMPSimpleClauseTypeName(Kind: K, Type: I) << "'";
18540 if (I + Skipped + 2 == Last)
18541 Out << " or ";
18542 else if (I + Skipped + 1 != Last)
18543 Out << ", ";
18544 }
18545 return std::string(Out.str());
18546}
18547
18548OMPClause *SemaOpenMP::ActOnOpenMPNumThreadsClause(
18549 ArrayRef<Expr *> VarList, OpenMPNumThreadsClauseModifier SimpleModifier,
18550 SourceLocation SimpleModifierLoc,
18551 OpenMPNumThreadsClauseModifier ComplexModifier, Expr *ComplexModifierExpr,
18552 SourceLocation ComplexModifierLoc, SourceLocation StartLoc,
18553 SourceLocation LParenLoc, SourceLocation EndLoc) {
18554 // Check that modifiers were correctly specified.
18555 if (ComplexModifierLoc.isValid() &&
18556 (ComplexModifier != OMPC_NUMTHREADS_dims || !ComplexModifierExpr)) {
18557 Diag(Loc: ComplexModifierLoc, DiagID: diag::err_omp_malformed_complex_modifier)
18558 << getOpenMPSimpleClauseTypeName(Kind: OMPC_num_threads, Type: OMPC_NUMTHREADS_dims)
18559 << getOpenMPClauseName(C: OMPC_num_threads);
18560 return nullptr;
18561 }
18562 if (SimpleModifierLoc.isValid() && SimpleModifier == OMPC_NUMTHREADS_dims) {
18563 Diag(Loc: SimpleModifierLoc, DiagID: diag::err_omp_malformed_complex_modifier)
18564 << getOpenMPSimpleClauseTypeName(Kind: OMPC_num_threads, Type: OMPC_NUMTHREADS_dims)
18565 << getOpenMPClauseName(C: OMPC_num_threads);
18566 return nullptr;
18567 }
18568 if (SimpleModifierLoc.isValid() && SimpleModifier != OMPC_NUMTHREADS_strict) {
18569 Diag(Loc: SimpleModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
18570 << getOpenMPSimpleClauseTypeName(Kind: OMPC_num_threads,
18571 Type: OMPC_NUMTHREADS_strict)
18572 << getOpenMPClauseName(C: OMPC_num_threads);
18573 return nullptr;
18574 }
18575
18576 if (VarList.empty())
18577 return nullptr;
18578
18579 SmallVector<Expr *, 3> Vars(VarList.begin(), VarList.end());
18580 for (Expr *&ValExpr : Vars) {
18581 // OpenMP [2.5, Restrictions]
18582 // The num_threads expression must evaluate to a positive integer value.
18583 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_num_threads,
18584 /*StrictlyPositive=*/true))
18585 return nullptr;
18586 }
18587
18588 if (ComplexModifier == OMPC_NUMTHREADS_dims) {
18589 ExprResult Res = ActOnOpenMPDimsModifier(Kind: OMPC_num_threads, Modifier: ComplexModifier,
18590 ModifierExpr: ComplexModifierExpr,
18591 ModifierLoc: ComplexModifierLoc, VarList: Vars, VarListEndLoc: EndLoc);
18592 if (Res.isInvalid())
18593 return nullptr;
18594 ComplexModifierExpr = Res.get();
18595
18596 if (validateMultidimClauseExprs(SemaRef&: *this, ClauseKind: OMPC_num_threads, ClauseBeginLoc: StartLoc, ClauseVarList: Vars,
18597 DimsModifierExpr: ComplexModifierExpr))
18598 return nullptr;
18599 }
18600 if (SimpleModifier == OMPC_NUMTHREADS_strict && getLangOpts().OpenMP < 60) {
18601 Diag(Loc: SimpleModifierLoc, DiagID: diag::err_omp_modifier_requires_version)
18602 << getOpenMPSimpleClauseTypeName(Kind: OMPC_num_threads, Type: SimpleModifier)
18603 << getOpenMPClauseName(C: OMPC_num_threads) << "6.0";
18604 return nullptr;
18605 }
18606
18607 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18608 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
18609 DKind, CKind: OMPC_num_threads, OMPVersion: getLangOpts().getOpenMPVersion());
18610 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
18611 return OMPNumThreadsClause::Create(
18612 C: getASTContext(), CaptureRegion, StartLoc, LParenLoc, EndLoc, VL: Vars,
18613 PrescriptivenessModifier: SimpleModifier, DimsModifier: ComplexModifier, PrescriptivenessModifierLoc: SimpleModifierLoc, DimsModifierLoc: ComplexModifierLoc,
18614 DimsModifierExpr: ComplexModifierExpr, /*PreInit=*/nullptr);
18615
18616 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18617 for (Expr *&ValExpr : Vars) {
18618 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
18619 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
18620 }
18621 if (ComplexModifierExpr) {
18622 ComplexModifierExpr = SemaRef.MakeFullExpr(Arg: ComplexModifierExpr).get();
18623 ComplexModifierExpr =
18624 tryBuildCapture(SemaRef, Capture: ComplexModifierExpr, Captures).get();
18625 }
18626 Stmt *PreInit = buildPreInits(Context&: getASTContext(), Captures);
18627
18628 return OMPNumThreadsClause::Create(
18629 C: getASTContext(), CaptureRegion, StartLoc, LParenLoc, EndLoc, VL: Vars,
18630 PrescriptivenessModifier: SimpleModifier, DimsModifier: ComplexModifier, PrescriptivenessModifierLoc: SimpleModifierLoc, DimsModifierLoc: ComplexModifierLoc,
18631 DimsModifierExpr: ComplexModifierExpr, PreInit);
18632}
18633
18634ExprResult SemaOpenMP::VerifyPositiveIntegerConstantInClause(
18635 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
18636 bool SuppressExprDiags) {
18637 if (!E)
18638 return ExprError();
18639 if (E->isValueDependent() || E->isTypeDependent() ||
18640 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
18641 return E;
18642
18643 llvm::APSInt Result;
18644 ExprResult ICE;
18645 if (SuppressExprDiags) {
18646 // Use a custom diagnoser that suppresses 'note' diagnostics about the
18647 // expression.
18648 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
18649 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
18650 SemaBase::SemaDiagnosticBuilder
18651 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
18652 llvm_unreachable("Diagnostic suppressed");
18653 }
18654 } Diagnoser;
18655 ICE = SemaRef.VerifyIntegerConstantExpression(E, Result: &Result, Diagnoser,
18656 CanFold: AllowFoldKind::Allow);
18657 } else {
18658 ICE =
18659 SemaRef.VerifyIntegerConstantExpression(E, Result: &Result,
18660 /*FIXME*/ CanFold: AllowFoldKind::Allow);
18661 }
18662 if (ICE.isInvalid())
18663 return ExprError();
18664
18665 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
18666 (!StrictlyPositive && !Result.isNonNegative())) {
18667 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_negative_expression_in_clause)
18668 << getOpenMPClauseNameForDiag(C: CKind) << (StrictlyPositive ? 1 : 0)
18669 << E->getSourceRange();
18670 return ExprError();
18671 }
18672 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
18673 CKind == OMPC_allocate) &&
18674 !Result.isPowerOf2()) {
18675 Diag(Loc: E->getExprLoc(), DiagID: diag::warn_omp_alignment_not_power_of_two)
18676 << E->getSourceRange();
18677 return ExprError();
18678 }
18679
18680 if (!Result.isRepresentableByInt64()) {
18681 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_large_expression_in_clause)
18682 << getOpenMPClauseNameForDiag(C: CKind) << E->getSourceRange();
18683 return ExprError();
18684 }
18685
18686 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
18687 DSAStack->setAssociatedLoops(Result.getExtValue());
18688 else if (CKind == OMPC_ordered)
18689 DSAStack->setAssociatedLoops(Result.getExtValue());
18690 return ICE;
18691}
18692
18693void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
18694
18695void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
18696
18697int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
18698
18699void SemaOpenMP::ActOnOpenMPDeviceNum(Expr *DeviceNumExpr) {
18700 llvm::APSInt Result;
18701 Expr::EvalResult EvalResult;
18702 // Evaluate the expression to an integer value
18703 if (!DeviceNumExpr->isValueDependent() &&
18704 DeviceNumExpr->EvaluateAsInt(Result&: EvalResult, Ctx: SemaRef.Context)) {
18705 // The device expression must evaluate to a non-negative integer value.
18706 Result = EvalResult.Val.getInt();
18707 if (Result.isNonNegative()) {
18708 setOpenMPDeviceNum(Result.getZExtValue());
18709 } else {
18710 Diag(Loc: DeviceNumExpr->getExprLoc(),
18711 DiagID: diag::err_omp_negative_expression_in_clause)
18712 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
18713 }
18714 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(Val: DeviceNumExpr)) {
18715 // Check if the expression is an identifier
18716 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
18717 if (IdInfo) {
18718 setOpenMPDeviceNumID(IdInfo->getName());
18719 }
18720 } else {
18721 Diag(Loc: DeviceNumExpr->getExprLoc(), DiagID: diag::err_expected_expression);
18722 }
18723}
18724
18725OMPClause *SemaOpenMP::ActOnOpenMPSafelenClause(Expr *Len,
18726 SourceLocation StartLoc,
18727 SourceLocation LParenLoc,
18728 SourceLocation EndLoc) {
18729 // OpenMP [2.8.1, simd construct, Description]
18730 // The parameter of the safelen clause must be a constant
18731 // positive integer expression.
18732 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(E: Len, CKind: OMPC_safelen);
18733 if (Safelen.isInvalid())
18734 return nullptr;
18735 return new (getASTContext())
18736 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
18737}
18738
18739OMPClause *SemaOpenMP::ActOnOpenMPSimdlenClause(Expr *Len,
18740 SourceLocation StartLoc,
18741 SourceLocation LParenLoc,
18742 SourceLocation EndLoc) {
18743 // OpenMP [2.8.1, simd construct, Description]
18744 // The parameter of the simdlen clause must be a constant
18745 // positive integer expression.
18746 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(E: Len, CKind: OMPC_simdlen);
18747 if (Simdlen.isInvalid())
18748 return nullptr;
18749 return new (getASTContext())
18750 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
18751}
18752
18753/// Tries to find omp_allocator_handle_t type.
18754static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
18755 DSAStackTy *Stack) {
18756 if (!Stack->getOMPAllocatorHandleT().isNull())
18757 return true;
18758
18759 // Set the allocator handle type.
18760 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_allocator_handle_t");
18761 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
18762 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
18763 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found)
18764 << "omp_allocator_handle_t";
18765 return false;
18766 }
18767 QualType AllocatorHandleEnumTy = PT.get();
18768 AllocatorHandleEnumTy.addConst();
18769
18770 // Fill the predefined allocator map.
18771 bool ErrorFound = false;
18772 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
18773 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
18774 StringRef Allocator =
18775 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(Val: AllocatorKind);
18776 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Name: Allocator);
18777 auto *VD = dyn_cast_or_null<ValueDecl>(
18778 Val: S.LookupSingleName(S: S.TUScope, Name: AllocatorName, Loc, NameKind: Sema::LookupAnyName));
18779 if (!VD) {
18780 ErrorFound = true;
18781 break;
18782 }
18783 QualType AllocatorType =
18784 VD->getType().getNonLValueExprType(Context: S.getASTContext());
18785 ExprResult Res = S.BuildDeclRefExpr(D: VD, Ty: AllocatorType, VK: VK_LValue, Loc);
18786 if (!Res.isUsable()) {
18787 ErrorFound = true;
18788 break;
18789 }
18790 Res = S.PerformImplicitConversion(From: Res.get(), ToType: AllocatorHandleEnumTy,
18791 Action: AssignmentAction::Initializing,
18792 /*AllowExplicit=*/true);
18793 if (!Res.isUsable()) {
18794 ErrorFound = true;
18795 break;
18796 }
18797 Stack->setAllocator(AllocatorKind, Allocator: Res.get());
18798 }
18799 if (ErrorFound) {
18800 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found)
18801 << "omp_allocator_handle_t";
18802 return false;
18803 }
18804
18805 // Record the type only now. It is what tells a later call that the map above
18806 // is ready to be read, so setting it before the map is filled would let that
18807 // call proceed on a map this one gave up on halfway through.
18808 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
18809
18810 return true;
18811}
18812
18813OMPClause *SemaOpenMP::ActOnOpenMPAllocatorClause(Expr *A,
18814 SourceLocation StartLoc,
18815 SourceLocation LParenLoc,
18816 SourceLocation EndLoc) {
18817 // OpenMP [2.11.3, allocate Directive, Description]
18818 // allocator is an expression of omp_allocator_handle_t type.
18819 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: A->getExprLoc(), DSAStack))
18820 return nullptr;
18821
18822 ExprResult Allocator = SemaRef.DefaultLvalueConversion(E: A);
18823 if (Allocator.isInvalid())
18824 return nullptr;
18825 Allocator = SemaRef.PerformImplicitConversion(
18826 From: Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
18827 Action: AssignmentAction::Initializing,
18828 /*AllowExplicit=*/true);
18829 if (Allocator.isInvalid())
18830 return nullptr;
18831 return new (getASTContext())
18832 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
18833}
18834
18835OMPClause *SemaOpenMP::ActOnOpenMPCollapseClause(Expr *NumForLoops,
18836 SourceLocation StartLoc,
18837 SourceLocation LParenLoc,
18838 SourceLocation EndLoc) {
18839 // OpenMP [2.7.1, loop construct, Description]
18840 // OpenMP [2.8.1, simd construct, Description]
18841 // OpenMP [2.9.6, distribute construct, Description]
18842 // The parameter of the collapse clause must be a constant
18843 // positive integer expression.
18844 ExprResult NumForLoopsResult =
18845 VerifyPositiveIntegerConstantInClause(E: NumForLoops, CKind: OMPC_collapse);
18846 if (NumForLoopsResult.isInvalid())
18847 return nullptr;
18848 return new (getASTContext())
18849 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
18850}
18851
18852OMPClause *SemaOpenMP::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
18853 SourceLocation EndLoc,
18854 SourceLocation LParenLoc,
18855 Expr *NumForLoops) {
18856 // OpenMP [2.7.1, loop construct, Description]
18857 // OpenMP [2.8.1, simd construct, Description]
18858 // OpenMP [2.9.6, distribute construct, Description]
18859 // The parameter of the ordered clause must be a constant
18860 // positive integer expression if any.
18861 if (NumForLoops && LParenLoc.isValid()) {
18862 ExprResult NumForLoopsResult =
18863 VerifyPositiveIntegerConstantInClause(E: NumForLoops, CKind: OMPC_ordered);
18864 if (NumForLoopsResult.isInvalid())
18865 return nullptr;
18866 NumForLoops = NumForLoopsResult.get();
18867 } else {
18868 NumForLoops = nullptr;
18869 }
18870 auto *Clause =
18871 OMPOrderedClause::Create(C: getASTContext(), Num: NumForLoops,
18872 NumLoops: NumForLoops ? DSAStack->getAssociatedLoops() : 0,
18873 StartLoc, LParenLoc, EndLoc);
18874 DSAStack->setOrderedRegion(/*IsOrdered=*/true, Param: NumForLoops, Clause);
18875 return Clause;
18876}
18877
18878OMPClause *SemaOpenMP::ActOnOpenMPSimpleClause(
18879 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
18880 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
18881 OMPClause *Res = nullptr;
18882 switch (Kind) {
18883 case OMPC_proc_bind:
18884 Res = ActOnOpenMPProcBindClause(Kind: static_cast<ProcBindKind>(Argument),
18885 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
18886 break;
18887 case OMPC_atomic_default_mem_order:
18888 Res = ActOnOpenMPAtomicDefaultMemOrderClause(
18889 Kind: static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
18890 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
18891 break;
18892 case OMPC_fail:
18893 Res = ActOnOpenMPFailClause(Kind: static_cast<OpenMPClauseKind>(Argument),
18894 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
18895 break;
18896 case OMPC_update_depend_objects:
18897 Res = ActOnOpenMPUpdateDependObjectsClause(
18898 Kind: static_cast<OpenMPDependClauseKind>(Argument), KindLoc: ArgumentLoc, StartLoc,
18899 LParenLoc, EndLoc);
18900 break;
18901 case OMPC_bind:
18902 Res = ActOnOpenMPBindClause(Kind: static_cast<OpenMPBindClauseKind>(Argument),
18903 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
18904 break;
18905 case OMPC_at:
18906 Res = ActOnOpenMPAtClause(Kind: static_cast<OpenMPAtClauseKind>(Argument),
18907 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
18908 break;
18909 case OMPC_severity:
18910 Res = ActOnOpenMPSeverityClause(
18911 Kind: static_cast<OpenMPSeverityClauseKind>(Argument), KindLoc: ArgumentLoc, StartLoc,
18912 LParenLoc, EndLoc);
18913 break;
18914 case OMPC_threadset:
18915 Res = ActOnOpenMPThreadsetClause(Kind: static_cast<OpenMPThreadsetKind>(Argument),
18916 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
18917 break;
18918 case OMPC_if:
18919 case OMPC_final:
18920 case OMPC_num_threads:
18921 case OMPC_safelen:
18922 case OMPC_simdlen:
18923 case OMPC_sizes:
18924 case OMPC_depth:
18925 case OMPC_allocator:
18926 case OMPC_collapse:
18927 case OMPC_schedule:
18928 case OMPC_private:
18929 case OMPC_firstprivate:
18930 case OMPC_lastprivate:
18931 case OMPC_shared:
18932 case OMPC_reduction:
18933 case OMPC_task_reduction:
18934 case OMPC_in_reduction:
18935 case OMPC_linear:
18936 case OMPC_aligned:
18937 case OMPC_copyin:
18938 case OMPC_copyprivate:
18939 case OMPC_ordered:
18940 case OMPC_nowait:
18941 case OMPC_untied:
18942 case OMPC_mergeable:
18943 case OMPC_threadprivate:
18944 case OMPC_groupprivate:
18945 case OMPC_allocate:
18946 case OMPC_flush:
18947 case OMPC_depobj:
18948 case OMPC_read:
18949 case OMPC_write:
18950 case OMPC_capture:
18951 case OMPC_compare:
18952 case OMPC_update:
18953 case OMPC_seq_cst:
18954 case OMPC_acq_rel:
18955 case OMPC_acquire:
18956 case OMPC_release:
18957 case OMPC_relaxed:
18958 case OMPC_depend:
18959 case OMPC_device:
18960 case OMPC_threads:
18961 case OMPC_simd:
18962 case OMPC_map:
18963 case OMPC_num_teams:
18964 case OMPC_thread_limit:
18965 case OMPC_priority:
18966 case OMPC_grainsize:
18967 case OMPC_nogroup:
18968 case OMPC_num_tasks:
18969 case OMPC_hint:
18970 case OMPC_dist_schedule:
18971 case OMPC_default:
18972 case OMPC_defaultmap:
18973 case OMPC_unknown:
18974 case OMPC_uniform:
18975 case OMPC_to:
18976 case OMPC_from:
18977 case OMPC_use_device_ptr:
18978 case OMPC_use_device_addr:
18979 case OMPC_is_device_ptr:
18980 case OMPC_has_device_addr:
18981 case OMPC_unified_address:
18982 case OMPC_unified_shared_memory:
18983 case OMPC_reverse_offload:
18984 case OMPC_dynamic_allocators:
18985 case OMPC_self_maps:
18986 case OMPC_device_type:
18987 case OMPC_match:
18988 case OMPC_nontemporal:
18989 case OMPC_destroy:
18990 case OMPC_novariants:
18991 case OMPC_nocontext:
18992 case OMPC_detach:
18993 case OMPC_inclusive:
18994 case OMPC_exclusive:
18995 case OMPC_uses_allocators:
18996 case OMPC_affinity:
18997 case OMPC_when:
18998 case OMPC_message:
18999 default:
19000 llvm_unreachable("Clause is not allowed.");
19001 }
19002 return Res;
19003}
19004
19005OMPClause *SemaOpenMP::ActOnOpenMPDefaultClause(
19006 llvm::omp::DefaultKind M, SourceLocation MLoc,
19007 OpenMPDefaultClauseVariableCategory VCKind, SourceLocation VCKindLoc,
19008 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
19009 if (M == OMP_DEFAULT_unknown) {
19010 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
19011 << getListOfPossibleValues(K: OMPC_default, /*First=*/0,
19012 /*Last=*/unsigned(OMP_DEFAULT_unknown))
19013 << getOpenMPClauseNameForDiag(C: OMPC_default);
19014 return nullptr;
19015 }
19016 if (VCKind == OMPC_DEFAULT_VC_unknown) {
19017 Diag(Loc: VCKindLoc, DiagID: diag::err_omp_default_vc)
19018 << getOpenMPSimpleClauseTypeName(Kind: OMPC_default, Type: unsigned(M));
19019 return nullptr;
19020 }
19021
19022 bool IsTargetDefault =
19023 getLangOpts().OpenMP >= 60 &&
19024 isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective());
19025
19026 // OpenMP 6.0, page 224, lines 3-4 default Clause, Semantics
19027 // If data-sharing-attribute is shared then the clause has no effect
19028 // on a target construct;
19029 if (IsTargetDefault && M == OMP_DEFAULT_shared)
19030 return nullptr;
19031
19032 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
19033 OpenMPDefaultClauseVariableCategory VCKind) {
19034 OpenMPDefaultmapClauseModifier DefMapMod;
19035 OpenMPDefaultmapClauseKind DefMapKind;
19036 // default data-sharing-attribute
19037 switch (M) {
19038 case OMP_DEFAULT_none:
19039 if (IsTargetDefault)
19040 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
19041 else
19042 DSAStack->setDefaultDSANone(MLoc);
19043 break;
19044 case OMP_DEFAULT_firstprivate:
19045 if (IsTargetDefault)
19046 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
19047 else
19048 DSAStack->setDefaultDSAFirstPrivate(MLoc);
19049 break;
19050 case OMP_DEFAULT_private:
19051 if (IsTargetDefault)
19052 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
19053 else
19054 DSAStack->setDefaultDSAPrivate(MLoc);
19055 break;
19056 case OMP_DEFAULT_shared:
19057 assert(!IsTargetDefault && "DSA shared invalid with target directive");
19058 DSAStack->setDefaultDSAShared(MLoc);
19059 break;
19060 default:
19061 llvm_unreachable("unexpected DSA in OpenMP default clause");
19062 }
19063 // default variable-category
19064 switch (VCKind) {
19065 case OMPC_DEFAULT_VC_aggregate:
19066 if (IsTargetDefault)
19067 DefMapKind = OMPC_DEFAULTMAP_aggregate;
19068 else
19069 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
19070 break;
19071 case OMPC_DEFAULT_VC_pointer:
19072 if (IsTargetDefault)
19073 DefMapKind = OMPC_DEFAULTMAP_pointer;
19074 else
19075 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
19076 break;
19077 case OMPC_DEFAULT_VC_scalar:
19078 if (IsTargetDefault)
19079 DefMapKind = OMPC_DEFAULTMAP_scalar;
19080 else
19081 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
19082 break;
19083 case OMPC_DEFAULT_VC_all:
19084 if (IsTargetDefault)
19085 DefMapKind = OMPC_DEFAULTMAP_all;
19086 else
19087 DSAStack->setDefaultDSAVCAll(VCKindLoc);
19088 break;
19089 default:
19090 llvm_unreachable("unexpected variable category in OpenMP default clause");
19091 }
19092 // OpenMP 6.0, page 224, lines 4-5 default Clause, Semantics
19093 // otherwise, its effect on a target construct is equivalent to
19094 // specifying the defaultmap clause with the same data-sharing-attribute
19095 // and variable-category.
19096 //
19097 // If earlier than OpenMP 6.0, or not a target directive, the default DSA
19098 // is/was set as before.
19099 if (IsTargetDefault) {
19100 if (DefMapKind == OMPC_DEFAULTMAP_all) {
19101 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: OMPC_DEFAULTMAP_aggregate, Loc: MLoc);
19102 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: OMPC_DEFAULTMAP_scalar, Loc: MLoc);
19103 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: OMPC_DEFAULTMAP_pointer, Loc: MLoc);
19104 } else {
19105 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: DefMapKind, Loc: MLoc);
19106 }
19107 }
19108 };
19109
19110 SetDefaultClauseAttrs(M, VCKind);
19111 return new (getASTContext())
19112 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
19113}
19114
19115OMPClause *SemaOpenMP::ActOnOpenMPThreadsetClause(OpenMPThreadsetKind Kind,
19116 SourceLocation KindLoc,
19117 SourceLocation StartLoc,
19118 SourceLocation LParenLoc,
19119 SourceLocation EndLoc) {
19120 if (Kind == OMPC_THREADSET_unknown) {
19121 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
19122 << getListOfPossibleValues(K: OMPC_threadset, /*First=*/0,
19123 /*Last=*/unsigned(OMPC_THREADSET_unknown))
19124 << getOpenMPClauseName(C: OMPC_threadset);
19125 return nullptr;
19126 }
19127
19128 return new (getASTContext())
19129 OMPThreadsetClause(Kind, KindLoc, StartLoc, LParenLoc, EndLoc);
19130}
19131
19132static OMPClause *
19133createTransparentClause(Sema &SemaRef, ASTContext &Ctx, Expr *ImpexTypeArg,
19134 Stmt *HelperValStmt, OpenMPDirectiveKind CaptureRegion,
19135 SourceLocation StartLoc, SourceLocation LParenLoc,
19136 SourceLocation EndLoc) {
19137 ExprResult ER = SemaRef.DefaultLvalueConversion(E: ImpexTypeArg);
19138 if (ER.isInvalid())
19139 return nullptr;
19140
19141 return new (Ctx) OMPTransparentClause(ER.get(), HelperValStmt, CaptureRegion,
19142 StartLoc, LParenLoc, EndLoc);
19143}
19144
19145OMPClause *SemaOpenMP::ActOnOpenMPTransparentClause(Expr *ImpexTypeArg,
19146 SourceLocation StartLoc,
19147 SourceLocation LParenLoc,
19148 SourceLocation EndLoc) {
19149 Stmt *HelperValStmt = nullptr;
19150 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19151 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
19152 DKind, CKind: OMPC_transparent, OMPVersion: getLangOpts().getOpenMPVersion());
19153 if (CaptureRegion != OMPD_unknown &&
19154 !SemaRef.CurContext->isDependentContext()) {
19155 Expr *ValExpr = SemaRef.MakeFullExpr(Arg: ImpexTypeArg).get();
19156 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19157 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
19158 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
19159 }
19160 if (!ImpexTypeArg) {
19161 return new (getASTContext())
19162 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
19163 StartLoc, LParenLoc, EndLoc);
19164 }
19165 QualType Ty = ImpexTypeArg->getType();
19166
19167 if (const auto *TT = Ty->getAs<TypedefType>()) {
19168 const TypedefNameDecl *TypedefDecl = TT->getDecl();
19169 llvm::StringRef TypedefName = TypedefDecl->getName();
19170 IdentifierInfo &II = SemaRef.PP.getIdentifierTable().get(Name: TypedefName);
19171 ParsedType ImpexTy =
19172 SemaRef.getTypeName(II, NameLoc: StartLoc, S: SemaRef.getCurScope());
19173 if (!ImpexTy.getAsOpaquePtr() || ImpexTy.get().isNull()) {
19174 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_implied_type_not_found)
19175 << TypedefName;
19176 return nullptr;
19177 }
19178 return new (getASTContext())
19179 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
19180 StartLoc, LParenLoc, EndLoc);
19181 }
19182
19183 if (Ty->isEnumeralType())
19184 return createTransparentClause(SemaRef, Ctx&: getASTContext(), ImpexTypeArg,
19185 HelperValStmt, CaptureRegion, StartLoc,
19186 LParenLoc, EndLoc);
19187 if (Ty->isIntegerType()) {
19188 if (isNonNegativeIntegerValue(ValExpr&: ImpexTypeArg, SemaRef, CKind: OMPC_transparent,
19189 /*StrictlyPositive=*/false)) {
19190 ExprResult Value =
19191 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc: StartLoc,
19192 Op: ImpexTypeArg);
19193 if (std::optional<llvm::APSInt> Result =
19194 Value.get()->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
19195 if (Result->isNegative() ||
19196 Result >
19197 static_cast<int64_t>(SemaOpenMP::OpenMPImpexType::OMP_Export))
19198 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_transparent_invalid_value);
19199 }
19200 return new (getASTContext())
19201 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
19202 StartLoc, LParenLoc, EndLoc);
19203 }
19204 }
19205 if (!isNonNegativeIntegerValue(ValExpr&: ImpexTypeArg, SemaRef, CKind: OMPC_transparent,
19206 /*StrictlyPositive=*/true))
19207 return nullptr;
19208 return new (getASTContext()) OMPTransparentClause(
19209 ImpexTypeArg, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19210}
19211
19212OMPClause *SemaOpenMP::ActOnOpenMPProcBindClause(ProcBindKind Kind,
19213 SourceLocation KindKwLoc,
19214 SourceLocation StartLoc,
19215 SourceLocation LParenLoc,
19216 SourceLocation EndLoc) {
19217 if (Kind == OMP_PROC_BIND_unknown) {
19218 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
19219 << getListOfPossibleValues(K: OMPC_proc_bind,
19220 /*First=*/unsigned(OMP_PROC_BIND_master),
19221 /*Last=*/
19222 unsigned(getLangOpts().OpenMP > 50
19223 ? OMP_PROC_BIND_primary
19224 : OMP_PROC_BIND_spread) +
19225 1)
19226 << getOpenMPClauseNameForDiag(C: OMPC_proc_bind);
19227 return nullptr;
19228 }
19229 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
19230 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
19231 << getListOfPossibleValues(K: OMPC_proc_bind,
19232 /*First=*/unsigned(OMP_PROC_BIND_master),
19233 /*Last=*/
19234 unsigned(OMP_PROC_BIND_spread) + 1)
19235 << getOpenMPClauseNameForDiag(C: OMPC_proc_bind);
19236 return new (getASTContext())
19237 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
19238}
19239
19240OMPClause *SemaOpenMP::ActOnOpenMPAtomicDefaultMemOrderClause(
19241 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
19242 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
19243 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
19244 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
19245 << getListOfPossibleValues(
19246 K: OMPC_atomic_default_mem_order, /*First=*/0,
19247 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
19248 << getOpenMPClauseNameForDiag(C: OMPC_atomic_default_mem_order);
19249 return nullptr;
19250 }
19251 return new (getASTContext()) OMPAtomicDefaultMemOrderClause(
19252 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
19253}
19254
19255OMPClause *SemaOpenMP::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
19256 SourceLocation KindKwLoc,
19257 SourceLocation StartLoc,
19258 SourceLocation LParenLoc,
19259 SourceLocation EndLoc) {
19260 if (Kind == OMPC_AT_unknown) {
19261 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
19262 << getListOfPossibleValues(K: OMPC_at, /*First=*/0,
19263 /*Last=*/OMPC_AT_unknown)
19264 << getOpenMPClauseNameForDiag(C: OMPC_at);
19265 return nullptr;
19266 }
19267 return new (getASTContext())
19268 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
19269}
19270
19271OMPClause *SemaOpenMP::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
19272 SourceLocation KindKwLoc,
19273 SourceLocation StartLoc,
19274 SourceLocation LParenLoc,
19275 SourceLocation EndLoc) {
19276 if (Kind == OMPC_SEVERITY_unknown) {
19277 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
19278 << getListOfPossibleValues(K: OMPC_severity, /*First=*/0,
19279 /*Last=*/OMPC_SEVERITY_unknown)
19280 << getOpenMPClauseNameForDiag(C: OMPC_severity);
19281 return nullptr;
19282 }
19283 return new (getASTContext())
19284 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
19285}
19286
19287OMPClause *SemaOpenMP::ActOnOpenMPMessageClause(Expr *ME,
19288 SourceLocation StartLoc,
19289 SourceLocation LParenLoc,
19290 SourceLocation EndLoc) {
19291 assert(ME && "NULL expr in Message clause");
19292 QualType Type = ME->getType();
19293 if ((!Type->isPointerType() && !Type->isArrayType()) ||
19294 !Type->getPointeeOrArrayElementType()->isAnyCharacterType()) {
19295 Diag(Loc: ME->getBeginLoc(), DiagID: diag::warn_clause_expected_string)
19296 << getOpenMPClauseNameForDiag(C: OMPC_message) << 0;
19297 return nullptr;
19298 }
19299
19300 Stmt *HelperValStmt = nullptr;
19301
19302 // Depending on whether this clause appears in an executable context or not,
19303 // we may or may not build a capture.
19304 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19305 OpenMPDirectiveKind CaptureRegion =
19306 DKind == OMPD_unknown
19307 ? OMPD_unknown
19308 : getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_message,
19309 OMPVersion: getLangOpts().getOpenMPVersion());
19310 if (CaptureRegion != OMPD_unknown &&
19311 !SemaRef.CurContext->isDependentContext()) {
19312 ME = SemaRef.MakeFullExpr(Arg: ME).get();
19313 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19314 ME = tryBuildCapture(SemaRef, Capture: ME, Captures).get();
19315 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
19316 }
19317
19318 // Convert array type to pointer type if needed.
19319 ME = SemaRef.DefaultFunctionArrayLvalueConversion(E: ME).get();
19320
19321 return new (getASTContext()) OMPMessageClause(
19322 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19323}
19324
19325OMPClause *SemaOpenMP::ActOnOpenMPOrderClause(
19326 OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind,
19327 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
19328 SourceLocation KindLoc, SourceLocation EndLoc) {
19329 if (Kind != OMPC_ORDER_concurrent ||
19330 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
19331 // Kind should be concurrent,
19332 // Modifiers introduced in OpenMP 5.1
19333 static_assert(OMPC_ORDER_unknown > 0,
19334 "OMPC_ORDER_unknown not greater than 0");
19335
19336 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
19337 << getListOfPossibleValues(K: OMPC_order,
19338 /*First=*/0,
19339 /*Last=*/OMPC_ORDER_unknown)
19340 << getOpenMPClauseNameForDiag(C: OMPC_order);
19341 return nullptr;
19342 }
19343 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
19344 MLoc.isValid()) {
19345 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
19346 << getListOfPossibleValues(K: OMPC_order,
19347 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
19348 /*Last=*/OMPC_ORDER_MODIFIER_last)
19349 << getOpenMPClauseNameForDiag(C: OMPC_order);
19350 } else if (getLangOpts().OpenMP >= 50) {
19351 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
19352 if (DSAStack->getCurScope()) {
19353 // mark the current scope with 'order' flag
19354 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
19355 DSAStack->getCurScope()->setFlags(existingFlags |
19356 Scope::OpenMPOrderClauseScope);
19357 }
19358 }
19359 return new (getASTContext()) OMPOrderClause(
19360 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
19361}
19362
19363OMPClause *SemaOpenMP::ActOnOpenMPUpdateDependObjectsClause(
19364 OpenMPDependClauseKind Kind, SourceLocation KindKwLoc,
19365 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
19366 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
19367 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
19368 SmallVector<unsigned> Except = {
19369 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
19370 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
19371 if (getLangOpts().OpenMP < 51)
19372 Except.push_back(Elt: OMPC_DEPEND_inoutset);
19373 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
19374 << getListOfPossibleValues(K: OMPC_depend, /*First=*/0,
19375 /*Last=*/OMPC_DEPEND_unknown, Exclude: Except)
19376 << getOpenMPClauseNameForDiag(C: OMPC_update_depend_objects);
19377 return nullptr;
19378 }
19379 return OMPUpdateDependObjectsClause::Create(
19380 C: getASTContext(), StartLoc, LParenLoc, ArgumentLoc: KindKwLoc, DK: Kind, EndLoc);
19381}
19382
19383OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
19384 SourceLocation StartLoc,
19385 SourceLocation LParenLoc,
19386 SourceLocation EndLoc) {
19387 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
19388
19389 for (Expr *&SizeExpr : SanitizedSizeExprs) {
19390 // Skip if already sanitized, e.g. during a partial template instantiation.
19391 if (!SizeExpr)
19392 continue;
19393
19394 bool IsValid = isNonNegativeIntegerValue(ValExpr&: SizeExpr, SemaRef, CKind: OMPC_sizes,
19395 /*StrictlyPositive=*/true);
19396
19397 // isNonNegativeIntegerValue returns true for non-integral types (but still
19398 // emits error diagnostic), so check for the expected type explicitly.
19399 QualType SizeTy = SizeExpr->getType();
19400 if (!SizeTy->isIntegerType())
19401 IsValid = false;
19402
19403 // Handling in templates is tricky. There are four possibilities to
19404 // consider:
19405 //
19406 // 1a. The expression is valid and we are in a instantiated template or not
19407 // in a template:
19408 // Pass valid expression to be further analysed later in Sema.
19409 // 1b. The expression is valid and we are in a template (including partial
19410 // instantiation):
19411 // isNonNegativeIntegerValue skipped any checks so there is no
19412 // guarantee it will be correct after instantiation.
19413 // ActOnOpenMPSizesClause will be called again at instantiation when
19414 // it is not in a dependent context anymore. This may cause warnings
19415 // to be emitted multiple times.
19416 // 2a. The expression is invalid and we are in an instantiated template or
19417 // not in a template:
19418 // Invalidate the expression with a clearly wrong value (nullptr) so
19419 // later in Sema we do not have to do the same validity analysis again
19420 // or crash from unexpected data. Error diagnostics have already been
19421 // emitted.
19422 // 2b. The expression is invalid and we are in a template (including partial
19423 // instantiation):
19424 // Pass the invalid expression as-is, template instantiation may
19425 // replace unexpected types/values with valid ones. The directives
19426 // with this clause must not try to use these expressions in dependent
19427 // contexts, but delay analysis until full instantiation.
19428 if (!SizeExpr->isInstantiationDependent() && !IsValid)
19429 SizeExpr = nullptr;
19430 }
19431
19432 return OMPSizesClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
19433 Sizes: SanitizedSizeExprs);
19434}
19435
19436OMPClause *SemaOpenMP::ActOnOpenMPCountsClause(ArrayRef<Expr *> CountExprs,
19437 SourceLocation StartLoc,
19438 SourceLocation LParenLoc,
19439 SourceLocation EndLoc,
19440 std::optional<unsigned> FillIdx,
19441 SourceLocation FillLoc,
19442 unsigned FillCount) {
19443 SmallVector<Expr *> SanitizedCountExprs(CountExprs);
19444
19445 // OpenMP 6.0: each list item in counts(...) is either the omp_fill keyword
19446 // or an integral constant expression (non-negative). Runtime variables are
19447 // not permitted; this matches split codegen, which needs segment sizes at
19448 // compile time.
19449 for (unsigned I = 0; I < SanitizedCountExprs.size(); ++I) {
19450 Expr *&CountExpr = SanitizedCountExprs[I];
19451 if (FillIdx && I == *FillIdx)
19452 continue;
19453 if (!CountExpr)
19454 continue;
19455
19456 ExprResult Verified = VerifyPositiveIntegerConstantInClause(
19457 E: CountExpr, CKind: OMPC_counts, /*StrictlyPositive=*/false);
19458 if (Verified.isInvalid())
19459 CountExpr = nullptr;
19460 else
19461 CountExpr = Verified.get();
19462 }
19463
19464 if (FillCount != 1) {
19465 Diag(Loc: FillCount == 0 ? StartLoc : FillLoc,
19466 DiagID: diag::err_omp_split_counts_not_one_omp_fill);
19467 }
19468
19469 return OMPCountsClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
19470 Counts: SanitizedCountExprs, FillIdx, FillLoc);
19471}
19472
19473OMPClause *SemaOpenMP::ActOnOpenMPPermutationClause(ArrayRef<Expr *> PermExprs,
19474 SourceLocation StartLoc,
19475 SourceLocation LParenLoc,
19476 SourceLocation EndLoc) {
19477 size_t NumLoops = PermExprs.size();
19478 SmallVector<Expr *> SanitizedPermExprs;
19479 llvm::append_range(C&: SanitizedPermExprs, R&: PermExprs);
19480
19481 for (Expr *&PermExpr : SanitizedPermExprs) {
19482 // Skip if template-dependent or already sanitized, e.g. during a partial
19483 // template instantiation.
19484 if (!PermExpr || PermExpr->isInstantiationDependent())
19485 continue;
19486
19487 llvm::APSInt PermVal;
19488 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
19489 E: PermExpr, Result: &PermVal, CanFold: AllowFoldKind::Allow);
19490 bool IsValid = PermEvalExpr.isUsable();
19491 if (IsValid)
19492 PermExpr = PermEvalExpr.get();
19493
19494 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
19495 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
19496 PermEvalExpr.get()->getEndLoc());
19497 Diag(Loc: PermEvalExpr.get()->getExprLoc(),
19498 DiagID: diag::err_omp_interchange_permutation_value_range)
19499 << NumLoops << ExprRange;
19500 IsValid = false;
19501 }
19502
19503 if (!PermExpr->isInstantiationDependent() && !IsValid)
19504 PermExpr = nullptr;
19505 }
19506
19507 return OMPPermutationClause::Create(C: getASTContext(), StartLoc, LParenLoc,
19508 EndLoc, Args: SanitizedPermExprs);
19509}
19510
19511OMPClause *SemaOpenMP::ActOnOpenMPFullClause(SourceLocation StartLoc,
19512 SourceLocation EndLoc) {
19513 return new (getASTContext()) OMPFullClause(StartLoc, EndLoc);
19514}
19515
19516OMPClause *SemaOpenMP::ActOnOpenMPPartialClause(Expr *FactorExpr,
19517 SourceLocation StartLoc,
19518 SourceLocation LParenLoc,
19519 SourceLocation EndLoc) {
19520 if (FactorExpr) {
19521 // If an argument is specified, it must be a constant (or an unevaluated
19522 // template expression).
19523 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
19524 E: FactorExpr, CKind: OMPC_partial, /*StrictlyPositive=*/true);
19525 if (FactorResult.isInvalid())
19526 return nullptr;
19527 FactorExpr = FactorResult.get();
19528 }
19529
19530 return new (getASTContext())
19531 OMPPartialClause(StartLoc, LParenLoc, EndLoc, FactorExpr);
19532}
19533
19534OMPClause *SemaOpenMP::ActOnOpenMPDepthClause(Expr *DepthExpr,
19535 SourceLocation StartLoc,
19536 SourceLocation LParenLoc,
19537 SourceLocation EndLoc) {
19538 // The depth-expr must be a positive integer constant expression and
19539 // not greater than the number of loops in the associated loop nest.
19540 ExprResult DepthResult = VerifyPositiveIntegerConstantInClause(
19541 E: DepthExpr, CKind: OMPC_depth, /*StrictlyPositive=*/true);
19542 if (DepthResult.isInvalid())
19543 return nullptr;
19544 DepthExpr = DepthResult.get();
19545
19546 return new (getASTContext())
19547 OMPDepthClause(StartLoc, LParenLoc, EndLoc, DepthExpr);
19548}
19549
19550OMPClause *SemaOpenMP::ActOnOpenMPLoopRangeClause(
19551 Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc,
19552 SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc) {
19553
19554 // OpenMP [6.0, Restrictions]
19555 // First and Count must be integer expressions with positive value
19556 ExprResult FirstVal =
19557 VerifyPositiveIntegerConstantInClause(E: First, CKind: OMPC_looprange);
19558 if (FirstVal.isInvalid())
19559 First = nullptr;
19560
19561 ExprResult CountVal =
19562 VerifyPositiveIntegerConstantInClause(E: Count, CKind: OMPC_looprange);
19563 if (CountVal.isInvalid())
19564 Count = nullptr;
19565
19566 // OpenMP [6.0, Restrictions]
19567 // first + count - 1 must not evaluate to a value greater than the
19568 // loop sequence length of the associated canonical loop sequence.
19569 // This check must be performed afterwards due to the delayed
19570 // parsing and computation of the associated loop sequence
19571 return new (getASTContext()) OMPLoopRangeClause(
19572 StartLoc, LParenLoc, FirstLoc, CountLoc, EndLoc, First, Count);
19573}
19574
19575OMPClause *SemaOpenMP::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
19576 SourceLocation LParenLoc,
19577 SourceLocation EndLoc) {
19578 ExprResult AlignVal;
19579 AlignVal = VerifyPositiveIntegerConstantInClause(E: A, CKind: OMPC_align);
19580 if (AlignVal.isInvalid())
19581 return nullptr;
19582 return new (getASTContext())
19583 OMPAlignClause(AlignVal.get(), StartLoc, LParenLoc, EndLoc);
19584}
19585
19586OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause(
19587 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
19588 SourceLocation StartLoc, SourceLocation LParenLoc,
19589 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
19590 SourceLocation EndLoc) {
19591 OMPClause *Res = nullptr;
19592 switch (Kind) {
19593 case OMPC_schedule: {
19594 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
19595 assert(Argument.size() == NumberOfElements &&
19596 ArgumentLoc.size() == NumberOfElements);
19597 Res = ActOnOpenMPScheduleClause(
19598 M1: static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
19599 M2: static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
19600 Kind: static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), ChunkSize: Expr,
19601 StartLoc, LParenLoc, M1Loc: ArgumentLoc[Modifier1], M2Loc: ArgumentLoc[Modifier2],
19602 KindLoc: ArgumentLoc[ScheduleKind], CommaLoc: DelimLoc, EndLoc);
19603 break;
19604 }
19605 case OMPC_if:
19606 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
19607 Res = ActOnOpenMPIfClause(NameModifier: static_cast<OpenMPDirectiveKind>(Argument.back()),
19608 Condition: Expr, StartLoc, LParenLoc, NameModifierLoc: ArgumentLoc.back(),
19609 ColonLoc: DelimLoc, EndLoc);
19610 break;
19611 case OMPC_dist_schedule:
19612 Res = ActOnOpenMPDistScheduleClause(
19613 Kind: static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), ChunkSize: Expr,
19614 StartLoc, LParenLoc, KindLoc: ArgumentLoc.back(), CommaLoc: DelimLoc, EndLoc);
19615 break;
19616 case OMPC_default:
19617 enum { DefaultModifier, DefaultVarCategory };
19618 Res = ActOnOpenMPDefaultClause(
19619 M: static_cast<llvm::omp::DefaultKind>(Argument[DefaultModifier]),
19620 MLoc: ArgumentLoc[DefaultModifier],
19621 VCKind: static_cast<OpenMPDefaultClauseVariableCategory>(
19622 Argument[DefaultVarCategory]),
19623 VCKindLoc: ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
19624 break;
19625 case OMPC_defaultmap:
19626 enum { Modifier, DefaultmapKind };
19627 Res = ActOnOpenMPDefaultmapClause(
19628 M: static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
19629 Kind: static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
19630 StartLoc, LParenLoc, MLoc: ArgumentLoc[Modifier], KindLoc: ArgumentLoc[DefaultmapKind],
19631 EndLoc);
19632 break;
19633 case OMPC_order:
19634 enum { OrderModifier, OrderKind };
19635 Res = ActOnOpenMPOrderClause(
19636 Modifier: static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
19637 Kind: static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
19638 LParenLoc, MLoc: ArgumentLoc[OrderModifier], KindLoc: ArgumentLoc[OrderKind], EndLoc);
19639 break;
19640 case OMPC_device:
19641 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
19642 Res = ActOnOpenMPDeviceClause(
19643 Modifier: static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Device: Expr,
19644 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
19645 break;
19646 case OMPC_grainsize:
19647 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
19648 "Modifier for grainsize clause and its location are expected.");
19649 Res = ActOnOpenMPGrainsizeClause(
19650 Modifier: static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Size: Expr,
19651 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
19652 break;
19653 case OMPC_num_tasks:
19654 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
19655 "Modifier for num_tasks clause and its location are expected.");
19656 Res = ActOnOpenMPNumTasksClause(
19657 Modifier: static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), NumTasks: Expr,
19658 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
19659 break;
19660 case OMPC_dyn_groupprivate: {
19661 enum { Modifier1, Modifier2, NumberOfElements };
19662 assert(Argument.size() == NumberOfElements &&
19663 ArgumentLoc.size() == NumberOfElements &&
19664 "Modifiers for dyn_groupprivate clause and their locations are "
19665 "expected.");
19666 Res = ActOnOpenMPDynGroupprivateClause(
19667 M1: static_cast<OpenMPDynGroupprivateClauseModifier>(Argument[Modifier1]),
19668 M2: static_cast<OpenMPDynGroupprivateClauseFallbackModifier>(
19669 Argument[Modifier2]),
19670 Size: Expr, StartLoc, LParenLoc, M1Loc: ArgumentLoc[Modifier1],
19671 M2Loc: ArgumentLoc[Modifier2], EndLoc);
19672 break;
19673 }
19674 case OMPC_final:
19675 case OMPC_safelen:
19676 case OMPC_simdlen:
19677 case OMPC_sizes:
19678 case OMPC_depth:
19679 case OMPC_allocator:
19680 case OMPC_collapse:
19681 case OMPC_proc_bind:
19682 case OMPC_private:
19683 case OMPC_firstprivate:
19684 case OMPC_lastprivate:
19685 case OMPC_shared:
19686 case OMPC_reduction:
19687 case OMPC_task_reduction:
19688 case OMPC_in_reduction:
19689 case OMPC_linear:
19690 case OMPC_aligned:
19691 case OMPC_copyin:
19692 case OMPC_copyprivate:
19693 case OMPC_ordered:
19694 case OMPC_nowait:
19695 case OMPC_untied:
19696 case OMPC_mergeable:
19697 case OMPC_threadprivate:
19698 case OMPC_groupprivate:
19699 case OMPC_allocate:
19700 case OMPC_flush:
19701 case OMPC_depobj:
19702 case OMPC_read:
19703 case OMPC_write:
19704 case OMPC_update:
19705 case OMPC_capture:
19706 case OMPC_compare:
19707 case OMPC_seq_cst:
19708 case OMPC_acq_rel:
19709 case OMPC_acquire:
19710 case OMPC_release:
19711 case OMPC_relaxed:
19712 case OMPC_depend:
19713 case OMPC_threads:
19714 case OMPC_simd:
19715 case OMPC_map:
19716 case OMPC_num_teams:
19717 case OMPC_thread_limit:
19718 case OMPC_priority:
19719 case OMPC_nogroup:
19720 case OMPC_hint:
19721 case OMPC_unknown:
19722 case OMPC_uniform:
19723 case OMPC_to:
19724 case OMPC_from:
19725 case OMPC_use_device_ptr:
19726 case OMPC_use_device_addr:
19727 case OMPC_is_device_ptr:
19728 case OMPC_has_device_addr:
19729 case OMPC_unified_address:
19730 case OMPC_unified_shared_memory:
19731 case OMPC_reverse_offload:
19732 case OMPC_dynamic_allocators:
19733 case OMPC_atomic_default_mem_order:
19734 case OMPC_self_maps:
19735 case OMPC_device_type:
19736 case OMPC_match:
19737 case OMPC_nontemporal:
19738 case OMPC_at:
19739 case OMPC_severity:
19740 case OMPC_message:
19741 case OMPC_destroy:
19742 case OMPC_novariants:
19743 case OMPC_nocontext:
19744 case OMPC_detach:
19745 case OMPC_inclusive:
19746 case OMPC_exclusive:
19747 case OMPC_uses_allocators:
19748 case OMPC_affinity:
19749 case OMPC_when:
19750 case OMPC_bind:
19751 default:
19752 llvm_unreachable("Clause is not allowed.");
19753 }
19754 return Res;
19755}
19756
19757static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
19758 OpenMPScheduleClauseModifier M2,
19759 SourceLocation M1Loc, SourceLocation M2Loc) {
19760 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
19761 SmallVector<unsigned, 2> Excluded;
19762 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
19763 Excluded.push_back(Elt: M2);
19764 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
19765 Excluded.push_back(Elt: OMPC_SCHEDULE_MODIFIER_monotonic);
19766 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
19767 Excluded.push_back(Elt: OMPC_SCHEDULE_MODIFIER_nonmonotonic);
19768 S.Diag(Loc: M1Loc, DiagID: diag::err_omp_unexpected_clause_value)
19769 << getListOfPossibleValues(K: OMPC_schedule,
19770 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
19771 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
19772 Exclude: Excluded)
19773 << getOpenMPClauseNameForDiag(C: OMPC_schedule);
19774 return true;
19775 }
19776 return false;
19777}
19778
19779OMPClause *SemaOpenMP::ActOnOpenMPScheduleClause(
19780 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
19781 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
19782 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
19783 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
19784 if (checkScheduleModifiers(S&: SemaRef, M1, M2, M1Loc, M2Loc) ||
19785 checkScheduleModifiers(S&: SemaRef, M1: M2, M2: M1, M1Loc: M2Loc, M2Loc: M1Loc))
19786 return nullptr;
19787 // OpenMP, 2.7.1, Loop Construct, Restrictions
19788 // Either the monotonic modifier or the nonmonotonic modifier can be specified
19789 // but not both.
19790 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
19791 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
19792 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
19793 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
19794 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
19795 Diag(Loc: M2Loc, DiagID: diag::err_omp_unexpected_schedule_modifier)
19796 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule, Type: M2)
19797 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule, Type: M1);
19798 return nullptr;
19799 }
19800 if (Kind == OMPC_SCHEDULE_unknown) {
19801 std::string Values;
19802 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
19803 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
19804 Values = getListOfPossibleValues(K: OMPC_schedule, /*First=*/0,
19805 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
19806 Exclude);
19807 } else {
19808 Values = getListOfPossibleValues(K: OMPC_schedule, /*First=*/0,
19809 /*Last=*/OMPC_SCHEDULE_unknown);
19810 }
19811 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
19812 << Values << getOpenMPClauseNameForDiag(C: OMPC_schedule);
19813 return nullptr;
19814 }
19815 // OpenMP, 2.7.1, Loop Construct, Restrictions
19816 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
19817 // schedule(guided).
19818 // OpenMP 5.0 does not have this restriction.
19819 if (getLangOpts().OpenMP < 50 &&
19820 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
19821 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
19822 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
19823 Diag(Loc: M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
19824 DiagID: diag::err_omp_schedule_nonmonotonic_static);
19825 return nullptr;
19826 }
19827 Expr *ValExpr = ChunkSize;
19828 Stmt *HelperValStmt = nullptr;
19829 if (ChunkSize) {
19830 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
19831 !ChunkSize->isInstantiationDependent() &&
19832 !ChunkSize->containsUnexpandedParameterPack()) {
19833 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
19834 ExprResult Val =
19835 PerformOpenMPImplicitIntegerConversion(Loc: ChunkSizeLoc, Op: ChunkSize);
19836 if (Val.isInvalid())
19837 return nullptr;
19838
19839 ValExpr = Val.get();
19840
19841 // OpenMP [2.7.1, Restrictions]
19842 // chunk_size must be a loop invariant integer expression with a positive
19843 // value.
19844 if (std::optional<llvm::APSInt> Result =
19845 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
19846 if (Result->isSigned() && !Result->isStrictlyPositive()) {
19847 Diag(Loc: ChunkSizeLoc, DiagID: diag::err_omp_negative_expression_in_clause)
19848 << "schedule" << 1 << ChunkSize->getSourceRange();
19849 return nullptr;
19850 }
19851 } else if (getOpenMPCaptureRegionForClause(
19852 DSAStack->getCurrentDirective(), CKind: OMPC_schedule,
19853 OMPVersion: getLangOpts().getOpenMPVersion()) != OMPD_unknown &&
19854 !SemaRef.CurContext->isDependentContext()) {
19855 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
19856 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19857 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
19858 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
19859 }
19860 }
19861 }
19862
19863 return new (getASTContext())
19864 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
19865 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
19866}
19867
19868OMPClause *SemaOpenMP::ActOnOpenMPClause(OpenMPClauseKind Kind,
19869 SourceLocation StartLoc,
19870 SourceLocation EndLoc) {
19871 OMPClause *Res = nullptr;
19872 switch (Kind) {
19873 case OMPC_ordered:
19874 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
19875 break;
19876 case OMPC_nowait:
19877 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc,
19878 /*LParenLoc=*/SourceLocation(),
19879 /*Condition=*/nullptr);
19880 break;
19881 case OMPC_untied:
19882 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
19883 break;
19884 case OMPC_mergeable:
19885 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
19886 break;
19887 case OMPC_read:
19888 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
19889 break;
19890 case OMPC_write:
19891 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
19892 break;
19893 case OMPC_update:
19894 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
19895 break;
19896 case OMPC_capture:
19897 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
19898 break;
19899 case OMPC_compare:
19900 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
19901 break;
19902 case OMPC_fail:
19903 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
19904 break;
19905 case OMPC_seq_cst:
19906 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
19907 break;
19908 case OMPC_acq_rel:
19909 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
19910 break;
19911 case OMPC_acquire:
19912 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
19913 break;
19914 case OMPC_release:
19915 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
19916 break;
19917 case OMPC_relaxed:
19918 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
19919 break;
19920 case OMPC_weak:
19921 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
19922 break;
19923 case OMPC_threads:
19924 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
19925 break;
19926 case OMPC_simd:
19927 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
19928 break;
19929 case OMPC_nogroup:
19930 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
19931 break;
19932 case OMPC_unified_address:
19933 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
19934 break;
19935 case OMPC_unified_shared_memory:
19936 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
19937 break;
19938 case OMPC_reverse_offload:
19939 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
19940 break;
19941 case OMPC_dynamic_allocators:
19942 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
19943 break;
19944 case OMPC_self_maps:
19945 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
19946 break;
19947 case OMPC_destroy:
19948 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
19949 /*LParenLoc=*/SourceLocation(),
19950 /*VarLoc=*/SourceLocation(), EndLoc);
19951 break;
19952 case OMPC_full:
19953 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
19954 break;
19955 case OMPC_partial:
19956 Res = ActOnOpenMPPartialClause(FactorExpr: nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
19957 break;
19958 case OMPC_ompx_bare:
19959 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
19960 break;
19961 case OMPC_if:
19962 case OMPC_final:
19963 case OMPC_num_threads:
19964 case OMPC_safelen:
19965 case OMPC_simdlen:
19966 case OMPC_sizes:
19967 case OMPC_depth:
19968 case OMPC_allocator:
19969 case OMPC_collapse:
19970 case OMPC_schedule:
19971 case OMPC_private:
19972 case OMPC_firstprivate:
19973 case OMPC_lastprivate:
19974 case OMPC_shared:
19975 case OMPC_reduction:
19976 case OMPC_task_reduction:
19977 case OMPC_in_reduction:
19978 case OMPC_linear:
19979 case OMPC_aligned:
19980 case OMPC_copyin:
19981 case OMPC_copyprivate:
19982 case OMPC_default:
19983 case OMPC_proc_bind:
19984 case OMPC_threadprivate:
19985 case OMPC_groupprivate:
19986 case OMPC_allocate:
19987 case OMPC_flush:
19988 case OMPC_depobj:
19989 case OMPC_depend:
19990 case OMPC_device:
19991 case OMPC_map:
19992 case OMPC_num_teams:
19993 case OMPC_thread_limit:
19994 case OMPC_priority:
19995 case OMPC_grainsize:
19996 case OMPC_num_tasks:
19997 case OMPC_hint:
19998 case OMPC_dist_schedule:
19999 case OMPC_defaultmap:
20000 case OMPC_unknown:
20001 case OMPC_uniform:
20002 case OMPC_to:
20003 case OMPC_from:
20004 case OMPC_use_device_ptr:
20005 case OMPC_use_device_addr:
20006 case OMPC_is_device_ptr:
20007 case OMPC_has_device_addr:
20008 case OMPC_atomic_default_mem_order:
20009 case OMPC_device_type:
20010 case OMPC_match:
20011 case OMPC_nontemporal:
20012 case OMPC_order:
20013 case OMPC_at:
20014 case OMPC_severity:
20015 case OMPC_message:
20016 case OMPC_novariants:
20017 case OMPC_nocontext:
20018 case OMPC_detach:
20019 case OMPC_inclusive:
20020 case OMPC_exclusive:
20021 case OMPC_uses_allocators:
20022 case OMPC_affinity:
20023 case OMPC_when:
20024 case OMPC_ompx_dyn_cgroup_mem:
20025 case OMPC_dyn_groupprivate:
20026 default:
20027 llvm_unreachable("Clause is not allowed.");
20028 }
20029 return Res;
20030}
20031
20032OMPClause *SemaOpenMP::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
20033 SourceLocation EndLoc,
20034 SourceLocation LParenLoc,
20035 Expr *Condition) {
20036 Expr *ValExpr = Condition;
20037 if (Condition && LParenLoc.isValid()) {
20038 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
20039 !Condition->isInstantiationDependent() &&
20040 !Condition->containsUnexpandedParameterPack()) {
20041 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
20042 if (Val.isInvalid())
20043 return nullptr;
20044
20045 ValExpr = Val.get();
20046 }
20047 }
20048 DSAStack->setNowaitRegion();
20049 return new (getASTContext())
20050 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
20051}
20052
20053OMPClause *SemaOpenMP::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
20054 SourceLocation EndLoc) {
20055 DSAStack->setUntiedRegion();
20056 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
20057}
20058
20059OMPClause *SemaOpenMP::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
20060 SourceLocation EndLoc) {
20061 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
20062}
20063
20064OMPClause *SemaOpenMP::ActOnOpenMPReadClause(SourceLocation StartLoc,
20065 SourceLocation EndLoc) {
20066 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
20067}
20068
20069OMPClause *SemaOpenMP::ActOnOpenMPWriteClause(SourceLocation StartLoc,
20070 SourceLocation EndLoc) {
20071 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
20072}
20073
20074OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
20075 SourceLocation EndLoc) {
20076 return new (getASTContext()) OMPUpdateClause(StartLoc, EndLoc);
20077}
20078
20079OMPClause *SemaOpenMP::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
20080 SourceLocation EndLoc) {
20081 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
20082}
20083
20084OMPClause *SemaOpenMP::ActOnOpenMPCompareClause(SourceLocation StartLoc,
20085 SourceLocation EndLoc) {
20086 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
20087}
20088
20089OMPClause *SemaOpenMP::ActOnOpenMPFailClause(SourceLocation StartLoc,
20090 SourceLocation EndLoc) {
20091 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
20092}
20093
20094OMPClause *SemaOpenMP::ActOnOpenMPFailClause(OpenMPClauseKind Parameter,
20095 SourceLocation KindLoc,
20096 SourceLocation StartLoc,
20097 SourceLocation LParenLoc,
20098 SourceLocation EndLoc) {
20099
20100 if (!checkFailClauseParameter(FailClauseParameter: Parameter)) {
20101 Diag(Loc: KindLoc, DiagID: diag::err_omp_atomic_fail_wrong_or_no_clauses);
20102 return nullptr;
20103 }
20104 return new (getASTContext())
20105 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
20106}
20107
20108OMPClause *SemaOpenMP::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
20109 SourceLocation EndLoc) {
20110 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
20111}
20112
20113OMPClause *SemaOpenMP::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
20114 SourceLocation EndLoc) {
20115 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
20116}
20117
20118OMPClause *SemaOpenMP::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
20119 SourceLocation EndLoc) {
20120 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
20121}
20122
20123OMPClause *SemaOpenMP::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
20124 SourceLocation EndLoc) {
20125 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
20126}
20127
20128OMPClause *SemaOpenMP::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
20129 SourceLocation EndLoc) {
20130 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
20131}
20132
20133OMPClause *SemaOpenMP::ActOnOpenMPWeakClause(SourceLocation StartLoc,
20134 SourceLocation EndLoc) {
20135 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
20136}
20137
20138OMPClause *SemaOpenMP::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
20139 SourceLocation EndLoc) {
20140 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
20141}
20142
20143OMPClause *SemaOpenMP::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
20144 SourceLocation EndLoc) {
20145 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
20146}
20147
20148OMPClause *SemaOpenMP::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
20149 SourceLocation EndLoc) {
20150 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
20151}
20152
20153OMPClause *SemaOpenMP::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
20154 SourceLocation EndLoc) {
20155 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
20156}
20157
20158OMPClause *
20159SemaOpenMP::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
20160 SourceLocation EndLoc) {
20161 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
20162}
20163
20164OMPClause *SemaOpenMP::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
20165 SourceLocation EndLoc) {
20166 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
20167}
20168
20169OMPClause *
20170SemaOpenMP::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
20171 SourceLocation EndLoc) {
20172 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
20173}
20174
20175OMPClause *SemaOpenMP::ActOnOpenMPSelfMapsClause(SourceLocation StartLoc,
20176 SourceLocation EndLoc) {
20177 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
20178}
20179
20180StmtResult
20181SemaOpenMP::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
20182 SourceLocation StartLoc,
20183 SourceLocation EndLoc) {
20184
20185 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
20186 // At least one action-clause must appear on a directive.
20187 if (!hasClauses(Clauses, K: OMPC_init, ClauseTypes: OMPC_use, ClauseTypes: OMPC_destroy, ClauseTypes: OMPC_nowait)) {
20188 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
20189 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
20190 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
20191 << Expected << getOpenMPDirectiveName(D: OMPD_interop, V: OMPVersion);
20192 return StmtError();
20193 }
20194
20195 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
20196 // A depend clause can only appear on the directive if a targetsync
20197 // interop-type is present or the interop-var was initialized with
20198 // the targetsync interop-type.
20199
20200 // If there is any 'init' clause diagnose if there is no 'init' clause with
20201 // interop-type of 'targetsync'. Cases involving other directives cannot be
20202 // diagnosed.
20203 const OMPDependClause *DependClause = nullptr;
20204 bool HasInitClause = false;
20205 bool IsTargetSync = false;
20206 for (const OMPClause *C : Clauses) {
20207 if (IsTargetSync)
20208 break;
20209 if (const auto *InitClause = dyn_cast<OMPInitClause>(Val: C)) {
20210 HasInitClause = true;
20211 if (InitClause->getIsTargetSync())
20212 IsTargetSync = true;
20213 } else if (const auto *DC = dyn_cast<OMPDependClause>(Val: C)) {
20214 DependClause = DC;
20215 }
20216 }
20217 if (DependClause && HasInitClause && !IsTargetSync) {
20218 Diag(Loc: DependClause->getBeginLoc(), DiagID: diag::err_omp_interop_bad_depend_clause);
20219 return StmtError();
20220 }
20221
20222 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
20223 // Each interop-var may be specified for at most one action-clause of each
20224 // interop construct.
20225 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
20226 for (OMPClause *C : Clauses) {
20227 OpenMPClauseKind ClauseKind = C->getClauseKind();
20228 std::pair<ValueDecl *, bool> DeclResult;
20229 SourceLocation ELoc;
20230 SourceRange ERange;
20231
20232 if (ClauseKind == OMPC_init) {
20233 auto *E = cast<OMPInitClause>(Val: C)->getInteropVar();
20234 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
20235 } else if (ClauseKind == OMPC_use) {
20236 auto *E = cast<OMPUseClause>(Val: C)->getInteropVar();
20237 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
20238 } else if (ClauseKind == OMPC_destroy) {
20239 auto *E = cast<OMPDestroyClause>(Val: C)->getInteropVar();
20240 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
20241 }
20242
20243 if (DeclResult.first) {
20244 if (!InteropVars.insert(Ptr: DeclResult.first).second) {
20245 Diag(Loc: ELoc, DiagID: diag::err_omp_interop_var_multiple_actions)
20246 << DeclResult.first;
20247 return StmtError();
20248 }
20249 }
20250 }
20251
20252 return OMPInteropDirective::Create(C: getASTContext(), StartLoc, EndLoc,
20253 Clauses);
20254}
20255
20256static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
20257 SourceLocation VarLoc,
20258 OpenMPClauseKind Kind) {
20259 SourceLocation ELoc;
20260 SourceRange ERange;
20261 Expr *RefExpr = InteropVarExpr;
20262 auto Res = getPrivateItem(S&: SemaRef, RefExpr, ELoc, ERange,
20263 /*AllowArraySection=*/false,
20264 /*AllowAssumedSizeArray=*/false,
20265 /*DiagType=*/"omp_interop_t");
20266
20267 if (Res.second) {
20268 // It will be analyzed later.
20269 return true;
20270 }
20271
20272 if (!Res.first)
20273 return false;
20274
20275 // Interop variable should be of type omp_interop_t.
20276 bool HasError = false;
20277 QualType InteropType;
20278 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get(Name: "omp_interop_t"),
20279 VarLoc, Sema::LookupOrdinaryName);
20280 if (SemaRef.LookupName(R&: Result, S: SemaRef.getCurScope())) {
20281 NamedDecl *ND = Result.getFoundDecl();
20282 if (const auto *TD = dyn_cast<TypeDecl>(Val: ND)) {
20283 InteropType = QualType(TD->getTypeForDecl(), 0);
20284 } else {
20285 HasError = true;
20286 }
20287 } else {
20288 HasError = true;
20289 }
20290
20291 if (HasError) {
20292 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_implied_type_not_found)
20293 << "omp_interop_t";
20294 return false;
20295 }
20296
20297 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
20298 if (!SemaRef.Context.hasSameType(T1: InteropType, T2: VarType)) {
20299 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_interop_variable_wrong_type);
20300 return false;
20301 }
20302
20303 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
20304 // The interop-var passed to init or destroy must be non-const.
20305 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
20306 isConstNotMutableType(SemaRef, Type: InteropVarExpr->getType())) {
20307 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_interop_variable_expected)
20308 << /*non-const*/ 1;
20309 return false;
20310 }
20311 return true;
20312}
20313
20314OMPClause *SemaOpenMP::ActOnOpenMPInitClause(
20315 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
20316 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
20317
20318 if (!isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_init))
20319 return nullptr;
20320
20321 if (!checkPreferTypeArgs(S&: *this, Info: InteropInfo))
20322 return nullptr;
20323
20324 return OMPInitClause::Create(C: getASTContext(), InteropVar, InteropInfo,
20325 StartLoc, LParenLoc, VarLoc, EndLoc);
20326}
20327
20328OMPClause *SemaOpenMP::ActOnOpenMPUseClause(Expr *InteropVar,
20329 SourceLocation StartLoc,
20330 SourceLocation LParenLoc,
20331 SourceLocation VarLoc,
20332 SourceLocation EndLoc) {
20333
20334 if (!isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_use))
20335 return nullptr;
20336
20337 return new (getASTContext())
20338 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
20339}
20340
20341OMPClause *SemaOpenMP::ActOnOpenMPDestroyClause(Expr *InteropVar,
20342 SourceLocation StartLoc,
20343 SourceLocation LParenLoc,
20344 SourceLocation VarLoc,
20345 SourceLocation EndLoc) {
20346 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
20347 DSAStack->getCurrentDirective() == OMPD_depobj) {
20348 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
20349 Diag(Loc: StartLoc, DiagID: diag::err_omp_expected_clause_argument)
20350 << getOpenMPClauseNameForDiag(C: OMPC_destroy)
20351 << getOpenMPDirectiveName(D: OMPD_depobj, V: OMPVersion);
20352 return nullptr;
20353 }
20354 if (InteropVar &&
20355 !isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_destroy))
20356 return nullptr;
20357
20358 return new (getASTContext())
20359 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
20360}
20361
20362OMPClause *SemaOpenMP::ActOnOpenMPNovariantsClause(Expr *Condition,
20363 SourceLocation StartLoc,
20364 SourceLocation LParenLoc,
20365 SourceLocation EndLoc) {
20366 Expr *ValExpr = Condition;
20367 Stmt *HelperValStmt = nullptr;
20368 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
20369 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
20370 !Condition->isInstantiationDependent() &&
20371 !Condition->containsUnexpandedParameterPack()) {
20372 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
20373 if (Val.isInvalid())
20374 return nullptr;
20375
20376 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
20377
20378 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20379 CaptureRegion = getOpenMPCaptureRegionForClause(
20380 DKind, CKind: OMPC_novariants, OMPVersion: getLangOpts().getOpenMPVersion());
20381 if (CaptureRegion != OMPD_unknown &&
20382 !SemaRef.CurContext->isDependentContext()) {
20383 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
20384 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20385 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
20386 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
20387 }
20388 }
20389
20390 return new (getASTContext()) OMPNovariantsClause(
20391 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
20392}
20393
20394OMPClause *SemaOpenMP::ActOnOpenMPNocontextClause(Expr *Condition,
20395 SourceLocation StartLoc,
20396 SourceLocation LParenLoc,
20397 SourceLocation EndLoc) {
20398 Expr *ValExpr = Condition;
20399 Stmt *HelperValStmt = nullptr;
20400 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
20401 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
20402 !Condition->isInstantiationDependent() &&
20403 !Condition->containsUnexpandedParameterPack()) {
20404 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
20405 if (Val.isInvalid())
20406 return nullptr;
20407
20408 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
20409
20410 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20411 CaptureRegion = getOpenMPCaptureRegionForClause(
20412 DKind, CKind: OMPC_nocontext, OMPVersion: getLangOpts().getOpenMPVersion());
20413 if (CaptureRegion != OMPD_unknown &&
20414 !SemaRef.CurContext->isDependentContext()) {
20415 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
20416 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20417 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
20418 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
20419 }
20420 }
20421
20422 return new (getASTContext()) OMPNocontextClause(
20423 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
20424}
20425
20426OMPClause *SemaOpenMP::ActOnOpenMPFilterClause(Expr *ThreadID,
20427 SourceLocation StartLoc,
20428 SourceLocation LParenLoc,
20429 SourceLocation EndLoc) {
20430 Expr *ValExpr = ThreadID;
20431 Stmt *HelperValStmt = nullptr;
20432
20433 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20434 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
20435 DKind, CKind: OMPC_filter, OMPVersion: getLangOpts().getOpenMPVersion());
20436 if (CaptureRegion != OMPD_unknown &&
20437 !SemaRef.CurContext->isDependentContext()) {
20438 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
20439 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20440 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
20441 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
20442 }
20443
20444 return new (getASTContext()) OMPFilterClause(
20445 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
20446}
20447
20448OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
20449 ArrayRef<Expr *> VarList,
20450 const OMPVarListLocTy &Locs,
20451 OpenMPVarListDataTy &Data) {
20452 SourceLocation StartLoc = Locs.StartLoc;
20453 SourceLocation LParenLoc = Locs.LParenLoc;
20454 SourceLocation EndLoc = Locs.EndLoc;
20455 OMPClause *Res = nullptr;
20456 int ExtraModifier = Data.ExtraModifier;
20457 int OriginalSharingModifier = Data.OriginalSharingModifier;
20458 Expr *ExtraModifierExpr = Data.ExtraModifierExpr;
20459 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
20460 SourceLocation ColonLoc = Data.ColonLoc;
20461 switch (Kind) {
20462 case OMPC_private:
20463 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
20464 break;
20465 case OMPC_firstprivate:
20466 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
20467 break;
20468 case OMPC_lastprivate:
20469 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
20470 "Unexpected lastprivate modifier.");
20471 Res = ActOnOpenMPLastprivateClause(
20472 VarList, LPKind: static_cast<OpenMPLastprivateModifier>(ExtraModifier),
20473 LPKindLoc: ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
20474 break;
20475 case OMPC_shared:
20476 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
20477 break;
20478 case OMPC_reduction:
20479 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
20480 "Unexpected lastprivate modifier.");
20481 Res = ActOnOpenMPReductionClause(
20482 VarList,
20483 Modifiers: OpenMPVarListDataTy::OpenMPReductionClauseModifiers(
20484 ExtraModifier, OriginalSharingModifier),
20485 StartLoc, LParenLoc, ModifierLoc: ExtraModifierLoc, ColonLoc, EndLoc,
20486 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
20487 break;
20488 case OMPC_task_reduction:
20489 Res = ActOnOpenMPTaskReductionClause(
20490 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
20491 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
20492 break;
20493 case OMPC_in_reduction:
20494 Res = ActOnOpenMPInReductionClause(
20495 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
20496 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
20497 break;
20498 case OMPC_linear:
20499 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
20500 "Unexpected linear modifier.");
20501 Res = ActOnOpenMPLinearClause(
20502 VarList, Step: Data.DepModOrTailExpr, StartLoc, LParenLoc,
20503 LinKind: static_cast<OpenMPLinearClauseKind>(ExtraModifier), LinLoc: ExtraModifierLoc,
20504 ColonLoc, StepModifierLoc: Data.StepModifierLoc, EndLoc);
20505 break;
20506 case OMPC_aligned:
20507 Res = ActOnOpenMPAlignedClause(VarList, Alignment: Data.DepModOrTailExpr, StartLoc,
20508 LParenLoc, ColonLoc, EndLoc);
20509 break;
20510 case OMPC_copyin:
20511 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
20512 break;
20513 case OMPC_copyprivate:
20514 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
20515 break;
20516 case OMPC_flush:
20517 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
20518 break;
20519 case OMPC_depend:
20520 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
20521 "Unexpected depend modifier.");
20522 Res = ActOnOpenMPDependClause(
20523 Data: {.DepKind: static_cast<OpenMPDependClauseKind>(ExtraModifier), .DepLoc: ExtraModifierLoc,
20524 .ColonLoc: ColonLoc, .OmpAllMemoryLoc: Data.OmpAllMemoryLoc},
20525 DepModifier: Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
20526 break;
20527 case OMPC_map:
20528 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
20529 "Unexpected map modifier.");
20530 Res = ActOnOpenMPMapClause(
20531 IteratorModifier: Data.IteratorExpr, MapTypeModifiers: Data.MapTypeModifiers, MapTypeModifiersLoc: Data.MapTypeModifiersLoc,
20532 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId,
20533 MapType: static_cast<OpenMPMapClauseKind>(ExtraModifier), IsMapTypeImplicit: Data.IsMapTypeImplicit,
20534 MapLoc: ExtraModifierLoc, ColonLoc, VarList, Locs);
20535 break;
20536 case OMPC_to:
20537 Res = ActOnOpenMPToClause(
20538 MotionModifiers: Data.MotionModifiers, MotionModifiersLoc: Data.MotionModifiersLoc, IteratorModifier: Data.IteratorExpr,
20539 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId, ColonLoc,
20540 VarList, Locs);
20541 break;
20542 case OMPC_from:
20543 Res = ActOnOpenMPFromClause(
20544 MotionModifiers: Data.MotionModifiers, MotionModifiersLoc: Data.MotionModifiersLoc, IteratorModifier: Data.IteratorExpr,
20545 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId, ColonLoc,
20546 VarList, Locs);
20547 break;
20548 case OMPC_use_device_ptr:
20549 assert(0 <= Data.ExtraModifier &&
20550 Data.ExtraModifier <= OMPC_USE_DEVICE_PTR_FALLBACK_unknown &&
20551 "Unexpected use_device_ptr fallback modifier.");
20552 Res = ActOnOpenMPUseDevicePtrClause(
20553 VarList, Locs,
20554 FallbackModifier: static_cast<OpenMPUseDevicePtrFallbackModifier>(Data.ExtraModifier),
20555 FallbackModifierLoc: Data.ExtraModifierLoc);
20556 break;
20557 case OMPC_use_device_addr:
20558 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
20559 break;
20560 case OMPC_is_device_ptr:
20561 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
20562 break;
20563 case OMPC_has_device_addr:
20564 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
20565 break;
20566 case OMPC_allocate: {
20567 OpenMPAllocateClauseModifier Modifier1 = OMPC_ALLOCATE_unknown;
20568 OpenMPAllocateClauseModifier Modifier2 = OMPC_ALLOCATE_unknown;
20569 SourceLocation Modifier1Loc, Modifier2Loc;
20570 if (!Data.AllocClauseModifiers.empty()) {
20571 assert(Data.AllocClauseModifiers.size() <= 2 &&
20572 "More allocate modifiers than expected");
20573 Modifier1 = Data.AllocClauseModifiers[0];
20574 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
20575 if (Data.AllocClauseModifiers.size() == 2) {
20576 Modifier2 = Data.AllocClauseModifiers[1];
20577 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
20578 }
20579 }
20580 Res = ActOnOpenMPAllocateClause(
20581 Allocator: Data.DepModOrTailExpr, Alignment: Data.AllocateAlignment, FirstModifier: Modifier1, FirstModifierLoc: Modifier1Loc,
20582 SecondModifier: Modifier2, SecondModifierLoc: Modifier2Loc, VarList, StartLoc, ColonLoc: LParenLoc, LParenLoc: ColonLoc,
20583 EndLoc);
20584 break;
20585 }
20586 case OMPC_nontemporal:
20587 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
20588 break;
20589 case OMPC_inclusive:
20590 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
20591 break;
20592 case OMPC_exclusive:
20593 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
20594 break;
20595 case OMPC_affinity:
20596 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
20597 Modifier: Data.DepModOrTailExpr, Locators: VarList);
20598 break;
20599 case OMPC_doacross:
20600 Res = ActOnOpenMPDoacrossClause(
20601 DepType: static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
20602 DepLoc: ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
20603 break;
20604 case OMPC_num_teams:
20605 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_NUMTEAMS_unknown &&
20606 "Unexpected num_teams modifier.");
20607 Res = ActOnOpenMPNumTeamsClause(
20608 VarList,
20609 Modifier: static_cast<OpenMPNumTeamsClauseModifier>(Data.ExtraModifierArray[0]),
20610 ModifierExpr: Data.ExtraModifierExprArray[0], ModifierLoc: Data.ExtraModifierLocArray[0],
20611 ModifierExtra: static_cast<OpenMPNumTeamsClauseModifier>(Data.ExtraModifierArray[1]),
20612 ModifierExtraExpr: Data.ExtraModifierExprArray[1], ModifierExtraLoc: Data.ExtraModifierLocArray[1], StartLoc,
20613 LParenLoc, EndLoc);
20614 break;
20615 case OMPC_thread_limit:
20616 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_THREADLIMIT_unknown &&
20617 "Unexpected thread_limit modifier.");
20618 Res = ActOnOpenMPThreadLimitClause(
20619 VarList, Modifier: static_cast<OpenMPThreadLimitClauseModifier>(ExtraModifier),
20620 ModifierExpr: ExtraModifierExpr, ModifierLoc: ExtraModifierLoc, StartLoc, LParenLoc, EndLoc);
20621 break;
20622 case OMPC_num_threads:
20623 assert(0 <= Data.ExtraModifierArray[0] &&
20624 Data.ExtraModifierArray[0] <= OMPC_NUMTHREADS_unknown &&
20625 0 <= Data.ExtraModifierArray[1] &&
20626 Data.ExtraModifierArray[1] <= OMPC_NUMTHREADS_unknown &&
20627 "Unexpected num_threads modifier.");
20628 Res = ActOnOpenMPNumThreadsClause(
20629 VarList,
20630 SimpleModifier: static_cast<OpenMPNumThreadsClauseModifier>(Data.ExtraModifierArray[0]),
20631 SimpleModifierLoc: Data.ExtraModifierLocArray[0],
20632 ComplexModifier: static_cast<OpenMPNumThreadsClauseModifier>(Data.ExtraModifierArray[1]),
20633 ComplexModifierExpr: Data.ExtraModifierExprArray[1], ComplexModifierLoc: Data.ExtraModifierLocArray[1], StartLoc,
20634 LParenLoc, EndLoc);
20635 break;
20636 case OMPC_if:
20637 case OMPC_depobj:
20638 case OMPC_final:
20639 case OMPC_safelen:
20640 case OMPC_simdlen:
20641 case OMPC_sizes:
20642 case OMPC_depth:
20643 case OMPC_allocator:
20644 case OMPC_collapse:
20645 case OMPC_default:
20646 case OMPC_proc_bind:
20647 case OMPC_schedule:
20648 case OMPC_ordered:
20649 case OMPC_nowait:
20650 case OMPC_untied:
20651 case OMPC_mergeable:
20652 case OMPC_threadprivate:
20653 case OMPC_groupprivate:
20654 case OMPC_read:
20655 case OMPC_write:
20656 case OMPC_update:
20657 case OMPC_capture:
20658 case OMPC_compare:
20659 case OMPC_seq_cst:
20660 case OMPC_acq_rel:
20661 case OMPC_acquire:
20662 case OMPC_release:
20663 case OMPC_relaxed:
20664 case OMPC_device:
20665 case OMPC_threads:
20666 case OMPC_simd:
20667 case OMPC_priority:
20668 case OMPC_grainsize:
20669 case OMPC_nogroup:
20670 case OMPC_num_tasks:
20671 case OMPC_hint:
20672 case OMPC_dist_schedule:
20673 case OMPC_defaultmap:
20674 case OMPC_unknown:
20675 case OMPC_uniform:
20676 case OMPC_unified_address:
20677 case OMPC_unified_shared_memory:
20678 case OMPC_reverse_offload:
20679 case OMPC_dynamic_allocators:
20680 case OMPC_atomic_default_mem_order:
20681 case OMPC_self_maps:
20682 case OMPC_device_type:
20683 case OMPC_match:
20684 case OMPC_order:
20685 case OMPC_at:
20686 case OMPC_severity:
20687 case OMPC_message:
20688 case OMPC_destroy:
20689 case OMPC_novariants:
20690 case OMPC_nocontext:
20691 case OMPC_detach:
20692 case OMPC_uses_allocators:
20693 case OMPC_when:
20694 case OMPC_bind:
20695 default:
20696 llvm_unreachable("Clause is not allowed.");
20697 }
20698 return Res;
20699}
20700
20701ExprResult SemaOpenMP::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
20702 ExprObjectKind OK,
20703 SourceLocation Loc) {
20704 ExprResult Res = SemaRef.BuildDeclRefExpr(
20705 D: Capture, Ty: Capture->getType().getNonReferenceType(), VK: VK_LValue, Loc);
20706 if (!Res.isUsable())
20707 return ExprError();
20708 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
20709 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: Loc, Opc: UO_Deref, InputExpr: Res.get());
20710 if (!Res.isUsable())
20711 return ExprError();
20712 }
20713 if (VK != VK_LValue && Res.get()->isGLValue()) {
20714 Res = SemaRef.DefaultLvalueConversion(E: Res.get());
20715 if (!Res.isUsable())
20716 return ExprError();
20717 }
20718 return Res;
20719}
20720
20721OMPClause *SemaOpenMP::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
20722 SourceLocation StartLoc,
20723 SourceLocation LParenLoc,
20724 SourceLocation EndLoc) {
20725 SmallVector<Expr *, 8> Vars;
20726 SmallVector<Expr *, 8> PrivateCopies;
20727 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
20728 bool IsImplicitClause =
20729 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
20730 for (Expr *RefExpr : VarList) {
20731 assert(RefExpr && "NULL expr in OpenMP private clause.");
20732 SourceLocation ELoc;
20733 SourceRange ERange;
20734 Expr *SimpleRefExpr = RefExpr;
20735 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
20736 if (Res.second) {
20737 // It will be analyzed later.
20738 Vars.push_back(Elt: RefExpr);
20739 PrivateCopies.push_back(Elt: nullptr);
20740 }
20741 ValueDecl *D = Res.first;
20742 if (!D)
20743 continue;
20744
20745 QualType Type = D->getType();
20746 auto *VD = dyn_cast<VarDecl>(Val: D);
20747
20748 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
20749 // A variable that appears in a private clause must not have an incomplete
20750 // type or a reference type.
20751 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
20752 DiagID: diag::err_omp_private_incomplete_type))
20753 continue;
20754 Type = Type.getNonReferenceType();
20755
20756 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20757 // A variable that is privatized must not have a const-qualified type
20758 // unless it is of class type with a mutable member. This restriction does
20759 // not apply to the firstprivate clause.
20760 //
20761 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
20762 // A variable that appears in a private clause must not have a
20763 // const-qualified type unless it is of class type with a mutable member.
20764 if (rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_private, ELoc))
20765 continue;
20766
20767 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
20768 // in a Construct]
20769 // Variables with the predetermined data-sharing attributes may not be
20770 // listed in data-sharing attributes clauses, except for the cases
20771 // listed below. For these exceptions only, listing a predetermined
20772 // variable in a data-sharing attribute clause is allowed and overrides
20773 // the variable's predetermined data-sharing attributes.
20774 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20775 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
20776 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
20777 << getOpenMPClauseNameForDiag(C: DVar.CKind)
20778 << getOpenMPClauseNameForDiag(C: OMPC_private);
20779 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20780 continue;
20781 }
20782
20783 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
20784 // Variably modified types are not supported for tasks.
20785 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
20786 isOpenMPTaskingDirective(Kind: CurrDir)) {
20787 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
20788 << getOpenMPClauseNameForDiag(C: OMPC_private) << Type
20789 << getOpenMPDirectiveName(D: CurrDir, V: OMPVersion);
20790 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20791 VarDecl::DeclarationOnly;
20792 Diag(Loc: D->getLocation(),
20793 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20794 << D;
20795 continue;
20796 }
20797
20798 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
20799 // A list item cannot appear in both a map clause and a data-sharing
20800 // attribute clause on the same construct
20801 //
20802 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
20803 // A list item cannot appear in both a map clause and a data-sharing
20804 // attribute clause on the same construct unless the construct is a
20805 // combined construct.
20806 if ((getLangOpts().OpenMP <= 45 &&
20807 isOpenMPTargetExecutionDirective(DKind: CurrDir)) ||
20808 CurrDir == OMPD_target) {
20809 OpenMPClauseKind ConflictKind;
20810 if (DSAStack->checkMappableExprComponentListsForDecl(
20811 VD, /*CurrentRegionOnly=*/true,
20812 Check: [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
20813 OpenMPClauseKind WhereFoundClauseKind) -> bool {
20814 ConflictKind = WhereFoundClauseKind;
20815 return true;
20816 })) {
20817 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
20818 << getOpenMPClauseNameForDiag(C: OMPC_private)
20819 << getOpenMPClauseNameForDiag(C: ConflictKind)
20820 << getOpenMPDirectiveName(D: CurrDir, V: OMPVersion);
20821 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20822 continue;
20823 }
20824 }
20825
20826 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
20827 // A variable of class type (or array thereof) that appears in a private
20828 // clause requires an accessible, unambiguous default constructor for the
20829 // class type.
20830 // Generate helper private variable and initialize it with the default
20831 // value. The address of the original variable is replaced by the address of
20832 // the new private variable in CodeGen. This new variable is not added to
20833 // IdResolver, so the code in the OpenMP region uses original variable for
20834 // proper diagnostics.
20835 Type = Type.getUnqualifiedType();
20836 VarDecl *VDPrivate =
20837 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
20838 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
20839 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
20840 SemaRef.ActOnUninitializedDecl(dcl: VDPrivate);
20841 if (VDPrivate->isInvalidDecl())
20842 continue;
20843 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
20844 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(), Loc: ELoc);
20845
20846 DeclRefExpr *Ref = nullptr;
20847 bool IsBindingDecl = isa<BindingDecl>(Val: D);
20848 if (!VD && !IsBindingDecl && !SemaRef.CurContext->isDependentContext()) {
20849 auto *FD = dyn_cast<FieldDecl>(Val: D);
20850 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
20851 if (VD)
20852 Ref = buildDeclRefExpr(S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(),
20853 Loc: RefExpr->getExprLoc());
20854 else
20855 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
20856 }
20857 if (!IsImplicitClause) {
20858 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_private, PrivateCopy: Ref);
20859 }
20860 Vars.push_back(
20861 Elt: (VD || IsBindingDecl || SemaRef.CurContext->isDependentContext())
20862 ? RefExpr->IgnoreParens()
20863 : Ref);
20864 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
20865 }
20866
20867 if (Vars.empty())
20868 return nullptr;
20869
20870 return OMPPrivateClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
20871 VL: Vars, PrivateVL: PrivateCopies);
20872}
20873
20874OMPClause *SemaOpenMP::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
20875 SourceLocation StartLoc,
20876 SourceLocation LParenLoc,
20877 SourceLocation EndLoc) {
20878 SmallVector<Expr *, 8> Vars;
20879 SmallVector<Expr *, 8> PrivateCopies;
20880 SmallVector<Expr *, 8> Inits;
20881 SmallVector<Decl *, 4> ExprCaptures;
20882 bool IsImplicitClause =
20883 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
20884 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
20885 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
20886
20887 for (Expr *RefExpr : VarList) {
20888 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
20889 SourceLocation ELoc;
20890 SourceRange ERange;
20891 Expr *SimpleRefExpr = RefExpr;
20892 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
20893 if (Res.second) {
20894 // It will be analyzed later.
20895 Vars.push_back(Elt: RefExpr);
20896 PrivateCopies.push_back(Elt: nullptr);
20897 Inits.push_back(Elt: nullptr);
20898 }
20899 ValueDecl *D = Res.first;
20900 if (!D)
20901 continue;
20902
20903 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
20904 QualType Type = D->getType();
20905 auto *VD = dyn_cast<VarDecl>(Val: D);
20906
20907 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
20908 // A variable that appears in a private clause must not have an incomplete
20909 // type or a reference type.
20910 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
20911 DiagID: diag::err_omp_firstprivate_incomplete_type))
20912 continue;
20913 Type = Type.getNonReferenceType();
20914
20915 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
20916 // A variable of class type (or array thereof) that appears in a private
20917 // clause requires an accessible, unambiguous copy constructor for the
20918 // class type.
20919 QualType ElemType =
20920 getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
20921
20922 // If an implicit firstprivate variable found it was checked already.
20923 DSAStackTy::DSAVarData TopDVar;
20924 if (!IsImplicitClause) {
20925 DSAStackTy::DSAVarData DVar =
20926 DSAStack->getTopDSA(D, /*FromParent=*/false);
20927 TopDVar = DVar;
20928 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
20929 bool IsConstant = ElemType.isConstant(Ctx: getASTContext());
20930 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
20931 // A list item that specifies a given variable may not appear in more
20932 // than one clause on the same directive, except that a variable may be
20933 // specified in both firstprivate and lastprivate clauses.
20934 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
20935 // A list item may appear in a firstprivate or lastprivate clause but not
20936 // both.
20937 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
20938 (isOpenMPDistributeDirective(DKind: CurrDir) ||
20939 DVar.CKind != OMPC_lastprivate) &&
20940 DVar.RefExpr) {
20941 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
20942 << getOpenMPClauseNameForDiag(C: DVar.CKind)
20943 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
20944 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20945 continue;
20946 }
20947
20948 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
20949 // in a Construct]
20950 // Variables with the predetermined data-sharing attributes may not be
20951 // listed in data-sharing attributes clauses, except for the cases
20952 // listed below. For these exceptions only, listing a predetermined
20953 // variable in a data-sharing attribute clause is allowed and overrides
20954 // the variable's predetermined data-sharing attributes.
20955 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
20956 // in a Construct, C/C++, p.2]
20957 // Variables with const-qualified type having no mutable member may be
20958 // listed in a firstprivate clause, even if they are static data members.
20959 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
20960 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
20961 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
20962 << getOpenMPClauseNameForDiag(C: DVar.CKind)
20963 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
20964 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20965 continue;
20966 }
20967
20968 // OpenMP [2.9.3.4, Restrictions, p.2]
20969 // A list item that is private within a parallel region must not appear
20970 // in a firstprivate clause on a worksharing construct if any of the
20971 // worksharing regions arising from the worksharing construct ever bind
20972 // to any of the parallel regions arising from the parallel construct.
20973 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
20974 // A list item that is private within a teams region must not appear in a
20975 // firstprivate clause on a distribute construct if any of the distribute
20976 // regions arising from the distribute construct ever bind to any of the
20977 // teams regions arising from the teams construct.
20978 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
20979 // A list item that appears in a reduction clause of a teams construct
20980 // must not appear in a firstprivate clause on a distribute construct if
20981 // any of the distribute regions arising from the distribute construct
20982 // ever bind to any of the teams regions arising from the teams construct.
20983 if ((isOpenMPWorksharingDirective(DKind: CurrDir) ||
20984 isOpenMPDistributeDirective(DKind: CurrDir)) &&
20985 !isOpenMPParallelDirective(DKind: CurrDir) &&
20986 !isOpenMPTeamsDirective(DKind: CurrDir)) {
20987 DVar = DSAStack->getImplicitDSA(D, FromParent: true);
20988 if (DVar.CKind != OMPC_shared &&
20989 (isOpenMPParallelDirective(DKind: DVar.DKind) ||
20990 isOpenMPTeamsDirective(DKind: DVar.DKind) ||
20991 DVar.DKind == OMPD_unknown)) {
20992 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
20993 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate)
20994 << getOpenMPClauseNameForDiag(C: OMPC_shared);
20995 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20996 continue;
20997 }
20998 }
20999 // OpenMP [2.9.3.4, Restrictions, p.3]
21000 // A list item that appears in a reduction clause of a parallel construct
21001 // must not appear in a firstprivate clause on a worksharing or task
21002 // construct if any of the worksharing or task regions arising from the
21003 // worksharing or task construct ever bind to any of the parallel regions
21004 // arising from the parallel construct.
21005 // OpenMP [2.9.3.4, Restrictions, p.4]
21006 // A list item that appears in a reduction clause in worksharing
21007 // construct must not appear in a firstprivate clause in a task construct
21008 // encountered during execution of any of the worksharing regions arising
21009 // from the worksharing construct.
21010 if (isOpenMPTaskingDirective(Kind: CurrDir)) {
21011 DVar = DSAStack->hasInnermostDSA(
21012 D,
21013 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
21014 return C == OMPC_reduction && !AppliedToPointee;
21015 },
21016 DPred: [](OpenMPDirectiveKind K) {
21017 return isOpenMPParallelDirective(DKind: K) ||
21018 isOpenMPWorksharingDirective(DKind: K) ||
21019 isOpenMPTeamsDirective(DKind: K);
21020 },
21021 /*FromParent=*/true);
21022 if (DVar.CKind == OMPC_reduction &&
21023 (isOpenMPParallelDirective(DKind: DVar.DKind) ||
21024 isOpenMPWorksharingDirective(DKind: DVar.DKind) ||
21025 isOpenMPTeamsDirective(DKind: DVar.DKind))) {
21026 Diag(Loc: ELoc, DiagID: diag::err_omp_parallel_reduction_in_task_firstprivate)
21027 << getOpenMPDirectiveName(D: DVar.DKind, V: OMPVersion);
21028 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
21029 continue;
21030 }
21031 }
21032
21033 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
21034 // A list item cannot appear in both a map clause and a data-sharing
21035 // attribute clause on the same construct
21036 //
21037 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
21038 // A list item cannot appear in both a map clause and a data-sharing
21039 // attribute clause on the same construct unless the construct is a
21040 // combined construct.
21041 if ((getLangOpts().OpenMP <= 45 &&
21042 isOpenMPTargetExecutionDirective(DKind: CurrDir)) ||
21043 CurrDir == OMPD_target) {
21044 OpenMPClauseKind ConflictKind;
21045 if (DSAStack->checkMappableExprComponentListsForDecl(
21046 VD, /*CurrentRegionOnly=*/true,
21047 Check: [&ConflictKind](
21048 OMPClauseMappableExprCommon::MappableExprComponentListRef,
21049 OpenMPClauseKind WhereFoundClauseKind) {
21050 ConflictKind = WhereFoundClauseKind;
21051 return true;
21052 })) {
21053 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
21054 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate)
21055 << getOpenMPClauseNameForDiag(C: ConflictKind)
21056 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
21057 V: OMPVersion);
21058 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
21059 continue;
21060 }
21061 }
21062 }
21063
21064 // Variably modified types are not supported for tasks.
21065 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
21066 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
21067 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
21068 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate) << Type
21069 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
21070 V: OMPVersion);
21071 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21072 VarDecl::DeclarationOnly;
21073 Diag(Loc: D->getLocation(),
21074 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21075 << D;
21076 continue;
21077 }
21078
21079 Type = Type.getUnqualifiedType();
21080
21081 // For BindingDecls, use the DecompositionDecl's type so all bindings from
21082 // the same decomposition are accessible in the privatized region. We do
21083 // this after conflict checking to preserve diagnostic errors. Don't modify
21084 // RefExpr/SimpleRefExpr to keep diagnostics working.
21085 bool IsBindingDecl = isa<BindingDecl>(Val: D);
21086 VarDecl *PrivateVD = VD;
21087 QualType PrivateType = Type;
21088 if (IsBindingDecl) {
21089 const auto *BD = cast<BindingDecl>(Val: D);
21090 PrivateVD = cast<VarDecl>(Val: BD->getDecomposedDecl());
21091 // PrivateType stays as the BindingDecl's type (Type), not the
21092 // DecompositionDecl's type.
21093 }
21094
21095 // For regular arrays, pass the original var ref. For BindingDecls, don't
21096 // pass the DecompositionDecl ref since VDPrivate has the binding's type,
21097 // not the decomposition type.
21098 VarDecl *VDPrivate = buildVarDecl(SemaRef, Loc: ELoc, Type: PrivateType, Name: D->getName(),
21099 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
21100 OrigRef: (PrivateVD && !IsBindingDecl)
21101 ? cast<DeclRefExpr>(Val: SimpleRefExpr)
21102 : nullptr);
21103
21104 // Generate helper private variable and initialize it with the value of the
21105 // original variable. The address of the original variable is replaced by
21106 // the address of the new private variable in the CodeGen. This new variable
21107 // is not added to IdResolver, so the code in the OpenMP region uses
21108 // original variable for proper diagnostics and variable capturing.
21109 Expr *VDInitRefExpr = nullptr;
21110
21111 // For BindingDecls, VDPrivate should have the binding's type (not the
21112 // DecompositionDecl's type), and will be initialized from the binding's
21113 // field in the original DecompositionDecl.
21114 if (IsBindingDecl && !PrivateType->isArrayType()) {
21115 // For non-array bindings, create a simple copy initialization.
21116 VarDecl *VDInit = buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(),
21117 Type: PrivateType, Name: ".firstprivate.temp");
21118 VDInitRefExpr =
21119 buildDeclRefExpr(S&: SemaRef, D: VDInit, Ty: PrivateType, Loc: RefExpr->getExprLoc());
21120
21121 // Initialize VDPrivate from VDInit (which will point to the field).
21122 SemaRef.AddInitializerToDecl(
21123 dcl: VDPrivate, init: SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get(),
21124 /*DirectInit=*/false);
21125 } else if (Type->isArrayType()) {
21126 // For arrays generate initializer for single element and replace it by
21127 // the original array element in CodeGen.
21128 VarDecl *VDInit =
21129 buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type: ElemType, Name: D->getName());
21130 VDInitRefExpr = buildDeclRefExpr(S&: SemaRef, D: VDInit, Ty: ElemType, Loc: ELoc);
21131 Expr *Init = SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get();
21132 ElemType = ElemType.getUnqualifiedType();
21133 VarDecl *VDInitTemp = buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(),
21134 Type: ElemType, Name: ".firstprivate.temp");
21135 InitializedEntity Entity =
21136 InitializedEntity::InitializeVariable(Var: VDInitTemp);
21137 InitializationKind Kind = InitializationKind::CreateCopy(InitLoc: ELoc, EqualLoc: ELoc);
21138
21139 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
21140 ExprResult Result = InitSeq.Perform(S&: SemaRef, Entity, Kind, Args: Init);
21141 if (Result.isInvalid())
21142 VDPrivate->setInvalidDecl();
21143 else
21144 VDPrivate->setInit(Result.getAs<Expr>());
21145 // Remove temp variable declaration.
21146 getASTContext().Deallocate(Ptr: VDInitTemp);
21147 } else {
21148 VarDecl *VDInit = buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type,
21149 Name: ".firstprivate.temp");
21150 VDInitRefExpr = buildDeclRefExpr(S&: SemaRef, D: VDInit, Ty: RefExpr->getType(),
21151 Loc: RefExpr->getExprLoc());
21152 SemaRef.AddInitializerToDecl(
21153 dcl: VDPrivate, init: SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get(),
21154 /*DirectInit=*/false);
21155 }
21156 if (VDPrivate->isInvalidDecl()) {
21157 if (IsImplicitClause) {
21158 Diag(Loc: RefExpr->getExprLoc(),
21159 DiagID: diag::note_omp_task_predetermined_firstprivate_here);
21160 }
21161 continue;
21162 }
21163 SemaRef.CurContext->addDecl(D: VDPrivate);
21164 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
21165 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(),
21166 Loc: RefExpr->getExprLoc());
21167 DeclRefExpr *Ref = nullptr;
21168 if (!VD && !SemaRef.CurContext->isDependentContext()) {
21169 if (TopDVar.CKind == OMPC_lastprivate) {
21170 Ref = TopDVar.PrivateCopy;
21171 } else if (!IsBindingDecl) {
21172 auto *FD = dyn_cast<FieldDecl>(Val: D);
21173 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
21174 if (VD)
21175 Ref =
21176 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(),
21177 Loc: RefExpr->getExprLoc());
21178 else
21179 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
21180 if (VD || !isOpenMPCapturedDecl(D))
21181 ExprCaptures.push_back(Elt: Ref->getDecl());
21182 }
21183 }
21184 if (!IsImplicitClause)
21185 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
21186 Vars.push_back(
21187 Elt: (VD || IsBindingDecl || SemaRef.CurContext->isDependentContext())
21188 ? RefExpr->IgnoreParens()
21189 : Ref);
21190 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
21191 Inits.push_back(Elt: VDInitRefExpr);
21192 }
21193
21194 if (Vars.empty())
21195 return nullptr;
21196
21197 return OMPFirstprivateClause::Create(
21198 C: getASTContext(), StartLoc, LParenLoc, EndLoc, VL: Vars, PrivateVL: PrivateCopies, InitVL: Inits,
21199 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures));
21200}
21201
21202OMPClause *SemaOpenMP::ActOnOpenMPLastprivateClause(
21203 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
21204 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
21205 SourceLocation LParenLoc, SourceLocation EndLoc) {
21206 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
21207 assert(ColonLoc.isValid() && "Colon location must be valid.");
21208 Diag(Loc: LPKindLoc, DiagID: diag::err_omp_unexpected_clause_value)
21209 << getListOfPossibleValues(K: OMPC_lastprivate, /*First=*/0,
21210 /*Last=*/OMPC_LASTPRIVATE_unknown)
21211 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate);
21212 return nullptr;
21213 }
21214
21215 SmallVector<Expr *, 8> Vars;
21216 SmallVector<Expr *, 8> SrcExprs;
21217 SmallVector<Expr *, 8> DstExprs;
21218 SmallVector<Expr *, 8> AssignmentOps;
21219 SmallVector<Decl *, 4> ExprCaptures;
21220 SmallVector<Expr *, 4> ExprPostUpdates;
21221 for (Expr *RefExpr : VarList) {
21222 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
21223 SourceLocation ELoc;
21224 SourceRange ERange;
21225 Expr *SimpleRefExpr = RefExpr;
21226 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
21227 if (Res.second) {
21228 // It will be analyzed later.
21229 Vars.push_back(Elt: RefExpr);
21230 SrcExprs.push_back(Elt: nullptr);
21231 DstExprs.push_back(Elt: nullptr);
21232 AssignmentOps.push_back(Elt: nullptr);
21233 }
21234 ValueDecl *D = Res.first;
21235 if (!D)
21236 continue;
21237
21238 QualType Type = D->getType();
21239 auto *VD = dyn_cast<VarDecl>(Val: D);
21240
21241 // Structured bindings with conditional modifier are currently not
21242 // supported.
21243 if (LPKind == OMPC_LASTPRIVATE_conditional && isa<BindingDecl>(Val: D)) {
21244 Diag(Loc: ELoc, DiagID: diag::err_omp_unsupported_on_binding) << 1;
21245 Diag(Loc: D->getLocation(), DiagID: diag::note_defined_here) << D;
21246 continue;
21247 }
21248
21249 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
21250 // A variable that appears in a lastprivate clause must not have an
21251 // incomplete type or a reference type.
21252 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
21253 DiagID: diag::err_omp_lastprivate_incomplete_type))
21254 continue;
21255 Type = Type.getNonReferenceType();
21256
21257 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
21258 // A variable that is privatized must not have a const-qualified type
21259 // unless it is of class type with a mutable member. This restriction does
21260 // not apply to the firstprivate clause.
21261 //
21262 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
21263 // A variable that appears in a lastprivate clause must not have a
21264 // const-qualified type unless it is of class type with a mutable member.
21265 if (rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_lastprivate, ELoc))
21266 continue;
21267
21268 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
21269 // A list item that appears in a lastprivate clause with the conditional
21270 // modifier must be a scalar variable.
21271 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
21272 Diag(Loc: ELoc, DiagID: diag::err_omp_lastprivate_conditional_non_scalar);
21273 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21274 VarDecl::DeclarationOnly;
21275 Diag(Loc: D->getLocation(),
21276 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21277 << D;
21278 continue;
21279 }
21280
21281 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
21282 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
21283 // in a Construct]
21284 // Variables with the predetermined data-sharing attributes may not be
21285 // listed in data-sharing attributes clauses, except for the cases
21286 // listed below.
21287 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
21288 // A list item may appear in a firstprivate or lastprivate clause but not
21289 // both.
21290 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
21291 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
21292 (isOpenMPDistributeDirective(DKind: CurrDir) ||
21293 DVar.CKind != OMPC_firstprivate) &&
21294 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
21295 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
21296 << getOpenMPClauseNameForDiag(C: DVar.CKind)
21297 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate);
21298 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
21299 continue;
21300 }
21301
21302 // OpenMP [2.14.3.5, Restrictions, p.2]
21303 // A list item that is private within a parallel region, or that appears in
21304 // the reduction clause of a parallel construct, must not appear in a
21305 // lastprivate clause on a worksharing construct if any of the corresponding
21306 // worksharing regions ever binds to any of the corresponding parallel
21307 // regions.
21308 DSAStackTy::DSAVarData TopDVar = DVar;
21309 if (isOpenMPWorksharingDirective(DKind: CurrDir) &&
21310 !isOpenMPParallelDirective(DKind: CurrDir) &&
21311 !isOpenMPTeamsDirective(DKind: CurrDir)) {
21312 DVar = DSAStack->getImplicitDSA(D, FromParent: true);
21313 if (DVar.CKind != OMPC_shared) {
21314 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
21315 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate)
21316 << getOpenMPClauseNameForDiag(C: OMPC_shared);
21317 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
21318 continue;
21319 }
21320 }
21321
21322 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
21323 // A variable of class type (or array thereof) that appears in a
21324 // lastprivate clause requires an accessible, unambiguous default
21325 // constructor for the class type, unless the list item is also specified
21326 // in a firstprivate clause.
21327 // A variable of class type (or array thereof) that appears in a
21328 // lastprivate clause requires an accessible, unambiguous copy assignment
21329 // operator for the class type.
21330 Type = getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
21331 VarDecl *SrcVD = buildVarDecl(SemaRef, Loc: ERange.getBegin(),
21332 Type: Type.getUnqualifiedType(), Name: ".lastprivate.src",
21333 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
21334 DeclRefExpr *PseudoSrcExpr =
21335 buildDeclRefExpr(S&: SemaRef, D: SrcVD, Ty: Type.getUnqualifiedType(), Loc: ELoc);
21336 VarDecl *DstVD =
21337 buildVarDecl(SemaRef, Loc: ERange.getBegin(), Type, Name: ".lastprivate.dst",
21338 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
21339 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: Type, Loc: ELoc);
21340 // For arrays generate assignment operation for single element and replace
21341 // it by the original array element in CodeGen.
21342 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, OpLoc: ELoc, Opc: BO_Assign,
21343 LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
21344 if (AssignmentOp.isInvalid())
21345 continue;
21346 AssignmentOp = SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: ELoc,
21347 /*DiscardedValue=*/false);
21348 if (AssignmentOp.isInvalid())
21349 continue;
21350
21351 DeclRefExpr *Ref = nullptr;
21352 if (!VD && !SemaRef.CurContext->isDependentContext()) {
21353 if (TopDVar.CKind == OMPC_firstprivate) {
21354 Ref = TopDVar.PrivateCopy;
21355 } else {
21356 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
21357 if (!isOpenMPCapturedDecl(D))
21358 ExprCaptures.push_back(Elt: Ref->getDecl());
21359 }
21360 if (Ref &&
21361 ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
21362 (!isOpenMPCapturedDecl(D) &&
21363 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()))) {
21364 ExprResult RefRes = SemaRef.DefaultLvalueConversion(E: Ref);
21365 if (!RefRes.isUsable())
21366 continue;
21367 ExprResult PostUpdateRes =
21368 SemaRef.BuildBinOp(DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign,
21369 LHSExpr: SimpleRefExpr, RHSExpr: RefRes.get());
21370 if (!PostUpdateRes.isUsable())
21371 continue;
21372 ExprPostUpdates.push_back(
21373 Elt: SemaRef.IgnoredValueConversions(E: PostUpdateRes.get()).get());
21374 }
21375 }
21376 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_lastprivate, PrivateCopy: Ref);
21377 bool IsBindingDecl = isa<BindingDecl>(Val: D);
21378 Vars.push_back(
21379 Elt: (VD || IsBindingDecl || SemaRef.CurContext->isDependentContext())
21380 ? RefExpr->IgnoreParens()
21381 : Ref);
21382 SrcExprs.push_back(Elt: PseudoSrcExpr);
21383 DstExprs.push_back(Elt: PseudoDstExpr);
21384 AssignmentOps.push_back(Elt: AssignmentOp.get());
21385 }
21386
21387 if (Vars.empty())
21388 return nullptr;
21389
21390 return OMPLastprivateClause::Create(
21391 C: getASTContext(), StartLoc, LParenLoc, EndLoc, VL: Vars, SrcExprs, DstExprs,
21392 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
21393 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures),
21394 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: ExprPostUpdates));
21395}
21396
21397OMPClause *SemaOpenMP::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
21398 SourceLocation StartLoc,
21399 SourceLocation LParenLoc,
21400 SourceLocation EndLoc) {
21401 SmallVector<Expr *, 8> Vars;
21402 for (Expr *RefExpr : VarList) {
21403 assert(RefExpr && "NULL expr in OpenMP shared clause.");
21404 SourceLocation ELoc;
21405 SourceRange ERange;
21406 Expr *SimpleRefExpr = RefExpr;
21407 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
21408 if (Res.second) {
21409 // It will be analyzed later.
21410 Vars.push_back(Elt: RefExpr);
21411 }
21412 ValueDecl *D = Res.first;
21413 if (!D)
21414 continue;
21415
21416 auto *VD = dyn_cast<VarDecl>(Val: D);
21417 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
21418 // in a Construct]
21419 // Variables with the predetermined data-sharing attributes may not be
21420 // listed in data-sharing attributes clauses, except for the cases
21421 // listed below. For these exceptions only, listing a predetermined
21422 // variable in a data-sharing attribute clause is allowed and overrides
21423 // the variable's predetermined data-sharing attributes.
21424 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
21425 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
21426 DVar.RefExpr) {
21427 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
21428 << getOpenMPClauseNameForDiag(C: DVar.CKind)
21429 << getOpenMPClauseNameForDiag(C: OMPC_shared);
21430 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
21431 continue;
21432 }
21433
21434 DeclRefExpr *Ref = nullptr;
21435 if (!VD && isOpenMPCapturedDecl(D) &&
21436 !SemaRef.CurContext->isDependentContext())
21437 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
21438 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_shared, PrivateCopy: Ref);
21439 Vars.push_back(Elt: (VD || !Ref || SemaRef.CurContext->isDependentContext())
21440 ? RefExpr->IgnoreParens()
21441 : Ref);
21442 }
21443
21444 if (Vars.empty())
21445 return nullptr;
21446
21447 return OMPSharedClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
21448 VL: Vars);
21449}
21450
21451namespace {
21452class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
21453 DSAStackTy *Stack;
21454
21455public:
21456 bool VisitDeclRefExpr(DeclRefExpr *E) {
21457 if (auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
21458 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D: VD, /*FromParent=*/false);
21459 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
21460 return false;
21461 if (DVar.CKind != OMPC_unknown)
21462 return true;
21463 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
21464 D: VD,
21465 CPred: [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
21466 return isOpenMPPrivate(Kind: C) && !AppliedToPointee;
21467 },
21468 DPred: [](OpenMPDirectiveKind) { return true; },
21469 /*FromParent=*/true);
21470 return DVarPrivate.CKind != OMPC_unknown;
21471 }
21472 return false;
21473 }
21474 bool VisitStmt(Stmt *S) {
21475 for (Stmt *Child : S->children()) {
21476 if (Child && Visit(S: Child))
21477 return true;
21478 }
21479 return false;
21480 }
21481 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
21482};
21483} // namespace
21484
21485namespace {
21486// Transform MemberExpression for specified FieldDecl of current class to
21487// DeclRefExpr to specified OMPCapturedExprDecl.
21488class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
21489 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
21490 ValueDecl *Field = nullptr;
21491 DeclRefExpr *CapturedExpr = nullptr;
21492
21493public:
21494 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
21495 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
21496
21497 ExprResult TransformMemberExpr(MemberExpr *E) {
21498 if (isa<CXXThisExpr>(Val: E->getBase()->IgnoreParenImpCasts()) &&
21499 E->getMemberDecl() == Field) {
21500 CapturedExpr = buildCapture(S&: SemaRef, D: Field, CaptureExpr: E, /*WithInit=*/false);
21501 return CapturedExpr;
21502 }
21503 return BaseTransform::TransformMemberExpr(E);
21504 }
21505 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
21506};
21507} // namespace
21508
21509template <typename T, typename U>
21510static T filterLookupForUDReductionAndMapper(
21511 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
21512 for (U &Set : Lookups) {
21513 for (auto *D : Set) {
21514 if (T Res = Gen(cast<ValueDecl>(D)))
21515 return Res;
21516 }
21517 }
21518 return T();
21519}
21520
21521static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
21522 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
21523
21524 for (auto *RD : D->redecls()) {
21525 // Don't bother with extra checks if we already know this one isn't visible.
21526 if (RD == D)
21527 continue;
21528
21529 auto ND = cast<NamedDecl>(Val: RD);
21530 if (LookupResult::isVisible(SemaRef, D: ND))
21531 return ND;
21532 }
21533
21534 return nullptr;
21535}
21536
21537static void
21538argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
21539 SourceLocation Loc, QualType Ty,
21540 SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
21541 // Find all of the associated namespaces and classes based on the
21542 // arguments we have.
21543 Sema::AssociatedNamespaceSet AssociatedNamespaces;
21544 Sema::AssociatedClassSet AssociatedClasses;
21545 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
21546 SemaRef.FindAssociatedClassesAndNamespaces(InstantiationLoc: Loc, Args: &OVE, AssociatedNamespaces,
21547 AssociatedClasses);
21548
21549 // C++ [basic.lookup.argdep]p3:
21550 // Let X be the lookup set produced by unqualified lookup (3.4.1)
21551 // and let Y be the lookup set produced by argument dependent
21552 // lookup (defined as follows). If X contains [...] then Y is
21553 // empty. Otherwise Y is the set of declarations found in the
21554 // namespaces associated with the argument types as described
21555 // below. The set of declarations found by the lookup of the name
21556 // is the union of X and Y.
21557 //
21558 // Here, we compute Y and add its members to the overloaded
21559 // candidate set.
21560 for (auto *NS : AssociatedNamespaces) {
21561 // When considering an associated namespace, the lookup is the
21562 // same as the lookup performed when the associated namespace is
21563 // used as a qualifier (3.4.3.2) except that:
21564 //
21565 // -- Any using-directives in the associated namespace are
21566 // ignored.
21567 //
21568 // -- Any namespace-scope friend functions declared in
21569 // associated classes are visible within their respective
21570 // namespaces even if they are not visible during an ordinary
21571 // lookup (11.4).
21572 DeclContext::lookup_result R = NS->lookup(Name: Id.getName());
21573 for (auto *D : R) {
21574 auto *Underlying = D;
21575 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
21576 Underlying = USD->getTargetDecl();
21577
21578 if (!isa<OMPDeclareReductionDecl>(Val: Underlying) &&
21579 !isa<OMPDeclareMapperDecl>(Val: Underlying))
21580 continue;
21581
21582 if (!SemaRef.isVisible(D)) {
21583 D = findAcceptableDecl(SemaRef, D);
21584 if (!D)
21585 continue;
21586 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
21587 Underlying = USD->getTargetDecl();
21588 }
21589 Lookups.emplace_back();
21590 Lookups.back().addDecl(D: Underlying);
21591 }
21592 }
21593}
21594
21595static ExprResult
21596buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
21597 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
21598 const DeclarationNameInfo &ReductionId, QualType Ty,
21599 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
21600 if (ReductionIdScopeSpec.isInvalid())
21601 return ExprError();
21602 SmallVector<UnresolvedSet<8>, 4> Lookups;
21603 if (S) {
21604 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
21605 Lookup.suppressDiagnostics();
21606 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &ReductionIdScopeSpec,
21607 /*ObjectType=*/QualType())) {
21608 NamedDecl *D = Lookup.getRepresentativeDecl();
21609 do {
21610 S = S->getParent();
21611 } while (S && !S->isDeclScope(D));
21612 if (S)
21613 S = S->getParent();
21614 Lookups.emplace_back();
21615 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
21616 Lookup.clear();
21617 }
21618 } else if (auto *ULE =
21619 cast_or_null<UnresolvedLookupExpr>(Val: UnresolvedReduction)) {
21620 Lookups.push_back(Elt: UnresolvedSet<8>());
21621 Decl *PrevD = nullptr;
21622 for (NamedDecl *D : ULE->decls()) {
21623 if (D == PrevD)
21624 Lookups.push_back(Elt: UnresolvedSet<8>());
21625 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Val: D))
21626 Lookups.back().addDecl(D: DRD);
21627 PrevD = D;
21628 }
21629 }
21630 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
21631 Ty->isInstantiationDependentType() ||
21632 Ty->containsUnexpandedParameterPack() ||
21633 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
21634 return !D->isInvalidDecl() &&
21635 (D->getType()->isDependentType() ||
21636 D->getType()->isInstantiationDependentType() ||
21637 D->getType()->containsUnexpandedParameterPack());
21638 })) {
21639 UnresolvedSet<8> ResSet;
21640 for (const UnresolvedSet<8> &Set : Lookups) {
21641 if (Set.empty())
21642 continue;
21643 ResSet.append(I: Set.begin(), E: Set.end());
21644 // The last item marks the end of all declarations at the specified scope.
21645 ResSet.addDecl(D: Set[Set.size() - 1]);
21646 }
21647 return UnresolvedLookupExpr::Create(
21648 Context: SemaRef.Context, /*NamingClass=*/nullptr,
21649 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: SemaRef.Context), NameInfo: ReductionId,
21650 /*ADL=*/RequiresADL: true, Begin: ResSet.begin(), End: ResSet.end(), /*KnownDependent=*/false,
21651 /*KnownInstantiationDependent=*/false);
21652 }
21653 // Lookup inside the classes.
21654 // C++ [over.match.oper]p3:
21655 // For a unary operator @ with an operand of a type whose
21656 // cv-unqualified version is T1, and for a binary operator @ with
21657 // a left operand of a type whose cv-unqualified version is T1 and
21658 // a right operand of a type whose cv-unqualified version is T2,
21659 // three sets of candidate functions, designated member
21660 // candidates, non-member candidates and built-in candidates, are
21661 // constructed as follows:
21662 // -- If T1 is a complete class type or a class currently being
21663 // defined, the set of member candidates is the result of the
21664 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
21665 // the set of member candidates is empty.
21666 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
21667 Lookup.suppressDiagnostics();
21668 if (Ty->isRecordType()) {
21669 // Complete the type if it can be completed.
21670 // If the type is neither complete nor being defined, bail out now.
21671 bool IsComplete = SemaRef.isCompleteType(Loc, T: Ty);
21672 auto *RD = Ty->castAsRecordDecl();
21673 if (IsComplete || RD->isBeingDefined()) {
21674 Lookup.clear();
21675 SemaRef.LookupQualifiedName(R&: Lookup, LookupCtx: RD);
21676 if (Lookup.empty()) {
21677 Lookups.emplace_back();
21678 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
21679 }
21680 }
21681 }
21682 // Perform ADL.
21683 if (SemaRef.getLangOpts().CPlusPlus)
21684 argumentDependentLookup(SemaRef, Id: ReductionId, Loc, Ty, Lookups);
21685 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21686 Lookups, Gen: [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
21687 if (!D->isInvalidDecl() &&
21688 SemaRef.Context.hasSameType(T1: D->getType(), T2: Ty))
21689 return D;
21690 return nullptr;
21691 }))
21692 return SemaRef.BuildDeclRefExpr(D: VD, Ty: VD->getType().getNonReferenceType(),
21693 VK: VK_LValue, Loc);
21694 if (SemaRef.getLangOpts().CPlusPlus) {
21695 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21696 Lookups, Gen: [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
21697 if (!D->isInvalidDecl() &&
21698 SemaRef.IsDerivedFrom(Loc, Derived: Ty, Base: D->getType()) &&
21699 !Ty.isMoreQualifiedThan(other: D->getType(),
21700 Ctx: SemaRef.getASTContext()))
21701 return D;
21702 return nullptr;
21703 })) {
21704 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21705 /*DetectVirtual=*/false);
21706 if (SemaRef.IsDerivedFrom(Loc, Derived: Ty, Base: VD->getType(), Paths)) {
21707 if (!Paths.isAmbiguous(BaseType: SemaRef.Context.getCanonicalType(
21708 T: VD->getType().getUnqualifiedType()))) {
21709 if (SemaRef.CheckBaseClassAccess(
21710 AccessLoc: Loc, Base: VD->getType(), Derived: Ty, Path: Paths.front(),
21711 /*DiagID=*/0) != Sema::AR_inaccessible) {
21712 SemaRef.BuildBasePathArray(Paths, BasePath);
21713 return SemaRef.BuildDeclRefExpr(
21714 D: VD, Ty: VD->getType().getNonReferenceType(), VK: VK_LValue, Loc);
21715 }
21716 }
21717 }
21718 }
21719 }
21720 if (ReductionIdScopeSpec.isSet()) {
21721 SemaRef.Diag(Loc, DiagID: diag::err_omp_not_resolved_reduction_identifier)
21722 << Ty << Range;
21723 return ExprError();
21724 }
21725 return ExprEmpty();
21726}
21727
21728namespace {
21729/// Data for the reduction-based clauses.
21730struct ReductionData {
21731 /// List of original reduction items.
21732 SmallVector<Expr *, 8> Vars;
21733 /// List of private copies of the reduction items.
21734 SmallVector<Expr *, 8> Privates;
21735 /// LHS expressions for the reduction_op expressions.
21736 SmallVector<Expr *, 8> LHSs;
21737 /// RHS expressions for the reduction_op expressions.
21738 SmallVector<Expr *, 8> RHSs;
21739 /// Reduction operation expression.
21740 SmallVector<Expr *, 8> ReductionOps;
21741 /// inscan copy operation expressions.
21742 SmallVector<Expr *, 8> InscanCopyOps;
21743 /// inscan copy temp array expressions for prefix sums.
21744 SmallVector<Expr *, 8> InscanCopyArrayTemps;
21745 /// inscan copy temp array element expressions for prefix sums.
21746 SmallVector<Expr *, 8> InscanCopyArrayElems;
21747 /// Taskgroup descriptors for the corresponding reduction items in
21748 /// in_reduction clauses.
21749 SmallVector<Expr *, 8> TaskgroupDescriptors;
21750 /// List of captures for clause.
21751 SmallVector<Decl *, 4> ExprCaptures;
21752 /// List of postupdate expressions.
21753 SmallVector<Expr *, 4> ExprPostUpdates;
21754 /// Reduction modifier.
21755 unsigned RedModifier = 0;
21756 /// Original modifier.
21757 unsigned OrigSharingModifier = 0;
21758 /// Private Variable Reduction
21759 SmallVector<bool, 8> IsPrivateVarReduction;
21760 ReductionData() = delete;
21761 /// Reserves required memory for the reduction data.
21762 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
21763 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
21764 Vars.reserve(N: Size);
21765 Privates.reserve(N: Size);
21766 LHSs.reserve(N: Size);
21767 RHSs.reserve(N: Size);
21768 ReductionOps.reserve(N: Size);
21769 IsPrivateVarReduction.reserve(N: Size);
21770 if (RedModifier == OMPC_REDUCTION_inscan) {
21771 InscanCopyOps.reserve(N: Size);
21772 InscanCopyArrayTemps.reserve(N: Size);
21773 InscanCopyArrayElems.reserve(N: Size);
21774 }
21775 TaskgroupDescriptors.reserve(N: Size);
21776 ExprCaptures.reserve(N: Size);
21777 ExprPostUpdates.reserve(N: Size);
21778 }
21779 /// Stores reduction item and reduction operation only (required for dependent
21780 /// reduction item).
21781 void push(Expr *Item, Expr *ReductionOp) {
21782 Vars.emplace_back(Args&: Item);
21783 Privates.emplace_back(Args: nullptr);
21784 LHSs.emplace_back(Args: nullptr);
21785 RHSs.emplace_back(Args: nullptr);
21786 ReductionOps.emplace_back(Args&: ReductionOp);
21787 IsPrivateVarReduction.emplace_back(Args: false);
21788 TaskgroupDescriptors.emplace_back(Args: nullptr);
21789 if (RedModifier == OMPC_REDUCTION_inscan) {
21790 InscanCopyOps.push_back(Elt: nullptr);
21791 InscanCopyArrayTemps.push_back(Elt: nullptr);
21792 InscanCopyArrayElems.push_back(Elt: nullptr);
21793 }
21794 }
21795 /// Stores reduction data.
21796 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
21797 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
21798 Expr *CopyArrayElem, bool IsPrivate) {
21799 Vars.emplace_back(Args&: Item);
21800 Privates.emplace_back(Args&: Private);
21801 LHSs.emplace_back(Args&: LHS);
21802 RHSs.emplace_back(Args&: RHS);
21803 ReductionOps.emplace_back(Args&: ReductionOp);
21804 TaskgroupDescriptors.emplace_back(Args&: TaskgroupDescriptor);
21805 if (RedModifier == OMPC_REDUCTION_inscan) {
21806 InscanCopyOps.push_back(Elt: CopyOp);
21807 InscanCopyArrayTemps.push_back(Elt: CopyArrayTemp);
21808 InscanCopyArrayElems.push_back(Elt: CopyArrayElem);
21809 } else {
21810 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
21811 CopyArrayElem == nullptr &&
21812 "Copy operation must be used for inscan reductions only.");
21813 }
21814 IsPrivateVarReduction.emplace_back(Args&: IsPrivate);
21815 }
21816};
21817} // namespace
21818
21819static bool checkOMPArraySectionConstantForReduction(
21820 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
21821 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
21822 const Expr *Length = OASE->getLength();
21823 if (Length == nullptr) {
21824 // For array sections of the form [1:] or [:], we would need to analyze
21825 // the lower bound...
21826 if (OASE->getColonLocFirst().isValid())
21827 return false;
21828
21829 // This is an array subscript which has implicit length 1!
21830 SingleElement = true;
21831 ArraySizes.push_back(Elt: llvm::APSInt::get(X: 1));
21832 } else {
21833 Expr::EvalResult Result;
21834 if (!Length->EvaluateAsInt(Result, Ctx: Context))
21835 return false;
21836
21837 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
21838 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
21839 ArraySizes.push_back(Elt: ConstantLengthValue);
21840 }
21841
21842 // Get the base of this array section and walk up from there.
21843 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
21844
21845 // We require length = 1 for all array sections except the right-most to
21846 // guarantee that the memory region is contiguous and has no holes in it.
21847 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Val: Base)) {
21848 Length = TempOASE->getLength();
21849 if (Length == nullptr) {
21850 // For array sections of the form [1:] or [:], we would need to analyze
21851 // the lower bound...
21852 if (OASE->getColonLocFirst().isValid())
21853 return false;
21854
21855 // This is an array subscript which has implicit length 1!
21856 llvm::APSInt ConstantOne = llvm::APSInt::get(X: 1);
21857 ArraySizes.push_back(Elt: ConstantOne);
21858 } else {
21859 Expr::EvalResult Result;
21860 if (!Length->EvaluateAsInt(Result, Ctx: Context))
21861 return false;
21862
21863 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
21864 if (ConstantLengthValue.getSExtValue() != 1)
21865 return false;
21866
21867 ArraySizes.push_back(Elt: ConstantLengthValue);
21868 }
21869 Base = TempOASE->getBase()->IgnoreParenImpCasts();
21870 }
21871
21872 // If we have a single element, we don't need to add the implicit lengths.
21873 if (!SingleElement) {
21874 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base)) {
21875 // Has implicit length 1!
21876 llvm::APSInt ConstantOne = llvm::APSInt::get(X: 1);
21877 ArraySizes.push_back(Elt: ConstantOne);
21878 Base = TempASE->getBase()->IgnoreParenImpCasts();
21879 }
21880 }
21881
21882 // This array section can be privatized as a single value or as a constant
21883 // sized array.
21884 return true;
21885}
21886
21887static BinaryOperatorKind
21888getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
21889 if (BOK == BO_Add)
21890 return BO_AddAssign;
21891 if (BOK == BO_Mul)
21892 return BO_MulAssign;
21893 if (BOK == BO_And)
21894 return BO_AndAssign;
21895 if (BOK == BO_Or)
21896 return BO_OrAssign;
21897 if (BOK == BO_Xor)
21898 return BO_XorAssign;
21899 return BOK;
21900}
21901
21902static bool actOnOMPReductionKindClause(
21903 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
21904 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21905 SourceLocation ColonLoc, SourceLocation EndLoc,
21906 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
21907 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
21908 DeclarationName DN = ReductionId.getName();
21909 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
21910 BinaryOperatorKind BOK = BO_Comma;
21911
21912 ASTContext &Context = S.Context;
21913 // OpenMP [2.14.3.6, reduction clause]
21914 // C
21915 // reduction-identifier is either an identifier or one of the following
21916 // operators: +, -, *, &, |, ^, && and ||
21917 // C++
21918 // reduction-identifier is either an id-expression or one of the following
21919 // operators: +, -, *, &, |, ^, && and ||
21920 switch (OOK) {
21921 case OO_Plus:
21922 BOK = BO_Add;
21923 break;
21924 case OO_Minus:
21925 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
21926 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
21927 // reduction identifier.
21928 if (S.LangOpts.OpenMP > 52)
21929 BOK = BO_Comma;
21930 else
21931 BOK = BO_Add;
21932 break;
21933 case OO_Star:
21934 BOK = BO_Mul;
21935 break;
21936 case OO_Amp:
21937 BOK = BO_And;
21938 break;
21939 case OO_Pipe:
21940 BOK = BO_Or;
21941 break;
21942 case OO_Caret:
21943 BOK = BO_Xor;
21944 break;
21945 case OO_AmpAmp:
21946 BOK = BO_LAnd;
21947 break;
21948 case OO_PipePipe:
21949 BOK = BO_LOr;
21950 break;
21951 case OO_New:
21952 case OO_Delete:
21953 case OO_Array_New:
21954 case OO_Array_Delete:
21955 case OO_Slash:
21956 case OO_Percent:
21957 case OO_Tilde:
21958 case OO_Exclaim:
21959 case OO_Equal:
21960 case OO_Less:
21961 case OO_Greater:
21962 case OO_LessEqual:
21963 case OO_GreaterEqual:
21964 case OO_PlusEqual:
21965 case OO_MinusEqual:
21966 case OO_StarEqual:
21967 case OO_SlashEqual:
21968 case OO_PercentEqual:
21969 case OO_CaretEqual:
21970 case OO_AmpEqual:
21971 case OO_PipeEqual:
21972 case OO_LessLess:
21973 case OO_GreaterGreater:
21974 case OO_LessLessEqual:
21975 case OO_GreaterGreaterEqual:
21976 case OO_EqualEqual:
21977 case OO_ExclaimEqual:
21978 case OO_Spaceship:
21979 case OO_PlusPlus:
21980 case OO_MinusMinus:
21981 case OO_Comma:
21982 case OO_ArrowStar:
21983 case OO_Arrow:
21984 case OO_Call:
21985 case OO_Subscript:
21986 case OO_Conditional:
21987 case OO_Coawait:
21988 case NUM_OVERLOADED_OPERATORS:
21989 llvm_unreachable("Unexpected reduction identifier");
21990 case OO_None:
21991 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
21992 if (II->isStr(Str: "max"))
21993 BOK = BO_GT;
21994 else if (II->isStr(Str: "min"))
21995 BOK = BO_LT;
21996 }
21997 break;
21998 }
21999
22000 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
22001 // A reduction clause with the minus (-) operator was deprecated
22002 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
22003 S.Diag(Loc: ReductionId.getLoc(), DiagID: diag::warn_omp_minus_in_reduction_deprecated);
22004
22005 SourceRange ReductionIdRange;
22006 if (ReductionIdScopeSpec.isValid())
22007 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
22008 else
22009 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
22010 ReductionIdRange.setEnd(ReductionId.getEndLoc());
22011
22012 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
22013 bool FirstIter = true;
22014 for (Expr *RefExpr : VarList) {
22015 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
22016 // OpenMP [2.1, C/C++]
22017 // A list item is a variable or array section, subject to the restrictions
22018 // specified in Section 2.4 on page 42 and in each of the sections
22019 // describing clauses and directives for which a list appears.
22020 // OpenMP [2.14.3.3, Restrictions, p.1]
22021 // A variable that is part of another variable (as an array or
22022 // structure element) cannot appear in a private clause.
22023 if (!FirstIter && IR != ER)
22024 ++IR;
22025 FirstIter = false;
22026 SourceLocation ELoc;
22027 SourceRange ERange;
22028 bool IsPrivate = false;
22029 Expr *SimpleRefExpr = RefExpr;
22030 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
22031 /*AllowArraySection=*/true);
22032 if (Res.second) {
22033 // Try to find 'declare reduction' corresponding construct before using
22034 // builtin/overloaded operators.
22035 QualType Type = Context.DependentTy;
22036 CXXCastPath BasePath;
22037 ExprResult DeclareReductionRef = buildDeclareReductionRef(
22038 SemaRef&: S, Loc: ELoc, Range: ERange, S: Stack->getCurScope(), ReductionIdScopeSpec,
22039 ReductionId, Ty: Type, BasePath, UnresolvedReduction: IR == ER ? nullptr : *IR);
22040 Expr *ReductionOp = nullptr;
22041 if (S.CurContext->isDependentContext() &&
22042 (DeclareReductionRef.isUnset() ||
22043 isa<UnresolvedLookupExpr>(Val: DeclareReductionRef.get())))
22044 ReductionOp = DeclareReductionRef.get();
22045 // It will be analyzed later.
22046 RD.push(Item: RefExpr, ReductionOp);
22047 }
22048 ValueDecl *D = Res.first;
22049 if (!D)
22050 continue;
22051
22052 Expr *TaskgroupDescriptor = nullptr;
22053 QualType Type;
22054 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: RefExpr->IgnoreParens());
22055 auto *OASE = dyn_cast<ArraySectionExpr>(Val: RefExpr->IgnoreParens());
22056 if (ASE) {
22057 Type = ASE->getType().getNonReferenceType();
22058 } else if (OASE) {
22059 QualType BaseType =
22060 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
22061 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22062 Type = ATy->getElementType();
22063 else
22064 Type = BaseType->getPointeeType();
22065 Type = Type.getNonReferenceType();
22066 } else {
22067 Type = Context.getBaseElementType(QT: D->getType().getNonReferenceType());
22068 }
22069 auto *VD = dyn_cast<VarDecl>(Val: D);
22070
22071 auto *BD = dyn_cast<BindingDecl>(Val: D);
22072 if (BD) {
22073 // FIXME: reductions on bindings are rejected.
22074 S.Diag(Loc: ELoc, DiagID: diag::err_omp_unsupported_on_binding) << 0;
22075 continue;
22076 }
22077
22078 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
22079 // A variable that appears in a private clause must not have an incomplete
22080 // type or a reference type.
22081 if (S.RequireCompleteType(Loc: ELoc, T: D->getType(),
22082 DiagID: diag::err_omp_reduction_incomplete_type))
22083 continue;
22084 // OpenMP [2.14.3.6, reduction clause, Restrictions]
22085 // A list item that appears in a reduction clause must not be
22086 // const-qualified.
22087 if (rejectConstNotMutableType(SemaRef&: S, D, Type, CKind: ClauseKind, ELoc,
22088 /*AcceptIfMutable=*/false, ListItemNotVar: ASE || OASE))
22089 continue;
22090
22091 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
22092 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
22093 // If a list-item is a reference type then it must bind to the same object
22094 // for all threads of the team.
22095 if (!ASE && !OASE) {
22096 if (VD) {
22097 VarDecl *VDDef = VD->getDefinition();
22098 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
22099 DSARefChecker Check(Stack);
22100 if (Check.Visit(S: VDDef->getInit())) {
22101 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_ref_type_arg)
22102 << getOpenMPClauseNameForDiag(C: ClauseKind) << ERange;
22103 S.Diag(Loc: VDDef->getLocation(), DiagID: diag::note_defined_here) << VDDef;
22104 continue;
22105 }
22106 }
22107 }
22108
22109 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
22110 // in a Construct]
22111 // Variables with the predetermined data-sharing attributes may not be
22112 // listed in data-sharing attributes clauses, except for the cases
22113 // listed below. For these exceptions only, listing a predetermined
22114 // variable in a data-sharing attribute clause is allowed and overrides
22115 // the variable's predetermined data-sharing attributes.
22116 // OpenMP [2.14.3.6, Restrictions, p.3]
22117 // Any number of reduction clauses can be specified on the directive,
22118 // but a list item can appear only once in the reduction clauses for that
22119 // directive.
22120 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
22121 if (DVar.CKind == OMPC_reduction) {
22122 S.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced)
22123 << getOpenMPClauseNameForDiag(C: ClauseKind);
22124 if (DVar.RefExpr)
22125 S.Diag(Loc: DVar.RefExpr->getExprLoc(), DiagID: diag::note_omp_referenced);
22126 continue;
22127 }
22128 if (DVar.CKind != OMPC_unknown) {
22129 S.Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
22130 << getOpenMPClauseNameForDiag(C: DVar.CKind)
22131 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
22132 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
22133 continue;
22134 }
22135
22136 // OpenMP [2.14.3.6, Restrictions, p.1]
22137 // A list item that appears in a reduction clause of a worksharing
22138 // construct must be shared in the parallel regions to which any of the
22139 // worksharing regions arising from the worksharing construct bind.
22140
22141 if (S.getLangOpts().OpenMP <= 52 &&
22142 isOpenMPWorksharingDirective(DKind: CurrDir) &&
22143 !isOpenMPParallelDirective(DKind: CurrDir) &&
22144 !isOpenMPTeamsDirective(DKind: CurrDir)) {
22145 DVar = Stack->getImplicitDSA(D, FromParent: true);
22146 if (DVar.CKind != OMPC_shared) {
22147 S.Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
22148 << getOpenMPClauseNameForDiag(C: OMPC_reduction)
22149 << getOpenMPClauseNameForDiag(C: OMPC_shared);
22150 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
22151 continue;
22152 }
22153 } else if (isOpenMPWorksharingDirective(DKind: CurrDir) &&
22154 !isOpenMPParallelDirective(DKind: CurrDir) &&
22155 !isOpenMPTeamsDirective(DKind: CurrDir)) {
22156 // OpenMP 6.0 [ 7.6.10 ]
22157 // Support Reduction over private variables with reduction clause.
22158 // A list item in a reduction clause can now be private in the enclosing
22159 // context. For orphaned constructs it is assumed to be shared unless
22160 // the original(private) modifier appears in the clause.
22161 DVar = Stack->getImplicitDSA(D, FromParent: true);
22162 // Determine if the variable should be considered private
22163 IsPrivate = DVar.CKind != OMPC_shared;
22164 bool IsOrphaned = false;
22165 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
22166 IsOrphaned = ParentDir == OMPD_unknown;
22167 if ((IsOrphaned &&
22168 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
22169 IsPrivate = true;
22170 }
22171 } else {
22172 // Threadprivates cannot be shared between threads, so dignose if the base
22173 // is a threadprivate variable.
22174 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
22175 if (DVar.CKind == OMPC_threadprivate) {
22176 S.Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
22177 << getOpenMPClauseNameForDiag(C: DVar.CKind)
22178 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
22179 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
22180 continue;
22181 }
22182 }
22183
22184 // Try to find 'declare reduction' corresponding construct before using
22185 // builtin/overloaded operators.
22186 CXXCastPath BasePath;
22187 ExprResult DeclareReductionRef = buildDeclareReductionRef(
22188 SemaRef&: S, Loc: ELoc, Range: ERange, S: Stack->getCurScope(), ReductionIdScopeSpec,
22189 ReductionId, Ty: Type, BasePath, UnresolvedReduction: IR == ER ? nullptr : *IR);
22190 if (DeclareReductionRef.isInvalid())
22191 continue;
22192 if (S.CurContext->isDependentContext() &&
22193 (DeclareReductionRef.isUnset() ||
22194 isa<UnresolvedLookupExpr>(Val: DeclareReductionRef.get()))) {
22195 RD.push(Item: RefExpr, ReductionOp: DeclareReductionRef.get());
22196 // Handle non-dependent inscan reduction variables in dependent contexts.
22197 if (RD.RedModifier == OMPC_REDUCTION_inscan)
22198 Stack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_reduction, PrivateCopy: nullptr,
22199 Modifier: RD.RedModifier, AppliedToPointee: ASE || OASE);
22200 continue;
22201 }
22202 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
22203 // Not allowed reduction identifier is found.
22204 if (S.LangOpts.OpenMP > 52)
22205 S.Diag(Loc: ReductionId.getBeginLoc(),
22206 DiagID: diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
22207 << Type << ReductionIdRange;
22208 else
22209 S.Diag(Loc: ReductionId.getBeginLoc(),
22210 DiagID: diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
22211 << Type << ReductionIdRange;
22212 continue;
22213 }
22214
22215 // OpenMP [2.14.3.6, reduction clause, Restrictions]
22216 // The type of a list item that appears in a reduction clause must be valid
22217 // for the reduction-identifier. For a max or min reduction in C, the type
22218 // of the list item must be an allowed arithmetic data type: char, int,
22219 // float, double, or _Bool, possibly modified with long, short, signed, or
22220 // unsigned. For a max or min reduction in C++, the type of the list item
22221 // must be an allowed arithmetic data type: char, wchar_t, int, float,
22222 // double, or bool, possibly modified with long, short, signed, or unsigned.
22223 if (DeclareReductionRef.isUnset()) {
22224 if ((BOK == BO_GT || BOK == BO_LT) &&
22225 !(Type->isScalarType() ||
22226 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
22227 S.Diag(Loc: ELoc, DiagID: diag::err_omp_clause_not_arithmetic_type_arg)
22228 << getOpenMPClauseNameForDiag(C: ClauseKind)
22229 << S.getLangOpts().CPlusPlus;
22230 if (!ASE && !OASE) {
22231 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
22232 VarDecl::DeclarationOnly;
22233 S.Diag(Loc: D->getLocation(),
22234 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
22235 << D;
22236 }
22237 continue;
22238 }
22239 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
22240 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
22241 S.Diag(Loc: ELoc, DiagID: diag::err_omp_clause_floating_type_arg)
22242 << getOpenMPClauseNameForDiag(C: ClauseKind);
22243 if (!ASE && !OASE) {
22244 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
22245 VarDecl::DeclarationOnly;
22246 S.Diag(Loc: D->getLocation(),
22247 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
22248 << D;
22249 }
22250 continue;
22251 }
22252 }
22253
22254 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
22255 VarDecl *LHSVD = buildVarDecl(SemaRef&: S, Loc: ELoc, Type, Name: ".reduction.lhs",
22256 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
22257 VarDecl *RHSVD = buildVarDecl(SemaRef&: S, Loc: ELoc, Type, Name: D->getName(),
22258 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
22259 QualType PrivateTy = Type;
22260
22261 // Try if we can determine constant lengths for all array sections and avoid
22262 // the VLA.
22263 bool ConstantLengthOASE = false;
22264 if (OASE) {
22265 bool SingleElement;
22266 llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
22267 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
22268 Context, OASE, SingleElement, ArraySizes);
22269
22270 // If we don't have a single element, we must emit a constant array type.
22271 if (ConstantLengthOASE && !SingleElement) {
22272 for (llvm::APSInt &Size : ArraySizes)
22273 PrivateTy = Context.getConstantArrayType(EltTy: PrivateTy, ArySize: Size, SizeExpr: nullptr,
22274 ASM: ArraySizeModifier::Normal,
22275 /*IndexTypeQuals=*/0);
22276 }
22277 }
22278
22279 if ((OASE && !ConstantLengthOASE) ||
22280 (!OASE && !ASE &&
22281 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
22282 if (!Context.getTargetInfo().isVLASupported()) {
22283 if (isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective())) {
22284 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_vla_unsupported) << !!OASE;
22285 S.Diag(Loc: ELoc, DiagID: diag::note_vla_unsupported);
22286 continue;
22287 } else {
22288 S.targetDiag(Loc: ELoc, DiagID: diag::err_omp_reduction_vla_unsupported) << !!OASE;
22289 S.targetDiag(Loc: ELoc, DiagID: diag::note_vla_unsupported);
22290 }
22291 }
22292 // For arrays/array sections only:
22293 // Create pseudo array type for private copy. The size for this array will
22294 // be generated during codegen.
22295 // For array subscripts or single variables Private Ty is the same as Type
22296 // (type of the variable or single array element).
22297 PrivateTy = Context.getVariableArrayType(
22298 EltTy: Type,
22299 NumElts: new (Context)
22300 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
22301 ASM: ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
22302 } else if (!ASE && !OASE &&
22303 Context.getAsArrayType(T: D->getType().getNonReferenceType())) {
22304 PrivateTy = D->getType().getNonReferenceType();
22305 }
22306 // Private copy.
22307 VarDecl *PrivateVD =
22308 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: PrivateTy, Name: D->getName(),
22309 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
22310 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
22311 // Add initializer for private variable.
22312 Expr *Init = nullptr;
22313 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, D: LHSVD, Ty: Type, Loc: ELoc);
22314 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, D: RHSVD, Ty: Type, Loc: ELoc);
22315 if (DeclareReductionRef.isUsable()) {
22316 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
22317 auto *DRD = cast<OMPDeclareReductionDecl>(Val: DRDRef->getDecl());
22318 if (DRD->getInitializer()) {
22319 Init = DRDRef;
22320 RHSVD->setInit(DRDRef);
22321 RHSVD->setInitStyle(VarDecl::CallInit);
22322 }
22323 } else {
22324 switch (BOK) {
22325 case BO_Add:
22326 case BO_Xor:
22327 case BO_Or:
22328 case BO_LOr:
22329 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
22330 if (Type->isScalarType() || Type->isAnyComplexType())
22331 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/0).get();
22332 break;
22333 case BO_Mul:
22334 // '*' reduction op - initializer is '1'.
22335 // For C++ class types (e.g. std::complex) the OpenMP built-in
22336 // reduction identifiers are an extension: the standard only defines
22337 // identities for arithmetic (and, in Clang, _Complex) types. Without
22338 // an explicit initializer the private copy would be value-initialized,
22339 // which yields the *additive* identity (e.g. std::complex(0,0)) and is
22340 // wrong for multiplication. Initialize from the integer literal '1'
22341 // instead and let the converting constructor build the multiplicative
22342 // identity (e.g. std::complex(1) == (1,0)).
22343 if (Type->isScalarType() || Type->isAnyComplexType()) {
22344 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
22345 } else if (S.getLangOpts().CPlusPlus && Type->isRecordType()) {
22346 // Only use '1' when the type is actually copy-initializable from it.
22347 // Otherwise fall back to value-initialization (the previous behavior)
22348 // rather than rejecting the reduction, so a class that used to
22349 // compile keeps compiling. Such a class keeps its (possibly
22350 // incorrect) value-initialized identity, matching the pre-existing
22351 // behavior; BO_Add likewise relies on value-initialization for class
22352 // types.
22353 Expr *One = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
22354 InitializedEntity Entity =
22355 InitializedEntity::InitializeTemporary(Type);
22356 InitializationKind Kind = InitializationKind::CreateCopy(InitLoc: ELoc, EqualLoc: ELoc);
22357 InitializationSequence Seq(S, Entity, Kind, One);
22358 if (Seq)
22359 Init = One;
22360 }
22361 break;
22362 case BO_LAnd:
22363 if (Type->isScalarType() || Type->isAnyComplexType()) {
22364 // '&&' reduction ops - initializer is '1'.
22365 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
22366 }
22367 break;
22368 case BO_And: {
22369 // '&' reduction op - initializer is '~0'.
22370 QualType OrigType = Type;
22371 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
22372 Type = ComplexTy->getElementType();
22373 if (Type->isRealFloatingType()) {
22374 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
22375 Semantics: Context.getFloatTypeSemantics(T: Type));
22376 Init = FloatingLiteral::Create(C: Context, V: InitValue, /*isexact=*/true,
22377 Type, L: ELoc);
22378 } else if (Type->isScalarType()) {
22379 uint64_t Size = Context.getTypeSize(T: Type);
22380 QualType IntTy = Context.getIntTypeForBitwidth(DestWidth: Size, /*Signed=*/0);
22381 llvm::APInt InitValue = llvm::APInt::getAllOnes(numBits: Size);
22382 Init = IntegerLiteral::Create(C: Context, V: InitValue, type: IntTy, l: ELoc);
22383 }
22384 if (Init && OrigType->isAnyComplexType()) {
22385 // Init = 0xFFFF + 0xFFFFi;
22386 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
22387 Init = S.CreateBuiltinBinOp(OpLoc: ELoc, Opc: BO_Add, LHSExpr: Init, RHSExpr: Im).get();
22388 }
22389 Type = OrigType;
22390 break;
22391 }
22392 case BO_LT:
22393 case BO_GT: {
22394 // 'min' reduction op - initializer is 'Largest representable number in
22395 // the reduction list item type'.
22396 // 'max' reduction op - initializer is 'Least representable number in
22397 // the reduction list item type'.
22398 if (Type->isIntegerType() || Type->isPointerType()) {
22399 bool IsSigned = Type->hasSignedIntegerRepresentation();
22400 uint64_t Size = Context.getTypeSize(T: Type);
22401 QualType IntTy =
22402 Context.getIntTypeForBitwidth(DestWidth: Size, /*Signed=*/IsSigned);
22403 llvm::APInt InitValue =
22404 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(numBits: Size)
22405 : llvm::APInt::getMinValue(numBits: Size)
22406 : IsSigned ? llvm::APInt::getSignedMaxValue(numBits: Size)
22407 : llvm::APInt::getMaxValue(numBits: Size);
22408 Init = IntegerLiteral::Create(C: Context, V: InitValue, type: IntTy, l: ELoc);
22409 if (Type->isPointerType()) {
22410 // Cast to pointer type.
22411 ExprResult CastExpr = S.BuildCStyleCastExpr(
22412 LParenLoc: ELoc, Ty: Context.getTrivialTypeSourceInfo(T: Type, Loc: ELoc), RParenLoc: ELoc, Op: Init);
22413 if (CastExpr.isInvalid())
22414 continue;
22415 Init = CastExpr.get();
22416 }
22417 } else if (Type->isRealFloatingType()) {
22418 llvm::APFloat InitValue = llvm::APFloat::getLargest(
22419 Sem: Context.getFloatTypeSemantics(T: Type), Negative: BOK != BO_LT);
22420 Init = FloatingLiteral::Create(C: Context, V: InitValue, /*isexact=*/true,
22421 Type, L: ELoc);
22422 }
22423 break;
22424 }
22425 case BO_PtrMemD:
22426 case BO_PtrMemI:
22427 case BO_MulAssign:
22428 case BO_Div:
22429 case BO_Rem:
22430 case BO_Sub:
22431 case BO_Shl:
22432 case BO_Shr:
22433 case BO_LE:
22434 case BO_GE:
22435 case BO_EQ:
22436 case BO_NE:
22437 case BO_Cmp:
22438 case BO_AndAssign:
22439 case BO_XorAssign:
22440 case BO_OrAssign:
22441 case BO_Assign:
22442 case BO_AddAssign:
22443 case BO_SubAssign:
22444 case BO_DivAssign:
22445 case BO_RemAssign:
22446 case BO_ShlAssign:
22447 case BO_ShrAssign:
22448 case BO_Comma:
22449 llvm_unreachable("Unexpected reduction operation");
22450 }
22451 }
22452 if (Init && DeclareReductionRef.isUnset()) {
22453 S.AddInitializerToDecl(dcl: RHSVD, init: Init, /*DirectInit=*/false);
22454 // Store initializer for single element in private copy. Will be used
22455 // during codegen.
22456 PrivateVD->setInit(RHSVD->getInit());
22457 PrivateVD->setInitStyle(RHSVD->getInitStyle());
22458 } else if (!Init) {
22459 S.ActOnUninitializedDecl(dcl: RHSVD);
22460 // Store initializer for single element in private copy. Will be used
22461 // during codegen.
22462 PrivateVD->setInit(RHSVD->getInit());
22463 PrivateVD->setInitStyle(RHSVD->getInitStyle());
22464 }
22465 if (RHSVD->isInvalidDecl())
22466 continue;
22467 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
22468 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_id_not_compatible)
22469 << Type << ReductionIdRange;
22470 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
22471 VarDecl::DeclarationOnly;
22472 S.Diag(Loc: D->getLocation(),
22473 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
22474 << D;
22475 continue;
22476 }
22477 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, D: PrivateVD, Ty: PrivateTy, Loc: ELoc);
22478 ExprResult ReductionOp;
22479 if (DeclareReductionRef.isUsable()) {
22480 QualType RedTy = DeclareReductionRef.get()->getType();
22481 QualType PtrRedTy = Context.getPointerType(T: RedTy);
22482 ExprResult LHS = S.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: LHSDRE);
22483 ExprResult RHS = S.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: RHSDRE);
22484 if (!BasePath.empty()) {
22485 LHS = S.DefaultLvalueConversion(E: LHS.get());
22486 RHS = S.DefaultLvalueConversion(E: RHS.get());
22487 LHS = ImplicitCastExpr::Create(
22488 Context, T: PtrRedTy, Kind: CK_UncheckedDerivedToBase, Operand: LHS.get(), BasePath: &BasePath,
22489 Cat: LHS.get()->getValueKind(), FPO: FPOptionsOverride());
22490 RHS = ImplicitCastExpr::Create(
22491 Context, T: PtrRedTy, Kind: CK_UncheckedDerivedToBase, Operand: RHS.get(), BasePath: &BasePath,
22492 Cat: RHS.get()->getValueKind(), FPO: FPOptionsOverride());
22493 }
22494 FunctionProtoType::ExtProtoInfo EPI;
22495 QualType Params[] = {PtrRedTy, PtrRedTy};
22496 QualType FnTy = Context.getFunctionType(ResultTy: Context.VoidTy, Args: Params, EPI);
22497 auto *OVE = new (Context) OpaqueValueExpr(
22498 ELoc, Context.getPointerType(T: FnTy), VK_PRValue, OK_Ordinary,
22499 S.DefaultLvalueConversion(E: DeclareReductionRef.get()).get());
22500 Expr *Args[] = {LHS.get(), RHS.get()};
22501 ReductionOp =
22502 CallExpr::Create(Ctx: Context, Fn: OVE, Args, Ty: Context.VoidTy, VK: VK_PRValue, RParenLoc: ELoc,
22503 FPFeatures: S.CurFPFeatureOverrides());
22504 } else {
22505 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
22506 if (Type->isRecordType() && CombBOK != BOK) {
22507 Sema::TentativeAnalysisScope Trap(S);
22508 ReductionOp =
22509 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
22510 Opc: CombBOK, LHSExpr: LHSDRE, RHSExpr: RHSDRE);
22511 }
22512 if (!ReductionOp.isUsable()) {
22513 ReductionOp =
22514 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(), Opc: BOK,
22515 LHSExpr: LHSDRE, RHSExpr: RHSDRE);
22516 if (ReductionOp.isUsable()) {
22517 if (BOK != BO_LT && BOK != BO_GT) {
22518 ReductionOp =
22519 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
22520 Opc: BO_Assign, LHSExpr: LHSDRE, RHSExpr: ReductionOp.get());
22521 } else {
22522 auto *ConditionalOp = new (Context)
22523 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
22524 RHSDRE, Type, VK_LValue, OK_Ordinary);
22525 ReductionOp =
22526 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
22527 Opc: BO_Assign, LHSExpr: LHSDRE, RHSExpr: ConditionalOp);
22528 }
22529 }
22530 }
22531 if (ReductionOp.isUsable())
22532 ReductionOp = S.ActOnFinishFullExpr(Expr: ReductionOp.get(),
22533 /*DiscardedValue=*/false);
22534 if (!ReductionOp.isUsable())
22535 continue;
22536 }
22537
22538 // Add copy operations for inscan reductions.
22539 // LHS = RHS;
22540 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
22541 if (ClauseKind == OMPC_reduction &&
22542 RD.RedModifier == OMPC_REDUCTION_inscan) {
22543 ExprResult RHS = S.DefaultLvalueConversion(E: RHSDRE);
22544 CopyOpRes = S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: LHSDRE,
22545 RHSExpr: RHS.get());
22546 if (!CopyOpRes.isUsable())
22547 continue;
22548 CopyOpRes =
22549 S.ActOnFinishFullExpr(Expr: CopyOpRes.get(), /*DiscardedValue=*/true);
22550 if (!CopyOpRes.isUsable())
22551 continue;
22552 // For simd directive and simd-based directives in simd mode no need to
22553 // construct temp array, need just a single temp element.
22554 if (Stack->getCurrentDirective() == OMPD_simd ||
22555 (S.getLangOpts().OpenMPSimd &&
22556 isOpenMPSimdDirective(DKind: Stack->getCurrentDirective()))) {
22557 VarDecl *TempArrayVD =
22558 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: PrivateTy, Name: D->getName(),
22559 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
22560 // Add a constructor to the temp decl.
22561 S.ActOnUninitializedDecl(dcl: TempArrayVD);
22562 TempArrayRes = buildDeclRefExpr(S, D: TempArrayVD, Ty: PrivateTy, Loc: ELoc);
22563 } else {
22564 // Build temp array for prefix sum.
22565 auto *Dim = new (S.Context)
22566 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
22567 QualType ArrayTy = S.Context.getVariableArrayType(
22568 EltTy: PrivateTy, NumElts: Dim, ASM: ArraySizeModifier::Normal,
22569 /*IndexTypeQuals=*/0);
22570 VarDecl *TempArrayVD =
22571 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: ArrayTy, Name: D->getName(),
22572 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
22573 // Add a constructor to the temp decl.
22574 S.ActOnUninitializedDecl(dcl: TempArrayVD);
22575 TempArrayRes = buildDeclRefExpr(S, D: TempArrayVD, Ty: ArrayTy, Loc: ELoc);
22576 TempArrayElem =
22577 S.DefaultFunctionArrayLvalueConversion(E: TempArrayRes.get());
22578 auto *Idx = new (S.Context)
22579 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
22580 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(Base: TempArrayElem.get(),
22581 LLoc: ELoc, Idx, RLoc: ELoc);
22582 }
22583 }
22584
22585 // OpenMP [2.15.4.6, Restrictions, p.2]
22586 // A list item that appears in an in_reduction clause of a task construct
22587 // must appear in a task_reduction clause of a construct associated with a
22588 // taskgroup region that includes the participating task in its taskgroup
22589 // set. The construct associated with the innermost region that meets this
22590 // condition must specify the same reduction-identifier as the in_reduction
22591 // clause.
22592 if (ClauseKind == OMPC_in_reduction) {
22593 SourceRange ParentSR;
22594 BinaryOperatorKind ParentBOK;
22595 const Expr *ParentReductionOp = nullptr;
22596 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
22597 DSAStackTy::DSAVarData ParentBOKDSA =
22598 Stack->getTopMostTaskgroupReductionData(D, SR&: ParentSR, BOK&: ParentBOK,
22599 TaskgroupDescriptor&: ParentBOKTD);
22600 DSAStackTy::DSAVarData ParentReductionOpDSA =
22601 Stack->getTopMostTaskgroupReductionData(
22602 D, SR&: ParentSR, ReductionRef&: ParentReductionOp, TaskgroupDescriptor&: ParentReductionOpTD);
22603 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
22604 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
22605 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
22606 (DeclareReductionRef.isUsable() && IsParentBOK) ||
22607 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
22608 bool EmitError = true;
22609 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
22610 llvm::FoldingSetNodeID RedId, ParentRedId;
22611 ParentReductionOp->Profile(ID&: ParentRedId, Context, /*Canonical=*/true);
22612 DeclareReductionRef.get()->Profile(ID&: RedId, Context,
22613 /*Canonical=*/true);
22614 EmitError = RedId != ParentRedId;
22615 }
22616 if (EmitError) {
22617 S.Diag(Loc: ReductionId.getBeginLoc(),
22618 DiagID: diag::err_omp_reduction_identifier_mismatch)
22619 << ReductionIdRange << RefExpr->getSourceRange();
22620 S.Diag(Loc: ParentSR.getBegin(),
22621 DiagID: diag::note_omp_previous_reduction_identifier)
22622 << ParentSR
22623 << (IsParentBOK ? ParentBOKDSA.RefExpr
22624 : ParentReductionOpDSA.RefExpr)
22625 ->getSourceRange();
22626 continue;
22627 }
22628 }
22629 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
22630 }
22631
22632 DeclRefExpr *Ref = nullptr;
22633 Expr *VarsExpr = RefExpr->IgnoreParens();
22634 bool IsBindingDecl = isa<BindingDecl>(Val: D);
22635 if (!VD && !IsBindingDecl && !S.CurContext->isDependentContext()) {
22636 if (ASE || OASE) {
22637 TransformExprToCaptures RebuildToCapture(S, D);
22638 VarsExpr =
22639 RebuildToCapture.TransformExpr(E: RefExpr->IgnoreParens()).get();
22640 Ref = RebuildToCapture.getCapturedExpr();
22641 } else {
22642 VarsExpr = Ref = buildCapture(S, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
22643 }
22644 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
22645 RD.ExprCaptures.emplace_back(Args: Ref->getDecl());
22646 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
22647 ExprResult RefRes = S.DefaultLvalueConversion(E: Ref);
22648 if (!RefRes.isUsable())
22649 continue;
22650 ExprResult PostUpdateRes =
22651 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: SimpleRefExpr,
22652 RHSExpr: RefRes.get());
22653 if (!PostUpdateRes.isUsable())
22654 continue;
22655 if (isOpenMPTaskingDirective(Kind: Stack->getCurrentDirective()) ||
22656 Stack->getCurrentDirective() == OMPD_taskgroup) {
22657 S.Diag(Loc: RefExpr->getExprLoc(),
22658 DiagID: diag::err_omp_reduction_non_addressable_expression)
22659 << RefExpr->getSourceRange();
22660 continue;
22661 }
22662 RD.ExprPostUpdates.emplace_back(
22663 Args: S.IgnoredValueConversions(E: PostUpdateRes.get()).get());
22664 }
22665 }
22666 }
22667 // All reduction items are still marked as reduction (to do not increase
22668 // code base size).
22669 unsigned Modifier = RD.RedModifier;
22670 // Consider task_reductions as reductions with task modifier. Required for
22671 // correct analysis of in_reduction clauses.
22672 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
22673 Modifier = OMPC_REDUCTION_task;
22674 Stack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_reduction, PrivateCopy: Ref, Modifier,
22675 AppliedToPointee: ASE || OASE);
22676 if (Modifier == OMPC_REDUCTION_task &&
22677 (CurrDir == OMPD_taskgroup ||
22678 ((isOpenMPParallelDirective(DKind: CurrDir) ||
22679 isOpenMPWorksharingDirective(DKind: CurrDir)) &&
22680 !isOpenMPSimdDirective(DKind: CurrDir)))) {
22681 if (DeclareReductionRef.isUsable())
22682 Stack->addTaskgroupReductionData(D, SR: ReductionIdRange,
22683 ReductionRef: DeclareReductionRef.get());
22684 else
22685 Stack->addTaskgroupReductionData(D, SR: ReductionIdRange, BOK);
22686 }
22687 RD.push(Item: VarsExpr, Private: PrivateDRE, LHS: LHSDRE, RHS: RHSDRE, ReductionOp: ReductionOp.get(),
22688 TaskgroupDescriptor, CopyOp: CopyOpRes.get(), CopyArrayTemp: TempArrayRes.get(),
22689 CopyArrayElem: TempArrayElem.get(), IsPrivate);
22690 }
22691 return RD.Vars.empty();
22692}
22693
22694OMPClause *SemaOpenMP::ActOnOpenMPReductionClause(
22695 ArrayRef<Expr *> VarList,
22696 OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers,
22697 SourceLocation StartLoc, SourceLocation LParenLoc,
22698 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
22699 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
22700 ArrayRef<Expr *> UnresolvedReductions) {
22701 OpenMPReductionClauseModifier Modifier =
22702 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
22703 OpenMPOriginalSharingModifier OriginalSharingModifier =
22704 static_cast<OpenMPOriginalSharingModifier>(
22705 Modifiers.OriginalSharingModifier);
22706 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
22707 Diag(Loc: LParenLoc, DiagID: diag::err_omp_unexpected_clause_value)
22708 << getListOfPossibleValues(K: OMPC_reduction, /*First=*/0,
22709 /*Last=*/OMPC_REDUCTION_unknown)
22710 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
22711 return nullptr;
22712 }
22713 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
22714 // A reduction clause with the inscan reduction-modifier may only appear on a
22715 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
22716 // construct, a parallel worksharing-loop construct or a parallel
22717 // worksharing-loop SIMD construct.
22718 if (Modifier == OMPC_REDUCTION_inscan &&
22719 (DSAStack->getCurrentDirective() != OMPD_for &&
22720 DSAStack->getCurrentDirective() != OMPD_for_simd &&
22721 DSAStack->getCurrentDirective() != OMPD_simd &&
22722 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
22723 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
22724 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_wrong_inscan_reduction);
22725 return nullptr;
22726 }
22727 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
22728 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_reduction, VarList,
22729 StartLoc, LParenLoc, ColonLoc, EndLoc,
22730 ReductionIdScopeSpec, ReductionId,
22731 UnresolvedReductions, RD))
22732 return nullptr;
22733
22734 return OMPReductionClause::Create(
22735 C: getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
22736 Modifier, VL: RD.Vars,
22737 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
22738 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps, CopyOps: RD.InscanCopyOps,
22739 CopyArrayTemps: RD.InscanCopyArrayTemps, CopyArrayElems: RD.InscanCopyArrayElems,
22740 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
22741 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates), IsPrivateVarReduction: RD.IsPrivateVarReduction,
22742 OriginalSharingModifier);
22743}
22744
22745OMPClause *SemaOpenMP::ActOnOpenMPTaskReductionClause(
22746 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
22747 SourceLocation ColonLoc, SourceLocation EndLoc,
22748 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
22749 ArrayRef<Expr *> UnresolvedReductions) {
22750 ReductionData RD(VarList.size());
22751 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_task_reduction,
22752 VarList, StartLoc, LParenLoc, ColonLoc,
22753 EndLoc, ReductionIdScopeSpec, ReductionId,
22754 UnresolvedReductions, RD))
22755 return nullptr;
22756
22757 return OMPTaskReductionClause::Create(
22758 C: getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, VL: RD.Vars,
22759 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
22760 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps,
22761 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
22762 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates));
22763}
22764
22765OMPClause *SemaOpenMP::ActOnOpenMPInReductionClause(
22766 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
22767 SourceLocation ColonLoc, SourceLocation EndLoc,
22768 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
22769 ArrayRef<Expr *> UnresolvedReductions) {
22770 ReductionData RD(VarList.size());
22771 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_in_reduction, VarList,
22772 StartLoc, LParenLoc, ColonLoc, EndLoc,
22773 ReductionIdScopeSpec, ReductionId,
22774 UnresolvedReductions, RD))
22775 return nullptr;
22776
22777 return OMPInReductionClause::Create(
22778 C: getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, VL: RD.Vars,
22779 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
22780 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps, TaskgroupDescriptors: RD.TaskgroupDescriptors,
22781 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
22782 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates));
22783}
22784
22785bool SemaOpenMP::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
22786 SourceLocation LinLoc) {
22787 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
22788 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
22789 Diag(Loc: LinLoc, DiagID: diag::err_omp_wrong_linear_modifier)
22790 << getLangOpts().CPlusPlus;
22791 return true;
22792 }
22793 return false;
22794}
22795
22796bool SemaOpenMP::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
22797 OpenMPLinearClauseKind LinKind,
22798 QualType Type, bool IsDeclareSimd) {
22799 const auto *VD = dyn_cast_or_null<VarDecl>(Val: D);
22800 // A variable must not have an incomplete type or a reference type.
22801 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
22802 DiagID: diag::err_omp_linear_incomplete_type))
22803 return true;
22804 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
22805 !Type->isReferenceType()) {
22806 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_linear_modifier_non_reference)
22807 << Type << getOpenMPSimpleClauseTypeName(Kind: OMPC_linear, Type: LinKind);
22808 return true;
22809 }
22810 Type = Type.getNonReferenceType();
22811
22812 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
22813 // A variable that is privatized must not have a const-qualified type
22814 // unless it is of class type with a mutable member. This restriction does
22815 // not apply to the firstprivate clause, nor to the linear clause on
22816 // declarative directives (like declare simd).
22817 if (!IsDeclareSimd &&
22818 rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_linear, ELoc))
22819 return true;
22820
22821 // A list item must be of integral or pointer type.
22822 Type = Type.getUnqualifiedType().getCanonicalType();
22823 const auto *Ty = Type.getTypePtrOrNull();
22824 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
22825 !Ty->isIntegralType(Ctx: getASTContext()) && !Ty->isPointerType())) {
22826 Diag(Loc: ELoc, DiagID: diag::err_omp_linear_expected_int_or_ptr) << Type;
22827 if (D) {
22828 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
22829 VarDecl::DeclarationOnly;
22830 Diag(Loc: D->getLocation(),
22831 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
22832 << D;
22833 }
22834 return true;
22835 }
22836 return false;
22837}
22838
22839OMPClause *SemaOpenMP::ActOnOpenMPLinearClause(
22840 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
22841 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
22842 SourceLocation LinLoc, SourceLocation ColonLoc,
22843 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
22844 SmallVector<Expr *, 8> Vars;
22845 SmallVector<Expr *, 8> Privates;
22846 SmallVector<Expr *, 8> Inits;
22847 SmallVector<Decl *, 4> ExprCaptures;
22848 SmallVector<Expr *, 4> ExprPostUpdates;
22849 // OpenMP 5.2 [Section 5.4.6, linear clause]
22850 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
22851 // 'ref'
22852 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
22853 getLangOpts().OpenMP >= 52)
22854 Diag(Loc: Step->getBeginLoc(), DiagID: diag::err_omp_step_simple_modifier_exclusive);
22855 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
22856 LinKind = OMPC_LINEAR_val;
22857 for (Expr *RefExpr : VarList) {
22858 assert(RefExpr && "NULL expr in OpenMP linear clause.");
22859 SourceLocation ELoc;
22860 SourceRange ERange;
22861 Expr *SimpleRefExpr = RefExpr;
22862 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
22863 if (Res.second) {
22864 // It will be analyzed later.
22865 Vars.push_back(Elt: RefExpr);
22866 Privates.push_back(Elt: nullptr);
22867 Inits.push_back(Elt: nullptr);
22868 }
22869 ValueDecl *D = Res.first;
22870 if (!D)
22871 continue;
22872
22873 // Linear on bindings only works for simple simd, not parallel constructs.
22874 if (isa<BindingDecl>(Val: D)) {
22875 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22876 if (isOpenMPParallelDirective(DKind)) {
22877 Diag(Loc: ELoc, DiagID: diag::err_omp_unsupported_on_binding) << 2;
22878 continue;
22879 }
22880 }
22881
22882 QualType Type = D->getType();
22883 auto *VD = dyn_cast<VarDecl>(Val: D);
22884
22885 // OpenMP [2.14.3.7, linear clause]
22886 // A list-item cannot appear in more than one linear clause.
22887 // A list-item that appears in a linear clause cannot appear in any
22888 // other data-sharing attribute clause.
22889 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
22890 if (DVar.RefExpr) {
22891 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
22892 << getOpenMPClauseNameForDiag(C: DVar.CKind)
22893 << getOpenMPClauseNameForDiag(C: OMPC_linear);
22894 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
22895 continue;
22896 }
22897
22898 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
22899 continue;
22900 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
22901
22902 // Build private copy of original var.
22903 VarDecl *Private =
22904 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
22905 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
22906 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
22907 DeclRefExpr *PrivateRef = buildDeclRefExpr(S&: SemaRef, D: Private, Ty: Type, Loc: ELoc);
22908 // Build var to save initial value.
22909 VarDecl *Init = buildVarDecl(SemaRef, Loc: ELoc, Type, Name: ".linear.start");
22910 Expr *InitExpr;
22911 DeclRefExpr *Ref = nullptr;
22912 bool IsBindingDecl = isa<BindingDecl>(Val: D);
22913 if (!VD && !IsBindingDecl && !SemaRef.CurContext->isDependentContext()) {
22914 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
22915 if (!isOpenMPCapturedDecl(D)) {
22916 ExprCaptures.push_back(Elt: Ref->getDecl());
22917 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
22918 ExprResult RefRes = SemaRef.DefaultLvalueConversion(E: Ref);
22919 if (!RefRes.isUsable())
22920 continue;
22921 ExprResult PostUpdateRes =
22922 SemaRef.BuildBinOp(DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign,
22923 LHSExpr: SimpleRefExpr, RHSExpr: RefRes.get());
22924 if (!PostUpdateRes.isUsable())
22925 continue;
22926 ExprPostUpdates.push_back(
22927 Elt: SemaRef.IgnoredValueConversions(E: PostUpdateRes.get()).get());
22928 }
22929 }
22930 }
22931 if (LinKind == OMPC_LINEAR_uval)
22932 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
22933 else
22934 InitExpr = (VD || IsBindingDecl) ? SimpleRefExpr : Ref;
22935 SemaRef.AddInitializerToDecl(
22936 dcl: Init, init: SemaRef.DefaultLvalueConversion(E: InitExpr).get(),
22937 /*DirectInit=*/false);
22938 DeclRefExpr *InitRef = buildDeclRefExpr(S&: SemaRef, D: Init, Ty: Type, Loc: ELoc);
22939
22940 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_linear, PrivateCopy: Ref);
22941 Vars.push_back(
22942 Elt: (VD || IsBindingDecl || SemaRef.CurContext->isDependentContext())
22943 ? RefExpr->IgnoreParens()
22944 : Ref);
22945 Privates.push_back(Elt: PrivateRef);
22946 Inits.push_back(Elt: InitRef);
22947 }
22948
22949 if (Vars.empty())
22950 return nullptr;
22951
22952 Expr *StepExpr = Step;
22953 Expr *CalcStepExpr = nullptr;
22954 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
22955 !Step->isInstantiationDependent() &&
22956 !Step->containsUnexpandedParameterPack()) {
22957 SourceLocation StepLoc = Step->getBeginLoc();
22958 ExprResult Val = PerformOpenMPImplicitIntegerConversion(Loc: StepLoc, Op: Step);
22959 if (Val.isInvalid())
22960 return nullptr;
22961 StepExpr = Val.get();
22962
22963 // Build var to save the step value.
22964 VarDecl *SaveVar =
22965 buildVarDecl(SemaRef, Loc: StepLoc, Type: StepExpr->getType(), Name: ".linear.step");
22966 ExprResult SaveRef =
22967 buildDeclRefExpr(S&: SemaRef, D: SaveVar, Ty: StepExpr->getType(), Loc: StepLoc);
22968 ExprResult CalcStep = SemaRef.BuildBinOp(
22969 S: SemaRef.getCurScope(), OpLoc: StepLoc, Opc: BO_Assign, LHSExpr: SaveRef.get(), RHSExpr: StepExpr);
22970 CalcStep =
22971 SemaRef.ActOnFinishFullExpr(Expr: CalcStep.get(), /*DiscardedValue=*/false);
22972
22973 // Warn about zero linear step (it would be probably better specified as
22974 // making corresponding variables 'const').
22975 if (std::optional<llvm::APSInt> Result =
22976 StepExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
22977 if (!Result->isNegative() && !Result->isStrictlyPositive())
22978 Diag(Loc: StepLoc, DiagID: diag::warn_omp_linear_step_zero)
22979 << Vars[0] << (Vars.size() > 1);
22980 } else if (CalcStep.isUsable()) {
22981 // Calculate the step beforehand instead of doing this on each iteration.
22982 // (This is not used if the number of iterations may be kfold-ed).
22983 CalcStepExpr = CalcStep.get();
22984 }
22985 }
22986
22987 return OMPLinearClause::Create(C: getASTContext(), StartLoc, LParenLoc, Modifier: LinKind,
22988 ModifierLoc: LinLoc, ColonLoc, StepModifierLoc, EndLoc,
22989 VL: Vars, PL: Privates, IL: Inits, Step: StepExpr, CalcStep: CalcStepExpr,
22990 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures),
22991 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: ExprPostUpdates));
22992}
22993
22994static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
22995 Expr *NumIterations, Sema &SemaRef,
22996 Scope *S, DSAStackTy *Stack) {
22997 // Walk the vars and build update/final expressions for the CodeGen.
22998 SmallVector<Expr *, 8> Updates;
22999 SmallVector<Expr *, 8> Finals;
23000 SmallVector<Expr *, 8> UsedExprs;
23001 Expr *Step = Clause.getStep();
23002 Expr *CalcStep = Clause.getCalcStep();
23003 // OpenMP [2.14.3.7, linear clause]
23004 // If linear-step is not specified it is assumed to be 1.
23005 if (!Step)
23006 Step = SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get();
23007 else if (CalcStep)
23008 Step = cast<BinaryOperator>(Val: CalcStep)->getLHS();
23009 bool HasErrors = false;
23010 auto CurInit = Clause.inits().begin();
23011 auto CurPrivate = Clause.privates().begin();
23012 OpenMPLinearClauseKind LinKind = Clause.getModifier();
23013 for (Expr *RefExpr : Clause.varlist()) {
23014 SourceLocation ELoc;
23015 SourceRange ERange;
23016 Expr *SimpleRefExpr = RefExpr;
23017 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
23018 ValueDecl *D = Res.first;
23019 if (Res.second || !D) {
23020 Updates.push_back(Elt: nullptr);
23021 Finals.push_back(Elt: nullptr);
23022 HasErrors = true;
23023 continue;
23024 }
23025 auto &&Info = Stack->isLoopControlVariable(D);
23026 // OpenMP [2.15.11, distribute simd Construct]
23027 // A list item may not appear in a linear clause, unless it is the loop
23028 // iteration variable.
23029 if (isOpenMPDistributeDirective(DKind: Stack->getCurrentDirective()) &&
23030 isOpenMPSimdDirective(DKind: Stack->getCurrentDirective()) && !Info.first) {
23031 SemaRef.Diag(Loc: ELoc,
23032 DiagID: diag::err_omp_linear_distribute_var_non_loop_iteration);
23033 Updates.push_back(Elt: nullptr);
23034 Finals.push_back(Elt: nullptr);
23035 HasErrors = true;
23036 continue;
23037 }
23038 Expr *InitExpr = *CurInit;
23039
23040 // Build privatized reference to the current linear var.
23041 auto *DE = cast<DeclRefExpr>(Val: SimpleRefExpr);
23042 Expr *CapturedRef;
23043 if (isa<BindingDecl>(Val: DE->getDecl())) {
23044 CapturedRef = SimpleRefExpr;
23045 } else if (LinKind == OMPC_LINEAR_uval) {
23046 CapturedRef = cast<VarDecl>(Val: DE->getDecl())->getInit();
23047 } else {
23048 CapturedRef =
23049 buildDeclRefExpr(S&: SemaRef, D: cast<VarDecl>(Val: DE->getDecl()),
23050 Ty: DE->getType().getUnqualifiedType(), Loc: DE->getExprLoc(),
23051 /*RefersToCapture=*/true);
23052 }
23053
23054 // Build update: Var = InitExpr + IV * Step
23055 ExprResult Update;
23056 if (!Info.first)
23057 Update = buildCounterUpdate(
23058 SemaRef, S, Loc: RefExpr->getExprLoc(), VarRef: *CurPrivate, Start: InitExpr, Iter: IV, Step,
23059 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
23060 else
23061 Update = *CurPrivate;
23062 Update = SemaRef.ActOnFinishFullExpr(Expr: Update.get(), CC: DE->getBeginLoc(),
23063 /*DiscardedValue=*/false);
23064
23065 // Build final: Var = PrivCopy;
23066 ExprResult Final;
23067 if (!Info.first)
23068 Final = SemaRef.BuildBinOp(
23069 S, OpLoc: RefExpr->getExprLoc(), Opc: BO_Assign, LHSExpr: CapturedRef,
23070 RHSExpr: SemaRef.DefaultLvalueConversion(E: *CurPrivate).get());
23071 else
23072 Final = *CurPrivate;
23073 Final = SemaRef.ActOnFinishFullExpr(Expr: Final.get(), CC: DE->getBeginLoc(),
23074 /*DiscardedValue=*/false);
23075
23076 if (!Update.isUsable() || !Final.isUsable()) {
23077 Updates.push_back(Elt: nullptr);
23078 Finals.push_back(Elt: nullptr);
23079 UsedExprs.push_back(Elt: nullptr);
23080 HasErrors = true;
23081 } else {
23082 Updates.push_back(Elt: Update.get());
23083 Finals.push_back(Elt: Final.get());
23084 if (!Info.first)
23085 UsedExprs.push_back(Elt: SimpleRefExpr);
23086 }
23087 ++CurInit;
23088 ++CurPrivate;
23089 }
23090 if (Expr *S = Clause.getStep())
23091 UsedExprs.push_back(Elt: S);
23092 // Fill the remaining part with the nullptr.
23093 UsedExprs.append(NumInputs: Clause.varlist_size() + 1 - UsedExprs.size(), Elt: nullptr);
23094 Clause.setUpdates(Updates);
23095 Clause.setFinals(Finals);
23096 Clause.setUsedExprs(UsedExprs);
23097 return HasErrors;
23098}
23099
23100OMPClause *SemaOpenMP::ActOnOpenMPAlignedClause(
23101 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
23102 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
23103 SmallVector<Expr *, 8> Vars;
23104 for (Expr *RefExpr : VarList) {
23105 assert(RefExpr && "NULL expr in OpenMP aligned clause.");
23106 SourceLocation ELoc;
23107 SourceRange ERange;
23108 Expr *SimpleRefExpr = RefExpr;
23109 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
23110 if (Res.second) {
23111 // It will be analyzed later.
23112 Vars.push_back(Elt: RefExpr);
23113 }
23114 ValueDecl *D = Res.first;
23115 if (!D)
23116 continue;
23117
23118 QualType QType = D->getType();
23119 auto *VD = dyn_cast<VarDecl>(Val: D);
23120
23121 // OpenMP [2.8.1, simd construct, Restrictions]
23122 // The type of list items appearing in the aligned clause must be
23123 // array, pointer, reference to array, or reference to pointer.
23124 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
23125 const Type *Ty = QType.getTypePtrOrNull();
23126 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
23127 Diag(Loc: ELoc, DiagID: diag::err_omp_aligned_expected_array_or_ptr)
23128 << QType << getLangOpts().CPlusPlus << ERange;
23129 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
23130 VarDecl::DeclarationOnly;
23131 Diag(Loc: D->getLocation(),
23132 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
23133 << D;
23134 continue;
23135 }
23136
23137 // OpenMP [2.8.1, simd construct, Restrictions]
23138 // A list-item cannot appear in more than one aligned clause.
23139 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, NewDE: SimpleRefExpr)) {
23140 Diag(Loc: ELoc, DiagID: diag::err_omp_used_in_clause_twice)
23141 << 0 << getOpenMPClauseNameForDiag(C: OMPC_aligned) << ERange;
23142 Diag(Loc: PrevRef->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
23143 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
23144 continue;
23145 }
23146
23147 DeclRefExpr *Ref = nullptr;
23148 if (!VD && isOpenMPCapturedDecl(D))
23149 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
23150 Vars.push_back(Elt: SemaRef
23151 .DefaultFunctionArrayConversion(
23152 E: (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
23153 .get());
23154 }
23155
23156 // OpenMP [2.8.1, simd construct, Description]
23157 // The parameter of the aligned clause, alignment, must be a constant
23158 // positive integer expression.
23159 // If no optional parameter is specified, implementation-defined default
23160 // alignments for SIMD instructions on the target platforms are assumed.
23161 if (Alignment != nullptr) {
23162 ExprResult AlignResult =
23163 VerifyPositiveIntegerConstantInClause(E: Alignment, CKind: OMPC_aligned);
23164 if (AlignResult.isInvalid())
23165 return nullptr;
23166 Alignment = AlignResult.get();
23167 }
23168 if (Vars.empty())
23169 return nullptr;
23170
23171 return OMPAlignedClause::Create(C: getASTContext(), StartLoc, LParenLoc,
23172 ColonLoc, EndLoc, VL: Vars, A: Alignment);
23173}
23174
23175OMPClause *SemaOpenMP::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
23176 SourceLocation StartLoc,
23177 SourceLocation LParenLoc,
23178 SourceLocation EndLoc) {
23179 SmallVector<Expr *, 8> Vars;
23180 SmallVector<Expr *, 8> SrcExprs;
23181 SmallVector<Expr *, 8> DstExprs;
23182 SmallVector<Expr *, 8> AssignmentOps;
23183 for (Expr *RefExpr : VarList) {
23184 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
23185 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
23186 // It will be analyzed later.
23187 Vars.push_back(Elt: RefExpr);
23188 SrcExprs.push_back(Elt: nullptr);
23189 DstExprs.push_back(Elt: nullptr);
23190 AssignmentOps.push_back(Elt: nullptr);
23191 continue;
23192 }
23193
23194 SourceLocation ELoc = RefExpr->getExprLoc();
23195 // OpenMP [2.1, C/C++]
23196 // A list item is a variable name.
23197 // OpenMP [2.14.4.1, Restrictions, p.1]
23198 // A list item that appears in a copyin clause must be threadprivate.
23199 auto *DE = dyn_cast<DeclRefExpr>(Val: RefExpr);
23200 if (!DE || !isa<VarDecl>(Val: DE->getDecl())) {
23201 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_var_name_member_expr)
23202 << 0 << RefExpr->getSourceRange();
23203 continue;
23204 }
23205
23206 Decl *D = DE->getDecl();
23207 auto *VD = cast<VarDecl>(Val: D);
23208
23209 QualType Type = VD->getType();
23210 if (Type->isDependentType() || Type->isInstantiationDependentType()) {
23211 // It will be analyzed later.
23212 Vars.push_back(Elt: DE);
23213 SrcExprs.push_back(Elt: nullptr);
23214 DstExprs.push_back(Elt: nullptr);
23215 AssignmentOps.push_back(Elt: nullptr);
23216 continue;
23217 }
23218
23219 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
23220 // A list item that appears in a copyin clause must be threadprivate.
23221 if (!DSAStack->isThreadPrivate(D: VD)) {
23222 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
23223 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
23224 << getOpenMPClauseNameForDiag(C: OMPC_copyin)
23225 << getOpenMPDirectiveName(D: OMPD_threadprivate, V: OMPVersion);
23226 continue;
23227 }
23228
23229 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
23230 // A variable of class type (or array thereof) that appears in a
23231 // copyin clause requires an accessible, unambiguous copy assignment
23232 // operator for the class type.
23233 QualType ElemType =
23234 getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
23235 VarDecl *SrcVD =
23236 buildVarDecl(SemaRef, Loc: DE->getBeginLoc(), Type: ElemType.getUnqualifiedType(),
23237 Name: ".copyin.src", Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr);
23238 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
23239 S&: SemaRef, D: SrcVD, Ty: ElemType.getUnqualifiedType(), Loc: DE->getExprLoc());
23240 VarDecl *DstVD =
23241 buildVarDecl(SemaRef, Loc: DE->getBeginLoc(), Type: ElemType, Name: ".copyin.dst",
23242 Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr);
23243 DeclRefExpr *PseudoDstExpr =
23244 buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: ElemType, Loc: DE->getExprLoc());
23245 // For arrays generate assignment operation for single element and replace
23246 // it by the original array element in CodeGen.
23247 ExprResult AssignmentOp =
23248 SemaRef.BuildBinOp(/*S=*/nullptr, OpLoc: DE->getExprLoc(), Opc: BO_Assign,
23249 LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
23250 if (AssignmentOp.isInvalid())
23251 continue;
23252 AssignmentOp =
23253 SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: DE->getExprLoc(),
23254 /*DiscardedValue=*/false);
23255 if (AssignmentOp.isInvalid())
23256 continue;
23257
23258 DSAStack->addDSA(D: VD, E: DE, A: OMPC_copyin);
23259 Vars.push_back(Elt: DE);
23260 SrcExprs.push_back(Elt: PseudoSrcExpr);
23261 DstExprs.push_back(Elt: PseudoDstExpr);
23262 AssignmentOps.push_back(Elt: AssignmentOp.get());
23263 }
23264
23265 if (Vars.empty())
23266 return nullptr;
23267
23268 return OMPCopyinClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
23269 VL: Vars, SrcExprs, DstExprs, AssignmentOps);
23270}
23271
23272OMPClause *SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
23273 SourceLocation StartLoc,
23274 SourceLocation LParenLoc,
23275 SourceLocation EndLoc) {
23276 SmallVector<Expr *, 8> Vars;
23277 SmallVector<Expr *, 8> SrcExprs;
23278 SmallVector<Expr *, 8> DstExprs;
23279 SmallVector<Expr *, 8> AssignmentOps;
23280 for (Expr *RefExpr : VarList) {
23281 assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
23282 SourceLocation ELoc;
23283 SourceRange ERange;
23284 Expr *SimpleRefExpr = RefExpr;
23285 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
23286 if (Res.second) {
23287 // It will be analyzed later.
23288 Vars.push_back(Elt: RefExpr);
23289 SrcExprs.push_back(Elt: nullptr);
23290 DstExprs.push_back(Elt: nullptr);
23291 AssignmentOps.push_back(Elt: nullptr);
23292 }
23293 ValueDecl *D = Res.first;
23294 if (!D)
23295 continue;
23296
23297 QualType Type = D->getType();
23298 auto *VD = dyn_cast<VarDecl>(Val: D);
23299
23300 // OpenMP [2.14.4.2, Restrictions, p.2]
23301 // A list item that appears in a copyprivate clause may not appear in a
23302 // private or firstprivate clause on the single construct.
23303 if (!VD || !DSAStack->isThreadPrivate(D: VD)) {
23304 DSAStackTy::DSAVarData DVar =
23305 DSAStack->getTopDSA(D, /*FromParent=*/false);
23306 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
23307 DVar.RefExpr) {
23308 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
23309 << getOpenMPClauseNameForDiag(C: DVar.CKind)
23310 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate);
23311 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
23312 continue;
23313 }
23314
23315 // OpenMP [2.11.4.2, Restrictions, p.1]
23316 // All list items that appear in a copyprivate clause must be either
23317 // threadprivate or private in the enclosing context.
23318 if (DVar.CKind == OMPC_unknown) {
23319 DVar = DSAStack->getImplicitDSA(D, FromParent: false);
23320 // A data member is private only if an enclosing construct captured it.
23321 const bool IsShared = DVar.CKind == OMPC_shared;
23322 if (IsShared ||
23323 (isa<FieldDecl>(Val: D) && !SemaRef.CurContext->isDependentContext() &&
23324 !isOpenMPCapturedDecl(D))) {
23325 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
23326 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate)
23327 << "threadprivate or private in the enclosing context";
23328 if (IsShared)
23329 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
23330 continue;
23331 }
23332 }
23333 }
23334
23335 // Variably modified types are not supported.
23336 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
23337 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
23338 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
23339 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate) << Type
23340 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
23341 V: OMPVersion);
23342 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
23343 VarDecl::DeclarationOnly;
23344 Diag(Loc: D->getLocation(),
23345 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
23346 << D;
23347 continue;
23348 }
23349
23350 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
23351 // A variable of class type (or array thereof) that appears in a
23352 // copyin clause requires an accessible, unambiguous copy assignment
23353 // operator for the class type.
23354 Type = getASTContext()
23355 .getBaseElementType(QT: Type.getNonReferenceType())
23356 .getUnqualifiedType();
23357 VarDecl *SrcVD =
23358 buildVarDecl(SemaRef, Loc: RefExpr->getBeginLoc(), Type, Name: ".copyprivate.src",
23359 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
23360 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(S&: SemaRef, D: SrcVD, Ty: Type, Loc: ELoc);
23361 VarDecl *DstVD =
23362 buildVarDecl(SemaRef, Loc: RefExpr->getBeginLoc(), Type, Name: ".copyprivate.dst",
23363 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
23364 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: Type, Loc: ELoc);
23365 ExprResult AssignmentOp = SemaRef.BuildBinOp(
23366 DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
23367 if (AssignmentOp.isInvalid())
23368 continue;
23369 AssignmentOp = SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: ELoc,
23370 /*DiscardedValue=*/false);
23371 if (AssignmentOp.isInvalid())
23372 continue;
23373
23374 // No need to mark vars as copyprivate, they are already threadprivate or
23375 // implicitly private.
23376 const bool IsBindingDecl = isa<BindingDecl>(Val: D);
23377 assert(VD || IsBindingDecl || SemaRef.CurContext->isDependentContext() ||
23378 isOpenMPCapturedDecl(D));
23379 Vars.push_back(
23380 Elt: (VD || IsBindingDecl || SemaRef.CurContext->isDependentContext())
23381 ? RefExpr->IgnoreParens()
23382 : buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false));
23383 SrcExprs.push_back(Elt: PseudoSrcExpr);
23384 DstExprs.push_back(Elt: PseudoDstExpr);
23385 AssignmentOps.push_back(Elt: AssignmentOp.get());
23386 }
23387
23388 if (Vars.empty())
23389 return nullptr;
23390
23391 return OMPCopyprivateClause::Create(C: getASTContext(), StartLoc, LParenLoc,
23392 EndLoc, VL: Vars, SrcExprs, DstExprs,
23393 AssignmentOps);
23394}
23395
23396OMPClause *SemaOpenMP::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
23397 SourceLocation StartLoc,
23398 SourceLocation LParenLoc,
23399 SourceLocation EndLoc) {
23400 if (VarList.empty())
23401 return nullptr;
23402
23403 return OMPFlushClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
23404 VL: VarList);
23405}
23406
23407/// Tries to find omp_depend_t. type.
23408static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
23409 bool Diagnose = true) {
23410 QualType OMPDependT = Stack->getOMPDependT();
23411 if (!OMPDependT.isNull())
23412 return true;
23413 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_depend_t");
23414 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
23415 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23416 if (Diagnose)
23417 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_depend_t";
23418 return false;
23419 }
23420 Stack->setOMPDependT(PT.get());
23421 return true;
23422}
23423
23424OMPClause *SemaOpenMP::ActOnOpenMPDepobjClause(Expr *Depobj,
23425 SourceLocation StartLoc,
23426 SourceLocation LParenLoc,
23427 SourceLocation EndLoc) {
23428 if (!Depobj)
23429 return nullptr;
23430
23431 bool OMPDependTFound = findOMPDependT(S&: SemaRef, Loc: StartLoc, DSAStack);
23432
23433 // OpenMP 5.0, 2.17.10.1 depobj Construct
23434 // depobj is an lvalue expression of type omp_depend_t.
23435 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
23436 !Depobj->isInstantiationDependent() &&
23437 !Depobj->containsUnexpandedParameterPack() &&
23438 (OMPDependTFound && !getASTContext().typesAreCompatible(
23439 DSAStack->getOMPDependT(), T2: Depobj->getType(),
23440 /*CompareUnqualified=*/true))) {
23441 Diag(Loc: Depobj->getExprLoc(), DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
23442 << 0 << Depobj->getType() << Depobj->getSourceRange();
23443 }
23444
23445 if (!Depobj->isLValue()) {
23446 Diag(Loc: Depobj->getExprLoc(), DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
23447 << 1 << Depobj->getSourceRange();
23448 }
23449
23450 return new (getASTContext())
23451 OMPDepobjClause(StartLoc, LParenLoc, EndLoc, Depobj);
23452}
23453
23454namespace {
23455// Utility struct that gathers the related info for doacross clause.
23456struct DoacrossDataInfoTy {
23457 // The list of expressions.
23458 SmallVector<Expr *, 8> Vars;
23459 // The OperatorOffset for doacross loop.
23460 DSAStackTy::OperatorOffsetTy OpsOffs;
23461 // The depended loop count.
23462 llvm::APSInt TotalDepCount;
23463};
23464} // namespace
23465static DoacrossDataInfoTy
23466ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource,
23467 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
23468 SourceLocation EndLoc) {
23469
23470 SmallVector<Expr *, 8> Vars;
23471 DSAStackTy::OperatorOffsetTy OpsOffs;
23472 llvm::APSInt DepCounter(/*BitWidth=*/32);
23473 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
23474
23475 if (const Expr *OrderedCountExpr =
23476 Stack->getParentOrderedRegionParam().first) {
23477 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Ctx: SemaRef.Context);
23478 TotalDepCount.setIsUnsigned(/*Val=*/true);
23479 }
23480
23481 for (Expr *RefExpr : VarList) {
23482 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
23483 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
23484 // It will be analyzed later.
23485 Vars.push_back(Elt: RefExpr);
23486 continue;
23487 }
23488
23489 SourceLocation ELoc = RefExpr->getExprLoc();
23490 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
23491 if (!IsSource) {
23492 if (Stack->getParentOrderedRegionParam().first &&
23493 DepCounter >= TotalDepCount) {
23494 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_unexpected_expr);
23495 continue;
23496 }
23497 ++DepCounter;
23498 // OpenMP [2.13.9, Summary]
23499 // depend(dependence-type : vec), where dependence-type is:
23500 // 'sink' and where vec is the iteration vector, which has the form:
23501 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
23502 // where n is the value specified by the ordered clause in the loop
23503 // directive, xi denotes the loop iteration variable of the i-th nested
23504 // loop associated with the loop directive, and di is a constant
23505 // non-negative integer.
23506 if (SemaRef.CurContext->isDependentContext()) {
23507 // It will be analyzed later.
23508 Vars.push_back(Elt: RefExpr);
23509 continue;
23510 }
23511 SimpleExpr = SimpleExpr->IgnoreImplicit();
23512 OverloadedOperatorKind OOK = OO_None;
23513 SourceLocation OOLoc;
23514 Expr *LHS = SimpleExpr;
23515 Expr *RHS = nullptr;
23516 if (auto *BO = dyn_cast<BinaryOperator>(Val: SimpleExpr)) {
23517 OOK = BinaryOperator::getOverloadedOperator(Opc: BO->getOpcode());
23518 OOLoc = BO->getOperatorLoc();
23519 LHS = BO->getLHS()->IgnoreParenImpCasts();
23520 RHS = BO->getRHS()->IgnoreParenImpCasts();
23521 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Val: SimpleExpr)) {
23522 OOK = OCE->getOperator();
23523 OOLoc = OCE->getOperatorLoc();
23524 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
23525 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
23526 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Val: SimpleExpr)) {
23527 OOK = MCE->getMethodDecl()
23528 ->getNameInfo()
23529 .getName()
23530 .getCXXOverloadedOperator();
23531 OOLoc = MCE->getCallee()->getExprLoc();
23532 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
23533 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
23534 }
23535 SourceLocation ELoc;
23536 SourceRange ERange;
23537 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: LHS, ELoc, ERange);
23538 if (Res.second) {
23539 // It will be analyzed later.
23540 Vars.push_back(Elt: RefExpr);
23541 }
23542 ValueDecl *D = Res.first;
23543 if (!D)
23544 continue;
23545
23546 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
23547 SemaRef.Diag(Loc: OOLoc, DiagID: diag::err_omp_depend_sink_expected_plus_minus);
23548 continue;
23549 }
23550 if (RHS) {
23551 ExprResult RHSRes =
23552 SemaRef.OpenMP().VerifyPositiveIntegerConstantInClause(
23553 E: RHS, CKind: OMPC_depend, /*StrictlyPositive=*/false);
23554 if (RHSRes.isInvalid())
23555 continue;
23556 }
23557 if (!SemaRef.CurContext->isDependentContext() &&
23558 Stack->getParentOrderedRegionParam().first &&
23559 DepCounter != Stack->isParentLoopControlVariable(D).first) {
23560 const ValueDecl *VD =
23561 Stack->getParentLoopControlVariable(I: DepCounter.getZExtValue());
23562 if (VD)
23563 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
23564 << 1 << VD;
23565 else
23566 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
23567 << 0;
23568 continue;
23569 }
23570 OpsOffs.emplace_back(Args&: RHS, Args&: OOK);
23571 }
23572 Vars.push_back(Elt: RefExpr->IgnoreParenImpCasts());
23573 }
23574 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
23575 TotalDepCount > VarList.size() &&
23576 Stack->getParentOrderedRegionParam().first &&
23577 Stack->getParentLoopControlVariable(I: VarList.size() + 1)) {
23578 SemaRef.Diag(Loc: EndLoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
23579 << 1 << Stack->getParentLoopControlVariable(I: VarList.size() + 1);
23580 }
23581 return {.Vars: Vars, .OpsOffs: OpsOffs, .TotalDepCount: TotalDepCount};
23582}
23583
23584OMPClause *SemaOpenMP::ActOnOpenMPDependClause(
23585 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
23586 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
23587 SourceLocation EndLoc) {
23588 OpenMPDependClauseKind DepKind = Data.DepKind;
23589 SourceLocation DepLoc = Data.DepLoc;
23590 if (DSAStack->getCurrentDirective() == OMPD_ordered_standalone &&
23591 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
23592 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
23593 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(C: OMPC_depend);
23594 return nullptr;
23595 }
23596 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
23597 DepKind == OMPC_DEPEND_mutexinoutset) {
23598 Diag(Loc: DepLoc, DiagID: diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
23599 return nullptr;
23600 }
23601 if ((DSAStack->getCurrentDirective() != OMPD_ordered_standalone ||
23602 DSAStack->getCurrentDirective() == OMPD_depobj) &&
23603 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
23604 DepKind == OMPC_DEPEND_sink ||
23605 ((getLangOpts().OpenMP < 50 ||
23606 DSAStack->getCurrentDirective() == OMPD_depobj) &&
23607 DepKind == OMPC_DEPEND_depobj))) {
23608 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
23609 OMPC_DEPEND_outallmemory,
23610 OMPC_DEPEND_inoutallmemory};
23611 if (getLangOpts().OpenMP < 50 ||
23612 DSAStack->getCurrentDirective() == OMPD_depobj)
23613 Except.push_back(Elt: OMPC_DEPEND_depobj);
23614 if (getLangOpts().OpenMP < 51)
23615 Except.push_back(Elt: OMPC_DEPEND_inoutset);
23616 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
23617 ? "depend modifier(iterator) or "
23618 : "";
23619 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
23620 << Expected + getListOfPossibleValues(K: OMPC_depend, /*First=*/0,
23621 /*Last=*/OMPC_DEPEND_unknown,
23622 Exclude: Except)
23623 << getOpenMPClauseNameForDiag(C: OMPC_depend);
23624 return nullptr;
23625 }
23626 if (DepModifier &&
23627 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
23628 Diag(Loc: DepModifier->getExprLoc(),
23629 DiagID: diag::err_omp_depend_sink_source_with_modifier);
23630 return nullptr;
23631 }
23632 if (DepModifier &&
23633 !DepModifier->getType()->isSpecificBuiltinType(K: BuiltinType::OMPIterator))
23634 Diag(Loc: DepModifier->getExprLoc(), DiagID: diag::err_omp_depend_modifier_not_iterator);
23635
23636 SmallVector<Expr *, 8> Vars;
23637 DSAStackTy::OperatorOffsetTy OpsOffs;
23638 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
23639
23640 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
23641 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
23642 SemaRef, IsSource: DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
23643 Vars = VarOffset.Vars;
23644 OpsOffs = VarOffset.OpsOffs;
23645 TotalDepCount = VarOffset.TotalDepCount;
23646 } else {
23647 for (Expr *RefExpr : VarList) {
23648 assert(RefExpr && "NULL expr in OpenMP depend clause.");
23649 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
23650 // It will be analyzed later.
23651 Vars.push_back(Elt: RefExpr);
23652 continue;
23653 }
23654
23655 SourceLocation ELoc = RefExpr->getExprLoc();
23656 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
23657 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
23658 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
23659 if (OMPDependTFound)
23660 OMPDependTFound = findOMPDependT(S&: SemaRef, Loc: StartLoc, DSAStack,
23661 Diagnose: DepKind == OMPC_DEPEND_depobj);
23662 if (DepKind == OMPC_DEPEND_depobj) {
23663 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
23664 // List items used in depend clauses with the depobj dependence type
23665 // must be expressions of the omp_depend_t type.
23666 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
23667 !RefExpr->isInstantiationDependent() &&
23668 !RefExpr->containsUnexpandedParameterPack() &&
23669 (OMPDependTFound &&
23670 !getASTContext().hasSameUnqualifiedType(
23671 DSAStack->getOMPDependT(), T2: RefExpr->getType()))) {
23672 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
23673 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
23674 continue;
23675 }
23676 if (!RefExpr->isLValue()) {
23677 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
23678 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
23679 continue;
23680 }
23681 } else {
23682 // OpenMP 5.0 [2.17.11, Restrictions]
23683 // List items used in depend clauses cannot be zero-length array
23684 // sections.
23685 QualType ExprTy = RefExpr->getType().getNonReferenceType();
23686 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: SimpleExpr);
23687 if (OASE) {
23688 QualType BaseType =
23689 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
23690 if (BaseType.isNull())
23691 return nullptr;
23692 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
23693 ExprTy = ATy->getElementType();
23694 else
23695 ExprTy = BaseType->getPointeeType();
23696 if (BaseType.isNull() || ExprTy.isNull())
23697 return nullptr;
23698 ExprTy = ExprTy.getNonReferenceType();
23699 const Expr *Length = OASE->getLength();
23700 Expr::EvalResult Result;
23701 if (Length && !Length->isValueDependent() &&
23702 Length->EvaluateAsInt(Result, Ctx: getASTContext()) &&
23703 Result.Val.getInt().isZero()) {
23704 Diag(Loc: ELoc,
23705 DiagID: diag::err_omp_depend_zero_length_array_section_not_allowed)
23706 << SimpleExpr->getSourceRange();
23707 continue;
23708 }
23709 }
23710
23711 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
23712 // List items used in depend clauses with the in, out, inout,
23713 // inoutset, or mutexinoutset dependence types cannot be
23714 // expressions of the omp_depend_t type.
23715 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
23716 !RefExpr->isInstantiationDependent() &&
23717 !RefExpr->containsUnexpandedParameterPack() &&
23718 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
23719 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
23720 ExprTy.getTypePtr()))) {
23721 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
23722 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
23723 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
23724 << RefExpr->getSourceRange();
23725 continue;
23726 }
23727
23728 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: SimpleExpr);
23729 if (ASE && !ASE->getBase()->isTypeDependent() &&
23730 !ASE->getBase()
23731 ->getType()
23732 .getNonReferenceType()
23733 ->isPointerType() &&
23734 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
23735 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
23736 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
23737 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
23738 << RefExpr->getSourceRange();
23739 continue;
23740 }
23741
23742 ExprResult Res;
23743 {
23744 Sema::TentativeAnalysisScope Trap(SemaRef);
23745 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf,
23746 InputExpr: RefExpr->IgnoreParenImpCasts());
23747 }
23748 if (!Res.isUsable() && !isa<ArraySectionExpr>(Val: SimpleExpr) &&
23749 !isa<OMPArrayShapingExpr>(Val: SimpleExpr)) {
23750 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
23751 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
23752 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
23753 << RefExpr->getSourceRange();
23754 continue;
23755 }
23756 }
23757 }
23758 Vars.push_back(Elt: RefExpr->IgnoreParenImpCasts());
23759 }
23760 }
23761
23762 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
23763 DepKind != OMPC_DEPEND_outallmemory &&
23764 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
23765 return nullptr;
23766
23767 auto *C = OMPDependClause::Create(
23768 C: getASTContext(), StartLoc, LParenLoc, EndLoc,
23769 Data: {.DepKind: DepKind, .DepLoc: DepLoc, .ColonLoc: Data.ColonLoc, .OmpAllMemoryLoc: Data.OmpAllMemoryLoc}, DepModifier, VL: Vars,
23770 NumLoops: TotalDepCount.getZExtValue());
23771 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
23772 DSAStack->isParentOrderedRegion())
23773 DSAStack->addDoacrossDependClause(C, OpsOffs);
23774 return C;
23775}
23776
23777OMPClause *SemaOpenMP::ActOnOpenMPDeviceClause(
23778 OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc,
23779 SourceLocation LParenLoc, SourceLocation ModifierLoc,
23780 SourceLocation EndLoc) {
23781 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
23782 "Unexpected device modifier in OpenMP < 50.");
23783
23784 bool ErrorFound = false;
23785 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
23786 std::string Values =
23787 getListOfPossibleValues(K: OMPC_device, /*First=*/0, Last: OMPC_DEVICE_unknown);
23788 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
23789 << Values << getOpenMPClauseNameForDiag(C: OMPC_device);
23790 ErrorFound = true;
23791 }
23792
23793 Expr *ValExpr = Device;
23794 Stmt *HelperValStmt = nullptr;
23795
23796 // OpenMP 5.2 [1.3, Execution Model]: a conforming device number is either
23797 // a non-negative integer that is less than or equal to omp_get_num_devices()
23798 // or equal to omp_initial_device or omp_invalid_device. The predefined
23799 // identifiers were introduced in OpenMP 5.2; earlier versions require a
23800 // non-negative integer.
23801 if (getLangOpts().OpenMP >= 52) {
23802 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
23803 !ValExpr->isInstantiationDependent()) {
23804 SourceLocation Loc = ValExpr->getExprLoc();
23805 ExprResult Value = PerformOpenMPImplicitIntegerConversion(Loc, Op: ValExpr);
23806 if (Value.isInvalid()) {
23807 ErrorFound = true;
23808 } else {
23809 ValExpr = Value.get();
23810 if (std::optional<llvm::APSInt> Result =
23811 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
23812 if (Result->isSigned() && Result->slt(RHS: -2)) {
23813 Diag(Loc, DiagID: diag::err_omp_device_expression_invalid)
23814 << ValExpr->getSourceRange();
23815 ErrorFound = true;
23816 }
23817 }
23818 }
23819 }
23820 } else {
23821 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_device,
23822 /*StrictlyPositive=*/false) ||
23823 ErrorFound;
23824 }
23825 if (ErrorFound)
23826 return nullptr;
23827
23828 // OpenMP 5.0 [2.12.5, Restrictions]
23829 // In case of ancestor device-modifier, a requires directive with
23830 // the reverse_offload clause must be specified.
23831 if (Modifier == OMPC_DEVICE_ancestor) {
23832 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
23833 SemaRef.targetDiag(
23834 Loc: StartLoc,
23835 DiagID: diag::err_omp_device_ancestor_without_requires_reverse_offload);
23836 ErrorFound = true;
23837 }
23838 }
23839
23840 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23841 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
23842 DKind, CKind: OMPC_device, OMPVersion: getLangOpts().getOpenMPVersion());
23843 if (CaptureRegion != OMPD_unknown &&
23844 !SemaRef.CurContext->isDependentContext()) {
23845 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
23846 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23847 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
23848 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
23849 }
23850
23851 return new (getASTContext())
23852 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
23853 LParenLoc, ModifierLoc, EndLoc);
23854}
23855
23856static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
23857 DSAStackTy *Stack, QualType QTy,
23858 bool FullCheck = true) {
23859 if (SemaRef.RequireCompleteType(Loc: SL, T: QTy, DiagID: diag::err_incomplete_type))
23860 return false;
23861 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
23862 !QTy.isTriviallyCopyableType(Context: SemaRef.Context))
23863 SemaRef.Diag(Loc: SL, DiagID: diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
23864 return true;
23865}
23866
23867/// Return true if it can be proven that the provided array expression
23868/// (array section or array subscript) does NOT specify the whole size of the
23869/// array whose base type is \a BaseQTy.
23870static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
23871 const Expr *E,
23872 QualType BaseQTy) {
23873 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: E);
23874
23875 // If this is an array subscript, it refers to the whole size if the size of
23876 // the dimension is constant and equals 1. Also, an array section assumes the
23877 // format of an array subscript if no colon is used.
23878 if (isa<ArraySubscriptExpr>(Val: E) ||
23879 (OASE && OASE->getColonLocFirst().isInvalid())) {
23880 if (const auto *ATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr()))
23881 return ATy->getSExtSize() != 1;
23882 // Size can't be evaluated statically.
23883 return false;
23884 }
23885
23886 assert(OASE && "Expecting array section if not an array subscript.");
23887 const Expr *LowerBound = OASE->getLowerBound();
23888 const Expr *Length = OASE->getLength();
23889
23890 // If there is a lower bound that does not evaluates to zero, we are not
23891 // covering the whole dimension.
23892 if (LowerBound) {
23893 Expr::EvalResult Result;
23894 if (!LowerBound->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
23895 return false; // Can't get the integer value as a constant.
23896
23897 llvm::APSInt ConstLowerBound = Result.Val.getInt();
23898 if (ConstLowerBound.getSExtValue())
23899 return true;
23900 }
23901
23902 // If we don't have a length we covering the whole dimension.
23903 if (!Length)
23904 return false;
23905
23906 // If the base is a pointer, we don't have a way to get the size of the
23907 // pointee.
23908 if (BaseQTy->isPointerType())
23909 return false;
23910
23911 // We can only check if the length is the same as the size of the dimension
23912 // if we have a constant array.
23913 const auto *CATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr());
23914 if (!CATy)
23915 return false;
23916
23917 Expr::EvalResult Result;
23918 if (!Length->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
23919 return false; // Can't get the integer value as a constant.
23920
23921 llvm::APSInt ConstLength = Result.Val.getInt();
23922 return CATy->getSExtSize() != ConstLength.getSExtValue();
23923}
23924
23925// Return true if it can be proven that the provided array expression (array
23926// section or array subscript) does NOT specify a single element of the array
23927// whose base type is \a BaseQTy.
23928static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
23929 const Expr *E,
23930 QualType BaseQTy) {
23931 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: E);
23932
23933 // An array subscript always refer to a single element. Also, an array section
23934 // assumes the format of an array subscript if no colon is used.
23935 if (isa<ArraySubscriptExpr>(Val: E) ||
23936 (OASE && OASE->getColonLocFirst().isInvalid()))
23937 return false;
23938
23939 assert(OASE && "Expecting array section if not an array subscript.");
23940 const Expr *Length = OASE->getLength();
23941
23942 // If we don't have a length we have to check if the array has unitary size
23943 // for this dimension. Also, we should always expect a length if the base type
23944 // is pointer.
23945 if (!Length) {
23946 if (const auto *ATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr()))
23947 return ATy->getSExtSize() != 1;
23948 // We cannot assume anything.
23949 return false;
23950 }
23951
23952 // Check if the length evaluates to 1.
23953 Expr::EvalResult Result;
23954 if (!Length->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
23955 return false; // Can't get the integer value as a constant.
23956
23957 llvm::APSInt ConstLength = Result.Val.getInt();
23958 return ConstLength.getSExtValue() != 1;
23959}
23960
23961// The base of elements of list in a map clause have to be either:
23962// - a reference to variable or field.
23963// - a member expression.
23964// - an array expression.
23965//
23966// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
23967// reference to 'r'.
23968//
23969// If we have:
23970//
23971// struct SS {
23972// Bla S;
23973// foo() {
23974// #pragma omp target map (S.Arr[:12]);
23975// }
23976// }
23977//
23978// We want to retrieve the member expression 'this->S';
23979
23980// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
23981// If a list item is an array section, it must specify contiguous storage.
23982//
23983// For this restriction it is sufficient that we make sure only references
23984// to variables or fields and array expressions, and that no array sections
23985// exist except in the rightmost expression (unless they cover the whole
23986// dimension of the array). E.g. these would be invalid:
23987//
23988// r.ArrS[3:5].Arr[6:7]
23989//
23990// r.ArrS[3:5].x
23991//
23992// but these would be valid:
23993// r.ArrS[3].Arr[6:7]
23994//
23995// r.ArrS[3].x
23996namespace {
23997class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
23998 Sema &SemaRef;
23999 OpenMPClauseKind CKind = OMPC_unknown;
24000 OpenMPDirectiveKind DKind = OMPD_unknown;
24001 OMPClauseMappableExprCommon::MappableExprComponentList &Components;
24002 bool IsNonContiguous = false;
24003 bool NoDiagnose = false;
24004 const Expr *RelevantExpr = nullptr;
24005 bool AllowUnitySizeArraySection = true;
24006 bool AllowWholeSizeArraySection = true;
24007 bool AllowAnotherPtr = true;
24008 SourceLocation ELoc;
24009 SourceRange ERange;
24010
24011 void emitErrorMsg() {
24012 // If nothing else worked, this is not a valid map clause expression.
24013 if (SemaRef.getLangOpts().OpenMP < 50) {
24014 SemaRef.Diag(Loc: ELoc,
24015 DiagID: diag::err_omp_expected_named_var_member_or_array_expression)
24016 << ERange;
24017 } else {
24018 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_non_lvalue_in_map_or_motion_clauses)
24019 << getOpenMPClauseNameForDiag(C: CKind) << ERange;
24020 }
24021 }
24022
24023public:
24024 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
24025 ValueDecl *D = DRE->getDecl();
24026 Expr *E = DRE;
24027
24028 // Handle BindingDecls by mapping them as member accesses.
24029 // When the user writes:
24030 // auto [a, b] = p;
24031 // #pragma omp target map(tofrom:a) map(to:b)
24032 // we transform it to:
24033 // #pragma omp target map(tofrom:p.x) map(to:p.y)
24034 // This avoids conflicts when different bindings have different map types.
24035 if (auto *BD = dyn_cast<BindingDecl>(Val: D)) {
24036 auto *DD = cast<DecompositionDecl>(Val: BD->getDecomposedDecl());
24037 Expr *BindingExpr = BD->getBinding();
24038
24039 // Check if the binding is a member expression (struct/class
24040 // decomposition).
24041 if (auto *ME = dyn_cast_or_null<MemberExpr>(Val: BindingExpr)) {
24042
24043 // Use the DecompositionDecl as the base for the member expression.
24044 // The structured binding creates a copy (if initialized from a
24045 // variable) or holds the only storage (if initialized from a prvalue).
24046 // Using DD ensures map clauses reference the correct storage.
24047 Expr *BaseExpr =
24048 SemaRef
24049 .BuildDeclarationNameExpr(
24050 SS: CXXScopeSpec(),
24051 NameInfo: DeclarationNameInfo(DD->getDeclName(), DRE->getLocation()),
24052 D: DD)
24053 .get();
24054
24055 // Create member expression: base.member.
24056 E = MemberExpr::Create(
24057 C: SemaRef.Context, Base: BaseExpr, /*IsArrow=*/false, OperatorLoc: ME->getOperatorLoc(),
24058 QualifierLoc: ME->getQualifierLoc(), TemplateKWLoc: ME->getTemplateKeywordLoc(),
24059 MemberDecl: ME->getMemberDecl(), FoundDecl: ME->getFoundDecl(), MemberNameInfo: ME->getMemberNameInfo(),
24060 /*TemplateArgs=*/nullptr, T: ME->getType(), VK: ME->getValueKind(),
24061 OK: ME->getObjectKind(), NOUR: ME->isNonOdrUse());
24062
24063 // Now process this as a member expression, which will properly
24064 // handle the field-level mapping.
24065 return Visit(S: E);
24066 }
24067 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(Val: BindingExpr)) {
24068 Expr *BaseExpr =
24069 SemaRef
24070 .BuildDeclarationNameExpr(
24071 SS: CXXScopeSpec(),
24072 NameInfo: DeclarationNameInfo(DD->getDeclName(), DRE->getLocation()),
24073 D: DD)
24074 .get();
24075 E = new (SemaRef.Context) ArraySubscriptExpr(
24076 BaseExpr, ASE->getIdx(), ASE->getType(), ASE->getValueKind(),
24077 ASE->getObjectKind(), ASE->getRBracketLoc());
24078 return Visit(S: E);
24079 }
24080 // Tuple-like should already be rejected; do not map DD as a silent
24081 // fallback.
24082 SemaRef.Diag(Loc: DRE->getExprLoc(),
24083 DiagID: diag::err_omp_unsupported_structured_binding_init)
24084 << 4;
24085 return false;
24086 }
24087 // Handle DecompositionDecl directly (implicit captures).
24088 else if (auto *DD = dyn_cast<DecompositionDecl>(Val: D)) {
24089 if (const VarDecl *OrigVar =
24090 getOriginalVarOrDiagnose(S&: SemaRef, DD, Loc: DRE->getExprLoc())) {
24091 D = const_cast<VarDecl *>(OrigVar);
24092 DeclarationNameInfo NameInfo(D->getDeclName(), DRE->getLocation());
24093 E = DeclRefExpr::Create(Context: SemaRef.Context, QualifierLoc: DRE->getQualifierLoc(),
24094 TemplateKWLoc: DRE->getTemplateKeywordLoc(), D,
24095 /*RefersToEnclosingVariableOrCapture=*/false,
24096 NameInfo, T: D->getType(), VK: DRE->getValueKind(),
24097 FoundD: DRE->getFoundDecl(),
24098 /*TemplateArgs=*/nullptr, NOUR: DRE->isNonOdrUse());
24099 } else {
24100 return false;
24101 }
24102 } else if (!isa<VarDecl>(Val: D)) {
24103 emitErrorMsg();
24104 return false;
24105 }
24106 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
24107 RelevantExpr = E;
24108 // Record the component.
24109 Components.emplace_back(Args&: E, Args&: D, Args&: IsNonContiguous);
24110 return true;
24111 }
24112
24113 bool VisitMemberExpr(MemberExpr *ME) {
24114 Expr *E = ME;
24115 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
24116
24117 if (isa<CXXThisExpr>(Val: BaseE)) {
24118 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
24119 // We found a base expression: this->Val.
24120 RelevantExpr = ME;
24121 } else {
24122 E = BaseE;
24123 }
24124
24125 if (!isa<FieldDecl>(Val: ME->getMemberDecl())) {
24126 if (!NoDiagnose) {
24127 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_access_to_data_field)
24128 << ME->getSourceRange();
24129 return false;
24130 }
24131 if (RelevantExpr)
24132 return false;
24133 return Visit(S: E);
24134 }
24135
24136 auto *FD = cast<FieldDecl>(Val: ME->getMemberDecl());
24137
24138 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
24139 // A bit-field cannot appear in a map clause.
24140 //
24141 if (FD->isBitField()) {
24142 if (!NoDiagnose) {
24143 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_bit_fields_forbidden_in_clause)
24144 << ME->getSourceRange() << getOpenMPClauseNameForDiag(C: CKind);
24145 return false;
24146 }
24147 if (RelevantExpr)
24148 return false;
24149 return Visit(S: E);
24150 }
24151
24152 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
24153 // If the type of a list item is a reference to a type T then the type
24154 // will be considered to be T for all purposes of this clause.
24155 QualType CurType = BaseE->getType().getNonReferenceType();
24156
24157 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
24158 // A list item cannot be a variable that is a member of a structure with
24159 // a union type.
24160 //
24161 if (CurType->isUnionType()) {
24162 if (!NoDiagnose) {
24163 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_union_type_not_allowed)
24164 << ME->getSourceRange();
24165 return false;
24166 }
24167 return RelevantExpr || Visit(S: E);
24168 }
24169
24170 // If we got a member expression, we should not expect any array section
24171 // before that:
24172 //
24173 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
24174 // If a list item is an element of a structure, only the rightmost symbol
24175 // of the variable reference can be an array section.
24176 //
24177 AllowUnitySizeArraySection = false;
24178 AllowWholeSizeArraySection = false;
24179
24180 // Record the component.
24181 Components.emplace_back(Args&: ME, Args&: FD, Args&: IsNonContiguous);
24182 return RelevantExpr || Visit(S: E);
24183 }
24184
24185 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
24186 Expr *E = AE->getBase()->IgnoreParenImpCasts();
24187
24188 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
24189 if (!NoDiagnose) {
24190 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
24191 << 0 << AE->getSourceRange();
24192 return false;
24193 }
24194 return RelevantExpr || Visit(S: E);
24195 }
24196
24197 // If we got an array subscript that express the whole dimension we
24198 // can have any array expressions before. If it only expressing part of
24199 // the dimension, we can only have unitary-size array expressions.
24200 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, E: AE, BaseQTy: E->getType()))
24201 AllowWholeSizeArraySection = false;
24202
24203 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E->IgnoreParenCasts())) {
24204 Expr::EvalResult Result;
24205 if (!AE->getIdx()->isValueDependent() &&
24206 AE->getIdx()->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()) &&
24207 !Result.Val.getInt().isZero()) {
24208 SemaRef.Diag(Loc: AE->getIdx()->getExprLoc(),
24209 DiagID: diag::err_omp_invalid_map_this_expr);
24210 SemaRef.Diag(Loc: AE->getIdx()->getExprLoc(),
24211 DiagID: diag::note_omp_invalid_subscript_on_this_ptr_map);
24212 }
24213 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
24214 RelevantExpr = TE;
24215 }
24216
24217 // Record the component - we don't have any declaration associated.
24218 Components.emplace_back(Args&: AE, Args: nullptr, Args&: IsNonContiguous);
24219
24220 return RelevantExpr || Visit(S: E);
24221 }
24222
24223 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
24224 // After OMP 5.0 Array section in reduction clause will be implicitly
24225 // mapped
24226 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
24227 "Array sections cannot be implicitly mapped.");
24228 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
24229 QualType CurType =
24230 ArraySectionExpr::getBaseOriginalType(Base: E).getCanonicalType();
24231
24232 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
24233 // If the type of a list item is a reference to a type T then the type
24234 // will be considered to be T for all purposes of this clause.
24235 if (CurType->isReferenceType())
24236 CurType = CurType->getPointeeType();
24237
24238 bool IsPointer = CurType->isAnyPointerType();
24239
24240 if (!IsPointer && !CurType->isArrayType()) {
24241 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
24242 << 0 << OASE->getSourceRange();
24243 return false;
24244 }
24245
24246 bool NotWhole =
24247 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, E: OASE, BaseQTy: CurType);
24248 bool NotUnity =
24249 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, E: OASE, BaseQTy: CurType);
24250
24251 if (AllowWholeSizeArraySection) {
24252 // Any array section is currently allowed. Allowing a whole size array
24253 // section implies allowing a unity array section as well.
24254 //
24255 // If this array section refers to the whole dimension we can still
24256 // accept other array sections before this one, except if the base is a
24257 // pointer. Otherwise, only unitary sections are accepted.
24258 if (NotWhole || IsPointer)
24259 AllowWholeSizeArraySection = false;
24260 } else if (DKind == OMPD_target_update &&
24261 SemaRef.getLangOpts().OpenMP >= 50) {
24262 if (IsPointer && !AllowAnotherPtr)
24263 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_section_length_undefined)
24264 << /*array of unknown bound */ 1;
24265 else
24266 IsNonContiguous = true;
24267 } else if (AllowUnitySizeArraySection && NotUnity) {
24268 // A unity or whole array section is not allowed and that is not
24269 // compatible with the properties of the current array section.
24270 if (NoDiagnose)
24271 return false;
24272 SemaRef.Diag(Loc: ELoc,
24273 DiagID: diag::err_array_section_does_not_specify_contiguous_storage)
24274 << OASE->getSourceRange();
24275 return false;
24276 }
24277
24278 if (IsPointer)
24279 AllowAnotherPtr = false;
24280
24281 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E)) {
24282 Expr::EvalResult ResultR;
24283 Expr::EvalResult ResultL;
24284 if (!OASE->getLength()->isValueDependent() &&
24285 OASE->getLength()->EvaluateAsInt(Result&: ResultR, Ctx: SemaRef.getASTContext()) &&
24286 !ResultR.Val.getInt().isOne()) {
24287 SemaRef.Diag(Loc: OASE->getLength()->getExprLoc(),
24288 DiagID: diag::err_omp_invalid_map_this_expr);
24289 SemaRef.Diag(Loc: OASE->getLength()->getExprLoc(),
24290 DiagID: diag::note_omp_invalid_length_on_this_ptr_mapping);
24291 }
24292 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
24293 OASE->getLowerBound()->EvaluateAsInt(Result&: ResultL,
24294 Ctx: SemaRef.getASTContext()) &&
24295 !ResultL.Val.getInt().isZero()) {
24296 SemaRef.Diag(Loc: OASE->getLowerBound()->getExprLoc(),
24297 DiagID: diag::err_omp_invalid_map_this_expr);
24298 SemaRef.Diag(Loc: OASE->getLowerBound()->getExprLoc(),
24299 DiagID: diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
24300 }
24301 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
24302 RelevantExpr = TE;
24303 }
24304
24305 // Record the component - we don't have any declaration associated.
24306 Components.emplace_back(Args&: OASE, Args: nullptr, /*IsNonContiguous=*/Args: false);
24307 return RelevantExpr || Visit(S: E);
24308 }
24309 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
24310 Expr *Base = E->getBase();
24311
24312 // Record the component - we don't have any declaration associated.
24313 Components.emplace_back(Args&: E, Args: nullptr, Args&: IsNonContiguous);
24314
24315 return Visit(S: Base->IgnoreParenImpCasts());
24316 }
24317
24318 bool VisitUnaryOperator(UnaryOperator *UO) {
24319 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
24320 UO->getOpcode() != UO_Deref) {
24321 emitErrorMsg();
24322 return false;
24323 }
24324 if (!RelevantExpr) {
24325 // Record the component if haven't found base decl.
24326 Components.emplace_back(Args&: UO, Args: nullptr, /*IsNonContiguous=*/Args: false);
24327 }
24328 return RelevantExpr || Visit(S: UO->getSubExpr()->IgnoreParenImpCasts());
24329 }
24330 bool VisitBinaryOperator(BinaryOperator *BO) {
24331 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
24332 emitErrorMsg();
24333 return false;
24334 }
24335
24336 // Pointer arithmetic is the only thing we expect to happen here so after we
24337 // make sure the binary operator is a pointer type, the only thing we need
24338 // to do is to visit the subtree that has the same type as root (so that we
24339 // know the other subtree is just an offset)
24340 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
24341 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
24342 Components.emplace_back(Args&: BO, Args: nullptr, Args: false);
24343 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
24344 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
24345 "Either LHS or RHS have base decl inside");
24346 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
24347 return RelevantExpr || Visit(S: LE);
24348 return RelevantExpr || Visit(S: RE);
24349 }
24350 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
24351 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
24352 RelevantExpr = CTE;
24353 Components.emplace_back(Args&: CTE, Args: nullptr, Args&: IsNonContiguous);
24354 return true;
24355 }
24356 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
24357 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
24358 Components.emplace_back(Args&: COCE, Args: nullptr, Args&: IsNonContiguous);
24359 return true;
24360 }
24361 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
24362 Expr *Source = E->getSourceExpr();
24363 if (!Source) {
24364 emitErrorMsg();
24365 return false;
24366 }
24367 return Visit(S: Source);
24368 }
24369 bool VisitStmt(Stmt *) {
24370 emitErrorMsg();
24371 return false;
24372 }
24373 const Expr *getFoundBase() const { return RelevantExpr; }
24374 explicit MapBaseChecker(
24375 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
24376 OMPClauseMappableExprCommon::MappableExprComponentList &Components,
24377 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
24378 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
24379 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
24380};
24381} // namespace
24382
24383/// Return the expression of the base of the mappable expression or null if it
24384/// cannot be determined and do all the necessary checks to see if the
24385/// expression is valid as a standalone mappable expression. In the process,
24386/// record all the components of the expression.
24387static const Expr *checkMapClauseExpressionBase(
24388 Sema &SemaRef, Expr *E,
24389 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
24390 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
24391 SourceLocation ELoc = E->getExprLoc();
24392 SourceRange ERange = E->getSourceRange();
24393 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
24394 ERange);
24395 if (Checker.Visit(S: E->IgnoreParens())) {
24396 // Check if the highest dimension array section has length specified
24397 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
24398 (CKind == OMPC_to || CKind == OMPC_from)) {
24399 auto CI = CurComponents.rbegin();
24400 auto CE = CurComponents.rend();
24401 for (; CI != CE; ++CI) {
24402 const auto *OASE =
24403 dyn_cast<ArraySectionExpr>(Val: CI->getAssociatedExpression());
24404 if (!OASE)
24405 continue;
24406 if (OASE && OASE->getLength())
24407 break;
24408 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_array_section_does_not_specify_length)
24409 << ERange;
24410 }
24411 }
24412 return Checker.getFoundBase();
24413 }
24414 return nullptr;
24415}
24416
24417// Return true if expression E associated with value VD has conflicts with other
24418// map information.
24419static bool checkMapConflicts(
24420 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
24421 bool CurrentRegionOnly,
24422 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
24423 OpenMPClauseKind CKind) {
24424 assert(VD && E);
24425 SourceLocation ELoc = E->getExprLoc();
24426 SourceRange ERange = E->getSourceRange();
24427
24428 // In order to easily check the conflicts we need to match each component of
24429 // the expression under test with the components of the expressions that are
24430 // already in the stack.
24431
24432 assert(!CurComponents.empty() && "Map clause expression with no components!");
24433 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
24434 "Map clause expression with unexpected base!");
24435
24436 // Variables to help detecting enclosing problems in data environment nests.
24437 bool IsEnclosedByDataEnvironmentExpr = false;
24438 const Expr *EnclosingExpr = nullptr;
24439
24440 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
24441 VD, CurrentRegionOnly,
24442 Check: [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
24443 ERange, CKind, &EnclosingExpr,
24444 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
24445 StackComponents,
24446 OpenMPClauseKind Kind) {
24447 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
24448 return false;
24449 assert(!StackComponents.empty() &&
24450 "Map clause expression with no components!");
24451 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
24452 "Map clause expression with unexpected base!");
24453 (void)VD;
24454
24455 // The whole expression in the stack.
24456 const Expr *RE = StackComponents.front().getAssociatedExpression();
24457
24458 // Expressions must start from the same base. Here we detect at which
24459 // point both expressions diverge from each other and see if we can
24460 // detect if the memory referred to both expressions is contiguous and
24461 // do not overlap.
24462 auto CI = CurComponents.rbegin();
24463 auto CE = CurComponents.rend();
24464 auto SI = StackComponents.rbegin();
24465 auto SE = StackComponents.rend();
24466 for (; CI != CE && SI != SE; ++CI, ++SI) {
24467
24468 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
24469 // At most one list item can be an array item derived from a given
24470 // variable in map clauses of the same construct.
24471 if (CurrentRegionOnly &&
24472 (isa<ArraySubscriptExpr>(Val: CI->getAssociatedExpression()) ||
24473 isa<ArraySectionExpr>(Val: CI->getAssociatedExpression()) ||
24474 isa<OMPArrayShapingExpr>(Val: CI->getAssociatedExpression())) &&
24475 (isa<ArraySubscriptExpr>(Val: SI->getAssociatedExpression()) ||
24476 isa<ArraySectionExpr>(Val: SI->getAssociatedExpression()) ||
24477 isa<OMPArrayShapingExpr>(Val: SI->getAssociatedExpression()))) {
24478 SemaRef.Diag(Loc: CI->getAssociatedExpression()->getExprLoc(),
24479 DiagID: diag::err_omp_multiple_array_items_in_map_clause)
24480 << CI->getAssociatedExpression()->getSourceRange();
24481 SemaRef.Diag(Loc: SI->getAssociatedExpression()->getExprLoc(),
24482 DiagID: diag::note_used_here)
24483 << SI->getAssociatedExpression()->getSourceRange();
24484 return true;
24485 }
24486
24487 // Do both expressions have the same kind?
24488 if (CI->getAssociatedExpression()->getStmtClass() !=
24489 SI->getAssociatedExpression()->getStmtClass())
24490 break;
24491
24492 // Are we dealing with different variables/fields?
24493 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
24494 break;
24495 }
24496 // Check if the extra components of the expressions in the enclosing
24497 // data environment are redundant for the current base declaration.
24498 // If they are, the maps completely overlap, which is legal.
24499 for (; SI != SE; ++SI) {
24500 QualType Type;
24501 if (const auto *ASE =
24502 dyn_cast<ArraySubscriptExpr>(Val: SI->getAssociatedExpression())) {
24503 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
24504 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
24505 Val: SI->getAssociatedExpression())) {
24506 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
24507 Type = ArraySectionExpr::getBaseOriginalType(Base: E).getCanonicalType();
24508 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
24509 Val: SI->getAssociatedExpression())) {
24510 Type = OASE->getBase()->getType()->getPointeeType();
24511 }
24512 if (Type.isNull() || Type->isAnyPointerType() ||
24513 checkArrayExpressionDoesNotReferToWholeSize(
24514 SemaRef, E: SI->getAssociatedExpression(), BaseQTy: Type))
24515 break;
24516 }
24517
24518 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
24519 // List items of map clauses in the same construct must not share
24520 // original storage.
24521 //
24522 // If the expressions are exactly the same or one is a subset of the
24523 // other, it means they are sharing storage.
24524 if (CI == CE && SI == SE) {
24525 if (CurrentRegionOnly) {
24526 if (CKind == OMPC_map) {
24527 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << ERange;
24528 } else {
24529 assert(CKind == OMPC_to || CKind == OMPC_from);
24530 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced_in_target_update)
24531 << ERange;
24532 }
24533 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
24534 << RE->getSourceRange();
24535 return true;
24536 }
24537 // If we find the same expression in the enclosing data environment,
24538 // that is legal.
24539 IsEnclosedByDataEnvironmentExpr = true;
24540 return false;
24541 }
24542
24543 QualType DerivedType =
24544 std::prev(x: CI)->getAssociatedDeclaration()->getType();
24545 SourceLocation DerivedLoc =
24546 std::prev(x: CI)->getAssociatedExpression()->getExprLoc();
24547
24548 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
24549 // If the type of a list item is a reference to a type T then the type
24550 // will be considered to be T for all purposes of this clause.
24551 DerivedType = DerivedType.getNonReferenceType();
24552
24553 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
24554 // A variable for which the type is pointer and an array section
24555 // derived from that variable must not appear as list items of map
24556 // clauses of the same construct.
24557 //
24558 // Also, cover one of the cases in:
24559 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
24560 // If any part of the original storage of a list item has corresponding
24561 // storage in the device data environment, all of the original storage
24562 // must have corresponding storage in the device data environment.
24563 //
24564 if (DerivedType->isAnyPointerType()) {
24565 if (CI == CE || SI == SE) {
24566 SemaRef.Diag(
24567 Loc: DerivedLoc,
24568 DiagID: diag::err_omp_pointer_mapped_along_with_derived_section)
24569 << DerivedLoc;
24570 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
24571 << RE->getSourceRange();
24572 return true;
24573 }
24574 if (CI->getAssociatedExpression()->getStmtClass() !=
24575 SI->getAssociatedExpression()->getStmtClass() ||
24576 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
24577 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
24578 assert(CI != CE && SI != SE);
24579 SemaRef.Diag(Loc: DerivedLoc, DiagID: diag::err_omp_same_pointer_dereferenced)
24580 << DerivedLoc;
24581 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
24582 << RE->getSourceRange();
24583 return true;
24584 }
24585 }
24586
24587 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
24588 // List items of map clauses in the same construct must not share
24589 // original storage.
24590 //
24591 // An expression is a subset of the other.
24592 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
24593 if (CKind == OMPC_map) {
24594 if (CI != CE || SI != SE) {
24595 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
24596 // a pointer.
24597 auto Begin =
24598 CI != CE ? CurComponents.begin() : StackComponents.begin();
24599 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
24600 auto It = Begin;
24601 while (It != End && !It->getAssociatedDeclaration())
24602 std::advance(i&: It, n: 1);
24603 assert(It != End &&
24604 "Expected at least one component with the declaration.");
24605 if (It != Begin && It->getAssociatedDeclaration()
24606 ->getType()
24607 .getCanonicalType()
24608 ->isAnyPointerType()) {
24609 IsEnclosedByDataEnvironmentExpr = false;
24610 EnclosingExpr = nullptr;
24611 return false;
24612 }
24613 }
24614 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << ERange;
24615 } else {
24616 assert(CKind == OMPC_to || CKind == OMPC_from);
24617 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced_in_target_update)
24618 << ERange;
24619 }
24620 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
24621 << RE->getSourceRange();
24622 return true;
24623 }
24624
24625 // The current expression uses the same base as other expression in the
24626 // data environment but does not contain it completely.
24627 if (!CurrentRegionOnly && SI != SE)
24628 EnclosingExpr = RE;
24629
24630 // The current expression is a subset of the expression in the data
24631 // environment.
24632 IsEnclosedByDataEnvironmentExpr |=
24633 (!CurrentRegionOnly && CI != CE && SI == SE);
24634
24635 return false;
24636 });
24637
24638 if (CurrentRegionOnly)
24639 return FoundError;
24640
24641 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
24642 // If any part of the original storage of a list item has corresponding
24643 // storage in the device data environment, all of the original storage must
24644 // have corresponding storage in the device data environment.
24645 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
24646 // If a list item is an element of a structure, and a different element of
24647 // the structure has a corresponding list item in the device data environment
24648 // prior to a task encountering the construct associated with the map clause,
24649 // then the list item must also have a corresponding list item in the device
24650 // data environment prior to the task encountering the construct.
24651 //
24652 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
24653 SemaRef.Diag(Loc: ELoc,
24654 DiagID: diag::err_omp_original_storage_is_shared_and_does_not_contain)
24655 << ERange;
24656 SemaRef.Diag(Loc: EnclosingExpr->getExprLoc(), DiagID: diag::note_used_here)
24657 << EnclosingExpr->getSourceRange();
24658 return true;
24659 }
24660
24661 return FoundError;
24662}
24663
24664// Look up the user-defined mapper given the mapper name and mapped type, and
24665// build a reference to it. \a ItemLoc is the location of the mapped list item;
24666// it is used as the point of instantiation since \a MapperId has no location
24667// for implicit map clauses.
24668static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
24669 CXXScopeSpec &MapperIdScopeSpec,
24670 const DeclarationNameInfo &MapperId,
24671 QualType Type,
24672 Expr *UnresolvedMapper,
24673 SourceLocation ItemLoc) {
24674 if (MapperIdScopeSpec.isInvalid())
24675 return ExprError();
24676 // Get the actual type for the array type.
24677 if (Type->isArrayType()) {
24678 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
24679 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
24680 }
24681 // Find all user-defined mappers with the given MapperId.
24682 SmallVector<UnresolvedSet<8>, 4> Lookups;
24683 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
24684 Lookup.suppressDiagnostics();
24685 if (S) {
24686 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &MapperIdScopeSpec,
24687 /*ObjectType=*/QualType())) {
24688 NamedDecl *D = Lookup.getRepresentativeDecl();
24689 while (S && !S->isDeclScope(D))
24690 S = S->getParent();
24691 if (S)
24692 S = S->getParent();
24693 Lookups.emplace_back();
24694 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
24695 Lookup.clear();
24696 }
24697 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(Val: UnresolvedMapper)) {
24698 // Extract the user-defined mappers with the given MapperId.
24699 Lookups.push_back(Elt: UnresolvedSet<8>());
24700 for (NamedDecl *D : ULE->decls()) {
24701 auto *DMD = cast<OMPDeclareMapperDecl>(Val: D);
24702 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
24703 Lookups.back().addDecl(D: DMD);
24704 }
24705 }
24706 // Defer the lookup for dependent types. The results will be passed through
24707 // UnresolvedMapper on instantiation.
24708 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
24709 Type->isInstantiationDependentType() ||
24710 Type->containsUnexpandedParameterPack() ||
24711 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
24712 return !D->isInvalidDecl() &&
24713 (D->getType()->isDependentType() ||
24714 D->getType()->isInstantiationDependentType() ||
24715 D->getType()->containsUnexpandedParameterPack());
24716 })) {
24717 UnresolvedSet<8> URS;
24718 for (const UnresolvedSet<8> &Set : Lookups) {
24719 if (Set.empty())
24720 continue;
24721 URS.append(I: Set.begin(), E: Set.end());
24722 }
24723 return UnresolvedLookupExpr::Create(
24724 Context: SemaRef.Context, /*NamingClass=*/nullptr,
24725 QualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: SemaRef.Context), NameInfo: MapperId,
24726 /*ADL=*/RequiresADL: false, Begin: URS.begin(), End: URS.end(), /*KnownDependent=*/false,
24727 /*KnownInstantiationDependent=*/false);
24728 }
24729 SourceLocation Loc = MapperId.getLoc();
24730 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
24731 // The type must be of struct, union or class type in C and C++
24732 if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
24733 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
24734 SemaRef.Diag(Loc, DiagID: diag::err_omp_mapper_wrong_type);
24735 return ExprError();
24736 }
24737 // Perform argument dependent lookup.
24738 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
24739 argumentDependentLookup(SemaRef, Id: MapperId, Loc: ItemLoc, Ty: Type, Lookups);
24740 // Return the first user-defined mapper with the desired type.
24741 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
24742 Lookups, Gen: [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
24743 if (!D->isInvalidDecl() &&
24744 SemaRef.Context.hasSameType(T1: D->getType(), T2: Type))
24745 return D;
24746 return nullptr;
24747 }))
24748 return SemaRef.BuildDeclRefExpr(D: VD, Ty: Type, VK: VK_LValue, Loc);
24749 // Find the first user-defined mapper with a type derived from the desired
24750 // type.
24751 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
24752 Lookups, Gen: [&SemaRef, Type, ItemLoc](ValueDecl *D) -> ValueDecl * {
24753 if (!D->isInvalidDecl() &&
24754 SemaRef.IsDerivedFrom(Loc: ItemLoc, Derived: Type, Base: D->getType()) &&
24755 !Type.isMoreQualifiedThan(other: D->getType(),
24756 Ctx: SemaRef.getASTContext()))
24757 return D;
24758 return nullptr;
24759 })) {
24760 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
24761 /*DetectVirtual=*/false);
24762 if (SemaRef.IsDerivedFrom(Loc: ItemLoc, Derived: Type, Base: VD->getType(), Paths)) {
24763 if (!Paths.isAmbiguous(BaseType: SemaRef.Context.getCanonicalType(
24764 T: VD->getType().getUnqualifiedType()))) {
24765 if (SemaRef.CheckBaseClassAccess(
24766 AccessLoc: ItemLoc, Base: VD->getType(), Derived: Type, Path: Paths.front(),
24767 /*DiagID=*/0) != Sema::AR_inaccessible) {
24768 return SemaRef.BuildDeclRefExpr(D: VD, Ty: Type, VK: VK_LValue, Loc);
24769 }
24770 }
24771 }
24772 }
24773 // Report error if a mapper is specified, but cannot be found.
24774 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
24775 SemaRef.Diag(Loc, DiagID: diag::err_omp_invalid_mapper)
24776 << Type << MapperId.getName();
24777 return ExprError();
24778 }
24779 return ExprEmpty();
24780}
24781
24782namespace {
24783// Utility struct that gathers all the related lists associated with a mappable
24784// expression.
24785struct MappableVarListInfo {
24786 // The list of expressions.
24787 ArrayRef<Expr *> VarList;
24788 // The list of processed expressions.
24789 SmallVector<Expr *, 16> ProcessedVarList;
24790 // The mappble components for each expression.
24791 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
24792 // The base declaration of the variable.
24793 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
24794 // The reference to the user-defined mapper associated with every expression.
24795 SmallVector<Expr *, 16> UDMapperList;
24796
24797 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
24798 // We have a list of components and base declarations for each entry in the
24799 // variable list.
24800 VarComponents.reserve(N: VarList.size());
24801 VarBaseDeclarations.reserve(N: VarList.size());
24802 }
24803};
24804} // namespace
24805
24806static DeclRefExpr *buildImplicitMap(Sema &S, QualType BaseType,
24807 DSAStackTy *Stack,
24808 SmallVectorImpl<OMPClause *> &Maps) {
24809
24810 const RecordDecl *RD = BaseType->getAsRecordDecl();
24811 SourceRange Range = RD->getSourceRange();
24812 DeclarationNameInfo ImplicitName;
24813 // Dummy variable _s for Mapper.
24814 VarDecl *VD = buildVarDecl(SemaRef&: S, Loc: Range.getEnd(), Type: BaseType, Name: "_s");
24815 DeclRefExpr *MapperVarRef =
24816 buildDeclRefExpr(S, D: VD, Ty: BaseType, Loc: SourceLocation());
24817
24818 // Create implicit map clause for mapper.
24819 SmallVector<Expr *, 4> SExprs;
24820 for (auto *FD : RD->fields()) {
24821 Expr *BE = S.BuildMemberExpr(
24822 Base: MapperVarRef, /*IsArrow=*/false, OpLoc: Range.getBegin(),
24823 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: Range.getBegin(), Member: FD,
24824 FoundDecl: DeclAccessPair::make(D: FD, AS: FD->getAccess()),
24825 /*HadMultipleCandidates=*/false,
24826 MemberNameInfo: DeclarationNameInfo(FD->getDeclName(), FD->getSourceRange().getBegin()),
24827 Ty: FD->getType(), VK: VK_LValue, OK: OK_Ordinary);
24828 SExprs.push_back(Elt: BE);
24829 }
24830 CXXScopeSpec MapperIdScopeSpec;
24831 DeclarationNameInfo MapperId;
24832 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
24833
24834 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
24835 IteratorModifier: nullptr, MapTypeModifiers: OMPC_MAP_MODIFIER_unknown, MapTypeModifiersLoc: SourceLocation(), MapperIdScopeSpec,
24836 MapperId, MapType: DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
24837 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(), VarList: SExprs,
24838 Locs: OMPVarListLocTy());
24839 Maps.push_back(Elt: MapClause);
24840 return MapperVarRef;
24841}
24842
24843static ExprResult buildImplicitMapper(Sema &S, QualType BaseType,
24844 DSAStackTy *Stack) {
24845
24846 // Build impilicit map for mapper
24847 SmallVector<OMPClause *, 4> Maps;
24848 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
24849
24850 const RecordDecl *RD = BaseType->getAsRecordDecl();
24851 // AST context is RD's ParentASTContext().
24852 ASTContext &Ctx = RD->getParentASTContext();
24853 // DeclContext is RD's DeclContext.
24854 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
24855
24856 // Create implicit default mapper for "RD".
24857 DeclarationName MapperId;
24858 auto &DeclNames = Ctx.DeclarationNames;
24859 MapperId = DeclNames.getIdentifier(ID: &Ctx.Idents.get(Name: "default"));
24860 auto *DMD = OMPDeclareMapperDecl::Create(C&: Ctx, DC: DCT, L: SourceLocation(), Name: MapperId,
24861 T: BaseType, VarName: MapperId, Clauses: Maps, PrevDeclInScope: nullptr);
24862 Scope *Scope = S.getScopeForContext(Ctx: DCT);
24863 if (Scope)
24864 S.PushOnScopeChains(D: DMD, S: Scope, /*AddToContext=*/false);
24865 DCT->addDecl(D: DMD);
24866 DMD->setAccess(clang::AS_none);
24867 auto *VD = cast<DeclRefExpr>(Val: MapperVarRef)->getDecl();
24868 VD->setDeclContext(DMD);
24869 VD->setLexicalDeclContext(DMD);
24870 DMD->addDecl(D: VD);
24871 DMD->setMapperVarRef(MapperVarRef);
24872 FieldDecl *FD = *RD->field_begin();
24873 // create mapper refence.
24874 return DeclRefExpr::Create(Context: Ctx, QualifierLoc: NestedNameSpecifierLoc{}, TemplateKWLoc: FD->getLocation(),
24875 D: DMD, RefersToEnclosingVariableOrCapture: false, NameLoc: SourceLocation(), T: BaseType, VK: VK_LValue);
24876}
24877
24878// Look up the user-defined mapper given the mapper name and mapper type,
24879// return true if found one.
24880static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
24881 CXXScopeSpec &MapperIdScopeSpec,
24882 const DeclarationNameInfo &MapperId,
24883 QualType Type) {
24884 // Find all user-defined mappers with the given MapperId.
24885 SmallVector<UnresolvedSet<8>, 4> Lookups;
24886 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
24887 Lookup.suppressDiagnostics();
24888 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &MapperIdScopeSpec,
24889 /*ObjectType=*/QualType())) {
24890 NamedDecl *D = Lookup.getRepresentativeDecl();
24891 while (S && !S->isDeclScope(D))
24892 S = S->getParent();
24893 if (S)
24894 S = S->getParent();
24895 Lookups.emplace_back();
24896 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
24897 Lookup.clear();
24898 }
24899 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
24900 Type->isInstantiationDependentType() ||
24901 Type->containsUnexpandedParameterPack() ||
24902 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
24903 return !D->isInvalidDecl() &&
24904 (D->getType()->isDependentType() ||
24905 D->getType()->isInstantiationDependentType() ||
24906 D->getType()->containsUnexpandedParameterPack());
24907 }))
24908 return false;
24909 // Perform argument dependent lookup.
24910 SourceLocation Loc = MapperId.getLoc();
24911 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
24912 argumentDependentLookup(SemaRef, Id: MapperId, Loc, Ty: Type, Lookups);
24913 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
24914 Lookups, Gen: [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
24915 if (!D->isInvalidDecl() &&
24916 SemaRef.Context.hasSameType(T1: D->getType(), T2: Type))
24917 return D;
24918 return nullptr;
24919 }))
24920 return true;
24921 // Find the first user-defined mapper with a type derived from the desired
24922 // type.
24923 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
24924 Lookups, Gen: [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
24925 if (!D->isInvalidDecl() &&
24926 SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: D->getType()) &&
24927 !Type.isMoreQualifiedThan(other: D->getType(), Ctx: SemaRef.getASTContext()))
24928 return D;
24929 return nullptr;
24930 });
24931 if (!VD)
24932 return false;
24933 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
24934 /*DetectVirtual=*/false);
24935 if (SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: VD->getType(), Paths)) {
24936 bool IsAmbiguous = !Paths.isAmbiguous(
24937 BaseType: SemaRef.Context.getCanonicalType(T: VD->getType().getUnqualifiedType()));
24938 if (IsAmbiguous)
24939 return false;
24940 if (SemaRef.CheckBaseClassAccess(AccessLoc: Loc, Base: VD->getType(), Derived: Type, Path: Paths.front(),
24941 /*DiagID=*/0) != Sema::AR_inaccessible)
24942 return true;
24943 }
24944 return false;
24945}
24946
24947static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
24948 QualType CanonType, const Expr *E) {
24949
24950 // DFS over data members in structures/classes.
24951 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(1,
24952 {CanonType, nullptr});
24953 llvm::DenseMap<const Type *, bool> Visited;
24954 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
24955 while (!Types.empty()) {
24956 auto [BaseType, CurFD] = Types.pop_back_val();
24957 while (ParentChain.back().second == 0)
24958 ParentChain.pop_back();
24959 --ParentChain.back().second;
24960 if (BaseType.isNull())
24961 continue;
24962 // Only structs/classes are allowed to have mappers.
24963 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
24964 if (!RD)
24965 continue;
24966 auto It = Visited.find(Val: BaseType.getTypePtr());
24967 if (It == Visited.end()) {
24968 // Try to find the associated user-defined mapper.
24969 CXXScopeSpec MapperIdScopeSpec;
24970 DeclarationNameInfo DefaultMapperId;
24971 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
24972 ID: &S.Context.Idents.get(Name: "default")));
24973 DefaultMapperId.setLoc(E->getExprLoc());
24974 bool HasUDMapper =
24975 hasUserDefinedMapper(SemaRef&: S, S: Stack->getCurScope(), MapperIdScopeSpec,
24976 MapperId: DefaultMapperId, Type: BaseType);
24977 It = Visited.try_emplace(Key: BaseType.getTypePtr(), Args&: HasUDMapper).first;
24978 }
24979 // Found default mapper.
24980 if (It->second)
24981 return true;
24982 // Check for the "default" mapper for data members.
24983 bool FirstIter = true;
24984 for (FieldDecl *FD : RD->fields()) {
24985 if (!FD)
24986 continue;
24987 QualType FieldTy = FD->getType();
24988 if (FieldTy.isNull() ||
24989 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
24990 continue;
24991 if (FirstIter) {
24992 FirstIter = false;
24993 ParentChain.emplace_back(Args&: CurFD, Args: 1);
24994 } else {
24995 ++ParentChain.back().second;
24996 }
24997 Types.emplace_back(Args&: FieldTy, Args&: FD);
24998 }
24999 }
25000 return false;
25001}
25002
25003// Check the validity of the provided variable list for the provided clause kind
25004// \a CKind. In the check process the valid expressions, mappable expression
25005// components, variables, and user-defined mappers are extracted and used to
25006// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
25007// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
25008// and \a MapperId are expected to be valid if the clause kind is 'map'.
25009static void checkMappableExpressionList(
25010 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
25011 MappableVarListInfo &MVLI, SourceLocation StartLoc,
25012 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
25013 ArrayRef<Expr *> UnresolvedMappers,
25014 OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
25015 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
25016 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
25017 // We only expect mappable expressions in 'to', 'from', 'map', and
25018 // 'use_device_addr' clauses.
25019 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from ||
25020 CKind == OMPC_use_device_addr) &&
25021 "Unexpected clause kind with mappable expressions!");
25022 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
25023
25024 // If the identifier of user-defined mapper is not specified, it is "default".
25025 // We do not change the actual name in this clause to distinguish whether a
25026 // mapper is specified explicitly, i.e., it is not explicitly specified when
25027 // MapperId.getName() is empty.
25028 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
25029 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
25030 MapperId.setName(DeclNames.getIdentifier(
25031 ID: &SemaRef.getASTContext().Idents.get(Name: "default")));
25032 MapperId.setLoc(StartLoc);
25033 }
25034
25035 // Iterators to find the current unresolved mapper expression.
25036 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
25037 bool UpdateUMIt = false;
25038 Expr *UnresolvedMapper = nullptr;
25039
25040 bool HasHoldModifier =
25041 llvm::is_contained(Range&: Modifiers, Element: OMPC_MAP_MODIFIER_ompx_hold);
25042
25043 // Keep track of the mappable components and base declarations in this clause.
25044 // Each entry in the list is going to have a list of components associated. We
25045 // record each set of the components so that we can build the clause later on.
25046 // In the end we should have the same amount of declarations and component
25047 // lists.
25048
25049 for (Expr *RE : MVLI.VarList) {
25050 assert(RE && "Null expr in omp to/from/map clause");
25051 SourceLocation ELoc = RE->getExprLoc();
25052
25053 // Find the current unresolved mapper expression.
25054 if (UpdateUMIt && UMIt != UMEnd) {
25055 UMIt++;
25056 assert(
25057 UMIt != UMEnd &&
25058 "Expect the size of UnresolvedMappers to match with that of VarList");
25059 }
25060 UpdateUMIt = true;
25061 if (UMIt != UMEnd)
25062 UnresolvedMapper = *UMIt;
25063
25064 const Expr *VE = RE->IgnoreParenLValueCasts();
25065
25066 if (VE->isValueDependent() || VE->isTypeDependent() ||
25067 VE->isInstantiationDependent() ||
25068 VE->containsUnexpandedParameterPack()) {
25069 // Try to find the associated user-defined mapper.
25070 ExprResult ER = buildUserDefinedMapperRef(
25071 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
25072 Type: VE->getType().getCanonicalType(), UnresolvedMapper, ItemLoc: ELoc);
25073 if (ER.isInvalid())
25074 continue;
25075 MVLI.UDMapperList.push_back(Elt: ER.get());
25076 // We can only analyze this information once the missing information is
25077 // resolved.
25078 MVLI.ProcessedVarList.push_back(Elt: RE);
25079 continue;
25080 }
25081
25082 Expr *SimpleExpr = RE->IgnoreParenCasts();
25083 if (!RE->isLValue()) {
25084 if (SemaRef.getLangOpts().OpenMP < 50) {
25085 SemaRef.Diag(
25086 Loc: ELoc, DiagID: diag::err_omp_expected_named_var_member_or_array_expression)
25087 << RE->getSourceRange();
25088 } else {
25089 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_non_lvalue_in_map_or_motion_clauses)
25090 << getOpenMPClauseNameForDiag(C: CKind) << RE->getSourceRange();
25091 }
25092 continue;
25093 }
25094
25095 // Check for unsupported structured bindings early.
25096 if (!NoDiagnose) {
25097 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: SimpleExpr)) {
25098 const DecompositionDecl *DD = nullptr;
25099 const BindingDecl *BD = nullptr;
25100 if (const auto *B = dyn_cast<BindingDecl>(Val: DRE->getDecl())) {
25101 BD = B;
25102 DD = cast<DecompositionDecl>(Val: B->getDecomposedDecl());
25103 } else if (const auto *D =
25104 dyn_cast<DecompositionDecl>(Val: DRE->getDecl())) {
25105 DD = D;
25106 }
25107 if (DD) {
25108 if (BD && BD->getHoldingVar()) {
25109 SemaRef.Diag(Loc: ELoc,
25110 DiagID: diag::err_omp_unsupported_structured_binding_init)
25111 << 4;
25112 continue;
25113 }
25114 if (!getOriginalVarOrDiagnose(S&: SemaRef, DD, Loc: ELoc))
25115 continue;
25116 }
25117 }
25118 }
25119 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
25120 ValueDecl *CurDeclaration = nullptr;
25121
25122 // Obtain the array or member expression bases if required. Also, fill the
25123 // components array with all the components identified in the process.
25124 const Expr *BE =
25125 checkMapClauseExpressionBase(SemaRef, E: SimpleExpr, CurComponents, CKind,
25126 DKind: DSAS->getCurrentDirective(), NoDiagnose);
25127 if (!BE)
25128 continue;
25129
25130 assert(!CurComponents.empty() &&
25131 "Invalid mappable expression information.");
25132
25133 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: BE)) {
25134 // Add store "this" pointer to class in DSAStackTy for future checking
25135 DSAS->addMappedClassesQualTypes(QT: TE->getType());
25136 // Try to find the associated user-defined mapper.
25137 ExprResult ER = buildUserDefinedMapperRef(
25138 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
25139 Type: VE->getType().getCanonicalType(), UnresolvedMapper, ItemLoc: ELoc);
25140 if (ER.isInvalid())
25141 continue;
25142 MVLI.UDMapperList.push_back(Elt: ER.get());
25143 // Skip restriction checking for variable or field declarations
25144 MVLI.ProcessedVarList.push_back(Elt: RE);
25145 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
25146 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
25147 in_end: CurComponents.end());
25148 MVLI.VarBaseDeclarations.push_back(Elt: nullptr);
25149 continue;
25150 }
25151
25152 // For the following checks, we rely on the base declaration which is
25153 // expected to be associated with the last component. The declaration is
25154 // expected to be a variable or a field (if 'this' is being mapped).
25155 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
25156 assert(CurDeclaration && "Null decl on map clause.");
25157 assert(
25158 CurDeclaration->isCanonicalDecl() &&
25159 "Expecting components to have associated only canonical declarations.");
25160
25161 auto *VD = dyn_cast<VarDecl>(Val: CurDeclaration);
25162 const auto *FD = dyn_cast<FieldDecl>(Val: CurDeclaration);
25163
25164 assert((VD || FD) && "Only variables or fields are expected here!");
25165 (void)FD;
25166
25167 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
25168 // threadprivate variables cannot appear in a map clause.
25169 // OpenMP 4.5 [2.10.5, target update Construct]
25170 // threadprivate variables cannot appear in a from clause.
25171 if (VD && DSAS->isThreadPrivate(D: VD)) {
25172 if (NoDiagnose)
25173 continue;
25174 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(D: VD, /*FromParent=*/false);
25175 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_threadprivate_in_clause)
25176 << getOpenMPClauseNameForDiag(C: CKind);
25177 reportOriginalDsa(SemaRef, Stack: DSAS, D: VD, DVar);
25178 continue;
25179 }
25180
25181 // OpenMP 6.0 [7.9.6, map Clause, Restrictions, p. 386]
25182 // A device-local variable must not appear as a list item in a map clause.
25183 if (VD && CKind == OMPC_map) {
25184 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
25185 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
25186 if (*Res == OMPDeclareTargetDeclAttr::MT_Local) {
25187 if (NoDiagnose)
25188 continue;
25189 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_device_local_in_clause)
25190 << VD << getOpenMPClauseNameForDiag(C: CKind);
25191 continue;
25192 }
25193 }
25194 }
25195
25196 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
25197 // A list item cannot appear in both a map clause and a data-sharing
25198 // attribute clause on the same construct.
25199
25200 // Check conflicts with other map clause expressions. We check the conflicts
25201 // with the current construct separately from the enclosing data
25202 // environment, because the restrictions are different. We only have to
25203 // check conflicts across regions for the map clauses.
25204 if (checkMapConflicts(SemaRef, DSAS, VD: CurDeclaration, E: SimpleExpr,
25205 /*CurrentRegionOnly=*/true, CurComponents, CKind))
25206 break;
25207 if (CKind == OMPC_map &&
25208 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
25209 checkMapConflicts(SemaRef, DSAS, VD: CurDeclaration, E: SimpleExpr,
25210 /*CurrentRegionOnly=*/false, CurComponents, CKind))
25211 break;
25212
25213 // OpenMP 4.5 [2.10.5, target update Construct]
25214 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
25215 // If the type of a list item is a reference to a type T then the type will
25216 // be considered to be T for all purposes of this clause.
25217 auto I = llvm::find_if(
25218 Range&: CurComponents,
25219 P: [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
25220 return MC.getAssociatedDeclaration();
25221 });
25222 assert(I != CurComponents.end() && "Null decl on map clause.");
25223 (void)I;
25224 QualType Type;
25225 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: VE->IgnoreParens());
25226 auto *OASE = dyn_cast<ArraySectionExpr>(Val: VE->IgnoreParens());
25227 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(Val: VE->IgnoreParens());
25228 if (ASE) {
25229 Type = ASE->getType().getNonReferenceType();
25230 } else if (OASE) {
25231 QualType BaseType =
25232 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
25233 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
25234 Type = ATy->getElementType();
25235 else
25236 Type = BaseType->getPointeeType();
25237 Type = Type.getNonReferenceType();
25238 } else if (OAShE) {
25239 Type = OAShE->getBase()->getType()->getPointeeType();
25240 } else {
25241 Type = VE->getType();
25242 }
25243
25244 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
25245 // A list item in a to or from clause must have a mappable type.
25246 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
25247 // A list item must have a mappable type.
25248 if (!checkTypeMappable(SL: VE->getExprLoc(), SR: VE->getSourceRange(), SemaRef,
25249 Stack: DSAS, QTy: Type, /*FullCheck=*/true))
25250 continue;
25251
25252 if (CKind == OMPC_map) {
25253 // target enter data
25254 // OpenMP [2.10.2, Restrictions, p. 99]
25255 // A map-type must be specified in all map clauses and must be either
25256 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
25257 // no map type is present.
25258 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
25259 if (DKind == OMPD_target_enter_data &&
25260 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
25261 SemaRef.getLangOpts().OpenMP >= 52)) {
25262 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
25263 << (IsMapTypeImplicit ? 1 : 0)
25264 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
25265 << getOpenMPDirectiveName(D: DKind, V: OMPVersion);
25266 continue;
25267 }
25268
25269 // target exit_data
25270 // OpenMP [2.10.3, Restrictions, p. 102]
25271 // A map-type must be specified in all map clauses and must be either
25272 // from, release, or delete. Starting with OpenMP 5.2 the default map
25273 // type is `from` if no map type is present.
25274 if (DKind == OMPD_target_exit_data &&
25275 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
25276 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
25277 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
25278 << (IsMapTypeImplicit ? 1 : 0)
25279 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
25280 << getOpenMPDirectiveName(D: DKind, V: OMPVersion);
25281 continue;
25282 }
25283
25284 // The 'ompx_hold' modifier is specifically intended to be used on a
25285 // 'target' or 'target data' directive to prevent data from being unmapped
25286 // during the associated statement. It is not permitted on a 'target
25287 // enter data' or 'target exit data' directive, which have no associated
25288 // statement.
25289 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
25290 HasHoldModifier) {
25291 SemaRef.Diag(Loc: StartLoc,
25292 DiagID: diag::err_omp_invalid_map_type_modifier_for_directive)
25293 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map,
25294 Type: OMPC_MAP_MODIFIER_ompx_hold)
25295 << getOpenMPDirectiveName(D: DKind, V: OMPVersion);
25296 continue;
25297 }
25298
25299 // target, target data
25300 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
25301 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
25302 // A map-type in a map clause must be to, from, tofrom or alloc
25303 if ((DKind == OMPD_target_data ||
25304 isOpenMPTargetExecutionDirective(DKind)) &&
25305 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
25306 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
25307 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
25308 << (IsMapTypeImplicit ? 1 : 0)
25309 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
25310 << getOpenMPDirectiveName(D: DKind, V: OMPVersion);
25311 continue;
25312 }
25313
25314 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
25315 // A list item cannot appear in both a map clause and a data-sharing
25316 // attribute clause on the same construct
25317 //
25318 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
25319 // A list item cannot appear in both a map clause and a data-sharing
25320 // attribute clause on the same construct unless the construct is a
25321 // combined construct.
25322 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
25323 isOpenMPTargetExecutionDirective(DKind)) ||
25324 DKind == OMPD_target)) {
25325 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(D: VD, /*FromParent=*/false);
25326 if (isOpenMPPrivate(Kind: DVar.CKind)) {
25327 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
25328 << getOpenMPClauseNameForDiag(C: DVar.CKind)
25329 << getOpenMPClauseNameForDiag(C: OMPC_map)
25330 << getOpenMPDirectiveName(D: DSAS->getCurrentDirective(),
25331 V: OMPVersion);
25332 reportOriginalDsa(SemaRef, Stack: DSAS, D: CurDeclaration, DVar);
25333 continue;
25334 }
25335 }
25336 }
25337
25338 // Try to find the associated user-defined mapper.
25339 ExprResult ER = buildUserDefinedMapperRef(
25340 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
25341 Type: Type.getCanonicalType(), UnresolvedMapper, ItemLoc: ELoc);
25342 if (ER.isInvalid())
25343 continue;
25344
25345 // If no user-defined mapper is found, we need to create an implicit one for
25346 // arrays/array-sections on structs that have members that have
25347 // user-defined mappers. This is needed to ensure that the mapper for the
25348 // member is invoked when mapping each element of the array/array-section.
25349 if (!ER.get()) {
25350 QualType BaseType;
25351
25352 if (isa<ArraySectionExpr>(Val: VE)) {
25353 BaseType = VE->getType().getCanonicalType();
25354 if (BaseType->isSpecificBuiltinType(K: BuiltinType::ArraySection)) {
25355 const auto *OASE = cast<ArraySectionExpr>(Val: VE->IgnoreParenImpCasts());
25356 QualType BType =
25357 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
25358 QualType ElemType;
25359 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
25360 ElemType = ATy->getElementType();
25361 else
25362 ElemType = BType->getPointeeType();
25363 BaseType = ElemType.getCanonicalType();
25364 }
25365 } else if (VE->getType()->isArrayType()) {
25366 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
25367 const QualType ElemType = AT->getElementType();
25368 BaseType = ElemType.getCanonicalType();
25369 }
25370
25371 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
25372 isImplicitMapperNeeded(S&: SemaRef, Stack: DSAS, CanonType: BaseType, E: VE)) {
25373 ER = buildImplicitMapper(S&: SemaRef, BaseType, Stack: DSAS);
25374 }
25375 }
25376 MVLI.UDMapperList.push_back(Elt: ER.get());
25377
25378 // Save the current expression.
25379 MVLI.ProcessedVarList.push_back(Elt: RE);
25380
25381 // Store the components in the stack so that they can be used to check
25382 // against other clauses later on.
25383 DSAS->addMappableExpressionComponents(VD: CurDeclaration, Components: CurComponents,
25384 /*WhereFoundClauseKind=*/OMPC_map);
25385
25386 // Save the components and declaration to create the clause. For purposes of
25387 // the clause creation, any component list that has base 'this' uses
25388 // null as base declaration.
25389 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
25390 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
25391 in_end: CurComponents.end());
25392 MVLI.VarBaseDeclarations.push_back(Elt: isa<MemberExpr>(Val: BE) ? nullptr
25393 : CurDeclaration);
25394 }
25395}
25396
25397OMPClause *SemaOpenMP::ActOnOpenMPMapClause(
25398 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
25399 ArrayRef<SourceLocation> MapTypeModifiersLoc,
25400 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
25401 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
25402 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
25403 const OMPVarListLocTy &Locs, bool NoDiagnose,
25404 ArrayRef<Expr *> UnresolvedMappers) {
25405 OpenMPMapModifierKind Modifiers[] = {
25406 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
25407 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
25408 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
25409 OMPC_MAP_MODIFIER_unknown};
25410 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
25411
25412 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
25413 K: BuiltinType::OMPIterator))
25414 Diag(Loc: IteratorModifier->getExprLoc(),
25415 DiagID: diag::err_omp_map_modifier_not_iterator);
25416
25417 // Process map-type-modifiers, flag errors for duplicate modifiers.
25418 unsigned Count = 0;
25419 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
25420 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
25421 llvm::is_contained(Range&: Modifiers, Element: MapTypeModifiers[I])) {
25422 Diag(Loc: MapTypeModifiersLoc[I], DiagID: diag::err_omp_duplicate_map_type_modifier);
25423 continue;
25424 }
25425 assert(Count < NumberOfOMPMapClauseModifiers &&
25426 "Modifiers exceed the allowed number of map type modifiers");
25427 Modifiers[Count] = MapTypeModifiers[I];
25428 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
25429 ++Count;
25430 }
25431
25432 MappableVarListInfo MVLI(VarList);
25433 // Per OpenMP 6.0 p299 lines 3-4, a list item with the const specifier and
25434 // no mutable members is ignored for 'from' clauses. A const-qualified
25435 // variable cannot be modified on the device, so copying back to the host
25436 // is unnecessary and potentially unsafe. Strip the FROM component:
25437 // map(tofrom:) -> map(to:), map(from:) -> map(alloc:).
25438 for (auto *E : VarList) {
25439 if ((MapType == OMPC_MAP_from || MapType == OMPC_MAP_tofrom) &&
25440 hasConstQualifiedMappingType(T: E->getType()))
25441 MapType = (MapType == OMPC_MAP_tofrom) ? OMPC_MAP_to : OMPC_MAP_alloc;
25442 }
25443 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_map, MVLI, StartLoc: Locs.StartLoc,
25444 MapperIdScopeSpec, MapperId, UnresolvedMappers,
25445 MapType, Modifiers, IsMapTypeImplicit,
25446 NoDiagnose);
25447
25448 // We need to produce a map clause even if we don't have variables so that
25449 // other diagnostics related with non-existing map clauses are accurate.
25450 return OMPMapClause::Create(
25451 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25452 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, IteratorModifier, MapModifiers: Modifiers,
25453 MapModifiersLoc: ModifiersLoc, UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()),
25454 MapperId, Type: MapType, TypeIsImplicit: IsMapTypeImplicit, TypeLoc: MapLoc);
25455}
25456
25457QualType SemaOpenMP::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
25458 TypeResult ParsedType) {
25459 assert(ParsedType.isUsable());
25460
25461 QualType ReductionType = SemaRef.GetTypeFromParser(Ty: ParsedType.get());
25462 if (ReductionType.isNull())
25463 return QualType();
25464
25465 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
25466 // A type name in a declare reduction directive cannot be a function type, an
25467 // array type, a reference type, or a type qualified with const, volatile or
25468 // restrict.
25469 if (ReductionType.hasQualifiers()) {
25470 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 0;
25471 return QualType();
25472 }
25473
25474 if (ReductionType->isFunctionType()) {
25475 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 1;
25476 return QualType();
25477 }
25478 if (ReductionType->isReferenceType()) {
25479 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 2;
25480 return QualType();
25481 }
25482 if (ReductionType->isArrayType()) {
25483 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 3;
25484 return QualType();
25485 }
25486 return ReductionType;
25487}
25488
25489SemaOpenMP::DeclGroupPtrTy
25490SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveStart(
25491 Scope *S, DeclContext *DC, DeclarationName Name,
25492 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
25493 AccessSpecifier AS, Decl *PrevDeclInScope) {
25494 SmallVector<Decl *, 8> Decls;
25495 Decls.reserve(N: ReductionTypes.size());
25496
25497 LookupResult Lookup(SemaRef, Name, SourceLocation(),
25498 Sema::LookupOMPReductionName,
25499 SemaRef.forRedeclarationInCurContext());
25500 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
25501 // A reduction-identifier may not be re-declared in the current scope for the
25502 // same type or for a type that is compatible according to the base language
25503 // rules.
25504 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
25505 OMPDeclareReductionDecl *PrevDRD = nullptr;
25506 bool InCompoundScope = true;
25507 if (S != nullptr) {
25508 // Find previous declaration with the same name not referenced in other
25509 // declarations.
25510 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
25511 InCompoundScope =
25512 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
25513 SemaRef.LookupName(R&: Lookup, S);
25514 SemaRef.FilterLookupForScope(R&: Lookup, Ctx: DC, S, /*ConsiderLinkage=*/false,
25515 /*AllowInlineNamespace=*/false);
25516 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
25517 LookupResult::Filter Filter = Lookup.makeFilter();
25518 while (Filter.hasNext()) {
25519 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Val: Filter.next());
25520 if (InCompoundScope) {
25521 UsedAsPrevious.try_emplace(Key: PrevDecl, Args: false);
25522 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
25523 UsedAsPrevious[D] = true;
25524 }
25525 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
25526 PrevDecl->getLocation();
25527 }
25528 Filter.done();
25529 if (InCompoundScope) {
25530 for (const auto &PrevData : UsedAsPrevious) {
25531 if (!PrevData.second) {
25532 PrevDRD = PrevData.first;
25533 break;
25534 }
25535 }
25536 }
25537 } else if (PrevDeclInScope != nullptr) {
25538 auto *PrevDRDInScope = PrevDRD =
25539 cast<OMPDeclareReductionDecl>(Val: PrevDeclInScope);
25540 do {
25541 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
25542 PrevDRDInScope->getLocation();
25543 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
25544 } while (PrevDRDInScope != nullptr);
25545 }
25546 for (const auto &TyData : ReductionTypes) {
25547 const auto I = PreviousRedeclTypes.find(Val: TyData.first.getCanonicalType());
25548 bool Invalid = false;
25549 if (I != PreviousRedeclTypes.end()) {
25550 Diag(Loc: TyData.second, DiagID: diag::err_omp_declare_reduction_redefinition)
25551 << TyData.first;
25552 Diag(Loc: I->second, DiagID: diag::note_previous_definition);
25553 Invalid = true;
25554 }
25555 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
25556 auto *DRD = OMPDeclareReductionDecl::Create(
25557 C&: getASTContext(), DC, L: TyData.second, Name, T: TyData.first, PrevDeclInScope: PrevDRD);
25558 DC->addDecl(D: DRD);
25559 DRD->setAccess(AS);
25560 Decls.push_back(Elt: DRD);
25561 if (Invalid)
25562 DRD->setInvalidDecl();
25563 else
25564 PrevDRD = DRD;
25565 }
25566
25567 return DeclGroupPtrTy::make(
25568 P: DeclGroupRef::Create(C&: getASTContext(), Decls: Decls.begin(), NumDecls: Decls.size()));
25569}
25570
25571void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
25572 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
25573
25574 // Enter new function scope.
25575 SemaRef.PushFunctionScope();
25576 SemaRef.setFunctionHasBranchProtectedScope();
25577 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
25578
25579 if (S != nullptr)
25580 SemaRef.PushDeclContext(S, DC: DRD);
25581 else
25582 SemaRef.CurContext = DRD;
25583
25584 SemaRef.PushExpressionEvaluationContext(
25585 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
25586
25587 QualType ReductionType = DRD->getType();
25588 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
25589 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
25590 // uses semantics of argument handles by value, but it should be passed by
25591 // reference. C lang does not support references, so pass all parameters as
25592 // pointers.
25593 // Create 'T omp_in;' variable.
25594 VarDecl *OmpInParm =
25595 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_in");
25596 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
25597 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
25598 // uses semantics of argument handles by value, but it should be passed by
25599 // reference. C lang does not support references, so pass all parameters as
25600 // pointers.
25601 // Create 'T omp_out;' variable.
25602 VarDecl *OmpOutParm =
25603 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_out");
25604 if (S != nullptr) {
25605 SemaRef.PushOnScopeChains(D: OmpInParm, S);
25606 SemaRef.PushOnScopeChains(D: OmpOutParm, S);
25607 } else {
25608 DRD->addDecl(D: OmpInParm);
25609 DRD->addDecl(D: OmpOutParm);
25610 }
25611 Expr *InE =
25612 ::buildDeclRefExpr(S&: SemaRef, D: OmpInParm, Ty: ReductionType, Loc: D->getLocation());
25613 Expr *OutE =
25614 ::buildDeclRefExpr(S&: SemaRef, D: OmpOutParm, Ty: ReductionType, Loc: D->getLocation());
25615 DRD->setCombinerData(InE, OutE);
25616}
25617
25618void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D,
25619 Expr *Combiner) {
25620 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
25621 SemaRef.DiscardCleanupsInEvaluationContext();
25622 SemaRef.PopExpressionEvaluationContext();
25623
25624 SemaRef.PopDeclContext();
25625 SemaRef.PopFunctionScopeInfo();
25626
25627 if (Combiner != nullptr)
25628 DRD->setCombiner(Combiner);
25629 else
25630 DRD->setInvalidDecl();
25631}
25632
25633VarDecl *SemaOpenMP::ActOnOpenMPDeclareReductionInitializerStart(Scope *S,
25634 Decl *D) {
25635 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
25636
25637 // Enter new function scope.
25638 SemaRef.PushFunctionScope();
25639 SemaRef.setFunctionHasBranchProtectedScope();
25640
25641 if (S != nullptr)
25642 SemaRef.PushDeclContext(S, DC: DRD);
25643 else
25644 SemaRef.CurContext = DRD;
25645
25646 SemaRef.PushExpressionEvaluationContext(
25647 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
25648
25649 QualType ReductionType = DRD->getType();
25650 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
25651 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
25652 // uses semantics of argument handles by value, but it should be passed by
25653 // reference. C lang does not support references, so pass all parameters as
25654 // pointers.
25655 // Create 'T omp_priv;' variable.
25656 VarDecl *OmpPrivParm =
25657 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_priv");
25658 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
25659 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
25660 // uses semantics of argument handles by value, but it should be passed by
25661 // reference. C lang does not support references, so pass all parameters as
25662 // pointers.
25663 // Create 'T omp_orig;' variable.
25664 VarDecl *OmpOrigParm =
25665 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_orig");
25666 if (S != nullptr) {
25667 SemaRef.PushOnScopeChains(D: OmpPrivParm, S);
25668 SemaRef.PushOnScopeChains(D: OmpOrigParm, S);
25669 } else {
25670 DRD->addDecl(D: OmpPrivParm);
25671 DRD->addDecl(D: OmpOrigParm);
25672 }
25673 Expr *OrigE =
25674 ::buildDeclRefExpr(S&: SemaRef, D: OmpOrigParm, Ty: ReductionType, Loc: D->getLocation());
25675 Expr *PrivE =
25676 ::buildDeclRefExpr(S&: SemaRef, D: OmpPrivParm, Ty: ReductionType, Loc: D->getLocation());
25677 DRD->setInitializerData(OrigE, PrivE);
25678 return OmpPrivParm;
25679}
25680
25681void SemaOpenMP::ActOnOpenMPDeclareReductionInitializerEnd(
25682 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
25683 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
25684
25685 // Ensure OmpPrivParm is default-constructed before the user initializer runs
25686 // (required for class types with non-trivial default constructors).
25687 if (Initializer && !DRD->getDeclContext()->isDependentContext()) {
25688 QualType ReductionType = DRD->getType();
25689 if (CXXRecordDecl *RD = ReductionType->getAsCXXRecordDecl()) {
25690 if (!RD->hasTrivialDefaultConstructor())
25691 SemaRef.ActOnUninitializedDecl(dcl: OmpPrivParm);
25692 }
25693 }
25694
25695 SemaRef.DiscardCleanupsInEvaluationContext();
25696 SemaRef.PopExpressionEvaluationContext();
25697
25698 SemaRef.PopDeclContext();
25699 SemaRef.PopFunctionScopeInfo();
25700
25701 if (Initializer != nullptr) {
25702 DRD->setInitializer(E: Initializer, IK: OMPDeclareReductionInitKind::Call);
25703 } else if (OmpPrivParm->hasInit()) {
25704 DRD->setInitializer(E: OmpPrivParm->getInit(),
25705 IK: OmpPrivParm->isDirectInit()
25706 ? OMPDeclareReductionInitKind::Direct
25707 : OMPDeclareReductionInitKind::Copy);
25708 } else {
25709 DRD->setInvalidDecl();
25710 }
25711}
25712
25713SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveEnd(
25714 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
25715 for (Decl *D : DeclReductions.get()) {
25716 if (IsValid) {
25717 if (S)
25718 SemaRef.PushOnScopeChains(D: cast<OMPDeclareReductionDecl>(Val: D), S,
25719 /*AddToContext=*/false);
25720 } else {
25721 D->setInvalidDecl();
25722 }
25723 }
25724 return DeclReductions;
25725}
25726
25727TypeResult SemaOpenMP::ActOnOpenMPDeclareMapperVarDecl(Scope *S,
25728 Declarator &D) {
25729 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
25730 QualType T = TInfo->getType();
25731 if (D.isInvalidType())
25732 return true;
25733
25734 if (getLangOpts().CPlusPlus) {
25735 // Check that there are no default arguments (C++ only).
25736 SemaRef.CheckExtraCXXDefaultArguments(D);
25737 }
25738
25739 return SemaRef.CreateParsedType(T, TInfo);
25740}
25741
25742QualType SemaOpenMP::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
25743 TypeResult ParsedType) {
25744 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
25745
25746 QualType MapperType = SemaRef.GetTypeFromParser(Ty: ParsedType.get());
25747 assert(!MapperType.isNull() && "Expect valid mapper type");
25748
25749 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
25750 // The type must be of struct, union or class type in C and C++
25751 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
25752 Diag(Loc: TyLoc, DiagID: diag::err_omp_mapper_wrong_type);
25753 return QualType();
25754 }
25755 return MapperType;
25756}
25757
25758SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareMapperDirective(
25759 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
25760 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
25761 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
25762 LookupResult Lookup(SemaRef, Name, SourceLocation(),
25763 Sema::LookupOMPMapperName,
25764 SemaRef.forRedeclarationInCurContext());
25765 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
25766 // A mapper-identifier may not be redeclared in the current scope for the
25767 // same type or for a type that is compatible according to the base language
25768 // rules.
25769 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
25770 OMPDeclareMapperDecl *PrevDMD = nullptr;
25771 bool InCompoundScope = true;
25772 if (S != nullptr) {
25773 // Find previous declaration with the same name not referenced in other
25774 // declarations.
25775 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
25776 InCompoundScope =
25777 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
25778 SemaRef.LookupName(R&: Lookup, S);
25779 SemaRef.FilterLookupForScope(R&: Lookup, Ctx: DC, S, /*ConsiderLinkage=*/false,
25780 /*AllowInlineNamespace=*/false);
25781 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
25782 LookupResult::Filter Filter = Lookup.makeFilter();
25783 while (Filter.hasNext()) {
25784 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Val: Filter.next());
25785 if (InCompoundScope) {
25786 UsedAsPrevious.try_emplace(Key: PrevDecl, Args: false);
25787 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
25788 UsedAsPrevious[D] = true;
25789 }
25790 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
25791 PrevDecl->getLocation();
25792 }
25793 Filter.done();
25794 if (InCompoundScope) {
25795 for (const auto &PrevData : UsedAsPrevious) {
25796 if (!PrevData.second) {
25797 PrevDMD = PrevData.first;
25798 break;
25799 }
25800 }
25801 }
25802 } else if (PrevDeclInScope) {
25803 auto *PrevDMDInScope = PrevDMD =
25804 cast<OMPDeclareMapperDecl>(Val: PrevDeclInScope);
25805 do {
25806 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
25807 PrevDMDInScope->getLocation();
25808 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
25809 } while (PrevDMDInScope != nullptr);
25810 }
25811 const auto I = PreviousRedeclTypes.find(Val: MapperType.getCanonicalType());
25812 bool Invalid = false;
25813 if (I != PreviousRedeclTypes.end()) {
25814 Diag(Loc: StartLoc, DiagID: diag::err_omp_declare_mapper_redefinition)
25815 << MapperType << Name;
25816 Diag(Loc: I->second, DiagID: diag::note_previous_definition);
25817 Invalid = true;
25818 }
25819 // Build expressions for implicit maps of data members with 'default'
25820 // mappers.
25821 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
25822 if (getLangOpts().OpenMP >= 50)
25823 processImplicitMapsWithDefaultMappers(S&: SemaRef, DSAStack,
25824 Clauses&: ClausesWithImplicit);
25825 auto *DMD = OMPDeclareMapperDecl::Create(C&: getASTContext(), DC, L: StartLoc, Name,
25826 T: MapperType, VarName: VN, Clauses: ClausesWithImplicit,
25827 PrevDeclInScope: PrevDMD);
25828 if (S)
25829 SemaRef.PushOnScopeChains(D: DMD, S);
25830 else
25831 DC->addDecl(D: DMD);
25832 DMD->setAccess(AS);
25833 if (Invalid)
25834 DMD->setInvalidDecl();
25835
25836 auto *VD = cast<DeclRefExpr>(Val: MapperVarRef)->getDecl();
25837 VD->setDeclContext(DMD);
25838 VD->setLexicalDeclContext(DMD);
25839 DMD->addDecl(D: VD);
25840 DMD->setMapperVarRef(MapperVarRef);
25841
25842 return DeclGroupPtrTy::make(P: DeclGroupRef(DMD));
25843}
25844
25845ExprResult SemaOpenMP::ActOnOpenMPDeclareMapperDirectiveVarDecl(
25846 Scope *S, QualType MapperType, SourceLocation StartLoc,
25847 DeclarationName VN) {
25848 TypeSourceInfo *TInfo =
25849 getASTContext().getTrivialTypeSourceInfo(T: MapperType, Loc: StartLoc);
25850 auto *VD = VarDecl::Create(
25851 C&: getASTContext(), DC: getASTContext().getTranslationUnitDecl(), StartLoc,
25852 IdLoc: StartLoc, Id: VN.getAsIdentifierInfo(), T: MapperType, TInfo, S: SC_None);
25853 if (S)
25854 SemaRef.PushOnScopeChains(D: VD, S, /*AddToContext=*/false);
25855 Expr *E = buildDeclRefExpr(S&: SemaRef, D: VD, Ty: MapperType, Loc: StartLoc);
25856 DSAStack->addDeclareMapperVarRef(Ref: E);
25857 return E;
25858}
25859
25860void SemaOpenMP::ActOnOpenMPIteratorVarDecl(VarDecl *VD) {
25861 bool IsGlobalVar =
25862 !VD->isLocalVarDecl() && VD->getDeclContext()->isTranslationUnit();
25863 if (DSAStack->getDeclareMapperVarRef()) {
25864 if (IsGlobalVar)
25865 SemaRef.Consumer.HandleTopLevelDecl(D: DeclGroupRef(VD));
25866 DSAStack->addIteratorVarDecl(VD);
25867 } else {
25868 // Currently, only declare mapper handles global-scope iterator vars.
25869 assert(!IsGlobalVar && "Only declare mapper handles TU-scope iterators.");
25870 }
25871}
25872
25873bool SemaOpenMP::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
25874 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
25875 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
25876 if (const auto *DRE = cast_or_null<DeclRefExpr>(Val: Ref)) {
25877 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
25878 return true;
25879 if (VD->isUsableInConstantExpressions(C: getASTContext()))
25880 return true;
25881 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
25882 return true;
25883 return false;
25884 }
25885 return true;
25886}
25887
25888const ValueDecl *SemaOpenMP::getOpenMPDeclareMapperVarName() const {
25889 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
25890 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
25891}
25892
25893ExprResult SemaOpenMP::ActOnOpenMPDimsModifier(OpenMPClauseKind ClauseKind,
25894 int Modifier, Expr *ModifierExpr,
25895 SourceLocation ModifierLoc,
25896 ArrayRef<Expr *> VarList,
25897 SourceLocation VarListEndLoc) {
25898 assert(ModifierExpr && "Unexpected modifier expression.");
25899
25900 if (getLangOpts().OpenMP < 61) {
25901 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_modifier_requires_version)
25902 << getOpenMPSimpleClauseTypeName(Kind: ClauseKind, Type: Modifier)
25903 << getOpenMPClauseName(C: ClauseKind) << "6.1";
25904 return ExprError();
25905 }
25906
25907 ExprResult DimsRes = VerifyPositiveIntegerConstantInClause(
25908 E: ModifierExpr, CKind: ClauseKind, /*StrictlyPositive=*/true,
25909 /*SuppressExprDiags=*/false);
25910 if (DimsRes.isInvalid())
25911 return ExprError();
25912
25913 ModifierExpr = DimsRes.get();
25914 if (ModifierExpr->isInstantiationDependent())
25915 return DimsRes;
25916
25917 uint64_t NumDims =
25918 ModifierExpr->EvaluateKnownConstInt(Ctx: getASTContext()).getExtValue();
25919 if (NumDims == VarList.size())
25920 return DimsRes;
25921
25922 Diag(Loc: VarListEndLoc, DiagID: diag::err_omp_unexpected_num_exprs)
25923 << getOpenMPClauseName(C: ClauseKind) << NumDims << VarList.size();
25924 return ExprError();
25925}
25926
25927OMPClause *SemaOpenMP::ActOnOpenMPNumTeamsClause(
25928 ArrayRef<Expr *> VarList, OpenMPNumTeamsClauseModifier Modifier,
25929 Expr *ModifierExpr, SourceLocation ModifierLoc,
25930 OpenMPNumTeamsClauseModifier ModifierExtra, Expr *,
25931 SourceLocation ModifierExtraLoc, SourceLocation StartLoc,
25932 SourceLocation LParenLoc, SourceLocation EndLoc) {
25933 if (VarList.empty())
25934 return nullptr;
25935
25936 for (Expr *ValExpr : VarList) {
25937 // OpenMP [teams Construct, Restrictions]
25938 // The num_teams expression must evaluate to a positive integer value.
25939 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_num_teams,
25940 /*StrictlyPositive=*/true))
25941 return nullptr;
25942 }
25943
25944 // OpenMP [teams Construct, Restrictions]
25945 // The lower-bound modifier cannot be specified if the dims modifier is
25946 // specified.
25947 if (Modifier != OMPC_NUMTEAMS_unknown &&
25948 ModifierExtra != OMPC_NUMTEAMS_unknown) {
25949 Diag(Loc: ModifierExtraLoc, DiagID: diag::err_omp_incompatible_modifiers)
25950 << getOpenMPSimpleClauseTypeName(Kind: llvm::omp::OMPC_num_teams,
25951 Type: ModifierExtra)
25952 << getOpenMPSimpleClauseTypeName(Kind: llvm::omp::OMPC_num_teams, Type: Modifier)
25953 << getOpenMPClauseName(C: llvm::omp::OMPC_num_teams);
25954 ModifierExtra = OMPC_NUMTEAMS_unknown;
25955 ModifierExtraLoc = SourceLocation();
25956 }
25957
25958 if (Modifier == OMPC_NUMTEAMS_dims) {
25959 ExprResult Res = ActOnOpenMPDimsModifier(
25960 ClauseKind: OMPC_num_teams, Modifier, ModifierExpr, ModifierLoc, VarList, VarListEndLoc: EndLoc);
25961 if (Res.isInvalid())
25962 return nullptr;
25963 ModifierExpr = Res.get();
25964 } else if (Modifier == OMPC_NUMTEAMS_lower_bound) {
25965 assert(ModifierExpr && "Unexpected modifier expression.");
25966
25967 if (getLangOpts().OpenMP < 51) {
25968 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_modifier_requires_version)
25969 << getOpenMPSimpleClauseTypeName(Kind: llvm::omp::OMPC_num_teams, Type: Modifier)
25970 << getOpenMPClauseName(C: llvm::omp::OMPC_num_teams) << "5.1";
25971 return nullptr;
25972 }
25973
25974 // OpenMP [teams Construct, Restrictions]
25975 // The lower-bound expression in num_teams must evaluate to a positive
25976 // integer value.
25977 if (!isNonNegativeIntegerValue(ValExpr&: ModifierExpr, SemaRef, CKind: OMPC_num_teams,
25978 /*StrictlyPositive=*/true))
25979 return nullptr;
25980
25981 // OpenMP 5.2: Validate lower-bound is less than or equal to upper-bound.
25982 Expr *LowerBound = ModifierExpr;
25983 Expr *UpperBound = VarList[0];
25984
25985 // Check if both are compile-time constants for validation.
25986 if (!LowerBound->isValueDependent() && !UpperBound->isValueDependent() &&
25987 LowerBound->isIntegerConstantExpr(Ctx: getASTContext()) &&
25988 UpperBound->isIntegerConstantExpr(Ctx: getASTContext())) {
25989
25990 // Get the actual constant values.
25991 llvm::APSInt LowerVal =
25992 LowerBound->EvaluateKnownConstInt(Ctx: getASTContext());
25993 llvm::APSInt UpperVal =
25994 UpperBound->EvaluateKnownConstInt(Ctx: getASTContext());
25995
25996 if (LowerVal > UpperVal) {
25997 Diag(Loc: LowerBound->getExprLoc(),
25998 DiagID: diag::err_omp_num_teams_lower_bound_larger)
25999 << LowerBound->getSourceRange() << UpperBound->getSourceRange();
26000 return nullptr;
26001 }
26002 }
26003 }
26004
26005 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
26006 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
26007 DKind, CKind: OMPC_num_teams, OMPVersion: getLangOpts().getOpenMPVersion());
26008 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
26009 return OMPNumTeamsClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
26010 LParenLoc, EndLoc, VL: VarList, Modifier,
26011 ModifierExpr, ModifierLoc,
26012 /*PreInit=*/nullptr);
26013
26014 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26015 SmallVector<Expr *, 3> Vars;
26016 for (Expr *ValExpr : VarList) {
26017 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
26018 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
26019 Vars.push_back(Elt: ValExpr);
26020 }
26021
26022 if (ModifierExpr) {
26023 ModifierExpr = SemaRef.MakeFullExpr(Arg: ModifierExpr).get();
26024 ModifierExpr = tryBuildCapture(SemaRef, Capture: ModifierExpr, Captures).get();
26025 }
26026
26027 Stmt *PreInit = buildPreInits(Context&: getASTContext(), Captures);
26028 return OMPNumTeamsClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
26029 LParenLoc, EndLoc, VL: Vars, Modifier,
26030 ModifierExpr, ModifierLoc, PreInit);
26031}
26032
26033OMPClause *SemaOpenMP::ActOnOpenMPThreadLimitClause(
26034 ArrayRef<Expr *> VarList, OpenMPThreadLimitClauseModifier Modifier,
26035 Expr *ModifierExpr, SourceLocation ModifierLoc, SourceLocation StartLoc,
26036 SourceLocation LParenLoc, SourceLocation EndLoc) {
26037 if (VarList.empty())
26038 return nullptr;
26039
26040 for (Expr *ValExpr : VarList) {
26041 // OpenMP [teams Constrcut, Restrictions]
26042 // The thread_limit expression must evaluate to a positive integer value.
26043 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_thread_limit,
26044 /*StrictlyPositive=*/true))
26045 return nullptr;
26046 }
26047
26048 if (Modifier == OMPC_THREADLIMIT_dims) {
26049 ExprResult Res =
26050 ActOnOpenMPDimsModifier(ClauseKind: OMPC_thread_limit, Modifier, ModifierExpr,
26051 ModifierLoc, VarList, VarListEndLoc: EndLoc);
26052 if (Res.isInvalid())
26053 return nullptr;
26054 ModifierExpr = Res.get();
26055 }
26056
26057 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
26058 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
26059 DKind, CKind: OMPC_thread_limit, OMPVersion: getLangOpts().getOpenMPVersion());
26060 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
26061 return OMPThreadLimitClause::Create(C: getASTContext(), CaptureRegion,
26062 StartLoc, LParenLoc, EndLoc, VL: VarList,
26063 Modifier, ModifierExpr, ModifierLoc,
26064 /*PreInit=*/nullptr);
26065
26066 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26067 SmallVector<Expr *, 3> Vars;
26068 for (Expr *ValExpr : VarList) {
26069 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
26070 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
26071 Vars.push_back(Elt: ValExpr);
26072 }
26073
26074 if (ModifierExpr) {
26075 ModifierExpr = SemaRef.MakeFullExpr(Arg: ModifierExpr).get();
26076 ModifierExpr = tryBuildCapture(SemaRef, Capture: ModifierExpr, Captures).get();
26077 }
26078
26079 Stmt *PreInit = buildPreInits(Context&: getASTContext(), Captures);
26080 return OMPThreadLimitClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
26081 LParenLoc, EndLoc, VL: Vars, Modifier,
26082 ModifierExpr, ModifierLoc, PreInit);
26083}
26084
26085OMPClause *SemaOpenMP::ActOnOpenMPPriorityClause(Expr *Priority,
26086 SourceLocation StartLoc,
26087 SourceLocation LParenLoc,
26088 SourceLocation EndLoc) {
26089 Expr *ValExpr = Priority;
26090 Stmt *HelperValStmt = nullptr;
26091 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
26092
26093 // OpenMP [2.9.1, task Constrcut]
26094 // The priority-value is a non-negative numerical scalar expression.
26095 if (!isNonNegativeIntegerValue(
26096 ValExpr, SemaRef, CKind: OMPC_priority,
26097 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
26098 DSAStack->getCurrentDirective(), CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
26099 return nullptr;
26100
26101 return new (getASTContext()) OMPPriorityClause(
26102 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
26103}
26104
26105OMPClause *SemaOpenMP::ActOnOpenMPGrainsizeClause(
26106 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
26107 SourceLocation StartLoc, SourceLocation LParenLoc,
26108 SourceLocation ModifierLoc, SourceLocation EndLoc) {
26109 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
26110 "Unexpected grainsize modifier in OpenMP < 51.");
26111
26112 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
26113 std::string Values = getListOfPossibleValues(K: OMPC_grainsize, /*First=*/0,
26114 Last: OMPC_GRAINSIZE_unknown);
26115 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
26116 << Values << getOpenMPClauseNameForDiag(C: OMPC_grainsize);
26117 return nullptr;
26118 }
26119
26120 Expr *ValExpr = Grainsize;
26121 Stmt *HelperValStmt = nullptr;
26122 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
26123
26124 // OpenMP [2.9.2, taskloop Constrcut]
26125 // The parameter of the grainsize clause must be a positive integer
26126 // expression.
26127 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_grainsize,
26128 /*StrictlyPositive=*/true,
26129 /*BuildCapture=*/true,
26130 DSAStack->getCurrentDirective(),
26131 CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
26132 return nullptr;
26133
26134 return new (getASTContext())
26135 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
26136 StartLoc, LParenLoc, ModifierLoc, EndLoc);
26137}
26138
26139OMPClause *SemaOpenMP::ActOnOpenMPNumTasksClause(
26140 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
26141 SourceLocation StartLoc, SourceLocation LParenLoc,
26142 SourceLocation ModifierLoc, SourceLocation EndLoc) {
26143 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
26144 "Unexpected num_tasks modifier in OpenMP < 51.");
26145
26146 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
26147 std::string Values = getListOfPossibleValues(K: OMPC_num_tasks, /*First=*/0,
26148 Last: OMPC_NUMTASKS_unknown);
26149 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
26150 << Values << getOpenMPClauseNameForDiag(C: OMPC_num_tasks);
26151 return nullptr;
26152 }
26153
26154 Expr *ValExpr = NumTasks;
26155 Stmt *HelperValStmt = nullptr;
26156 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
26157
26158 // OpenMP [2.9.2, taskloop Constrcut]
26159 // The parameter of the num_tasks clause must be a positive integer
26160 // expression.
26161 if (!isNonNegativeIntegerValue(
26162 ValExpr, SemaRef, CKind: OMPC_num_tasks,
26163 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
26164 DSAStack->getCurrentDirective(), CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
26165 return nullptr;
26166
26167 return new (getASTContext())
26168 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
26169 StartLoc, LParenLoc, ModifierLoc, EndLoc);
26170}
26171
26172OMPClause *SemaOpenMP::ActOnOpenMPHintClause(Expr *Hint,
26173 SourceLocation StartLoc,
26174 SourceLocation LParenLoc,
26175 SourceLocation EndLoc) {
26176 // OpenMP [2.13.2, critical construct, Description]
26177 // ... where hint-expression is an integer constant expression that evaluates
26178 // to a valid lock hint.
26179 ExprResult HintExpr =
26180 VerifyPositiveIntegerConstantInClause(E: Hint, CKind: OMPC_hint, StrictlyPositive: false);
26181 if (HintExpr.isInvalid())
26182 return nullptr;
26183 return new (getASTContext())
26184 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
26185}
26186
26187/// Tries to find omp_event_handle_t type.
26188static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
26189 DSAStackTy *Stack) {
26190 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
26191 if (!OMPEventHandleT.isNull())
26192 return true;
26193 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_event_handle_t");
26194 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
26195 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
26196 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
26197 return false;
26198 }
26199 Stack->setOMPEventHandleT(PT.get());
26200 return true;
26201}
26202
26203OMPClause *SemaOpenMP::ActOnOpenMPDetachClause(Expr *Evt,
26204 SourceLocation StartLoc,
26205 SourceLocation LParenLoc,
26206 SourceLocation EndLoc) {
26207 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
26208 !Evt->isInstantiationDependent() &&
26209 !Evt->containsUnexpandedParameterPack()) {
26210 if (!findOMPEventHandleT(S&: SemaRef, Loc: Evt->getExprLoc(), DSAStack))
26211 return nullptr;
26212 // OpenMP 5.0, 2.10.1 task Construct.
26213 // event-handle is a variable of the omp_event_handle_t type.
26214 auto *Ref = dyn_cast<DeclRefExpr>(Val: Evt->IgnoreParenImpCasts());
26215 if (!Ref) {
26216 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
26217 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
26218 return nullptr;
26219 }
26220 auto *VD = dyn_cast_or_null<VarDecl>(Val: Ref->getDecl());
26221 if (!VD) {
26222 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
26223 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
26224 return nullptr;
26225 }
26226 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
26227 T2: VD->getType()) ||
26228 VD->getType().isConstant(Ctx: getASTContext())) {
26229 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
26230 << "omp_event_handle_t" << 1 << VD->getType()
26231 << Evt->getSourceRange();
26232 return nullptr;
26233 }
26234 // OpenMP 5.0, 2.10.1 task Construct
26235 // [detach clause]... The event-handle will be considered as if it was
26236 // specified on a firstprivate clause.
26237 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
26238 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
26239 DVar.RefExpr) {
26240 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
26241 << getOpenMPClauseNameForDiag(C: DVar.CKind)
26242 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
26243 reportOriginalDsa(SemaRef, DSAStack, D: VD, DVar);
26244 return nullptr;
26245 }
26246 }
26247
26248 return new (getASTContext())
26249 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
26250}
26251
26252OMPClause *SemaOpenMP::ActOnOpenMPDistScheduleClause(
26253 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
26254 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
26255 SourceLocation EndLoc) {
26256 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
26257 std::string Values;
26258 Values += "'";
26259 Values += getOpenMPSimpleClauseTypeName(Kind: OMPC_dist_schedule, Type: 0);
26260 Values += "'";
26261 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
26262 << Values << getOpenMPClauseNameForDiag(C: OMPC_dist_schedule);
26263 return nullptr;
26264 }
26265 Expr *ValExpr = ChunkSize;
26266 Stmt *HelperValStmt = nullptr;
26267 if (ChunkSize) {
26268 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
26269 !ChunkSize->isInstantiationDependent() &&
26270 !ChunkSize->containsUnexpandedParameterPack()) {
26271 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
26272 ExprResult Val =
26273 PerformOpenMPImplicitIntegerConversion(Loc: ChunkSizeLoc, Op: ChunkSize);
26274 if (Val.isInvalid())
26275 return nullptr;
26276
26277 ValExpr = Val.get();
26278
26279 // OpenMP [2.7.1, Restrictions]
26280 // chunk_size must be a loop invariant integer expression with a positive
26281 // value.
26282 if (std::optional<llvm::APSInt> Result =
26283 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
26284 if (Result->isSigned() && !Result->isStrictlyPositive()) {
26285 Diag(Loc: ChunkSizeLoc, DiagID: diag::err_omp_negative_expression_in_clause)
26286 << "dist_schedule" << /*strictly positive*/ 1
26287 << ChunkSize->getSourceRange();
26288 return nullptr;
26289 }
26290 } else if (getOpenMPCaptureRegionForClause(
26291 DSAStack->getCurrentDirective(), CKind: OMPC_dist_schedule,
26292 OMPVersion: getLangOpts().getOpenMPVersion()) != OMPD_unknown &&
26293 !SemaRef.CurContext->isDependentContext()) {
26294 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
26295 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26296 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
26297 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
26298 }
26299 }
26300 }
26301
26302 return new (getASTContext())
26303 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
26304 Kind, ValExpr, HelperValStmt);
26305}
26306
26307OMPClause *SemaOpenMP::ActOnOpenMPDefaultmapClause(
26308 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
26309 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
26310 SourceLocation KindLoc, SourceLocation EndLoc) {
26311 if (getLangOpts().OpenMP < 50) {
26312 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
26313 Kind != OMPC_DEFAULTMAP_scalar) {
26314 std::string Value;
26315 SourceLocation Loc;
26316 Value += "'";
26317 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
26318 Value += getOpenMPSimpleClauseTypeName(Kind: OMPC_defaultmap,
26319 Type: OMPC_DEFAULTMAP_MODIFIER_tofrom);
26320 Loc = MLoc;
26321 } else {
26322 Value += getOpenMPSimpleClauseTypeName(Kind: OMPC_defaultmap,
26323 Type: OMPC_DEFAULTMAP_scalar);
26324 Loc = KindLoc;
26325 }
26326 Value += "'";
26327 Diag(Loc, DiagID: diag::err_omp_unexpected_clause_value)
26328 << Value << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
26329 return nullptr;
26330 }
26331 } else {
26332 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
26333 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
26334 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
26335 if (!isDefaultmapKind || !isDefaultmapModifier) {
26336 StringRef KindValue = getLangOpts().OpenMP < 52
26337 ? "'scalar', 'aggregate', 'pointer'"
26338 : "'scalar', 'aggregate', 'pointer', 'all'";
26339 if (getLangOpts().OpenMP == 50) {
26340 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
26341 "'firstprivate', 'none', 'default'";
26342 if (!isDefaultmapKind && isDefaultmapModifier) {
26343 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
26344 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
26345 } else if (isDefaultmapKind && !isDefaultmapModifier) {
26346 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
26347 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
26348 } else {
26349 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
26350 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
26351 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
26352 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
26353 }
26354 } else {
26355 StringRef ModifierValue =
26356 getLangOpts().OpenMP < 60
26357 ? "'alloc', 'from', 'to', 'tofrom', "
26358 "'firstprivate', 'none', 'default', 'present'"
26359 : "'storage', 'from', 'to', 'tofrom', "
26360 "'firstprivate', 'private', 'none', 'default', 'present'";
26361 if (!isDefaultmapKind && isDefaultmapModifier) {
26362 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
26363 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
26364 } else if (isDefaultmapKind && !isDefaultmapModifier) {
26365 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
26366 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
26367 } else {
26368 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
26369 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
26370 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
26371 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
26372 }
26373 }
26374 return nullptr;
26375 }
26376
26377 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
26378 // At most one defaultmap clause for each category can appear on the
26379 // directive.
26380 if (DSAStack->checkDefaultmapCategory(VariableCategory: Kind)) {
26381 Diag(Loc: StartLoc, DiagID: diag::err_omp_one_defaultmap_each_category);
26382 return nullptr;
26383 }
26384 }
26385 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
26386 // Variable category is not specified - mark all categories.
26387 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_aggregate, Loc: StartLoc);
26388 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_scalar, Loc: StartLoc);
26389 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_pointer, Loc: StartLoc);
26390 } else {
26391 DSAStack->setDefaultDMAAttr(M, Kind, Loc: StartLoc);
26392 }
26393
26394 return new (getASTContext())
26395 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
26396}
26397
26398bool SemaOpenMP::ActOnStartOpenMPDeclareTargetContext(
26399 DeclareTargetContextInfo &DTCI) {
26400 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
26401 if (!CurLexicalContext->isFileContext() &&
26402 !CurLexicalContext->isExternCContext() &&
26403 !CurLexicalContext->isExternCXXContext() &&
26404 !isa<CXXRecordDecl>(Val: CurLexicalContext) &&
26405 !isa<ClassTemplateDecl>(Val: CurLexicalContext) &&
26406 !isa<ClassTemplatePartialSpecializationDecl>(Val: CurLexicalContext) &&
26407 !isa<ClassTemplateSpecializationDecl>(Val: CurLexicalContext)) {
26408 Diag(Loc: DTCI.Loc, DiagID: diag::err_omp_region_not_file_context);
26409 return false;
26410 }
26411
26412 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
26413 if (getLangOpts().HIP)
26414 Diag(Loc: DTCI.Loc, DiagID: diag::warn_hip_omp_target_directives);
26415
26416 DeclareTargetNesting.push_back(Elt: DTCI);
26417 return true;
26418}
26419
26420const SemaOpenMP::DeclareTargetContextInfo
26421SemaOpenMP::ActOnOpenMPEndDeclareTargetDirective() {
26422 assert(!DeclareTargetNesting.empty() &&
26423 "check isInOpenMPDeclareTargetContext() first!");
26424 return DeclareTargetNesting.pop_back_val();
26425}
26426
26427void SemaOpenMP::ActOnFinishedOpenMPDeclareTargetContext(
26428 DeclareTargetContextInfo &DTCI) {
26429 for (auto &It : DTCI.ExplicitlyMapped)
26430 ActOnOpenMPDeclareTargetName(ND: It.first, Loc: It.second.Loc, MT: It.second.MT, DTCI);
26431}
26432
26433void SemaOpenMP::DiagnoseUnterminatedOpenMPDeclareTarget() {
26434 if (DeclareTargetNesting.empty())
26435 return;
26436 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
26437 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
26438 Diag(Loc: DTCI.Loc, DiagID: diag::warn_omp_unterminated_declare_target)
26439 << getOpenMPDirectiveName(D: DTCI.Kind, V: OMPVersion);
26440}
26441
26442NamedDecl *SemaOpenMP::lookupOpenMPDeclareTargetName(
26443 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
26444 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
26445 SemaRef.LookupParsedName(R&: Lookup, S: CurScope, SS: &ScopeSpec,
26446 /*ObjectType=*/QualType(),
26447 /*AllowBuiltinCreation=*/true);
26448
26449 if (Lookup.isAmbiguous())
26450 return nullptr;
26451 Lookup.suppressDiagnostics();
26452
26453 if (!Lookup.isSingleResult()) {
26454 VarOrFuncDeclFilterCCC CCC(SemaRef);
26455 if (TypoCorrection Corrected =
26456 SemaRef.CorrectTypo(Typo: Id, LookupKind: Sema::LookupOrdinaryName, S: CurScope, SS: nullptr,
26457 CCC, Mode: CorrectTypoKind::ErrorRecovery)) {
26458 SemaRef.diagnoseTypo(Correction: Corrected,
26459 TypoDiag: SemaRef.PDiag(DiagID: diag::err_undeclared_var_use_suggest)
26460 << Id.getName());
26461 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: Corrected.getCorrectionDecl());
26462 return nullptr;
26463 }
26464
26465 Diag(Loc: Id.getLoc(), DiagID: diag::err_undeclared_var_use) << Id.getName();
26466 return nullptr;
26467 }
26468
26469 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
26470 if (!isa<VarDecl>(Val: ND) && !isa<FunctionDecl>(Val: ND) &&
26471 !isa<FunctionTemplateDecl>(Val: ND)) {
26472 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_invalid_target_decl) << Id.getName();
26473 return nullptr;
26474 }
26475 return ND;
26476}
26477
26478void SemaOpenMP::ActOnOpenMPDeclareTargetName(
26479 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
26480 DeclareTargetContextInfo &DTCI) {
26481 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
26482 isa<FunctionTemplateDecl>(ND)) &&
26483 "Expected variable, function or function template.");
26484
26485 if (auto *VD = dyn_cast<VarDecl>(Val: ND)) {
26486 // Only global variables can be marked as declare target.
26487 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
26488 !VD->isStaticDataMember()) {
26489 Diag(Loc, DiagID: diag::err_omp_declare_target_has_local_vars)
26490 << VD->getNameAsString();
26491 return;
26492 }
26493 }
26494 // Diagnose marking after use as it may lead to incorrect diagnosis and
26495 // codegen.
26496 if (getLangOpts().OpenMP >= 50 &&
26497 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
26498 Diag(Loc, DiagID: diag::warn_omp_declare_target_after_first_use);
26499
26500 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
26501 if (getLangOpts().HIP)
26502 Diag(Loc, DiagID: diag::warn_hip_omp_target_directives);
26503
26504 // 'local' is incompatible with 'device_type(host)' because 'local'
26505 // variables exist only on the device.
26506 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
26507 DTCI.DT == OMPDeclareTargetDeclAttr::DT_Host) {
26508 Diag(Loc, DiagID: diag::err_omp_declare_target_local_host_only);
26509 return;
26510 }
26511
26512 // Explicit declare target lists have precedence.
26513 const unsigned Level = -1;
26514
26515 auto *VD = cast<ValueDecl>(Val: ND);
26516 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
26517 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
26518 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
26519 (*ActiveAttr)->getLevel() == Level) {
26520 Diag(Loc, DiagID: diag::err_omp_device_type_mismatch)
26521 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(Val: DTCI.DT)
26522 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
26523 Val: (*ActiveAttr)->getDevType());
26524 return;
26525 }
26526 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
26527 (*ActiveAttr)->getLevel() == Level) {
26528 Diag(Loc, DiagID: diag::err_omp_declare_target_var_in_both_clauses)
26529 << ND
26530 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(
26531 Val: (*ActiveAttr)->getMapType())
26532 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(Val: MT);
26533 return;
26534 }
26535
26536 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
26537 return;
26538
26539 Expr *IndirectE = nullptr;
26540 bool IsIndirect = false;
26541 if (DTCI.Indirect) {
26542 IndirectE = *DTCI.Indirect;
26543 if (!IndirectE)
26544 IsIndirect = true;
26545 }
26546 // FIXME: 'local' with 'device_type(nohost)' is not yet fully supported
26547 // in codegen. Treat as 'device_type(any)' for now. The variable will
26548 // exist on both host and device, but the host copy is unused.
26549 auto DT = DTCI.DT;
26550 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
26551 DT == OMPDeclareTargetDeclAttr::DT_NoHost) {
26552 Diag(Loc, DiagID: diag::warn_omp_declare_target_local_nohost);
26553 DT = OMPDeclareTargetDeclAttr::DT_Any;
26554 }
26555
26556 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
26557 Ctx&: getASTContext(), MapType: MT, DevType: DT, IndirectExpr: IndirectE, Indirect: IsIndirect, Level,
26558 Range: SourceRange(Loc, Loc));
26559 ND->addAttr(A);
26560 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
26561 ML->DeclarationMarkedOpenMPDeclareTarget(D: ND, Attr: A);
26562 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: ND, IdLoc: Loc);
26563 if (auto *VD = dyn_cast<VarDecl>(Val: ND);
26564 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
26565 VD->hasGlobalStorage())
26566 ActOnOpenMPDeclareTargetInitializer(D: ND);
26567}
26568
26569static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
26570 Sema &SemaRef, Decl *D) {
26571 if (!D || !isa<VarDecl>(Val: D))
26572 return;
26573 auto *VD = cast<VarDecl>(Val: D);
26574 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
26575 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
26576 if (SemaRef.LangOpts.OpenMP >= 50 &&
26577 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
26578 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
26579 VD->hasGlobalStorage()) {
26580 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
26581 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter &&
26582 *MapTy != OMPDeclareTargetDeclAttr::MT_Local)) {
26583 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
26584 // If a lambda declaration and definition appears between a
26585 // declare target directive and the matching end declare target
26586 // directive, all variables that are captured by the lambda
26587 // expression must also appear in a to clause.
26588 SemaRef.Diag(Loc: VD->getLocation(),
26589 DiagID: diag::err_omp_lambda_capture_in_declare_target_not_to);
26590 SemaRef.Diag(Loc: SL, DiagID: diag::note_var_explicitly_captured_here)
26591 << VD << 0 << SR;
26592 return;
26593 }
26594 }
26595 if (MapTy)
26596 return;
26597 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::warn_omp_not_in_target_context);
26598 SemaRef.Diag(Loc: SL, DiagID: diag::note_used_here) << SR;
26599}
26600
26601static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
26602 Sema &SemaRef, DSAStackTy *Stack,
26603 ValueDecl *VD) {
26604 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
26605 checkTypeMappable(SL, SR, SemaRef, Stack, QTy: VD->getType(),
26606 /*FullCheck=*/false);
26607}
26608
26609void SemaOpenMP::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
26610 SourceLocation IdLoc) {
26611 if (!D || D->isInvalidDecl())
26612 return;
26613 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
26614 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
26615 if (auto *VD = dyn_cast<VarDecl>(Val: D)) {
26616 // Only global variables can be marked as declare target.
26617 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
26618 !VD->isStaticDataMember())
26619 return;
26620 // 2.10.6: threadprivate variable cannot appear in a declare target
26621 // directive.
26622 if (DSAStack->isThreadPrivate(D: VD)) {
26623 Diag(Loc: SL, DiagID: diag::err_omp_threadprivate_in_target);
26624 reportOriginalDsa(SemaRef, DSAStack, D: VD, DSAStack->getTopDSA(D: VD, FromParent: false));
26625 return;
26626 }
26627 }
26628 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: D))
26629 D = FTD->getTemplatedDecl();
26630 if (auto *FD = dyn_cast<FunctionDecl>(Val: D)) {
26631 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
26632 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD: FD);
26633 if (IdLoc.isValid() && Res &&
26634 (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
26635 *Res == OMPDeclareTargetDeclAttr::MT_Local)) {
26636 Diag(Loc: IdLoc, DiagID: diag::err_omp_function_in_target_clause_list)
26637 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(Val: *Res);
26638 Diag(Loc: FD->getLocation(), DiagID: diag::note_defined_here) << FD;
26639 return;
26640 }
26641 }
26642 if (auto *VD = dyn_cast<ValueDecl>(Val: D)) {
26643 // Problem if any with var declared with incomplete type will be reported
26644 // as normal, so no need to check it here.
26645 if ((E || !VD->getType()->isIncompleteType()) &&
26646 !checkValueDeclInTarget(SL, SR, SemaRef, DSAStack, VD))
26647 return;
26648 if (!E && isInOpenMPDeclareTargetContext()) {
26649 // Checking declaration inside declare target region.
26650 if (isa<VarDecl>(Val: D) || isa<FunctionDecl>(Val: D) ||
26651 isa<FunctionTemplateDecl>(Val: D)) {
26652 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
26653 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
26654 unsigned Level = DeclareTargetNesting.size();
26655 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
26656 return;
26657 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
26658 Expr *IndirectE = nullptr;
26659 bool IsIndirect = false;
26660 if (DTCI.Indirect) {
26661 IndirectE = *DTCI.Indirect;
26662 if (!IndirectE)
26663 IsIndirect = true;
26664 }
26665 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
26666 Ctx&: getASTContext(),
26667 MapType: getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
26668 : OMPDeclareTargetDeclAttr::MT_To,
26669 DevType: DTCI.DT, IndirectExpr: IndirectE, Indirect: IsIndirect, Level,
26670 Range: SourceRange(DTCI.Loc, DTCI.Loc));
26671 D->addAttr(A);
26672 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
26673 ML->DeclarationMarkedOpenMPDeclareTarget(D, Attr: A);
26674 }
26675 return;
26676 }
26677 }
26678 if (!E)
26679 return;
26680 checkDeclInTargetContext(SL: E->getExprLoc(), SR: E->getSourceRange(), SemaRef, D);
26681}
26682
26683/// This class visits every VarDecl that the initializer references and adds
26684/// OMPDeclareTargetDeclAttr to each of them.
26685class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
26686 SmallVector<VarDecl *> DeclVector;
26687 Attr *A;
26688
26689public:
26690 /// A StmtVisitor class function that visits all DeclRefExpr and adds
26691 /// OMPDeclareTargetDeclAttr to them.
26692 void VisitDeclRefExpr(DeclRefExpr *Node) {
26693 if (auto *VD = dyn_cast<VarDecl>(Val: Node->getDecl())) {
26694 VD->addAttr(A);
26695 DeclVector.push_back(Elt: VD);
26696 }
26697 }
26698 /// A function that iterates across each of the Expr's children.
26699 void VisitExpr(Expr *Ex) {
26700 for (auto *Child : Ex->children()) {
26701 Visit(S: Child);
26702 }
26703 }
26704 /// A function that keeps a record of all the Decls that are variables, has
26705 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
26706 /// each Decl one at a time and use the inherited 'visit' functions to look
26707 /// for DeclRefExpr.
26708 void declareTargetInitializer(Decl *TD) {
26709 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
26710 DeclVector.push_back(Elt: cast<VarDecl>(Val: TD));
26711 llvm::SmallDenseSet<Decl *> Visited;
26712 while (!DeclVector.empty()) {
26713 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
26714 if (!Visited.insert(V: TargetVarDecl).second)
26715 continue;
26716
26717 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
26718 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
26719 if (Expr *Ex = TargetVarDecl->getInit())
26720 Visit(S: Ex);
26721 }
26722 }
26723 }
26724};
26725
26726/// Adding OMPDeclareTargetDeclAttr to variables with static storage
26727/// duration that are referenced in the initializer expression list of
26728/// variables with static storage duration in declare target directive.
26729void SemaOpenMP::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) {
26730 GlobalDeclRefChecker Checker;
26731 if (isa<VarDecl>(Val: TargetDecl))
26732 Checker.declareTargetInitializer(TD: TargetDecl);
26733}
26734
26735OMPClause *SemaOpenMP::ActOnOpenMPToClause(
26736 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
26737 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
26738 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
26739 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
26740 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
26741 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
26742 OMPC_MOTION_MODIFIER_unknown,
26743 OMPC_MOTION_MODIFIER_unknown};
26744 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
26745
26746 // Process motion-modifiers, flag errors for duplicate modifiers.
26747 unsigned Count = 0;
26748 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
26749 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
26750 llvm::is_contained(Range&: Modifiers, Element: MotionModifiers[I])) {
26751 Diag(Loc: MotionModifiersLoc[I], DiagID: diag::err_omp_duplicate_motion_modifier);
26752 continue;
26753 }
26754 assert(Count < NumberOfOMPMotionModifiers &&
26755 "Modifiers exceed the allowed number of motion modifiers");
26756 Modifiers[Count] = MotionModifiers[I];
26757 ModifiersLoc[Count] = MotionModifiersLoc[I];
26758 ++Count;
26759 }
26760
26761 MappableVarListInfo MVLI(VarList);
26762 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_to, MVLI, StartLoc: Locs.StartLoc,
26763 MapperIdScopeSpec, MapperId, UnresolvedMappers);
26764 if (MVLI.ProcessedVarList.empty())
26765 return nullptr;
26766 if (IteratorExpr)
26767 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: IteratorExpr))
26768 if (auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
26769 DSAStack->addIteratorVarDecl(VD);
26770 return OMPToClause::Create(
26771 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
26772 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, IteratorModifier: IteratorExpr, MotionModifiers: Modifiers,
26773 MotionModifiersLoc: ModifiersLoc, UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()),
26774 MapperId);
26775}
26776
26777OMPClause *SemaOpenMP::ActOnOpenMPFromClause(
26778 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
26779 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
26780 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
26781 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
26782 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
26783 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
26784 OMPC_MOTION_MODIFIER_unknown,
26785 OMPC_MOTION_MODIFIER_unknown};
26786 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
26787
26788 // Process motion-modifiers, flag errors for duplicate modifiers.
26789 unsigned Count = 0;
26790 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
26791 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
26792 llvm::is_contained(Range&: Modifiers, Element: MotionModifiers[I])) {
26793 Diag(Loc: MotionModifiersLoc[I], DiagID: diag::err_omp_duplicate_motion_modifier);
26794 continue;
26795 }
26796 assert(Count < NumberOfOMPMotionModifiers &&
26797 "Modifiers exceed the allowed number of motion modifiers");
26798 Modifiers[Count] = MotionModifiers[I];
26799 ModifiersLoc[Count] = MotionModifiersLoc[I];
26800 ++Count;
26801 }
26802
26803 MappableVarListInfo MVLI(VarList);
26804 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_from, MVLI, StartLoc: Locs.StartLoc,
26805 MapperIdScopeSpec, MapperId, UnresolvedMappers);
26806 if (MVLI.ProcessedVarList.empty())
26807 return nullptr;
26808 if (IteratorExpr)
26809 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: IteratorExpr))
26810 if (auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
26811 DSAStack->addIteratorVarDecl(VD);
26812 return OMPFromClause::Create(
26813 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
26814 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, IteratorExpr, MotionModifiers: Modifiers,
26815 MotionModifiersLoc: ModifiersLoc, UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()),
26816 MapperId);
26817}
26818
26819OMPClause *SemaOpenMP::ActOnOpenMPUseDevicePtrClause(
26820 ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs,
26821 OpenMPUseDevicePtrFallbackModifier FallbackModifier,
26822 SourceLocation FallbackModifierLoc) {
26823 MappableVarListInfo MVLI(VarList);
26824 SmallVector<Expr *, 8> PrivateCopies;
26825 SmallVector<Expr *, 8> Inits;
26826
26827 for (Expr *RefExpr : VarList) {
26828 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
26829 SourceLocation ELoc;
26830 SourceRange ERange;
26831 Expr *SimpleRefExpr = RefExpr;
26832 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
26833 if (Res.second) {
26834 // It will be analyzed later.
26835 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
26836 PrivateCopies.push_back(Elt: nullptr);
26837 Inits.push_back(Elt: nullptr);
26838 }
26839 ValueDecl *D = Res.first;
26840 if (!D)
26841 continue;
26842
26843 QualType Type = D->getType();
26844 Type = Type.getNonReferenceType().getUnqualifiedType();
26845
26846 auto *VD = dyn_cast<VarDecl>(Val: D);
26847
26848 // Item should be a pointer or reference to pointer.
26849 if (!Type->isPointerType()) {
26850 Diag(Loc: ELoc, DiagID: diag::err_omp_usedeviceptr_not_a_pointer)
26851 << 0 << RefExpr->getSourceRange();
26852 continue;
26853 }
26854
26855 // Build the private variable and the expression that refers to it.
26856 auto VDPrivate =
26857 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
26858 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
26859 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
26860 if (VDPrivate->isInvalidDecl())
26861 continue;
26862
26863 SemaRef.CurContext->addDecl(D: VDPrivate);
26864 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
26865 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(), Loc: ELoc);
26866
26867 // Add temporary variable to initialize the private copy of the pointer.
26868 VarDecl *VDInit =
26869 buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type, Name: ".devptr.temp");
26870 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
26871 S&: SemaRef, D: VDInit, Ty: RefExpr->getType(), Loc: RefExpr->getExprLoc());
26872 SemaRef.AddInitializerToDecl(
26873 dcl: VDPrivate, init: SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get(),
26874 /*DirectInit=*/false);
26875
26876 // If required, build a capture to implement the privatization initialized
26877 // with the current list item value.
26878 DeclRefExpr *Ref = nullptr;
26879 if (!VD)
26880 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
26881 MVLI.ProcessedVarList.push_back(Elt: VD ? RefExpr->IgnoreParens() : Ref);
26882 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
26883 Inits.push_back(Elt: VDInitRefExpr);
26884
26885 // We need to add a data sharing attribute for this variable to make sure it
26886 // is correctly captured. A variable that shows up in a use_device_ptr has
26887 // similar properties of a first private variable.
26888 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
26889
26890 // Create a mappable component for the list item. List items in this clause
26891 // only need a component.
26892 MVLI.VarBaseDeclarations.push_back(Elt: D);
26893 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
26894 MVLI.VarComponents.back().emplace_back(Args&: SimpleRefExpr, Args&: D,
26895 /*IsNonContiguous=*/Args: false);
26896 }
26897
26898 if (MVLI.ProcessedVarList.empty())
26899 return nullptr;
26900
26901 return OMPUseDevicePtrClause::Create(
26902 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, PrivateVars: PrivateCopies, Inits,
26903 Declarations: MVLI.VarBaseDeclarations, ComponentLists: MVLI.VarComponents, FallbackModifier,
26904 FallbackModifierLoc);
26905}
26906
26907OMPClause *
26908SemaOpenMP::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
26909 const OMPVarListLocTy &Locs) {
26910 MappableVarListInfo MVLI(VarList);
26911
26912 for (Expr *RefExpr : VarList) {
26913 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
26914 SourceLocation ELoc;
26915 SourceRange ERange;
26916 Expr *SimpleRefExpr = RefExpr;
26917 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
26918 /*AllowArraySection=*/true,
26919 /*AllowAssumedSizeArray=*/true);
26920 if (Res.second) {
26921 // It will be analyzed later.
26922 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
26923 }
26924 ValueDecl *D = Res.first;
26925 if (!D)
26926 continue;
26927 auto *VD = dyn_cast<VarDecl>(Val: D);
26928
26929 // If required, build a capture to implement the privatization initialized
26930 // with the current list item value.
26931 DeclRefExpr *Ref = nullptr;
26932 if (!VD)
26933 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
26934 MVLI.ProcessedVarList.push_back(Elt: VD ? RefExpr->IgnoreParens() : Ref);
26935
26936 // We need to add a data sharing attribute for this variable to make sure it
26937 // is correctly captured. A variable that shows up in a use_device_addr has
26938 // similar properties of a first private variable.
26939 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
26940
26941 // Use the map-like approach to fully populate VarComponents
26942 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
26943
26944 const Expr *BE = checkMapClauseExpressionBase(
26945 SemaRef, E: RefExpr, CurComponents, CKind: OMPC_use_device_addr,
26946 DSAStack->getCurrentDirective(),
26947 /*NoDiagnose=*/false);
26948
26949 if (!BE)
26950 continue;
26951
26952 assert(!CurComponents.empty() &&
26953 "use_device_addr clause expression with no components!");
26954
26955 // OpenMP use_device_addr: If a list item is an array section, the array
26956 // base must be a base language identifier. We caught the cases where
26957 // the array-section has a base-variable in getPrivateItem. e.g.
26958 // struct S {
26959 // int a[10];
26960 // }; S s1;
26961 // ... use_device_addr(s1.a[0]) // not ok, caught already
26962 //
26963 // But we still neeed to verify that the base-pointer is also a
26964 // base-language identifier, and catch cases like:
26965 // int *pa[10]; *p;
26966 // ... use_device_addr(pa[1][2]) // not ok, base-pointer is pa[1]
26967 // ... use_device_addr(p[1]) // ok
26968 // ... use_device_addr(this->p[1]) // ok
26969 auto AttachPtrResult = OMPClauseMappableExprCommon::findAttachPtrExpr(
26970 Components: CurComponents, DSAStack->getCurrentDirective());
26971 const Expr *AttachPtrExpr = AttachPtrResult.first;
26972
26973 if (AttachPtrExpr) {
26974 const Expr *BaseExpr = AttachPtrExpr->IgnoreParenImpCasts();
26975 bool IsValidBase = false;
26976
26977 if (isa<DeclRefExpr>(Val: BaseExpr))
26978 IsValidBase = true;
26979 else if (const auto *ME = dyn_cast<MemberExpr>(Val: BaseExpr);
26980 ME && isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
26981 IsValidBase = true;
26982
26983 if (!IsValidBase) {
26984 SemaRef.Diag(Loc: ELoc,
26985 DiagID: diag::err_omp_expected_base_pointer_var_name_member_expr)
26986 << (SemaRef.getCurrentThisType().isNull() ? 0 : 1)
26987 << AttachPtrExpr->getSourceRange();
26988 continue;
26989 }
26990 }
26991
26992 // Get the declaration from the components
26993 ValueDecl *CurDeclaration = CurComponents.back().getAssociatedDeclaration();
26994 assert((isa<CXXThisExpr>(BE) || CurDeclaration) &&
26995 "Unexpected null decl for use_device_addr clause.");
26996
26997 MVLI.VarBaseDeclarations.push_back(Elt: CurDeclaration);
26998 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
26999 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
27000 in_end: CurComponents.end());
27001 }
27002
27003 if (MVLI.ProcessedVarList.empty())
27004 return nullptr;
27005
27006 return OMPUseDeviceAddrClause::Create(
27007 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
27008 ComponentLists: MVLI.VarComponents);
27009}
27010
27011OMPClause *
27012SemaOpenMP::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
27013 const OMPVarListLocTy &Locs) {
27014 MappableVarListInfo MVLI(VarList);
27015 for (Expr *RefExpr : VarList) {
27016 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
27017 SourceLocation ELoc;
27018 SourceRange ERange;
27019 Expr *SimpleRefExpr = RefExpr;
27020 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
27021 if (Res.second) {
27022 // It will be analyzed later.
27023 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
27024 }
27025 ValueDecl *D = Res.first;
27026 if (!D)
27027 continue;
27028
27029 QualType Type = D->getType();
27030 // item should be a pointer or array or reference to pointer or array
27031 if (!Type.getNonReferenceType()->isPointerType() &&
27032 !Type.getNonReferenceType()->isArrayType()) {
27033 Diag(Loc: ELoc, DiagID: diag::err_omp_argument_type_isdeviceptr)
27034 << 0 << RefExpr->getSourceRange();
27035 continue;
27036 }
27037
27038 // Check if the declaration in the clause does not show up in any data
27039 // sharing attribute.
27040 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
27041 if (isOpenMPPrivate(Kind: DVar.CKind)) {
27042 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
27043 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
27044 << getOpenMPClauseNameForDiag(C: DVar.CKind)
27045 << getOpenMPClauseNameForDiag(C: OMPC_is_device_ptr)
27046 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
27047 V: OMPVersion);
27048 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
27049 continue;
27050 }
27051
27052 const Expr *ConflictExpr;
27053 if (DSAStack->checkMappableExprComponentListsForDecl(
27054 VD: D, /*CurrentRegionOnly=*/true,
27055 Check: [&ConflictExpr](
27056 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
27057 OpenMPClauseKind) -> bool {
27058 ConflictExpr = R.front().getAssociatedExpression();
27059 return true;
27060 })) {
27061 Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
27062 Diag(Loc: ConflictExpr->getExprLoc(), DiagID: diag::note_used_here)
27063 << ConflictExpr->getSourceRange();
27064 continue;
27065 }
27066
27067 // Store the components in the stack so that they can be used to check
27068 // against other clauses later on.
27069 OMPClauseMappableExprCommon::MappableComponent MC(
27070 SimpleRefExpr, D, /*IsNonContiguous=*/false);
27071 DSAStack->addMappableExpressionComponents(
27072 VD: D, Components: MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
27073
27074 // Record the expression we've just processed.
27075 MVLI.ProcessedVarList.push_back(Elt: SimpleRefExpr);
27076
27077 // Create a mappable component for the list item. List items in this clause
27078 // only need a component. We use a null declaration to signal fields in
27079 // 'this'.
27080 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
27081 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
27082 "Unexpected device pointer expression!");
27083 MVLI.VarBaseDeclarations.push_back(
27084 Elt: isa<DeclRefExpr>(Val: SimpleRefExpr) ? D : nullptr);
27085 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
27086 MVLI.VarComponents.back().push_back(Elt: MC);
27087 }
27088
27089 if (MVLI.ProcessedVarList.empty())
27090 return nullptr;
27091
27092 return OMPIsDevicePtrClause::Create(
27093 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
27094 ComponentLists: MVLI.VarComponents);
27095}
27096
27097OMPClause *
27098SemaOpenMP::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
27099 const OMPVarListLocTy &Locs) {
27100 MappableVarListInfo MVLI(VarList);
27101 for (Expr *RefExpr : VarList) {
27102 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
27103 SourceLocation ELoc;
27104 SourceRange ERange;
27105 Expr *SimpleRefExpr = RefExpr;
27106 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
27107 /*AllowArraySection=*/true);
27108 if (Res.second) {
27109 // It will be analyzed later.
27110 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
27111 }
27112 ValueDecl *D = Res.first;
27113 if (!D)
27114 continue;
27115
27116 // Check if the declaration in the clause does not show up in any data
27117 // sharing attribute.
27118 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
27119 if (isOpenMPPrivate(Kind: DVar.CKind)) {
27120 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
27121 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
27122 << getOpenMPClauseNameForDiag(C: DVar.CKind)
27123 << getOpenMPClauseNameForDiag(C: OMPC_has_device_addr)
27124 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
27125 V: OMPVersion);
27126 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
27127 continue;
27128 }
27129
27130 const Expr *ConflictExpr;
27131 if (DSAStack->checkMappableExprComponentListsForDecl(
27132 VD: D, /*CurrentRegionOnly=*/true,
27133 Check: [&ConflictExpr](
27134 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
27135 OpenMPClauseKind) -> bool {
27136 ConflictExpr = R.front().getAssociatedExpression();
27137 return true;
27138 })) {
27139 Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
27140 Diag(Loc: ConflictExpr->getExprLoc(), DiagID: diag::note_used_here)
27141 << ConflictExpr->getSourceRange();
27142 continue;
27143 }
27144
27145 // Store the components in the stack so that they can be used to check
27146 // against other clauses later on.
27147 Expr *Component = SimpleRefExpr;
27148 auto *VD = dyn_cast<VarDecl>(Val: D);
27149 if (VD && (isa<ArraySectionExpr>(Val: RefExpr->IgnoreParenImpCasts()) ||
27150 isa<ArraySubscriptExpr>(Val: RefExpr->IgnoreParenImpCasts())))
27151 Component =
27152 SemaRef.DefaultFunctionArrayLvalueConversion(E: SimpleRefExpr).get();
27153 OMPClauseMappableExprCommon::MappableComponent MC(
27154 Component, D, /*IsNonContiguous=*/false);
27155 DSAStack->addMappableExpressionComponents(
27156 VD: D, Components: MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
27157
27158 // Record the expression we've just processed.
27159 if (!VD && !SemaRef.CurContext->isDependentContext()) {
27160 DeclRefExpr *Ref =
27161 buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
27162 assert(Ref && "has_device_addr capture failed");
27163 MVLI.ProcessedVarList.push_back(Elt: Ref);
27164 } else
27165 MVLI.ProcessedVarList.push_back(Elt: RefExpr->IgnoreParens());
27166
27167 // Create a mappable component for the list item. List items in this clause
27168 // only need a component. We use a null declaration to signal fields in
27169 // 'this'.
27170 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
27171 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
27172 "Unexpected device pointer expression!");
27173 MVLI.VarBaseDeclarations.push_back(
27174 Elt: isa<DeclRefExpr>(Val: SimpleRefExpr) ? D : nullptr);
27175 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
27176 MVLI.VarComponents.back().push_back(Elt: MC);
27177 }
27178
27179 if (MVLI.ProcessedVarList.empty())
27180 return nullptr;
27181
27182 return OMPHasDeviceAddrClause::Create(
27183 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
27184 ComponentLists: MVLI.VarComponents);
27185}
27186
27187OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause(
27188 Expr *Allocator, Expr *Alignment,
27189 OpenMPAllocateClauseModifier FirstAllocateModifier,
27190 SourceLocation FirstAllocateModifierLoc,
27191 OpenMPAllocateClauseModifier SecondAllocateModifier,
27192 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
27193 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
27194 SourceLocation EndLoc) {
27195 if (Allocator) {
27196 // Allocator expression is dependent - skip it for now and build the
27197 // allocator when instantiated.
27198 bool AllocDependent =
27199 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
27200 Allocator->isInstantiationDependent() ||
27201 Allocator->containsUnexpandedParameterPack());
27202 if (!AllocDependent) {
27203 // OpenMP [2.11.4 allocate Clause, Description]
27204 // allocator is an expression of omp_allocator_handle_t type.
27205 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: Allocator->getExprLoc(), DSAStack))
27206 return nullptr;
27207
27208 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(E: Allocator);
27209 if (AllocatorRes.isInvalid())
27210 return nullptr;
27211 AllocatorRes = SemaRef.PerformImplicitConversion(
27212 From: AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
27213 Action: AssignmentAction::Initializing,
27214 /*AllowExplicit=*/true);
27215 if (AllocatorRes.isInvalid())
27216 return nullptr;
27217 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
27218 }
27219 } else {
27220 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
27221 // allocate clauses that appear on a target construct or on constructs in a
27222 // target region must specify an allocator expression unless a requires
27223 // directive with the dynamic_allocators clause is present in the same
27224 // compilation unit.
27225 if (getLangOpts().OpenMPIsTargetDevice &&
27226 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
27227 SemaRef.targetDiag(Loc: StartLoc, DiagID: diag::err_expected_allocator_expression);
27228 }
27229 if (Alignment) {
27230 bool AlignmentDependent = Alignment->isTypeDependent() ||
27231 Alignment->isValueDependent() ||
27232 Alignment->isInstantiationDependent() ||
27233 Alignment->containsUnexpandedParameterPack();
27234 if (!AlignmentDependent) {
27235 ExprResult AlignResult =
27236 VerifyPositiveIntegerConstantInClause(E: Alignment, CKind: OMPC_allocate);
27237 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
27238 }
27239 }
27240 // Analyze and build list of variables.
27241 SmallVector<Expr *, 8> Vars;
27242 for (Expr *RefExpr : VarList) {
27243 assert(RefExpr && "NULL expr in OpenMP allocate clause.");
27244 SourceLocation ELoc;
27245 SourceRange ERange;
27246 Expr *SimpleRefExpr = RefExpr;
27247 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
27248 if (Res.second) {
27249 // It will be analyzed later.
27250 Vars.push_back(Elt: RefExpr);
27251 }
27252 ValueDecl *D = Res.first;
27253 if (!D)
27254 continue;
27255
27256 auto *VD = dyn_cast<VarDecl>(Val: D);
27257 DeclRefExpr *Ref = nullptr;
27258 if (!VD && !SemaRef.CurContext->isDependentContext())
27259 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
27260 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
27261 ? RefExpr->IgnoreParens()
27262 : Ref);
27263 }
27264
27265 if (Vars.empty())
27266 return nullptr;
27267
27268 if (Allocator)
27269 DSAStack->addInnerAllocatorExpr(E: Allocator);
27270
27271 return OMPAllocateClause::Create(
27272 C: getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
27273 Modifier1: FirstAllocateModifier, Modifier1Loc: FirstAllocateModifierLoc, Modifier2: SecondAllocateModifier,
27274 Modifier2Loc: SecondAllocateModifierLoc, EndLoc, VL: Vars);
27275}
27276
27277OMPClause *SemaOpenMP::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
27278 SourceLocation StartLoc,
27279 SourceLocation LParenLoc,
27280 SourceLocation EndLoc) {
27281 SmallVector<Expr *, 8> Vars;
27282 for (Expr *RefExpr : VarList) {
27283 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
27284 SourceLocation ELoc;
27285 SourceRange ERange;
27286 Expr *SimpleRefExpr = RefExpr;
27287 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
27288 if (Res.second)
27289 // It will be analyzed later.
27290 Vars.push_back(Elt: RefExpr);
27291 ValueDecl *D = Res.first;
27292 if (!D)
27293 continue;
27294
27295 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
27296 // A list-item cannot appear in more than one nontemporal clause.
27297 if (const Expr *PrevRef =
27298 DSAStack->addUniqueNontemporal(D, NewDE: SimpleRefExpr)) {
27299 Diag(Loc: ELoc, DiagID: diag::err_omp_used_in_clause_twice)
27300 << 0 << getOpenMPClauseNameForDiag(C: OMPC_nontemporal) << ERange;
27301 Diag(Loc: PrevRef->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
27302 << getOpenMPClauseNameForDiag(C: OMPC_nontemporal);
27303 continue;
27304 }
27305
27306 Vars.push_back(Elt: RefExpr);
27307 }
27308
27309 if (Vars.empty())
27310 return nullptr;
27311
27312 return OMPNontemporalClause::Create(C: getASTContext(), StartLoc, LParenLoc,
27313 EndLoc, VL: Vars);
27314}
27315
27316StmtResult SemaOpenMP::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
27317 Stmt *AStmt,
27318 SourceLocation StartLoc,
27319 SourceLocation EndLoc) {
27320 if (!AStmt)
27321 return StmtError();
27322
27323 SemaRef.setFunctionHasBranchProtectedScope();
27324
27325 return OMPScopeDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
27326 AssociatedStmt: AStmt);
27327}
27328
27329OMPClause *SemaOpenMP::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
27330 SourceLocation StartLoc,
27331 SourceLocation LParenLoc,
27332 SourceLocation EndLoc) {
27333 SmallVector<Expr *, 8> Vars;
27334 for (Expr *RefExpr : VarList) {
27335 assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
27336 SourceLocation ELoc;
27337 SourceRange ERange;
27338 Expr *SimpleRefExpr = RefExpr;
27339 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
27340 /*AllowArraySection=*/true);
27341 if (Res.second)
27342 // It will be analyzed later.
27343 Vars.push_back(Elt: RefExpr);
27344 ValueDecl *D = Res.first;
27345 if (!D)
27346 continue;
27347
27348 const DSAStackTy::DSAVarData DVar =
27349 DSAStack->getTopDSA(D, /*FromParent=*/true);
27350 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
27351 // A list item that appears in the inclusive or exclusive clause must appear
27352 // in a reduction clause with the inscan modifier on the enclosing
27353 // worksharing-loop, worksharing-loop SIMD, or simd construct.
27354 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
27355 Diag(Loc: ELoc, DiagID: diag::err_omp_inclusive_exclusive_not_reduction)
27356 << RefExpr->getSourceRange();
27357
27358 if (DSAStack->getParentDirective() != OMPD_unknown)
27359 DSAStack->markDeclAsUsedInScanDirective(D);
27360 Vars.push_back(Elt: RefExpr);
27361 }
27362
27363 if (Vars.empty())
27364 return nullptr;
27365
27366 return OMPInclusiveClause::Create(C: getASTContext(), StartLoc, LParenLoc,
27367 EndLoc, VL: Vars);
27368}
27369
27370OMPClause *SemaOpenMP::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
27371 SourceLocation StartLoc,
27372 SourceLocation LParenLoc,
27373 SourceLocation EndLoc) {
27374 SmallVector<Expr *, 8> Vars;
27375 for (Expr *RefExpr : VarList) {
27376 assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
27377 SourceLocation ELoc;
27378 SourceRange ERange;
27379 Expr *SimpleRefExpr = RefExpr;
27380 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
27381 /*AllowArraySection=*/true);
27382 if (Res.second)
27383 // It will be analyzed later.
27384 Vars.push_back(Elt: RefExpr);
27385 ValueDecl *D = Res.first;
27386 if (!D)
27387 continue;
27388
27389 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
27390 DSAStackTy::DSAVarData DVar;
27391 if (ParentDirective != OMPD_unknown)
27392 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
27393 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
27394 // A list item that appears in the inclusive or exclusive clause must appear
27395 // in a reduction clause with the inscan modifier on the enclosing
27396 // worksharing-loop, worksharing-loop SIMD, or simd construct.
27397 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
27398 DVar.Modifier != OMPC_REDUCTION_inscan) {
27399 Diag(Loc: ELoc, DiagID: diag::err_omp_inclusive_exclusive_not_reduction)
27400 << RefExpr->getSourceRange();
27401 } else {
27402 DSAStack->markDeclAsUsedInScanDirective(D);
27403 }
27404 Vars.push_back(Elt: RefExpr);
27405 }
27406
27407 if (Vars.empty())
27408 return nullptr;
27409
27410 return OMPExclusiveClause::Create(C: getASTContext(), StartLoc, LParenLoc,
27411 EndLoc, VL: Vars);
27412}
27413
27414/// Tries to find omp_alloctrait_t type.
27415static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
27416 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
27417 if (!OMPAlloctraitT.isNull())
27418 return true;
27419 IdentifierInfo &II = S.PP.getIdentifierTable().get(Name: "omp_alloctrait_t");
27420 ParsedType PT = S.getTypeName(II, NameLoc: Loc, S: S.getCurScope());
27421 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
27422 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
27423 return false;
27424 }
27425 Stack->setOMPAlloctraitT(PT.get());
27426 return true;
27427}
27428
27429OMPClause *SemaOpenMP::ActOnOpenMPUsesAllocatorClause(
27430 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
27431 ArrayRef<UsesAllocatorsData> Data) {
27432 ASTContext &Context = getASTContext();
27433 // OpenMP [2.12.5, target Construct]
27434 // allocator is an identifier of omp_allocator_handle_t type.
27435 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: StartLoc, DSAStack))
27436 return nullptr;
27437 // OpenMP [2.12.5, target Construct]
27438 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
27439 if (llvm::any_of(
27440 Range&: Data,
27441 P: [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
27442 !findOMPAlloctraitT(S&: SemaRef, Loc: StartLoc, DSAStack))
27443 return nullptr;
27444 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
27445 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
27446 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
27447 StringRef Allocator =
27448 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(Val: AllocatorKind);
27449 DeclarationName AllocatorName = &Context.Idents.get(Name: Allocator);
27450 PredefinedAllocators.insert(Ptr: SemaRef.LookupSingleName(
27451 S: SemaRef.TUScope, Name: AllocatorName, Loc: StartLoc, NameKind: Sema::LookupAnyName));
27452 }
27453
27454 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
27455 for (const UsesAllocatorsData &D : Data) {
27456 Expr *AllocatorExpr = nullptr;
27457 // Check allocator expression.
27458 if (D.Allocator->isTypeDependent()) {
27459 AllocatorExpr = D.Allocator;
27460 } else {
27461 // Traits were specified - need to assign new allocator to the specified
27462 // allocator, so it must be an lvalue.
27463 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
27464 auto *DRE = dyn_cast<DeclRefExpr>(Val: AllocatorExpr);
27465 bool IsPredefinedAllocator = false;
27466 if (DRE) {
27467 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
27468 getAllocatorKind(S&: SemaRef, DSAStack, Allocator: AllocatorExpr);
27469 IsPredefinedAllocator =
27470 AllocatorTy !=
27471 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
27472 }
27473 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
27474 QualType AllocatorExprType = AllocatorExpr->getType();
27475 bool IsTypeCompatible = IsPredefinedAllocator;
27476 IsTypeCompatible = IsTypeCompatible ||
27477 Context.hasSameUnqualifiedType(T1: AllocatorExprType,
27478 T2: OMPAllocatorHandleT);
27479 IsTypeCompatible =
27480 IsTypeCompatible ||
27481 Context.typesAreCompatible(T1: AllocatorExprType, T2: OMPAllocatorHandleT);
27482 bool IsNonConstantLValue =
27483 !AllocatorExprType.isConstant(Ctx: Context) && AllocatorExpr->isLValue();
27484 if (!DRE || !IsTypeCompatible ||
27485 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
27486 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::err_omp_var_expected)
27487 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
27488 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
27489 continue;
27490 }
27491 // OpenMP [2.12.5, target Construct]
27492 // Predefined allocators appearing in a uses_allocators clause cannot have
27493 // traits specified.
27494 if (IsPredefinedAllocator && D.AllocatorTraits) {
27495 Diag(Loc: D.AllocatorTraits->getExprLoc(),
27496 DiagID: diag::err_omp_predefined_allocator_with_traits)
27497 << D.AllocatorTraits->getSourceRange();
27498 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::note_omp_predefined_allocator)
27499 << cast<NamedDecl>(Val: DRE->getDecl())->getName()
27500 << D.Allocator->getSourceRange();
27501 continue;
27502 }
27503 // OpenMP [2.12.5, target Construct]
27504 // Non-predefined allocators appearing in a uses_allocators clause must
27505 // have traits specified.
27506 if (getLangOpts().OpenMP < 52) {
27507 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
27508 Diag(Loc: D.Allocator->getExprLoc(),
27509 DiagID: diag::err_omp_nonpredefined_allocator_without_traits);
27510 continue;
27511 }
27512 }
27513 // No allocator traits - just convert it to rvalue.
27514 if (!D.AllocatorTraits)
27515 AllocatorExpr = SemaRef.DefaultLvalueConversion(E: AllocatorExpr).get();
27516 DSAStack->addUsesAllocatorsDecl(
27517 D: DRE->getDecl(),
27518 Kind: IsPredefinedAllocator
27519 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
27520 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
27521 }
27522 Expr *AllocatorTraitsExpr = nullptr;
27523 if (D.AllocatorTraits) {
27524 if (D.AllocatorTraits->isTypeDependent()) {
27525 AllocatorTraitsExpr = D.AllocatorTraits;
27526 } else {
27527 // OpenMP [2.12.5, target Construct]
27528 // Arrays that contain allocator traits that appear in a uses_allocators
27529 // clause must be constant arrays, have constant values and be defined
27530 // in the same scope as the construct in which the clause appears.
27531 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
27532 // Check that traits expr is a constant array.
27533 QualType TraitTy;
27534 if (const ArrayType *Ty =
27535 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
27536 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Val: Ty))
27537 TraitTy = ConstArrayTy->getElementType();
27538 if (TraitTy.isNull() ||
27539 !(Context.hasSameUnqualifiedType(T1: TraitTy,
27540 DSAStack->getOMPAlloctraitT()) ||
27541 Context.typesAreCompatible(T1: TraitTy, DSAStack->getOMPAlloctraitT(),
27542 /*CompareUnqualified=*/true))) {
27543 Diag(Loc: D.AllocatorTraits->getExprLoc(),
27544 DiagID: diag::err_omp_expected_array_alloctraits)
27545 << AllocatorTraitsExpr->getType();
27546 continue;
27547 }
27548 // Do not map by default allocator traits if it is a standalone
27549 // variable.
27550 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: AllocatorTraitsExpr))
27551 DSAStack->addUsesAllocatorsDecl(
27552 D: DRE->getDecl(),
27553 Kind: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
27554 }
27555 }
27556 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
27557 NewD.Allocator = AllocatorExpr;
27558 NewD.AllocatorTraits = AllocatorTraitsExpr;
27559 NewD.LParenLoc = D.LParenLoc;
27560 NewD.RParenLoc = D.RParenLoc;
27561 }
27562 return OMPUsesAllocatorsClause::Create(C: getASTContext(), StartLoc, LParenLoc,
27563 EndLoc, Data: NewData);
27564}
27565
27566OMPClause *SemaOpenMP::ActOnOpenMPAffinityClause(
27567 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
27568 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
27569 SmallVector<Expr *, 8> Vars;
27570 for (Expr *RefExpr : Locators) {
27571 assert(RefExpr && "NULL expr in OpenMP affinity clause.");
27572 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr) || RefExpr->isTypeDependent()) {
27573 // It will be analyzed later.
27574 Vars.push_back(Elt: RefExpr);
27575 continue;
27576 }
27577
27578 SourceLocation ELoc = RefExpr->getExprLoc();
27579 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
27580
27581 if (!SimpleExpr->isLValue()) {
27582 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
27583 << 1 << 0 << RefExpr->getSourceRange();
27584 continue;
27585 }
27586
27587 ExprResult Res;
27588 {
27589 Sema::TentativeAnalysisScope Trap(SemaRef);
27590 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: SimpleExpr);
27591 }
27592 if (!Res.isUsable() && !isa<ArraySectionExpr>(Val: SimpleExpr) &&
27593 !isa<OMPArrayShapingExpr>(Val: SimpleExpr)) {
27594 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
27595 << 1 << 0 << RefExpr->getSourceRange();
27596 continue;
27597 }
27598 Vars.push_back(Elt: SimpleExpr);
27599 }
27600
27601 return OMPAffinityClause::Create(C: getASTContext(), StartLoc, LParenLoc,
27602 ColonLoc, EndLoc, Modifier, Locators: Vars);
27603}
27604
27605OMPClause *SemaOpenMP::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
27606 SourceLocation KindLoc,
27607 SourceLocation StartLoc,
27608 SourceLocation LParenLoc,
27609 SourceLocation EndLoc) {
27610 if (Kind == OMPC_BIND_unknown) {
27611 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
27612 << getListOfPossibleValues(K: OMPC_bind, /*First=*/0,
27613 /*Last=*/unsigned(OMPC_BIND_unknown))
27614 << getOpenMPClauseNameForDiag(C: OMPC_bind);
27615 return nullptr;
27616 }
27617
27618 return new (getASTContext())
27619 OMPBindClause(Kind, KindLoc, StartLoc, LParenLoc, EndLoc);
27620}
27621
27622OMPClause *SemaOpenMP::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
27623 SourceLocation StartLoc,
27624 SourceLocation LParenLoc,
27625 SourceLocation EndLoc) {
27626 Expr *ValExpr = Size;
27627 Stmt *HelperValStmt = nullptr;
27628
27629 // OpenMP [2.5, Restrictions]
27630 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
27631 // value.
27632 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_ompx_dyn_cgroup_mem,
27633 /*StrictlyPositive=*/false))
27634 return nullptr;
27635
27636 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
27637 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
27638 DKind, CKind: OMPC_ompx_dyn_cgroup_mem, OMPVersion: getLangOpts().getOpenMPVersion());
27639 if (CaptureRegion != OMPD_unknown &&
27640 !SemaRef.CurContext->isDependentContext()) {
27641 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
27642 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
27643 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
27644 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
27645 }
27646
27647 return new (getASTContext()) OMPXDynCGroupMemClause(
27648 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
27649}
27650
27651OMPClause *SemaOpenMP::ActOnOpenMPDynGroupprivateClause(
27652 OpenMPDynGroupprivateClauseModifier M1,
27653 OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size,
27654 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
27655 SourceLocation M2Loc, SourceLocation EndLoc) {
27656
27657 if ((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ||
27658 (M2Loc.isValid() && M2 == OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown)) {
27659 std::string Values = getListOfPossibleValues(
27660 K: OMPC_dyn_groupprivate, /*First=*/0, Last: OMPC_DYN_GROUPPRIVATE_unknown);
27661 Diag(Loc: (M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ? M1Loc
27662 : M2Loc,
27663 DiagID: diag::err_omp_unexpected_clause_value)
27664 << Values << getOpenMPClauseName(C: OMPC_dyn_groupprivate);
27665 return nullptr;
27666 }
27667
27668 Expr *ValExpr = Size;
27669 Stmt *HelperValStmt = nullptr;
27670
27671 // OpenMP [2.5, Restrictions]
27672 // The dyn_groupprivate expression must evaluate to a positive integer
27673 // value.
27674 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_dyn_groupprivate,
27675 /*StrictlyPositive=*/false))
27676 return nullptr;
27677
27678 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
27679 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
27680 DKind, CKind: OMPC_dyn_groupprivate, OMPVersion: getLangOpts().getOpenMPVersion());
27681 if (CaptureRegion != OMPD_unknown &&
27682 !SemaRef.CurContext->isDependentContext()) {
27683 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
27684 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
27685 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
27686 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
27687 }
27688
27689 return new (getASTContext()) OMPDynGroupprivateClause(
27690 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
27691 M1Loc, M2, M2Loc);
27692}
27693
27694OMPClause *SemaOpenMP::ActOnOpenMPDoacrossClause(
27695 OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
27696 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
27697 SourceLocation LParenLoc, SourceLocation EndLoc) {
27698
27699 if (DSAStack->getCurrentDirective() == OMPD_ordered_standalone &&
27700 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
27701 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
27702 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
27703 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
27704 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(C: OMPC_doacross);
27705 return nullptr;
27706 }
27707
27708 SmallVector<Expr *, 8> Vars;
27709 DSAStackTy::OperatorOffsetTy OpsOffs;
27710 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
27711 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
27712 SemaRef,
27713 IsSource: DepType == OMPC_DOACROSS_source ||
27714 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
27715 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
27716 VarList, DSAStack, EndLoc);
27717 Vars = VarOffset.Vars;
27718 OpsOffs = VarOffset.OpsOffs;
27719 TotalDepCount = VarOffset.TotalDepCount;
27720 auto *C = OMPDoacrossClause::Create(C: getASTContext(), StartLoc, LParenLoc,
27721 EndLoc, DepType, DepLoc, ColonLoc, VL: Vars,
27722 NumLoops: TotalDepCount.getZExtValue());
27723 if (DSAStack->isParentOrderedRegion())
27724 DSAStack->addDoacrossDependClause(C, OpsOffs);
27725 return C;
27726}
27727
27728OMPClause *SemaOpenMP::ActOnOpenMPXAttributeClause(ArrayRef<const Attr *> Attrs,
27729 SourceLocation StartLoc,
27730 SourceLocation LParenLoc,
27731 SourceLocation EndLoc) {
27732 return new (getASTContext())
27733 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
27734}
27735
27736OMPClause *SemaOpenMP::ActOnOpenMPXBareClause(SourceLocation StartLoc,
27737 SourceLocation EndLoc) {
27738 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
27739}
27740
27741OMPClause *SemaOpenMP::ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc,
27742 SourceLocation LParenLoc,
27743 SourceLocation EndLoc) {
27744 if (E->HasSideEffects(Ctx: getASTContext()))
27745 Diag(Loc: E->getBeginLoc(), DiagID: diag::warn_assume_side_effects)
27746 << "holds" << E->getSourceRange();
27747 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
27748}
27749
27750OMPClause *SemaOpenMP::ActOnOpenMPDirectivePresenceClause(
27751 OpenMPClauseKind CK, llvm::ArrayRef<OpenMPDirectiveKind> DKVec,
27752 SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc) {
27753 switch (CK) {
27754 case OMPC_absent:
27755 return OMPAbsentClause::Create(C: getASTContext(), DKVec, Loc, LLoc, RLoc);
27756 case OMPC_contains:
27757 return OMPContainsClause::Create(C: getASTContext(), DKVec, Loc, LLoc, RLoc);
27758 default:
27759 llvm_unreachable("Unexpected OpenMP clause");
27760 }
27761}
27762
27763OMPClause *SemaOpenMP::ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK,
27764 SourceLocation Loc,
27765 SourceLocation RLoc) {
27766 switch (CK) {
27767 case OMPC_no_openmp:
27768 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
27769 case OMPC_no_openmp_routines:
27770 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
27771 case OMPC_no_parallelism:
27772 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
27773 case OMPC_no_openmp_constructs:
27774 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
27775 default:
27776 llvm_unreachable("Unexpected OpenMP clause");
27777 }
27778}
27779
27780ExprResult SemaOpenMP::ActOnOMPArraySectionExpr(
27781 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
27782 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
27783 Expr *Stride, SourceLocation RBLoc) {
27784 ASTContext &Context = getASTContext();
27785 if (Base->hasPlaceholderType() &&
27786 !Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
27787 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base);
27788 if (Result.isInvalid())
27789 return ExprError();
27790 Base = Result.get();
27791 }
27792 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
27793 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: LowerBound);
27794 if (Result.isInvalid())
27795 return ExprError();
27796 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
27797 if (Result.isInvalid())
27798 return ExprError();
27799 LowerBound = Result.get();
27800 }
27801 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
27802 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Length);
27803 if (Result.isInvalid())
27804 return ExprError();
27805 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
27806 if (Result.isInvalid())
27807 return ExprError();
27808 Length = Result.get();
27809 }
27810 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
27811 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Stride);
27812 if (Result.isInvalid())
27813 return ExprError();
27814 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
27815 if (Result.isInvalid())
27816 return ExprError();
27817 Stride = Result.get();
27818 }
27819
27820 // Build an unanalyzed expression if either operand is type-dependent.
27821 if (Base->isTypeDependent() ||
27822 (LowerBound &&
27823 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
27824 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
27825 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
27826 return new (Context) ArraySectionExpr(
27827 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
27828 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
27829 }
27830
27831 // Perform default conversions.
27832 QualType OriginalTy = ArraySectionExpr::getBaseOriginalType(Base);
27833 QualType ResultTy;
27834 if (OriginalTy->isAnyPointerType()) {
27835 ResultTy = OriginalTy->getPointeeType();
27836 } else if (OriginalTy->isArrayType()) {
27837 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
27838 } else {
27839 return ExprError(
27840 Diag(Loc: Base->getExprLoc(), DiagID: diag::err_omp_typecheck_section_value)
27841 << Base->getSourceRange());
27842 }
27843 // C99 6.5.2.1p1
27844 if (LowerBound) {
27845 auto Res = PerformOpenMPImplicitIntegerConversion(Loc: LowerBound->getExprLoc(),
27846 Op: LowerBound);
27847 if (Res.isInvalid())
27848 return ExprError(Diag(Loc: LowerBound->getExprLoc(),
27849 DiagID: diag::err_omp_typecheck_section_not_integer)
27850 << 0 << LowerBound->getSourceRange());
27851 LowerBound = Res.get();
27852
27853 if (LowerBound->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
27854 LowerBound->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
27855 Diag(Loc: LowerBound->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
27856 << 0 << LowerBound->getSourceRange();
27857 }
27858 if (Length) {
27859 auto Res =
27860 PerformOpenMPImplicitIntegerConversion(Loc: Length->getExprLoc(), Op: Length);
27861 if (Res.isInvalid())
27862 return ExprError(Diag(Loc: Length->getExprLoc(),
27863 DiagID: diag::err_omp_typecheck_section_not_integer)
27864 << 1 << Length->getSourceRange());
27865 Length = Res.get();
27866
27867 if (Length->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
27868 Length->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
27869 Diag(Loc: Length->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
27870 << 1 << Length->getSourceRange();
27871 }
27872 if (Stride) {
27873 ExprResult Res =
27874 PerformOpenMPImplicitIntegerConversion(Loc: Stride->getExprLoc(), Op: Stride);
27875 if (Res.isInvalid())
27876 return ExprError(Diag(Loc: Stride->getExprLoc(),
27877 DiagID: diag::err_omp_typecheck_section_not_integer)
27878 << 1 << Stride->getSourceRange());
27879 Stride = Res.get();
27880
27881 if (Stride->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
27882 Stride->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
27883 Diag(Loc: Stride->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
27884 << 1 << Stride->getSourceRange();
27885 }
27886
27887 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
27888 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
27889 // type. Note that functions are not objects, and that (in C99 parlance)
27890 // incomplete types are not object types.
27891 if (ResultTy->isFunctionType()) {
27892 Diag(Loc: Base->getExprLoc(), DiagID: diag::err_omp_section_function_type)
27893 << ResultTy << Base->getSourceRange();
27894 return ExprError();
27895 }
27896
27897 if (SemaRef.RequireCompleteType(Loc: Base->getExprLoc(), T: ResultTy,
27898 DiagID: diag::err_omp_section_incomplete_type, Args: Base))
27899 return ExprError();
27900
27901 if (LowerBound && !OriginalTy->isAnyPointerType()) {
27902 Expr::EvalResult Result;
27903 if (LowerBound->EvaluateAsInt(Result, Ctx: Context)) {
27904 // OpenMP 5.0, [2.1.5 Array Sections]
27905 // The array section must be a subset of the original array.
27906 llvm::APSInt LowerBoundValue = Result.Val.getInt();
27907 if (LowerBoundValue.isNegative()) {
27908 Diag(Loc: LowerBound->getExprLoc(),
27909 DiagID: diag::err_omp_section_not_subset_of_array)
27910 << LowerBound->getSourceRange();
27911 return ExprError();
27912 }
27913 }
27914 }
27915
27916 if (Length) {
27917 Expr::EvalResult Result;
27918 if (Length->EvaluateAsInt(Result, Ctx: Context)) {
27919 // OpenMP 5.0, [2.1.5 Array Sections]
27920 // The length must evaluate to non-negative integers.
27921 llvm::APSInt LengthValue = Result.Val.getInt();
27922 if (LengthValue.isNegative()) {
27923 Diag(Loc: Length->getExprLoc(), DiagID: diag::err_omp_section_length_negative)
27924 << toString(I: LengthValue, /*Radix=*/10, /*Signed=*/true)
27925 << Length->getSourceRange();
27926 return ExprError();
27927 }
27928 }
27929 } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
27930 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
27931 !OriginalTy->isVariableArrayType()))) {
27932 // OpenMP 5.0, [2.1.5 Array Sections]
27933 // When the size of the array dimension is not known, the length must be
27934 // specified explicitly.
27935 Diag(Loc: ColonLocFirst, DiagID: diag::err_omp_section_length_undefined)
27936 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
27937 return ExprError();
27938 }
27939
27940 if (Stride) {
27941 Expr::EvalResult Result;
27942 if (Stride->EvaluateAsInt(Result, Ctx: Context)) {
27943 // OpenMP 5.0, [2.1.5 Array Sections]
27944 // The stride must evaluate to a positive integer.
27945 llvm::APSInt StrideValue = Result.Val.getInt();
27946 if (!StrideValue.isStrictlyPositive()) {
27947 Diag(Loc: Stride->getExprLoc(), DiagID: diag::err_omp_section_stride_non_positive)
27948 << toString(I: StrideValue, /*Radix=*/10, /*Signed=*/true)
27949 << Stride->getSourceRange();
27950 return ExprError();
27951 }
27952 }
27953 }
27954
27955 if (!Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
27956 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(E: Base);
27957 if (Result.isInvalid())
27958 return ExprError();
27959 Base = Result.get();
27960 }
27961 return new (Context) ArraySectionExpr(
27962 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
27963 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
27964}
27965
27966ExprResult SemaOpenMP::ActOnOMPArrayShapingExpr(
27967 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
27968 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
27969 ASTContext &Context = getASTContext();
27970 if (Base->hasPlaceholderType()) {
27971 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base);
27972 if (Result.isInvalid())
27973 return ExprError();
27974 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
27975 if (Result.isInvalid())
27976 return ExprError();
27977 Base = Result.get();
27978 }
27979 QualType BaseTy = Base->getType();
27980 // Delay analysis of the types/expressions if instantiation/specialization is
27981 // required.
27982 if (!BaseTy->isPointerType() && Base->isTypeDependent())
27983 return OMPArrayShapingExpr::Create(Context, T: Context.DependentTy, Op: Base,
27984 L: LParenLoc, R: RParenLoc, Dims, BracketRanges: Brackets);
27985 if (!BaseTy->isPointerType() ||
27986 (!Base->isTypeDependent() &&
27987 BaseTy->getPointeeType()->isIncompleteType()))
27988 return ExprError(Diag(Loc: Base->getExprLoc(),
27989 DiagID: diag::err_omp_non_pointer_type_array_shaping_base)
27990 << Base->getSourceRange());
27991
27992 SmallVector<Expr *, 4> NewDims;
27993 bool ErrorFound = false;
27994 for (Expr *Dim : Dims) {
27995 if (Dim->hasPlaceholderType()) {
27996 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Dim);
27997 if (Result.isInvalid()) {
27998 ErrorFound = true;
27999 continue;
28000 }
28001 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
28002 if (Result.isInvalid()) {
28003 ErrorFound = true;
28004 continue;
28005 }
28006 Dim = Result.get();
28007 }
28008 if (!Dim->isTypeDependent()) {
28009 ExprResult Result =
28010 PerformOpenMPImplicitIntegerConversion(Loc: Dim->getExprLoc(), Op: Dim);
28011 if (Result.isInvalid()) {
28012 ErrorFound = true;
28013 Diag(Loc: Dim->getExprLoc(), DiagID: diag::err_omp_typecheck_shaping_not_integer)
28014 << Dim->getSourceRange();
28015 continue;
28016 }
28017 Dim = Result.get();
28018 Expr::EvalResult EvResult;
28019 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(Result&: EvResult, Ctx: Context)) {
28020 // OpenMP 5.0, [2.1.4 Array Shaping]
28021 // Each si is an integral type expression that must evaluate to a
28022 // positive integer.
28023 llvm::APSInt Value = EvResult.Val.getInt();
28024 if (!Value.isStrictlyPositive()) {
28025 Diag(Loc: Dim->getExprLoc(), DiagID: diag::err_omp_shaping_dimension_not_positive)
28026 << toString(I: Value, /*Radix=*/10, /*Signed=*/true)
28027 << Dim->getSourceRange();
28028 ErrorFound = true;
28029 continue;
28030 }
28031 }
28032 }
28033 NewDims.push_back(Elt: Dim);
28034 }
28035 if (ErrorFound)
28036 return ExprError();
28037 return OMPArrayShapingExpr::Create(Context, T: Context.OMPArrayShapingTy, Op: Base,
28038 L: LParenLoc, R: RParenLoc, Dims: NewDims, BracketRanges: Brackets);
28039}
28040
28041ExprResult SemaOpenMP::ActOnOMPIteratorExpr(Scope *S,
28042 SourceLocation IteratorKwLoc,
28043 SourceLocation LLoc,
28044 SourceLocation RLoc,
28045 ArrayRef<OMPIteratorData> Data) {
28046 ASTContext &Context = getASTContext();
28047 SmallVector<OMPIteratorExpr::IteratorDefinition, 4> ID;
28048 bool IsCorrect = true;
28049 for (const OMPIteratorData &D : Data) {
28050 TypeSourceInfo *TInfo = nullptr;
28051 SourceLocation StartLoc;
28052 QualType DeclTy;
28053 if (!D.Type.getAsOpaquePtr()) {
28054 // OpenMP 5.0, 2.1.6 Iterators
28055 // In an iterator-specifier, if the iterator-type is not specified then
28056 // the type of that iterator is of int type.
28057 DeclTy = Context.IntTy;
28058 StartLoc = D.DeclIdentLoc;
28059 } else {
28060 DeclTy = Sema::GetTypeFromParser(Ty: D.Type, TInfo: &TInfo);
28061 StartLoc = TInfo->getTypeLoc().getBeginLoc();
28062 }
28063
28064 bool IsDeclTyDependent = DeclTy->isDependentType() ||
28065 DeclTy->containsUnexpandedParameterPack() ||
28066 DeclTy->isInstantiationDependentType();
28067 if (!IsDeclTyDependent) {
28068 if (!DeclTy->isIntegralType(Ctx: Context) && !DeclTy->isAnyPointerType()) {
28069 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
28070 // The iterator-type must be an integral or pointer type.
28071 Diag(Loc: StartLoc, DiagID: diag::err_omp_iterator_not_integral_or_pointer)
28072 << DeclTy;
28073 IsCorrect = false;
28074 continue;
28075 }
28076 if (DeclTy.isConstant(Ctx: Context)) {
28077 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
28078 // The iterator-type must not be const qualified.
28079 Diag(Loc: StartLoc, DiagID: diag::err_omp_iterator_not_integral_or_pointer)
28080 << DeclTy;
28081 IsCorrect = false;
28082 continue;
28083 }
28084 }
28085
28086 // Iterator declaration.
28087 assert(D.DeclIdent && "Identifier expected.");
28088 // Always try to create iterator declarator to avoid extra error messages
28089 // about unknown declarations use.
28090 auto *VD =
28091 VarDecl::Create(C&: Context, DC: SemaRef.CurContext, StartLoc, IdLoc: D.DeclIdentLoc,
28092 Id: D.DeclIdent, T: DeclTy, TInfo, S: SC_None);
28093 VD->setImplicit();
28094 if (S) {
28095 // Check for conflicting previous declaration.
28096 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
28097 LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
28098 RedeclarationKind::ForVisibleRedeclaration);
28099 Previous.suppressDiagnostics();
28100 SemaRef.LookupName(R&: Previous, S);
28101
28102 SemaRef.FilterLookupForScope(R&: Previous, Ctx: SemaRef.CurContext, S,
28103 /*ConsiderLinkage=*/false,
28104 /*AllowInlineNamespace=*/false);
28105 if (!Previous.empty()) {
28106 NamedDecl *Old = Previous.getRepresentativeDecl();
28107 Diag(Loc: D.DeclIdentLoc, DiagID: diag::err_redefinition) << VD->getDeclName();
28108 Diag(Loc: Old->getLocation(), DiagID: diag::note_previous_definition);
28109 } else {
28110 SemaRef.PushOnScopeChains(D: VD, S);
28111 }
28112 } else {
28113 SemaRef.CurContext->addDecl(D: VD);
28114 }
28115
28116 /// Act on the iterator variable declaration.
28117 ActOnOpenMPIteratorVarDecl(VD);
28118
28119 Expr *Begin = D.Range.Begin;
28120 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
28121 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
28122 From: Begin, ToType: DeclTy, Action: AssignmentAction::Converting);
28123 Begin = BeginRes.get();
28124 }
28125 Expr *End = D.Range.End;
28126 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
28127 ExprResult EndRes = SemaRef.PerformImplicitConversion(
28128 From: End, ToType: DeclTy, Action: AssignmentAction::Converting);
28129 End = EndRes.get();
28130 }
28131 Expr *Step = D.Range.Step;
28132 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
28133 if (!Step->getType()->isIntegralType(Ctx: Context)) {
28134 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_iterator_step_not_integral)
28135 << Step << Step->getSourceRange();
28136 IsCorrect = false;
28137 continue;
28138 }
28139 std::optional<llvm::APSInt> Result =
28140 Step->getIntegerConstantExpr(Ctx: Context);
28141 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
28142 // If the step expression of a range-specification equals zero, the
28143 // behavior is unspecified.
28144 if (Result && Result->isZero()) {
28145 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_iterator_step_constant_zero)
28146 << Step << Step->getSourceRange();
28147 IsCorrect = false;
28148 continue;
28149 }
28150 }
28151 if (!Begin || !End || !IsCorrect) {
28152 IsCorrect = false;
28153 continue;
28154 }
28155 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
28156 IDElem.IteratorDecl = VD;
28157 IDElem.AssignmentLoc = D.AssignLoc;
28158 IDElem.Range.Begin = Begin;
28159 IDElem.Range.End = End;
28160 IDElem.Range.Step = Step;
28161 IDElem.ColonLoc = D.ColonLoc;
28162 IDElem.SecondColonLoc = D.SecColonLoc;
28163 }
28164 if (!IsCorrect) {
28165 // Invalidate all created iterator declarations if error is found.
28166 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
28167 if (Decl *ID = D.IteratorDecl)
28168 ID->setInvalidDecl();
28169 }
28170 return ExprError();
28171 }
28172 SmallVector<OMPIteratorHelperData, 4> Helpers;
28173 if (!SemaRef.CurContext->isDependentContext()) {
28174 // Build number of ityeration for each iteration range.
28175 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
28176 // ((Begini-Stepi-1-Endi) / -Stepi);
28177 for (OMPIteratorExpr::IteratorDefinition &D : ID) {
28178 // (Endi - Begini)
28179 ExprResult Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Sub,
28180 LHSExpr: D.Range.End, RHSExpr: D.Range.Begin);
28181 if (!Res.isUsable()) {
28182 IsCorrect = false;
28183 continue;
28184 }
28185 ExprResult St, St1;
28186 if (D.Range.Step) {
28187 St = D.Range.Step;
28188 // (Endi - Begini) + Stepi
28189 Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add, LHSExpr: Res.get(),
28190 RHSExpr: St.get());
28191 if (!Res.isUsable()) {
28192 IsCorrect = false;
28193 continue;
28194 }
28195 // (Endi - Begini) + Stepi - 1
28196 Res = SemaRef.CreateBuiltinBinOp(
28197 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: Res.get(),
28198 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 1).get());
28199 if (!Res.isUsable()) {
28200 IsCorrect = false;
28201 continue;
28202 }
28203 // ((Endi - Begini) + Stepi - 1) / Stepi
28204 Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Div, LHSExpr: Res.get(),
28205 RHSExpr: St.get());
28206 if (!Res.isUsable()) {
28207 IsCorrect = false;
28208 continue;
28209 }
28210 St1 = SemaRef.CreateBuiltinUnaryOp(OpLoc: D.AssignmentLoc, Opc: UO_Minus,
28211 InputExpr: D.Range.Step);
28212 // (Begini - Endi)
28213 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
28214 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: D.Range.Begin, RHSExpr: D.Range.End);
28215 if (!Res1.isUsable()) {
28216 IsCorrect = false;
28217 continue;
28218 }
28219 // (Begini - Endi) - Stepi
28220 Res1 = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add, LHSExpr: Res1.get(),
28221 RHSExpr: St1.get());
28222 if (!Res1.isUsable()) {
28223 IsCorrect = false;
28224 continue;
28225 }
28226 // (Begini - Endi) - Stepi - 1
28227 Res1 = SemaRef.CreateBuiltinBinOp(
28228 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: Res1.get(),
28229 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 1).get());
28230 if (!Res1.isUsable()) {
28231 IsCorrect = false;
28232 continue;
28233 }
28234 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
28235 Res1 = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Div, LHSExpr: Res1.get(),
28236 RHSExpr: St1.get());
28237 if (!Res1.isUsable()) {
28238 IsCorrect = false;
28239 continue;
28240 }
28241 // Stepi > 0.
28242 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
28243 OpLoc: D.AssignmentLoc, Opc: BO_GT, LHSExpr: D.Range.Step,
28244 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 0).get());
28245 if (!CmpRes.isUsable()) {
28246 IsCorrect = false;
28247 continue;
28248 }
28249 Res = SemaRef.ActOnConditionalOp(QuestionLoc: D.AssignmentLoc, ColonLoc: D.AssignmentLoc,
28250 CondExpr: CmpRes.get(), LHSExpr: Res.get(), RHSExpr: Res1.get());
28251 if (!Res.isUsable()) {
28252 IsCorrect = false;
28253 continue;
28254 }
28255 }
28256 Res = SemaRef.ActOnFinishFullExpr(Expr: Res.get(), /*DiscardedValue=*/false);
28257 if (!Res.isUsable()) {
28258 IsCorrect = false;
28259 continue;
28260 }
28261
28262 // Build counter update.
28263 // Build counter.
28264 auto *CounterVD = VarDecl::Create(C&: Context, DC: SemaRef.CurContext,
28265 StartLoc: D.IteratorDecl->getBeginLoc(),
28266 IdLoc: D.IteratorDecl->getBeginLoc(), Id: nullptr,
28267 T: Res.get()->getType(), TInfo: nullptr, S: SC_None);
28268 CounterVD->setImplicit();
28269 ExprResult RefRes =
28270 SemaRef.BuildDeclRefExpr(D: CounterVD, Ty: CounterVD->getType(), VK: VK_LValue,
28271 Loc: D.IteratorDecl->getBeginLoc());
28272 // Build counter update.
28273 // I = Begini + counter * Stepi;
28274 ExprResult UpdateRes;
28275 if (D.Range.Step) {
28276 UpdateRes = SemaRef.CreateBuiltinBinOp(
28277 OpLoc: D.AssignmentLoc, Opc: BO_Mul,
28278 LHSExpr: SemaRef.DefaultLvalueConversion(E: RefRes.get()).get(), RHSExpr: St.get());
28279 } else {
28280 UpdateRes = SemaRef.DefaultLvalueConversion(E: RefRes.get());
28281 }
28282 if (!UpdateRes.isUsable()) {
28283 IsCorrect = false;
28284 continue;
28285 }
28286 UpdateRes = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add,
28287 LHSExpr: D.Range.Begin, RHSExpr: UpdateRes.get());
28288 if (!UpdateRes.isUsable()) {
28289 IsCorrect = false;
28290 continue;
28291 }
28292 ExprResult VDRes =
28293 SemaRef.BuildDeclRefExpr(D: cast<VarDecl>(Val: D.IteratorDecl),
28294 Ty: cast<VarDecl>(Val: D.IteratorDecl)->getType(),
28295 VK: VK_LValue, Loc: D.IteratorDecl->getBeginLoc());
28296 UpdateRes = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Assign,
28297 LHSExpr: VDRes.get(), RHSExpr: UpdateRes.get());
28298 if (!UpdateRes.isUsable()) {
28299 IsCorrect = false;
28300 continue;
28301 }
28302 UpdateRes =
28303 SemaRef.ActOnFinishFullExpr(Expr: UpdateRes.get(), /*DiscardedValue=*/true);
28304 if (!UpdateRes.isUsable()) {
28305 IsCorrect = false;
28306 continue;
28307 }
28308 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
28309 OpLoc: D.AssignmentLoc, Opc: UO_PreInc, InputExpr: RefRes.get());
28310 if (!CounterUpdateRes.isUsable()) {
28311 IsCorrect = false;
28312 continue;
28313 }
28314 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(Expr: CounterUpdateRes.get(),
28315 /*DiscardedValue=*/true);
28316 if (!CounterUpdateRes.isUsable()) {
28317 IsCorrect = false;
28318 continue;
28319 }
28320 OMPIteratorHelperData &HD = Helpers.emplace_back();
28321 HD.CounterVD = CounterVD;
28322 HD.Upper = Res.get();
28323 HD.Update = UpdateRes.get();
28324 HD.CounterUpdate = CounterUpdateRes.get();
28325 }
28326 } else {
28327 Helpers.assign(NumElts: ID.size(), Elt: {});
28328 }
28329 if (!IsCorrect) {
28330 // Invalidate all created iterator declarations if error is found.
28331 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
28332 if (Decl *ID = D.IteratorDecl)
28333 ID->setInvalidDecl();
28334 }
28335 return ExprError();
28336 }
28337 return OMPIteratorExpr::Create(Context, T: Context.OMPIteratorTy, IteratorKwLoc,
28338 L: LLoc, R: RLoc, Data: ID, Helpers);
28339}
28340
28341/// Check if \p AssumptionStr is a known assumption and warn if not.
28342static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc,
28343 StringRef AssumptionStr) {
28344 if (llvm::getKnownAssumptionStrings().count(Key: AssumptionStr))
28345 return;
28346
28347 unsigned BestEditDistance = 3;
28348 StringRef Suggestion;
28349 for (const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
28350 unsigned EditDistance =
28351 AssumptionStr.edit_distance(Other: KnownAssumptionIt.getKey());
28352 if (EditDistance < BestEditDistance) {
28353 Suggestion = KnownAssumptionIt.getKey();
28354 BestEditDistance = EditDistance;
28355 }
28356 }
28357
28358 if (!Suggestion.empty())
28359 S.Diag(Loc, DiagID: diag::warn_omp_assume_attribute_string_unknown_suggested)
28360 << AssumptionStr << Suggestion;
28361 else
28362 S.Diag(Loc, DiagID: diag::warn_omp_assume_attribute_string_unknown)
28363 << AssumptionStr;
28364}
28365
28366void SemaOpenMP::handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL) {
28367 // Handle the case where the attribute has a text message.
28368 StringRef Str;
28369 SourceLocation AttrStrLoc;
28370 if (!SemaRef.checkStringLiteralArgumentAttr(Attr: AL, ArgNum: 0, Str, ArgLocation: &AttrStrLoc))
28371 return;
28372
28373 checkOMPAssumeAttr(S&: SemaRef, Loc: AttrStrLoc, AssumptionStr: Str);
28374
28375 D->addAttr(A: ::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
28376}
28377
28378SemaOpenMP::SemaOpenMP(Sema &S)
28379 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
28380