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/StmtCXX.h"
28#include "clang/AST/StmtOpenMP.h"
29#include "clang/AST/StmtVisitor.h"
30#include "clang/Basic/DiagnosticSema.h"
31#include "clang/Basic/OpenMPKinds.h"
32#include "clang/Basic/PartialDiagnostic.h"
33#include "clang/Basic/TargetInfo.h"
34#include "clang/Sema/EnterExpressionEvaluationContext.h"
35#include "clang/Sema/Initialization.h"
36#include "clang/Sema/Lookup.h"
37#include "clang/Sema/ParsedAttr.h"
38#include "clang/Sema/Scope.h"
39#include "clang/Sema/ScopeInfo.h"
40#include "clang/Sema/Sema.h"
41#include "llvm/ADT/IndexedMap.h"
42#include "llvm/ADT/PointerEmbeddedInt.h"
43#include "llvm/ADT/STLExtras.h"
44#include "llvm/ADT/Sequence.h"
45#include "llvm/ADT/SetVector.h"
46#include "llvm/ADT/SmallSet.h"
47#include "llvm/ADT/StringExtras.h"
48#include "llvm/Frontend/OpenMP/OMPAssume.h"
49#include "llvm/Frontend/OpenMP/OMPConstants.h"
50#include "llvm/Frontend/OpenMP/OMPVersion.h"
51#include "llvm/IR/Assumptions.h"
52#include <optional>
53
54using namespace clang;
55using namespace llvm::omp;
56
57//===----------------------------------------------------------------------===//
58// Stack of data-sharing attributes for variables
59//===----------------------------------------------------------------------===//
60
61static const Expr *checkMapClauseExpressionBase(
62 Sema &SemaRef, Expr *E,
63 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
64 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
65
66static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C);
67
68namespace {
69/// Default data sharing attributes, which can be applied to directive.
70enum DefaultDataSharingAttributes {
71 DSA_unspecified = 0, /// Data sharing attribute not specified.
72 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
73 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
74 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
75 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
76};
77
78/// Variable Category attributes to restrict the modifier of the
79/// default clause (DefaultDataSharingAttributes)
80/// Not mentioning any Variable category attribute indicates
81/// the modifier (DefaultDataSharingAttributes) is for all variables.
82enum DefaultDataSharingVCAttributes {
83 DSA_VC_all = 0, /// for all variables.
84 DSA_VC_aggregate, /// for aggregate variables.
85 DSA_VC_pointer, /// for pointer variables.
86 DSA_VC_scalar, /// for scalar variables.
87};
88
89/// Stack for tracking declarations used in OpenMP directives and
90/// clauses and their data-sharing attributes.
91class DSAStackTy {
92public:
93 struct DSAVarData {
94 OpenMPDirectiveKind DKind = OMPD_unknown;
95 OpenMPClauseKind CKind = OMPC_unknown;
96 unsigned Modifier = 0;
97 const Expr *RefExpr = nullptr;
98 DeclRefExpr *PrivateCopy = nullptr;
99 SourceLocation ImplicitDSALoc;
100 bool AppliedToPointee = false;
101 DSAVarData() = default;
102 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
103 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
104 SourceLocation ImplicitDSALoc, unsigned Modifier,
105 bool AppliedToPointee)
106 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
107 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
108 AppliedToPointee(AppliedToPointee) {}
109 };
110 using OperatorOffsetTy =
111 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
112 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
113 /// Kind of the declaration used in the uses_allocators clauses.
114 enum class UsesAllocatorsDeclKind {
115 /// Predefined allocator
116 PredefinedAllocator,
117 /// User-defined allocator
118 UserDefinedAllocator,
119 /// The declaration that represent allocator trait
120 AllocatorTrait,
121 };
122
123private:
124 struct DSAInfo {
125 OpenMPClauseKind Attributes = OMPC_unknown;
126 unsigned Modifier = 0;
127 /// Pointer to a reference expression and a flag which shows that the
128 /// variable is marked as lastprivate(true) or not (false).
129 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
130 DeclRefExpr *PrivateCopy = nullptr;
131 /// true if the attribute is applied to the pointee, not the variable
132 /// itself.
133 bool AppliedToPointee = false;
134 };
135 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
136 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
137 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
138 using LoopControlVariablesMapTy =
139 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
140 /// Struct that associates a component with the clause kind where they are
141 /// found.
142 struct MappedExprComponentTy {
143 OMPClauseMappableExprCommon::MappableExprComponentLists Components;
144 OpenMPClauseKind Kind = OMPC_unknown;
145 };
146 using MappedExprComponentsTy =
147 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
148 using CriticalsWithHintsTy =
149 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
150 struct ReductionData {
151 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
152 SourceRange ReductionRange;
153 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
154 ReductionData() = default;
155 void set(BinaryOperatorKind BO, SourceRange RR) {
156 ReductionRange = RR;
157 ReductionOp = BO;
158 }
159 void set(const Expr *RefExpr, SourceRange RR) {
160 ReductionRange = RR;
161 ReductionOp = RefExpr;
162 }
163 };
164 using DeclReductionMapTy =
165 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
166 struct DefaultmapInfo {
167 OpenMPDefaultmapClauseModifier ImplicitBehavior =
168 OMPC_DEFAULTMAP_MODIFIER_unknown;
169 SourceLocation SLoc;
170 DefaultmapInfo() = default;
171 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
172 : ImplicitBehavior(M), SLoc(Loc) {}
173 };
174
175 struct SharingMapTy {
176 DeclSAMapTy SharingMap;
177 DeclReductionMapTy ReductionMap;
178 UsedRefMapTy AlignedMap;
179 UsedRefMapTy NontemporalMap;
180 MappedExprComponentsTy MappedExprComponents;
181 LoopControlVariablesMapTy LCVMap;
182 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
183 SourceLocation DefaultAttrLoc;
184 DefaultDataSharingVCAttributes DefaultVCAttr = DSA_VC_all;
185 SourceLocation DefaultAttrVCLoc;
186 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
187 OpenMPDirectiveKind Directive = OMPD_unknown;
188 DeclarationNameInfo DirectiveName;
189 Scope *CurScope = nullptr;
190 DeclContext *Context = nullptr;
191 SourceLocation ConstructLoc;
192 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
193 /// get the data (loop counters etc.) about enclosing loop-based construct.
194 /// This data is required during codegen.
195 DoacrossClauseMapTy DoacrossDepends;
196 /// First argument (Expr *) contains optional argument of the
197 /// 'ordered' clause, the second one is true if the regions has 'ordered'
198 /// clause, false otherwise.
199 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
200 bool RegionHasOrderConcurrent = false;
201 unsigned AssociatedLoops = 1;
202 bool HasMutipleLoops = false;
203 const Decl *PossiblyLoopCounter = nullptr;
204 bool NowaitRegion = false;
205 bool UntiedRegion = false;
206 bool CancelRegion = false;
207 bool LoopStart = false;
208 bool BodyComplete = false;
209 SourceLocation PrevScanLocation;
210 SourceLocation PrevOrderedLocation;
211 SourceLocation InnerTeamsRegionLoc;
212 /// Reference to the taskgroup task_reduction reference expression.
213 Expr *TaskgroupReductionRef = nullptr;
214 llvm::DenseSet<QualType> MappedClassesQualTypes;
215 SmallVector<Expr *, 4> InnerUsedAllocators;
216 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
217 /// List of globals marked as declare target link in this target region
218 /// (isOpenMPTargetExecutionDirective(Directive) == true).
219 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
220 /// List of decls used in inclusive/exclusive clauses of the scan directive.
221 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
222 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
223 UsesAllocatorsDecls;
224 /// Data is required on creating capture fields for implicit
225 /// default first|private clause.
226 struct ImplicitDefaultFDInfoTy {
227 /// Field decl.
228 const FieldDecl *FD = nullptr;
229 /// Nesting stack level
230 size_t StackLevel = 0;
231 /// Capture variable decl.
232 VarDecl *VD = nullptr;
233 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
234 VarDecl *VD)
235 : FD(FD), StackLevel(StackLevel), VD(VD) {}
236 };
237 /// List of captured fields
238 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
239 ImplicitDefaultFirstprivateFDs;
240 Expr *DeclareMapperVar = nullptr;
241 SmallVector<VarDecl *, 16> IteratorVarDecls;
242 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
243 Scope *CurScope, SourceLocation Loc)
244 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
245 ConstructLoc(Loc) {}
246 SharingMapTy() = default;
247 };
248
249 using StackTy = SmallVector<SharingMapTy, 4>;
250
251 /// Stack of used declaration and their data-sharing attributes.
252 DeclSAMapTy Threadprivates;
253 DeclSAMapTy Groupprivates;
254 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
255 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
256 /// true, if check for DSA must be from parent directive, false, if
257 /// from current directive.
258 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
259 Sema &SemaRef;
260 bool ForceCapturing = false;
261 /// true if all the variables in the target executable directives must be
262 /// captured by reference.
263 bool ForceCaptureByReferenceInTargetExecutable = false;
264 CriticalsWithHintsTy Criticals;
265 unsigned IgnoredStackElements = 0;
266
267 /// Iterators over the stack iterate in order from innermost to outermost
268 /// directive.
269 using const_iterator = StackTy::const_reverse_iterator;
270 const_iterator begin() const {
271 return Stack.empty() ? const_iterator()
272 : Stack.back().first.rbegin() + IgnoredStackElements;
273 }
274 const_iterator end() const {
275 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
276 }
277 using iterator = StackTy::reverse_iterator;
278 iterator begin() {
279 return Stack.empty() ? iterator()
280 : Stack.back().first.rbegin() + IgnoredStackElements;
281 }
282 iterator end() {
283 return Stack.empty() ? iterator() : Stack.back().first.rend();
284 }
285
286 // Convenience operations to get at the elements of the stack.
287
288 bool isStackEmpty() const {
289 return Stack.empty() ||
290 Stack.back().second != CurrentNonCapturingFunctionScope ||
291 Stack.back().first.size() <= IgnoredStackElements;
292 }
293 size_t getStackSize() const {
294 return isStackEmpty() ? 0
295 : Stack.back().first.size() - IgnoredStackElements;
296 }
297
298 SharingMapTy *getTopOfStackOrNull() {
299 size_t Size = getStackSize();
300 if (Size == 0)
301 return nullptr;
302 return &Stack.back().first[Size - 1];
303 }
304 const SharingMapTy *getTopOfStackOrNull() const {
305 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
306 }
307 SharingMapTy &getTopOfStack() {
308 assert(!isStackEmpty() && "no current directive");
309 return *getTopOfStackOrNull();
310 }
311 const SharingMapTy &getTopOfStack() const {
312 return const_cast<DSAStackTy &>(*this).getTopOfStack();
313 }
314
315 SharingMapTy *getSecondOnStackOrNull() {
316 size_t Size = getStackSize();
317 if (Size <= 1)
318 return nullptr;
319 return &Stack.back().first[Size - 2];
320 }
321 const SharingMapTy *getSecondOnStackOrNull() const {
322 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
323 }
324
325 /// Get the stack element at a certain level (previously returned by
326 /// \c getNestingLevel).
327 ///
328 /// Note that nesting levels count from outermost to innermost, and this is
329 /// the reverse of our iteration order where new inner levels are pushed at
330 /// the front of the stack.
331 SharingMapTy &getStackElemAtLevel(unsigned Level) {
332 assert(Level < getStackSize() && "no such stack element");
333 return Stack.back().first[Level];
334 }
335 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
336 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
337 }
338
339 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
340
341 /// Checks if the variable is a local for OpenMP region.
342 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
343
344 /// Vector of previously declared requires directives
345 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
346 /// omp_allocator_handle_t type.
347 QualType OMPAllocatorHandleT;
348 /// omp_depend_t type.
349 QualType OMPDependT;
350 /// omp_event_handle_t type.
351 QualType OMPEventHandleT;
352 /// omp_alloctrait_t type.
353 QualType OMPAlloctraitT;
354 /// Expression for the predefined allocators.
355 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
356 nullptr};
357 /// Vector of previously encountered target directives
358 SmallVector<SourceLocation, 2> TargetLocations;
359 SourceLocation AtomicLocation;
360 /// Vector of declare variant construct traits.
361 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
362
363public:
364 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
365
366 /// Sets omp_allocator_handle_t type.
367 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
368 /// Gets omp_allocator_handle_t type.
369 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
370 /// Sets omp_alloctrait_t type.
371 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
372 /// Gets omp_alloctrait_t type.
373 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
374 /// Sets the given default allocator.
375 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
376 Expr *Allocator) {
377 OMPPredefinedAllocators[AllocatorKind] = Allocator;
378 }
379 /// Returns the specified default allocator.
380 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
381 return OMPPredefinedAllocators[AllocatorKind];
382 }
383 /// Sets omp_depend_t type.
384 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
385 /// Gets omp_depend_t type.
386 QualType getOMPDependT() const { return OMPDependT; }
387
388 /// Sets omp_event_handle_t type.
389 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
390 /// Gets omp_event_handle_t type.
391 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
392
393 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
394 OpenMPClauseKind getClauseParsingMode() const {
395 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
396 return ClauseKindMode;
397 }
398 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
399
400 bool isBodyComplete() const {
401 const SharingMapTy *Top = getTopOfStackOrNull();
402 return Top && Top->BodyComplete;
403 }
404 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
405
406 bool isForceVarCapturing() const { return ForceCapturing; }
407 void setForceVarCapturing(bool V) { ForceCapturing = V; }
408
409 void setForceCaptureByReferenceInTargetExecutable(bool V) {
410 ForceCaptureByReferenceInTargetExecutable = V;
411 }
412 bool isForceCaptureByReferenceInTargetExecutable() const {
413 return ForceCaptureByReferenceInTargetExecutable;
414 }
415
416 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
417 Scope *CurScope, SourceLocation Loc) {
418 assert(!IgnoredStackElements &&
419 "cannot change stack while ignoring elements");
420 if (Stack.empty() ||
421 Stack.back().second != CurrentNonCapturingFunctionScope)
422 Stack.emplace_back(Args: StackTy(), Args&: CurrentNonCapturingFunctionScope);
423 Stack.back().first.emplace_back(Args&: DKind, Args: DirName, Args&: CurScope, Args&: Loc);
424 Stack.back().first.back().DefaultAttrLoc = Loc;
425 }
426
427 void pop() {
428 assert(!IgnoredStackElements &&
429 "cannot change stack while ignoring elements");
430 assert(!Stack.back().first.empty() &&
431 "Data-sharing attributes stack is empty!");
432 Stack.back().first.pop_back();
433 }
434
435 /// RAII object to temporarily leave the scope of a directive when we want to
436 /// logically operate in its parent.
437 class ParentDirectiveScope {
438 DSAStackTy &Self;
439 bool Active;
440
441 public:
442 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
443 : Self(Self), Active(false) {
444 if (Activate)
445 enable();
446 }
447 ~ParentDirectiveScope() { disable(); }
448 void disable() {
449 if (Active) {
450 --Self.IgnoredStackElements;
451 Active = false;
452 }
453 }
454 void enable() {
455 if (!Active) {
456 ++Self.IgnoredStackElements;
457 Active = true;
458 }
459 }
460 };
461
462 /// Marks that we're started loop parsing.
463 void loopInit() {
464 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
465 "Expected loop-based directive.");
466 getTopOfStack().LoopStart = true;
467 }
468 /// Start capturing of the variables in the loop context.
469 void loopStart() {
470 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
471 "Expected loop-based directive.");
472 getTopOfStack().LoopStart = false;
473 }
474 /// true, if variables are captured, false otherwise.
475 bool isLoopStarted() const {
476 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
477 "Expected loop-based directive.");
478 return !getTopOfStack().LoopStart;
479 }
480 /// Marks (or clears) declaration as possibly loop counter.
481 void resetPossibleLoopCounter(const Decl *D = nullptr) {
482 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
483 }
484 /// Gets the possible loop counter decl.
485 const Decl *getPossiblyLoopCounter() const {
486 return getTopOfStack().PossiblyLoopCounter;
487 }
488 /// Start new OpenMP region stack in new non-capturing function.
489 void pushFunction() {
490 assert(!IgnoredStackElements &&
491 "cannot change stack while ignoring elements");
492 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
493 assert(!isa<CapturingScopeInfo>(CurFnScope));
494 CurrentNonCapturingFunctionScope = CurFnScope;
495 }
496 /// Pop region stack for non-capturing function.
497 void popFunction(const FunctionScopeInfo *OldFSI) {
498 assert(!IgnoredStackElements &&
499 "cannot change stack while ignoring elements");
500 if (!Stack.empty() && Stack.back().second == OldFSI) {
501 assert(Stack.back().first.empty());
502 Stack.pop_back();
503 }
504 CurrentNonCapturingFunctionScope = nullptr;
505 for (const FunctionScopeInfo *FSI : llvm::reverse(C&: SemaRef.FunctionScopes)) {
506 if (!isa<CapturingScopeInfo>(Val: FSI)) {
507 CurrentNonCapturingFunctionScope = FSI;
508 break;
509 }
510 }
511 }
512
513 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
514 Criticals.try_emplace(Key: D->getDirectiveName().getAsString(), Args&: D, Args&: Hint);
515 }
516 std::pair<const OMPCriticalDirective *, llvm::APSInt>
517 getCriticalWithHint(const DeclarationNameInfo &Name) const {
518 auto I = Criticals.find(Key: Name.getAsString());
519 if (I != Criticals.end())
520 return I->second;
521 return std::make_pair(x: nullptr, y: llvm::APSInt());
522 }
523 /// If 'aligned' declaration for given variable \a D was not seen yet,
524 /// add it and return NULL; otherwise return previous occurrence's expression
525 /// for diagnostics.
526 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
527 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
528 /// add it and return NULL; otherwise return previous occurrence's expression
529 /// for diagnostics.
530 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
531
532 /// Register specified variable as loop control variable.
533 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
534 /// Check if the specified variable is a loop control variable for
535 /// current region.
536 /// \return The index of the loop control variable in the list of associated
537 /// for-loops (from outer to inner).
538 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
539 /// Check if the specified variable is a loop control variable for
540 /// parent 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 isParentLoopControlVariable(const ValueDecl *D) const;
544 /// Check if the specified variable is a loop control variable for
545 /// current 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 isLoopControlVariable(const ValueDecl *D,
549 unsigned Level) const;
550 /// Get the loop control variable for the I-th loop (or nullptr) in
551 /// parent directive.
552 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
553
554 /// Marks the specified decl \p D as used in scan directive.
555 void markDeclAsUsedInScanDirective(ValueDecl *D) {
556 if (SharingMapTy *Stack = getSecondOnStackOrNull())
557 Stack->UsedInScanDirective.insert(V: D);
558 }
559
560 /// Checks if the specified declaration was used in the inner scan directive.
561 bool isUsedInScanDirective(ValueDecl *D) const {
562 if (const SharingMapTy *Stack = getTopOfStackOrNull())
563 return Stack->UsedInScanDirective.contains(V: D);
564 return false;
565 }
566
567 /// Adds explicit data sharing attribute to the specified declaration.
568 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
569 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
570 bool AppliedToPointee = false);
571
572 /// Adds additional information for the reduction items with the reduction id
573 /// represented as an operator.
574 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
575 BinaryOperatorKind BOK);
576 /// Adds additional information for the reduction items with the reduction id
577 /// represented as reduction identifier.
578 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
579 const Expr *ReductionRef);
580 /// Returns the location and reduction operation from the innermost parent
581 /// region for the given \p D.
582 const DSAVarData
583 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
584 BinaryOperatorKind &BOK,
585 Expr *&TaskgroupDescriptor) const;
586 /// Returns the location and reduction operation from the innermost parent
587 /// region for the given \p D.
588 const DSAVarData
589 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
590 const Expr *&ReductionRef,
591 Expr *&TaskgroupDescriptor) const;
592 /// Return reduction reference expression for the current taskgroup or
593 /// parallel/worksharing directives with task reductions.
594 Expr *getTaskgroupReductionRef() const {
595 assert((getTopOfStack().Directive == OMPD_taskgroup ||
596 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
597 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
598 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
599 "taskgroup reference expression requested for non taskgroup or "
600 "parallel/worksharing directive.");
601 return getTopOfStack().TaskgroupReductionRef;
602 }
603 /// Checks if the given \p VD declaration is actually a taskgroup reduction
604 /// descriptor variable at the \p Level of OpenMP regions.
605 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
606 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
607 cast<DeclRefExpr>(Val: getStackElemAtLevel(Level).TaskgroupReductionRef)
608 ->getDecl() == VD;
609 }
610
611 /// Returns data sharing attributes from top of the stack for the
612 /// specified declaration.
613 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
614 /// Returns data-sharing attributes for the specified declaration.
615 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
616 /// Returns data-sharing attributes for the specified declaration.
617 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
618 /// Checks if the specified variables has data-sharing attributes which
619 /// match specified \a CPred predicate in any directive which matches \a DPred
620 /// predicate.
621 const DSAVarData
622 hasDSA(ValueDecl *D,
623 const llvm::function_ref<bool(OpenMPClauseKind, bool,
624 DefaultDataSharingAttributes)>
625 CPred,
626 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
627 bool FromParent) const;
628 /// Checks if the specified variables has data-sharing attributes which
629 /// match specified \a CPred predicate in any innermost directive which
630 /// matches \a DPred predicate.
631 const DSAVarData
632 hasInnermostDSA(ValueDecl *D,
633 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
634 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
635 bool FromParent) const;
636 /// Checks if the specified variables has explicit data-sharing
637 /// attributes which match specified \a CPred predicate at the specified
638 /// OpenMP region.
639 bool
640 hasExplicitDSA(const ValueDecl *D,
641 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
642 unsigned Level, bool NotLastprivate = false) const;
643
644 /// Returns true if the directive at level \Level matches in the
645 /// specified \a DPred predicate.
646 bool hasExplicitDirective(
647 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
648 unsigned Level) const;
649
650 /// Finds a directive which matches specified \a DPred predicate.
651 bool hasDirective(
652 const llvm::function_ref<bool(
653 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
654 DPred,
655 bool FromParent) const;
656
657 /// Returns currently analyzed directive.
658 OpenMPDirectiveKind getCurrentDirective() const {
659 const SharingMapTy *Top = getTopOfStackOrNull();
660 return Top ? Top->Directive : OMPD_unknown;
661 }
662 /// Returns directive kind at specified level.
663 OpenMPDirectiveKind getDirective(unsigned Level) const {
664 assert(!isStackEmpty() && "No directive at specified level.");
665 return getStackElemAtLevel(Level).Directive;
666 }
667 /// Returns the capture region at the specified level.
668 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
669 unsigned OpenMPCaptureLevel) const {
670 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
671 getOpenMPCaptureRegions(CaptureRegions, DKind: getDirective(Level));
672 return CaptureRegions[OpenMPCaptureLevel];
673 }
674 /// Returns parent directive.
675 OpenMPDirectiveKind getParentDirective() const {
676 const SharingMapTy *Parent = getSecondOnStackOrNull();
677 return Parent ? Parent->Directive : OMPD_unknown;
678 }
679
680 /// Add requires decl to internal vector
681 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(Elt: RD); }
682
683 /// Checks if the defined 'requires' directive has specified type of clause.
684 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
685 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
686 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
687 return isa<ClauseType>(C);
688 });
689 });
690 }
691
692 /// Checks for a duplicate clause amongst previously declared requires
693 /// directives
694 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
695 bool IsDuplicate = false;
696 for (OMPClause *CNew : ClauseList) {
697 for (const OMPRequiresDecl *D : RequiresDecls) {
698 for (const OMPClause *CPrev : D->clauselists()) {
699 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
700 SemaRef.Diag(Loc: CNew->getBeginLoc(),
701 DiagID: diag::err_omp_requires_clause_redeclaration)
702 << getOpenMPClauseNameForDiag(C: CNew->getClauseKind());
703 SemaRef.Diag(Loc: CPrev->getBeginLoc(),
704 DiagID: diag::note_omp_requires_previous_clause)
705 << getOpenMPClauseNameForDiag(C: CPrev->getClauseKind());
706 IsDuplicate = true;
707 }
708 }
709 }
710 }
711 return IsDuplicate;
712 }
713
714 /// Add location of previously encountered target to internal vector
715 void addTargetDirLocation(SourceLocation LocStart) {
716 TargetLocations.push_back(Elt: LocStart);
717 }
718
719 /// Add location for the first encountered atomic directive.
720 void addAtomicDirectiveLoc(SourceLocation Loc) {
721 if (AtomicLocation.isInvalid())
722 AtomicLocation = Loc;
723 }
724
725 /// Returns the location of the first encountered atomic directive in the
726 /// module.
727 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
728
729 // Return previously encountered target region locations.
730 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
731 return TargetLocations;
732 }
733
734 /// Set default data sharing attribute to none.
735 void setDefaultDSANone(SourceLocation Loc) {
736 getTopOfStack().DefaultAttr = DSA_none;
737 getTopOfStack().DefaultAttrLoc = Loc;
738 }
739 /// Set default data sharing attribute to shared.
740 void setDefaultDSAShared(SourceLocation Loc) {
741 getTopOfStack().DefaultAttr = DSA_shared;
742 getTopOfStack().DefaultAttrLoc = Loc;
743 }
744 /// Set default data sharing attribute to private.
745 void setDefaultDSAPrivate(SourceLocation Loc) {
746 getTopOfStack().DefaultAttr = DSA_private;
747 getTopOfStack().DefaultAttrLoc = Loc;
748 }
749 /// Set default data sharing attribute to firstprivate.
750 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
751 getTopOfStack().DefaultAttr = DSA_firstprivate;
752 getTopOfStack().DefaultAttrLoc = Loc;
753 }
754 /// Set default data sharing variable category attribute to aggregate.
755 void setDefaultDSAVCAggregate(SourceLocation VCLoc) {
756 getTopOfStack().DefaultVCAttr = DSA_VC_aggregate;
757 getTopOfStack().DefaultAttrVCLoc = VCLoc;
758 }
759 /// Set default data sharing variable category attribute to all.
760 void setDefaultDSAVCAll(SourceLocation VCLoc) {
761 getTopOfStack().DefaultVCAttr = DSA_VC_all;
762 getTopOfStack().DefaultAttrVCLoc = VCLoc;
763 }
764 /// Set default data sharing variable category attribute to pointer.
765 void setDefaultDSAVCPointer(SourceLocation VCLoc) {
766 getTopOfStack().DefaultVCAttr = DSA_VC_pointer;
767 getTopOfStack().DefaultAttrVCLoc = VCLoc;
768 }
769 /// Set default data sharing variable category attribute to scalar.
770 void setDefaultDSAVCScalar(SourceLocation VCLoc) {
771 getTopOfStack().DefaultVCAttr = DSA_VC_scalar;
772 getTopOfStack().DefaultAttrVCLoc = VCLoc;
773 }
774 /// Set default data mapping attribute to Modifier:Kind
775 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
776 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
777 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
778 DMI.ImplicitBehavior = M;
779 DMI.SLoc = Loc;
780 }
781 /// Check whether the implicit-behavior has been set in defaultmap
782 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
783 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
784 return getTopOfStack()
785 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
786 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
787 getTopOfStack()
788 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
789 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
790 getTopOfStack()
791 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
792 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
793 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
794 OMPC_DEFAULTMAP_MODIFIER_unknown;
795 }
796
797 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
798 return ConstructTraits;
799 }
800 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
801 bool ScopeEntry) {
802 if (ScopeEntry)
803 ConstructTraits.append(in_start: Traits.begin(), in_end: Traits.end());
804 else
805 for (llvm::omp::TraitProperty Trait : llvm::reverse(C&: Traits)) {
806 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
807 assert(Top == Trait && "Something left a trait on the stack!");
808 (void)Trait;
809 (void)Top;
810 }
811 }
812
813 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
814 return getStackSize() <= Level ? DSA_unspecified
815 : getStackElemAtLevel(Level).DefaultAttr;
816 }
817 DefaultDataSharingAttributes getDefaultDSA() const {
818 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
819 }
820 SourceLocation getDefaultDSALocation() const {
821 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
822 }
823 OpenMPDefaultmapClauseModifier
824 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
825 return isStackEmpty()
826 ? OMPC_DEFAULTMAP_MODIFIER_unknown
827 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
828 }
829 OpenMPDefaultmapClauseModifier
830 getDefaultmapModifierAtLevel(unsigned Level,
831 OpenMPDefaultmapClauseKind Kind) const {
832 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
833 }
834 bool isDefaultmapCapturedByRef(unsigned Level,
835 OpenMPDefaultmapClauseKind Kind) const {
836 OpenMPDefaultmapClauseModifier M =
837 getDefaultmapModifierAtLevel(Level, Kind);
838 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
839 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
840 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
841 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
842 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
843 (M == OMPC_DEFAULTMAP_MODIFIER_present) ||
844 (M == OMPC_DEFAULTMAP_MODIFIER_storage);
845 }
846 return true;
847 }
848 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
849 OpenMPDefaultmapClauseKind Kind) {
850 switch (Kind) {
851 case OMPC_DEFAULTMAP_scalar:
852 case OMPC_DEFAULTMAP_pointer:
853 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
854 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
855 (M == OMPC_DEFAULTMAP_MODIFIER_default);
856 case OMPC_DEFAULTMAP_aggregate:
857 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
858 default:
859 break;
860 }
861 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
862 }
863 bool mustBeFirstprivateAtLevel(unsigned Level,
864 OpenMPDefaultmapClauseKind Kind) const {
865 OpenMPDefaultmapClauseModifier M =
866 getDefaultmapModifierAtLevel(Level, Kind);
867 return mustBeFirstprivateBase(M, Kind);
868 }
869 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
870 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
871 return mustBeFirstprivateBase(M, Kind);
872 }
873
874 /// Checks if the specified variable is a threadprivate.
875 bool isThreadPrivate(VarDecl *D) {
876 const DSAVarData DVar = getTopDSA(D, FromParent: false);
877 return isOpenMPThreadPrivate(Kind: DVar.CKind);
878 }
879
880 /// Marks current region as ordered (it has an 'ordered' clause).
881 void setOrderedRegion(bool IsOrdered, const Expr *Param,
882 OMPOrderedClause *Clause) {
883 if (IsOrdered)
884 getTopOfStack().OrderedRegion.emplace(args&: Param, args&: Clause);
885 else
886 getTopOfStack().OrderedRegion.reset();
887 }
888 /// Returns true, if region is ordered (has associated 'ordered' clause),
889 /// false - otherwise.
890 bool isOrderedRegion() const {
891 if (const SharingMapTy *Top = getTopOfStackOrNull())
892 return Top->OrderedRegion.has_value();
893 return false;
894 }
895 /// Returns optional parameter for the ordered region.
896 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
897 if (const SharingMapTy *Top = getTopOfStackOrNull())
898 if (Top->OrderedRegion)
899 return *Top->OrderedRegion;
900 return std::make_pair(x: nullptr, y: nullptr);
901 }
902 /// Returns true, if parent region is ordered (has associated
903 /// 'ordered' clause), false - otherwise.
904 bool isParentOrderedRegion() const {
905 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
906 return Parent->OrderedRegion.has_value();
907 return false;
908 }
909 /// Returns optional parameter for the ordered region.
910 std::pair<const Expr *, OMPOrderedClause *>
911 getParentOrderedRegionParam() const {
912 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
913 if (Parent->OrderedRegion)
914 return *Parent->OrderedRegion;
915 return std::make_pair(x: nullptr, y: nullptr);
916 }
917 /// Marks current region as having an 'order' clause.
918 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
919 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
920 }
921 /// Returns true, if parent region is order (has associated
922 /// 'order' clause), false - otherwise.
923 bool isParentOrderConcurrent() const {
924 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
925 return Parent->RegionHasOrderConcurrent;
926 return false;
927 }
928 /// Marks current region as nowait (it has a 'nowait' clause).
929 void setNowaitRegion(bool IsNowait = true) {
930 getTopOfStack().NowaitRegion = IsNowait;
931 }
932 /// Returns true, if parent region is nowait (has associated
933 /// 'nowait' clause), false - otherwise.
934 bool isParentNowaitRegion() const {
935 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
936 return Parent->NowaitRegion;
937 return false;
938 }
939 /// Marks current region as untied (it has a 'untied' clause).
940 void setUntiedRegion(bool IsUntied = true) {
941 getTopOfStack().UntiedRegion = IsUntied;
942 }
943 /// Return true if current region is untied.
944 bool isUntiedRegion() const {
945 const SharingMapTy *Top = getTopOfStackOrNull();
946 return Top ? Top->UntiedRegion : false;
947 }
948 /// Marks parent region as cancel region.
949 void setParentCancelRegion(bool Cancel = true) {
950 if (SharingMapTy *Parent = getSecondOnStackOrNull())
951 Parent->CancelRegion |= Cancel;
952 }
953 /// Return true if current region has inner cancel construct.
954 bool isCancelRegion() const {
955 const SharingMapTy *Top = getTopOfStackOrNull();
956 return Top ? Top->CancelRegion : false;
957 }
958
959 /// Mark that parent region already has scan directive.
960 void setParentHasScanDirective(SourceLocation Loc) {
961 if (SharingMapTy *Parent = getSecondOnStackOrNull())
962 Parent->PrevScanLocation = Loc;
963 }
964 /// Return true if current region has inner cancel construct.
965 bool doesParentHasScanDirective() const {
966 const SharingMapTy *Top = getSecondOnStackOrNull();
967 return Top ? Top->PrevScanLocation.isValid() : false;
968 }
969 /// Return true if current region has inner cancel construct.
970 SourceLocation getParentScanDirectiveLoc() const {
971 const SharingMapTy *Top = getSecondOnStackOrNull();
972 return Top ? Top->PrevScanLocation : SourceLocation();
973 }
974 /// Mark that parent region already has ordered directive.
975 void setParentHasOrderedDirective(SourceLocation Loc) {
976 if (SharingMapTy *Parent = getSecondOnStackOrNull())
977 Parent->PrevOrderedLocation = Loc;
978 }
979 /// Return true if current region has inner ordered construct.
980 bool doesParentHasOrderedDirective() const {
981 const SharingMapTy *Top = getSecondOnStackOrNull();
982 return Top ? Top->PrevOrderedLocation.isValid() : false;
983 }
984 /// Returns the location of the previously specified ordered directive.
985 SourceLocation getParentOrderedDirectiveLoc() const {
986 const SharingMapTy *Top = getSecondOnStackOrNull();
987 return Top ? Top->PrevOrderedLocation : SourceLocation();
988 }
989
990 /// Set collapse value for the region.
991 void setAssociatedLoops(unsigned Val) {
992 getTopOfStack().AssociatedLoops = Val;
993 if (Val > 1)
994 getTopOfStack().HasMutipleLoops = true;
995 }
996 /// Return collapse value for region.
997 unsigned getAssociatedLoops() const {
998 const SharingMapTy *Top = getTopOfStackOrNull();
999 return Top ? Top->AssociatedLoops : 0;
1000 }
1001 /// Returns true if the construct is associated with multiple loops.
1002 bool hasMutipleLoops() const {
1003 const SharingMapTy *Top = getTopOfStackOrNull();
1004 return Top ? Top->HasMutipleLoops : false;
1005 }
1006
1007 /// Marks current target region as one with closely nested teams
1008 /// region.
1009 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
1010 if (SharingMapTy *Parent = getSecondOnStackOrNull())
1011 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
1012 }
1013 /// Returns true, if current region has closely nested teams region.
1014 bool hasInnerTeamsRegion() const {
1015 return getInnerTeamsRegionLoc().isValid();
1016 }
1017 /// Returns location of the nested teams region (if any).
1018 SourceLocation getInnerTeamsRegionLoc() const {
1019 const SharingMapTy *Top = getTopOfStackOrNull();
1020 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1021 }
1022
1023 Scope *getCurScope() const {
1024 const SharingMapTy *Top = getTopOfStackOrNull();
1025 return Top ? Top->CurScope : nullptr;
1026 }
1027 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1028 SourceLocation getConstructLoc() const {
1029 const SharingMapTy *Top = getTopOfStackOrNull();
1030 return Top ? Top->ConstructLoc : SourceLocation();
1031 }
1032
1033 /// Do the check specified in \a Check to all component lists and return true
1034 /// if any issue is found.
1035 bool checkMappableExprComponentListsForDecl(
1036 const ValueDecl *VD, bool CurrentRegionOnly,
1037 const llvm::function_ref<
1038 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1039 OpenMPClauseKind)>
1040 Check) const {
1041 if (isStackEmpty())
1042 return false;
1043 auto SI = begin();
1044 auto SE = end();
1045
1046 if (SI == SE)
1047 return false;
1048
1049 if (CurrentRegionOnly)
1050 SE = std::next(x: SI);
1051 else
1052 std::advance(i&: SI, n: 1);
1053
1054 for (; SI != SE; ++SI) {
1055 auto MI = SI->MappedExprComponents.find(Val: VD);
1056 if (MI != SI->MappedExprComponents.end())
1057 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1058 MI->second.Components)
1059 if (Check(L, MI->second.Kind))
1060 return true;
1061 }
1062 return false;
1063 }
1064
1065 /// Do the check specified in \a Check to all component lists at a given level
1066 /// and return true if any issue is found.
1067 bool checkMappableExprComponentListsForDeclAtLevel(
1068 const ValueDecl *VD, unsigned Level,
1069 const llvm::function_ref<
1070 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1071 OpenMPClauseKind)>
1072 Check) const {
1073 if (getStackSize() <= Level)
1074 return false;
1075
1076 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1077 auto MI = StackElem.MappedExprComponents.find(Val: VD);
1078 if (MI != StackElem.MappedExprComponents.end())
1079 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1080 MI->second.Components)
1081 if (Check(L, MI->second.Kind))
1082 return true;
1083 return false;
1084 }
1085
1086 /// Create a new mappable expression component list associated with a given
1087 /// declaration and initialize it with the provided list of components.
1088 void addMappableExpressionComponents(
1089 const ValueDecl *VD,
1090 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
1091 OpenMPClauseKind WhereFoundClauseKind) {
1092 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1093 // Create new entry and append the new components there.
1094 MEC.Components.resize(N: MEC.Components.size() + 1);
1095 MEC.Components.back().append(in_start: Components.begin(), in_end: Components.end());
1096 MEC.Kind = WhereFoundClauseKind;
1097 }
1098
1099 unsigned getNestingLevel() const {
1100 assert(!isStackEmpty());
1101 return getStackSize() - 1;
1102 }
1103 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1104 SharingMapTy *Parent = getSecondOnStackOrNull();
1105 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1106 Parent->DoacrossDepends.try_emplace(Key: C, Args: OpsOffs);
1107 }
1108 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1109 getDoacrossDependClauses() const {
1110 const SharingMapTy &StackElem = getTopOfStack();
1111 if (isOpenMPWorksharingDirective(DKind: StackElem.Directive)) {
1112 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1113 return llvm::make_range(x: Ref.begin(), y: Ref.end());
1114 }
1115 return llvm::make_range(x: StackElem.DoacrossDepends.end(),
1116 y: StackElem.DoacrossDepends.end());
1117 }
1118
1119 // Store types of classes which have been explicitly mapped
1120 void addMappedClassesQualTypes(QualType QT) {
1121 SharingMapTy &StackElem = getTopOfStack();
1122 StackElem.MappedClassesQualTypes.insert(V: QT);
1123 }
1124
1125 // Return set of mapped classes types
1126 bool isClassPreviouslyMapped(QualType QT) const {
1127 const SharingMapTy &StackElem = getTopOfStack();
1128 return StackElem.MappedClassesQualTypes.contains(V: QT);
1129 }
1130
1131 /// Adds global declare target to the parent target region.
1132 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1133 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1134 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1135 "Expected declare target link global.");
1136 for (auto &Elem : *this) {
1137 if (isOpenMPTargetExecutionDirective(DKind: Elem.Directive)) {
1138 Elem.DeclareTargetLinkVarDecls.push_back(Elt: E);
1139 return;
1140 }
1141 }
1142 }
1143
1144 /// Returns the list of globals with declare target link if current directive
1145 /// is target.
1146 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1147 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1148 "Expected target executable directive.");
1149 return getTopOfStack().DeclareTargetLinkVarDecls;
1150 }
1151
1152 /// Adds list of allocators expressions.
1153 void addInnerAllocatorExpr(Expr *E) {
1154 getTopOfStack().InnerUsedAllocators.push_back(Elt: E);
1155 }
1156 /// Return list of used allocators.
1157 ArrayRef<Expr *> getInnerAllocators() const {
1158 return getTopOfStack().InnerUsedAllocators;
1159 }
1160 /// Marks the declaration as implicitly firstprivate nin the task-based
1161 /// regions.
1162 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1163 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(V: D);
1164 }
1165 /// Checks if the decl is implicitly firstprivate in the task-based region.
1166 bool isImplicitTaskFirstprivate(Decl *D) const {
1167 return getTopOfStack().ImplicitTaskFirstprivates.contains(V: D);
1168 }
1169
1170 /// Marks decl as used in uses_allocators clause as the allocator.
1171 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1172 getTopOfStack().UsesAllocatorsDecls.try_emplace(Key: D, Args&: Kind);
1173 }
1174 /// Checks if specified decl is used in uses allocator clause as the
1175 /// allocator.
1176 std::optional<UsesAllocatorsDeclKind>
1177 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1178 const SharingMapTy &StackElem = getTopOfStack();
1179 auto I = StackElem.UsesAllocatorsDecls.find(Val: D);
1180 if (I == StackElem.UsesAllocatorsDecls.end())
1181 return std::nullopt;
1182 return I->getSecond();
1183 }
1184 std::optional<UsesAllocatorsDeclKind>
1185 isUsesAllocatorsDecl(const Decl *D) const {
1186 const SharingMapTy &StackElem = getTopOfStack();
1187 auto I = StackElem.UsesAllocatorsDecls.find(Val: D);
1188 if (I == StackElem.UsesAllocatorsDecls.end())
1189 return std::nullopt;
1190 return I->getSecond();
1191 }
1192
1193 void addDeclareMapperVarRef(Expr *Ref) {
1194 SharingMapTy &StackElem = getTopOfStack();
1195 StackElem.DeclareMapperVar = Ref;
1196 }
1197 const Expr *getDeclareMapperVarRef() const {
1198 const SharingMapTy *Top = getTopOfStackOrNull();
1199 return Top ? Top->DeclareMapperVar : nullptr;
1200 }
1201
1202 /// Add a new iterator variable.
1203 void addIteratorVarDecl(VarDecl *VD) {
1204 SharingMapTy &StackElem = getTopOfStack();
1205 StackElem.IteratorVarDecls.push_back(Elt: VD->getCanonicalDecl());
1206 }
1207 /// Check if variable declaration is an iterator VarDecl.
1208 bool isIteratorVarDecl(const VarDecl *VD) const {
1209 const SharingMapTy *Top = getTopOfStackOrNull();
1210 if (!Top)
1211 return false;
1212
1213 return llvm::is_contained(Range: Top->IteratorVarDecls, Element: VD->getCanonicalDecl());
1214 }
1215 /// get captured field from ImplicitDefaultFirstprivateFDs
1216 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1217 const_iterator I = begin();
1218 const_iterator EndI = end();
1219 size_t StackLevel = getStackSize();
1220 for (; I != EndI; ++I) {
1221 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1222 break;
1223 StackLevel--;
1224 }
1225 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1226 if (I == EndI)
1227 return nullptr;
1228 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1229 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1230 return IFD.VD;
1231 return nullptr;
1232 }
1233 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1234 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1235 const_iterator I = begin();
1236 const_iterator EndI = end();
1237 for (; I != EndI; ++I)
1238 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1239 break;
1240 if (I == EndI)
1241 return false;
1242 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1243 if (IFD.VD == VD)
1244 return true;
1245 return false;
1246 }
1247 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1248 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1249 iterator I = begin();
1250 const_iterator EndI = end();
1251 size_t StackLevel = getStackSize();
1252 for (; I != EndI; ++I) {
1253 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1254 I->ImplicitDefaultFirstprivateFDs.emplace_back(Args&: FD, Args&: StackLevel, Args&: VD);
1255 break;
1256 }
1257 StackLevel--;
1258 }
1259 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1260 }
1261 void setOrderedToBlockAssociated() {
1262 assert(getCurrentDirective() == OMPD_ordered_standalone);
1263 getTopOfStack().Directive = OMPD_ordered_blockassoc;
1264 }
1265};
1266
1267bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1268 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1269}
1270
1271bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1272 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(Kind: DKind) ||
1273 DKind == OMPD_unknown;
1274}
1275
1276} // namespace
1277
1278static const Expr *getExprAsWritten(const Expr *E) {
1279 if (const auto *FE = dyn_cast<FullExpr>(Val: E))
1280 E = FE->getSubExpr();
1281
1282 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Val: E))
1283 E = MTE->getSubExpr();
1284
1285 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(Val: E))
1286 E = Binder->getSubExpr();
1287
1288 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(Val: E))
1289 E = ICE->getSubExprAsWritten();
1290 return E->IgnoreParens();
1291}
1292
1293static Expr *getExprAsWritten(Expr *E) {
1294 return const_cast<Expr *>(getExprAsWritten(E: const_cast<const Expr *>(E)));
1295}
1296
1297static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1298 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: D))
1299 if (const auto *ME = dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit())))
1300 D = ME->getMemberDecl();
1301
1302 D = cast<ValueDecl>(Val: D->getCanonicalDecl());
1303 return D;
1304}
1305
1306static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1307 return const_cast<ValueDecl *>(
1308 getCanonicalDecl(D: const_cast<const ValueDecl *>(D)));
1309}
1310
1311static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C) {
1312 if (C == OMPC_threadprivate)
1313 return getOpenMPClauseName(C).str() + " or thread local";
1314 return getOpenMPClauseName(C).str();
1315}
1316
1317DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1318 ValueDecl *D) const {
1319 D = getCanonicalDecl(D);
1320 auto *VD = dyn_cast<VarDecl>(Val: D);
1321 const auto *FD = dyn_cast<FieldDecl>(Val: D);
1322 DSAVarData DVar;
1323 if (Iter == end()) {
1324 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1325 // in a region but not in construct]
1326 // File-scope or namespace-scope variables referenced in called routines
1327 // in the region are shared unless they appear in a threadprivate
1328 // directive.
1329 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(Val: VD))
1330 DVar.CKind = OMPC_shared;
1331
1332 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1333 // in a region but not in construct]
1334 // Variables with static storage duration that are declared in called
1335 // routines in the region are shared.
1336 if (VD && VD->hasGlobalStorage())
1337 DVar.CKind = OMPC_shared;
1338
1339 // Non-static data members are shared by default.
1340 if (FD)
1341 DVar.CKind = OMPC_shared;
1342
1343 return DVar;
1344 }
1345
1346 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1347 // in a Construct, C/C++, predetermined, p.1]
1348 // Variables with automatic storage duration that are declared in a scope
1349 // inside the construct are private.
1350 if (VD && isOpenMPLocal(D: VD, Iter) && VD->isLocalVarDecl() &&
1351 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1352 DVar.CKind = OMPC_private;
1353 return DVar;
1354 }
1355
1356 DVar.DKind = Iter->Directive;
1357 // Explicitly specified attributes and local variables with predetermined
1358 // attributes.
1359 if (Iter->SharingMap.count(Val: D)) {
1360 const DSAInfo &Data = Iter->SharingMap.lookup(Val: D);
1361 DVar.RefExpr = Data.RefExpr.getPointer();
1362 DVar.PrivateCopy = Data.PrivateCopy;
1363 DVar.CKind = Data.Attributes;
1364 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1365 DVar.Modifier = Data.Modifier;
1366 DVar.AppliedToPointee = Data.AppliedToPointee;
1367 return DVar;
1368 }
1369
1370 DefaultDataSharingAttributes IterDA = Iter->DefaultAttr;
1371 switch (Iter->DefaultVCAttr) {
1372 case DSA_VC_aggregate:
1373 if (!D->getType()->isAggregateType())
1374 IterDA = DSA_none;
1375 break;
1376 case DSA_VC_pointer:
1377 if (!D->getType()->isPointerType())
1378 IterDA = DSA_none;
1379 break;
1380 case DSA_VC_scalar:
1381 if (!D->getType()->isScalarType())
1382 IterDA = DSA_none;
1383 break;
1384 case DSA_VC_all:
1385 break;
1386 }
1387
1388 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1389 // in a Construct, C/C++, implicitly determined, p.1]
1390 // In a parallel or task construct, the data-sharing attributes of these
1391 // variables are determined by the default clause, if present.
1392 switch (IterDA) {
1393 case DSA_shared:
1394 DVar.CKind = OMPC_shared;
1395 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1396 return DVar;
1397 case DSA_none:
1398 return DVar;
1399 case DSA_firstprivate:
1400 if (VD && VD->getStorageDuration() == SD_Static &&
1401 VD->getDeclContext()->isFileContext()) {
1402 DVar.CKind = OMPC_unknown;
1403 } else {
1404 DVar.CKind = OMPC_firstprivate;
1405 }
1406 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1407 return DVar;
1408 case DSA_private:
1409 // each variable with static storage duration that is declared
1410 // in a namespace or global scope and referenced in the construct,
1411 // and that does not have a predetermined data-sharing attribute
1412 if (VD && VD->getStorageDuration() == SD_Static &&
1413 VD->getDeclContext()->isFileContext()) {
1414 DVar.CKind = OMPC_unknown;
1415 } else {
1416 DVar.CKind = OMPC_private;
1417 }
1418 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1419 return DVar;
1420 case DSA_unspecified:
1421 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1422 // in a Construct, implicitly determined, p.2]
1423 // In a parallel construct, if no default clause is present, these
1424 // variables are shared.
1425 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1426 if ((isOpenMPParallelDirective(DKind: DVar.DKind) &&
1427 !isOpenMPTaskLoopDirective(DKind: DVar.DKind)) ||
1428 isOpenMPTeamsDirective(DKind: DVar.DKind)) {
1429 DVar.CKind = OMPC_shared;
1430 return DVar;
1431 }
1432
1433 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1434 // in a Construct, implicitly determined, p.4]
1435 // In a task construct, if no default clause is present, a variable that in
1436 // the enclosing context is determined to be shared by all implicit tasks
1437 // bound to the current team is shared.
1438 if (isOpenMPTaskingDirective(Kind: DVar.DKind)) {
1439 DSAVarData DVarTemp;
1440 const_iterator I = Iter, E = end();
1441 do {
1442 ++I;
1443 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1444 // Referenced in a Construct, implicitly determined, p.6]
1445 // In a task construct, if no default clause is present, a variable
1446 // whose data-sharing attribute is not determined by the rules above is
1447 // firstprivate.
1448 DVarTemp = getDSA(Iter&: I, D);
1449 if (DVarTemp.CKind != OMPC_shared) {
1450 DVar.RefExpr = nullptr;
1451 DVar.CKind = OMPC_firstprivate;
1452 return DVar;
1453 }
1454 } while (I != E && !isImplicitTaskingRegion(DKind: I->Directive));
1455 DVar.CKind =
1456 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1457 return DVar;
1458 }
1459 }
1460 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1461 // in a Construct, implicitly determined, p.3]
1462 // For constructs other than task, if no default clause is present, these
1463 // variables inherit their data-sharing attributes from the enclosing
1464 // context.
1465 return getDSA(Iter&: ++Iter, D);
1466}
1467
1468const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1469 const Expr *NewDE) {
1470 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1471 D = getCanonicalDecl(D);
1472 SharingMapTy &StackElem = getTopOfStack();
1473 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(Key: D, Args&: NewDE);
1474 if (Inserted) {
1475 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1476 return nullptr;
1477 }
1478 assert(It->second && "Unexpected nullptr expr in the aligned map");
1479 return It->second;
1480}
1481
1482const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1483 const Expr *NewDE) {
1484 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1485 D = getCanonicalDecl(D);
1486 SharingMapTy &StackElem = getTopOfStack();
1487 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(Key: D, Args&: NewDE);
1488 if (Inserted) {
1489 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1490 return nullptr;
1491 }
1492 assert(It->second && "Unexpected nullptr expr in the aligned map");
1493 return It->second;
1494}
1495
1496void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1497 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1498 D = getCanonicalDecl(D);
1499 SharingMapTy &StackElem = getTopOfStack();
1500 StackElem.LCVMap.try_emplace(
1501 Key: D, Args: LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1502}
1503
1504const DSAStackTy::LCDeclInfo
1505DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1506 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1507 D = getCanonicalDecl(D);
1508 const SharingMapTy &StackElem = getTopOfStack();
1509 auto It = StackElem.LCVMap.find(Val: D);
1510 if (It != StackElem.LCVMap.end())
1511 return It->second;
1512 return {0, nullptr};
1513}
1514
1515const DSAStackTy::LCDeclInfo
1516DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1517 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1518 D = getCanonicalDecl(D);
1519 for (unsigned I = Level + 1; I > 0; --I) {
1520 const SharingMapTy &StackElem = getStackElemAtLevel(Level: I - 1);
1521 auto It = StackElem.LCVMap.find(Val: D);
1522 if (It != StackElem.LCVMap.end())
1523 return It->second;
1524 }
1525 return {0, nullptr};
1526}
1527
1528const DSAStackTy::LCDeclInfo
1529DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1530 const SharingMapTy *Parent = getSecondOnStackOrNull();
1531 assert(Parent && "Data-sharing attributes stack is empty");
1532 D = getCanonicalDecl(D);
1533 auto It = Parent->LCVMap.find(Val: D);
1534 if (It != Parent->LCVMap.end())
1535 return It->second;
1536 return {0, nullptr};
1537}
1538
1539const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1540 const SharingMapTy *Parent = getSecondOnStackOrNull();
1541 assert(Parent && "Data-sharing attributes stack is empty");
1542 if (Parent->LCVMap.size() < I)
1543 return nullptr;
1544 for (const auto &Pair : Parent->LCVMap)
1545 if (Pair.second.first == I)
1546 return Pair.first;
1547 return nullptr;
1548}
1549
1550void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1551 DeclRefExpr *PrivateCopy, unsigned Modifier,
1552 bool AppliedToPointee) {
1553 D = getCanonicalDecl(D);
1554 if (A == OMPC_threadprivate) {
1555 DSAInfo &Data = Threadprivates[D];
1556 Data.Attributes = A;
1557 Data.RefExpr.setPointer(E);
1558 Data.PrivateCopy = nullptr;
1559 Data.Modifier = Modifier;
1560 } else if (A == OMPC_groupprivate) {
1561 DSAInfo &Data = Groupprivates[D];
1562 Data.Attributes = A;
1563 Data.RefExpr.setPointer(E);
1564 Data.PrivateCopy = nullptr;
1565 Data.Modifier = Modifier;
1566 } else {
1567 DSAInfo &Data = getTopOfStack().SharingMap[D];
1568 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1569 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1570 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1571 (isLoopControlVariable(D).first && A == OMPC_private));
1572 Data.Modifier = Modifier;
1573 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1574 Data.RefExpr.setInt(/*IntVal=*/true);
1575 return;
1576 }
1577 const bool IsLastprivate =
1578 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1579 Data.Attributes = A;
1580 Data.RefExpr.setPointerAndInt(PtrVal: E, IntVal: IsLastprivate);
1581 Data.PrivateCopy = PrivateCopy;
1582 Data.AppliedToPointee = AppliedToPointee;
1583 if (PrivateCopy) {
1584 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1585 Data.Modifier = Modifier;
1586 Data.Attributes = A;
1587 Data.RefExpr.setPointerAndInt(PtrVal: PrivateCopy, IntVal: IsLastprivate);
1588 Data.PrivateCopy = nullptr;
1589 Data.AppliedToPointee = AppliedToPointee;
1590 }
1591 }
1592}
1593
1594/// Build a variable declaration for OpenMP loop iteration variable.
1595static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
1596 StringRef Name, const AttrVec *Attrs = nullptr,
1597 DeclRefExpr *OrigRef = nullptr) {
1598 DeclContext *DC = SemaRef.CurContext;
1599 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1600 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(T: Type, Loc);
1601 auto *Decl =
1602 VarDecl::Create(C&: SemaRef.Context, DC, StartLoc: Loc, IdLoc: Loc, Id: II, T: Type, TInfo, S: SC_None);
1603 if (Attrs) {
1604 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1605 I != E; ++I)
1606 Decl->addAttr(A: *I);
1607 }
1608 Decl->setImplicit();
1609 if (OrigRef) {
1610 Decl->addAttr(
1611 A: OMPReferencedVarAttr::CreateImplicit(Ctx&: SemaRef.Context, Ref: OrigRef));
1612 }
1613 return Decl;
1614}
1615
1616static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
1617 SourceLocation Loc,
1618 bool RefersToCapture = false) {
1619 D->setReferenced();
1620 D->markUsed(C&: S.Context);
1621 return DeclRefExpr::Create(Context: S.getASTContext(), QualifierLoc: NestedNameSpecifierLoc(),
1622 TemplateKWLoc: SourceLocation(), D, RefersToEnclosingVariableOrCapture: RefersToCapture, NameLoc: Loc, T: Ty,
1623 VK: VK_LValue);
1624}
1625
1626void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1627 BinaryOperatorKind BOK) {
1628 D = getCanonicalDecl(D);
1629 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1630 assert(
1631 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1632 "Additional reduction info may be specified only for reduction items.");
1633 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1634 assert(ReductionData.ReductionRange.isInvalid() &&
1635 (getTopOfStack().Directive == OMPD_taskgroup ||
1636 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1637 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1638 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1639 "Additional reduction info may be specified only once for reduction "
1640 "items.");
1641 ReductionData.set(BO: BOK, RR: SR);
1642 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1643 if (!TaskgroupReductionRef) {
1644 VarDecl *VD = buildVarDecl(SemaRef, Loc: SR.getBegin(),
1645 Type: SemaRef.Context.VoidPtrTy, Name: ".task_red.");
1646 TaskgroupReductionRef =
1647 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: SemaRef.Context.VoidPtrTy, Loc: SR.getBegin());
1648 }
1649}
1650
1651void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1652 const Expr *ReductionRef) {
1653 D = getCanonicalDecl(D);
1654 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1655 assert(
1656 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1657 "Additional reduction info may be specified only for reduction items.");
1658 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1659 assert(ReductionData.ReductionRange.isInvalid() &&
1660 (getTopOfStack().Directive == OMPD_taskgroup ||
1661 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1662 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1663 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1664 "Additional reduction info may be specified only once for reduction "
1665 "items.");
1666 ReductionData.set(RefExpr: ReductionRef, RR: SR);
1667 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1668 if (!TaskgroupReductionRef) {
1669 VarDecl *VD = buildVarDecl(SemaRef, Loc: SR.getBegin(),
1670 Type: SemaRef.Context.VoidPtrTy, Name: ".task_red.");
1671 TaskgroupReductionRef =
1672 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: SemaRef.Context.VoidPtrTy, Loc: SR.getBegin());
1673 }
1674}
1675
1676const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1677 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1678 Expr *&TaskgroupDescriptor) const {
1679 D = getCanonicalDecl(D);
1680 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1681 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1682 const DSAInfo &Data = I->SharingMap.lookup(Val: D);
1683 if (Data.Attributes != OMPC_reduction ||
1684 Data.Modifier != OMPC_REDUCTION_task)
1685 continue;
1686 const ReductionData &ReductionData = I->ReductionMap.lookup(Val: D);
1687 if (!ReductionData.ReductionOp ||
1688 isa<const Expr *>(Val: ReductionData.ReductionOp))
1689 return DSAVarData();
1690 SR = ReductionData.ReductionRange;
1691 BOK = cast<ReductionData::BOKPtrType>(Val: ReductionData.ReductionOp);
1692 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1693 "expression for the descriptor is not "
1694 "set.");
1695 TaskgroupDescriptor = I->TaskgroupReductionRef;
1696 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1697 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1698 /*AppliedToPointee=*/false);
1699 }
1700 return DSAVarData();
1701}
1702
1703const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1704 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1705 Expr *&TaskgroupDescriptor) const {
1706 D = getCanonicalDecl(D);
1707 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1708 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1709 const DSAInfo &Data = I->SharingMap.lookup(Val: D);
1710 if (Data.Attributes != OMPC_reduction ||
1711 Data.Modifier != OMPC_REDUCTION_task)
1712 continue;
1713 const ReductionData &ReductionData = I->ReductionMap.lookup(Val: D);
1714 if (!ReductionData.ReductionOp ||
1715 !isa<const Expr *>(Val: ReductionData.ReductionOp))
1716 return DSAVarData();
1717 SR = ReductionData.ReductionRange;
1718 ReductionRef = cast<const Expr *>(Val: ReductionData.ReductionOp);
1719 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1720 "expression for the descriptor is not "
1721 "set.");
1722 TaskgroupDescriptor = I->TaskgroupReductionRef;
1723 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1724 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1725 /*AppliedToPointee=*/false);
1726 }
1727 return DSAVarData();
1728}
1729
1730bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1731 D = D->getCanonicalDecl();
1732 for (const_iterator E = end(); I != E; ++I) {
1733 if (isImplicitOrExplicitTaskingRegion(DKind: I->Directive) ||
1734 isOpenMPTargetExecutionDirective(DKind: I->Directive)) {
1735 if (I->CurScope) {
1736 Scope *TopScope = I->CurScope->getParent();
1737 Scope *CurScope = getCurScope();
1738 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1739 CurScope = CurScope->getParent();
1740 return CurScope != TopScope;
1741 }
1742 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1743 if (I->Context == DC)
1744 return true;
1745 return false;
1746 }
1747 }
1748 return false;
1749}
1750
1751static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
1752 bool AcceptIfMutable = true,
1753 bool *IsClassType = nullptr) {
1754 ASTContext &Context = SemaRef.getASTContext();
1755 Type = Type.getNonReferenceType().getCanonicalType();
1756 bool IsConstant = Type.isConstant(Ctx: Context);
1757 Type = Context.getBaseElementType(QT: Type);
1758 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1759 ? Type->getAsCXXRecordDecl()
1760 : nullptr;
1761 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(Val: RD))
1762 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1763 RD = CTD->getTemplatedDecl();
1764 if (IsClassType)
1765 *IsClassType = RD;
1766 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1767 RD->hasDefinition() && RD->hasMutableFields());
1768}
1769
1770static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1771 QualType Type, OpenMPClauseKind CKind,
1772 SourceLocation ELoc,
1773 bool AcceptIfMutable = true,
1774 bool ListItemNotVar = false) {
1775 ASTContext &Context = SemaRef.getASTContext();
1776 bool IsClassType;
1777 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, IsClassType: &IsClassType)) {
1778 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1779 : IsClassType ? diag::err_omp_const_not_mutable_variable
1780 : diag::err_omp_const_variable;
1781 SemaRef.Diag(Loc: ELoc, DiagID: Diag) << getOpenMPClauseNameForDiag(C: CKind);
1782 if (!ListItemNotVar && D) {
1783 const VarDecl *VD = dyn_cast<VarDecl>(Val: D);
1784 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1785 VarDecl::DeclarationOnly;
1786 SemaRef.Diag(Loc: D->getLocation(),
1787 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1788 << D;
1789 }
1790 return true;
1791 }
1792 return false;
1793}
1794
1795const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1796 bool FromParent) {
1797 D = getCanonicalDecl(D);
1798 DSAVarData DVar;
1799
1800 auto *VD = dyn_cast<VarDecl>(Val: D);
1801 auto TI = Threadprivates.find(Val: D);
1802 if (TI != Threadprivates.end()) {
1803 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1804 DVar.CKind = OMPC_threadprivate;
1805 DVar.Modifier = TI->getSecond().Modifier;
1806 return DVar;
1807 }
1808 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1809 DVar.RefExpr = buildDeclRefExpr(
1810 S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1811 Loc: VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1812 DVar.CKind = OMPC_threadprivate;
1813 addDSA(D, E: DVar.RefExpr, A: OMPC_threadprivate);
1814 return DVar;
1815 }
1816 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1817 // in a Construct, C/C++, predetermined, p.1]
1818 // Variables appearing in threadprivate directives are threadprivate.
1819 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1820 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1821 SemaRef.getLangOpts().OpenMPUseTLS &&
1822 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1823 (VD && VD->getStorageClass() == SC_Register &&
1824 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1825 DVar.RefExpr = buildDeclRefExpr(
1826 S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(), Loc: D->getLocation());
1827 DVar.CKind = OMPC_threadprivate;
1828 addDSA(D, E: DVar.RefExpr, A: OMPC_threadprivate);
1829 return DVar;
1830 }
1831 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1832 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1833 !isLoopControlVariable(D).first) {
1834 const_iterator IterTarget =
1835 std::find_if(first: begin(), last: end(), pred: [](const SharingMapTy &Data) {
1836 return isOpenMPTargetExecutionDirective(DKind: Data.Directive);
1837 });
1838 if (IterTarget != end()) {
1839 const_iterator ParentIterTarget = IterTarget + 1;
1840 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1841 if (isOpenMPLocal(D: VD, I: Iter)) {
1842 DVar.RefExpr =
1843 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1844 Loc: D->getLocation());
1845 DVar.CKind = OMPC_threadprivate;
1846 return DVar;
1847 }
1848 }
1849 if (!isClauseParsingMode() || IterTarget != begin()) {
1850 auto DSAIter = IterTarget->SharingMap.find(Val: D);
1851 if (DSAIter != IterTarget->SharingMap.end() &&
1852 isOpenMPPrivate(Kind: DSAIter->getSecond().Attributes)) {
1853 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1854 DVar.CKind = OMPC_threadprivate;
1855 return DVar;
1856 }
1857 const_iterator End = end();
1858 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1859 D, Level: std::distance(first: ParentIterTarget, last: End),
1860 /*OpenMPCaptureLevel=*/0)) {
1861 DVar.RefExpr =
1862 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1863 Loc: IterTarget->ConstructLoc);
1864 DVar.CKind = OMPC_threadprivate;
1865 return DVar;
1866 }
1867 }
1868 }
1869 }
1870
1871 if (isStackEmpty())
1872 // Not in OpenMP execution region and top scope was already checked.
1873 return DVar;
1874
1875 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1876 // in a Construct, C/C++, predetermined, p.4]
1877 // Static data members are shared.
1878 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1879 // in a Construct, C/C++, predetermined, p.7]
1880 // Variables with static storage duration that are declared in a scope
1881 // inside the construct are shared.
1882 if (VD && VD->isStaticDataMember()) {
1883 // Check for explicitly specified attributes.
1884 const_iterator I = begin();
1885 const_iterator EndI = end();
1886 if (FromParent && I != EndI)
1887 ++I;
1888 if (I != EndI) {
1889 auto It = I->SharingMap.find(Val: D);
1890 if (It != I->SharingMap.end()) {
1891 const DSAInfo &Data = It->getSecond();
1892 DVar.RefExpr = Data.RefExpr.getPointer();
1893 DVar.PrivateCopy = Data.PrivateCopy;
1894 DVar.CKind = Data.Attributes;
1895 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1896 DVar.DKind = I->Directive;
1897 DVar.Modifier = Data.Modifier;
1898 DVar.AppliedToPointee = Data.AppliedToPointee;
1899 return DVar;
1900 }
1901 }
1902
1903 DVar.CKind = OMPC_shared;
1904 return DVar;
1905 }
1906
1907 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1908 // The predetermined shared attribute for const-qualified types having no
1909 // mutable members was removed after OpenMP 3.1.
1910 if (SemaRef.LangOpts.OpenMP <= 31) {
1911 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1912 // in a Construct, C/C++, predetermined, p.6]
1913 // Variables with const qualified type having no mutable member are
1914 // shared.
1915 if (isConstNotMutableType(SemaRef, Type: D->getType())) {
1916 // Variables with const-qualified type having no mutable member may be
1917 // listed in a firstprivate clause, even if they are static data members.
1918 DSAVarData DVarTemp = hasInnermostDSA(
1919 D,
1920 CPred: [](OpenMPClauseKind C, bool) {
1921 return C == OMPC_firstprivate || C == OMPC_shared;
1922 },
1923 DPred: MatchesAlways, FromParent);
1924 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1925 return DVarTemp;
1926
1927 DVar.CKind = OMPC_shared;
1928 return DVar;
1929 }
1930 }
1931
1932 // Explicitly specified attributes and local variables with predetermined
1933 // attributes.
1934 const_iterator I = begin();
1935 const_iterator EndI = end();
1936 if (FromParent && I != EndI)
1937 ++I;
1938 if (I == EndI)
1939 return DVar;
1940 auto It = I->SharingMap.find(Val: D);
1941 if (It != I->SharingMap.end()) {
1942 const DSAInfo &Data = It->getSecond();
1943 DVar.RefExpr = Data.RefExpr.getPointer();
1944 DVar.PrivateCopy = Data.PrivateCopy;
1945 DVar.CKind = Data.Attributes;
1946 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1947 DVar.DKind = I->Directive;
1948 DVar.Modifier = Data.Modifier;
1949 DVar.AppliedToPointee = Data.AppliedToPointee;
1950 }
1951
1952 return DVar;
1953}
1954
1955const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1956 bool FromParent) const {
1957 if (isStackEmpty()) {
1958 const_iterator I;
1959 return getDSA(Iter&: I, D);
1960 }
1961 D = getCanonicalDecl(D);
1962 const_iterator StartI = begin();
1963 const_iterator EndI = end();
1964 if (FromParent && StartI != EndI)
1965 ++StartI;
1966 return getDSA(Iter&: StartI, D);
1967}
1968
1969const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1970 unsigned Level) const {
1971 if (getStackSize() <= Level)
1972 return DSAVarData();
1973 D = getCanonicalDecl(D);
1974 const_iterator StartI = std::next(x: begin(), n: getStackSize() - 1 - Level);
1975 return getDSA(Iter&: StartI, D);
1976}
1977
1978const DSAStackTy::DSAVarData
1979DSAStackTy::hasDSA(ValueDecl *D,
1980 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1981 DefaultDataSharingAttributes)>
1982 CPred,
1983 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1984 bool FromParent) const {
1985 if (isStackEmpty())
1986 return {};
1987 D = getCanonicalDecl(D);
1988 const_iterator I = begin();
1989 const_iterator EndI = end();
1990 if (FromParent && I != EndI)
1991 ++I;
1992 for (; I != EndI; ++I) {
1993 if (!DPred(I->Directive) &&
1994 !isImplicitOrExplicitTaskingRegion(DKind: I->Directive))
1995 continue;
1996 const_iterator NewI = I;
1997 DSAVarData DVar = getDSA(Iter&: NewI, D);
1998 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1999 return DVar;
2000 }
2001 return {};
2002}
2003
2004const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
2005 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2006 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2007 bool FromParent) const {
2008 if (isStackEmpty())
2009 return {};
2010 D = getCanonicalDecl(D);
2011 const_iterator StartI = begin();
2012 const_iterator EndI = end();
2013 if (FromParent && StartI != EndI)
2014 ++StartI;
2015 if (StartI == EndI || !DPred(StartI->Directive))
2016 return {};
2017 const_iterator NewI = StartI;
2018 DSAVarData DVar = getDSA(Iter&: NewI, D);
2019 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
2020 ? DVar
2021 : DSAVarData();
2022}
2023
2024bool DSAStackTy::hasExplicitDSA(
2025 const ValueDecl *D,
2026 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2027 unsigned Level, bool NotLastprivate) const {
2028 if (getStackSize() <= Level)
2029 return false;
2030 D = getCanonicalDecl(D);
2031 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2032 auto I = StackElem.SharingMap.find(Val: D);
2033 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
2034 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
2035 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
2036 return true;
2037 // Check predetermined rules for the loop control variables.
2038 auto LI = StackElem.LCVMap.find(Val: D);
2039 if (LI != StackElem.LCVMap.end())
2040 return CPred(OMPC_private, /*AppliedToPointee=*/false);
2041 return false;
2042}
2043
2044bool DSAStackTy::hasExplicitDirective(
2045 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2046 unsigned Level) const {
2047 if (getStackSize() <= Level)
2048 return false;
2049 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2050 return DPred(StackElem.Directive);
2051}
2052
2053bool DSAStackTy::hasDirective(
2054 const llvm::function_ref<bool(OpenMPDirectiveKind,
2055 const DeclarationNameInfo &, SourceLocation)>
2056 DPred,
2057 bool FromParent) const {
2058 // We look only in the enclosing region.
2059 size_t Skip = FromParent ? 2 : 1;
2060 for (const_iterator I = begin() + std::min(a: Skip, b: getStackSize()), E = end();
2061 I != E; ++I) {
2062 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2063 return true;
2064 }
2065 return false;
2066}
2067
2068void SemaOpenMP::InitDataSharingAttributesStack() {
2069 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2070}
2071
2072#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2073
2074void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2075
2076void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2077 DSAStack->popFunction(OldFSI);
2078}
2079
2080static bool isOpenMPDeviceDelayedContext(Sema &S) {
2081 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2082 "Expected OpenMP device compilation.");
2083 return !S.OpenMP().isInOpenMPTargetExecutionDirective();
2084}
2085
2086namespace {
2087/// Status of the function emission on the host/device.
2088enum class FunctionEmissionStatus {
2089 Emitted,
2090 Discarded,
2091 Unknown,
2092};
2093} // anonymous namespace
2094
2095SemaBase::SemaDiagnosticBuilder
2096SemaOpenMP::diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID,
2097 const FunctionDecl *FD) {
2098 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2099 "Expected OpenMP device compilation.");
2100
2101 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2102 if (FD) {
2103 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(Decl: FD);
2104 switch (FES) {
2105 case Sema::FunctionEmissionStatus::Emitted:
2106 Kind = SemaDiagnosticBuilder::K_Immediate;
2107 break;
2108 case Sema::FunctionEmissionStatus::Unknown:
2109 // TODO: We should always delay diagnostics here in case a target
2110 // region is in a function we do not emit. However, as the
2111 // current diagnostics are associated with the function containing
2112 // the target region and we do not emit that one, we would miss out
2113 // on diagnostics for the target region itself. We need to anchor
2114 // the diagnostics with the new generated function *or* ensure we
2115 // emit diagnostics associated with the surrounding function.
2116 Kind = isOpenMPDeviceDelayedContext(S&: SemaRef)
2117 ? SemaDiagnosticBuilder::K_Deferred
2118 : SemaDiagnosticBuilder::K_Immediate;
2119 break;
2120 case Sema::FunctionEmissionStatus::TemplateDiscarded:
2121 case Sema::FunctionEmissionStatus::OMPDiscarded:
2122 Kind = SemaDiagnosticBuilder::K_Nop;
2123 break;
2124 case Sema::FunctionEmissionStatus::CUDADiscarded:
2125 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2126 break;
2127 }
2128 }
2129
2130 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2131}
2132
2133SemaBase::SemaDiagnosticBuilder
2134SemaOpenMP::diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID,
2135 const FunctionDecl *FD) {
2136 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2137 "Expected OpenMP host compilation.");
2138
2139 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2140 if (FD) {
2141 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(Decl: FD);
2142 switch (FES) {
2143 case Sema::FunctionEmissionStatus::Emitted:
2144 Kind = SemaDiagnosticBuilder::K_Immediate;
2145 break;
2146 case Sema::FunctionEmissionStatus::Unknown:
2147 Kind = SemaDiagnosticBuilder::K_Deferred;
2148 break;
2149 case Sema::FunctionEmissionStatus::TemplateDiscarded:
2150 case Sema::FunctionEmissionStatus::OMPDiscarded:
2151 case Sema::FunctionEmissionStatus::CUDADiscarded:
2152 Kind = SemaDiagnosticBuilder::K_Nop;
2153 break;
2154 }
2155 }
2156
2157 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2158}
2159
2160static OpenMPDefaultmapClauseKind
2161getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) {
2162 if (LO.OpenMP <= 45) {
2163 if (VD->getType().getNonReferenceType()->isScalarType())
2164 return OMPC_DEFAULTMAP_scalar;
2165 return OMPC_DEFAULTMAP_aggregate;
2166 }
2167 if (VD->getType().getNonReferenceType()->isAnyPointerType())
2168 return OMPC_DEFAULTMAP_pointer;
2169 if (VD->getType().getNonReferenceType()->isScalarType())
2170 return OMPC_DEFAULTMAP_scalar;
2171 return OMPC_DEFAULTMAP_aggregate;
2172}
2173
2174bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2175 unsigned OpenMPCaptureLevel) const {
2176 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2177
2178 ASTContext &Ctx = getASTContext();
2179 bool IsByRef = true;
2180
2181 // Find the directive that is associated with the provided scope.
2182 D = cast<ValueDecl>(Val: D->getCanonicalDecl());
2183 QualType Ty = D->getType();
2184
2185 bool IsVariableUsedInMapClause = false;
2186 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective, Level)) {
2187 // This table summarizes how a given variable should be passed to the device
2188 // given its type and the clauses where it appears. This table is based on
2189 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2190 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2191 //
2192 // =========================================================================
2193 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2194 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2195 // =========================================================================
2196 // | scl | | | | - | | bycopy|
2197 // | scl | | - | x | - | - | bycopy|
2198 // | scl | | x | - | - | - | null |
2199 // | scl | x | | | - | | byref |
2200 // | scl | x | - | x | - | - | bycopy|
2201 // | scl | x | x | - | - | - | null |
2202 // | scl | | - | - | - | x | byref |
2203 // | scl | x | - | - | - | x | byref |
2204 //
2205 // | agg | n.a. | | | - | | byref |
2206 // | agg | n.a. | - | x | - | - | byref |
2207 // | agg | n.a. | x | - | - | - | null |
2208 // | agg | n.a. | - | - | - | x | byref |
2209 // | agg | n.a. | - | - | - | x[] | byref |
2210 //
2211 // | ptr | n.a. | | | - | | bycopy|
2212 // | ptr | n.a. | - | x | - | - | bycopy|
2213 // | ptr | n.a. | x | - | - | - | null |
2214 // | ptr | n.a. | - | - | - | x | byref |
2215 // | ptr | n.a. | - | - | - | x, x[] | bycopy|
2216 // | ptr | n.a. | - | - | - | x[] | bycopy|
2217 // | ptr | n.a. | - | - | x | | bycopy|
2218 // | ptr | n.a. | - | - | x | x | bycopy|
2219 // | ptr | n.a. | - | - | x | x[] | bycopy|
2220 // =========================================================================
2221 // Legend:
2222 // scl - scalar
2223 // ptr - pointer
2224 // agg - aggregate
2225 // x - applies
2226 // - - invalid in this combination
2227 // [] - mapped with an array section
2228 // byref - should be mapped by reference
2229 // byval - should be mapped by value
2230 // null - initialize a local variable to null on the device
2231 //
2232 // Observations:
2233 // - All scalar declarations that show up in a map clause have to be passed
2234 // by reference, because they may have been mapped in the enclosing data
2235 // environment.
2236 // - If the scalar value does not fit the size of uintptr, it has to be
2237 // passed by reference, regardless the result in the table above.
2238 // - For pointers mapped by value that have either an implicit map or an
2239 // array section, the runtime library may pass the NULL value to the
2240 // device instead of the value passed to it by the compiler.
2241 // - If both a pointer and a dereference of it are mapped, then the pointer
2242 // should be passed by reference.
2243
2244 if (Ty->isReferenceType())
2245 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2246
2247 // Locate map clauses and see if the variable being captured is mapped by
2248 // itself, or referred to, in any of those clauses. Here we only care about
2249 // variables, not fields, because fields are part of aggregates.
2250 bool IsVariableAssociatedWithSection = false;
2251 bool IsVariableItselfMapped = false;
2252
2253 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2254 VD: D, Level,
2255 Check: [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2256 &IsVariableItselfMapped,
2257 D](OMPClauseMappableExprCommon::MappableExprComponentListRef
2258 MapExprComponents,
2259 OpenMPClauseKind WhereFoundClauseKind) {
2260 // Both map and has_device_addr clauses information influences how a
2261 // variable is captured. E.g. is_device_ptr does not require changing
2262 // the default behavior.
2263 if (WhereFoundClauseKind != OMPC_map &&
2264 WhereFoundClauseKind != OMPC_has_device_addr)
2265 return false;
2266
2267 auto EI = MapExprComponents.rbegin();
2268 auto EE = MapExprComponents.rend();
2269
2270 assert(EI != EE && "Invalid map expression!");
2271
2272 if (isa<DeclRefExpr>(Val: EI->getAssociatedExpression()) &&
2273 EI->getAssociatedDeclaration() == D) {
2274 IsVariableUsedInMapClause = true;
2275
2276 // If the component list has only one element, it's for mapping the
2277 // variable itself, like map(p). This takes precedence in
2278 // determining how it's captured, so we don't need to look further
2279 // for any other maps that use the variable (like map(p[0]) etc.)
2280 if (MapExprComponents.size() == 1) {
2281 IsVariableItselfMapped = true;
2282 return true;
2283 }
2284 }
2285
2286 ++EI;
2287 if (EI == EE)
2288 return false;
2289 auto Last = std::prev(x: EE);
2290 const auto *UO =
2291 dyn_cast<UnaryOperator>(Val: Last->getAssociatedExpression());
2292 if ((UO && UO->getOpcode() == UO_Deref) ||
2293 isa<ArraySubscriptExpr>(Val: Last->getAssociatedExpression()) ||
2294 isa<ArraySectionExpr>(Val: Last->getAssociatedExpression()) ||
2295 isa<MemberExpr>(Val: EI->getAssociatedExpression()) ||
2296 isa<OMPArrayShapingExpr>(Val: Last->getAssociatedExpression())) {
2297 IsVariableAssociatedWithSection = true;
2298 // We've found a case like map(p[0]) or map(p->a) or map(*p),
2299 // so we are done with this particular map, but we need to keep
2300 // looking in case we find a map(p).
2301 return false;
2302 }
2303
2304 // Keep looking for more map info.
2305 return false;
2306 });
2307
2308 if (IsVariableUsedInMapClause) {
2309 // If variable is identified in a map clause it is always captured by
2310 // reference except if it is a pointer that is dereferenced somehow, but
2311 // not itself mapped.
2312 //
2313 // OpenMP 6.0, 7.1.1: Data sharing attribute rules, variables referenced
2314 // in a construct::
2315 // If a list item in a has_device_addr clause or in a map clause on the
2316 // target construct has a base pointer, and the base pointer is a scalar
2317 // variable *that is not a list item in a map clause on the construct*,
2318 // the base pointer is firstprivate.
2319 //
2320 // OpenMP 4.5, 2.15.1.1: Data-sharing Attribute Rules for Variables
2321 // Referenced in a Construct:
2322 // If an array section is a list item in a map clause on the target
2323 // construct and the array section is derived from a variable for which
2324 // the type is pointer then that variable is firstprivate.
2325 IsByRef = IsVariableItselfMapped ||
2326 !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2327 } else {
2328 // By default, all the data that has a scalar type is mapped by copy
2329 // (except for reduction variables).
2330 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2331 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2332 !Ty->isAnyPointerType()) ||
2333 !Ty->isScalarType() ||
2334 DSAStack->isDefaultmapCapturedByRef(
2335 Level, Kind: getVariableCategoryFromDecl(LO: getLangOpts(), VD: D)) ||
2336 DSAStack->hasExplicitDSA(
2337 D,
2338 CPred: [](OpenMPClauseKind K, bool AppliedToPointee) {
2339 return K == OMPC_reduction && !AppliedToPointee;
2340 },
2341 Level);
2342 }
2343 }
2344
2345 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2346 IsByRef =
2347 ((IsVariableUsedInMapClause &&
2348 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2349 OMPD_target) ||
2350 !(DSAStack->hasExplicitDSA(
2351 D,
2352 CPred: [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2353 return K == OMPC_firstprivate ||
2354 (K == OMPC_reduction && AppliedToPointee);
2355 },
2356 Level, /*NotLastprivate=*/true) ||
2357 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2358 // If the variable is artificial and must be captured by value - try to
2359 // capture by value.
2360 !(isa<OMPCapturedExprDecl>(Val: D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2361 !cast<OMPCapturedExprDecl>(Val: D)->getInit()->isGLValue()) &&
2362 // If the variable is implicitly firstprivate and scalar - capture by
2363 // copy
2364 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2365 DSAStack->getDefaultDSA() == DSA_private) &&
2366 !DSAStack->hasExplicitDSA(
2367 D, CPred: [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2368 Level) &&
2369 !DSAStack->isLoopControlVariable(D, Level).first);
2370 }
2371
2372 // When passing data by copy, we need to make sure it fits the uintptr size
2373 // and alignment, because the runtime library only deals with uintptr types.
2374 // If it does not fit the uintptr size, we need to pass the data by reference
2375 // instead.
2376 if (!IsByRef && (Ctx.getTypeSizeInChars(T: Ty) >
2377 Ctx.getTypeSizeInChars(T: Ctx.getUIntPtrType()) ||
2378 Ctx.getAlignOfGlobalVarInChars(T: Ty, VD: dyn_cast<VarDecl>(Val: D)) >
2379 Ctx.getTypeAlignInChars(T: Ctx.getUIntPtrType()))) {
2380 IsByRef = true;
2381 }
2382
2383 return IsByRef;
2384}
2385
2386unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2387 assert(getLangOpts().OpenMP);
2388 return DSAStack->getNestingLevel();
2389}
2390
2391bool SemaOpenMP::isInOpenMPTaskUntiedContext() const {
2392 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2393 DSAStack->isUntiedRegion();
2394}
2395
2396bool SemaOpenMP::isInOpenMPTargetExecutionDirective() const {
2397 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2398 !DSAStack->isClauseParsingMode()) ||
2399 DSAStack->hasDirective(
2400 DPred: [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2401 SourceLocation) -> bool {
2402 return isOpenMPTargetExecutionDirective(DKind: K);
2403 },
2404 FromParent: false);
2405}
2406
2407bool SemaOpenMP::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2408 // Only rebuild for Field.
2409 if (!isa<FieldDecl>(Val: D))
2410 return false;
2411 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2412 D,
2413 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2414 DefaultDataSharingAttributes DefaultAttr) {
2415 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2416 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2417 },
2418 DPred: [](OpenMPDirectiveKind) { return true; },
2419 DSAStack->isClauseParsingMode());
2420 if (DVarPrivate.CKind != OMPC_unknown)
2421 return true;
2422 return false;
2423}
2424
2425static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
2426 Expr *CaptureExpr, bool WithInit,
2427 DeclContext *CurContext,
2428 bool AsExpression);
2429
2430VarDecl *SemaOpenMP::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2431 unsigned StopAt) {
2432 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2433 D = getCanonicalDecl(D);
2434
2435 auto *VD = dyn_cast<VarDecl>(Val: D);
2436 // Do not capture constexpr variables.
2437 if (VD && VD->isConstexpr())
2438 return nullptr;
2439
2440 // If we want to determine whether the variable should be captured from the
2441 // perspective of the current capturing scope, and we've already left all the
2442 // capturing scopes of the top directive on the stack, check from the
2443 // perspective of its parent directive (if any) instead.
2444 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2445 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2446
2447 // If we are attempting to capture a global variable in a directive with
2448 // 'target' we return true so that this global is also mapped to the device.
2449 //
2450 if (VD && !VD->hasLocalStorage() &&
2451 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2452 SemaRef.getCurLambda())) {
2453 if (isInOpenMPTargetExecutionDirective()) {
2454 DSAStackTy::DSAVarData DVarTop =
2455 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2456 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2457 return VD;
2458 // If the declaration is enclosed in a 'declare target' directive,
2459 // then it should not be captured.
2460 //
2461 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2462 return nullptr;
2463 CapturedRegionScopeInfo *CSI = nullptr;
2464 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2465 RangeOrContainer: llvm::reverse(C&: SemaRef.FunctionScopes),
2466 N: CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2467 : 0)) {
2468 if (!isa<CapturingScopeInfo>(Val: FSI))
2469 return nullptr;
2470 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(Val: FSI))
2471 if (RSI->CapRegionKind == CR_OpenMP) {
2472 CSI = RSI;
2473 break;
2474 }
2475 }
2476 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2477 SmallVector<OpenMPDirectiveKind, 4> Regions;
2478 getOpenMPCaptureRegions(CaptureRegions&: Regions,
2479 DSAStack->getDirective(Level: CSI->OpenMPLevel));
2480 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2481 return VD;
2482 }
2483 if (isInOpenMPDeclareTargetContext()) {
2484 // Try to mark variable as declare target if it is used in capturing
2485 // regions.
2486 if (getLangOpts().OpenMP <= 45 &&
2487 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2488 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: VD);
2489 return nullptr;
2490 }
2491 }
2492
2493 if (CheckScopeInfo) {
2494 bool OpenMPFound = false;
2495 for (unsigned I = StopAt + 1; I > 0; --I) {
2496 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2497 if (!isa<CapturingScopeInfo>(Val: FSI))
2498 return nullptr;
2499 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(Val: FSI))
2500 if (RSI->CapRegionKind == CR_OpenMP) {
2501 OpenMPFound = true;
2502 break;
2503 }
2504 }
2505 if (!OpenMPFound)
2506 return nullptr;
2507 }
2508
2509 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2510 (!DSAStack->isClauseParsingMode() ||
2511 DSAStack->getParentDirective() != OMPD_unknown)) {
2512 auto &&Info = DSAStack->isLoopControlVariable(D);
2513 if (Info.first ||
2514 (VD && VD->hasLocalStorage() &&
2515 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2516 (VD && DSAStack->isForceVarCapturing()))
2517 return VD ? VD : Info.second;
2518 DSAStackTy::DSAVarData DVarTop =
2519 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2520 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(Kind: DVarTop.CKind) &&
2521 (!VD || VD->hasLocalStorage() ||
2522 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2523 return VD ? VD : cast<VarDecl>(Val: DVarTop.PrivateCopy->getDecl());
2524 // Threadprivate variables must not be captured.
2525 if (isOpenMPThreadPrivate(Kind: DVarTop.CKind))
2526 return nullptr;
2527 // The variable is not private or it is the variable in the directive with
2528 // default(none) clause and not used in any clause.
2529 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2530 D,
2531 CPred: [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2532 return isOpenMPPrivate(Kind: C) && !AppliedToPointee;
2533 },
2534 DPred: [](OpenMPDirectiveKind) { return true; },
2535 DSAStack->isClauseParsingMode());
2536 // Global shared must not be captured.
2537 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2538 ((DSAStack->getDefaultDSA() != DSA_none &&
2539 DSAStack->getDefaultDSA() != DSA_private &&
2540 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2541 DVarTop.CKind == OMPC_shared))
2542 return nullptr;
2543 auto *FD = dyn_cast<FieldDecl>(Val: D);
2544 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2545 !DVarPrivate.PrivateCopy) {
2546 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2547 D,
2548 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2549 DefaultDataSharingAttributes DefaultAttr) {
2550 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2551 (DefaultAttr == DSA_firstprivate ||
2552 DefaultAttr == DSA_private);
2553 },
2554 DPred: [](OpenMPDirectiveKind) { return true; },
2555 DSAStack->isClauseParsingMode());
2556 if (DVarPrivate.CKind == OMPC_unknown)
2557 return nullptr;
2558
2559 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2560 if (VD)
2561 return VD;
2562 if (SemaRef.getCurrentThisType().isNull())
2563 return nullptr;
2564 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(Loc: SourceLocation(),
2565 Type: SemaRef.getCurrentThisType(),
2566 /*IsImplicit=*/true);
2567 const CXXScopeSpec CS = CXXScopeSpec();
2568 Expr *ME = SemaRef.BuildMemberExpr(
2569 Base: ThisExpr, /*IsArrow=*/true, OpLoc: SourceLocation(),
2570 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: FD,
2571 FoundDecl: DeclAccessPair::make(D: FD, AS: FD->getAccess()),
2572 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(), Ty: FD->getType(),
2573 VK: VK_LValue, OK: OK_Ordinary);
2574 OMPCapturedExprDecl *CD = buildCaptureDecl(
2575 S&: SemaRef, Id: FD->getIdentifier(), CaptureExpr: ME, WithInit: DVarPrivate.CKind != OMPC_private,
2576 CurContext: SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2577 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2578 S&: SemaRef, D: CD, Ty: CD->getType().getNonReferenceType(), Loc: SourceLocation());
2579 VD = cast<VarDecl>(Val: VDPrivateRefExpr->getDecl());
2580 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2581 return VD;
2582 }
2583 if (DVarPrivate.CKind != OMPC_unknown ||
2584 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2585 DSAStack->getDefaultDSA() == DSA_private ||
2586 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2587 return VD ? VD : cast<VarDecl>(Val: DVarPrivate.PrivateCopy->getDecl());
2588 }
2589 return nullptr;
2590}
2591
2592void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2593 unsigned Level) const {
2594 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2595}
2596
2597void SemaOpenMP::startOpenMPLoop() {
2598 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2599 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2600 DSAStack->loopInit();
2601}
2602
2603void SemaOpenMP::startOpenMPCXXRangeFor() {
2604 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2605 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2606 DSAStack->resetPossibleLoopCounter();
2607 DSAStack->loopStart();
2608 }
2609}
2610
2611OpenMPClauseKind SemaOpenMP::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2612 unsigned CapLevel) const {
2613 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2614 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2615 (!DSAStack->isClauseParsingMode() ||
2616 DSAStack->getParentDirective() != OMPD_unknown)) {
2617 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2618 D,
2619 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2620 DefaultDataSharingAttributes DefaultAttr) {
2621 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2622 DefaultAttr == DSA_private;
2623 },
2624 DPred: [](OpenMPDirectiveKind) { return true; },
2625 DSAStack->isClauseParsingMode());
2626 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(Val: D) &&
2627 DSAStack->isImplicitDefaultFirstprivateFD(VD: cast<VarDecl>(Val: D)) &&
2628 !DSAStack->isLoopControlVariable(D).first)
2629 return OMPC_private;
2630 }
2631 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTaskingDirective, Level)) {
2632 bool IsTriviallyCopyable =
2633 D->getType().getNonReferenceType().isTriviallyCopyableType(
2634 Context: getASTContext()) &&
2635 !D->getType()
2636 .getNonReferenceType()
2637 .getCanonicalType()
2638 ->getAsCXXRecordDecl();
2639 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2640 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2641 getOpenMPCaptureRegions(CaptureRegions, DKind);
2642 if (isOpenMPTaskingDirective(Kind: CaptureRegions[CapLevel]) &&
2643 (IsTriviallyCopyable ||
2644 !isOpenMPTaskLoopDirective(DKind: CaptureRegions[CapLevel]))) {
2645 if (DSAStack->hasExplicitDSA(
2646 D,
2647 CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2648 Level, /*NotLastprivate=*/true))
2649 return OMPC_firstprivate;
2650 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2651 if (DVar.CKind != OMPC_shared &&
2652 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2653 DSAStack->addImplicitTaskFirstprivate(Level, D);
2654 return OMPC_firstprivate;
2655 }
2656 }
2657 }
2658 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2659 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2660 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2661 DSAStack->resetPossibleLoopCounter(D);
2662 DSAStack->loopStart();
2663 return OMPC_private;
2664 }
2665 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2666 DSAStack->isLoopControlVariable(D).first) &&
2667 !DSAStack->hasExplicitDSA(
2668 D, CPred: [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2669 Level) &&
2670 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2671 return OMPC_private;
2672 }
2673 if (const auto *VD = dyn_cast<VarDecl>(Val: D)) {
2674 if (DSAStack->isThreadPrivate(D: const_cast<VarDecl *>(VD)) &&
2675 DSAStack->isForceVarCapturing() &&
2676 !DSAStack->hasExplicitDSA(
2677 D, CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2678 Level))
2679 return OMPC_private;
2680 }
2681 // User-defined allocators are private since they must be defined in the
2682 // context of target region.
2683 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective, Level) &&
2684 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2685 u: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2686 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2687 return OMPC_private;
2688 return (DSAStack->hasExplicitDSA(
2689 D, CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2690 Level) ||
2691 (DSAStack->isClauseParsingMode() &&
2692 DSAStack->getClauseParsingMode() == OMPC_private) ||
2693 // Consider taskgroup reduction descriptor variable a private
2694 // to avoid possible capture in the region.
2695 (DSAStack->hasExplicitDirective(
2696 DPred: [](OpenMPDirectiveKind K) {
2697 return K == OMPD_taskgroup ||
2698 ((isOpenMPParallelDirective(DKind: K) ||
2699 isOpenMPWorksharingDirective(DKind: K)) &&
2700 !isOpenMPSimdDirective(DKind: K));
2701 },
2702 Level) &&
2703 DSAStack->isTaskgroupReductionRef(VD: D, Level)))
2704 ? OMPC_private
2705 : OMPC_unknown;
2706}
2707
2708void SemaOpenMP::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2709 unsigned Level) {
2710 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2711 D = getCanonicalDecl(D);
2712 OpenMPClauseKind OMPC = OMPC_unknown;
2713 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2714 const unsigned NewLevel = I - 1;
2715 if (DSAStack->hasExplicitDSA(
2716 D,
2717 CPred: [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2718 if (isOpenMPPrivate(Kind: K) && !AppliedToPointee) {
2719 OMPC = K;
2720 return true;
2721 }
2722 return false;
2723 },
2724 Level: NewLevel))
2725 break;
2726 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2727 VD: D, Level: NewLevel,
2728 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2729 OpenMPClauseKind) { return true; })) {
2730 OMPC = OMPC_map;
2731 break;
2732 }
2733 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective,
2734 Level: NewLevel)) {
2735 OMPC = OMPC_map;
2736 if (DSAStack->mustBeFirstprivateAtLevel(
2737 Level: NewLevel, Kind: getVariableCategoryFromDecl(LO: getLangOpts(), VD: D)))
2738 OMPC = OMPC_firstprivate;
2739 break;
2740 }
2741 }
2742 if (OMPC != OMPC_unknown)
2743 FD->addAttr(
2744 A: OMPCaptureKindAttr::CreateImplicit(Ctx&: getASTContext(), CaptureKindVal: unsigned(OMPC)));
2745}
2746
2747bool SemaOpenMP::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2748 unsigned CaptureLevel) const {
2749 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2750 // Return true if the current level is no longer enclosed in a target region.
2751
2752 SmallVector<OpenMPDirectiveKind, 4> Regions;
2753 getOpenMPCaptureRegions(CaptureRegions&: Regions, DSAStack->getDirective(Level));
2754 const auto *VD = dyn_cast<VarDecl>(Val: D);
2755 return VD && !VD->hasLocalStorage() &&
2756 DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective,
2757 Level) &&
2758 Regions[CaptureLevel] != OMPD_task;
2759}
2760
2761bool SemaOpenMP::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2762 unsigned CaptureLevel) const {
2763 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2764 // Return true if the current level is no longer enclosed in a target region.
2765
2766 if (const auto *VD = dyn_cast<VarDecl>(Val: D)) {
2767 if (!VD->hasLocalStorage()) {
2768 if (isInOpenMPTargetExecutionDirective())
2769 return true;
2770 DSAStackTy::DSAVarData TopDVar =
2771 DSAStack->getTopDSA(D, /*FromParent=*/false);
2772 unsigned NumLevels =
2773 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2774 if (Level == 0)
2775 // non-file scope static variable with default(firstprivate)
2776 // should be global captured.
2777 return (NumLevels == CaptureLevel + 1 &&
2778 (TopDVar.CKind != OMPC_shared ||
2779 DSAStack->getDefaultDSA() == DSA_firstprivate));
2780 do {
2781 --Level;
2782 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2783 if (DVar.CKind != OMPC_shared)
2784 return true;
2785 } while (Level > 0);
2786 }
2787 }
2788 return true;
2789}
2790
2791void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2792
2793void SemaOpenMP::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2794 OMPTraitInfo &TI) {
2795 OMPDeclareVariantScopes.push_back(Elt: OMPDeclareVariantScope(TI));
2796}
2797
2798void SemaOpenMP::ActOnOpenMPEndDeclareVariant() {
2799 assert(isInOpenMPDeclareVariantScope() &&
2800 "Not in OpenMP declare variant scope!");
2801
2802 OMPDeclareVariantScopes.pop_back();
2803}
2804
2805void SemaOpenMP::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2806 const FunctionDecl *Callee,
2807 SourceLocation Loc) {
2808 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2809 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2810 OMPDeclareTargetDeclAttr::getDeviceType(VD: Caller->getMostRecentDecl());
2811 // Ignore host functions during device analysis.
2812 if (getLangOpts().OpenMPIsTargetDevice &&
2813 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2814 return;
2815 // Ignore nohost functions during host analysis.
2816 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2817 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2818 return;
2819 const FunctionDecl *FD = Callee->getMostRecentDecl();
2820 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(VD: FD);
2821 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2822 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2823 // Diagnose host function called during device codegen.
2824 StringRef HostDevTy =
2825 getOpenMPSimpleClauseTypeName(Kind: OMPC_device_type, Type: OMPC_DEVICE_TYPE_host);
2826 Diag(Loc, DiagID: diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2827 Diag(Loc: *OMPDeclareTargetDeclAttr::getLocation(VD: FD),
2828 DiagID: diag::note_omp_marked_device_type_here)
2829 << HostDevTy;
2830 return;
2831 }
2832 if (!getLangOpts().OpenMPIsTargetDevice &&
2833 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2834 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2835 // In OpenMP 5.2 or later, if the function has a host variant then allow
2836 // that to be called instead
2837 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2838 for (OMPDeclareVariantAttr *A :
2839 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2840 auto *DeclRefVariant = cast<DeclRefExpr>(Val: A->getVariantFuncRef());
2841 auto *VariantFD = cast<FunctionDecl>(Val: DeclRefVariant->getDecl());
2842 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2843 OMPDeclareTargetDeclAttr::getDeviceType(
2844 VD: VariantFD->getMostRecentDecl());
2845 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2846 return true;
2847 }
2848 return false;
2849 };
2850 if (getLangOpts().OpenMP >= 52 &&
2851 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2852 return;
2853 // Diagnose nohost function called during host codegen.
2854 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2855 Kind: OMPC_device_type, Type: OMPC_DEVICE_TYPE_nohost);
2856 Diag(Loc, DiagID: diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2857 Diag(Loc: *OMPDeclareTargetDeclAttr::getLocation(VD: FD),
2858 DiagID: diag::note_omp_marked_device_type_here)
2859 << NoHostDevTy;
2860 }
2861}
2862
2863void SemaOpenMP::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2864 const DeclarationNameInfo &DirName,
2865 Scope *CurScope, SourceLocation Loc) {
2866 DSAStack->push(DKind, DirName, CurScope, Loc);
2867 SemaRef.PushExpressionEvaluationContext(
2868 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
2869}
2870
2871void SemaOpenMP::StartOpenMPClause(OpenMPClauseKind K) {
2872 DSAStack->setClauseParsingMode(K);
2873}
2874
2875void SemaOpenMP::EndOpenMPClause() {
2876 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2877 SemaRef.CleanupVarDeclMarking();
2878}
2879
2880static std::pair<ValueDecl *, bool>
2881getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2882 SourceRange &ERange, bool AllowArraySection = false,
2883 bool AllowAssumedSizeArray = false, StringRef DiagType = "");
2884
2885/// Check consistency of the reduction clauses.
2886static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2887 ArrayRef<OMPClause *> Clauses) {
2888 bool InscanFound = false;
2889 SourceLocation InscanLoc;
2890 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2891 // A reduction clause without the inscan reduction-modifier may not appear on
2892 // a construct on which a reduction clause with the inscan reduction-modifier
2893 // appears.
2894 for (OMPClause *C : Clauses) {
2895 if (C->getClauseKind() != OMPC_reduction)
2896 continue;
2897 auto *RC = cast<OMPReductionClause>(Val: C);
2898 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2899 InscanFound = true;
2900 InscanLoc = RC->getModifierLoc();
2901 continue;
2902 }
2903 if (RC->getModifier() == OMPC_REDUCTION_task) {
2904 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2905 // A reduction clause with the task reduction-modifier may only appear on
2906 // a parallel construct, a worksharing construct or a combined or
2907 // composite construct for which any of the aforementioned constructs is a
2908 // constituent construct and simd or loop are not constituent constructs.
2909 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2910 if (!(isOpenMPParallelDirective(DKind: CurDir) ||
2911 isOpenMPWorksharingDirective(DKind: CurDir)) ||
2912 isOpenMPSimdDirective(DKind: CurDir))
2913 S.Diag(Loc: RC->getModifierLoc(),
2914 DiagID: diag::err_omp_reduction_task_not_parallel_or_worksharing);
2915 continue;
2916 }
2917 }
2918 if (InscanFound) {
2919 for (OMPClause *C : Clauses) {
2920 if (C->getClauseKind() != OMPC_reduction)
2921 continue;
2922 auto *RC = cast<OMPReductionClause>(Val: C);
2923 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2924 S.Diag(Loc: RC->getModifier() == OMPC_REDUCTION_unknown
2925 ? RC->getBeginLoc()
2926 : RC->getModifierLoc(),
2927 DiagID: diag::err_omp_inscan_reduction_expected);
2928 S.Diag(Loc: InscanLoc, DiagID: diag::note_omp_previous_inscan_reduction);
2929 continue;
2930 }
2931 for (Expr *Ref : RC->varlist()) {
2932 assert(Ref && "NULL expr in OpenMP reduction clause.");
2933 SourceLocation ELoc;
2934 SourceRange ERange;
2935 Expr *SimpleRefExpr = Ref;
2936 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
2937 /*AllowArraySection=*/true);
2938 ValueDecl *D = Res.first;
2939 if (!D)
2940 continue;
2941 if (!Stack->isUsedInScanDirective(D: getCanonicalDecl(D))) {
2942 S.Diag(Loc: Ref->getExprLoc(),
2943 DiagID: diag::err_omp_reduction_not_inclusive_exclusive)
2944 << Ref->getSourceRange();
2945 }
2946 }
2947 }
2948 }
2949}
2950
2951static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2952 ArrayRef<OMPClause *> Clauses);
2953static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2954 bool WithInit);
2955
2956static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2957 const ValueDecl *D,
2958 const DSAStackTy::DSAVarData &DVar,
2959 bool IsLoopIterVar = false);
2960
2961void SemaOpenMP::EndOpenMPDSABlock(Stmt *CurDirective) {
2962 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2963 // A variable of class type (or array thereof) that appears in a lastprivate
2964 // clause requires an accessible, unambiguous default constructor for the
2965 // class type, unless the list item is also specified in a firstprivate
2966 // clause.
2967
2968 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2969 SmallVector<Expr *, 8> PrivateCopies;
2970 for (Expr *DE : Clause->varlist()) {
2971 if (DE->isValueDependent() || DE->isTypeDependent()) {
2972 PrivateCopies.push_back(Elt: nullptr);
2973 continue;
2974 }
2975 auto *DRE = cast<DeclRefExpr>(Val: DE->IgnoreParens());
2976 auto *VD = cast<VarDecl>(Val: DRE->getDecl());
2977 QualType Type = VD->getType().getNonReferenceType();
2978 const DSAStackTy::DSAVarData DVar =
2979 DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
2980 if (DVar.CKind != OMPC_lastprivate) {
2981 // The variable is also a firstprivate, so initialization sequence
2982 // for private copy is generated already.
2983 PrivateCopies.push_back(Elt: nullptr);
2984 continue;
2985 }
2986 // Generate helper private variable and initialize it with the
2987 // default value. The address of the original variable is replaced
2988 // by the address of the new private variable in CodeGen. This new
2989 // variable is not added to IdResolver, so the code in the OpenMP
2990 // region uses original variable for proper diagnostics.
2991 VarDecl *VDPrivate = buildVarDecl(
2992 SemaRef, Loc: DE->getExprLoc(), Type: Type.getUnqualifiedType(), Name: VD->getName(),
2993 Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr, OrigRef: DRE);
2994 SemaRef.ActOnUninitializedDecl(dcl: VDPrivate);
2995 if (VDPrivate->isInvalidDecl()) {
2996 PrivateCopies.push_back(Elt: nullptr);
2997 continue;
2998 }
2999 PrivateCopies.push_back(Elt: buildDeclRefExpr(
3000 S&: SemaRef, D: VDPrivate, Ty: DE->getType(), Loc: DE->getExprLoc()));
3001 }
3002 Clause->setPrivateCopies(PrivateCopies);
3003 };
3004
3005 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
3006 // Finalize nontemporal clause by handling private copies, if any.
3007 SmallVector<Expr *, 8> PrivateRefs;
3008 for (Expr *RefExpr : Clause->varlist()) {
3009 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
3010 SourceLocation ELoc;
3011 SourceRange ERange;
3012 Expr *SimpleRefExpr = RefExpr;
3013 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
3014 if (Res.second)
3015 // It will be analyzed later.
3016 PrivateRefs.push_back(Elt: RefExpr);
3017 ValueDecl *D = Res.first;
3018 if (!D)
3019 continue;
3020
3021 const DSAStackTy::DSAVarData DVar =
3022 DSAStack->getTopDSA(D, /*FromParent=*/false);
3023 PrivateRefs.push_back(Elt: DVar.PrivateCopy ? DVar.PrivateCopy
3024 : SimpleRefExpr);
3025 }
3026 Clause->setPrivateRefs(PrivateRefs);
3027 };
3028
3029 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
3030 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3031 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
3032 auto *DRE = dyn_cast<DeclRefExpr>(Val: D.Allocator->IgnoreParenImpCasts());
3033 if (!DRE)
3034 continue;
3035 ValueDecl *VD = DRE->getDecl();
3036 if (!VD || !isa<VarDecl>(Val: VD))
3037 continue;
3038 DSAStackTy::DSAVarData DVar =
3039 DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
3040 // OpenMP [2.12.5, target Construct]
3041 // Memory allocators that appear in a uses_allocators clause cannot
3042 // appear in other data-sharing attribute clauses or data-mapping
3043 // attribute clauses in the same construct.
3044 Expr *MapExpr = nullptr;
3045 if (DVar.RefExpr ||
3046 DSAStack->checkMappableExprComponentListsForDecl(
3047 VD, /*CurrentRegionOnly=*/true,
3048 Check: [VD, &MapExpr](
3049 OMPClauseMappableExprCommon::MappableExprComponentListRef
3050 MapExprComponents,
3051 OpenMPClauseKind C) {
3052 auto MI = MapExprComponents.rbegin();
3053 auto ME = MapExprComponents.rend();
3054 if (MI != ME &&
3055 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3056 VD->getCanonicalDecl()) {
3057 MapExpr = MI->getAssociatedExpression();
3058 return true;
3059 }
3060 return false;
3061 })) {
3062 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::err_omp_allocator_used_in_clauses)
3063 << D.Allocator->getSourceRange();
3064 if (DVar.RefExpr)
3065 reportOriginalDsa(SemaRef, DSAStack, D: VD, DVar);
3066 else
3067 Diag(Loc: MapExpr->getExprLoc(), DiagID: diag::note_used_here)
3068 << MapExpr->getSourceRange();
3069 }
3070 }
3071 };
3072
3073 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(Val: CurDirective)) {
3074 for (OMPClause *C : D->clauses()) {
3075 if (auto *Clause = dyn_cast<OMPLastprivateClause>(Val: C)) {
3076 FinalizeLastprivate(Clause);
3077 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(Val: C)) {
3078 FinalizeNontemporal(Clause);
3079 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(Val: C)) {
3080 FinalizeAllocators(Clause);
3081 }
3082 }
3083 // Check allocate clauses.
3084 if (!SemaRef.CurContext->isDependentContext())
3085 checkAllocateClauses(S&: SemaRef, DSAStack, Clauses: D->clauses());
3086 checkReductionClauses(S&: SemaRef, DSAStack, Clauses: D->clauses());
3087 }
3088
3089 DSAStack->pop();
3090 SemaRef.DiscardCleanupsInEvaluationContext();
3091 SemaRef.PopExpressionEvaluationContext();
3092}
3093
3094static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3095 Expr *NumIterations, Sema &SemaRef,
3096 Scope *S, DSAStackTy *Stack);
3097
3098static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
3099 OMPLoopBasedDirective::HelperExprs &B,
3100 DSAStackTy *Stack) {
3101 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3102 "loop exprs were not built");
3103
3104 if (SemaRef.CurContext->isDependentContext())
3105 return false;
3106
3107 // Finalize the clauses that need pre-built expressions for CodeGen.
3108 for (OMPClause *C : Clauses) {
3109 auto *LC = dyn_cast<OMPLinearClause>(Val: C);
3110 if (!LC)
3111 continue;
3112 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
3113 NumIterations: B.NumIterations, SemaRef,
3114 S: SemaRef.getCurScope(), Stack))
3115 return true;
3116 }
3117
3118 return false;
3119}
3120
3121namespace {
3122
3123class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3124private:
3125 Sema &SemaRef;
3126
3127public:
3128 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3129 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3130 NamedDecl *ND = Candidate.getCorrectionDecl();
3131 if (const auto *VD = dyn_cast_or_null<VarDecl>(Val: ND)) {
3132 return VD->hasGlobalStorage() &&
3133 SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(),
3134 S: SemaRef.getCurScope());
3135 }
3136 return false;
3137 }
3138
3139 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3140 return std::make_unique<VarDeclFilterCCC>(args&: *this);
3141 }
3142};
3143
3144class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3145private:
3146 Sema &SemaRef;
3147
3148public:
3149 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3150 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3151 NamedDecl *ND = Candidate.getCorrectionDecl();
3152 if (ND && ((isa<VarDecl>(Val: ND) && ND->getKind() == Decl::Var) ||
3153 isa<FunctionDecl>(Val: ND))) {
3154 return SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(),
3155 S: SemaRef.getCurScope());
3156 }
3157 return false;
3158 }
3159
3160 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3161 return std::make_unique<VarOrFuncDeclFilterCCC>(args&: *this);
3162 }
3163};
3164
3165} // namespace
3166
3167ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope,
3168 CXXScopeSpec &ScopeSpec,
3169 const DeclarationNameInfo &Id,
3170 OpenMPDirectiveKind Kind) {
3171 ASTContext &Context = getASTContext();
3172 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
3173 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
3174 SemaRef.LookupParsedName(R&: Lookup, S: CurScope, SS: &ScopeSpec,
3175 /*ObjectType=*/QualType(),
3176 /*AllowBuiltinCreation=*/true);
3177
3178 if (Lookup.isAmbiguous())
3179 return ExprError();
3180
3181 VarDecl *VD;
3182 if (!Lookup.isSingleResult()) {
3183 VarDeclFilterCCC CCC(SemaRef);
3184 if (TypoCorrection Corrected =
3185 SemaRef.CorrectTypo(Typo: Id, LookupKind: Sema::LookupOrdinaryName, S: CurScope, SS: nullptr,
3186 CCC, Mode: CorrectTypoKind::ErrorRecovery)) {
3187 SemaRef.diagnoseTypo(
3188 Correction: Corrected,
3189 TypoDiag: SemaRef.PDiag(DiagID: Lookup.empty() ? diag::err_undeclared_var_use_suggest
3190 : diag::err_omp_expected_var_arg_suggest)
3191 << Id.getName());
3192 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3193 } else {
3194 Diag(Loc: Id.getLoc(), DiagID: Lookup.empty() ? diag::err_undeclared_var_use
3195 : diag::err_omp_expected_var_arg)
3196 << Id.getName();
3197 return ExprError();
3198 }
3199 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3200 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_expected_var_arg) << Id.getName();
3201 Diag(Loc: Lookup.getFoundDecl()->getLocation(), DiagID: diag::note_declared_at);
3202 return ExprError();
3203 }
3204 Lookup.suppressDiagnostics();
3205
3206 // OpenMP [2.9.2, Syntax, C/C++]
3207 // Variables must be file-scope, namespace-scope, or static block-scope.
3208 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3209 !VD->hasGlobalStorage()) {
3210 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_global_var_arg)
3211 << getOpenMPDirectiveName(D: Kind, V: OMPVersion) << !VD->isStaticLocal();
3212 bool IsDecl =
3213 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3214 Diag(Loc: VD->getLocation(),
3215 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3216 << VD;
3217 return ExprError();
3218 }
3219
3220 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3221 NamedDecl *ND = CanonicalVD;
3222 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3223 // A threadprivate or groupprivate directive for file-scope variables must
3224 // appear outside any definition or declaration.
3225 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3226 !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3227 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3228 << getOpenMPDirectiveName(D: Kind, V: OMPVersion) << VD;
3229 bool IsDecl =
3230 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3231 Diag(Loc: VD->getLocation(),
3232 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3233 << VD;
3234 return ExprError();
3235 }
3236 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3237 // A threadprivate or groupprivate directive for static class member
3238 // variables must appear in the class definition, in the same scope in which
3239 // the member variables are declared.
3240 if (CanonicalVD->isStaticDataMember() &&
3241 !CanonicalVD->getDeclContext()->Equals(DC: SemaRef.getCurLexicalContext())) {
3242 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3243 << getOpenMPDirectiveName(D: Kind, V: OMPVersion) << VD;
3244 bool IsDecl =
3245 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3246 Diag(Loc: VD->getLocation(),
3247 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3248 << VD;
3249 return ExprError();
3250 }
3251 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3252 // A threadprivate or groupprivate directive for namespace-scope variables
3253 // must appear outside any definition or declaration other than the
3254 // namespace definition itself.
3255 if (CanonicalVD->getDeclContext()->isNamespace() &&
3256 (!SemaRef.getCurLexicalContext()->isFileContext() ||
3257 !SemaRef.getCurLexicalContext()->Encloses(
3258 DC: CanonicalVD->getDeclContext()))) {
3259 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3260 << getOpenMPDirectiveName(D: Kind, V: OMPVersion) << VD;
3261 bool IsDecl =
3262 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3263 Diag(Loc: VD->getLocation(),
3264 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3265 << VD;
3266 return ExprError();
3267 }
3268 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3269 // A threadprivate or groupprivate directive for static block-scope
3270 // variables must appear in the scope of the variable and not in a nested
3271 // scope.
3272 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3273 !SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(), S: CurScope)) {
3274 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3275 << getOpenMPDirectiveName(D: Kind, V: OMPVersion) << VD;
3276 bool IsDecl =
3277 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3278 Diag(Loc: VD->getLocation(),
3279 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3280 << VD;
3281 return ExprError();
3282 }
3283
3284 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3285 // A threadprivate or groupprivate directive must lexically precede all
3286 // references to any of the variables in its list.
3287 if ((Kind == OMPD_threadprivate && VD->isUsed() &&
3288 !DSAStack->isThreadPrivate(D: VD)) ||
3289 (Kind == OMPD_groupprivate && VD->isUsed())) {
3290 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_used)
3291 << getOpenMPDirectiveName(D: Kind, V: OMPVersion) << VD;
3292 return ExprError();
3293 }
3294
3295 QualType ExprType = VD->getType().getNonReferenceType();
3296 return DeclRefExpr::Create(Context, QualifierLoc: NestedNameSpecifierLoc(),
3297 TemplateKWLoc: SourceLocation(), D: VD,
3298 /*RefersToEnclosingVariableOrCapture=*/false,
3299 NameLoc: Id.getLoc(), T: ExprType, VK: VK_LValue);
3300}
3301
3302SemaOpenMP::DeclGroupPtrTy
3303SemaOpenMP::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3304 ArrayRef<Expr *> VarList) {
3305 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3306 SemaRef.CurContext->addDecl(D);
3307 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3308 }
3309 return nullptr;
3310}
3311
3312SemaOpenMP::DeclGroupPtrTy
3313SemaOpenMP::ActOnOpenMPGroupPrivateDirective(SourceLocation Loc,
3314 ArrayRef<Expr *> VarList) {
3315 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
3316 if (!OMPVersion || OMPVersion < 60) {
3317 Diag(Loc, DiagID: diag::err_omp_unexpected_directive)
3318 << getOpenMPDirectiveName(D: OMPD_groupprivate, V: OMPVersion);
3319 return nullptr;
3320 }
3321 if (OMPGroupPrivateDecl *D = CheckOMPGroupPrivateDecl(Loc, VarList)) {
3322 SemaRef.CurContext->addDecl(D);
3323 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3324 }
3325 return nullptr;
3326}
3327
3328namespace {
3329class LocalVarRefChecker final
3330 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3331 Sema &SemaRef;
3332
3333public:
3334 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3335 if (const auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
3336 if (VD->hasLocalStorage()) {
3337 SemaRef.Diag(Loc: E->getBeginLoc(),
3338 DiagID: diag::err_omp_local_var_in_threadprivate_init)
3339 << E->getSourceRange();
3340 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::note_defined_here)
3341 << VD << VD->getSourceRange();
3342 return true;
3343 }
3344 }
3345 return false;
3346 }
3347 bool VisitStmt(const Stmt *S) {
3348 for (const Stmt *Child : S->children()) {
3349 if (Child && Visit(S: Child))
3350 return true;
3351 }
3352 return false;
3353 }
3354 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3355};
3356} // namespace
3357
3358OMPThreadPrivateDecl *
3359SemaOpenMP::CheckOMPThreadPrivateDecl(SourceLocation Loc,
3360 ArrayRef<Expr *> VarList) {
3361 ASTContext &Context = getASTContext();
3362 SmallVector<Expr *, 8> Vars;
3363 for (Expr *RefExpr : VarList) {
3364 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3365 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3366 SourceLocation ILoc = DE->getExprLoc();
3367
3368 // Mark variable as used.
3369 VD->setReferenced();
3370 VD->markUsed(C&: Context);
3371
3372 QualType QType = VD->getType();
3373 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3374 // It will be analyzed later.
3375 Vars.push_back(Elt: DE);
3376 continue;
3377 }
3378
3379 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3380 // A threadprivate variable must not have an incomplete type.
3381 if (SemaRef.RequireCompleteType(
3382 Loc: ILoc, T: VD->getType(), DiagID: diag::err_omp_threadprivate_incomplete_type)) {
3383 continue;
3384 }
3385
3386 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3387 // A threadprivate variable must not have a reference type.
3388 if (VD->getType()->isReferenceType()) {
3389 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
3390 Diag(Loc: ILoc, DiagID: diag::err_omp_ref_type_arg)
3391 << getOpenMPDirectiveName(D: OMPD_threadprivate, V: OMPVersion)
3392 << VD->getType();
3393 bool IsDecl =
3394 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3395 Diag(Loc: VD->getLocation(),
3396 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3397 << VD;
3398 continue;
3399 }
3400
3401 // Check if this is a TLS variable. If TLS is not being supported, produce
3402 // the corresponding diagnostic.
3403 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3404 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3405 getLangOpts().OpenMPUseTLS &&
3406 getASTContext().getTargetInfo().isTLSSupported())) ||
3407 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3408 !VD->isLocalVarDecl())) {
3409 Diag(Loc: ILoc, DiagID: diag::err_omp_var_thread_local)
3410 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3411 bool IsDecl =
3412 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3413 Diag(Loc: VD->getLocation(),
3414 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3415 << VD;
3416 continue;
3417 }
3418
3419 // Check if initial value of threadprivate variable reference variable with
3420 // local storage (it is not supported by runtime).
3421 if (const Expr *Init = VD->getAnyInitializer()) {
3422 LocalVarRefChecker Checker(SemaRef);
3423 if (Checker.Visit(S: Init))
3424 continue;
3425 }
3426
3427 Vars.push_back(Elt: RefExpr);
3428 DSAStack->addDSA(D: VD, E: DE, A: OMPC_threadprivate);
3429 VD->addAttr(A: OMPThreadPrivateDeclAttr::CreateImplicit(
3430 Ctx&: Context, Range: SourceRange(Loc, Loc)));
3431 if (ASTMutationListener *ML = Context.getASTMutationListener())
3432 ML->DeclarationMarkedOpenMPThreadPrivate(D: VD);
3433 }
3434 OMPThreadPrivateDecl *D = nullptr;
3435 if (!Vars.empty()) {
3436 D = OMPThreadPrivateDecl::Create(C&: Context, DC: SemaRef.getCurLexicalContext(),
3437 L: Loc, VL: Vars);
3438 D->setAccess(AS_public);
3439 }
3440 return D;
3441}
3442
3443OMPGroupPrivateDecl *
3444SemaOpenMP::CheckOMPGroupPrivateDecl(SourceLocation Loc,
3445 ArrayRef<Expr *> VarList) {
3446 ASTContext &Context = getASTContext();
3447 SmallVector<Expr *, 8> Vars;
3448 for (Expr *RefExpr : VarList) {
3449 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3450 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3451 SourceLocation ILoc = DE->getExprLoc();
3452
3453 // Mark variable as used.
3454 VD->setReferenced();
3455 VD->markUsed(C&: Context);
3456
3457 QualType QType = VD->getType();
3458 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3459 // It will be analyzed later.
3460 Vars.push_back(Elt: DE);
3461 continue;
3462 }
3463
3464 // OpenMP groupprivate restrictions:
3465 // A groupprivate variable must not have an incomplete type.
3466 if (SemaRef.RequireCompleteType(
3467 Loc: ILoc, T: VD->getType(), DiagID: diag::err_omp_groupprivate_incomplete_type)) {
3468 continue;
3469 }
3470
3471 // A groupprivate variable must not have a reference type.
3472 if (VD->getType()->isReferenceType()) {
3473 Diag(Loc: ILoc, DiagID: diag::err_omp_ref_type_arg)
3474 << getOpenMPDirectiveName(D: OMPD_groupprivate) << VD->getType();
3475 bool IsDecl =
3476 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3477 Diag(Loc: VD->getLocation(),
3478 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3479 << VD;
3480 continue;
3481 }
3482
3483 // A variable that is declared with an initializer must not appear in a
3484 // groupprivate directive.
3485 if (VD->getAnyInitializer()) {
3486 Diag(Loc: ILoc, DiagID: diag::err_omp_groupprivate_with_initializer)
3487 << VD->getDeclName();
3488 bool IsDecl =
3489 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3490 Diag(Loc: VD->getLocation(),
3491 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3492 << VD;
3493 continue;
3494 }
3495
3496 Vars.push_back(Elt: RefExpr);
3497 DSAStack->addDSA(D: VD, E: DE, A: OMPC_groupprivate);
3498 VD->addAttr(A: OMPGroupPrivateDeclAttr::CreateImplicit(Ctx&: Context,
3499 Range: SourceRange(Loc, Loc)));
3500 if (ASTMutationListener *ML = Context.getASTMutationListener())
3501 ML->DeclarationMarkedOpenMPGroupPrivate(D: VD);
3502 }
3503 OMPGroupPrivateDecl *D = nullptr;
3504 if (!Vars.empty()) {
3505 D = OMPGroupPrivateDecl::Create(C&: Context, DC: SemaRef.getCurLexicalContext(),
3506 L: Loc, VL: Vars);
3507 D->setAccess(AS_public);
3508 }
3509 return D;
3510}
3511
3512static OMPAllocateDeclAttr::AllocatorTypeTy
3513getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3514 if (!Allocator)
3515 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3516 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3517 Allocator->isInstantiationDependent() ||
3518 Allocator->containsUnexpandedParameterPack())
3519 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3520 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3521 llvm::FoldingSetNodeID AEId;
3522 const Expr *AE = Allocator->IgnoreParenImpCasts();
3523 AE->IgnoreImpCasts()->Profile(ID&: AEId, Context: S.getASTContext(), /*Canonical=*/true);
3524 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3525 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3526 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3527 llvm::FoldingSetNodeID DAEId;
3528 DefAllocator->IgnoreImpCasts()->Profile(ID&: DAEId, Context: S.getASTContext(),
3529 /*Canonical=*/true);
3530 if (AEId == DAEId) {
3531 AllocatorKindRes = AllocatorKind;
3532 break;
3533 }
3534 }
3535 return AllocatorKindRes;
3536}
3537
3538static bool checkPreviousOMPAllocateAttribute(
3539 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3540 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3541 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3542 return false;
3543 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3544 Expr *PrevAllocator = A->getAllocator();
3545 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3546 getAllocatorKind(S, Stack, Allocator: PrevAllocator);
3547 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3548 if (AllocatorsMatch &&
3549 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3550 Allocator && PrevAllocator) {
3551 const Expr *AE = Allocator->IgnoreParenImpCasts();
3552 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3553 llvm::FoldingSetNodeID AEId, PAEId;
3554 AE->Profile(ID&: AEId, Context: S.Context, /*Canonical=*/true);
3555 PAE->Profile(ID&: PAEId, Context: S.Context, /*Canonical=*/true);
3556 AllocatorsMatch = AEId == PAEId;
3557 }
3558 if (!AllocatorsMatch) {
3559 SmallString<256> AllocatorBuffer;
3560 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3561 if (Allocator)
3562 Allocator->printPretty(OS&: AllocatorStream, Helper: nullptr, Policy: S.getPrintingPolicy());
3563 SmallString<256> PrevAllocatorBuffer;
3564 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3565 if (PrevAllocator)
3566 PrevAllocator->printPretty(OS&: PrevAllocatorStream, Helper: nullptr,
3567 Policy: S.getPrintingPolicy());
3568
3569 SourceLocation AllocatorLoc =
3570 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3571 SourceRange AllocatorRange =
3572 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3573 SourceLocation PrevAllocatorLoc =
3574 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3575 SourceRange PrevAllocatorRange =
3576 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3577 S.Diag(Loc: AllocatorLoc, DiagID: diag::warn_omp_used_different_allocator)
3578 << (Allocator ? 1 : 0) << AllocatorStream.str()
3579 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3580 << AllocatorRange;
3581 S.Diag(Loc: PrevAllocatorLoc, DiagID: diag::note_omp_previous_allocator)
3582 << PrevAllocatorRange;
3583 return true;
3584 }
3585 return false;
3586}
3587
3588static void
3589applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3590 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3591 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3592 if (VD->hasAttr<OMPAllocateDeclAttr>())
3593 return;
3594 if (Alignment &&
3595 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3596 Alignment->isInstantiationDependent() ||
3597 Alignment->containsUnexpandedParameterPack()))
3598 // Apply later when we have a usable value.
3599 return;
3600 if (Allocator &&
3601 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3602 Allocator->isInstantiationDependent() ||
3603 Allocator->containsUnexpandedParameterPack()))
3604 return;
3605 auto *A = OMPAllocateDeclAttr::CreateImplicit(Ctx&: S.Context, AllocatorType: AllocatorKind,
3606 Allocator, Alignment, Range: SR);
3607 VD->addAttr(A);
3608 if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3609 ML->DeclarationMarkedOpenMPAllocate(D: VD, A);
3610}
3611
3612SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPAllocateDirective(
3613 SourceLocation Loc, ArrayRef<Expr *> VarList, ArrayRef<OMPClause *> Clauses,
3614 DeclContext *Owner) {
3615 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3616 Expr *Alignment = nullptr;
3617 Expr *Allocator = nullptr;
3618 if (Clauses.empty()) {
3619 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3620 // allocate directives that appear in a target region must specify an
3621 // allocator clause unless a requires directive with the dynamic_allocators
3622 // clause is present in the same compilation unit.
3623 if (getLangOpts().OpenMPIsTargetDevice &&
3624 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3625 SemaRef.targetDiag(Loc, DiagID: diag::err_expected_allocator_clause);
3626 } else {
3627 for (const OMPClause *C : Clauses)
3628 if (const auto *AC = dyn_cast<OMPAllocatorClause>(Val: C))
3629 Allocator = AC->getAllocator();
3630 else if (const auto *AC = dyn_cast<OMPAlignClause>(Val: C))
3631 Alignment = AC->getAlignment();
3632 else
3633 llvm_unreachable("Unexpected clause on allocate directive");
3634 }
3635 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3636 getAllocatorKind(S&: SemaRef, DSAStack, Allocator);
3637 SmallVector<Expr *, 8> Vars;
3638 for (Expr *RefExpr : VarList) {
3639 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3640 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3641
3642 // Check if this is a TLS variable or global register.
3643 if (VD->getTLSKind() != VarDecl::TLS_None ||
3644 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3645 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3646 !VD->isLocalVarDecl()))
3647 continue;
3648
3649 // If the used several times in the allocate directive, the same allocator
3650 // must be used.
3651 if (checkPreviousOMPAllocateAttribute(S&: SemaRef, DSAStack, RefExpr, VD,
3652 AllocatorKind, Allocator))
3653 continue;
3654
3655 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3656 // If a list item has a static storage type, the allocator expression in the
3657 // allocator clause must be a constant expression that evaluates to one of
3658 // the predefined memory allocator values.
3659 if (Allocator && VD->hasGlobalStorage()) {
3660 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3661 Diag(Loc: Allocator->getExprLoc(),
3662 DiagID: diag::err_omp_expected_predefined_allocator)
3663 << Allocator->getSourceRange();
3664 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3665 VarDecl::DeclarationOnly;
3666 Diag(Loc: VD->getLocation(),
3667 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3668 << VD;
3669 continue;
3670 }
3671 }
3672
3673 Vars.push_back(Elt: RefExpr);
3674 applyOMPAllocateAttribute(S&: SemaRef, VD, AllocatorKind, Allocator, Alignment,
3675 SR: DE->getSourceRange());
3676 }
3677 if (Vars.empty())
3678 return nullptr;
3679 if (!Owner)
3680 Owner = SemaRef.getCurLexicalContext();
3681 auto *D = OMPAllocateDecl::Create(C&: getASTContext(), DC: Owner, L: Loc, VL: Vars, CL: Clauses);
3682 D->setAccess(AS_public);
3683 Owner->addDecl(D);
3684 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3685}
3686
3687SemaOpenMP::DeclGroupPtrTy
3688SemaOpenMP::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3689 ArrayRef<OMPClause *> ClauseList) {
3690 OMPRequiresDecl *D = nullptr;
3691 if (!SemaRef.CurContext->isFileContext()) {
3692 Diag(Loc, DiagID: diag::err_omp_invalid_scope) << "requires";
3693 } else {
3694 D = CheckOMPRequiresDecl(Loc, Clauses: ClauseList);
3695 if (D) {
3696 SemaRef.CurContext->addDecl(D);
3697 DSAStack->addRequiresDecl(RD: D);
3698 }
3699 }
3700 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3701}
3702
3703void SemaOpenMP::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3704 OpenMPDirectiveKind DKind,
3705 ArrayRef<std::string> Assumptions,
3706 bool SkippedClauses) {
3707 if (!SkippedClauses && Assumptions.empty()) {
3708 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
3709 Diag(Loc, DiagID: diag::err_omp_no_clause_for_directive)
3710 << llvm::omp::getAllAssumeClauseOptions()
3711 << llvm::omp::getOpenMPDirectiveName(D: DKind, V: OMPVersion);
3712 }
3713
3714 auto *AA =
3715 OMPAssumeAttr::Create(Ctx&: getASTContext(), Assumption: llvm::join(R&: Assumptions, Separator: ","), Range: Loc);
3716 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3717 OMPAssumeScoped.push_back(Elt: AA);
3718 return;
3719 }
3720
3721 // Global assumes without assumption clauses are ignored.
3722 if (Assumptions.empty())
3723 return;
3724
3725 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3726 "Unexpected omp assumption directive!");
3727 OMPAssumeGlobal.push_back(Elt: AA);
3728
3729 // The OMPAssumeGlobal scope above will take care of new declarations but
3730 // we also want to apply the assumption to existing ones, e.g., to
3731 // declarations in included headers. To this end, we traverse all existing
3732 // declaration contexts and annotate function declarations here.
3733 SmallVector<DeclContext *, 8> DeclContexts;
3734 auto *Ctx = SemaRef.CurContext;
3735 while (Ctx->getLexicalParent())
3736 Ctx = Ctx->getLexicalParent();
3737 DeclContexts.push_back(Elt: Ctx);
3738 while (!DeclContexts.empty()) {
3739 DeclContext *DC = DeclContexts.pop_back_val();
3740 for (auto *SubDC : DC->decls()) {
3741 if (SubDC->isInvalidDecl())
3742 continue;
3743 if (auto *CTD = dyn_cast<ClassTemplateDecl>(Val: SubDC)) {
3744 DeclContexts.push_back(Elt: CTD->getTemplatedDecl());
3745 llvm::append_range(C&: DeclContexts, R: CTD->specializations());
3746 continue;
3747 }
3748 if (auto *DC = dyn_cast<DeclContext>(Val: SubDC))
3749 DeclContexts.push_back(Elt: DC);
3750 if (auto *F = dyn_cast<FunctionDecl>(Val: SubDC)) {
3751 F->addAttr(A: AA);
3752 continue;
3753 }
3754 }
3755 }
3756}
3757
3758void SemaOpenMP::ActOnOpenMPEndAssumesDirective() {
3759 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3760 OMPAssumeScoped.pop_back();
3761}
3762
3763StmtResult SemaOpenMP::ActOnOpenMPAssumeDirective(ArrayRef<OMPClause *> Clauses,
3764 Stmt *AStmt,
3765 SourceLocation StartLoc,
3766 SourceLocation EndLoc) {
3767 if (!AStmt)
3768 return StmtError();
3769
3770 return OMPAssumeDirective::Create(Ctx: getASTContext(), StartLoc, EndLoc, Clauses,
3771 AStmt);
3772}
3773
3774OMPRequiresDecl *
3775SemaOpenMP::CheckOMPRequiresDecl(SourceLocation Loc,
3776 ArrayRef<OMPClause *> ClauseList) {
3777 /// For target specific clauses, the requires directive cannot be
3778 /// specified after the handling of any of the target regions in the
3779 /// current compilation unit.
3780 ArrayRef<SourceLocation> TargetLocations =
3781 DSAStack->getEncounteredTargetLocs();
3782 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3783 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3784 for (const OMPClause *CNew : ClauseList) {
3785 // Check if any of the requires clauses affect target regions.
3786 if (isa<OMPUnifiedSharedMemoryClause>(Val: CNew) ||
3787 isa<OMPUnifiedAddressClause>(Val: CNew) ||
3788 isa<OMPReverseOffloadClause>(Val: CNew) ||
3789 isa<OMPDynamicAllocatorsClause>(Val: CNew)) {
3790 Diag(Loc, DiagID: diag::err_omp_directive_before_requires)
3791 << "target" << getOpenMPClauseNameForDiag(C: CNew->getClauseKind());
3792 for (SourceLocation TargetLoc : TargetLocations) {
3793 Diag(Loc: TargetLoc, DiagID: diag::note_omp_requires_encountered_directive)
3794 << "target";
3795 }
3796 } else if (!AtomicLoc.isInvalid() &&
3797 isa<OMPAtomicDefaultMemOrderClause>(Val: CNew)) {
3798 Diag(Loc, DiagID: diag::err_omp_directive_before_requires)
3799 << "atomic" << getOpenMPClauseNameForDiag(C: CNew->getClauseKind());
3800 Diag(Loc: AtomicLoc, DiagID: diag::note_omp_requires_encountered_directive)
3801 << "atomic";
3802 }
3803 }
3804 }
3805
3806 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3807 return OMPRequiresDecl::Create(
3808 C&: getASTContext(), DC: SemaRef.getCurLexicalContext(), L: Loc, CL: ClauseList);
3809 return nullptr;
3810}
3811
3812static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3813 const ValueDecl *D,
3814 const DSAStackTy::DSAVarData &DVar,
3815 bool IsLoopIterVar) {
3816 if (DVar.RefExpr) {
3817 SemaRef.Diag(Loc: DVar.RefExpr->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
3818 << getOpenMPClauseNameForDiag(C: DVar.CKind);
3819 return;
3820 }
3821 enum {
3822 PDSA_StaticMemberShared,
3823 PDSA_StaticLocalVarShared,
3824 PDSA_LoopIterVarPrivate,
3825 PDSA_LoopIterVarLinear,
3826 PDSA_LoopIterVarLastprivate,
3827 PDSA_ConstVarShared,
3828 PDSA_GlobalVarShared,
3829 PDSA_TaskVarFirstprivate,
3830 PDSA_LocalVarPrivate,
3831 PDSA_Implicit
3832 } Reason = PDSA_Implicit;
3833 bool ReportHint = false;
3834 auto ReportLoc = D->getLocation();
3835 auto *VD = dyn_cast<VarDecl>(Val: D);
3836 if (IsLoopIterVar) {
3837 if (DVar.CKind == OMPC_private)
3838 Reason = PDSA_LoopIterVarPrivate;
3839 else if (DVar.CKind == OMPC_lastprivate)
3840 Reason = PDSA_LoopIterVarLastprivate;
3841 else
3842 Reason = PDSA_LoopIterVarLinear;
3843 } else if (isOpenMPTaskingDirective(Kind: DVar.DKind) &&
3844 DVar.CKind == OMPC_firstprivate) {
3845 Reason = PDSA_TaskVarFirstprivate;
3846 ReportLoc = DVar.ImplicitDSALoc;
3847 } else if (VD && VD->isStaticLocal())
3848 Reason = PDSA_StaticLocalVarShared;
3849 else if (VD && VD->isStaticDataMember())
3850 Reason = PDSA_StaticMemberShared;
3851 else if (VD && VD->isFileVarDecl())
3852 Reason = PDSA_GlobalVarShared;
3853 else if (D->getType().isConstant(Ctx: SemaRef.getASTContext()))
3854 Reason = PDSA_ConstVarShared;
3855 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3856 ReportHint = true;
3857 Reason = PDSA_LocalVarPrivate;
3858 }
3859 if (Reason != PDSA_Implicit) {
3860 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
3861 SemaRef.Diag(Loc: ReportLoc, DiagID: diag::note_omp_predetermined_dsa)
3862 << Reason << ReportHint
3863 << getOpenMPDirectiveName(D: Stack->getCurrentDirective(), V: OMPVersion);
3864 } else if (DVar.ImplicitDSALoc.isValid()) {
3865 SemaRef.Diag(Loc: DVar.ImplicitDSALoc, DiagID: diag::note_omp_implicit_dsa)
3866 << getOpenMPClauseNameForDiag(C: DVar.CKind);
3867 }
3868}
3869
3870static OpenMPMapClauseKind
3871getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
3872 bool IsAggregateOrDeclareTarget,
3873 bool HasConstQualifier) {
3874 OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
3875 switch (M) {
3876 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3877 case OMPC_DEFAULTMAP_MODIFIER_storage:
3878 Kind = OMPC_MAP_alloc;
3879 break;
3880 case OMPC_DEFAULTMAP_MODIFIER_to:
3881 Kind = OMPC_MAP_to;
3882 break;
3883 case OMPC_DEFAULTMAP_MODIFIER_from:
3884 Kind = OMPC_MAP_from;
3885 break;
3886 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3887 Kind = OMPC_MAP_tofrom;
3888 break;
3889 case OMPC_DEFAULTMAP_MODIFIER_present:
3890 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3891 // If implicit-behavior is present, each variable referenced in the
3892 // construct in the category specified by variable-category is treated as if
3893 // it had been listed in a map clause with the map-type of alloc and
3894 // map-type-modifier of present.
3895 Kind = OMPC_MAP_alloc;
3896 break;
3897 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3898 case OMPC_DEFAULTMAP_MODIFIER_private:
3899 case OMPC_DEFAULTMAP_MODIFIER_last:
3900 llvm_unreachable("Unexpected defaultmap implicit behavior");
3901 case OMPC_DEFAULTMAP_MODIFIER_none:
3902 case OMPC_DEFAULTMAP_MODIFIER_default:
3903 case OMPC_DEFAULTMAP_MODIFIER_unknown:
3904 // IsAggregateOrDeclareTarget could be true if:
3905 // 1. the implicit behavior for aggregate is tofrom
3906 // 2. it's a declare target link
3907 if (IsAggregateOrDeclareTarget) {
3908 if (HasConstQualifier)
3909 Kind = OMPC_MAP_to;
3910 else
3911 Kind = OMPC_MAP_tofrom;
3912 break;
3913 }
3914 llvm_unreachable("Unexpected defaultmap implicit behavior");
3915 }
3916 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3917 return Kind;
3918}
3919
3920static bool hasNoMutableFields(const CXXRecordDecl *RD) {
3921 for (const auto *FD : RD->fields()) {
3922 if (FD->isMutable())
3923 return false;
3924 QualType FT = FD->getType();
3925 while (FT->isArrayType())
3926 FT = FT->getAsArrayTypeUnsafe()->getElementType();
3927 if (const auto *NestedRD = FT->getAsCXXRecordDecl())
3928 if (!hasNoMutableFields(RD: NestedRD))
3929 return false;
3930 }
3931 return true;
3932}
3933
3934static bool hasConstQualifiedMappingType(QualType T) {
3935 while (T->isArrayType())
3936 T = T->getAsArrayTypeUnsafe()->getElementType();
3937 if (!T.isConstQualified())
3938 return false;
3939 if (const auto *RD = T->getAsCXXRecordDecl())
3940 // TODO : Per OpenMP 6.0 p299 lines 3-4, non-mutable members of a
3941 // const-qualified struct should also be ignored for 'from'. This
3942 // requires per-member mapping granularity via compiler-generated
3943 // default mappers and a mechanism to ensure constness to the mapper.
3944 // For now we conservatively treat any struct with mutable members as
3945 // requiring full 'tofrom'.
3946 return hasNoMutableFields(RD);
3947 return true;
3948}
3949
3950namespace {
3951struct VariableImplicitInfo {
3952 static const unsigned MapKindNum = OMPC_MAP_unknown;
3953 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3954
3955 llvm::SetVector<Expr *> Privates;
3956 llvm::SetVector<Expr *> Firstprivates;
3957 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3958 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3959 MapModifiers[DefaultmapKindNum];
3960};
3961
3962class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3963 DSAStackTy *Stack;
3964 Sema &SemaRef;
3965 OpenMPDirectiveKind DKind = OMPD_unknown;
3966 bool ErrorFound = false;
3967 bool TryCaptureCXXThisMembers = false;
3968 CapturedStmt *CS = nullptr;
3969
3970 VariableImplicitInfo ImpInfo;
3971 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3972 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3973
3974 void VisitSubCaptures(OMPExecutableDirective *S) {
3975 // Check implicitly captured variables.
3976 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3977 return;
3978 if (S->getDirectiveKind() == OMPD_atomic ||
3979 S->getDirectiveKind() == OMPD_critical ||
3980 S->getDirectiveKind() == OMPD_section ||
3981 S->getDirectiveKind() == OMPD_master ||
3982 S->getDirectiveKind() == OMPD_masked ||
3983 S->getDirectiveKind() == OMPD_scope ||
3984 S->getDirectiveKind() == OMPD_assume ||
3985 isOpenMPLoopTransformationDirective(DKind: S->getDirectiveKind())) {
3986 Visit(S: S->getAssociatedStmt());
3987 return;
3988 }
3989 visitSubCaptures(S: S->getInnermostCapturedStmt());
3990 // Try to capture inner this->member references to generate correct mappings
3991 // and diagnostics.
3992 if (TryCaptureCXXThisMembers ||
3993 (isOpenMPTargetExecutionDirective(DKind) &&
3994 llvm::any_of(Range: S->getInnermostCapturedStmt()->captures(),
3995 P: [](const CapturedStmt::Capture &C) {
3996 return C.capturesThis();
3997 }))) {
3998 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3999 TryCaptureCXXThisMembers = true;
4000 Visit(S: S->getInnermostCapturedStmt()->getCapturedStmt());
4001 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
4002 }
4003 // In tasks firstprivates are not captured anymore, need to analyze them
4004 // explicitly.
4005 if (isOpenMPTaskingDirective(Kind: S->getDirectiveKind()) &&
4006 !isOpenMPTaskLoopDirective(DKind: S->getDirectiveKind())) {
4007 for (OMPClause *C : S->clauses())
4008 if (auto *FC = dyn_cast<OMPFirstprivateClause>(Val: C)) {
4009 for (Expr *Ref : FC->varlist())
4010 Visit(S: Ref);
4011 }
4012 }
4013 }
4014
4015public:
4016 void VisitDeclRefExpr(DeclRefExpr *E) {
4017 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
4018 E->isValueDependent() || E->containsUnexpandedParameterPack() ||
4019 E->isInstantiationDependent() ||
4020 E->isNonOdrUse() == clang::NOUR_Unevaluated)
4021 return;
4022 if (auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
4023 // Check the datasharing rules for the expressions in the clauses.
4024 if (!CS || (isa<OMPCapturedExprDecl>(Val: VD) && !CS->capturesVariable(Var: VD) &&
4025 !Stack->getTopDSA(D: VD, /*FromParent=*/false).RefExpr &&
4026 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
4027 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: VD))
4028 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
4029 Visit(S: CED->getInit());
4030 return;
4031 }
4032 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(Val: VD))
4033 // Do not analyze internal variables and do not enclose them into
4034 // implicit clauses.
4035 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
4036 return;
4037 VD = VD->getCanonicalDecl();
4038 // Skip internally declared variables.
4039 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(Var: VD) &&
4040 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4041 !Stack->isImplicitTaskFirstprivate(D: VD))
4042 return;
4043 // Skip allocators in uses_allocators clauses.
4044 if (Stack->isUsesAllocatorsDecl(D: VD))
4045 return;
4046
4047 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D: VD, /*FromParent=*/false);
4048 // Check if the variable has explicit DSA set and stop analysis if it so.
4049 if (DVar.RefExpr || !ImplicitDeclarations.insert(V: VD).second)
4050 return;
4051
4052 // Skip internally declared static variables.
4053 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
4054 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
4055 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(Var: VD) &&
4056 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
4057 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
4058 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4059 !Stack->isImplicitTaskFirstprivate(D: VD))
4060 return;
4061
4062 SourceLocation ELoc = E->getExprLoc();
4063 // The default(none) clause requires that each variable that is referenced
4064 // in the construct, and does not have a predetermined data-sharing
4065 // attribute, must have its data-sharing attribute explicitly determined
4066 // by being listed in a data-sharing attribute clause.
4067 if (DVar.CKind == OMPC_unknown &&
4068 (Stack->getDefaultDSA() == DSA_none ||
4069 Stack->getDefaultDSA() == DSA_private ||
4070 Stack->getDefaultDSA() == DSA_firstprivate) &&
4071 isImplicitOrExplicitTaskingRegion(DKind) &&
4072 VarsWithInheritedDSA.count(Val: VD) == 0) {
4073 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4074 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4075 Stack->getDefaultDSA() == DSA_private)) {
4076 DSAStackTy::DSAVarData DVar =
4077 Stack->getImplicitDSA(D: VD, /*FromParent=*/false);
4078 InheritedDSA = DVar.CKind == OMPC_unknown;
4079 }
4080 if (InheritedDSA)
4081 VarsWithInheritedDSA[VD] = E;
4082 if (Stack->getDefaultDSA() == DSA_none)
4083 return;
4084 }
4085
4086 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
4087 // If implicit-behavior is none, each variable referenced in the
4088 // construct that does not have a predetermined data-sharing attribute
4089 // and does not appear in a to or link clause on a declare target
4090 // directive must be listed in a data-mapping attribute clause, a
4091 // data-sharing attribute clause (including a data-sharing attribute
4092 // clause on a combined construct where target. is one of the
4093 // constituent constructs), or an is_device_ptr clause.
4094 OpenMPDefaultmapClauseKind ClauseKind =
4095 getVariableCategoryFromDecl(LO: SemaRef.getLangOpts(), VD);
4096 if (SemaRef.getLangOpts().OpenMP >= 50) {
4097 bool IsModifierNone = Stack->getDefaultmapModifier(Kind: ClauseKind) ==
4098 OMPC_DEFAULTMAP_MODIFIER_none;
4099 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4100 VarsWithInheritedDSA.count(Val: VD) == 0 && !Res) {
4101 // Only check for data-mapping attribute and is_device_ptr here
4102 // since we have already make sure that the declaration does not
4103 // have a data-sharing attribute above
4104 if (!Stack->checkMappableExprComponentListsForDecl(
4105 VD, /*CurrentRegionOnly=*/true,
4106 Check: [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
4107 MapExprComponents,
4108 OpenMPClauseKind) {
4109 auto MI = MapExprComponents.rbegin();
4110 auto ME = MapExprComponents.rend();
4111 return MI != ME && MI->getAssociatedDeclaration() == VD;
4112 })) {
4113 VarsWithInheritedDSA[VD] = E;
4114 return;
4115 }
4116 }
4117 }
4118 if (SemaRef.getLangOpts().OpenMP > 50) {
4119 bool IsModifierPresent = Stack->getDefaultmapModifier(Kind: ClauseKind) ==
4120 OMPC_DEFAULTMAP_MODIFIER_present;
4121 if (IsModifierPresent) {
4122 if (!llvm::is_contained(Range&: ImpInfo.MapModifiers[ClauseKind],
4123 Element: OMPC_MAP_MODIFIER_present)) {
4124 ImpInfo.MapModifiers[ClauseKind].push_back(
4125 Elt: OMPC_MAP_MODIFIER_present);
4126 }
4127 }
4128 }
4129
4130 if (isOpenMPTargetExecutionDirective(DKind) &&
4131 !Stack->isLoopControlVariable(D: VD).first) {
4132 if (!Stack->checkMappableExprComponentListsForDecl(
4133 VD, /*CurrentRegionOnly=*/true,
4134 Check: [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
4135 StackComponents,
4136 OpenMPClauseKind) {
4137 if (SemaRef.LangOpts.OpenMP >= 50)
4138 return !StackComponents.empty();
4139 // Variable is used if it has been marked as an array, array
4140 // section, array shaping or the variable itself.
4141 return StackComponents.size() == 1 ||
4142 llvm::all_of(
4143 Range: llvm::drop_begin(RangeOrContainer: llvm::reverse(C&: StackComponents)),
4144 P: [](const OMPClauseMappableExprCommon::
4145 MappableComponent &MC) {
4146 return MC.getAssociatedDeclaration() ==
4147 nullptr &&
4148 (isa<ArraySectionExpr>(
4149 Val: MC.getAssociatedExpression()) ||
4150 isa<OMPArrayShapingExpr>(
4151 Val: MC.getAssociatedExpression()) ||
4152 isa<ArraySubscriptExpr>(
4153 Val: MC.getAssociatedExpression()));
4154 });
4155 })) {
4156 bool IsFirstprivate = false;
4157 // By default lambdas are captured as firstprivates.
4158 if (const auto *RD =
4159 VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
4160 IsFirstprivate = RD->isLambda();
4161 IsFirstprivate =
4162 IsFirstprivate || (Stack->mustBeFirstprivate(Kind: ClauseKind) && !Res);
4163 if (IsFirstprivate) {
4164 ImpInfo.Firstprivates.insert(X: E);
4165 } else {
4166 OpenMPDefaultmapClauseModifier M =
4167 Stack->getDefaultmapModifier(Kind: ClauseKind);
4168 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4169 ImpInfo.Privates.insert(X: E);
4170 } else {
4171 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
4172 M, IsAggregateOrDeclareTarget: ClauseKind == OMPC_DEFAULTMAP_aggregate || Res,
4173 HasConstQualifier: hasConstQualifiedMappingType(T: E->getType()));
4174 ImpInfo.Mappings[ClauseKind][Kind].insert(X: E);
4175 }
4176 }
4177 return;
4178 }
4179 }
4180
4181 // OpenMP [2.9.3.6, Restrictions, p.2]
4182 // A list item that appears in a reduction clause of the innermost
4183 // enclosing worksharing or parallel construct may not be accessed in an
4184 // explicit task.
4185 DVar = Stack->hasInnermostDSA(
4186 D: VD,
4187 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
4188 return C == OMPC_reduction && !AppliedToPointee;
4189 },
4190 DPred: [](OpenMPDirectiveKind K) {
4191 return isOpenMPParallelDirective(DKind: K) ||
4192 isOpenMPWorksharingDirective(DKind: K) || isOpenMPTeamsDirective(DKind: K);
4193 },
4194 /*FromParent=*/true);
4195 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind == OMPC_reduction) {
4196 ErrorFound = true;
4197 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_in_task);
4198 reportOriginalDsa(SemaRef, Stack, D: VD, DVar);
4199 return;
4200 }
4201
4202 // Define implicit data-sharing attributes for task.
4203 DVar = Stack->getImplicitDSA(D: VD, /*FromParent=*/false);
4204 if (((isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind != OMPC_shared) ||
4205 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4206 DVar.CKind == OMPC_firstprivate) ||
4207 (Stack->getDefaultDSA() == DSA_private &&
4208 DVar.CKind == OMPC_private)) &&
4209 !DVar.RefExpr)) &&
4210 !Stack->isLoopControlVariable(D: VD).first) {
4211 if (Stack->getDefaultDSA() == DSA_private)
4212 ImpInfo.Privates.insert(X: E);
4213 else
4214 ImpInfo.Firstprivates.insert(X: E);
4215 return;
4216 }
4217
4218 // Store implicitly used globals with declare target link for parent
4219 // target.
4220 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
4221 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4222 Stack->addToParentTargetRegionLinkGlobals(E);
4223 return;
4224 }
4225 }
4226 }
4227 void VisitMemberExpr(MemberExpr *E) {
4228 if (E->isTypeDependent() || E->isValueDependent() ||
4229 E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
4230 return;
4231 auto *FD = dyn_cast<FieldDecl>(Val: E->getMemberDecl());
4232 if (auto *TE = dyn_cast<CXXThisExpr>(Val: E->getBase()->IgnoreParenCasts())) {
4233 if (!FD)
4234 return;
4235 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D: FD, /*FromParent=*/false);
4236 // Check if the variable has explicit DSA set and stop analysis if it
4237 // so.
4238 if (DVar.RefExpr || !ImplicitDeclarations.insert(V: FD).second)
4239 return;
4240
4241 if (isOpenMPTargetExecutionDirective(DKind) &&
4242 !Stack->isLoopControlVariable(D: FD).first &&
4243 !Stack->checkMappableExprComponentListsForDecl(
4244 VD: FD, /*CurrentRegionOnly=*/true,
4245 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef
4246 StackComponents,
4247 OpenMPClauseKind) {
4248 return isa<CXXThisExpr>(
4249 Val: cast<MemberExpr>(
4250 Val: StackComponents.back().getAssociatedExpression())
4251 ->getBase()
4252 ->IgnoreParens());
4253 })) {
4254 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4255 // A bit-field cannot appear in a map clause.
4256 //
4257 if (FD->isBitField())
4258 return;
4259
4260 // Check to see if the member expression is referencing a class that
4261 // has already been explicitly mapped
4262 if (Stack->isClassPreviouslyMapped(QT: TE->getType()))
4263 return;
4264
4265 OpenMPDefaultmapClauseModifier Modifier =
4266 Stack->getDefaultmapModifier(Kind: OMPC_DEFAULTMAP_aggregate);
4267 OpenMPDefaultmapClauseKind ClauseKind =
4268 getVariableCategoryFromDecl(LO: SemaRef.getLangOpts(), VD: FD);
4269 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
4270 M: Modifier, /*IsAggregateOrDeclareTarget=*/true,
4271 /*HasConstQualifier=*/false);
4272 ImpInfo.Mappings[ClauseKind][Kind].insert(X: E);
4273 return;
4274 }
4275
4276 SourceLocation ELoc = E->getExprLoc();
4277 // OpenMP [2.9.3.6, Restrictions, p.2]
4278 // A list item that appears in a reduction clause of the innermost
4279 // enclosing worksharing or parallel construct may not be accessed in
4280 // an explicit task.
4281 DVar = Stack->hasInnermostDSA(
4282 D: FD,
4283 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
4284 return C == OMPC_reduction && !AppliedToPointee;
4285 },
4286 DPred: [](OpenMPDirectiveKind K) {
4287 return isOpenMPParallelDirective(DKind: K) ||
4288 isOpenMPWorksharingDirective(DKind: K) || isOpenMPTeamsDirective(DKind: K);
4289 },
4290 /*FromParent=*/true);
4291 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind == OMPC_reduction) {
4292 ErrorFound = true;
4293 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_in_task);
4294 reportOriginalDsa(SemaRef, Stack, D: FD, DVar);
4295 return;
4296 }
4297
4298 // Define implicit data-sharing attributes for task.
4299 DVar = Stack->getImplicitDSA(D: FD, /*FromParent=*/false);
4300 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind != OMPC_shared &&
4301 !Stack->isLoopControlVariable(D: FD).first) {
4302 // Check if there is a captured expression for the current field in the
4303 // region. Do not mark it as firstprivate unless there is no captured
4304 // expression.
4305 // TODO: try to make it firstprivate.
4306 if (DVar.CKind != OMPC_unknown)
4307 ImpInfo.Firstprivates.insert(X: E);
4308 }
4309 return;
4310 }
4311 if (isOpenMPTargetExecutionDirective(DKind)) {
4312 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
4313 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, CKind: OMPC_map,
4314 DKind, /*NoDiagnose=*/true))
4315 return;
4316 const auto *VD = cast<ValueDecl>(
4317 Val: CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4318 if (!Stack->checkMappableExprComponentListsForDecl(
4319 VD, /*CurrentRegionOnly=*/true,
4320 Check: [&CurComponents](
4321 OMPClauseMappableExprCommon::MappableExprComponentListRef
4322 StackComponents,
4323 OpenMPClauseKind) {
4324 auto CCI = CurComponents.rbegin();
4325 auto CCE = CurComponents.rend();
4326 for (const auto &SC : llvm::reverse(C&: StackComponents)) {
4327 // Do both expressions have the same kind?
4328 if (CCI->getAssociatedExpression()->getStmtClass() !=
4329 SC.getAssociatedExpression()->getStmtClass())
4330 if (!((isa<ArraySectionExpr>(
4331 Val: SC.getAssociatedExpression()) ||
4332 isa<OMPArrayShapingExpr>(
4333 Val: SC.getAssociatedExpression())) &&
4334 isa<ArraySubscriptExpr>(
4335 Val: CCI->getAssociatedExpression())))
4336 return false;
4337
4338 const Decl *CCD = CCI->getAssociatedDeclaration();
4339 const Decl *SCD = SC.getAssociatedDeclaration();
4340 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4341 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4342 if (SCD != CCD)
4343 return false;
4344 std::advance(i&: CCI, n: 1);
4345 if (CCI == CCE)
4346 break;
4347 }
4348 return true;
4349 })) {
4350 Visit(S: E->getBase());
4351 }
4352 } else if (!TryCaptureCXXThisMembers) {
4353 Visit(S: E->getBase());
4354 }
4355 }
4356 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4357 for (OMPClause *C : S->clauses()) {
4358 // Skip analysis of arguments of private clauses for task|target
4359 // directives.
4360 if (isa_and_nonnull<OMPPrivateClause>(Val: C))
4361 continue;
4362 // Skip analysis of arguments of implicitly defined firstprivate clause
4363 // for task|target directives.
4364 // Skip analysis of arguments of implicitly defined map clause for target
4365 // directives.
4366 if (C && !((isa<OMPFirstprivateClause>(Val: C) || isa<OMPMapClause>(Val: C)) &&
4367 C->isImplicit() && !isOpenMPTaskingDirective(Kind: DKind))) {
4368 for (Stmt *CC : C->children()) {
4369 if (CC)
4370 Visit(S: CC);
4371 }
4372 }
4373 }
4374 // Check implicitly captured variables.
4375 VisitSubCaptures(S);
4376 }
4377
4378 void VisitOMPCanonicalLoopNestTransformationDirective(
4379 OMPCanonicalLoopNestTransformationDirective *S) {
4380 // Loop transformation directives do not introduce data sharing
4381 VisitStmt(S);
4382 }
4383
4384 void VisitCallExpr(CallExpr *S) {
4385 for (Stmt *C : S->arguments()) {
4386 if (C) {
4387 // Check implicitly captured variables in the task-based directives to
4388 // check if they must be firstprivatized.
4389 Visit(S: C);
4390 }
4391 }
4392 if (Expr *Callee = S->getCallee()) {
4393 auto *CI = Callee->IgnoreParenImpCasts();
4394 if (auto *CE = dyn_cast<MemberExpr>(Val: CI))
4395 Visit(S: CE->getBase());
4396 else if (auto *CE = dyn_cast<DeclRefExpr>(Val: CI))
4397 Visit(S: CE);
4398 }
4399 }
4400 void VisitStmt(Stmt *S) {
4401 for (Stmt *C : S->children()) {
4402 if (C) {
4403 // Check implicitly captured variables in the task-based directives to
4404 // check if they must be firstprivatized.
4405 Visit(S: C);
4406 }
4407 }
4408 }
4409
4410 void visitSubCaptures(CapturedStmt *S) {
4411 for (const CapturedStmt::Capture &Cap : S->captures()) {
4412 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4413 continue;
4414 VarDecl *VD = Cap.getCapturedVar();
4415 // Do not try to map the variable if it or its sub-component was mapped
4416 // already.
4417 if (isOpenMPTargetExecutionDirective(DKind) &&
4418 Stack->checkMappableExprComponentListsForDecl(
4419 VD, /*CurrentRegionOnly=*/true,
4420 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4421 OpenMPClauseKind) { return true; }))
4422 continue;
4423 DeclRefExpr *DRE = buildDeclRefExpr(
4424 S&: SemaRef, D: VD, Ty: VD->getType().getNonLValueExprType(Context: SemaRef.Context),
4425 Loc: Cap.getLocation(), /*RefersToCapture=*/true);
4426 Visit(S: DRE);
4427 }
4428 }
4429 bool isErrorFound() const { return ErrorFound; }
4430 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4431 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4432 return VarsWithInheritedDSA;
4433 }
4434
4435 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4436 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4437 DKind = S->getCurrentDirective();
4438 // Process declare target link variables for the target directives.
4439 if (isOpenMPTargetExecutionDirective(DKind)) {
4440 for (DeclRefExpr *E : Stack->getLinkGlobals())
4441 Visit(S: E);
4442 }
4443 }
4444};
4445} // namespace
4446
4447static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4448 OpenMPDirectiveKind DKind,
4449 bool ScopeEntry) {
4450 SmallVector<llvm::omp::TraitProperty, 8> Traits;
4451 if (isOpenMPTargetExecutionDirective(DKind))
4452 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_target_target);
4453 if (isOpenMPTeamsDirective(DKind))
4454 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_teams_teams);
4455 if (isOpenMPParallelDirective(DKind))
4456 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_parallel_parallel);
4457 if (isOpenMPWorksharingDirective(DKind))
4458 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_for_for);
4459 if (isOpenMPSimdDirective(DKind))
4460 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_simd_simd);
4461 Stack->handleConstructTrait(Traits, ScopeEntry);
4462}
4463
4464static SmallVector<SemaOpenMP::CapturedParamNameType>
4465getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4466 ASTContext &Context = SemaRef.getASTContext();
4467 QualType KmpInt32Ty =
4468 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4469 QualType KmpInt32PtrTy =
4470 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4471 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4472 std::make_pair(x: ".global_tid.", y&: KmpInt32PtrTy),
4473 std::make_pair(x: ".bound_tid.", y&: KmpInt32PtrTy),
4474 };
4475 if (LoopBoundSharing) {
4476 QualType KmpSizeTy = Context.getSizeType().withConst();
4477 Params.push_back(Elt: std::make_pair(x: ".previous.lb.", y&: KmpSizeTy));
4478 Params.push_back(Elt: std::make_pair(x: ".previous.ub.", y&: KmpSizeTy));
4479 }
4480
4481 // __context with shared vars
4482 Params.push_back(Elt: std::make_pair(x: StringRef(), y: QualType()));
4483 return Params;
4484}
4485
4486static SmallVector<SemaOpenMP::CapturedParamNameType>
4487getTeamsRegionParams(Sema &SemaRef) {
4488 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4489}
4490
4491static SmallVector<SemaOpenMP::CapturedParamNameType>
4492getTaskRegionParams(Sema &SemaRef) {
4493 ASTContext &Context = SemaRef.getASTContext();
4494 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(DestWidth: 32, Signed: 1).withConst();
4495 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4496 QualType KmpInt32PtrTy =
4497 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4498 QualType Args[] = {VoidPtrTy};
4499 FunctionProtoType::ExtProtoInfo EPI;
4500 EPI.Variadic = true;
4501 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4502 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4503 std::make_pair(x: ".global_tid.", y&: KmpInt32Ty),
4504 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4505 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4506 std::make_pair(
4507 x: ".copy_fn.",
4508 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4509 std::make_pair(x: ".task_t.", y: Context.VoidPtrTy.withConst()),
4510 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4511 };
4512 return Params;
4513}
4514
4515static SmallVector<SemaOpenMP::CapturedParamNameType>
4516getTargetRegionParams(Sema &SemaRef) {
4517 ASTContext &Context = SemaRef.getASTContext();
4518 SmallVector<SemaOpenMP::CapturedParamNameType> Params;
4519 // __context with shared vars
4520 Params.push_back(Elt: std::make_pair(x: StringRef(), y: QualType()));
4521 // Implicit dyn_ptr argument, appended as the last parameter. Present on both
4522 // host and device so argument counts match without runtime manipulation.
4523 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4524 Params.push_back(Elt: std::make_pair(x: StringRef("dyn_ptr"), y&: VoidPtrTy));
4525 return Params;
4526}
4527
4528static SmallVector<SemaOpenMP::CapturedParamNameType>
4529getUnknownRegionParams(Sema &SemaRef) {
4530 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4531 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4532 };
4533 return Params;
4534}
4535
4536static SmallVector<SemaOpenMP::CapturedParamNameType>
4537getTaskloopRegionParams(Sema &SemaRef) {
4538 ASTContext &Context = SemaRef.getASTContext();
4539 QualType KmpInt32Ty =
4540 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4541 QualType KmpUInt64Ty =
4542 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4543 QualType KmpInt64Ty =
4544 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4545 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4546 QualType KmpInt32PtrTy =
4547 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4548 QualType Args[] = {VoidPtrTy};
4549 FunctionProtoType::ExtProtoInfo EPI;
4550 EPI.Variadic = true;
4551 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4552 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4553 std::make_pair(x: ".global_tid.", y&: KmpInt32Ty),
4554 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4555 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4556 std::make_pair(
4557 x: ".copy_fn.",
4558 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4559 std::make_pair(x: ".task_t.", y: Context.VoidPtrTy.withConst()),
4560 std::make_pair(x: ".lb.", y&: KmpUInt64Ty),
4561 std::make_pair(x: ".ub.", y&: KmpUInt64Ty),
4562 std::make_pair(x: ".st.", y&: KmpInt64Ty),
4563 std::make_pair(x: ".liter.", y&: KmpInt32Ty),
4564 std::make_pair(x: ".reductions.", y&: VoidPtrTy),
4565 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4566 };
4567 return Params;
4568}
4569
4570static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind,
4571 Scope *CurScope, SourceLocation Loc) {
4572 SmallVector<OpenMPDirectiveKind> Regions;
4573 getOpenMPCaptureRegions(CaptureRegions&: Regions, DKind);
4574
4575 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(Kind: DKind);
4576
4577 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4578 CSI->TheCapturedDecl->addAttr(A: AlwaysInlineAttr::CreateImplicit(
4579 Ctx&: SemaRef.getASTContext(), Range: {}, S: AlwaysInlineAttr::Keyword_forceinline));
4580 };
4581
4582 for (auto [Level, RKind] : llvm::enumerate(First&: Regions)) {
4583 switch (RKind) {
4584 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4585 // are listed here.
4586 case OMPD_parallel:
4587 SemaRef.ActOnCapturedRegionStart(
4588 Loc, CurScope, Kind: CR_OpenMP,
4589 Params: getParallelRegionParams(SemaRef, LoopBoundSharing), OpenMPCaptureLevel: Level);
4590 break;
4591 case OMPD_teams:
4592 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4593 Params: getTeamsRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4594 break;
4595 case OMPD_task:
4596 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4597 Params: getTaskRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4598 // Mark this captured region as inlined, because we don't use outlined
4599 // function directly.
4600 MarkAsInlined(SemaRef.getCurCapturedRegion());
4601 break;
4602 case OMPD_taskloop:
4603 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4604 Params: getTaskloopRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4605 // Mark this captured region as inlined, because we don't use outlined
4606 // function directly.
4607 MarkAsInlined(SemaRef.getCurCapturedRegion());
4608 break;
4609 case OMPD_target:
4610 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4611 Params: getTargetRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4612 break;
4613 case OMPD_unknown:
4614 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4615 Params: getUnknownRegionParams(SemaRef));
4616 break;
4617 case OMPD_metadirective:
4618 case OMPD_nothing:
4619 default:
4620 llvm_unreachable("Unexpected capture region");
4621 }
4622 }
4623}
4624
4625void SemaOpenMP::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,
4626 Scope *CurScope) {
4627 if (DKind == OMPD_ordered_blockassoc &&
4628 DSAStack->getCurrentDirective() == OMPD_ordered_standalone) {
4629 DSAStack->setOrderedToBlockAssociated();
4630 }
4631 switch (DKind) {
4632 case OMPD_atomic:
4633 case OMPD_critical:
4634 case OMPD_masked:
4635 case OMPD_master:
4636 case OMPD_section:
4637 case OMPD_tile:
4638 case OMPD_stripe:
4639 case OMPD_unroll:
4640 case OMPD_reverse:
4641 case OMPD_split:
4642 case OMPD_interchange:
4643 case OMPD_fuse:
4644 case OMPD_assume:
4645 break;
4646 default:
4647 processCapturedRegions(SemaRef, DKind, CurScope,
4648 DSAStack->getConstructLoc());
4649 break;
4650 }
4651
4652 DSAStack->setContext(SemaRef.CurContext);
4653 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4654}
4655
4656int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4657 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4658}
4659
4660int SemaOpenMP::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4661 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4662 getOpenMPCaptureRegions(CaptureRegions, DKind);
4663 return CaptureRegions.size();
4664}
4665
4666static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
4667 Expr *CaptureExpr, bool WithInit,
4668 DeclContext *CurContext,
4669 bool AsExpression) {
4670 assert(CaptureExpr);
4671 ASTContext &C = S.getASTContext();
4672 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4673 QualType Ty = Init->getType();
4674 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4675 if (S.getLangOpts().CPlusPlus) {
4676 Ty = C.getLValueReferenceType(T: Ty);
4677 } else {
4678 Ty = C.getPointerType(T: Ty);
4679 ExprResult Res =
4680 S.CreateBuiltinUnaryOp(OpLoc: CaptureExpr->getExprLoc(), Opc: UO_AddrOf, InputExpr: Init);
4681 if (!Res.isUsable())
4682 return nullptr;
4683 Init = Res.get();
4684 }
4685 WithInit = true;
4686 }
4687 auto *CED = OMPCapturedExprDecl::Create(C, DC: CurContext, Id, T: Ty,
4688 StartLoc: CaptureExpr->getBeginLoc());
4689 if (!WithInit)
4690 CED->addAttr(A: OMPCaptureNoInitAttr::CreateImplicit(Ctx&: C));
4691 CurContext->addHiddenDecl(D: CED);
4692 Sema::TentativeAnalysisScope Trap(S);
4693 S.AddInitializerToDecl(dcl: CED, init: Init, /*DirectInit=*/false);
4694 return CED;
4695}
4696
4697static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4698 bool WithInit) {
4699 OMPCapturedExprDecl *CD;
4700 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4701 CD = cast<OMPCapturedExprDecl>(Val: VD);
4702 else
4703 CD = buildCaptureDecl(S, Id: D->getIdentifier(), CaptureExpr, WithInit,
4704 CurContext: S.CurContext,
4705 /*AsExpression=*/false);
4706 return buildDeclRefExpr(S, D: CD, Ty: CD->getType().getNonReferenceType(),
4707 Loc: CaptureExpr->getExprLoc());
4708}
4709
4710static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4711 StringRef Name) {
4712 CaptureExpr = S.DefaultLvalueConversion(E: CaptureExpr).get();
4713 if (!Ref) {
4714 OMPCapturedExprDecl *CD = buildCaptureDecl(
4715 S, Id: &S.getASTContext().Idents.get(Name), CaptureExpr,
4716 /*WithInit=*/true, CurContext: S.CurContext, /*AsExpression=*/true);
4717 Ref = buildDeclRefExpr(S, D: CD, Ty: CD->getType().getNonReferenceType(),
4718 Loc: CaptureExpr->getExprLoc());
4719 }
4720 ExprResult Res = Ref;
4721 if (!S.getLangOpts().CPlusPlus &&
4722 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4723 Ref->getType()->isPointerType()) {
4724 Res = S.CreateBuiltinUnaryOp(OpLoc: CaptureExpr->getExprLoc(), Opc: UO_Deref, InputExpr: Ref);
4725 if (!Res.isUsable())
4726 return ExprError();
4727 }
4728 return S.DefaultLvalueConversion(E: Res.get());
4729}
4730
4731namespace {
4732// OpenMP directives parsed in this section are represented as a
4733// CapturedStatement with an associated statement. If a syntax error
4734// is detected during the parsing of the associated statement, the
4735// compiler must abort processing and close the CapturedStatement.
4736//
4737// Combined directives such as 'target parallel' have more than one
4738// nested CapturedStatements. This RAII ensures that we unwind out
4739// of all the nested CapturedStatements when an error is found.
4740class CaptureRegionUnwinderRAII {
4741private:
4742 Sema &S;
4743 bool &ErrorFound;
4744 OpenMPDirectiveKind DKind = OMPD_unknown;
4745
4746public:
4747 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4748 OpenMPDirectiveKind DKind)
4749 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4750 ~CaptureRegionUnwinderRAII() {
4751 if (ErrorFound) {
4752 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4753 while (--ThisCaptureLevel >= 0)
4754 S.ActOnCapturedRegionError();
4755 }
4756 }
4757};
4758} // namespace
4759
4760void SemaOpenMP::tryCaptureOpenMPLambdas(ValueDecl *V) {
4761 // Capture variables captured by reference in lambdas for target-based
4762 // directives.
4763 if (!SemaRef.CurContext->isDependentContext() &&
4764 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4765 isOpenMPTargetDataManagementDirective(
4766 DSAStack->getCurrentDirective()))) {
4767 QualType Type = V->getType();
4768 if (const auto *RD = Type.getCanonicalType()
4769 .getNonReferenceType()
4770 ->getAsCXXRecordDecl()) {
4771 bool SavedForceCaptureByReferenceInTargetExecutable =
4772 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4773 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4774 /*V=*/true);
4775 if (RD->isLambda()) {
4776 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4777 FieldDecl *ThisCapture;
4778 RD->getCaptureFields(Captures, ThisCapture);
4779 for (const LambdaCapture &LC : RD->captures()) {
4780 if (LC.getCaptureKind() == LCK_ByRef) {
4781 VarDecl *VD = cast<VarDecl>(Val: LC.getCapturedVar());
4782 DeclContext *VDC = VD->getDeclContext();
4783 if (!VDC->Encloses(DC: SemaRef.CurContext))
4784 continue;
4785 SemaRef.MarkVariableReferenced(Loc: LC.getLocation(), Var: VD);
4786 } else if (LC.getCaptureKind() == LCK_This) {
4787 QualType ThisTy = SemaRef.getCurrentThisType();
4788 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4789 T1: ThisTy, T2: ThisCapture->getType()))
4790 SemaRef.CheckCXXThisCapture(Loc: LC.getLocation());
4791 }
4792 }
4793 }
4794 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4795 SavedForceCaptureByReferenceInTargetExecutable);
4796 }
4797 }
4798}
4799
4800static bool checkOrderedOrderSpecified(Sema &S,
4801 const ArrayRef<OMPClause *> Clauses) {
4802 const OMPOrderedClause *Ordered = nullptr;
4803 const OMPOrderClause *Order = nullptr;
4804
4805 for (const OMPClause *Clause : Clauses) {
4806 if (Clause->getClauseKind() == OMPC_ordered)
4807 Ordered = cast<OMPOrderedClause>(Val: Clause);
4808 else if (Clause->getClauseKind() == OMPC_order) {
4809 Order = cast<OMPOrderClause>(Val: Clause);
4810 if (Order->getKind() != OMPC_ORDER_concurrent)
4811 Order = nullptr;
4812 }
4813 if (Ordered && Order)
4814 break;
4815 }
4816
4817 if (Ordered && Order) {
4818 S.Diag(Loc: Order->getKindKwLoc(),
4819 DiagID: diag::err_omp_simple_clause_incompatible_with_ordered)
4820 << getOpenMPClauseNameForDiag(C: OMPC_order)
4821 << getOpenMPSimpleClauseTypeName(Kind: OMPC_order, Type: OMPC_ORDER_concurrent)
4822 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4823 S.Diag(Loc: Ordered->getBeginLoc(), DiagID: diag::note_omp_ordered_param)
4824 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4825 return true;
4826 }
4827 return false;
4828}
4829
4830StmtResult SemaOpenMP::ActOnOpenMPRegionEnd(StmtResult S,
4831 ArrayRef<OMPClause *> Clauses) {
4832 handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(),
4833 /*ScopeEntry=*/false);
4834 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4835 return S;
4836
4837 bool ErrorFound = false;
4838 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4839 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4840 if (!S.isUsable()) {
4841 ErrorFound = true;
4842 return StmtError();
4843 }
4844
4845 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4846 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4847 OMPOrderedClause *OC = nullptr;
4848 OMPScheduleClause *SC = nullptr;
4849 SmallVector<const OMPLinearClause *, 4> LCs;
4850 SmallVector<const OMPClauseWithPreInit *, 4> PICs;
4851 // This is required for proper codegen.
4852 for (OMPClause *Clause : Clauses) {
4853 if (!getLangOpts().OpenMPSimd &&
4854 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4855 DSAStack->getCurrentDirective() == OMPD_target) &&
4856 Clause->getClauseKind() == OMPC_in_reduction) {
4857 // Capture taskgroup task_reduction descriptors inside the tasking regions
4858 // with the corresponding in_reduction items.
4859 auto *IRC = cast<OMPInReductionClause>(Val: Clause);
4860 for (Expr *E : IRC->taskgroup_descriptors())
4861 if (E)
4862 SemaRef.MarkDeclarationsReferencedInExpr(E);
4863 }
4864 if (isOpenMPPrivate(Kind: Clause->getClauseKind()) ||
4865 Clause->getClauseKind() == OMPC_copyprivate ||
4866 (getLangOpts().OpenMPUseTLS &&
4867 getASTContext().getTargetInfo().isTLSSupported() &&
4868 Clause->getClauseKind() == OMPC_copyin)) {
4869 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4870 // Mark all variables in private list clauses as used in inner region.
4871 for (Stmt *VarRef : Clause->children()) {
4872 if (auto *E = cast_or_null<Expr>(Val: VarRef)) {
4873 SemaRef.MarkDeclarationsReferencedInExpr(E);
4874 }
4875 }
4876 DSAStack->setForceVarCapturing(/*V=*/false);
4877 } else if (CaptureRegions.size() > 1 ||
4878 CaptureRegions.back() != OMPD_unknown) {
4879 if (auto *C = OMPClauseWithPreInit::get(C: Clause))
4880 PICs.push_back(Elt: C);
4881 if (auto *C = OMPClauseWithPostUpdate::get(C: Clause)) {
4882 if (Expr *E = C->getPostUpdateExpr())
4883 SemaRef.MarkDeclarationsReferencedInExpr(E);
4884 }
4885 }
4886 if (Clause->getClauseKind() == OMPC_schedule)
4887 SC = cast<OMPScheduleClause>(Val: Clause);
4888 else if (Clause->getClauseKind() == OMPC_ordered)
4889 OC = cast<OMPOrderedClause>(Val: Clause);
4890 else if (Clause->getClauseKind() == OMPC_linear)
4891 LCs.push_back(Elt: cast<OMPLinearClause>(Val: Clause));
4892 }
4893 // Capture allocator expressions if used.
4894 for (Expr *E : DSAStack->getInnerAllocators())
4895 SemaRef.MarkDeclarationsReferencedInExpr(E);
4896 // OpenMP, 2.7.1 Loop Construct, Restrictions
4897 // The nonmonotonic modifier cannot be specified if an ordered clause is
4898 // specified.
4899 if (SC &&
4900 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4901 SC->getSecondScheduleModifier() ==
4902 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4903 OC) {
4904 Diag(Loc: SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4905 ? SC->getFirstScheduleModifierLoc()
4906 : SC->getSecondScheduleModifierLoc(),
4907 DiagID: diag::err_omp_simple_clause_incompatible_with_ordered)
4908 << getOpenMPClauseNameForDiag(C: OMPC_schedule)
4909 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule,
4910 Type: OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4911 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4912 ErrorFound = true;
4913 }
4914 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4915 // If an order(concurrent) clause is present, an ordered clause may not appear
4916 // on the same directive.
4917 if (checkOrderedOrderSpecified(S&: SemaRef, Clauses))
4918 ErrorFound = true;
4919 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4920 for (const OMPLinearClause *C : LCs) {
4921 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_linear_ordered)
4922 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4923 }
4924 ErrorFound = true;
4925 }
4926 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4927 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4928 OC->getNumForLoops()) {
4929 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
4930 Diag(Loc: OC->getBeginLoc(), DiagID: diag::err_omp_ordered_simd)
4931 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), V: OMPVersion);
4932 ErrorFound = true;
4933 }
4934 if (ErrorFound) {
4935 return StmtError();
4936 }
4937 StmtResult SR = S;
4938 unsigned CompletedRegions = 0;
4939 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(C&: CaptureRegions)) {
4940 // Mark all variables in private list clauses as used in inner region.
4941 // Required for proper codegen of combined directives.
4942 // TODO: add processing for other clauses.
4943 if (ThisCaptureRegion != OMPD_unknown) {
4944 for (const clang::OMPClauseWithPreInit *C : PICs) {
4945 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4946 // Find the particular capture region for the clause if the
4947 // directive is a combined one with multiple capture regions.
4948 // If the directive is not a combined one, the capture region
4949 // associated with the clause is OMPD_unknown and is generated
4950 // only once.
4951 if (CaptureRegion == ThisCaptureRegion ||
4952 CaptureRegion == OMPD_unknown) {
4953 if (auto *DS = cast_or_null<DeclStmt>(Val: C->getPreInitStmt())) {
4954 for (Decl *D : DS->decls())
4955 SemaRef.MarkVariableReferenced(Loc: D->getLocation(),
4956 Var: cast<VarDecl>(Val: D));
4957 }
4958 }
4959 }
4960 }
4961 if (ThisCaptureRegion == OMPD_target) {
4962 // Capture allocator traits in the target region. They are used implicitly
4963 // and, thus, are not captured by default.
4964 for (OMPClause *C : Clauses) {
4965 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(Val: C)) {
4966 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4967 ++I) {
4968 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4969 if (Expr *E = D.AllocatorTraits)
4970 SemaRef.MarkDeclarationsReferencedInExpr(E);
4971 }
4972 continue;
4973 }
4974 }
4975 }
4976 if (ThisCaptureRegion == OMPD_parallel) {
4977 // Capture temp arrays for inscan reductions and locals in aligned
4978 // clauses.
4979 for (OMPClause *C : Clauses) {
4980 if (auto *RC = dyn_cast<OMPReductionClause>(Val: C)) {
4981 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4982 continue;
4983 for (Expr *E : RC->copy_array_temps())
4984 if (E)
4985 SemaRef.MarkDeclarationsReferencedInExpr(E);
4986 }
4987 if (auto *AC = dyn_cast<OMPAlignedClause>(Val: C)) {
4988 for (Expr *E : AC->varlist())
4989 SemaRef.MarkDeclarationsReferencedInExpr(E);
4990 }
4991 }
4992 }
4993 if (++CompletedRegions == CaptureRegions.size())
4994 DSAStack->setBodyComplete();
4995 SR = SemaRef.ActOnCapturedRegionEnd(S: SR.get());
4996 }
4997 return SR;
4998}
4999
5000static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
5001 OpenMPDirectiveKind CancelRegion,
5002 SourceLocation StartLoc) {
5003 // CancelRegion is only needed for cancel and cancellation_point.
5004 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
5005 return false;
5006
5007 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
5008 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
5009 return false;
5010
5011 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
5012 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_wrong_cancel_region)
5013 << getOpenMPDirectiveName(D: CancelRegion, V: OMPVersion);
5014 return true;
5015}
5016
5017static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
5018 OpenMPDirectiveKind CurrentRegion,
5019 const DeclarationNameInfo &CurrentName,
5020 OpenMPDirectiveKind CancelRegion,
5021 OpenMPBindClauseKind BindKind,
5022 SourceLocation StartLoc) {
5023 if (!Stack->getCurScope())
5024 return false;
5025
5026 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
5027 OpenMPDirectiveKind OffendingRegion = ParentRegion;
5028 bool NestingProhibited = false;
5029 bool CloseNesting = true;
5030 bool OrphanSeen = false;
5031 enum {
5032 NoRecommend,
5033 ShouldBeInParallelRegion,
5034 ShouldBeInOrderedRegion,
5035 ShouldBeInTargetRegion,
5036 ShouldBeInTeamsRegion,
5037 ShouldBeInLoopSimdRegion,
5038 } Recommend = NoRecommend;
5039
5040 SmallVector<OpenMPDirectiveKind, 4> LeafOrComposite;
5041 ArrayRef<OpenMPDirectiveKind> ParentLOC =
5042 getLeafOrCompositeConstructs(D: ParentRegion, Output&: LeafOrComposite);
5043 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
5044 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
5045
5046 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
5047 !isOpenMPOrderConcurrentNestableDirective(DKind: CurrentRegion,
5048 LangOpts: SemaRef.LangOpts)) {
5049 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_order)
5050 << getOpenMPDirectiveName(D: CurrentRegion, V: OMPVersion);
5051 return true;
5052 }
5053 if (isOpenMPSimdDirective(DKind: ParentRegion) &&
5054 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered_blockassoc) ||
5055 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered_blockassoc &&
5056 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5057 CurrentRegion != OMPD_scan))) {
5058 // OpenMP [2.16, Nesting of Regions]
5059 // OpenMP constructs may not be nested inside a simd region.
5060 // OpenMP [2.8.1,simd Construct, Restrictions]
5061 // An ordered construct with the simd clause is the only OpenMP
5062 // construct that can appear in the simd region.
5063 // Allowing a SIMD construct nested in another SIMD construct is an
5064 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5065 // message.
5066 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5067 // The only OpenMP constructs that can be encountered during execution of
5068 // a simd region are the atomic construct, the loop construct, the simd
5069 // construct and the ordered construct with the simd clause.
5070 SemaRef.Diag(Loc: StartLoc, DiagID: (CurrentRegion != OMPD_simd)
5071 ? diag::err_omp_prohibited_region_simd
5072 : diag::warn_omp_nesting_simd)
5073 << (OMPVersion >= 50 ? 1 : 0);
5074 return CurrentRegion != OMPD_simd;
5075 }
5076 if (EnclosingConstruct == OMPD_atomic) {
5077 // OpenMP [2.16, Nesting of Regions]
5078 // OpenMP constructs may not be nested inside an atomic region.
5079 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_atomic);
5080 return true;
5081 }
5082 if (CurrentRegion == OMPD_section) {
5083 // OpenMP [2.7.2, sections Construct, Restrictions]
5084 // Orphaned section directives are prohibited. That is, the section
5085 // directives must appear within the sections construct and must not be
5086 // encountered elsewhere in the sections region.
5087 if (EnclosingConstruct != OMPD_sections) {
5088 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_section_directive)
5089 << (ParentRegion != OMPD_unknown)
5090 << getOpenMPDirectiveName(D: ParentRegion, V: OMPVersion);
5091 return true;
5092 }
5093 return false;
5094 }
5095 // Allow some constructs (except teams and cancellation constructs) to be
5096 // orphaned (they could be used in functions, called from OpenMP regions
5097 // with the required preconditions).
5098 if (ParentRegion == OMPD_unknown &&
5099 !isOpenMPNestingTeamsDirective(DKind: CurrentRegion) &&
5100 CurrentRegion != OMPD_cancellation_point &&
5101 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5102 return false;
5103 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5104 // for a detailed explanation
5105 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5106 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5107 (isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5108 EnclosingConstruct == OMPD_loop)) {
5109 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5110 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region)
5111 << true << getOpenMPDirectiveName(D: ParentRegion, V: OMPVersion)
5112 << ErrorMsgNumber << getOpenMPDirectiveName(D: CurrentRegion, V: OMPVersion);
5113 return true;
5114 }
5115 if (CurrentRegion == OMPD_cancellation_point ||
5116 CurrentRegion == OMPD_cancel) {
5117 // OpenMP [2.16, Nesting of Regions]
5118 // A cancellation point construct for which construct-type-clause is
5119 // taskgroup must be nested inside a task construct. A cancellation
5120 // point construct for which construct-type-clause is not taskgroup must
5121 // be closely nested inside an OpenMP construct that matches the type
5122 // specified in construct-type-clause.
5123 // A cancel construct for which construct-type-clause is taskgroup must be
5124 // nested inside a task construct. A cancel construct for which
5125 // construct-type-clause is not taskgroup must be closely nested inside an
5126 // OpenMP construct that matches the type specified in
5127 // construct-type-clause.
5128 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(D: ParentRegion);
5129 if (CancelRegion == OMPD_taskgroup) {
5130 NestingProhibited =
5131 EnclosingConstruct != OMPD_task &&
5132 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5133 } else if (CancelRegion == OMPD_sections) {
5134 NestingProhibited = EnclosingConstruct != OMPD_section &&
5135 EnclosingConstruct != OMPD_sections;
5136 } else {
5137 NestingProhibited = CancelRegion != Leafs.back();
5138 }
5139 OrphanSeen = ParentRegion == OMPD_unknown;
5140 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5141 // OpenMP 5.1 [2.22, Nesting of Regions]
5142 // A masked region may not be closely nested inside a worksharing, loop,
5143 // atomic, task, or taskloop region.
5144 NestingProhibited = isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5145 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
5146 isOpenMPTaskingDirective(Kind: ParentRegion);
5147 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5148 // OpenMP [2.16, Nesting of Regions]
5149 // A critical region may not be nested (closely or otherwise) inside a
5150 // critical region with the same name. Note that this restriction is not
5151 // sufficient to prevent deadlock.
5152 SourceLocation PreviousCriticalLoc;
5153 bool DeadLock = Stack->hasDirective(
5154 DPred: [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5155 const DeclarationNameInfo &DNI,
5156 SourceLocation Loc) {
5157 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5158 PreviousCriticalLoc = Loc;
5159 return true;
5160 }
5161 return false;
5162 },
5163 FromParent: false /* skip top directive */);
5164 if (DeadLock) {
5165 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_critical_same_name)
5166 << CurrentName.getName();
5167 if (PreviousCriticalLoc.isValid())
5168 SemaRef.Diag(Loc: PreviousCriticalLoc,
5169 DiagID: diag::note_omp_previous_critical_region);
5170 return true;
5171 }
5172 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5173 // OpenMP 5.1 [2.22, Nesting of Regions]
5174 // A scope region may not be closely nested inside a worksharing, loop,
5175 // task, taskloop, critical, ordered, atomic, or masked region.
5176 // OpenMP 5.1 [2.22, Nesting of Regions]
5177 // A barrier region may not be closely nested inside a worksharing, loop,
5178 // task, taskloop, critical, ordered, atomic, or masked region.
5179 NestingProhibited =
5180 isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5181 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
5182 isOpenMPTaskingDirective(Kind: ParentRegion) ||
5183 llvm::is_contained(
5184 Set: {OMPD_masked, OMPD_master, OMPD_critical, OMPD_ordered_blockassoc},
5185 Element: EnclosingConstruct);
5186 } else if (isOpenMPWorksharingDirective(DKind: CurrentRegion) &&
5187 !isOpenMPParallelDirective(DKind: CurrentRegion) &&
5188 !isOpenMPTeamsDirective(DKind: CurrentRegion)) {
5189 // OpenMP 5.1 [2.22, Nesting of Regions]
5190 // A loop region that binds to a parallel region or a worksharing region
5191 // may not be closely nested inside a worksharing, loop, task, taskloop,
5192 // critical, ordered, atomic, or masked region.
5193 NestingProhibited =
5194 isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5195 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
5196 isOpenMPTaskingDirective(Kind: ParentRegion) ||
5197 llvm::is_contained(
5198 Set: {OMPD_masked, OMPD_master, OMPD_critical, OMPD_ordered_blockassoc},
5199 Element: EnclosingConstruct);
5200 Recommend = ShouldBeInParallelRegion;
5201 } else if (CurrentRegion == OMPD_ordered_blockassoc ||
5202 CurrentRegion == OMPD_ordered_standalone) {
5203 // OpenMP [2.16, Nesting of Regions]
5204 // An ordered region may not be closely nested inside a critical,
5205 // atomic, or explicit task region.
5206 // An ordered region must be closely nested inside a loop region (or
5207 // parallel loop region) with an ordered clause.
5208 // OpenMP [2.8.1,simd Construct, Restrictions]
5209 // An ordered construct with the simd clause is the only OpenMP construct
5210 // that can appear in the simd region.
5211 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5212 isOpenMPTaskingDirective(Kind: ParentRegion) ||
5213 !(isOpenMPSimdDirective(DKind: ParentRegion) ||
5214 Stack->isParentOrderedRegion());
5215 Recommend = ShouldBeInOrderedRegion;
5216 } else if (isOpenMPNestingTeamsDirective(DKind: CurrentRegion)) {
5217 // OpenMP [2.16, Nesting of Regions]
5218 // If specified, a teams construct must be contained within a target
5219 // construct.
5220 NestingProhibited =
5221 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5222 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5223 EnclosingConstruct != OMPD_target);
5224 OrphanSeen = ParentRegion == OMPD_unknown;
5225 Recommend = ShouldBeInTargetRegion;
5226 } else if (CurrentRegion == OMPD_scan) {
5227 if (OMPVersion >= 50) {
5228 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
5229 // simd, or for simd. This has to take into account combined directives.
5230 // In 5.2 this seems to be implied by the fact that the specified
5231 // separated constructs are do, for, and simd.
5232 NestingProhibited = !llvm::is_contained(
5233 Set: {OMPD_for, OMPD_simd, OMPD_for_simd}, Element: EnclosingConstruct);
5234 } else {
5235 NestingProhibited = true;
5236 }
5237 OrphanSeen = ParentRegion == OMPD_unknown;
5238 Recommend = ShouldBeInLoopSimdRegion;
5239 }
5240 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(DKind: CurrentRegion) &&
5241 !isOpenMPTargetDataManagementDirective(DKind: CurrentRegion) &&
5242 EnclosingConstruct == OMPD_teams) {
5243 // OpenMP [5.1, 2.22, Nesting of Regions]
5244 // distribute, distribute simd, distribute parallel worksharing-loop,
5245 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5246 // including any parallel regions arising from combined constructs,
5247 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5248 // only OpenMP regions that may be strictly nested inside the teams
5249 // region.
5250 //
5251 // As an extension, we permit atomic within teams as well.
5252 NestingProhibited = !isOpenMPParallelDirective(DKind: CurrentRegion) &&
5253 !isOpenMPDistributeDirective(DKind: CurrentRegion) &&
5254 CurrentRegion != OMPD_loop &&
5255 !(SemaRef.getLangOpts().OpenMPExtensions &&
5256 CurrentRegion == OMPD_atomic);
5257 Recommend = ShouldBeInParallelRegion;
5258 }
5259 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5260 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5261 // If the bind clause is present on the loop construct and binding is
5262 // teams then the corresponding loop region must be strictly nested inside
5263 // a teams region.
5264 NestingProhibited =
5265 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5266 Recommend = ShouldBeInTeamsRegion;
5267 }
5268 if (!NestingProhibited && isOpenMPNestingDistributeDirective(DKind: CurrentRegion)) {
5269 // OpenMP 4.5 [2.17 Nesting of Regions]
5270 // The region associated with the distribute construct must be strictly
5271 // nested inside a teams region
5272 NestingProhibited = EnclosingConstruct != OMPD_teams;
5273 Recommend = ShouldBeInTeamsRegion;
5274 }
5275 if (!NestingProhibited &&
5276 (isOpenMPTargetExecutionDirective(DKind: CurrentRegion) ||
5277 isOpenMPTargetDataManagementDirective(DKind: CurrentRegion))) {
5278 // OpenMP 4.5 [2.17 Nesting of Regions]
5279 // If a target, target update, target data, target enter data, or
5280 // target exit data construct is encountered during execution of a
5281 // target region, the behavior is unspecified.
5282 NestingProhibited = Stack->hasDirective(
5283 DPred: [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5284 SourceLocation) {
5285 if (isOpenMPTargetExecutionDirective(DKind: K)) {
5286 OffendingRegion = K;
5287 return true;
5288 }
5289 return false;
5290 },
5291 FromParent: false /* don't skip top directive */);
5292 CloseNesting = false;
5293 }
5294 if (NestingProhibited) {
5295 if (OrphanSeen) {
5296 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_device_directive)
5297 << getOpenMPDirectiveName(D: CurrentRegion, V: OMPVersion) << Recommend;
5298 } else {
5299 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region)
5300 << CloseNesting << getOpenMPDirectiveName(D: OffendingRegion, V: OMPVersion)
5301 << Recommend << getOpenMPDirectiveName(D: CurrentRegion, V: OMPVersion);
5302 }
5303 return true;
5304 }
5305 return false;
5306}
5307
5308struct Kind2Unsigned {
5309 using argument_type = OpenMPDirectiveKind;
5310 unsigned operator()(argument_type DK) { return unsigned(DK); }
5311};
5312static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5313 ArrayRef<OMPClause *> Clauses,
5314 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5315 bool ErrorFound = false;
5316 unsigned NamedModifiersNumber = 0;
5317 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5318 FoundNameModifiers.resize(S: llvm::omp::Directive_enumSize + 1);
5319 SmallVector<SourceLocation, 4> NameModifierLoc;
5320 llvm::omp::Version OMPVersion = S.getLangOpts().getOpenMPVersion();
5321 for (const OMPClause *C : Clauses) {
5322 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(Val: C)) {
5323 // At most one if clause without a directive-name-modifier can appear on
5324 // the directive.
5325 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5326 auto &FNM = FoundNameModifiers[CurNM];
5327 if (FNM) {
5328 S.Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_more_one_clause)
5329 << getOpenMPDirectiveName(D: Kind, V: OMPVersion)
5330 << getOpenMPClauseNameForDiag(C: OMPC_if) << (CurNM != OMPD_unknown)
5331 << getOpenMPDirectiveName(D: CurNM, V: OMPVersion);
5332 ErrorFound = true;
5333 } else if (CurNM != OMPD_unknown) {
5334 NameModifierLoc.push_back(Elt: IC->getNameModifierLoc());
5335 ++NamedModifiersNumber;
5336 }
5337 FNM = IC;
5338 if (CurNM == OMPD_unknown)
5339 continue;
5340 // Check if the specified name modifier is allowed for the current
5341 // directive.
5342 // At most one if clause with the particular directive-name-modifier can
5343 // appear on the directive.
5344 if (!llvm::is_contained(Range&: AllowedNameModifiers, Element: CurNM)) {
5345 S.Diag(Loc: IC->getNameModifierLoc(),
5346 DiagID: diag::err_omp_wrong_if_directive_name_modifier)
5347 << getOpenMPDirectiveName(D: CurNM, V: OMPVersion)
5348 << getOpenMPDirectiveName(D: Kind, V: OMPVersion);
5349 ErrorFound = true;
5350 }
5351 }
5352 }
5353 // If any if clause on the directive includes a directive-name-modifier then
5354 // all if clauses on the directive must include a directive-name-modifier.
5355 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5356 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5357 S.Diag(Loc: FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5358 DiagID: diag::err_omp_no_more_if_clause);
5359 } else {
5360 std::string Values;
5361 std::string Sep(", ");
5362 unsigned AllowedCnt = 0;
5363 unsigned TotalAllowedNum =
5364 AllowedNameModifiers.size() - NamedModifiersNumber;
5365 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5366 ++Cnt) {
5367 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5368 if (!FoundNameModifiers[NM]) {
5369 Values += "'";
5370 Values += getOpenMPDirectiveName(D: NM, V: OMPVersion);
5371 Values += "'";
5372 if (AllowedCnt + 2 == TotalAllowedNum)
5373 Values += " or ";
5374 else if (AllowedCnt + 1 != TotalAllowedNum)
5375 Values += Sep;
5376 ++AllowedCnt;
5377 }
5378 }
5379 S.Diag(Loc: FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5380 DiagID: diag::err_omp_unnamed_if_clause)
5381 << (TotalAllowedNum > 1) << Values;
5382 }
5383 for (SourceLocation Loc : NameModifierLoc) {
5384 S.Diag(Loc, DiagID: diag::note_omp_previous_named_if_clause);
5385 }
5386 ErrorFound = true;
5387 }
5388 return ErrorFound;
5389}
5390
5391static std::pair<ValueDecl *, bool>
5392getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
5393 SourceRange &ERange, bool AllowArraySection,
5394 bool AllowAssumedSizeArray, StringRef DiagType) {
5395 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5396 RefExpr->containsUnexpandedParameterPack())
5397 return std::make_pair(x: nullptr, y: true);
5398
5399 // OpenMP [3.1, C/C++]
5400 // A list item is a variable name.
5401 // OpenMP [2.9.3.3, Restrictions, p.1]
5402 // A variable that is part of another variable (as an array or
5403 // structure element) cannot appear in a private clause.
5404 //
5405 // OpenMP [6.0]
5406 // 5.2.5 Array Sections, p. 166, L28-29
5407 // When the length is absent and the size of the dimension is not known,
5408 // the array section is an assumed-size array.
5409 // 2 Glossary, p. 23, L4-6
5410 // assumed-size array
5411 // For C/C++, an array section for which the length is absent and the
5412 // size of the dimensions is not known.
5413 // 5.2.5 Array Sections, p. 168, L11
5414 // An assumed-size array can appear only in clauses for which it is
5415 // explicitly allowed.
5416 // 7.4 List Item Privatization, Restrictions, p. 222, L15
5417 // Assumed-size arrays must not be privatized.
5418 RefExpr = RefExpr->IgnoreParens();
5419 enum {
5420 NoArrayExpr = -1,
5421 ArraySubscript = 0,
5422 OMPArraySection = 1
5423 } IsArrayExpr = NoArrayExpr;
5424 if (AllowArraySection) {
5425 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(Val: RefExpr)) {
5426 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5427 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base))
5428 Base = TempASE->getBase()->IgnoreParenImpCasts();
5429 RefExpr = Base;
5430 IsArrayExpr = ArraySubscript;
5431 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(Val: RefExpr)) {
5432 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5433 if (S.getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5434 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5435 QualType BaseType = ArraySectionExpr::getBaseOriginalType(Base);
5436 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5437 !BaseType->isVariableArrayType())) {
5438 S.Diag(Loc: OASE->getColonLocFirst(),
5439 DiagID: diag::err_omp_section_length_undefined)
5440 << (!BaseType.isNull() && BaseType->isArrayType());
5441 return std::make_pair(x: nullptr, y: false);
5442 }
5443 }
5444 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Val: Base))
5445 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5446 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base))
5447 Base = TempASE->getBase()->IgnoreParenImpCasts();
5448 RefExpr = Base;
5449 IsArrayExpr = OMPArraySection;
5450 }
5451 }
5452 ELoc = RefExpr->getExprLoc();
5453 ERange = RefExpr->getSourceRange();
5454 RefExpr = RefExpr->IgnoreParenImpCasts();
5455 auto *DE = dyn_cast_or_null<DeclRefExpr>(Val: RefExpr);
5456 auto *ME = dyn_cast_or_null<MemberExpr>(Val: RefExpr);
5457 if ((!DE || !isa<VarDecl>(Val: DE->getDecl())) &&
5458 (S.getCurrentThisType().isNull() || !ME ||
5459 !isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()) ||
5460 !isa<FieldDecl>(Val: ME->getMemberDecl()))) {
5461 if (IsArrayExpr != NoArrayExpr) {
5462 S.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
5463 << IsArrayExpr << ERange;
5464 } else if (!DiagType.empty()) {
5465 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5466 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5467 : 0;
5468 S.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_var_name_member_expr_with_type)
5469 << DiagSelect << DiagType << ERange;
5470 } else {
5471 S.Diag(Loc: ELoc,
5472 DiagID: AllowArraySection
5473 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5474 : diag::err_omp_expected_var_name_member_expr)
5475 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5476 }
5477 return std::make_pair(x: nullptr, y: false);
5478 }
5479 return std::make_pair(
5480 x: getCanonicalDecl(D: DE ? DE->getDecl() : ME->getMemberDecl()), y: false);
5481}
5482
5483namespace {
5484/// Checks if the allocator is used in uses_allocators clause to be allowed in
5485/// target regions.
5486class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5487 DSAStackTy *S = nullptr;
5488
5489public:
5490 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5491 return S->isUsesAllocatorsDecl(D: E->getDecl())
5492 .value_or(u: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5493 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5494 }
5495 bool VisitStmt(const Stmt *S) {
5496 for (const Stmt *Child : S->children()) {
5497 if (Child && Visit(S: Child))
5498 return true;
5499 }
5500 return false;
5501 }
5502 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5503};
5504} // namespace
5505
5506static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5507 ArrayRef<OMPClause *> Clauses) {
5508 assert(!S.CurContext->isDependentContext() &&
5509 "Expected non-dependent context.");
5510 auto AllocateRange =
5511 llvm::make_filter_range(Range&: Clauses, Pred: OMPAllocateClause::classof);
5512 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5513 auto PrivateRange = llvm::make_filter_range(Range&: Clauses, Pred: [](const OMPClause *C) {
5514 return isOpenMPPrivate(Kind: C->getClauseKind());
5515 });
5516 for (OMPClause *Cl : PrivateRange) {
5517 MutableArrayRef<Expr *>::iterator I, It, Et;
5518 if (Cl->getClauseKind() == OMPC_private) {
5519 auto *PC = cast<OMPPrivateClause>(Val: Cl);
5520 I = PC->private_copies().begin();
5521 It = PC->varlist_begin();
5522 Et = PC->varlist_end();
5523 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5524 auto *PC = cast<OMPFirstprivateClause>(Val: Cl);
5525 I = PC->private_copies().begin();
5526 It = PC->varlist_begin();
5527 Et = PC->varlist_end();
5528 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5529 auto *PC = cast<OMPLastprivateClause>(Val: Cl);
5530 I = PC->private_copies().begin();
5531 It = PC->varlist_begin();
5532 Et = PC->varlist_end();
5533 } else if (Cl->getClauseKind() == OMPC_linear) {
5534 auto *PC = cast<OMPLinearClause>(Val: Cl);
5535 I = PC->privates().begin();
5536 It = PC->varlist_begin();
5537 Et = PC->varlist_end();
5538 } else if (Cl->getClauseKind() == OMPC_reduction) {
5539 auto *PC = cast<OMPReductionClause>(Val: Cl);
5540 I = PC->privates().begin();
5541 It = PC->varlist_begin();
5542 Et = PC->varlist_end();
5543 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5544 auto *PC = cast<OMPTaskReductionClause>(Val: Cl);
5545 I = PC->privates().begin();
5546 It = PC->varlist_begin();
5547 Et = PC->varlist_end();
5548 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5549 auto *PC = cast<OMPInReductionClause>(Val: Cl);
5550 I = PC->privates().begin();
5551 It = PC->varlist_begin();
5552 Et = PC->varlist_end();
5553 } else {
5554 llvm_unreachable("Expected private clause.");
5555 }
5556 for (Expr *E : llvm::make_range(x: It, y: Et)) {
5557 if (!*I) {
5558 ++I;
5559 continue;
5560 }
5561 SourceLocation ELoc;
5562 SourceRange ERange;
5563 Expr *SimpleRefExpr = E;
5564 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
5565 /*AllowArraySection=*/true);
5566 DeclToCopy.try_emplace(Key: Res.first,
5567 Args: cast<VarDecl>(Val: cast<DeclRefExpr>(Val: *I)->getDecl()));
5568 ++I;
5569 }
5570 }
5571 for (OMPClause *C : AllocateRange) {
5572 auto *AC = cast<OMPAllocateClause>(Val: C);
5573 if (S.getLangOpts().OpenMP >= 50 &&
5574 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5575 isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective()) &&
5576 AC->getAllocator()) {
5577 Expr *Allocator = AC->getAllocator();
5578 // OpenMP, 2.12.5 target Construct
5579 // Memory allocators that do not appear in a uses_allocators clause cannot
5580 // appear as an allocator in an allocate clause or be used in the target
5581 // region unless a requires directive with the dynamic_allocators clause
5582 // is present in the same compilation unit.
5583 AllocatorChecker Checker(Stack);
5584 if (Checker.Visit(S: Allocator))
5585 S.Diag(Loc: Allocator->getExprLoc(),
5586 DiagID: diag::err_omp_allocator_not_in_uses_allocators)
5587 << Allocator->getSourceRange();
5588 }
5589 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5590 getAllocatorKind(S, Stack, Allocator: AC->getAllocator());
5591 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5592 // For task, taskloop or target directives, allocation requests to memory
5593 // allocators with the trait access set to thread result in unspecified
5594 // behavior.
5595 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5596 (isOpenMPTaskingDirective(Kind: Stack->getCurrentDirective()) ||
5597 isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective()))) {
5598 llvm::omp::Version OMPVersion = S.getLangOpts().getOpenMPVersion();
5599 S.Diag(Loc: AC->getAllocator()->getExprLoc(),
5600 DiagID: diag::warn_omp_allocate_thread_on_task_target_directive)
5601 << getOpenMPDirectiveName(D: Stack->getCurrentDirective(), V: OMPVersion);
5602 }
5603 for (Expr *E : AC->varlist()) {
5604 SourceLocation ELoc;
5605 SourceRange ERange;
5606 Expr *SimpleRefExpr = E;
5607 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange);
5608 ValueDecl *VD = Res.first;
5609 if (!VD)
5610 continue;
5611 DSAStackTy::DSAVarData Data = Stack->getTopDSA(D: VD, /*FromParent=*/false);
5612 if (!isOpenMPPrivate(Kind: Data.CKind)) {
5613 S.Diag(Loc: E->getExprLoc(),
5614 DiagID: diag::err_omp_expected_private_copy_for_allocate);
5615 continue;
5616 }
5617 VarDecl *PrivateVD = DeclToCopy[VD];
5618 if (checkPreviousOMPAllocateAttribute(S, Stack, RefExpr: E, VD: PrivateVD,
5619 AllocatorKind, Allocator: AC->getAllocator()))
5620 continue;
5621 applyOMPAllocateAttribute(S, VD: PrivateVD, AllocatorKind, Allocator: AC->getAllocator(),
5622 Alignment: AC->getAlignment(), SR: E->getSourceRange());
5623 }
5624 }
5625}
5626
5627namespace {
5628/// Rewrite statements and expressions for Sema \p Actions CurContext.
5629///
5630/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5631/// context. DeclRefExpr used inside the new context are changed to refer to the
5632/// captured variable instead.
5633class CaptureVars : public TreeTransform<CaptureVars> {
5634 using BaseTransform = TreeTransform<CaptureVars>;
5635
5636public:
5637 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5638
5639 bool AlwaysRebuild() { return true; }
5640};
5641} // namespace
5642
5643static VarDecl *precomputeExpr(Sema &Actions,
5644 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5645 StringRef Name) {
5646 Expr *NewE = AssertSuccess(R: CaptureVars(Actions).TransformExpr(E));
5647 VarDecl *NewVar = buildVarDecl(SemaRef&: Actions, Loc: {}, Type: NewE->getType(), Name, Attrs: nullptr,
5648 OrigRef: dyn_cast<DeclRefExpr>(Val: E->IgnoreImplicit()));
5649 auto *NewDeclStmt = cast<DeclStmt>(Val: AssertSuccess(
5650 R: Actions.ActOnDeclStmt(Decl: Actions.ConvertDeclToDeclGroup(Ptr: NewVar), StartLoc: {}, EndLoc: {})));
5651 Actions.AddInitializerToDecl(dcl: NewDeclStmt->getSingleDecl(), init: NewE, DirectInit: false);
5652 BodyStmts.push_back(Elt: NewDeclStmt);
5653 return NewVar;
5654}
5655
5656/// Create a closure that computes the number of iterations of a loop.
5657///
5658/// \param Actions The Sema object.
5659/// \param LogicalTy Type for the logical iteration number.
5660/// \param Rel Comparison operator of the loop condition.
5661/// \param StartExpr Value of the loop counter at the first iteration.
5662/// \param StopExpr Expression the loop counter is compared against in the loop
5663/// condition. \param StepExpr Amount of increment after each iteration.
5664///
5665/// \return Closure (CapturedStmt) of the distance calculation.
5666static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5667 BinaryOperator::Opcode Rel,
5668 Expr *StartExpr, Expr *StopExpr,
5669 Expr *StepExpr) {
5670 ASTContext &Ctx = Actions.getASTContext();
5671 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(T: LogicalTy);
5672
5673 // Captured regions currently don't support return values, we use an
5674 // out-parameter instead. All inputs are implicit captures.
5675 // TODO: Instead of capturing each DeclRefExpr occurring in
5676 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5677 QualType ResultTy = Ctx.getLValueReferenceType(T: LogicalTy);
5678 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5679 {StringRef(), QualType()}};
5680 Actions.ActOnCapturedRegionStart(Loc: {}, CurScope: nullptr, Kind: CR_Default, Params);
5681
5682 Stmt *Body;
5683 {
5684 Sema::CompoundScopeRAII CompoundScope(Actions);
5685 CapturedDecl *CS = cast<CapturedDecl>(Val: Actions.CurContext);
5686
5687 // Get the LValue expression for the result.
5688 ImplicitParamDecl *DistParam = CS->getParam(i: 0);
5689 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5690 D: DistParam, Ty: LogicalTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
5691
5692 SmallVector<Stmt *, 4> BodyStmts;
5693
5694 // Capture all referenced variable references.
5695 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5696 // CapturedStmt, we could compute them before and capture the result, to be
5697 // used jointly with the LoopVar function.
5698 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, E: StartExpr, Name: ".start");
5699 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, E: StopExpr, Name: ".stop");
5700 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, E: StepExpr, Name: ".step");
5701 auto BuildVarRef = [&](VarDecl *VD) {
5702 return buildDeclRefExpr(S&: Actions, D: VD, Ty: VD->getType(), Loc: {});
5703 };
5704
5705 IntegerLiteral *Zero = IntegerLiteral::Create(
5706 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 0), type: LogicalTy, l: {});
5707 IntegerLiteral *One = IntegerLiteral::Create(
5708 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 1), type: LogicalTy, l: {});
5709 Expr *Dist;
5710 if (Rel == BO_NE) {
5711 // When using a != comparison, the increment can be +1 or -1. This can be
5712 // dynamic at runtime, so we need to check for the direction.
5713 Expr *IsNegStep = AssertSuccess(
5714 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_LT, LHSExpr: BuildVarRef(NewStep), RHSExpr: Zero));
5715
5716 // Positive increment.
5717 Expr *ForwardRange = AssertSuccess(R: Actions.BuildBinOp(
5718 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStop), RHSExpr: BuildVarRef(NewStart)));
5719 ForwardRange = AssertSuccess(
5720 R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: ForwardRange));
5721 Expr *ForwardDist = AssertSuccess(R: Actions.BuildBinOp(
5722 S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: ForwardRange, RHSExpr: BuildVarRef(NewStep)));
5723
5724 // Negative increment.
5725 Expr *BackwardRange = AssertSuccess(R: Actions.BuildBinOp(
5726 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5727 BackwardRange = AssertSuccess(
5728 R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: BackwardRange));
5729 Expr *NegIncAmount = AssertSuccess(
5730 R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: BuildVarRef(NewStep)));
5731 Expr *BackwardDist = AssertSuccess(
5732 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: BackwardRange, RHSExpr: NegIncAmount));
5733
5734 // Use the appropriate case.
5735 Dist = AssertSuccess(R: Actions.ActOnConditionalOp(
5736 QuestionLoc: {}, ColonLoc: {}, CondExpr: IsNegStep, LHSExpr: BackwardDist, RHSExpr: ForwardDist));
5737 } else {
5738 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5739 "Expected one of these relational operators");
5740
5741 // We can derive the direction from any other comparison operator. It is
5742 // non well-formed OpenMP if Step increments/decrements in the other
5743 // directions. Whether at least the first iteration passes the loop
5744 // condition.
5745 Expr *HasAnyIteration = AssertSuccess(R: Actions.BuildBinOp(
5746 S: nullptr, OpLoc: {}, Opc: Rel, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5747
5748 // Compute the range between first and last counter value.
5749 Expr *Range;
5750 if (Rel == BO_GE || Rel == BO_GT)
5751 Range = AssertSuccess(R: Actions.BuildBinOp(
5752 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5753 else
5754 Range = AssertSuccess(R: Actions.BuildBinOp(
5755 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStop), RHSExpr: BuildVarRef(NewStart)));
5756
5757 // Ensure unsigned range space.
5758 Range =
5759 AssertSuccess(R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: Range));
5760
5761 if (Rel == BO_LE || Rel == BO_GE) {
5762 // Add one to the range if the relational operator is inclusive.
5763 Range =
5764 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: Range, RHSExpr: One));
5765 }
5766
5767 // Divide by the absolute step amount. If the range is not a multiple of
5768 // the step size, rounding-up the effective upper bound ensures that the
5769 // last iteration is included.
5770 // Note that the rounding-up may cause an overflow in a temporary that
5771 // could be avoided, but would have occurred in a C-style for-loop as
5772 // well.
5773 Expr *Divisor = BuildVarRef(NewStep);
5774 if (Rel == BO_GE || Rel == BO_GT)
5775 Divisor =
5776 AssertSuccess(R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: Divisor));
5777 Expr *DivisorMinusOne =
5778 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: Divisor, RHSExpr: One));
5779 Expr *RangeRoundUp = AssertSuccess(
5780 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: Range, RHSExpr: DivisorMinusOne));
5781 Dist = AssertSuccess(
5782 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: RangeRoundUp, RHSExpr: Divisor));
5783
5784 // If there is not at least one iteration, the range contains garbage. Fix
5785 // to zero in this case.
5786 Dist = AssertSuccess(
5787 R: Actions.ActOnConditionalOp(QuestionLoc: {}, ColonLoc: {}, CondExpr: HasAnyIteration, LHSExpr: Dist, RHSExpr: Zero));
5788 }
5789
5790 // Assign the result to the out-parameter.
5791 Stmt *ResultAssign = AssertSuccess(R: Actions.BuildBinOp(
5792 S: Actions.getCurScope(), OpLoc: {}, Opc: BO_Assign, LHSExpr: DistRef, RHSExpr: Dist));
5793 BodyStmts.push_back(Elt: ResultAssign);
5794
5795 Body = AssertSuccess(R: Actions.ActOnCompoundStmt(L: {}, R: {}, Elts: BodyStmts, isStmtExpr: false));
5796 }
5797
5798 return cast<CapturedStmt>(
5799 Val: AssertSuccess(R: Actions.ActOnCapturedRegionEnd(S: Body)));
5800}
5801
5802/// Create a closure that computes the loop variable from the logical iteration
5803/// number.
5804///
5805/// \param Actions The Sema object.
5806/// \param LoopVarTy Type for the loop variable used for result value.
5807/// \param LogicalTy Type for the logical iteration number.
5808/// \param StartExpr Value of the loop counter at the first iteration.
5809/// \param Step Amount of increment after each iteration.
5810/// \param Deref Whether the loop variable is a dereference of the loop
5811/// counter variable.
5812///
5813/// \return Closure (CapturedStmt) of the loop value calculation.
5814static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5815 QualType LogicalTy,
5816 DeclRefExpr *StartExpr, Expr *Step,
5817 bool Deref) {
5818 ASTContext &Ctx = Actions.getASTContext();
5819
5820 // Pass the result as an out-parameter. Passing as return value would require
5821 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5822 // invoke a copy constructor.
5823 QualType TargetParamTy = Ctx.getLValueReferenceType(T: LoopVarTy);
5824 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5825 {"Logical", LogicalTy},
5826 {StringRef(), QualType()}};
5827 Actions.ActOnCapturedRegionStart(Loc: {}, CurScope: nullptr, Kind: CR_Default, Params);
5828
5829 // Capture the initial iterator which represents the LoopVar value at the
5830 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5831 // it in every iteration, capture it by value before it is modified.
5832 VarDecl *StartVar = cast<VarDecl>(Val: StartExpr->getDecl());
5833 bool Invalid = Actions.tryCaptureVariable(Var: StartVar, Loc: {},
5834 Kind: TryCaptureKind::ExplicitByVal, EllipsisLoc: {});
5835 (void)Invalid;
5836 assert(!Invalid && "Expecting capture-by-value to work.");
5837
5838 Expr *Body;
5839 {
5840 Sema::CompoundScopeRAII CompoundScope(Actions);
5841 auto *CS = cast<CapturedDecl>(Val: Actions.CurContext);
5842
5843 ImplicitParamDecl *TargetParam = CS->getParam(i: 0);
5844 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5845 D: TargetParam, Ty: LoopVarTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
5846 ImplicitParamDecl *IndvarParam = CS->getParam(i: 1);
5847 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5848 D: IndvarParam, Ty: LogicalTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
5849
5850 // Capture the Start expression.
5851 CaptureVars Recap(Actions);
5852 Expr *NewStart = AssertSuccess(R: Recap.TransformExpr(E: StartExpr));
5853 Expr *NewStep = AssertSuccess(R: Recap.TransformExpr(E: Step));
5854
5855 Expr *Skip = AssertSuccess(
5856 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Mul, LHSExpr: NewStep, RHSExpr: LogicalRef));
5857 // TODO: Explicitly cast to the iterator's difference_type instead of
5858 // relying on implicit conversion.
5859 Expr *Advanced =
5860 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: NewStart, RHSExpr: Skip));
5861
5862 if (Deref) {
5863 // For range-based for-loops convert the loop counter value to a concrete
5864 // loop variable value by dereferencing the iterator.
5865 Advanced =
5866 AssertSuccess(R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Deref, Input: Advanced));
5867 }
5868
5869 // Assign the result to the output parameter.
5870 Body = AssertSuccess(R: Actions.BuildBinOp(S: Actions.getCurScope(), OpLoc: {},
5871 Opc: BO_Assign, LHSExpr: TargetRef, RHSExpr: Advanced));
5872 }
5873 return cast<CapturedStmt>(
5874 Val: AssertSuccess(R: Actions.ActOnCapturedRegionEnd(S: Body)));
5875}
5876
5877StmtResult SemaOpenMP::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
5878 ASTContext &Ctx = getASTContext();
5879
5880 // Extract the common elements of ForStmt and CXXForRangeStmt:
5881 // Loop variable, repeat condition, increment
5882 Expr *Cond, *Inc;
5883 VarDecl *LIVDecl, *LUVDecl;
5884 if (auto *For = dyn_cast<ForStmt>(Val: AStmt)) {
5885 Stmt *Init = For->getInit();
5886 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Val: Init)) {
5887 // For statement declares loop variable.
5888 LIVDecl = cast<VarDecl>(Val: LCVarDeclStmt->getSingleDecl());
5889 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Val: Init)) {
5890 // For statement reuses variable.
5891 assert(LCAssign->getOpcode() == BO_Assign &&
5892 "init part must be a loop variable assignment");
5893 auto *CounterRef = cast<DeclRefExpr>(Val: LCAssign->getLHS());
5894 LIVDecl = cast<VarDecl>(Val: CounterRef->getDecl());
5895 } else
5896 llvm_unreachable("Cannot determine loop variable");
5897 LUVDecl = LIVDecl;
5898
5899 Cond = For->getCond();
5900 Inc = For->getInc();
5901 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(Val: AStmt)) {
5902 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5903 LIVDecl = cast<VarDecl>(Val: BeginStmt->getSingleDecl());
5904 LUVDecl = RangeFor->getLoopVariable();
5905
5906 Cond = RangeFor->getCond();
5907 Inc = RangeFor->getInc();
5908 } else
5909 llvm_unreachable("unhandled kind of loop");
5910
5911 QualType CounterTy = LIVDecl->getType();
5912 QualType LVTy = LUVDecl->getType();
5913
5914 // Analyze the loop condition.
5915 Expr *LHS, *RHS;
5916 BinaryOperator::Opcode CondRel;
5917 Cond = Cond->IgnoreImplicit();
5918 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Val: Cond)) {
5919 LHS = CondBinExpr->getLHS();
5920 RHS = CondBinExpr->getRHS();
5921 CondRel = CondBinExpr->getOpcode();
5922 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Val: Cond)) {
5923 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5924 LHS = CondCXXOp->getArg(Arg: 0);
5925 RHS = CondCXXOp->getArg(Arg: 1);
5926 switch (CondCXXOp->getOperator()) {
5927 case OO_ExclaimEqual:
5928 CondRel = BO_NE;
5929 break;
5930 case OO_Less:
5931 CondRel = BO_LT;
5932 break;
5933 case OO_LessEqual:
5934 CondRel = BO_LE;
5935 break;
5936 case OO_Greater:
5937 CondRel = BO_GT;
5938 break;
5939 case OO_GreaterEqual:
5940 CondRel = BO_GE;
5941 break;
5942 default:
5943 llvm_unreachable("unexpected iterator operator");
5944 }
5945 } else
5946 llvm_unreachable("unexpected loop condition");
5947
5948 // Normalize such that the loop counter is on the LHS.
5949 if (!isa<DeclRefExpr>(Val: LHS->IgnoreImplicit()) ||
5950 cast<DeclRefExpr>(Val: LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5951 std::swap(a&: LHS, b&: RHS);
5952 CondRel = BinaryOperator::reverseComparisonOp(Opc: CondRel);
5953 }
5954 auto *CounterRef = cast<DeclRefExpr>(Val: LHS->IgnoreImplicit());
5955
5956 // Decide the bit width for the logical iteration counter. By default use the
5957 // unsigned ptrdiff_t integer size (for iterators and pointers).
5958 // TODO: For iterators, use iterator::difference_type,
5959 // std::iterator_traits<>::difference_type or decltype(it - end).
5960 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5961 if (CounterTy->isIntegerType()) {
5962 unsigned BitWidth = Ctx.getIntWidth(T: CounterTy);
5963 LogicalTy = Ctx.getIntTypeForBitwidth(DestWidth: BitWidth, Signed: false);
5964 }
5965
5966 // Analyze the loop increment.
5967 Expr *Step;
5968 if (auto *IncUn = dyn_cast<UnaryOperator>(Val: Inc)) {
5969 int Direction;
5970 switch (IncUn->getOpcode()) {
5971 case UO_PreInc:
5972 case UO_PostInc:
5973 Direction = 1;
5974 break;
5975 case UO_PreDec:
5976 case UO_PostDec:
5977 Direction = -1;
5978 break;
5979 default:
5980 llvm_unreachable("unhandled unary increment operator");
5981 }
5982 Step = IntegerLiteral::Create(
5983 C: Ctx,
5984 V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), Direction, /*isSigned=*/true),
5985 type: LogicalTy, l: {});
5986 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Val: Inc)) {
5987 if (IncBin->getOpcode() == BO_AddAssign) {
5988 Step = IncBin->getRHS();
5989 } else if (IncBin->getOpcode() == BO_SubAssign) {
5990 Step = AssertSuccess(
5991 R: SemaRef.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: IncBin->getRHS()));
5992 } else
5993 llvm_unreachable("unhandled binary increment operator");
5994 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Val: Inc)) {
5995 switch (CondCXXOp->getOperator()) {
5996 case OO_PlusPlus:
5997 Step = IntegerLiteral::Create(
5998 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 1), type: LogicalTy, l: {});
5999 break;
6000 case OO_MinusMinus:
6001 Step = IntegerLiteral::Create(
6002 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), -1), type: LogicalTy, l: {});
6003 break;
6004 case OO_PlusEqual:
6005 Step = CondCXXOp->getArg(Arg: 1);
6006 break;
6007 case OO_MinusEqual:
6008 Step = AssertSuccess(
6009 R: SemaRef.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: CondCXXOp->getArg(Arg: 1)));
6010 break;
6011 default:
6012 llvm_unreachable("unhandled overloaded increment operator");
6013 }
6014 } else
6015 llvm_unreachable("unknown increment expression");
6016
6017 CapturedStmt *DistanceFunc =
6018 buildDistanceFunc(Actions&: SemaRef, LogicalTy, Rel: CondRel, StartExpr: LHS, StopExpr: RHS, StepExpr: Step);
6019 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
6020 Actions&: SemaRef, LoopVarTy: LVTy, LogicalTy, StartExpr: CounterRef, Step, Deref: isa<CXXForRangeStmt>(Val: AStmt));
6021 DeclRefExpr *LVRef =
6022 SemaRef.BuildDeclRefExpr(D: LUVDecl, Ty: LUVDecl->getType(), VK: VK_LValue, NameInfo: {},
6023 SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
6024 return OMPCanonicalLoop::create(Ctx: getASTContext(), LoopStmt: AStmt, DistanceFunc,
6025 LoopVarFunc, LoopVarRef: LVRef);
6026}
6027
6028StmtResult SemaOpenMP::ActOnOpenMPLoopnest(Stmt *AStmt) {
6029 // Handle a literal loop.
6030 if (isa<ForStmt>(Val: AStmt) || isa<CXXForRangeStmt>(Val: AStmt))
6031 return ActOnOpenMPCanonicalLoop(AStmt);
6032
6033 // If not a literal loop, it must be the result of a loop transformation.
6034 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(Val: AStmt);
6035 assert(
6036 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
6037 "Loop transformation directive expected");
6038 return LoopTransform;
6039}
6040
6041static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
6042 CXXScopeSpec &MapperIdScopeSpec,
6043 const DeclarationNameInfo &MapperId,
6044 QualType Type,
6045 Expr *UnresolvedMapper);
6046
6047/// Perform DFS through the structure/class data members trying to find
6048/// member(s) with user-defined 'default' mapper and generate implicit map
6049/// clauses for such members with the found 'default' mapper.
6050static void
6051processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
6052 SmallVectorImpl<OMPClause *> &Clauses) {
6053 // Check for the default mapper for data members.
6054 if (S.getLangOpts().OpenMP < 50)
6055 return;
6056 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6057 auto *C = dyn_cast<OMPMapClause>(Val: Clauses[Cnt]);
6058 if (!C)
6059 continue;
6060 SmallVector<Expr *, 4> SubExprs;
6061 auto *MI = C->mapperlist_begin();
6062 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
6063 ++I, ++MI) {
6064 // Expression is mapped using mapper - skip it.
6065 if (*MI)
6066 continue;
6067 Expr *E = *I;
6068 // Expression is dependent - skip it, build the mapper when it gets
6069 // instantiated.
6070 if (E->isTypeDependent() || E->isValueDependent() ||
6071 E->containsUnexpandedParameterPack())
6072 continue;
6073 // Array section - need to check for the mapping of the array section
6074 // element.
6075 QualType CanonType = E->getType().getCanonicalType();
6076 if (CanonType->isSpecificBuiltinType(K: BuiltinType::ArraySection)) {
6077 const auto *OASE = cast<ArraySectionExpr>(Val: E->IgnoreParenImpCasts());
6078 QualType BaseType =
6079 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
6080 QualType ElemType;
6081 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6082 ElemType = ATy->getElementType();
6083 else
6084 ElemType = BaseType->getPointeeType();
6085 CanonType = ElemType;
6086 }
6087
6088 // DFS over data members in structures/classes.
6089 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
6090 1, {CanonType, nullptr});
6091 llvm::DenseMap<const Type *, Expr *> Visited;
6092 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
6093 1, {nullptr, 1});
6094 while (!Types.empty()) {
6095 QualType BaseType;
6096 FieldDecl *CurFD;
6097 std::tie(args&: BaseType, args&: CurFD) = Types.pop_back_val();
6098 while (ParentChain.back().second == 0)
6099 ParentChain.pop_back();
6100 --ParentChain.back().second;
6101 if (BaseType.isNull())
6102 continue;
6103 // Only structs/classes are allowed to have mappers.
6104 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6105 if (!RD)
6106 continue;
6107 auto It = Visited.find(Val: BaseType.getTypePtr());
6108 if (It == Visited.end()) {
6109 // Try to find the associated user-defined mapper.
6110 CXXScopeSpec MapperIdScopeSpec;
6111 DeclarationNameInfo DefaultMapperId;
6112 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
6113 ID: &S.Context.Idents.get(Name: "default")));
6114 DefaultMapperId.setLoc(E->getExprLoc());
6115 ExprResult ER = buildUserDefinedMapperRef(
6116 SemaRef&: S, S: Stack->getCurScope(), MapperIdScopeSpec, MapperId: DefaultMapperId,
6117 Type: BaseType, /*UnresolvedMapper=*/nullptr);
6118 if (ER.isInvalid())
6119 continue;
6120 It = Visited.try_emplace(Key: BaseType.getTypePtr(), Args: ER.get()).first;
6121 }
6122 // Found default mapper.
6123 if (It->second) {
6124 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6125 VK_LValue, OK_Ordinary, E);
6126 OE->setIsUnique(/*V=*/true);
6127 Expr *BaseExpr = OE;
6128 for (const auto &P : ParentChain) {
6129 if (P.first) {
6130 BaseExpr = S.BuildMemberExpr(
6131 Base: BaseExpr, /*IsArrow=*/false, OpLoc: E->getExprLoc(),
6132 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: P.first,
6133 FoundDecl: DeclAccessPair::make(D: P.first, AS: P.first->getAccess()),
6134 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(),
6135 Ty: P.first->getType(), VK: VK_LValue, OK: OK_Ordinary);
6136 BaseExpr = S.DefaultLvalueConversion(E: BaseExpr).get();
6137 }
6138 }
6139 if (CurFD)
6140 BaseExpr = S.BuildMemberExpr(
6141 Base: BaseExpr, /*IsArrow=*/false, OpLoc: E->getExprLoc(),
6142 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: CurFD,
6143 FoundDecl: DeclAccessPair::make(D: CurFD, AS: CurFD->getAccess()),
6144 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(),
6145 Ty: CurFD->getType(), VK: VK_LValue, OK: OK_Ordinary);
6146 SubExprs.push_back(Elt: BaseExpr);
6147 continue;
6148 }
6149 // Check for the "default" mapper for data members.
6150 bool FirstIter = true;
6151 for (FieldDecl *FD : RD->fields()) {
6152 if (!FD)
6153 continue;
6154 QualType FieldTy = FD->getType();
6155 if (FieldTy.isNull() ||
6156 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6157 continue;
6158 if (FirstIter) {
6159 FirstIter = false;
6160 ParentChain.emplace_back(Args&: CurFD, Args: 1);
6161 } else {
6162 ++ParentChain.back().second;
6163 }
6164 Types.emplace_back(Args&: FieldTy, Args&: FD);
6165 }
6166 }
6167 }
6168 if (SubExprs.empty())
6169 continue;
6170 CXXScopeSpec MapperIdScopeSpec;
6171 DeclarationNameInfo MapperId;
6172 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
6173 IteratorModifier: nullptr, MapTypeModifiers: C->getMapTypeModifiers(), MapTypeModifiersLoc: C->getMapTypeModifiersLoc(),
6174 MapperIdScopeSpec, MapperId, MapType: C->getMapType(),
6175 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(),
6176 VarList: SubExprs, Locs: OMPVarListLocTy()))
6177 Clauses.push_back(Elt: NewClause);
6178 }
6179}
6180
6181namespace {
6182/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
6183/// call in the associated loop-nest cannot be a 'parallel for'.
6184class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
6185 Sema &SemaRef;
6186
6187public:
6188 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
6189
6190 // Is there a nested OpenMP loop bind(parallel)
6191 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
6192 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6193 if (const auto *C = D->getSingleClause<OMPBindClause>())
6194 if (C->getBindKind() == OMPC_BIND_parallel) {
6195 TeamsLoopCanBeParallelFor = false;
6196 // No need to continue visiting any more
6197 return;
6198 }
6199 }
6200 for (const Stmt *Child : D->children())
6201 if (Child)
6202 Visit(S: Child);
6203 }
6204
6205 void VisitCallExpr(const CallExpr *C) {
6206 // Function calls inhibit parallel loop translation of 'target teams loop'
6207 // unless the assume-no-nested-parallelism flag has been specified.
6208 // OpenMP API runtime library calls do not inhibit parallel loop
6209 // translation, regardless of the assume-no-nested-parallelism.
6210 bool IsOpenMPAPI = false;
6211 auto *FD = dyn_cast_or_null<FunctionDecl>(Val: C->getCalleeDecl());
6212 if (FD) {
6213 std::string Name = FD->getNameInfo().getAsString();
6214 IsOpenMPAPI = Name.find(s: "omp_") == 0;
6215 }
6216 TeamsLoopCanBeParallelFor =
6217 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6218 if (!TeamsLoopCanBeParallelFor)
6219 return;
6220
6221 for (const Stmt *Child : C->children())
6222 if (Child)
6223 Visit(S: Child);
6224 }
6225
6226 void VisitCapturedStmt(const CapturedStmt *S) {
6227 if (!S)
6228 return;
6229 Visit(S: S->getCapturedDecl()->getBody());
6230 }
6231
6232 void VisitStmt(const Stmt *S) {
6233 if (!S)
6234 return;
6235 for (const Stmt *Child : S->children())
6236 if (Child)
6237 Visit(S: Child);
6238 }
6239 explicit TeamsLoopChecker(Sema &SemaRef)
6240 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
6241
6242private:
6243 bool TeamsLoopCanBeParallelFor;
6244};
6245} // namespace
6246
6247static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
6248 TeamsLoopChecker Checker(SemaRef);
6249 Checker.Visit(S: AStmt);
6250 return Checker.teamsLoopCanBeParallelFor();
6251}
6252
6253StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective(
6254 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6255 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6256 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6257 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
6258
6259 StmtResult Res = StmtError();
6260 OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
6261 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6262
6263 if (const OMPBindClause *BC =
6264 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6265 BindKind = BC->getBindKind();
6266
6267 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6268 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6269
6270 // Setting the enclosing teams or parallel construct for the loop
6271 // directive without bind clause.
6272 // [5.0:129:25-28] If the bind clause is not present on the construct and
6273 // the loop construct is closely nested inside a teams or parallel
6274 // construct, the binding region is the corresponding teams or parallel
6275 // region. If none of those conditions hold, the binding region is not
6276 // defined.
6277 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6278 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6279 getLeafConstructsOrSelf(D: ParentDirective);
6280
6281 if (ParentDirective == OMPD_unknown) {
6282 Diag(DSAStack->getDefaultDSALocation(),
6283 DiagID: diag::err_omp_bind_required_on_loop);
6284 } else if (ParentLeafs.back() == OMPD_parallel) {
6285 BindKind = OMPC_BIND_parallel;
6286 } else if (ParentLeafs.back() == OMPD_teams) {
6287 BindKind = OMPC_BIND_teams;
6288 }
6289
6290 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6291
6292 OMPClause *C =
6293 ActOnOpenMPBindClause(Kind: BindKind, KindLoc: SourceLocation(), StartLoc: SourceLocation(),
6294 LParenLoc: SourceLocation(), EndLoc: SourceLocation());
6295 ClausesWithImplicit.push_back(Elt: C);
6296 }
6297
6298 // Diagnose "loop bind(teams)" with "reduction".
6299 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6300 for (OMPClause *C : Clauses) {
6301 if (C->getClauseKind() == OMPC_reduction)
6302 Diag(DSAStack->getDefaultDSALocation(),
6303 DiagID: diag::err_omp_loop_reduction_clause);
6304 }
6305 }
6306
6307 // First check CancelRegion which is then used in checkNestingOfRegions.
6308 if (checkCancelRegion(SemaRef, CurrentRegion: Kind, CancelRegion, StartLoc) ||
6309 checkNestingOfRegions(SemaRef, DSAStack, CurrentRegion: Kind, CurrentName: DirName, CancelRegion,
6310 BindKind, StartLoc)) {
6311 return StmtError();
6312 }
6313
6314 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6315 if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(DKind: Kind) ||
6316 isOpenMPTargetDataManagementDirective(DKind: Kind)))
6317 Diag(Loc: StartLoc, DiagID: diag::warn_hip_omp_target_directives);
6318
6319 VarsWithInheritedDSAType VarsWithInheritedDSA;
6320 bool ErrorFound = false;
6321 ClausesWithImplicit.append(in_start: Clauses.begin(), in_end: Clauses.end());
6322
6323 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6324 isOpenMPCapturingDirective(DKind: Kind)) {
6325 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6326
6327 // Check default data sharing attributes for referenced variables.
6328 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(Val: AStmt));
6329 int ThisCaptureLevel = getOpenMPCaptureLevels(DKind: Kind);
6330 Stmt *S = AStmt;
6331 while (--ThisCaptureLevel >= 0)
6332 S = cast<CapturedStmt>(Val: S)->getCapturedStmt();
6333 DSAChecker.Visit(S);
6334 if (!isOpenMPTargetDataManagementDirective(DKind: Kind) &&
6335 !isOpenMPTaskingDirective(Kind)) {
6336 // Visit subcaptures to generate implicit clauses for captured vars.
6337 auto *CS = cast<CapturedStmt>(Val: AStmt);
6338 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
6339 getOpenMPCaptureRegions(CaptureRegions, DKind: Kind);
6340 // Ignore outer tasking regions for target directives.
6341 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6342 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
6343 DSAChecker.visitSubCaptures(S: CS);
6344 }
6345 if (DSAChecker.isErrorFound())
6346 return StmtError();
6347 // Generate list of implicitly defined firstprivate variables.
6348 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6349 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6350
6351 SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
6352 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6353 // Get the original location of present modifier from Defaultmap clause.
6354 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6355 for (OMPClause *C : Clauses) {
6356 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(Val: C))
6357 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6358 PresentModifierLocs[DMC->getDefaultmapKind()] =
6359 DMC->getDefaultmapModifierLoc();
6360 }
6361
6362 for (OpenMPDefaultmapClauseKind K :
6363 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6364 Begin: OpenMPDefaultmapClauseKind(), End: OMPC_DEFAULTMAP_unknown)) {
6365 std::fill_n(first: std::back_inserter(x&: ImplicitMapModifiersLoc[K]),
6366 n: ImpInfo.MapModifiers[K].size(), value: PresentModifierLocs[K]);
6367 }
6368 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6369 for (OMPClause *C : Clauses) {
6370 if (auto *IRC = dyn_cast<OMPInReductionClause>(Val: C)) {
6371 for (Expr *E : IRC->taskgroup_descriptors())
6372 if (E)
6373 ImpInfo.Firstprivates.insert(X: E);
6374 }
6375 // OpenMP 5.0, 2.10.1 task Construct
6376 // [detach clause]... The event-handle will be considered as if it was
6377 // specified on a firstprivate clause.
6378 if (auto *DC = dyn_cast<OMPDetachClause>(Val: C))
6379 ImpInfo.Firstprivates.insert(X: DC->getEventHandler());
6380 }
6381 if (!ImpInfo.Firstprivates.empty()) {
6382 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6383 VarList: ImpInfo.Firstprivates.getArrayRef(), StartLoc: SourceLocation(),
6384 LParenLoc: SourceLocation(), EndLoc: SourceLocation())) {
6385 ClausesWithImplicit.push_back(Elt: Implicit);
6386 ErrorFound = cast<OMPFirstprivateClause>(Val: Implicit)->varlist_size() !=
6387 ImpInfo.Firstprivates.size();
6388 } else {
6389 ErrorFound = true;
6390 }
6391 }
6392 if (!ImpInfo.Privates.empty()) {
6393 if (OMPClause *Implicit = ActOnOpenMPPrivateClause(
6394 VarList: ImpInfo.Privates.getArrayRef(), StartLoc: SourceLocation(),
6395 LParenLoc: SourceLocation(), EndLoc: SourceLocation())) {
6396 ClausesWithImplicit.push_back(Elt: Implicit);
6397 ErrorFound = cast<OMPPrivateClause>(Val: Implicit)->varlist_size() !=
6398 ImpInfo.Privates.size();
6399 } else {
6400 ErrorFound = true;
6401 }
6402 }
6403 // OpenMP 5.0 [2.19.7]
6404 // If a list item appears in a reduction, lastprivate or linear
6405 // clause on a combined target construct then it is treated as
6406 // if it also appears in a map clause with a map-type of tofrom
6407 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6408 isOpenMPTargetExecutionDirective(DKind: Kind)) {
6409 SmallVector<Expr *, 4> ImplicitExprs;
6410 for (OMPClause *C : Clauses) {
6411 if (auto *RC = dyn_cast<OMPReductionClause>(Val: C))
6412 for (Expr *E : RC->varlist())
6413 if (!isa<DeclRefExpr>(Val: E->IgnoreParenImpCasts()))
6414 ImplicitExprs.emplace_back(Args&: E);
6415 }
6416 if (!ImplicitExprs.empty()) {
6417 ArrayRef<Expr *> Exprs = ImplicitExprs;
6418 CXXScopeSpec MapperIdScopeSpec;
6419 DeclarationNameInfo MapperId;
6420 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6421 IteratorModifier: nullptr, MapTypeModifiers: OMPC_MAP_MODIFIER_unknown, MapTypeModifiersLoc: SourceLocation(),
6422 MapperIdScopeSpec, MapperId, MapType: OMPC_MAP_tofrom,
6423 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(),
6424 VarList: Exprs, Locs: OMPVarListLocTy(), /*NoDiagnose=*/true))
6425 ClausesWithImplicit.emplace_back(Args&: Implicit);
6426 }
6427 }
6428 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6429 int ClauseKindCnt = -1;
6430 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6431 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6432 ++ClauseKindCnt;
6433 if (ImplicitMap.empty())
6434 continue;
6435 CXXScopeSpec MapperIdScopeSpec;
6436 DeclarationNameInfo MapperId;
6437 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6438 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6439 IteratorModifier: nullptr, MapTypeModifiers: ImpInfo.MapModifiers[I], MapTypeModifiersLoc: ImplicitMapModifiersLoc[I],
6440 MapperIdScopeSpec, MapperId, MapType: K, /*IsMapTypeImplicit=*/true,
6441 MapLoc: SourceLocation(), ColonLoc: SourceLocation(), VarList: ImplicitMap,
6442 Locs: OMPVarListLocTy())) {
6443 ClausesWithImplicit.emplace_back(Args&: Implicit);
6444 ErrorFound |= cast<OMPMapClause>(Val: Implicit)->varlist_size() !=
6445 ImplicitMap.size();
6446 } else {
6447 ErrorFound = true;
6448 }
6449 }
6450 }
6451 // Build expressions for implicit maps of data members with 'default'
6452 // mappers.
6453 if (getLangOpts().OpenMP >= 50)
6454 processImplicitMapsWithDefaultMappers(S&: SemaRef, DSAStack,
6455 Clauses&: ClausesWithImplicit);
6456 }
6457
6458 switch (Kind) {
6459 case OMPD_parallel:
6460 Res = ActOnOpenMPParallelDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6461 EndLoc);
6462 break;
6463 case OMPD_simd:
6464 Res = ActOnOpenMPSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6465 VarsWithImplicitDSA&: VarsWithInheritedDSA);
6466 break;
6467 case OMPD_tile:
6468 Res =
6469 ActOnOpenMPTileDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6470 break;
6471 case OMPD_stripe:
6472 Res = ActOnOpenMPStripeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6473 EndLoc);
6474 break;
6475 case OMPD_unroll:
6476 Res = ActOnOpenMPUnrollDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6477 EndLoc);
6478 break;
6479 case OMPD_reverse:
6480 assert(ClausesWithImplicit.empty() &&
6481 "reverse directive does not support any clauses");
6482 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6483 break;
6484 case OMPD_split:
6485 Res =
6486 ActOnOpenMPSplitDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6487 break;
6488 case OMPD_interchange:
6489 Res = ActOnOpenMPInterchangeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6490 EndLoc);
6491 break;
6492 case OMPD_fuse:
6493 Res =
6494 ActOnOpenMPFuseDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6495 break;
6496 case OMPD_for:
6497 Res = ActOnOpenMPForDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6498 VarsWithImplicitDSA&: VarsWithInheritedDSA);
6499 break;
6500 case OMPD_for_simd:
6501 Res = ActOnOpenMPForSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6502 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6503 break;
6504 case OMPD_sections:
6505 Res = ActOnOpenMPSectionsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6506 EndLoc);
6507 break;
6508 case OMPD_section:
6509 assert(ClausesWithImplicit.empty() &&
6510 "No clauses are allowed for 'omp section' directive");
6511 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6512 break;
6513 case OMPD_single:
6514 Res = ActOnOpenMPSingleDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6515 EndLoc);
6516 break;
6517 case OMPD_master:
6518 assert(ClausesWithImplicit.empty() &&
6519 "No clauses are allowed for 'omp master' directive");
6520 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6521 break;
6522 case OMPD_masked:
6523 Res = ActOnOpenMPMaskedDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6524 EndLoc);
6525 break;
6526 case OMPD_critical:
6527 Res = ActOnOpenMPCriticalDirective(DirName, Clauses: ClausesWithImplicit, AStmt,
6528 StartLoc, EndLoc);
6529 break;
6530 case OMPD_parallel_for:
6531 Res = ActOnOpenMPParallelForDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6532 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6533 break;
6534 case OMPD_parallel_for_simd:
6535 Res = ActOnOpenMPParallelForSimdDirective(
6536 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6537 break;
6538 case OMPD_scope:
6539 Res =
6540 ActOnOpenMPScopeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6541 break;
6542 case OMPD_parallel_master:
6543 Res = ActOnOpenMPParallelMasterDirective(Clauses: ClausesWithImplicit, AStmt,
6544 StartLoc, EndLoc);
6545 break;
6546 case OMPD_parallel_masked:
6547 Res = ActOnOpenMPParallelMaskedDirective(Clauses: ClausesWithImplicit, AStmt,
6548 StartLoc, EndLoc);
6549 break;
6550 case OMPD_parallel_sections:
6551 Res = ActOnOpenMPParallelSectionsDirective(Clauses: ClausesWithImplicit, AStmt,
6552 StartLoc, EndLoc);
6553 break;
6554 case OMPD_task:
6555 Res =
6556 ActOnOpenMPTaskDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6557 break;
6558 case OMPD_taskyield:
6559 assert(ClausesWithImplicit.empty() &&
6560 "No clauses are allowed for 'omp taskyield' directive");
6561 assert(AStmt == nullptr &&
6562 "No associated statement allowed for 'omp taskyield' directive");
6563 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6564 break;
6565 case OMPD_error:
6566 assert(AStmt == nullptr &&
6567 "No associated statement allowed for 'omp error' directive");
6568 Res = ActOnOpenMPErrorDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6569 break;
6570 case OMPD_barrier:
6571 assert(ClausesWithImplicit.empty() &&
6572 "No clauses are allowed for 'omp barrier' directive");
6573 assert(AStmt == nullptr &&
6574 "No associated statement allowed for 'omp barrier' directive");
6575 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6576 break;
6577 case OMPD_taskwait:
6578 assert(AStmt == nullptr &&
6579 "No associated statement allowed for 'omp taskwait' directive");
6580 Res = ActOnOpenMPTaskwaitDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6581 break;
6582 case OMPD_taskgroup:
6583 Res = ActOnOpenMPTaskgroupDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6584 EndLoc);
6585 break;
6586 case OMPD_flush:
6587 assert(AStmt == nullptr &&
6588 "No associated statement allowed for 'omp flush' directive");
6589 Res = ActOnOpenMPFlushDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6590 break;
6591 case OMPD_depobj:
6592 assert(AStmt == nullptr &&
6593 "No associated statement allowed for 'omp depobj' directive");
6594 Res = ActOnOpenMPDepobjDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6595 break;
6596 case OMPD_scan:
6597 assert(AStmt == nullptr &&
6598 "No associated statement allowed for 'omp scan' directive");
6599 Res = ActOnOpenMPScanDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6600 break;
6601 case OMPD_ordered_blockassoc:
6602 case OMPD_ordered_standalone:
6603 Res = ActOnOpenMPOrderedDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6604 EndLoc);
6605 break;
6606 case OMPD_atomic:
6607 Res = ActOnOpenMPAtomicDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6608 EndLoc);
6609 break;
6610 case OMPD_teams:
6611 Res =
6612 ActOnOpenMPTeamsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6613 break;
6614 case OMPD_target:
6615 Res = ActOnOpenMPTargetDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6616 EndLoc);
6617 break;
6618 case OMPD_target_parallel:
6619 Res = ActOnOpenMPTargetParallelDirective(Clauses: ClausesWithImplicit, AStmt,
6620 StartLoc, EndLoc);
6621 break;
6622 case OMPD_target_parallel_for:
6623 Res = ActOnOpenMPTargetParallelForDirective(
6624 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6625 break;
6626 case OMPD_cancellation_point:
6627 assert(ClausesWithImplicit.empty() &&
6628 "No clauses are allowed for 'omp cancellation point' directive");
6629 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6630 "cancellation point' directive");
6631 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6632 break;
6633 case OMPD_cancel:
6634 assert(AStmt == nullptr &&
6635 "No associated statement allowed for 'omp cancel' directive");
6636 Res = ActOnOpenMPCancelDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc,
6637 CancelRegion);
6638 break;
6639 case OMPD_target_data:
6640 Res = ActOnOpenMPTargetDataDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6641 EndLoc);
6642 break;
6643 case OMPD_target_enter_data:
6644 Res = ActOnOpenMPTargetEnterDataDirective(Clauses: ClausesWithImplicit, StartLoc,
6645 EndLoc, AStmt);
6646 break;
6647 case OMPD_target_exit_data:
6648 Res = ActOnOpenMPTargetExitDataDirective(Clauses: ClausesWithImplicit, StartLoc,
6649 EndLoc, AStmt);
6650 break;
6651 case OMPD_taskloop:
6652 Res = ActOnOpenMPTaskLoopDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6653 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6654 break;
6655 case OMPD_taskloop_simd:
6656 Res = ActOnOpenMPTaskLoopSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6657 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6658 break;
6659 case OMPD_master_taskloop:
6660 Res = ActOnOpenMPMasterTaskLoopDirective(
6661 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6662 break;
6663 case OMPD_masked_taskloop:
6664 Res = ActOnOpenMPMaskedTaskLoopDirective(
6665 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6666 break;
6667 case OMPD_master_taskloop_simd:
6668 Res = ActOnOpenMPMasterTaskLoopSimdDirective(
6669 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6670 break;
6671 case OMPD_masked_taskloop_simd:
6672 Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
6673 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6674 break;
6675 case OMPD_parallel_master_taskloop:
6676 Res = ActOnOpenMPParallelMasterTaskLoopDirective(
6677 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6678 break;
6679 case OMPD_parallel_masked_taskloop:
6680 Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
6681 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6682 break;
6683 case OMPD_parallel_master_taskloop_simd:
6684 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6685 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6686 break;
6687 case OMPD_parallel_masked_taskloop_simd:
6688 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6689 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6690 break;
6691 case OMPD_distribute:
6692 Res = ActOnOpenMPDistributeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6693 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6694 break;
6695 case OMPD_target_update:
6696 Res = ActOnOpenMPTargetUpdateDirective(Clauses: ClausesWithImplicit, StartLoc,
6697 EndLoc, AStmt);
6698 break;
6699 case OMPD_distribute_parallel_for:
6700 Res = ActOnOpenMPDistributeParallelForDirective(
6701 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6702 break;
6703 case OMPD_distribute_parallel_for_simd:
6704 Res = ActOnOpenMPDistributeParallelForSimdDirective(
6705 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6706 break;
6707 case OMPD_distribute_simd:
6708 Res = ActOnOpenMPDistributeSimdDirective(
6709 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6710 break;
6711 case OMPD_target_parallel_for_simd:
6712 Res = ActOnOpenMPTargetParallelForSimdDirective(
6713 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6714 break;
6715 case OMPD_target_simd:
6716 Res = ActOnOpenMPTargetSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6717 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6718 break;
6719 case OMPD_teams_distribute:
6720 Res = ActOnOpenMPTeamsDistributeDirective(
6721 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6722 break;
6723 case OMPD_teams_distribute_simd:
6724 Res = ActOnOpenMPTeamsDistributeSimdDirective(
6725 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6726 break;
6727 case OMPD_teams_distribute_parallel_for_simd:
6728 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6729 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6730 break;
6731 case OMPD_teams_distribute_parallel_for:
6732 Res = ActOnOpenMPTeamsDistributeParallelForDirective(
6733 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6734 break;
6735 case OMPD_target_teams:
6736 Res = ActOnOpenMPTargetTeamsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6737 EndLoc);
6738 break;
6739 case OMPD_target_teams_distribute:
6740 Res = ActOnOpenMPTargetTeamsDistributeDirective(
6741 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6742 break;
6743 case OMPD_target_teams_distribute_parallel_for:
6744 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6745 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6746 break;
6747 case OMPD_target_teams_distribute_parallel_for_simd:
6748 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6749 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6750 break;
6751 case OMPD_target_teams_distribute_simd:
6752 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
6753 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6754 break;
6755 case OMPD_interop:
6756 assert(AStmt == nullptr &&
6757 "No associated statement allowed for 'omp interop' directive");
6758 Res = ActOnOpenMPInteropDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6759 break;
6760 case OMPD_dispatch:
6761 Res = ActOnOpenMPDispatchDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6762 EndLoc);
6763 break;
6764 case OMPD_loop:
6765 Res = ActOnOpenMPGenericLoopDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6766 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6767 break;
6768 case OMPD_teams_loop:
6769 Res = ActOnOpenMPTeamsGenericLoopDirective(
6770 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6771 break;
6772 case OMPD_target_teams_loop:
6773 Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
6774 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6775 break;
6776 case OMPD_parallel_loop:
6777 Res = ActOnOpenMPParallelGenericLoopDirective(
6778 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6779 break;
6780 case OMPD_target_parallel_loop:
6781 Res = ActOnOpenMPTargetParallelGenericLoopDirective(
6782 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6783 break;
6784 case OMPD_declare_target:
6785 case OMPD_end_declare_target:
6786 case OMPD_threadprivate:
6787 case OMPD_allocate:
6788 case OMPD_declare_reduction:
6789 case OMPD_declare_mapper:
6790 case OMPD_declare_simd:
6791 case OMPD_requires:
6792 case OMPD_declare_variant:
6793 case OMPD_begin_declare_variant:
6794 case OMPD_end_declare_variant:
6795 llvm_unreachable("OpenMP Directive is not allowed");
6796 case OMPD_taskgraph:
6797 Diag(Loc: StartLoc, DiagID: diag::err_omp_unexpected_directive)
6798 << 1 << getOpenMPDirectiveName(D: OMPD_taskgraph);
6799 return StmtError();
6800 case OMPD_unknown:
6801 default:
6802 llvm_unreachable("Unknown OpenMP directive");
6803 }
6804
6805 ErrorFound = Res.isInvalid() || ErrorFound;
6806
6807 // Check variables in the clauses if default(none) or
6808 // default(firstprivate) was specified.
6809 if (DSAStack->getDefaultDSA() == DSA_none ||
6810 DSAStack->getDefaultDSA() == DSA_private ||
6811 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6812 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6813 for (OMPClause *C : Clauses) {
6814 switch (C->getClauseKind()) {
6815 case OMPC_num_threads:
6816 case OMPC_dist_schedule:
6817 // Do not analyze if no parent teams directive.
6818 if (isOpenMPTeamsDirective(DKind: Kind))
6819 break;
6820 continue;
6821 case OMPC_if:
6822 if (isOpenMPTeamsDirective(DKind: Kind) &&
6823 cast<OMPIfClause>(Val: C)->getNameModifier() != OMPD_target)
6824 break;
6825 if (isOpenMPParallelDirective(DKind: Kind) &&
6826 isOpenMPTaskLoopDirective(DKind: Kind) &&
6827 cast<OMPIfClause>(Val: C)->getNameModifier() != OMPD_parallel)
6828 break;
6829 continue;
6830 case OMPC_schedule:
6831 case OMPC_detach:
6832 break;
6833 case OMPC_grainsize:
6834 case OMPC_num_tasks:
6835 case OMPC_final:
6836 case OMPC_priority:
6837 case OMPC_novariants:
6838 case OMPC_nocontext:
6839 // Do not analyze if no parent parallel directive.
6840 if (isOpenMPParallelDirective(DKind: Kind))
6841 break;
6842 continue;
6843 case OMPC_ordered:
6844 case OMPC_device:
6845 case OMPC_num_teams:
6846 case OMPC_thread_limit:
6847 case OMPC_hint:
6848 case OMPC_collapse:
6849 case OMPC_safelen:
6850 case OMPC_simdlen:
6851 case OMPC_sizes:
6852 case OMPC_default:
6853 case OMPC_proc_bind:
6854 case OMPC_private:
6855 case OMPC_firstprivate:
6856 case OMPC_lastprivate:
6857 case OMPC_shared:
6858 case OMPC_reduction:
6859 case OMPC_task_reduction:
6860 case OMPC_in_reduction:
6861 case OMPC_linear:
6862 case OMPC_aligned:
6863 case OMPC_copyin:
6864 case OMPC_copyprivate:
6865 case OMPC_nowait:
6866 case OMPC_untied:
6867 case OMPC_mergeable:
6868 case OMPC_allocate:
6869 case OMPC_read:
6870 case OMPC_write:
6871 case OMPC_update:
6872 case OMPC_capture:
6873 case OMPC_compare:
6874 case OMPC_seq_cst:
6875 case OMPC_acq_rel:
6876 case OMPC_acquire:
6877 case OMPC_release:
6878 case OMPC_relaxed:
6879 case OMPC_depend:
6880 case OMPC_threads:
6881 case OMPC_simd:
6882 case OMPC_map:
6883 case OMPC_nogroup:
6884 case OMPC_defaultmap:
6885 case OMPC_to:
6886 case OMPC_from:
6887 case OMPC_use_device_ptr:
6888 case OMPC_use_device_addr:
6889 case OMPC_is_device_ptr:
6890 case OMPC_has_device_addr:
6891 case OMPC_nontemporal:
6892 case OMPC_order:
6893 case OMPC_destroy:
6894 case OMPC_inclusive:
6895 case OMPC_exclusive:
6896 case OMPC_uses_allocators:
6897 case OMPC_affinity:
6898 case OMPC_bind:
6899 case OMPC_filter:
6900 case OMPC_severity:
6901 case OMPC_message:
6902 continue;
6903 case OMPC_allocator:
6904 case OMPC_flush:
6905 case OMPC_depobj:
6906 case OMPC_threadprivate:
6907 case OMPC_groupprivate:
6908 case OMPC_uniform:
6909 case OMPC_unknown:
6910 case OMPC_unified_address:
6911 case OMPC_unified_shared_memory:
6912 case OMPC_reverse_offload:
6913 case OMPC_dynamic_allocators:
6914 case OMPC_atomic_default_mem_order:
6915 case OMPC_self_maps:
6916 case OMPC_device_type:
6917 case OMPC_match:
6918 case OMPC_when:
6919 case OMPC_at:
6920 default:
6921 llvm_unreachable("Unexpected clause");
6922 }
6923 for (Stmt *CC : C->children()) {
6924 if (CC)
6925 DSAChecker.Visit(S: CC);
6926 }
6927 }
6928 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6929 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6930 }
6931 for (const auto &P : VarsWithInheritedDSA) {
6932 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(Val: P.getFirst()))
6933 continue;
6934 ErrorFound = true;
6935 if (DSAStack->getDefaultDSA() == DSA_none ||
6936 DSAStack->getDefaultDSA() == DSA_private ||
6937 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6938 Diag(Loc: P.second->getExprLoc(), DiagID: diag::err_omp_no_dsa_for_variable)
6939 << P.first << P.second->getSourceRange();
6940 Diag(DSAStack->getDefaultDSALocation(), DiagID: diag::note_omp_default_dsa_none);
6941 } else if (getLangOpts().OpenMP >= 50) {
6942 Diag(Loc: P.second->getExprLoc(),
6943 DiagID: diag::err_omp_defaultmap_no_attr_for_variable)
6944 << P.first << P.second->getSourceRange();
6945 Diag(DSAStack->getDefaultDSALocation(),
6946 DiagID: diag::note_omp_defaultmap_attr_none);
6947 }
6948 }
6949
6950 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6951 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(D: Kind)) {
6952 if (isAllowedClauseForDirective(D, C: OMPC_if,
6953 V: getLangOpts().getOpenMPVersion()))
6954 AllowedNameModifiers.push_back(Elt: D);
6955 }
6956 if (!AllowedNameModifiers.empty())
6957 ErrorFound = checkIfClauses(S&: SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6958 ErrorFound;
6959
6960 if (ErrorFound)
6961 return StmtError();
6962
6963 if (!SemaRef.CurContext->isDependentContext() &&
6964 isOpenMPTargetExecutionDirective(DKind: Kind) &&
6965 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6966 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6967 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6968 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6969 // Register target to DSA Stack.
6970 DSAStack->addTargetDirLocation(LocStart: StartLoc);
6971 }
6972
6973 return Res;
6974}
6975
6976SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareSimdDirective(
6977 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6978 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6979 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6980 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6981 assert(Aligneds.size() == Alignments.size());
6982 assert(Linears.size() == LinModifiers.size());
6983 assert(Linears.size() == Steps.size());
6984 if (!DG || DG.get().isNull())
6985 return DeclGroupPtrTy();
6986
6987 const int SimdId = 0;
6988 if (!DG.get().isSingleDecl()) {
6989 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_single_decl_in_declare_simd_variant)
6990 << SimdId;
6991 return DG;
6992 }
6993 Decl *ADecl = DG.get().getSingleDecl();
6994 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: ADecl))
6995 ADecl = FTD->getTemplatedDecl();
6996
6997 auto *FD = dyn_cast<FunctionDecl>(Val: ADecl);
6998 if (!FD) {
6999 Diag(Loc: ADecl->getLocation(), DiagID: diag::err_omp_function_expected) << SimdId;
7000 return DeclGroupPtrTy();
7001 }
7002
7003 // OpenMP [2.8.2, declare simd construct, Description]
7004 // The parameter of the simdlen clause must be a constant positive integer
7005 // expression.
7006 ExprResult SL;
7007 if (Simdlen)
7008 SL = VerifyPositiveIntegerConstantInClause(Op: Simdlen, CKind: OMPC_simdlen);
7009 // OpenMP [2.8.2, declare simd construct, Description]
7010 // The special this pointer can be used as if was one of the arguments to the
7011 // function in any of the linear, aligned, or uniform clauses.
7012 // The uniform clause declares one or more arguments to have an invariant
7013 // value for all concurrent invocations of the function in the execution of a
7014 // single SIMD loop.
7015 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
7016 const Expr *UniformedLinearThis = nullptr;
7017 for (const Expr *E : Uniforms) {
7018 E = E->IgnoreParenImpCasts();
7019 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7020 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl()))
7021 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7022 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7023 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
7024 UniformedArgs.try_emplace(Key: PVD->getCanonicalDecl(), Args&: E);
7025 continue;
7026 }
7027 if (isa<CXXThisExpr>(Val: E)) {
7028 UniformedLinearThis = E;
7029 continue;
7030 }
7031 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
7032 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
7033 }
7034 // OpenMP [2.8.2, declare simd construct, Description]
7035 // The aligned clause declares that the object to which each list item points
7036 // is aligned to the number of bytes expressed in the optional parameter of
7037 // the aligned clause.
7038 // The special this pointer can be used as if was one of the arguments to the
7039 // function in any of the linear, aligned, or uniform clauses.
7040 // The type of list items appearing in the aligned clause must be array,
7041 // pointer, reference to array, or reference to pointer.
7042 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
7043 const Expr *AlignedThis = nullptr;
7044 for (const Expr *E : Aligneds) {
7045 E = E->IgnoreParenImpCasts();
7046 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7047 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7048 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7049 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7050 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7051 ->getCanonicalDecl() == CanonPVD) {
7052 // OpenMP [2.8.1, simd construct, Restrictions]
7053 // A list-item cannot appear in more than one aligned clause.
7054 auto [It, Inserted] = AlignedArgs.try_emplace(Key: CanonPVD, Args&: E);
7055 if (!Inserted) {
7056 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_used_in_clause_twice)
7057 << 1 << getOpenMPClauseNameForDiag(C: OMPC_aligned)
7058 << E->getSourceRange();
7059 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7060 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
7061 continue;
7062 }
7063 QualType QTy = PVD->getType()
7064 .getNonReferenceType()
7065 .getUnqualifiedType()
7066 .getCanonicalType();
7067 const Type *Ty = QTy.getTypePtrOrNull();
7068 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
7069 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_aligned_expected_array_or_ptr)
7070 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
7071 Diag(Loc: PVD->getLocation(), DiagID: diag::note_previous_decl) << PVD;
7072 }
7073 continue;
7074 }
7075 }
7076 if (isa<CXXThisExpr>(Val: E)) {
7077 if (AlignedThis) {
7078 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_used_in_clause_twice)
7079 << 2 << getOpenMPClauseNameForDiag(C: OMPC_aligned)
7080 << E->getSourceRange();
7081 Diag(Loc: AlignedThis->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7082 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
7083 }
7084 AlignedThis = E;
7085 continue;
7086 }
7087 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
7088 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
7089 }
7090 // The optional parameter of the aligned clause, alignment, must be a constant
7091 // positive integer expression. If no optional parameter is specified,
7092 // implementation-defined default alignments for SIMD instructions on the
7093 // target platforms are assumed.
7094 SmallVector<const Expr *, 4> NewAligns;
7095 for (Expr *E : Alignments) {
7096 ExprResult Align;
7097 if (E)
7098 Align = VerifyPositiveIntegerConstantInClause(Op: E, CKind: OMPC_aligned);
7099 NewAligns.push_back(Elt: Align.get());
7100 }
7101 // OpenMP [2.8.2, declare simd construct, Description]
7102 // The linear clause declares one or more list items to be private to a SIMD
7103 // lane and to have a linear relationship with respect to the iteration space
7104 // of a loop.
7105 // The special this pointer can be used as if was one of the arguments to the
7106 // function in any of the linear, aligned, or uniform clauses.
7107 // When a linear-step expression is specified in a linear clause it must be
7108 // either a constant integer expression or an integer-typed parameter that is
7109 // specified in a uniform clause on the directive.
7110 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7111 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7112 auto MI = LinModifiers.begin();
7113 for (const Expr *E : Linears) {
7114 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7115 ++MI;
7116 E = E->IgnoreParenImpCasts();
7117 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7118 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7119 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7120 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7121 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7122 ->getCanonicalDecl() == CanonPVD) {
7123 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7124 // A list-item cannot appear in more than one linear clause.
7125 if (auto It = LinearArgs.find(Val: CanonPVD); It != LinearArgs.end()) {
7126 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
7127 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7128 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7129 << E->getSourceRange();
7130 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7131 << getOpenMPClauseNameForDiag(C: OMPC_linear);
7132 continue;
7133 }
7134 // Each argument can appear in at most one uniform or linear clause.
7135 if (auto It = UniformedArgs.find(Val: CanonPVD);
7136 It != UniformedArgs.end()) {
7137 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
7138 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7139 << getOpenMPClauseNameForDiag(C: OMPC_uniform)
7140 << E->getSourceRange();
7141 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7142 << getOpenMPClauseNameForDiag(C: OMPC_uniform);
7143 continue;
7144 }
7145 LinearArgs[CanonPVD] = E;
7146 if (E->isValueDependent() || E->isTypeDependent() ||
7147 E->isInstantiationDependent() ||
7148 E->containsUnexpandedParameterPack())
7149 continue;
7150 (void)CheckOpenMPLinearDecl(D: CanonPVD, ELoc: E->getExprLoc(), LinKind,
7151 Type: PVD->getOriginalType(),
7152 /*IsDeclareSimd=*/true);
7153 continue;
7154 }
7155 }
7156 if (isa<CXXThisExpr>(Val: E)) {
7157 if (UniformedLinearThis) {
7158 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
7159 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7160 << getOpenMPClauseNameForDiag(C: IsUniformedThis ? OMPC_uniform
7161 : OMPC_linear)
7162 << E->getSourceRange();
7163 Diag(Loc: UniformedLinearThis->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7164 << getOpenMPClauseNameForDiag(C: IsUniformedThis ? OMPC_uniform
7165 : OMPC_linear);
7166 continue;
7167 }
7168 UniformedLinearThis = E;
7169 if (E->isValueDependent() || E->isTypeDependent() ||
7170 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
7171 continue;
7172 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, ELoc: E->getExprLoc(), LinKind,
7173 Type: E->getType(), /*IsDeclareSimd=*/true);
7174 continue;
7175 }
7176 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
7177 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
7178 }
7179 Expr *Step = nullptr;
7180 Expr *NewStep = nullptr;
7181 SmallVector<Expr *, 4> NewSteps;
7182 for (Expr *E : Steps) {
7183 // Skip the same step expression, it was checked already.
7184 if (Step == E || !E) {
7185 NewSteps.push_back(Elt: E ? NewStep : nullptr);
7186 continue;
7187 }
7188 Step = E;
7189 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: Step))
7190 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7191 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7192 if (UniformedArgs.count(Val: CanonPVD) == 0) {
7193 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_expected_uniform_param)
7194 << Step->getSourceRange();
7195 } else if (E->isValueDependent() || E->isTypeDependent() ||
7196 E->isInstantiationDependent() ||
7197 E->containsUnexpandedParameterPack() ||
7198 CanonPVD->getType()->hasIntegerRepresentation()) {
7199 NewSteps.push_back(Elt: Step);
7200 } else {
7201 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_expected_int_param)
7202 << Step->getSourceRange();
7203 }
7204 continue;
7205 }
7206 NewStep = Step;
7207 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7208 !Step->isInstantiationDependent() &&
7209 !Step->containsUnexpandedParameterPack()) {
7210 NewStep = PerformOpenMPImplicitIntegerConversion(OpLoc: Step->getExprLoc(), Op: Step)
7211 .get();
7212 if (NewStep)
7213 NewStep = SemaRef
7214 .VerifyIntegerConstantExpression(
7215 E: NewStep, /*FIXME*/ CanFold: AllowFoldKind::Allow)
7216 .get();
7217 }
7218 NewSteps.push_back(Elt: NewStep);
7219 }
7220 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7221 Ctx&: getASTContext(), BranchState: BS, Simdlen: SL.get(), Uniforms: const_cast<Expr **>(Uniforms.data()),
7222 UniformsSize: Uniforms.size(), Aligneds: const_cast<Expr **>(Aligneds.data()), AlignedsSize: Aligneds.size(),
7223 Alignments: const_cast<Expr **>(NewAligns.data()), AlignmentsSize: NewAligns.size(),
7224 Linears: const_cast<Expr **>(Linears.data()), LinearsSize: Linears.size(),
7225 Modifiers: const_cast<unsigned *>(LinModifiers.data()), ModifiersSize: LinModifiers.size(),
7226 Steps: NewSteps.data(), StepsSize: NewSteps.size(), Range: SR);
7227 ADecl->addAttr(A: NewAttr);
7228 return DG;
7229}
7230
7231StmtResult SemaOpenMP::ActOnOpenMPInformationalDirective(
7232 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
7233 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
7234 SourceLocation EndLoc) {
7235 assert(isOpenMPInformationalDirective(Kind) &&
7236 "Unexpected directive category");
7237
7238 StmtResult Res = StmtError();
7239
7240 switch (Kind) {
7241 case OMPD_assume:
7242 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
7243 break;
7244 default:
7245 llvm_unreachable("Unknown OpenMP directive");
7246 }
7247
7248 return Res;
7249}
7250
7251static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7252 QualType NewType) {
7253 assert(NewType->isFunctionProtoType() &&
7254 "Expected function type with prototype.");
7255 assert(FD->getType()->isFunctionNoProtoType() &&
7256 "Expected function with type with no prototype.");
7257 assert(FDWithProto->getType()->isFunctionProtoType() &&
7258 "Expected function with prototype.");
7259 // Synthesize parameters with the same types.
7260 FD->setType(NewType);
7261 SmallVector<ParmVarDecl *, 16> Params;
7262 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7263 auto *Param = ParmVarDecl::Create(C&: S.getASTContext(), DC: FD, StartLoc: SourceLocation(),
7264 IdLoc: SourceLocation(), Id: nullptr, T: P->getType(),
7265 /*TInfo=*/nullptr, S: SC_None, DefArg: nullptr);
7266 Param->setScopeInfo(scopeDepth: 0, parameterIndex: Params.size());
7267 Param->setImplicit();
7268 Params.push_back(Elt: Param);
7269 }
7270
7271 FD->setParams(Params);
7272}
7273
7274void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
7275 if (D->isInvalidDecl())
7276 return;
7277 FunctionDecl *FD = nullptr;
7278 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(Val: D))
7279 FD = UTemplDecl->getTemplatedDecl();
7280 else
7281 FD = cast<FunctionDecl>(Val: D);
7282 assert(FD && "Expected a function declaration!");
7283
7284 // If we are instantiating templates we do *not* apply scoped assumptions but
7285 // only global ones. We apply scoped assumption to the template definition
7286 // though.
7287 if (!SemaRef.inTemplateInstantiation()) {
7288 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7289 FD->addAttr(A: AA);
7290 }
7291 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7292 FD->addAttr(A: AA);
7293}
7294
7295SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7296 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7297
7298void SemaOpenMP::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7299 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7300 SmallVectorImpl<FunctionDecl *> &Bases) {
7301 if (!D.getIdentifier())
7302 return;
7303
7304 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7305
7306 // Template specialization is an extension, check if we do it.
7307 bool IsTemplated = !TemplateParamLists.empty();
7308 if (IsTemplated &&
7309 !DVScope.TI->isExtensionActive(
7310 TP: llvm::omp::TraitProperty::implementation_extension_allow_templates))
7311 return;
7312
7313 const IdentifierInfo *BaseII = D.getIdentifier();
7314 LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(),
7315 Sema::LookupOrdinaryName);
7316 SemaRef.LookupParsedName(R&: Lookup, S, SS: &D.getCXXScopeSpec(),
7317 /*ObjectType=*/QualType());
7318
7319 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7320 QualType FType = TInfo->getType();
7321
7322 bool IsConstexpr =
7323 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7324 bool IsConsteval =
7325 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7326
7327 for (auto *Candidate : Lookup) {
7328 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7329 FunctionDecl *UDecl = nullptr;
7330 if (IsTemplated && isa<FunctionTemplateDecl>(Val: CandidateDecl)) {
7331 auto *FTD = cast<FunctionTemplateDecl>(Val: CandidateDecl);
7332 // FIXME: Should this compare the template parameter lists on all levels?
7333 if (SemaRef.Context.isSameTemplateParameterList(
7334 X: FTD->getTemplateParameters(), Y: TemplateParamLists.back()))
7335 UDecl = FTD->getTemplatedDecl();
7336 } else if (!IsTemplated)
7337 UDecl = dyn_cast<FunctionDecl>(Val: CandidateDecl);
7338 if (!UDecl)
7339 continue;
7340
7341 // Don't specialize constexpr/consteval functions with
7342 // non-constexpr/consteval functions.
7343 if (UDecl->isConstexpr() && !IsConstexpr)
7344 continue;
7345 if (UDecl->isConsteval() && !IsConsteval)
7346 continue;
7347
7348 QualType UDeclTy = UDecl->getType();
7349 if (!UDeclTy->isDependentType()) {
7350 QualType NewType = getASTContext().mergeFunctionTypes(
7351 FType, UDeclTy, /*OfBlockPointer=*/false,
7352 /*Unqualified=*/false, /*AllowCXX=*/true);
7353 if (NewType.isNull())
7354 continue;
7355 }
7356
7357 // Found a base!
7358 Bases.push_back(Elt: UDecl);
7359 }
7360
7361 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7362 TP: llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7363 // If no base was found we create a declaration that we use as base.
7364 if (Bases.empty() && UseImplicitBase) {
7365 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7366 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParameterLists: TemplateParamLists);
7367 BaseD->setImplicit(true);
7368 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(Val: BaseD))
7369 Bases.push_back(Elt: BaseTemplD->getTemplatedDecl());
7370 else
7371 Bases.push_back(Elt: cast<FunctionDecl>(Val: BaseD));
7372 }
7373
7374 std::string MangledName;
7375 MangledName += D.getIdentifier()->getName();
7376 MangledName += getOpenMPVariantManglingSeparatorStr();
7377 MangledName += DVScope.NameSuffix;
7378 IdentifierInfo &VariantII = getASTContext().Idents.get(Name: MangledName);
7379
7380 VariantII.setMangledOpenMPVariantName(true);
7381 D.SetIdentifier(Id: &VariantII, IdLoc: D.getBeginLoc());
7382}
7383
7384void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7385 Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
7386 // Do not mark function as is used to prevent its emission if this is the
7387 // only place where it is used.
7388 EnterExpressionEvaluationContext Unevaluated(
7389 SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);
7390
7391 FunctionDecl *FD = nullptr;
7392 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(Val: D))
7393 FD = UTemplDecl->getTemplatedDecl();
7394 else
7395 FD = cast<FunctionDecl>(Val: D);
7396 auto *VariantFuncRef = DeclRefExpr::Create(
7397 Context: getASTContext(), QualifierLoc: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), D: FD,
7398 /*RefersToEnclosingVariableOrCapture=*/false,
7399 /*NameLoc=*/FD->getLocation(), T: FD->getType(), VK: ExprValueKind::VK_PRValue);
7400
7401 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7402 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7403 Ctx&: getASTContext(), VariantFuncRef, TraitInfos: DVScope.TI,
7404 /*NothingArgs=*/AdjustArgsNothing: nullptr, /*NothingArgsSize=*/AdjustArgsNothingSize: 0,
7405 /*NeedDevicePtrArgs=*/AdjustArgsNeedDevicePtr: nullptr, /*NeedDevicePtrArgsSize=*/AdjustArgsNeedDevicePtrSize: 0,
7406 /*NeedDeviceAddrArgs=*/AdjustArgsNeedDeviceAddr: nullptr, /*NeedDeviceAddrArgsSize=*/AdjustArgsNeedDeviceAddrSize: 0,
7407 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7408 for (FunctionDecl *BaseFD : Bases)
7409 BaseFD->addAttr(A: OMPDeclareVariantA);
7410}
7411
7412ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
7413 SourceLocation LParenLoc,
7414 MultiExprArg ArgExprs,
7415 SourceLocation RParenLoc,
7416 Expr *ExecConfig) {
7417 // The common case is a regular call we do not want to specialize at all. Try
7418 // to make that case fast by bailing early.
7419 CallExpr *CE = dyn_cast<CallExpr>(Val: Call.get());
7420 if (!CE)
7421 return Call;
7422
7423 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7424
7425 // Mark indirect calls inside target regions, to allow for insertion of
7426 // __llvm_omp_indirect_call_lookup calls during codegen.
7427 if (!CalleeFnDecl) {
7428 if (isInOpenMPTargetExecutionDirective()) {
7429 Expr *E = CE->getCallee()->IgnoreParenImpCasts();
7430 DeclRefExpr *DRE = nullptr;
7431 while (E) {
7432 if ((DRE = dyn_cast<DeclRefExpr>(Val: E)))
7433 break;
7434 if (auto *ME = dyn_cast<MemberExpr>(Val: E))
7435 E = ME->getBase()->IgnoreParenImpCasts();
7436 else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: E))
7437 E = ASE->getBase()->IgnoreParenImpCasts();
7438 else
7439 break;
7440 }
7441 VarDecl *VD = DRE ? dyn_cast<VarDecl>(Val: DRE->getDecl()) : nullptr;
7442 if (VD && !VD->hasAttr<OMPTargetIndirectCallAttr>()) {
7443 VD->addAttr(A: OMPTargetIndirectCallAttr::CreateImplicit(Ctx&: getASTContext()));
7444 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
7445 ML->DeclarationMarkedOpenMPIndirectCall(D: VD);
7446 }
7447 }
7448
7449 return Call;
7450 }
7451
7452 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7453 CalleeFnDecl->getIdentifier() &&
7454 CalleeFnDecl->getName().starts_with_insensitive(Prefix: "omp_")) {
7455 // checking for any calls inside an Order region
7456 if (Scope && Scope->isOpenMPOrderClauseScope())
7457 Diag(Loc: LParenLoc, DiagID: diag::err_omp_unexpected_call_to_omp_runtime_api);
7458 }
7459
7460 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7461 return Call;
7462
7463 ASTContext &Context = getASTContext();
7464 std::function<void(StringRef)> DiagUnknownTrait = [this,
7465 CE](StringRef ISATrait) {
7466 // TODO Track the selector locations in a way that is accessible here to
7467 // improve the diagnostic location.
7468 Diag(Loc: CE->getBeginLoc(), DiagID: diag::warn_unknown_declare_variant_isa_trait)
7469 << ISATrait;
7470 };
7471 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7472 SemaRef.getCurFunctionDecl(),
7473 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7474
7475 QualType CalleeFnType = CalleeFnDecl->getType();
7476
7477 SmallVector<Expr *, 4> Exprs;
7478 SmallVector<VariantMatchInfo, 4> VMIs;
7479 while (CalleeFnDecl) {
7480 for (OMPDeclareVariantAttr *A :
7481 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7482 Expr *VariantRef = A->getVariantFuncRef();
7483
7484 VariantMatchInfo VMI;
7485 OMPTraitInfo &TI = A->getTraitInfo();
7486 TI.getAsVariantMatchInfo(ASTCtx&: Context, VMI);
7487 if (!isVariantApplicableInContext(VMI, Ctx: OMPCtx,
7488 /*DeviceSetOnly=*/DeviceOrImplementationSetOnly: false))
7489 continue;
7490
7491 VMIs.push_back(Elt: VMI);
7492 Exprs.push_back(Elt: VariantRef);
7493 }
7494
7495 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7496 }
7497
7498 ExprResult NewCall;
7499 do {
7500 int BestIdx = getBestVariantMatchForContext(VMIs, Ctx: OMPCtx);
7501 if (BestIdx < 0)
7502 return Call;
7503 Expr *BestExpr = cast<DeclRefExpr>(Val: Exprs[BestIdx]);
7504 Decl *BestDecl = cast<DeclRefExpr>(Val: BestExpr)->getDecl();
7505
7506 {
7507 // Try to build a (member) call expression for the current best applicable
7508 // variant expression. We allow this to fail in which case we continue
7509 // with the next best variant expression. The fail case is part of the
7510 // implementation defined behavior in the OpenMP standard when it talks
7511 // about what differences in the function prototypes: "Any differences
7512 // that the specific OpenMP context requires in the prototype of the
7513 // variant from the base function prototype are implementation defined."
7514 // This wording is there to allow the specialized variant to have a
7515 // different type than the base function. This is intended and OK but if
7516 // we cannot create a call the difference is not in the "implementation
7517 // defined range" we allow.
7518 Sema::TentativeAnalysisScope Trap(SemaRef);
7519
7520 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(Val: BestDecl)) {
7521 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(Val: CE);
7522 BestExpr = MemberExpr::CreateImplicit(
7523 C: Context, Base: MemberCall->getImplicitObjectArgument(),
7524 /*IsArrow=*/false, MemberDecl: SpecializedMethod, T: Context.BoundMemberTy,
7525 VK: MemberCall->getValueKind(), OK: MemberCall->getObjectKind());
7526 }
7527 NewCall = SemaRef.BuildCallExpr(S: Scope, Fn: BestExpr, LParenLoc, ArgExprs,
7528 RParenLoc, ExecConfig);
7529 if (NewCall.isUsable()) {
7530 if (CallExpr *NCE = dyn_cast<CallExpr>(Val: NewCall.get())) {
7531 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7532 QualType NewType = getASTContext().mergeFunctionTypes(
7533 CalleeFnType, NewCalleeFnDecl->getType(),
7534 /*OfBlockPointer=*/false,
7535 /*Unqualified=*/false, /*AllowCXX=*/true);
7536 if (!NewType.isNull())
7537 break;
7538 // Don't use the call if the function type was not compatible.
7539 NewCall = nullptr;
7540 }
7541 }
7542 }
7543
7544 VMIs.erase(CI: VMIs.begin() + BestIdx);
7545 Exprs.erase(CI: Exprs.begin() + BestIdx);
7546 } while (!VMIs.empty());
7547
7548 if (!NewCall.isUsable())
7549 return Call;
7550 return PseudoObjectExpr::Create(Context: getASTContext(), syntactic: CE, semantic: {NewCall.get()}, resultIndex: 0);
7551}
7552
7553std::optional<std::pair<FunctionDecl *, Expr *>>
7554SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG,
7555 Expr *VariantRef,
7556 OMPTraitInfo &TI,
7557 unsigned NumAppendArgs,
7558 SourceRange SR) {
7559 ASTContext &Context = getASTContext();
7560 if (!DG || DG.get().isNull())
7561 return std::nullopt;
7562
7563 const int VariantId = 1;
7564 // Must be applied only to single decl.
7565 if (!DG.get().isSingleDecl()) {
7566 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_single_decl_in_declare_simd_variant)
7567 << VariantId << SR;
7568 return std::nullopt;
7569 }
7570 Decl *ADecl = DG.get().getSingleDecl();
7571 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: ADecl))
7572 ADecl = FTD->getTemplatedDecl();
7573
7574 // Decl must be a function.
7575 auto *FD = dyn_cast<FunctionDecl>(Val: ADecl);
7576 if (!FD) {
7577 Diag(Loc: ADecl->getLocation(), DiagID: diag::err_omp_function_expected)
7578 << VariantId << SR;
7579 return std::nullopt;
7580 }
7581
7582 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7583 // The 'target' attribute needs to be separately checked because it does
7584 // not always signify a multiversion function declaration.
7585 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7586 };
7587 // OpenMP is not compatible with multiversion function attributes.
7588 if (HasMultiVersionAttributes(FD)) {
7589 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_incompat_attributes)
7590 << SR;
7591 return std::nullopt;
7592 }
7593
7594 // Allow #pragma omp declare variant only if the function is not used.
7595 if (FD->isUsed(CheckUsedAttr: false))
7596 Diag(Loc: SR.getBegin(), DiagID: diag::warn_omp_declare_variant_after_used)
7597 << FD->getLocation();
7598
7599 // Check if the function was emitted already.
7600 const FunctionDecl *Definition;
7601 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7602 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(D: Definition)))
7603 Diag(Loc: SR.getBegin(), DiagID: diag::warn_omp_declare_variant_after_emitted)
7604 << FD->getLocation();
7605
7606 // The VariantRef must point to function.
7607 if (!VariantRef) {
7608 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_function_expected) << VariantId;
7609 return std::nullopt;
7610 }
7611
7612 auto ShouldDelayChecks = [](Expr *&E, bool) {
7613 return E && (E->isTypeDependent() || E->isValueDependent() ||
7614 E->containsUnexpandedParameterPack() ||
7615 E->isInstantiationDependent());
7616 };
7617 // Do not check templates, wait until instantiation.
7618 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7619 TI.anyScoreOrCondition(Cond: ShouldDelayChecks))
7620 return std::make_pair(x&: FD, y&: VariantRef);
7621
7622 // Deal with non-constant score and user condition expressions.
7623 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7624 bool IsScore) -> bool {
7625 if (!E || E->isIntegerConstantExpr(Ctx: getASTContext()))
7626 return false;
7627
7628 if (IsScore) {
7629 // We warn on non-constant scores and pretend they were not present.
7630 Diag(Loc: E->getExprLoc(), DiagID: diag::warn_omp_declare_variant_score_not_constant)
7631 << E;
7632 E = nullptr;
7633 } else {
7634 // We could replace a non-constant user condition with "false" but we
7635 // will soon need to handle these anyway for the dynamic version of
7636 // OpenMP context selectors.
7637 Diag(Loc: E->getExprLoc(),
7638 DiagID: diag::err_omp_declare_variant_user_condition_not_constant)
7639 << E;
7640 }
7641 return true;
7642 };
7643 if (TI.anyScoreOrCondition(Cond: HandleNonConstantScoresAndConditions))
7644 return std::nullopt;
7645
7646 QualType AdjustedFnType = FD->getType();
7647 if (NumAppendArgs) {
7648 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7649 if (!PTy) {
7650 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_prototype_required)
7651 << SR;
7652 return std::nullopt;
7653 }
7654 // Adjust the function type to account for an extra omp_interop_t for each
7655 // specified in the append_args clause.
7656 const TypeDecl *TD = nullptr;
7657 LookupResult Result(SemaRef, &Context.Idents.get(Name: "omp_interop_t"),
7658 SR.getBegin(), Sema::LookupOrdinaryName);
7659 if (SemaRef.LookupName(R&: Result, S: SemaRef.getCurScope())) {
7660 NamedDecl *ND = Result.getFoundDecl();
7661 TD = dyn_cast_or_null<TypeDecl>(Val: ND);
7662 }
7663 if (!TD) {
7664 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_interop_type_not_found) << SR;
7665 return std::nullopt;
7666 }
7667 QualType InteropType =
7668 Context.getTypeDeclType(Keyword: ElaboratedTypeKeyword::None,
7669 /*Qualifier=*/std::nullopt, Decl: TD);
7670 if (PTy->isVariadic()) {
7671 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_append_args_with_varargs) << SR;
7672 return std::nullopt;
7673 }
7674 llvm::SmallVector<QualType, 8> Params;
7675 Params.append(in_start: PTy->param_type_begin(), in_end: PTy->param_type_end());
7676 Params.insert(I: Params.end(), NumToInsert: NumAppendArgs, Elt: InteropType);
7677 AdjustedFnType = Context.getFunctionType(ResultTy: PTy->getReturnType(), Args: Params,
7678 EPI: PTy->getExtProtoInfo());
7679 }
7680
7681 // Convert VariantRef expression to the type of the original function to
7682 // resolve possible conflicts.
7683 ExprResult VariantRefCast = VariantRef;
7684 if (getLangOpts().CPlusPlus) {
7685 QualType FnPtrType;
7686 auto *Method = dyn_cast<CXXMethodDecl>(Val: FD);
7687 if (Method && !Method->isStatic()) {
7688 FnPtrType = Context.getMemberPointerType(
7689 T: AdjustedFnType, /*Qualifier=*/std::nullopt, Cls: Method->getParent());
7690 ExprResult ER;
7691 {
7692 // Build addr_of unary op to correctly handle type checks for member
7693 // functions.
7694 Sema::TentativeAnalysisScope Trap(SemaRef);
7695 ER = SemaRef.CreateBuiltinUnaryOp(OpLoc: VariantRef->getBeginLoc(), Opc: UO_AddrOf,
7696 InputExpr: VariantRef);
7697 }
7698 if (!ER.isUsable()) {
7699 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7700 << VariantId << VariantRef->getSourceRange();
7701 return std::nullopt;
7702 }
7703 VariantRef = ER.get();
7704 } else {
7705 FnPtrType = Context.getPointerType(T: AdjustedFnType);
7706 }
7707 QualType VarianPtrType = Context.getPointerType(T: VariantRef->getType());
7708 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7709 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7710 From: VariantRef, ToType: FnPtrType.getUnqualifiedType(),
7711 /*SuppressUserConversions=*/false, AllowExplicit: Sema::AllowedExplicit::None,
7712 /*InOverloadResolution=*/false,
7713 /*CStyle=*/false,
7714 /*AllowObjCWritebackConversion=*/false);
7715 if (ICS.isFailure()) {
7716 Diag(Loc: VariantRef->getExprLoc(),
7717 DiagID: diag::err_omp_declare_variant_incompat_types)
7718 << VariantRef->getType()
7719 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7720 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7721 return std::nullopt;
7722 }
7723 VariantRefCast = SemaRef.PerformImplicitConversion(
7724 From: VariantRef, ToType: FnPtrType.getUnqualifiedType(),
7725 Action: AssignmentAction::Converting);
7726 if (!VariantRefCast.isUsable())
7727 return std::nullopt;
7728 }
7729 // Drop previously built artificial addr_of unary op for member functions.
7730 if (Method && !Method->isStatic()) {
7731 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7732 if (auto *UO = dyn_cast<UnaryOperator>(
7733 Val: PossibleAddrOfVariantRef->IgnoreImplicit()))
7734 VariantRefCast = UO->getSubExpr();
7735 }
7736 }
7737
7738 ExprResult ER = SemaRef.CheckPlaceholderExpr(E: VariantRefCast.get());
7739 if (!ER.isUsable() ||
7740 !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7741 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7742 << VariantId << VariantRef->getSourceRange();
7743 return std::nullopt;
7744 }
7745
7746 // The VariantRef must point to function.
7747 auto *DRE = dyn_cast<DeclRefExpr>(Val: ER.get()->IgnoreParenImpCasts());
7748 if (!DRE) {
7749 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7750 << VariantId << VariantRef->getSourceRange();
7751 return std::nullopt;
7752 }
7753 auto *NewFD = dyn_cast_or_null<FunctionDecl>(Val: DRE->getDecl());
7754 if (!NewFD) {
7755 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7756 << VariantId << VariantRef->getSourceRange();
7757 return std::nullopt;
7758 }
7759
7760 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7761 Diag(Loc: VariantRef->getExprLoc(),
7762 DiagID: diag::err_omp_declare_variant_same_base_function)
7763 << VariantRef->getSourceRange();
7764 return std::nullopt;
7765 }
7766
7767 // Check if function types are compatible in C.
7768 if (!getLangOpts().CPlusPlus) {
7769 QualType NewType =
7770 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7771 if (NewType.isNull()) {
7772 Diag(Loc: VariantRef->getExprLoc(),
7773 DiagID: diag::err_omp_declare_variant_incompat_types)
7774 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7775 << VariantRef->getSourceRange();
7776 return std::nullopt;
7777 }
7778 if (NewType->isFunctionProtoType()) {
7779 if (FD->getType()->isFunctionNoProtoType())
7780 setPrototype(S&: SemaRef, FD, FDWithProto: NewFD, NewType);
7781 else if (NewFD->getType()->isFunctionNoProtoType())
7782 setPrototype(S&: SemaRef, FD: NewFD, FDWithProto: FD, NewType);
7783 }
7784 }
7785
7786 // Check if variant function is not marked with declare variant directive.
7787 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7788 Diag(Loc: VariantRef->getExprLoc(),
7789 DiagID: diag::warn_omp_declare_variant_marked_as_declare_variant)
7790 << VariantRef->getSourceRange();
7791 SourceRange SR =
7792 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7793 Diag(Loc: SR.getBegin(), DiagID: diag::note_omp_marked_declare_variant_here) << SR;
7794 return std::nullopt;
7795 }
7796
7797 enum DoesntSupport {
7798 VirtFuncs = 1,
7799 Constructors = 3,
7800 Destructors = 4,
7801 DeletedFuncs = 5,
7802 DefaultedFuncs = 6,
7803 ConstexprFuncs = 7,
7804 ConstevalFuncs = 8,
7805 };
7806 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(Val: FD)) {
7807 if (CXXFD->isVirtual()) {
7808 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7809 << VirtFuncs;
7810 return std::nullopt;
7811 }
7812
7813 if (isa<CXXConstructorDecl>(Val: FD)) {
7814 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7815 << Constructors;
7816 return std::nullopt;
7817 }
7818
7819 if (isa<CXXDestructorDecl>(Val: FD)) {
7820 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7821 << Destructors;
7822 return std::nullopt;
7823 }
7824 }
7825
7826 if (FD->isDeleted()) {
7827 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7828 << DeletedFuncs;
7829 return std::nullopt;
7830 }
7831
7832 if (FD->isDefaulted()) {
7833 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7834 << DefaultedFuncs;
7835 return std::nullopt;
7836 }
7837
7838 if (FD->isConstexpr()) {
7839 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7840 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7841 return std::nullopt;
7842 }
7843
7844 // Check general compatibility.
7845 if (SemaRef.areMultiversionVariantFunctionsCompatible(
7846 OldFD: FD, NewFD, NoProtoDiagID: PartialDiagnostic::NullDiagnostic(),
7847 NoteCausedDiagIDAt: PartialDiagnosticAt(SourceLocation(),
7848 PartialDiagnostic::NullDiagnostic()),
7849 NoSupportDiagIDAt: PartialDiagnosticAt(
7850 VariantRef->getExprLoc(),
7851 SemaRef.PDiag(DiagID: diag::err_omp_declare_variant_doesnt_support)),
7852 DiffDiagIDAt: PartialDiagnosticAt(VariantRef->getExprLoc(),
7853 SemaRef.PDiag(DiagID: diag::err_omp_declare_variant_diff)
7854 << FD->getLocation()),
7855 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7856 /*CLinkageMayDiffer=*/true))
7857 return std::nullopt;
7858 return std::make_pair(x&: FD, y: cast<Expr>(Val: DRE));
7859}
7860
7861/// Validate prefer_type fr() and attr() arguments in an OMPInteropInfo.
7862/// fr() must be a string literal or constant integer expression.
7863/// attr() must be a string literal starting with "ompx_" and containing no
7864/// commas. Returns true if valid; emits diagnostic and returns false on first
7865/// error.
7866static bool checkPreferTypeArgs(SemaOpenMP &S, const OMPInteropInfo &Info) {
7867 auto isDependent = [](const Expr *E) {
7868 return E->isValueDependent() || E->isTypeDependent() ||
7869 E->isInstantiationDependent() ||
7870 E->containsUnexpandedParameterPack();
7871 };
7872 for (const OMPInteropPref &P : Info.Prefs) {
7873 const Expr *E = P.Fr;
7874 if (!E) {
7875 assert(Info.HasPreferAttrs && "null Fr requires OMP 6.0 syntax");
7876 } else if (!isDependent(E)) {
7877 if (!E->isIntegerConstantExpr(Ctx: S.getASTContext()) &&
7878 !isa<StringLiteral>(Val: E)) {
7879 S.Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_interop_prefer_type);
7880 return false;
7881 }
7882 }
7883 for (const Expr *A : P.Attrs) {
7884 if (isDependent(A))
7885 continue;
7886 const auto *SL = dyn_cast<StringLiteral>(Val: A);
7887 if (!SL) {
7888 S.Diag(Loc: A->getExprLoc(), DiagID: diag::err_omp_interop_attr_not_string);
7889 return false;
7890 }
7891 StringRef Str = SL->getString();
7892 if (!Str.starts_with(Prefix: "ompx_")) {
7893 S.Diag(Loc: A->getExprLoc(), DiagID: diag::err_omp_interop_attr_missing_ompx_prefix)
7894 << Str;
7895 return false;
7896 }
7897 if (Str.contains(C: ',')) {
7898 S.Diag(Loc: A->getExprLoc(), DiagID: diag::err_omp_interop_attr_contains_comma)
7899 << Str;
7900 return false;
7901 }
7902 }
7903 }
7904 return true;
7905}
7906
7907void SemaOpenMP::ActOnOpenMPDeclareVariantDirective(
7908 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7909 ArrayRef<Expr *> AdjustArgsNothing,
7910 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7911 ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
7912 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7913 SourceLocation AppendArgsLoc, SourceRange SR) {
7914
7915 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7916 // An adjust_args clause or append_args clause can only be specified if the
7917 // dispatch selector of the construct selector set appears in the match
7918 // clause.
7919
7920 SmallVector<Expr *, 8> AllAdjustArgs;
7921 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNothing);
7922 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNeedDevicePtr);
7923 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNeedDeviceAddr);
7924
7925 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7926 VariantMatchInfo VMI;
7927 TI.getAsVariantMatchInfo(ASTCtx&: getASTContext(), VMI);
7928 if (!llvm::is_contained(
7929 Range&: VMI.ConstructTraits,
7930 Element: llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7931 if (!AllAdjustArgs.empty())
7932 Diag(Loc: AdjustArgsLoc, DiagID: diag::err_omp_clause_requires_dispatch_construct)
7933 << getOpenMPClauseNameForDiag(C: OMPC_adjust_args);
7934 if (!AppendArgs.empty())
7935 Diag(Loc: AppendArgsLoc, DiagID: diag::err_omp_clause_requires_dispatch_construct)
7936 << getOpenMPClauseNameForDiag(C: OMPC_append_args);
7937 return;
7938 }
7939 }
7940
7941 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7942 // Each argument can only appear in a single adjust_args clause for each
7943 // declare variant directive.
7944 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
7945
7946 for (Expr *E : AllAdjustArgs) {
7947 E = E->IgnoreParenImpCasts();
7948 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E)) {
7949 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7950 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7951 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7952 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7953 ->getCanonicalDecl() == CanonPVD) {
7954 // It's a parameter of the function, check duplicates.
7955 if (!AdjustVars.insert(Ptr: CanonPVD).second) {
7956 Diag(Loc: DRE->getLocation(), DiagID: diag::err_omp_adjust_arg_multiple_clauses)
7957 << PVD;
7958 return;
7959 }
7960 continue;
7961 }
7962 }
7963 }
7964 // Anything that is not a function parameter is an error.
7965 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause) << FD << 0;
7966 return;
7967 }
7968
7969 // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
7970 // If the `need_device_addr` adjust-op modifier is present, each list item
7971 // that appears in the clause must refer to an argument in the declaration of
7972 // the function variant that has a reference type
7973 if (getLangOpts().OpenMP >= 60) {
7974 for (Expr *E : AdjustArgsNeedDeviceAddr) {
7975 E = E->IgnoreParenImpCasts();
7976 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E)) {
7977 if (const auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl())) {
7978 if (!VD->getType()->isReferenceType())
7979 Diag(Loc: E->getExprLoc(),
7980 DiagID: diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7981 }
7982 }
7983 }
7984 }
7985
7986 // OpenMP 6.0 [16.1.3] Check prefer_type fr()/attr() arguments in
7987 // append_args.
7988 for (const OMPInteropInfo &Info : AppendArgs) {
7989 if (!checkPreferTypeArgs(S&: *this, Info))
7990 return;
7991 }
7992
7993 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7994 Ctx&: getASTContext(), VariantFuncRef: VariantRef, TraitInfos: &TI,
7995 AdjustArgsNothing: const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothingSize: AdjustArgsNothing.size(),
7996 AdjustArgsNeedDevicePtr: const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7997 AdjustArgsNeedDevicePtrSize: AdjustArgsNeedDevicePtr.size(),
7998 AdjustArgsNeedDeviceAddr: const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
7999 AdjustArgsNeedDeviceAddrSize: AdjustArgsNeedDeviceAddr.size(),
8000 AppendArgs: const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgsSize: AppendArgs.size(), Range: SR);
8001 FD->addAttr(A: NewAttr);
8002}
8003
8004static CapturedStmt *
8005setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt) {
8006 auto *CS = dyn_cast<CapturedStmt>(Val: AStmt);
8007 assert(CS && "Captured statement expected");
8008 // 1.2.2 OpenMP Language Terminology
8009 // Structured block - An executable statement with a single entry at the
8010 // top and a single exit at the bottom.
8011 // The point of exit cannot be a branch out of the structured block.
8012 // longjmp() and throw() must not violate the entry/exit criteria.
8013 CS->getCapturedDecl()->setNothrow();
8014
8015 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
8016 ThisCaptureLevel > 1; --ThisCaptureLevel) {
8017 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
8018 // 1.2.2 OpenMP Language Terminology
8019 // Structured block - An executable statement with a single entry at the
8020 // top and a single exit at the bottom.
8021 // The point of exit cannot be a branch out of the structured block.
8022 // longjmp() and throw() must not violate the entry/exit criteria.
8023 CS->getCapturedDecl()->setNothrow();
8024 }
8025 SemaRef.setFunctionHasBranchProtectedScope();
8026 return CS;
8027}
8028
8029StmtResult
8030SemaOpenMP::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
8031 Stmt *AStmt, SourceLocation StartLoc,
8032 SourceLocation EndLoc) {
8033 if (!AStmt)
8034 return StmtError();
8035
8036 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel, AStmt);
8037
8038 return OMPParallelDirective::Create(
8039 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
8040 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
8041}
8042
8043namespace {
8044/// Iteration space of a single for loop.
8045struct LoopIterationSpace final {
8046 /// True if the condition operator is the strict compare operator (<, > or
8047 /// !=).
8048 bool IsStrictCompare = false;
8049 /// Condition of the loop.
8050 Expr *PreCond = nullptr;
8051 /// This expression calculates the number of iterations in the loop.
8052 /// It is always possible to calculate it before starting the loop.
8053 Expr *NumIterations = nullptr;
8054 /// The loop counter variable.
8055 Expr *CounterVar = nullptr;
8056 /// Private loop counter variable.
8057 Expr *PrivateCounterVar = nullptr;
8058 /// This is initializer for the initial value of #CounterVar.
8059 Expr *CounterInit = nullptr;
8060 /// This is step for the #CounterVar used to generate its update:
8061 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
8062 Expr *CounterStep = nullptr;
8063 /// Should step be subtracted?
8064 bool Subtract = false;
8065 /// Source range of the loop init.
8066 SourceRange InitSrcRange;
8067 /// Source range of the loop condition.
8068 SourceRange CondSrcRange;
8069 /// Source range of the loop increment.
8070 SourceRange IncSrcRange;
8071 /// Minimum value that can have the loop control variable. Used to support
8072 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
8073 /// since only such variables can be used in non-loop invariant expressions.
8074 Expr *MinValue = nullptr;
8075 /// Maximum value that can have the loop control variable. Used to support
8076 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
8077 /// since only such variables can be used in non-loop invariant expressions.
8078 Expr *MaxValue = nullptr;
8079 /// true, if the lower bound depends on the outer loop control var.
8080 bool IsNonRectangularLB = false;
8081 /// true, if the upper bound depends on the outer loop control var.
8082 bool IsNonRectangularUB = false;
8083 /// Index of the loop this loop depends on and forms non-rectangular loop
8084 /// nest.
8085 unsigned LoopDependentIdx = 0;
8086 /// Final condition for the non-rectangular loop nest support. It is used to
8087 /// check that the number of iterations for this particular counter must be
8088 /// finished.
8089 Expr *FinalCondition = nullptr;
8090};
8091
8092/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
8093/// set are referenced. Used for verifying loop nest structure before
8094/// performing a loop collapse operation.
8095class ForSubExprChecker : public DynamicRecursiveASTVisitor {
8096 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8097 VarDecl *ForbiddenVar = nullptr;
8098 SourceRange ErrLoc;
8099
8100public:
8101 explicit ForSubExprChecker(
8102 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
8103 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
8104 // We want to visit implicit code, i.e. synthetic initialisation statements
8105 // created during range-for lowering.
8106 ShouldVisitImplicitCode = true;
8107 }
8108
8109 bool VisitDeclRefExpr(DeclRefExpr *E) override {
8110 ValueDecl *VD = E->getDecl();
8111 if (!isa<VarDecl, BindingDecl>(Val: VD))
8112 return true;
8113 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
8114 if (V->getType()->isReferenceType()) {
8115 VarDecl *VD = V->getDefinition();
8116 if (VD && VD->hasInit()) {
8117 Expr *I = VD->getInit();
8118 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Val: I);
8119 if (!DRE)
8120 return true;
8121 V = DRE->getDecl()->getPotentiallyDecomposedVarDecl();
8122 }
8123 }
8124 Decl *Canon = V->getCanonicalDecl();
8125 if (CollapsedLoopVarDecls.contains(Ptr: Canon)) {
8126 ForbiddenVar = V;
8127 ErrLoc = E->getSourceRange();
8128 return false;
8129 }
8130
8131 return true;
8132 }
8133
8134 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
8135 SourceRange getErrRange() const { return ErrLoc; }
8136};
8137
8138/// Helper class for checking canonical form of the OpenMP loops and
8139/// extracting iteration space of each loop in the loop nest, that will be used
8140/// for IR generation.
8141class OpenMPIterationSpaceChecker {
8142 /// Reference to Sema.
8143 Sema &SemaRef;
8144 /// Does the loop associated directive support non-rectangular loops?
8145 bool SupportsNonRectangular;
8146 /// Data-sharing stack.
8147 DSAStackTy &Stack;
8148 /// A location for diagnostics (when there is no some better location).
8149 SourceLocation DefaultLoc;
8150 /// A location for diagnostics (when increment is not compatible).
8151 SourceLocation ConditionLoc;
8152 /// The set of variables declared within the (to be collapsed) loop nest.
8153 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8154 /// The set of induction variables from outer collapsed loops.
8155 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars;
8156 /// A source location for referring to loop init later.
8157 SourceRange InitSrcRange;
8158 /// A source location for referring to condition later.
8159 SourceRange ConditionSrcRange;
8160 /// A source location for referring to increment later.
8161 SourceRange IncrementSrcRange;
8162 /// Loop variable.
8163 ValueDecl *LCDecl = nullptr;
8164 /// Reference to loop variable.
8165 Expr *LCRef = nullptr;
8166 /// Lower bound (initializer for the var).
8167 Expr *LB = nullptr;
8168 /// Upper bound.
8169 Expr *UB = nullptr;
8170 /// Loop step (increment).
8171 Expr *Step = nullptr;
8172 /// This flag is true when condition is one of:
8173 /// Var < UB
8174 /// Var <= UB
8175 /// UB > Var
8176 /// UB >= Var
8177 /// This will have no value when the condition is !=
8178 std::optional<bool> TestIsLessOp;
8179 /// This flag is true when condition is strict ( < or > ).
8180 bool TestIsStrictOp = false;
8181 /// This flag is true when step is subtracted on each iteration.
8182 bool SubtractStep = false;
8183 /// The outer loop counter this loop depends on (if any).
8184 const ValueDecl *DepDecl = nullptr;
8185 /// Contains number of loop (starts from 1) on which loop counter init
8186 /// expression of this loop depends on.
8187 std::optional<unsigned> InitDependOnLC;
8188 /// Contains number of loop (starts from 1) on which loop counter condition
8189 /// expression of this loop depends on.
8190 std::optional<unsigned> CondDependOnLC;
8191 /// Checks if the provide statement depends on the loop counter.
8192 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8193 bool IsInitializer);
8194 /// Original condition required for checking of the exit condition for
8195 /// non-rectangular loop.
8196 Expr *Condition = nullptr;
8197
8198public:
8199 OpenMPIterationSpaceChecker(
8200 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
8201 SourceLocation DefaultLoc,
8202 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls,
8203 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars)
8204 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8205 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8206 CollapsedLoopVarDecls(CollapsedLoopDecls),
8207 CollapsedLoopInductionVars(CollapsedLoopInductionVars) {}
8208 /// Check init-expr for canonical loop form and save loop counter
8209 /// variable - #Var and its initialization value - #LB.
8210 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8211 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8212 /// for less/greater and for strict/non-strict comparison.
8213 bool checkAndSetCond(Expr *S);
8214 /// Check incr-expr for canonical loop form and return true if it
8215 /// does not conform, otherwise save loop step (#Step).
8216 bool checkAndSetInc(Expr *S);
8217 /// Return the loop counter variable.
8218 ValueDecl *getLoopDecl() const { return LCDecl; }
8219 /// Return the reference expression to loop counter variable.
8220 Expr *getLoopDeclRefExpr() const { return LCRef; }
8221 /// Source range of the loop init.
8222 SourceRange getInitSrcRange() const { return InitSrcRange; }
8223 /// Source range of the loop condition.
8224 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8225 /// Source range of the loop increment.
8226 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8227 /// True if the step should be subtracted.
8228 bool shouldSubtractStep() const { return SubtractStep; }
8229 /// True, if the compare operator is strict (<, > or !=).
8230 bool isStrictTestOp() const { return TestIsStrictOp; }
8231 /// Build the expression to calculate the number of iterations.
8232 Expr *buildNumIterations(
8233 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8234 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8235 /// Build the precondition expression for the loops.
8236 Expr *
8237 buildPreCond(Scope *S, Expr *Cond,
8238 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8239 /// Build reference expression to the counter be used for codegen.
8240 DeclRefExpr *
8241 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8242 DSAStackTy &DSA) const;
8243 /// Build reference expression to the private counter be used for
8244 /// codegen.
8245 Expr *buildPrivateCounterVar() const;
8246 /// Build initialization of the counter be used for codegen.
8247 Expr *buildCounterInit() const;
8248 /// Build step of the counter be used for codegen.
8249 Expr *buildCounterStep() const;
8250 /// Build loop data with counter value for depend clauses in ordered
8251 /// directives.
8252 Expr *
8253 buildOrderedLoopData(Scope *S, Expr *Counter,
8254 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8255 SourceLocation Loc, Expr *Inc = nullptr,
8256 OverloadedOperatorKind OOK = OO_Amp);
8257 /// Builds the minimum value for the loop counter.
8258 std::pair<Expr *, Expr *> buildMinMaxValues(
8259 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8260 /// Builds final condition for the non-rectangular loops.
8261 Expr *buildFinalCondition(Scope *S) const;
8262 /// Return true if any expression is dependent.
8263 bool dependent() const;
8264 /// Returns true if the initializer forms non-rectangular loop.
8265 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8266 /// Returns true if the condition forms non-rectangular loop.
8267 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8268 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8269 unsigned getLoopDependentIdx() const {
8270 return InitDependOnLC.value_or(u: CondDependOnLC.value_or(u: 0));
8271 }
8272
8273private:
8274 /// Check the right-hand side of an assignment in the increment
8275 /// expression.
8276 bool checkAndSetIncRHS(Expr *RHS);
8277 /// Helper to set loop counter variable and its initializer.
8278 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8279 bool EmitDiags);
8280 /// Helper to set upper bound.
8281 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8282 SourceRange SR, SourceLocation SL);
8283 /// Helper to set loop increment.
8284 bool setStep(Expr *NewStep, bool Subtract);
8285};
8286
8287bool OpenMPIterationSpaceChecker::dependent() const {
8288 if (!LCDecl) {
8289 assert(!LB && !UB && !Step);
8290 return false;
8291 }
8292 return LCDecl->getType()->isDependentType() ||
8293 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8294 (Step && Step->isValueDependent());
8295}
8296
8297bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8298 Expr *NewLCRefExpr,
8299 Expr *NewLB, bool EmitDiags) {
8300 // State consistency checking to ensure correct usage.
8301 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8302 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8303 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8304 return true;
8305 LCDecl = getCanonicalDecl(D: NewLCDecl);
8306 LCRef = NewLCRefExpr;
8307 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(Val: NewLB))
8308 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8309 if ((Ctor->isCopyOrMoveConstructor() ||
8310 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8311 CE->getNumArgs() > 0 && CE->getArg(Arg: 0) != nullptr)
8312 NewLB = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
8313 LB = NewLB;
8314 if (EmitDiags)
8315 InitDependOnLC = doesDependOnLoopCounter(S: LB, /*IsInitializer=*/true);
8316 return false;
8317}
8318
8319bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8320 bool StrictOp, SourceRange SR,
8321 SourceLocation SL) {
8322 // State consistency checking to ensure correct usage.
8323 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8324 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8325 if (!NewUB || NewUB->containsErrors())
8326 return true;
8327 UB = NewUB;
8328 if (LessOp)
8329 TestIsLessOp = LessOp;
8330 TestIsStrictOp = StrictOp;
8331 ConditionSrcRange = SR;
8332 ConditionLoc = SL;
8333 CondDependOnLC = doesDependOnLoopCounter(S: UB, /*IsInitializer=*/false);
8334 return false;
8335}
8336
8337bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8338 // State consistency checking to ensure correct usage.
8339 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8340 if (!NewStep || NewStep->containsErrors())
8341 return true;
8342 if (!NewStep->isValueDependent()) {
8343 // Check that the step is integer expression.
8344 SourceLocation StepLoc = NewStep->getBeginLoc();
8345 ExprResult Val = SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(
8346 OpLoc: StepLoc, Op: getExprAsWritten(E: NewStep));
8347 if (Val.isInvalid())
8348 return true;
8349 NewStep = Val.get();
8350
8351 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8352 // If test-expr is of form var relational-op b and relational-op is < or
8353 // <= then incr-expr must cause var to increase on each iteration of the
8354 // loop. If test-expr is of form var relational-op b and relational-op is
8355 // > or >= then incr-expr must cause var to decrease on each iteration of
8356 // the loop.
8357 // If test-expr is of form b relational-op var and relational-op is < or
8358 // <= then incr-expr must cause var to decrease on each iteration of the
8359 // loop. If test-expr is of form b relational-op var and relational-op is
8360 // > or >= then incr-expr must cause var to increase on each iteration of
8361 // the loop.
8362 std::optional<llvm::APSInt> Result =
8363 NewStep->getIntegerConstantExpr(Ctx: SemaRef.Context);
8364 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8365 bool IsConstNeg =
8366 Result && Result->isSigned() && (Subtract != Result->isNegative());
8367 bool IsConstPos =
8368 Result && Result->isSigned() && (Subtract == Result->isNegative());
8369 bool IsConstZero = Result && !Result->getBoolValue();
8370
8371 // != with increment is treated as <; != with decrement is treated as >
8372 if (!TestIsLessOp)
8373 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8374 if (UB && (IsConstZero ||
8375 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8376 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8377 SemaRef.Diag(Loc: NewStep->getExprLoc(),
8378 DiagID: diag::err_omp_loop_incr_not_compatible)
8379 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8380 SemaRef.Diag(Loc: ConditionLoc,
8381 DiagID: diag::note_omp_loop_cond_requires_compatible_incr)
8382 << *TestIsLessOp << ConditionSrcRange;
8383 return true;
8384 }
8385 if (*TestIsLessOp == Subtract) {
8386 NewStep =
8387 SemaRef.CreateBuiltinUnaryOp(OpLoc: NewStep->getExprLoc(), Opc: UO_Minus, InputExpr: NewStep)
8388 .get();
8389 Subtract = !Subtract;
8390 }
8391 }
8392
8393 Step = NewStep;
8394 SubtractStep = Subtract;
8395 return false;
8396}
8397
8398namespace {
8399/// Checker for the non-rectangular loops. Checks if the initializer or
8400/// condition expression references loop counter variable.
8401class LoopCounterRefChecker final
8402 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8403 Sema &SemaRef;
8404 DSAStackTy &Stack;
8405 const ValueDecl *CurLCDecl = nullptr;
8406 const ValueDecl *DepDecl = nullptr;
8407 const ValueDecl *PrevDepDecl = nullptr;
8408 bool IsInitializer = true;
8409 bool SupportsNonRectangular;
8410 unsigned BaseLoopId = 0;
8411 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8412 if (getCanonicalDecl(D: VD) == getCanonicalDecl(D: CurLCDecl)) {
8413 SemaRef.Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_stmt_depends_on_loop_counter)
8414 << (IsInitializer ? 0 : 1);
8415 return false;
8416 }
8417 const auto &&Data = Stack.isLoopControlVariable(D: VD);
8418 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8419 // The type of the loop iterator on which we depend may not have a random
8420 // access iterator type.
8421 if (Data.first && VD->getType()->isRecordType()) {
8422 SmallString<128> Name;
8423 llvm::raw_svector_ostream OS(Name);
8424 VD->getNameForDiagnostic(OS, Policy: SemaRef.getPrintingPolicy(),
8425 /*Qualified=*/true);
8426 SemaRef.Diag(Loc: E->getExprLoc(),
8427 DiagID: diag::err_omp_wrong_dependency_iterator_type)
8428 << OS.str();
8429 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::note_previous_decl) << VD;
8430 return false;
8431 }
8432 if (Data.first && !SupportsNonRectangular) {
8433 SemaRef.Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_invariant_dependency);
8434 return false;
8435 }
8436 if (Data.first &&
8437 (DepDecl || (PrevDepDecl &&
8438 getCanonicalDecl(D: VD) != getCanonicalDecl(D: PrevDepDecl)))) {
8439 if (!DepDecl && PrevDepDecl)
8440 DepDecl = PrevDepDecl;
8441 SmallString<128> Name;
8442 llvm::raw_svector_ostream OS(Name);
8443 DepDecl->getNameForDiagnostic(OS, Policy: SemaRef.getPrintingPolicy(),
8444 /*Qualified=*/true);
8445 SemaRef.Diag(Loc: E->getExprLoc(),
8446 DiagID: diag::err_omp_invariant_or_linear_dependency)
8447 << OS.str();
8448 return false;
8449 }
8450 if (Data.first) {
8451 DepDecl = VD;
8452 BaseLoopId = Data.first;
8453 }
8454 return Data.first;
8455 }
8456
8457public:
8458 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8459 const ValueDecl *VD = E->getDecl();
8460 if (isa<VarDecl>(Val: VD))
8461 return checkDecl(E, VD);
8462 return false;
8463 }
8464 bool VisitMemberExpr(const MemberExpr *E) {
8465 if (isa<CXXThisExpr>(Val: E->getBase()->IgnoreParens())) {
8466 const ValueDecl *VD = E->getMemberDecl();
8467 if (isa<VarDecl>(Val: VD) || isa<FieldDecl>(Val: VD))
8468 return checkDecl(E, VD);
8469 }
8470 return false;
8471 }
8472 bool VisitStmt(const Stmt *S) {
8473 bool Res = false;
8474 for (const Stmt *Child : S->children())
8475 Res = (Child && Visit(S: Child)) || Res;
8476 return Res;
8477 }
8478 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8479 const ValueDecl *CurLCDecl, bool IsInitializer,
8480 const ValueDecl *PrevDepDecl = nullptr,
8481 bool SupportsNonRectangular = true)
8482 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8483 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8484 SupportsNonRectangular(SupportsNonRectangular) {}
8485 unsigned getBaseLoopId() const {
8486 assert(CurLCDecl && "Expected loop dependency.");
8487 return BaseLoopId;
8488 }
8489 const ValueDecl *getDepDecl() const {
8490 assert(CurLCDecl && "Expected loop dependency.");
8491 return DepDecl;
8492 }
8493};
8494} // namespace
8495
8496std::optional<unsigned>
8497OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8498 bool IsInitializer) {
8499 // Check for the non-rectangular loops.
8500 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8501 DepDecl, SupportsNonRectangular);
8502 if (LoopStmtChecker.Visit(S)) {
8503 DepDecl = LoopStmtChecker.getDepDecl();
8504 return LoopStmtChecker.getBaseLoopId();
8505 }
8506 return std::nullopt;
8507}
8508
8509bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8510 // Check init-expr for canonical loop form and save loop counter
8511 // variable - #Var and its initialization value - #LB.
8512 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8513 // var = lb
8514 // integer-type var = lb
8515 // random-access-iterator-type var = lb
8516 // pointer-type var = lb
8517 //
8518 if (!S) {
8519 if (EmitDiags) {
8520 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_init);
8521 }
8522 return true;
8523 }
8524 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: S))
8525 if (!ExprTemp->cleanupsHaveSideEffects())
8526 S = ExprTemp->getSubExpr();
8527
8528 if (!CollapsedLoopVarDecls.empty()) {
8529 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8530 if (!FSEC.TraverseStmt(S)) {
8531 SourceRange Range = FSEC.getErrRange();
8532 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
8533 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8534 return true;
8535 }
8536 }
8537
8538 // Helper lambda to check if a loop variable is already used in an outer
8539 // loop.
8540 auto CheckLoopVarReuse = [&](ValueDecl *LoopVar, SourceLocation Loc) -> bool {
8541 if (EmitDiags &&
8542 CollapsedLoopInductionVars.count(Ptr: LoopVar->getCanonicalDecl())) {
8543 SemaRef.Diag(Loc, DiagID: diag::err_omp_loop_var_reused_in_collapsed_loop)
8544 << LoopVar;
8545 return true;
8546 }
8547 return false;
8548 };
8549
8550 InitSrcRange = S->getSourceRange();
8551 if (Expr *E = dyn_cast<Expr>(Val: S))
8552 S = E->IgnoreParens();
8553 if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8554 if (BO->getOpcode() == BO_Assign) {
8555 Expr *LHS = BO->getLHS()->IgnoreParens();
8556 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS)) {
8557 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: DRE->getDecl()))
8558 if (auto *ME =
8559 dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit()))) {
8560 ValueDecl *LoopVar = ME->getMemberDecl();
8561 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8562 return true;
8563 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: BO->getRHS(), EmitDiags);
8564 }
8565 ValueDecl *LoopVar = DRE->getDecl();
8566 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8567 return true;
8568 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: DRE, NewLB: BO->getRHS(), EmitDiags);
8569 }
8570 if (auto *ME = dyn_cast<MemberExpr>(Val: LHS)) {
8571 if (ME->isArrow() &&
8572 isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts())) {
8573 ValueDecl *LoopVar = ME->getMemberDecl();
8574 if (CheckLoopVarReuse(LoopVar, LHS->getBeginLoc()))
8575 return true;
8576 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: BO->getRHS(), EmitDiags);
8577 }
8578 }
8579 }
8580 } else if (auto *DS = dyn_cast<DeclStmt>(Val: S)) {
8581 if (DS->isSingleDecl()) {
8582 if (auto *Var = dyn_cast_or_null<VarDecl>(Val: DS->getSingleDecl())) {
8583 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8584 // Accept non-canonical init form here but emit ext. warning.
8585 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8586 SemaRef.Diag(Loc: S->getBeginLoc(),
8587 DiagID: diag::ext_omp_loop_not_canonical_init)
8588 << S->getSourceRange();
8589 if (CheckLoopVarReuse(Var, Var->getLocation()))
8590 return true;
8591 return setLCDeclAndLB(
8592 NewLCDecl: Var,
8593 NewLCRefExpr: buildDeclRefExpr(S&: SemaRef, D: Var,
8594 Ty: Var->getType().getNonReferenceType(),
8595 Loc: DS->getBeginLoc()),
8596 NewLB: Var->getInit(), EmitDiags);
8597 }
8598 }
8599 }
8600 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8601 if (CE->getOperator() == OO_Equal) {
8602 Expr *LHS = CE->getArg(Arg: 0);
8603 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS)) {
8604 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: DRE->getDecl()))
8605 if (auto *ME =
8606 dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit()))) {
8607 ValueDecl *LoopVar = ME->getMemberDecl();
8608 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8609 return true;
8610 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: CE->getArg(Arg: 1), EmitDiags);
8611 }
8612 ValueDecl *LoopVar = DRE->getDecl();
8613 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8614 return true;
8615 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: DRE, NewLB: CE->getArg(Arg: 1), EmitDiags);
8616 }
8617 if (auto *ME = dyn_cast<MemberExpr>(Val: LHS)) {
8618 if (ME->isArrow() &&
8619 isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts())) {
8620 ValueDecl *LoopVar = ME->getMemberDecl();
8621 if (CheckLoopVarReuse(LoopVar, LHS->getBeginLoc()))
8622 return true;
8623 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: CE->getArg(Arg: 1), EmitDiags);
8624 }
8625 }
8626 }
8627 }
8628
8629 if (dependent() || SemaRef.CurContext->isDependentContext())
8630 return false;
8631 if (EmitDiags) {
8632 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_init)
8633 << S->getSourceRange();
8634 }
8635 return true;
8636}
8637
8638/// Ignore parenthesizes, implicit casts, copy constructor and return the
8639/// variable (which may be the loop variable) if possible.
8640static const ValueDecl *getInitLCDecl(const Expr *E) {
8641 if (!E)
8642 return nullptr;
8643 E = getExprAsWritten(E);
8644 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(Val: E))
8645 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8646 if ((Ctor->isCopyOrMoveConstructor() ||
8647 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8648 CE->getNumArgs() > 0 && CE->getArg(Arg: 0) != nullptr)
8649 E = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
8650 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(Val: E)) {
8651 if (const auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
8652 return getCanonicalDecl(D: VD);
8653 }
8654 if (const auto *ME = dyn_cast_or_null<MemberExpr>(Val: E))
8655 if (ME->isArrow() && isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
8656 return getCanonicalDecl(D: ME->getMemberDecl());
8657 return nullptr;
8658}
8659
8660bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8661 // Check test-expr for canonical form, save upper-bound UB, flags for
8662 // less/greater and for strict/non-strict comparison.
8663 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8664 // var relational-op b
8665 // b relational-op var
8666 //
8667 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8668 if (!S) {
8669 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_cond)
8670 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8671 return true;
8672 }
8673 Condition = S;
8674 S = getExprAsWritten(E: S);
8675
8676 if (!CollapsedLoopVarDecls.empty()) {
8677 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8678 if (!FSEC.TraverseStmt(S)) {
8679 SourceRange Range = FSEC.getErrRange();
8680 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
8681 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8682 return true;
8683 }
8684 }
8685
8686 SourceLocation CondLoc = S->getBeginLoc();
8687 auto &&CheckAndSetCond =
8688 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8689 const Expr *RHS, SourceRange SR,
8690 SourceLocation OpLoc) -> std::optional<bool> {
8691 if (BinaryOperator::isRelationalOp(Opc: Opcode)) {
8692 if (getInitLCDecl(E: LHS) == LCDecl)
8693 return setUB(NewUB: const_cast<Expr *>(RHS),
8694 LessOp: (Opcode == BO_LT || Opcode == BO_LE),
8695 StrictOp: (Opcode == BO_LT || Opcode == BO_GT), SR, SL: OpLoc);
8696 if (getInitLCDecl(E: RHS) == LCDecl)
8697 return setUB(NewUB: const_cast<Expr *>(LHS),
8698 LessOp: (Opcode == BO_GT || Opcode == BO_GE),
8699 StrictOp: (Opcode == BO_LT || Opcode == BO_GT), SR, SL: OpLoc);
8700 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8701 return setUB(NewUB: const_cast<Expr *>(getInitLCDecl(E: LHS) == LCDecl ? RHS : LHS),
8702 /*LessOp=*/std::nullopt,
8703 /*StrictOp=*/true, SR, SL: OpLoc);
8704 }
8705 return std::nullopt;
8706 };
8707 std::optional<bool> Res;
8708 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(Val: S)) {
8709 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8710 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8711 RBO->getOperatorLoc());
8712 } else if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8713 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8714 BO->getSourceRange(), BO->getOperatorLoc());
8715 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8716 if (CE->getNumArgs() == 2) {
8717 Res = CheckAndSetCond(
8718 BinaryOperator::getOverloadedOpcode(OO: CE->getOperator()), CE->getArg(Arg: 0),
8719 CE->getArg(Arg: 1), CE->getSourceRange(), CE->getOperatorLoc());
8720 }
8721 }
8722 if (Res)
8723 return *Res;
8724 if (dependent() || SemaRef.CurContext->isDependentContext())
8725 return false;
8726 SemaRef.Diag(Loc: CondLoc, DiagID: diag::err_omp_loop_not_canonical_cond)
8727 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8728 return true;
8729}
8730
8731bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8732 // RHS of canonical loop form increment can be:
8733 // var + incr
8734 // incr + var
8735 // var - incr
8736 //
8737 RHS = RHS->IgnoreParenImpCasts();
8738 if (auto *BO = dyn_cast<BinaryOperator>(Val: RHS)) {
8739 if (BO->isAdditiveOp()) {
8740 bool IsAdd = BO->getOpcode() == BO_Add;
8741 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8742 return setStep(NewStep: BO->getRHS(), Subtract: !IsAdd);
8743 if (IsAdd && getInitLCDecl(E: BO->getRHS()) == LCDecl)
8744 return setStep(NewStep: BO->getLHS(), /*Subtract=*/false);
8745 }
8746 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: RHS)) {
8747 bool IsAdd = CE->getOperator() == OO_Plus;
8748 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8749 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8750 return setStep(NewStep: CE->getArg(Arg: 1), Subtract: !IsAdd);
8751 if (IsAdd && getInitLCDecl(E: CE->getArg(Arg: 1)) == LCDecl)
8752 return setStep(NewStep: CE->getArg(Arg: 0), /*Subtract=*/false);
8753 }
8754 }
8755 if (dependent() || SemaRef.CurContext->isDependentContext())
8756 return false;
8757 SemaRef.Diag(Loc: RHS->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_incr)
8758 << RHS->getSourceRange() << LCDecl;
8759 return true;
8760}
8761
8762bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8763 // Check incr-expr for canonical loop form and return true if it
8764 // does not conform.
8765 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8766 // ++var
8767 // var++
8768 // --var
8769 // var--
8770 // var += incr
8771 // var -= incr
8772 // var = var + incr
8773 // var = incr + var
8774 // var = var - incr
8775 //
8776 if (!S) {
8777 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_incr) << LCDecl;
8778 return true;
8779 }
8780 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: S))
8781 if (!ExprTemp->cleanupsHaveSideEffects())
8782 S = ExprTemp->getSubExpr();
8783
8784 if (!CollapsedLoopVarDecls.empty()) {
8785 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8786 if (!FSEC.TraverseStmt(S)) {
8787 SourceRange Range = FSEC.getErrRange();
8788 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
8789 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8790 return true;
8791 }
8792 }
8793
8794 IncrementSrcRange = S->getSourceRange();
8795 S = S->IgnoreParens();
8796 if (auto *UO = dyn_cast<UnaryOperator>(Val: S)) {
8797 if (UO->isIncrementDecrementOp() &&
8798 getInitLCDecl(E: UO->getSubExpr()) == LCDecl)
8799 return setStep(NewStep: SemaRef
8800 .ActOnIntegerConstant(Loc: UO->getBeginLoc(),
8801 Val: (UO->isDecrementOp() ? -1 : 1))
8802 .get(),
8803 /*Subtract=*/false);
8804 } else if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8805 switch (BO->getOpcode()) {
8806 case BO_AddAssign:
8807 case BO_SubAssign:
8808 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8809 return setStep(NewStep: BO->getRHS(), Subtract: BO->getOpcode() == BO_SubAssign);
8810 break;
8811 case BO_Assign:
8812 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8813 return checkAndSetIncRHS(RHS: BO->getRHS());
8814 break;
8815 default:
8816 break;
8817 }
8818 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8819 switch (CE->getOperator()) {
8820 case OO_PlusPlus:
8821 case OO_MinusMinus:
8822 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8823 return setStep(NewStep: SemaRef
8824 .ActOnIntegerConstant(
8825 Loc: CE->getBeginLoc(),
8826 Val: ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8827 .get(),
8828 /*Subtract=*/false);
8829 break;
8830 case OO_PlusEqual:
8831 case OO_MinusEqual:
8832 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8833 return setStep(NewStep: CE->getArg(Arg: 1), Subtract: CE->getOperator() == OO_MinusEqual);
8834 break;
8835 case OO_Equal:
8836 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8837 return checkAndSetIncRHS(RHS: CE->getArg(Arg: 1));
8838 break;
8839 default:
8840 break;
8841 }
8842 }
8843 if (dependent() || SemaRef.CurContext->isDependentContext())
8844 return false;
8845 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_incr)
8846 << S->getSourceRange() << LCDecl;
8847 return true;
8848}
8849
8850static ExprResult
8851tryBuildCapture(Sema &SemaRef, Expr *Capture,
8852 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8853 StringRef Name = ".capture_expr.") {
8854 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8855 return Capture;
8856 if (Capture->isEvaluatable(Ctx: SemaRef.Context, AllowSideEffects: Expr::SE_AllowSideEffects))
8857 return SemaRef.PerformImplicitConversion(From: Capture->IgnoreImpCasts(),
8858 ToType: Capture->getType(),
8859 Action: AssignmentAction::Converting,
8860 /*AllowExplicit=*/true);
8861 auto I = Captures.find(Key: Capture);
8862 if (I != Captures.end())
8863 return buildCapture(S&: SemaRef, CaptureExpr: Capture, Ref&: I->second, Name);
8864 DeclRefExpr *Ref = nullptr;
8865 ExprResult Res = buildCapture(S&: SemaRef, CaptureExpr: Capture, Ref, Name);
8866 Captures[Capture] = Ref;
8867 return Res;
8868}
8869
8870/// Calculate number of iterations, transforming to unsigned, if number of
8871/// iterations may be larger than the original type.
8872static Expr *
8873calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8874 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8875 bool TestIsStrictOp, bool RoundToStep,
8876 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8877 std::optional<unsigned> InitDependOnLC,
8878 std::optional<unsigned> CondDependOnLC) {
8879 ExprResult NewStep = tryBuildCapture(SemaRef, Capture: Step, Captures, Name: ".new_step");
8880 if (!NewStep.isUsable())
8881 return nullptr;
8882 llvm::APSInt LRes, SRes;
8883 bool IsLowerConst = false, IsStepConst = false;
8884 if (std::optional<llvm::APSInt> Res =
8885 Lower->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8886 LRes = *Res;
8887 IsLowerConst = true;
8888 }
8889 if (std::optional<llvm::APSInt> Res =
8890 Step->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8891 SRes = *Res;
8892 IsStepConst = true;
8893 }
8894 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8895 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8896 (TestIsStrictOp && LRes.isStrictlyPositive()));
8897 bool NeedToReorganize = false;
8898 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8899 if (!NoNeedToConvert && IsLowerConst &&
8900 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8901 NoNeedToConvert = true;
8902 if (RoundToStep) {
8903 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8904 ? LRes.getBitWidth()
8905 : SRes.getBitWidth();
8906 LRes = LRes.extend(width: BW + 1);
8907 LRes.setIsSigned(true);
8908 SRes = SRes.extend(width: BW + 1);
8909 SRes.setIsSigned(true);
8910 LRes -= SRes;
8911 NoNeedToConvert = LRes.trunc(width: BW).extend(width: BW + 1) == LRes;
8912 LRes = LRes.trunc(width: BW);
8913 }
8914 if (TestIsStrictOp) {
8915 unsigned BW = LRes.getBitWidth();
8916 LRes = LRes.extend(width: BW + 1);
8917 LRes.setIsSigned(true);
8918 ++LRes;
8919 NoNeedToConvert =
8920 NoNeedToConvert && LRes.trunc(width: BW).extend(width: BW + 1) == LRes;
8921 // truncate to the original bitwidth.
8922 LRes = LRes.trunc(width: BW);
8923 }
8924 NeedToReorganize = NoNeedToConvert;
8925 }
8926 llvm::APSInt URes;
8927 bool IsUpperConst = false;
8928 if (std::optional<llvm::APSInt> Res =
8929 Upper->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8930 URes = *Res;
8931 IsUpperConst = true;
8932 }
8933 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8934 (!RoundToStep || IsStepConst)) {
8935 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8936 : URes.getBitWidth();
8937 LRes = LRes.extend(width: BW + 1);
8938 LRes.setIsSigned(true);
8939 URes = URes.extend(width: BW + 1);
8940 URes.setIsSigned(true);
8941 URes -= LRes;
8942 NoNeedToConvert = URes.trunc(width: BW).extend(width: BW + 1) == URes;
8943 NeedToReorganize = NoNeedToConvert;
8944 }
8945 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8946 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8947 // unsigned.
8948 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8949 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8950 QualType LowerTy = Lower->getType();
8951 QualType UpperTy = Upper->getType();
8952 uint64_t LowerSize = SemaRef.Context.getTypeSize(T: LowerTy);
8953 uint64_t UpperSize = SemaRef.Context.getTypeSize(T: UpperTy);
8954 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8955 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8956 QualType CastType = SemaRef.Context.getIntTypeForBitwidth(
8957 DestWidth: LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8958 Upper =
8959 SemaRef
8960 .PerformImplicitConversion(
8961 From: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Upper).get(),
8962 ToType: CastType, Action: AssignmentAction::Converting)
8963 .get();
8964 Lower = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Lower).get();
8965 NewStep = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: NewStep.get());
8966 }
8967 }
8968 if (!Lower || !Upper || NewStep.isInvalid())
8969 return nullptr;
8970
8971 ExprResult Diff;
8972
8973 // For nested triangular loops (depth >= 2), use already computed Upper and
8974 // Lower bounds to calculate the number of iterations: Upper - Lower + 1.
8975 // Don't apply to first-level triangular loops as the standard formula handles
8976 // those correctly.
8977 if (TestIsStrictOp && InitDependOnLC.has_value() &&
8978 InitDependOnLC.value() >= 2 && !CondDependOnLC.has_value()) {
8979 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Lower);
8980 if (!Diff.isUsable())
8981 return nullptr;
8982
8983 Diff =
8984 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(),
8985 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: DefaultLoc, Val: 1).get());
8986 if (!Diff.isUsable())
8987 return nullptr;
8988
8989 return Diff.get();
8990 }
8991
8992 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8993 // 1]).
8994 if (NeedToReorganize) {
8995 Diff = Lower;
8996
8997 if (RoundToStep) {
8998 // Lower - Step
8999 Diff =
9000 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
9001 if (!Diff.isUsable())
9002 return nullptr;
9003 }
9004
9005 // Lower - Step [+ 1]
9006 if (TestIsStrictOp)
9007 Diff = SemaRef.BuildBinOp(
9008 S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(),
9009 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
9010 if (!Diff.isUsable())
9011 return nullptr;
9012
9013 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9014 if (!Diff.isUsable())
9015 return nullptr;
9016
9017 // Upper - (Lower - Step [+ 1]).
9018 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Diff.get());
9019 if (!Diff.isUsable())
9020 return nullptr;
9021 } else {
9022 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Lower);
9023
9024 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
9025 // BuildBinOp already emitted error, this one is to point user to upper
9026 // and lower bound, and to tell what is passed to 'operator-'.
9027 SemaRef.Diag(Loc: Upper->getBeginLoc(), DiagID: diag::err_omp_loop_diff_cxx)
9028 << Upper->getSourceRange() << Lower->getSourceRange();
9029 return nullptr;
9030 }
9031
9032 if (!Diff.isUsable())
9033 return nullptr;
9034
9035 // Upper - Lower [- 1]
9036 if (TestIsStrictOp)
9037 Diff = SemaRef.BuildBinOp(
9038 S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Diff.get(),
9039 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
9040 if (!Diff.isUsable())
9041 return nullptr;
9042
9043 if (RoundToStep) {
9044 // Upper - Lower [- 1] + Step
9045 Diff =
9046 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
9047 if (!Diff.isUsable())
9048 return nullptr;
9049 }
9050 }
9051
9052 // Parentheses (for dumping/debugging purposes only).
9053 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9054 if (!Diff.isUsable())
9055 return nullptr;
9056
9057 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
9058 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Div, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
9059 if (!Diff.isUsable())
9060 return nullptr;
9061
9062 return Diff.get();
9063}
9064
9065/// Build the expression to calculate the number of iterations.
9066Expr *OpenMPIterationSpaceChecker::buildNumIterations(
9067 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
9068 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9069 QualType VarType = LCDecl->getType().getNonReferenceType();
9070 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9071 !SemaRef.getLangOpts().CPlusPlus)
9072 return nullptr;
9073 Expr *LBVal = LB;
9074 Expr *UBVal = UB;
9075 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
9076 // max(LB(MinVal), LB(MaxVal)))
9077 if (InitDependOnLC) {
9078 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
9079 if (!IS.MinValue || !IS.MaxValue)
9080 return nullptr;
9081 // OuterVar = Min
9082 ExprResult MinValue =
9083 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MinValue);
9084 if (!MinValue.isUsable())
9085 return nullptr;
9086
9087 ExprResult LBMinVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9088 LHSExpr: IS.CounterVar, RHSExpr: MinValue.get());
9089 if (!LBMinVal.isUsable())
9090 return nullptr;
9091 // OuterVar = Min, LBVal
9092 LBMinVal =
9093 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: LBMinVal.get(), RHSExpr: LBVal);
9094 if (!LBMinVal.isUsable())
9095 return nullptr;
9096 // (OuterVar = Min, LBVal)
9097 LBMinVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: LBMinVal.get());
9098 if (!LBMinVal.isUsable())
9099 return nullptr;
9100
9101 // OuterVar = Max
9102 ExprResult MaxValue =
9103 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MaxValue);
9104 if (!MaxValue.isUsable())
9105 return nullptr;
9106
9107 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9108 LHSExpr: IS.CounterVar, RHSExpr: MaxValue.get());
9109 if (!LBMaxVal.isUsable())
9110 return nullptr;
9111 // OuterVar = Max, LBVal
9112 LBMaxVal =
9113 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: LBMaxVal.get(), RHSExpr: LBVal);
9114 if (!LBMaxVal.isUsable())
9115 return nullptr;
9116 // (OuterVar = Max, LBVal)
9117 LBMaxVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: LBMaxVal.get());
9118 if (!LBMaxVal.isUsable())
9119 return nullptr;
9120
9121 Expr *LBMin =
9122 tryBuildCapture(SemaRef, Capture: LBMinVal.get(), Captures, Name: ".lb_min").get();
9123 Expr *LBMax =
9124 tryBuildCapture(SemaRef, Capture: LBMaxVal.get(), Captures, Name: ".lb_max").get();
9125 if (!LBMin || !LBMax)
9126 return nullptr;
9127 // LB(MinVal) < LB(MaxVal)
9128 ExprResult MinLessMaxRes =
9129 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_LT, LHSExpr: LBMin, RHSExpr: LBMax);
9130 if (!MinLessMaxRes.isUsable())
9131 return nullptr;
9132 Expr *MinLessMax =
9133 tryBuildCapture(SemaRef, Capture: MinLessMaxRes.get(), Captures, Name: ".min_less_max")
9134 .get();
9135 if (!MinLessMax)
9136 return nullptr;
9137 if (*TestIsLessOp) {
9138 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
9139 // LB(MaxVal))
9140 ExprResult MinLB = SemaRef.ActOnConditionalOp(QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc,
9141 CondExpr: MinLessMax, LHSExpr: LBMin, RHSExpr: LBMax);
9142 if (!MinLB.isUsable())
9143 return nullptr;
9144 LBVal = MinLB.get();
9145 } else {
9146 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
9147 // LB(MaxVal))
9148 ExprResult MaxLB = SemaRef.ActOnConditionalOp(QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc,
9149 CondExpr: MinLessMax, LHSExpr: LBMax, RHSExpr: LBMin);
9150 if (!MaxLB.isUsable())
9151 return nullptr;
9152 LBVal = MaxLB.get();
9153 }
9154 // OuterVar = LB
9155 LBMinVal =
9156 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign, LHSExpr: IS.CounterVar, RHSExpr: LBVal);
9157 if (!LBMinVal.isUsable())
9158 return nullptr;
9159 LBVal = LBMinVal.get();
9160 }
9161 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
9162 // min(UB(MinVal), UB(MaxVal))
9163 if (CondDependOnLC) {
9164 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
9165 if (!IS.MinValue || !IS.MaxValue)
9166 return nullptr;
9167 // OuterVar = Min
9168 ExprResult MinValue =
9169 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MinValue);
9170 if (!MinValue.isUsable())
9171 return nullptr;
9172
9173 ExprResult UBMinVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9174 LHSExpr: IS.CounterVar, RHSExpr: MinValue.get());
9175 if (!UBMinVal.isUsable())
9176 return nullptr;
9177 // OuterVar = Min, UBVal
9178 UBMinVal =
9179 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: UBMinVal.get(), RHSExpr: UBVal);
9180 if (!UBMinVal.isUsable())
9181 return nullptr;
9182 // (OuterVar = Min, UBVal)
9183 UBMinVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: UBMinVal.get());
9184 if (!UBMinVal.isUsable())
9185 return nullptr;
9186
9187 // OuterVar = Max
9188 ExprResult MaxValue =
9189 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MaxValue);
9190 if (!MaxValue.isUsable())
9191 return nullptr;
9192
9193 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9194 LHSExpr: IS.CounterVar, RHSExpr: MaxValue.get());
9195 if (!UBMaxVal.isUsable())
9196 return nullptr;
9197 // OuterVar = Max, UBVal
9198 UBMaxVal =
9199 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: UBMaxVal.get(), RHSExpr: UBVal);
9200 if (!UBMaxVal.isUsable())
9201 return nullptr;
9202 // (OuterVar = Max, UBVal)
9203 UBMaxVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: UBMaxVal.get());
9204 if (!UBMaxVal.isUsable())
9205 return nullptr;
9206
9207 Expr *UBMin =
9208 tryBuildCapture(SemaRef, Capture: UBMinVal.get(), Captures, Name: ".ub_min").get();
9209 Expr *UBMax =
9210 tryBuildCapture(SemaRef, Capture: UBMaxVal.get(), Captures, Name: ".ub_max").get();
9211 if (!UBMin || !UBMax)
9212 return nullptr;
9213 // UB(MinVal) > UB(MaxVal)
9214 ExprResult MinGreaterMaxRes =
9215 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_GT, LHSExpr: UBMin, RHSExpr: UBMax);
9216 if (!MinGreaterMaxRes.isUsable())
9217 return nullptr;
9218 Expr *MinGreaterMax = tryBuildCapture(SemaRef, Capture: MinGreaterMaxRes.get(),
9219 Captures, Name: ".min_greater_max")
9220 .get();
9221 if (!MinGreaterMax)
9222 return nullptr;
9223 if (*TestIsLessOp) {
9224 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
9225 // UB(MaxVal))
9226 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
9227 QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc, CondExpr: MinGreaterMax, LHSExpr: UBMin, RHSExpr: UBMax);
9228 if (!MaxUB.isUsable())
9229 return nullptr;
9230 UBVal = MaxUB.get();
9231 } else {
9232 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9233 // UB(MaxVal))
9234 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9235 QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc, CondExpr: MinGreaterMax, LHSExpr: UBMax, RHSExpr: UBMin);
9236 if (!MinUB.isUsable())
9237 return nullptr;
9238 UBVal = MinUB.get();
9239 }
9240 }
9241 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9242 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9243 Expr *Upper = tryBuildCapture(SemaRef, Capture: UBExpr, Captures, Name: ".upper").get();
9244 Expr *Lower = tryBuildCapture(SemaRef, Capture: LBExpr, Captures, Name: ".lower").get();
9245 if (!Upper || !Lower)
9246 return nullptr;
9247
9248 ExprResult Diff = calculateNumIters(
9249 SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType, TestIsStrictOp,
9250 /*RoundToStep=*/true, Captures, InitDependOnLC, CondDependOnLC);
9251 if (!Diff.isUsable())
9252 return nullptr;
9253
9254 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9255 QualType Type = Diff.get()->getType();
9256 ASTContext &C = SemaRef.Context;
9257 bool UseVarType = VarType->hasIntegerRepresentation() &&
9258 C.getTypeSize(T: Type) > C.getTypeSize(T: VarType);
9259 if (!Type->isIntegerType() || UseVarType) {
9260 unsigned NewSize =
9261 UseVarType ? C.getTypeSize(T: VarType) : C.getTypeSize(T: Type);
9262 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9263 : Type->hasSignedIntegerRepresentation();
9264 Type = C.getIntTypeForBitwidth(DestWidth: NewSize, Signed: IsSigned);
9265 if (!SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: Type)) {
9266 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: Type,
9267 Action: AssignmentAction::Converting,
9268 /*AllowExplicit=*/true);
9269 if (!Diff.isUsable())
9270 return nullptr;
9271 }
9272 }
9273 if (LimitedType) {
9274 unsigned NewSize = (C.getTypeSize(T: Type) > 32) ? 64 : 32;
9275 if (NewSize != C.getTypeSize(T: Type)) {
9276 if (NewSize < C.getTypeSize(T: Type)) {
9277 assert(NewSize == 64 && "incorrect loop var size");
9278 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::warn_omp_loop_64_bit_var)
9279 << InitSrcRange << ConditionSrcRange;
9280 }
9281 QualType NewType = C.getIntTypeForBitwidth(
9282 DestWidth: NewSize, Signed: Type->hasSignedIntegerRepresentation() ||
9283 C.getTypeSize(T: Type) < NewSize);
9284 if (!SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: NewType)) {
9285 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: NewType,
9286 Action: AssignmentAction::Converting,
9287 /*AllowExplicit=*/true);
9288 if (!Diff.isUsable())
9289 return nullptr;
9290 }
9291 }
9292 }
9293
9294 return Diff.get();
9295}
9296
9297std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9298 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9299 // Do not build for iterators, they cannot be used in non-rectangular loop
9300 // nests.
9301 if (LCDecl->getType()->isRecordType())
9302 return std::make_pair(x: nullptr, y: nullptr);
9303 // If we subtract, the min is in the condition, otherwise the min is in the
9304 // init value.
9305 Expr *MinExpr = nullptr;
9306 Expr *MaxExpr = nullptr;
9307 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9308 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9309 bool LBNonRect =
9310 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9311 bool UBNonRect =
9312 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9313 Expr *Lower =
9314 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, Capture: LBExpr, Captures).get();
9315 Expr *Upper =
9316 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, Capture: UBExpr, Captures).get();
9317 if (!Upper || !Lower)
9318 return std::make_pair(x: nullptr, y: nullptr);
9319
9320 if (*TestIsLessOp)
9321 MinExpr = Lower;
9322 else
9323 MaxExpr = Upper;
9324
9325 // Build minimum/maximum value based on number of iterations.
9326 QualType VarType = LCDecl->getType().getNonReferenceType();
9327
9328 ExprResult Diff = calculateNumIters(
9329 SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType, TestIsStrictOp,
9330 /*RoundToStep=*/false, Captures, InitDependOnLC, CondDependOnLC);
9331
9332 if (!Diff.isUsable())
9333 return std::make_pair(x: nullptr, y: nullptr);
9334
9335 // ((Upper - Lower [- 1]) / Step) * Step
9336 // Parentheses (for dumping/debugging purposes only).
9337 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9338 if (!Diff.isUsable())
9339 return std::make_pair(x: nullptr, y: nullptr);
9340
9341 ExprResult NewStep = tryBuildCapture(SemaRef, Capture: Step, Captures, Name: ".new_step");
9342 if (!NewStep.isUsable())
9343 return std::make_pair(x: nullptr, y: nullptr);
9344 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Mul, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
9345 if (!Diff.isUsable())
9346 return std::make_pair(x: nullptr, y: nullptr);
9347
9348 // Parentheses (for dumping/debugging purposes only).
9349 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9350 if (!Diff.isUsable())
9351 return std::make_pair(x: nullptr, y: nullptr);
9352
9353 // Convert to the ptrdiff_t, if original type is pointer.
9354 if (VarType->isAnyPointerType() &&
9355 !SemaRef.Context.hasSameType(
9356 T1: Diff.get()->getType(),
9357 T2: SemaRef.Context.getUnsignedPointerDiffType())) {
9358 Diff = SemaRef.PerformImplicitConversion(
9359 From: Diff.get(), ToType: SemaRef.Context.getUnsignedPointerDiffType(),
9360 Action: AssignmentAction::Converting, /*AllowExplicit=*/true);
9361 }
9362 if (!Diff.isUsable())
9363 return std::make_pair(x: nullptr, y: nullptr);
9364
9365 if (*TestIsLessOp) {
9366 // MinExpr = Lower;
9367 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9368 Diff = SemaRef.BuildBinOp(
9369 S, OpLoc: DefaultLoc, Opc: BO_Add,
9370 LHSExpr: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Lower).get(),
9371 RHSExpr: Diff.get());
9372 if (!Diff.isUsable())
9373 return std::make_pair(x: nullptr, y: nullptr);
9374 } else {
9375 // MaxExpr = Upper;
9376 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9377 Diff = SemaRef.BuildBinOp(
9378 S, OpLoc: DefaultLoc, Opc: BO_Sub,
9379 LHSExpr: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Upper).get(),
9380 RHSExpr: Diff.get());
9381 if (!Diff.isUsable())
9382 return std::make_pair(x: nullptr, y: nullptr);
9383 }
9384
9385 // Convert to the original type.
9386 if (SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: VarType))
9387 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: VarType,
9388 Action: AssignmentAction::Converting,
9389 /*AllowExplicit=*/true);
9390 if (!Diff.isUsable())
9391 return std::make_pair(x: nullptr, y: nullptr);
9392
9393 Sema::TentativeAnalysisScope Trap(SemaRef);
9394 Diff = SemaRef.ActOnFinishFullExpr(Expr: Diff.get(), /*DiscardedValue=*/false);
9395 if (!Diff.isUsable())
9396 return std::make_pair(x: nullptr, y: nullptr);
9397
9398 if (*TestIsLessOp)
9399 MaxExpr = Diff.get();
9400 else
9401 MinExpr = Diff.get();
9402
9403 return std::make_pair(x&: MinExpr, y&: MaxExpr);
9404}
9405
9406Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9407 if (InitDependOnLC || CondDependOnLC)
9408 return Condition;
9409 return nullptr;
9410}
9411
9412Expr *OpenMPIterationSpaceChecker::buildPreCond(
9413 Scope *S, Expr *Cond,
9414 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9415 // Do not build a precondition when the condition/initialization is dependent
9416 // to prevent pessimistic early loop exit.
9417 // TODO: this can be improved by calculating min/max values but not sure that
9418 // it will be very effective.
9419 if (CondDependOnLC || InitDependOnLC)
9420 return SemaRef
9421 .PerformImplicitConversion(
9422 From: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get(),
9423 ToType: SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
9424 /*AllowExplicit=*/true)
9425 .get();
9426
9427 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9428 Sema::TentativeAnalysisScope Trap(SemaRef);
9429
9430 ExprResult NewLB = tryBuildCapture(SemaRef, Capture: LB, Captures);
9431 ExprResult NewUB = tryBuildCapture(SemaRef, Capture: UB, Captures);
9432 if (!NewLB.isUsable() || !NewUB.isUsable())
9433 return nullptr;
9434
9435 ExprResult CondExpr =
9436 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc,
9437 Opc: *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9438 : (TestIsStrictOp ? BO_GT : BO_GE),
9439 LHSExpr: NewLB.get(), RHSExpr: NewUB.get());
9440 if (CondExpr.isUsable()) {
9441 if (!SemaRef.Context.hasSameUnqualifiedType(T1: CondExpr.get()->getType(),
9442 T2: SemaRef.Context.BoolTy))
9443 CondExpr = SemaRef.PerformImplicitConversion(
9444 From: CondExpr.get(), ToType: SemaRef.Context.BoolTy,
9445 /*Action=*/AssignmentAction::Casting,
9446 /*AllowExplicit=*/true);
9447 }
9448
9449 // Otherwise use original loop condition and evaluate it in runtime.
9450 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9451}
9452
9453/// Build reference expression to the counter be used for codegen.
9454DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9455 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9456 DSAStackTy &DSA) const {
9457 auto *VD = dyn_cast<VarDecl>(Val: LCDecl);
9458 if (!VD) {
9459 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(D: LCDecl);
9460 DeclRefExpr *Ref = buildDeclRefExpr(
9461 S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(), Loc: DefaultLoc);
9462 const DSAStackTy::DSAVarData Data =
9463 DSA.getTopDSA(D: LCDecl, /*FromParent=*/false);
9464 // If the loop control decl is explicitly marked as private, do not mark it
9465 // as captured again.
9466 if (!isOpenMPPrivate(Kind: Data.CKind) || !Data.RefExpr)
9467 Captures.insert(KV: std::make_pair(x: LCRef, y&: Ref));
9468 return Ref;
9469 }
9470 return cast<DeclRefExpr>(Val: LCRef);
9471}
9472
9473Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9474 if (LCDecl && !LCDecl->isInvalidDecl()) {
9475 QualType Type = LCDecl->getType().getNonReferenceType();
9476 VarDecl *PrivateVar = buildVarDecl(
9477 SemaRef, Loc: DefaultLoc, Type, Name: LCDecl->getName(),
9478 Attrs: LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9479 OrigRef: isa<VarDecl>(Val: LCDecl)
9480 ? buildDeclRefExpr(S&: SemaRef, D: cast<VarDecl>(Val: LCDecl), Ty: Type, Loc: DefaultLoc)
9481 : nullptr);
9482 if (PrivateVar->isInvalidDecl())
9483 return nullptr;
9484 return buildDeclRefExpr(S&: SemaRef, D: PrivateVar, Ty: Type, Loc: DefaultLoc);
9485 }
9486 return nullptr;
9487}
9488
9489/// Build initialization of the counter to be used for codegen.
9490Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9491
9492/// Build step of the counter be used for codegen.
9493Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9494
9495Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9496 Scope *S, Expr *Counter,
9497 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9498 Expr *Inc, OverloadedOperatorKind OOK) {
9499 Expr *Cnt = SemaRef.DefaultLvalueConversion(E: Counter).get();
9500 if (!Cnt)
9501 return nullptr;
9502 if (Inc) {
9503 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9504 "Expected only + or - operations for depend clauses.");
9505 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9506 Cnt = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BOK, LHSExpr: Cnt, RHSExpr: Inc).get();
9507 if (!Cnt)
9508 return nullptr;
9509 }
9510 QualType VarType = LCDecl->getType().getNonReferenceType();
9511 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9512 !SemaRef.getLangOpts().CPlusPlus)
9513 return nullptr;
9514 // Upper - Lower
9515 Expr *Upper =
9516 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, Capture: LB, Captures).get();
9517 Expr *Lower =
9518 *TestIsLessOp ? tryBuildCapture(SemaRef, Capture: LB, Captures).get() : Cnt;
9519 if (!Upper || !Lower)
9520 return nullptr;
9521
9522 ExprResult Diff =
9523 calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType,
9524 /*TestIsStrictOp=*/false, /*RoundToStep=*/false,
9525 Captures, InitDependOnLC, CondDependOnLC);
9526 if (!Diff.isUsable())
9527 return nullptr;
9528
9529 return Diff.get();
9530}
9531} // namespace
9532
9533void SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc,
9534 Stmt *Init) {
9535 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9536 assert(Init && "Expected loop in canonical form.");
9537 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9538 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9539 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9540 return;
9541
9542 DSAStack->loopStart();
9543 llvm::SmallPtrSet<const Decl *, 1> EmptyDeclSet;
9544 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9545 *DSAStack, ForLoc, EmptyDeclSet,
9546 EmptyDeclSet);
9547 if (!ISC.checkAndSetInit(S: Init, /*EmitDiags=*/false)) {
9548 if (ValueDecl *D = ISC.getLoopDecl()) {
9549 auto *VD = dyn_cast<VarDecl>(Val: D);
9550 DeclRefExpr *PrivateRef = nullptr;
9551 if (!VD) {
9552 if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9553 VD = Private;
9554 } else {
9555 PrivateRef = buildCapture(S&: SemaRef, D, CaptureExpr: ISC.getLoopDeclRefExpr(),
9556 /*WithInit=*/false);
9557 VD = cast<VarDecl>(Val: PrivateRef->getDecl());
9558 }
9559 }
9560 DSAStack->addLoopControlVariable(D, Capture: VD);
9561 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9562 if (LD != D->getCanonicalDecl()) {
9563 DSAStack->resetPossibleLoopCounter();
9564 if (auto *Var = dyn_cast_or_null<VarDecl>(Val: LD))
9565 SemaRef.MarkDeclarationsReferencedInExpr(E: buildDeclRefExpr(
9566 S&: SemaRef, D: const_cast<VarDecl *>(Var),
9567 Ty: Var->getType().getNonLValueExprType(Context: getASTContext()), Loc: ForLoc,
9568 /*RefersToCapture=*/true));
9569 }
9570 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9571 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9572 // associated for-loop of a simd construct with just one associated
9573 // for-loop may be listed in a linear clause with a constant-linear-step
9574 // that is the increment of the associated for-loop. The loop iteration
9575 // variable(s) in the associated for-loop(s) of a for or parallel for
9576 // construct may be listed in a private or lastprivate clause.
9577 DSAStackTy::DSAVarData DVar =
9578 DSAStack->getTopDSA(D, /*FromParent=*/false);
9579 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9580 // is declared in the loop and it is predetermined as a private.
9581 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9582 OpenMPClauseKind PredeterminedCKind =
9583 isOpenMPSimdDirective(DKind)
9584 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9585 : OMPC_private;
9586 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9587 return getLeafConstructsOrSelf(D: DK).back() == OMPD_taskloop;
9588 };
9589 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9590 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9591 (getLangOpts().OpenMP <= 45 ||
9592 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9593 ((isOpenMPWorksharingDirective(DKind) ||
9594 IsOpenMPTaskloopDirective(DKind) ||
9595 isOpenMPDistributeDirective(DKind)) &&
9596 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9597 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9598 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9599 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
9600 Diag(Loc: Init->getBeginLoc(), DiagID: diag::err_omp_loop_var_dsa)
9601 << getOpenMPClauseNameForDiag(C: DVar.CKind)
9602 << getOpenMPDirectiveName(D: DKind, V: OMPVersion)
9603 << getOpenMPClauseNameForDiag(C: PredeterminedCKind);
9604 if (DVar.RefExpr == nullptr)
9605 DVar.CKind = PredeterminedCKind;
9606 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9607 } else if (LoopDeclRefExpr) {
9608 // Make the loop iteration variable private (for worksharing
9609 // constructs), linear (for simd directives with the only one
9610 // associated loop) or lastprivate (for simd directives with several
9611 // collapsed or ordered loops).
9612 if (DVar.CKind == OMPC_unknown)
9613 DSAStack->addDSA(D, E: LoopDeclRefExpr, A: PredeterminedCKind, PrivateCopy: PrivateRef);
9614 }
9615 }
9616 }
9617 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9618}
9619
9620namespace {
9621// Utility for OpenMP doacross clause kind
9622class OMPDoacrossKind {
9623public:
9624 bool isSource(const OMPDoacrossClause *C) {
9625 return C->getDependenceType() == OMPC_DOACROSS_source ||
9626 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9627 }
9628 bool isSink(const OMPDoacrossClause *C) {
9629 return C->getDependenceType() == OMPC_DOACROSS_sink;
9630 }
9631 bool isSinkIter(const OMPDoacrossClause *C) {
9632 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9633 }
9634};
9635} // namespace
9636/// Called on a for stmt to check and extract its iteration space
9637/// for further processing (such as collapsing).
9638static bool checkOpenMPIterationSpace(
9639 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9640 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9641 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9642 Expr *OrderedLoopCountExpr,
9643 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9644 llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
9645 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9646 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls,
9647 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars) {
9648 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9649
9650 // See the tile reinterpretation design note in ActOnOpenMPTileDirective.
9651 // If the loop carries the hint, analyze its rectangular form instead.
9652 //
9653 // Only directives that emit the per-iteration body guard (i.e. those going
9654 // through EmitOMPLoopBody's finals-conditions handling) may reinterpret the
9655 // loop; a loop transformation such as an enclosing 'tile' has nowhere to put
9656 // the overshoot guard, so for those the stored min-bounded form is analyzed
9657 // exactly as it is on a build without this hint.
9658 // OpenMP [2.9.1, Canonical Loop Form]
9659 // for (init-expr; test-expr; incr-expr) structured-block
9660 // for (range-decl: range-expr) structured-block
9661 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(Val: S))
9662 S = CanonLoop->getLoopStmt();
9663 const OMPInvariantPredicateBoundAttr *IntraTileHint =
9664 OMPLoopBasedDirective::getIntraTileHint(S);
9665 if (IntraTileHint)
9666 S = OMPLoopBasedDirective::ignoreIntraTileHint(S);
9667 Expr *TileRectCond = nullptr;
9668 Expr *TileBodyPredicate = nullptr;
9669 Expr *TileTripCount = nullptr;
9670 if (IntraTileHint && !isOpenMPLoopTransformationDirective(DKind)) {
9671 TileRectCond = IntraTileHint->getRectCond();
9672 TileBodyPredicate = IntraTileHint->getPredicate();
9673 TileTripCount = IntraTileHint->getTileSize();
9674 }
9675 auto *For = dyn_cast_or_null<ForStmt>(Val: S);
9676 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(Val: S);
9677 // Ranged for is supported only in OpenMP 5.0.
9678 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9679 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
9680 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_not_for)
9681 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9682 << getOpenMPDirectiveName(D: DKind, V: OMPVersion) << TotalNestedLoopCount
9683 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9684 if (TotalNestedLoopCount > 1) {
9685 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9686 SemaRef.Diag(Loc: DSA.getConstructLoc(),
9687 DiagID: diag::note_omp_collapse_ordered_expr)
9688 << 2 << CollapseLoopCountExpr->getSourceRange()
9689 << OrderedLoopCountExpr->getSourceRange();
9690 else if (CollapseLoopCountExpr)
9691 SemaRef.Diag(Loc: CollapseLoopCountExpr->getExprLoc(),
9692 DiagID: diag::note_omp_collapse_ordered_expr)
9693 << 0 << CollapseLoopCountExpr->getSourceRange();
9694 else if (OrderedLoopCountExpr)
9695 SemaRef.Diag(Loc: OrderedLoopCountExpr->getExprLoc(),
9696 DiagID: diag::note_omp_collapse_ordered_expr)
9697 << 1 << OrderedLoopCountExpr->getSourceRange();
9698 }
9699 return true;
9700 }
9701 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9702 "No loop body.");
9703 // Postpone analysis in dependent contexts for ranged for loops.
9704 if (CXXFor && SemaRef.CurContext->isDependentContext())
9705 return false;
9706
9707 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9708 For ? For->getForLoc() : CXXFor->getForLoc(),
9709 CollapsedLoopVarDecls,
9710 CollapsedLoopInductionVars);
9711
9712 // Check init.
9713 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9714 if (ISC.checkAndSetInit(S: Init))
9715 return true;
9716
9717 bool HasErrors = false;
9718
9719 // Condition used for iteration-space analysis: the rectangular hint when
9720 // reinterpreting an intra-tile loop, otherwise the loop's own condition.
9721 Expr *EffectiveCond =
9722 TileRectCond ? TileRectCond : (For ? For->getCond() : CXXFor->getCond());
9723
9724 // Check loop variable's type.
9725 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9726 // OpenMP [2.6, Canonical Loop Form]
9727 // Var is one of the following:
9728 // A variable of signed or unsigned integer type.
9729 // For C++, a variable of a random access iterator type.
9730 // For C, a variable of a pointer type.
9731 QualType VarType = LCDecl->getType().getNonReferenceType();
9732 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9733 !VarType->isPointerType() &&
9734 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9735 SemaRef.Diag(Loc: Init->getBeginLoc(), DiagID: diag::err_omp_loop_variable_type)
9736 << SemaRef.getLangOpts().CPlusPlus;
9737 HasErrors = true;
9738 }
9739
9740 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9741 // a Construct
9742 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9743 // parallel for construct is (are) private.
9744 // The loop iteration variable in the associated for-loop of a simd
9745 // construct with just one associated for-loop is linear with a
9746 // constant-linear-step that is the increment of the associated for-loop.
9747 // Exclude loop var from the list of variables with implicitly defined data
9748 // sharing attributes.
9749 VarsWithImplicitDSA.erase(Val: LCDecl);
9750
9751 assert((isOpenMPLoopDirective(DKind) ||
9752 isOpenMPCanonicalLoopSequenceTransformationDirective(DKind)) &&
9753 "DSA for non-loop vars");
9754
9755 // Check test-expr.
9756 HasErrors |= ISC.checkAndSetCond(S: EffectiveCond);
9757
9758 // Check incr-expr.
9759 HasErrors |= ISC.checkAndSetInc(S: For ? For->getInc() : CXXFor->getInc());
9760 }
9761
9762 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9763 return HasErrors;
9764
9765 // Build the loop's iteration space representation.
9766 //
9767 // A reinterpreted intra-tile loop takes all three of these from the hint
9768 // instead of deriving them: the precondition is trivially true (the floor
9769 // loop's own precondition already covers an empty iteration space), the trip
9770 // count is the constant tile size, and any overshoot on the remainder tile
9771 // is handled by the body guard.
9772 if (TileRectCond) {
9773 ResultIterSpaces[CurrentNestedLoopCount].PreCond =
9774 SemaRef
9775 .PerformImplicitConversion(
9776 From: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get(),
9777 ToType: SemaRef.Context.BoolTy, Action: AssignmentAction::Casting,
9778 /*AllowExplicit=*/true)
9779 .get();
9780 ResultIterSpaces[CurrentNestedLoopCount].NumIterations = TileTripCount;
9781 } else {
9782 ResultIterSpaces[CurrentNestedLoopCount].PreCond =
9783 ISC.buildPreCond(S: DSA.getCurScope(), Cond: EffectiveCond, Captures);
9784 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9785 ISC.buildNumIterations(S: DSA.getCurScope(), ResultIterSpaces,
9786 LimitedType: (isOpenMPWorksharingDirective(DKind) ||
9787 isOpenMPGenericLoopDirective(DKind) ||
9788 isOpenMPTaskLoopDirective(DKind) ||
9789 isOpenMPDistributeDirective(DKind) ||
9790 isOpenMPLoopTransformationDirective(DKind)),
9791 Captures);
9792 }
9793 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9794 ISC.buildCounterVar(Captures, DSA);
9795 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9796 ISC.buildPrivateCounterVar();
9797 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9798 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9799 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9800 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9801 ISC.getConditionSrcRange();
9802 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9803 ISC.getIncrementSrcRange();
9804 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9805 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9806 ISC.isStrictTestOp();
9807 std::tie(args&: ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9808 args&: ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9809 ISC.buildMinMaxValues(S: DSA.getCurScope(), Captures);
9810 if (TileRectCond) {
9811 // Floor is not a registered loop-control variable, so this helper is null.
9812 // Use the overshoot guard only (null when N % T == 0).
9813 assert(!ISC.buildFinalCondition(DSA.getCurScope()) &&
9814 "intra-tile floor is not a registered loop-control variable");
9815 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition = TileBodyPredicate;
9816
9817 // Re-read .floor.iv each outer trip. Match it to an outer collapsed
9818 // counter.
9819 bool FoundFloor = false;
9820 if (Expr *InitExpr = ResultIterSpaces[CurrentNestedLoopCount].CounterInit) {
9821 if (const auto *LBRef =
9822 dyn_cast<DeclRefExpr>(Val: InitExpr->IgnoreParenImpCasts())) {
9823 const Decl *FloorDecl = LBRef->getDecl()->getCanonicalDecl();
9824 for (unsigned K = 0; K < CurrentNestedLoopCount; ++K) {
9825 const auto *CV =
9826 dyn_cast_or_null<DeclRefExpr>(Val: ResultIterSpaces[K].CounterVar);
9827 if (CV && CV->getDecl()->getCanonicalDecl() == FloorDecl) {
9828 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB = true;
9829 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx = K + 1;
9830 FoundFloor = true;
9831 break;
9832 }
9833 }
9834 }
9835 }
9836 if (!FoundFloor) {
9837 // The floor this intra-tile loop starts from is not one of the
9838 // collapsed counters: it is assigned in the body of an enclosing
9839 // transformed loop, so the collapsed nest would read a stale value
9840 // instead of recomputing it per iteration. Diagnose to avoid silently
9841 // producing the wrong iteration space.
9842 SemaRef.Diag(Loc: ISC.getInitSrcRange().getBegin(),
9843 DiagID: diag::err_omp_collapse_stacked_tile)
9844 << /*Collapse=*/0;
9845 return true;
9846 }
9847 } else {
9848 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9849 ISC.buildFinalCondition(S: DSA.getCurScope());
9850 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9851 ISC.doesInitDependOnLC();
9852 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9853 ISC.doesCondDependOnLC();
9854 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9855 ISC.getLoopDependentIdx();
9856 }
9857
9858 HasErrors |=
9859 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9860 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9861 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9862 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9863 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9864 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9865 if (!HasErrors && DSA.isOrderedRegion()) {
9866 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9867 if (CurrentNestedLoopCount <
9868 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9869 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9870 NumLoop: CurrentNestedLoopCount,
9871 NumIterations: ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9872 DSA.getOrderedRegionParam().second->setLoopCounter(
9873 NumLoop: CurrentNestedLoopCount,
9874 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9875 }
9876 }
9877 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9878 auto *DependC = dyn_cast<OMPDependClause>(Val: Pair.first);
9879 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Val: Pair.first);
9880 unsigned NumLoops =
9881 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9882 if (CurrentNestedLoopCount >= NumLoops) {
9883 // Erroneous case - clause has some problems.
9884 continue;
9885 }
9886 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9887 Pair.second.size() <= CurrentNestedLoopCount) {
9888 // Erroneous case - clause has some problems.
9889 DependC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: nullptr);
9890 continue;
9891 }
9892 OMPDoacrossKind ODK;
9893 if (DoacrossC && ODK.isSink(C: DoacrossC) &&
9894 Pair.second.size() <= CurrentNestedLoopCount) {
9895 // Erroneous case - clause has some problems.
9896 DoacrossC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: nullptr);
9897 continue;
9898 }
9899 Expr *CntValue;
9900 SourceLocation DepLoc =
9901 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9902 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9903 (DoacrossC && ODK.isSource(C: DoacrossC)))
9904 CntValue = ISC.buildOrderedLoopData(
9905 S: DSA.getCurScope(),
9906 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9907 Loc: DepLoc);
9908 else if (DoacrossC && ODK.isSinkIter(C: DoacrossC)) {
9909 Expr *Cnt = SemaRef
9910 .DefaultLvalueConversion(
9911 E: ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9912 .get();
9913 if (!Cnt)
9914 continue;
9915 // build CounterVar - 1
9916 Expr *Inc =
9917 SemaRef.ActOnIntegerConstant(Loc: DoacrossC->getColonLoc(), /*Val=*/1)
9918 .get();
9919 CntValue = ISC.buildOrderedLoopData(
9920 S: DSA.getCurScope(),
9921 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9922 Loc: DepLoc, Inc, OOK: clang::OO_Minus);
9923 } else
9924 CntValue = ISC.buildOrderedLoopData(
9925 S: DSA.getCurScope(),
9926 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9927 Loc: DepLoc, Inc: Pair.second[CurrentNestedLoopCount].first,
9928 OOK: Pair.second[CurrentNestedLoopCount].second);
9929 if (DependC)
9930 DependC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: CntValue);
9931 else
9932 DoacrossC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: CntValue);
9933 }
9934 }
9935 // Record the loop induction variable for nested loop reuse checking.
9936 if (CurrentNestedLoopCount < NestedLoopCount && !HasErrors) {
9937 if (const ValueDecl *LCDecl = ISC.getLoopDecl())
9938 CollapsedLoopInductionVars.insert(Ptr: LCDecl->getCanonicalDecl());
9939 }
9940 return HasErrors;
9941}
9942
9943/// Build 'VarRef = Start.
9944static ExprResult
9945buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9946 ExprResult Start, bool IsNonRectangularLB,
9947 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9948 // Build 'VarRef = Start.
9949 ExprResult NewStart = IsNonRectangularLB
9950 ? Start.get()
9951 : tryBuildCapture(SemaRef, Capture: Start.get(), Captures);
9952 if (!NewStart.isUsable())
9953 return ExprError();
9954 if (!SemaRef.Context.hasSameType(T1: NewStart.get()->getType(),
9955 T2: VarRef.get()->getType())) {
9956 NewStart = SemaRef.PerformImplicitConversion(
9957 From: NewStart.get(), ToType: VarRef.get()->getType(), Action: AssignmentAction::Converting,
9958 /*AllowExplicit=*/true);
9959 if (!NewStart.isUsable())
9960 return ExprError();
9961 }
9962
9963 ExprResult Init =
9964 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: NewStart.get());
9965 return Init;
9966}
9967
9968/// Build 'VarRef = Start + Iter * Step'.
9969static ExprResult buildCounterUpdate(
9970 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9971 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9972 bool IsNonRectangularLB,
9973 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9974 // Add parentheses (for debugging purposes only).
9975 Iter = SemaRef.ActOnParenExpr(L: Loc, R: Loc, E: Iter.get());
9976 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9977 !Step.isUsable())
9978 return ExprError();
9979
9980 ExprResult NewStep = Step;
9981 if (Captures)
9982 NewStep = tryBuildCapture(SemaRef, Capture: Step.get(), Captures&: *Captures);
9983 if (NewStep.isInvalid())
9984 return ExprError();
9985 ExprResult Update =
9986 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Mul, LHSExpr: Iter.get(), RHSExpr: NewStep.get());
9987 if (!Update.isUsable())
9988 return ExprError();
9989
9990 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9991 // 'VarRef = Start (+|-) Iter * Step'.
9992 if (!Start.isUsable())
9993 return ExprError();
9994 ExprResult NewStart = SemaRef.ActOnParenExpr(L: Loc, R: Loc, E: Start.get());
9995 if (!NewStart.isUsable())
9996 return ExprError();
9997 if (Captures && !IsNonRectangularLB)
9998 NewStart = tryBuildCapture(SemaRef, Capture: Start.get(), Captures&: *Captures);
9999 if (NewStart.isInvalid())
10000 return ExprError();
10001
10002 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
10003 ExprResult SavedUpdate = Update;
10004 ExprResult UpdateVal;
10005 if (VarRef.get()->getType()->isOverloadableType() ||
10006 NewStart.get()->getType()->isOverloadableType() ||
10007 Update.get()->getType()->isOverloadableType()) {
10008 Sema::TentativeAnalysisScope Trap(SemaRef);
10009
10010 Update =
10011 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: NewStart.get());
10012 if (Update.isUsable()) {
10013 UpdateVal =
10014 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: Subtract ? BO_SubAssign : BO_AddAssign,
10015 LHSExpr: VarRef.get(), RHSExpr: SavedUpdate.get());
10016 if (UpdateVal.isUsable()) {
10017 Update = SemaRef.CreateBuiltinBinOp(OpLoc: Loc, Opc: BO_Comma, LHSExpr: Update.get(),
10018 RHSExpr: UpdateVal.get());
10019 }
10020 }
10021 }
10022
10023 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
10024 if (!Update.isUsable() || !UpdateVal.isUsable()) {
10025 Update = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: Subtract ? BO_Sub : BO_Add,
10026 LHSExpr: NewStart.get(), RHSExpr: SavedUpdate.get());
10027 if (!Update.isUsable())
10028 return ExprError();
10029
10030 if (!SemaRef.Context.hasSameType(T1: Update.get()->getType(),
10031 T2: VarRef.get()->getType())) {
10032 Update = SemaRef.PerformImplicitConversion(
10033 From: Update.get(), ToType: VarRef.get()->getType(), Action: AssignmentAction::Converting,
10034 /*AllowExplicit=*/true);
10035 if (!Update.isUsable())
10036 return ExprError();
10037 }
10038
10039 Update = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: Update.get());
10040 }
10041 return Update;
10042}
10043
10044/// Convert integer expression \a E to make it have at least \a Bits
10045/// bits.
10046static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
10047 if (E == nullptr)
10048 return ExprError();
10049 ASTContext &C = SemaRef.Context;
10050 QualType OldType = E->getType();
10051 unsigned HasBits = C.getTypeSize(T: OldType);
10052 if (HasBits >= Bits)
10053 return ExprResult(E);
10054 // OK to convert to signed, because new type has more bits than old.
10055 QualType NewType = C.getIntTypeForBitwidth(DestWidth: Bits, /*Signed=*/true);
10056 return SemaRef.PerformImplicitConversion(
10057 From: E, ToType: NewType, Action: AssignmentAction::Converting, /*AllowExplicit=*/true);
10058}
10059
10060/// Check if the given expression \a E is a constant integer that fits
10061/// into \a Bits bits.
10062static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
10063 if (E == nullptr)
10064 return false;
10065 if (std::optional<llvm::APSInt> Result =
10066 E->getIntegerConstantExpr(Ctx: SemaRef.Context))
10067 return Signed ? Result->isSignedIntN(N: Bits) : Result->isIntN(N: Bits);
10068 return false;
10069}
10070
10071/// Build preinits statement for the given declarations.
10072static Stmt *buildPreInits(ASTContext &Context,
10073 MutableArrayRef<Decl *> PreInits) {
10074 if (!PreInits.empty()) {
10075 return new (Context) DeclStmt(
10076 DeclGroupRef::Create(C&: Context, Decls: PreInits.begin(), NumDecls: PreInits.size()),
10077 SourceLocation(), SourceLocation());
10078 }
10079 return nullptr;
10080}
10081
10082/// Append the \p Item or the content of a CompoundStmt to the list \p
10083/// TargetList.
10084///
10085/// A CompoundStmt is used as container in case multiple statements need to be
10086/// stored in lieu of using an explicit list. Flattening is necessary because
10087/// contained DeclStmts need to be visible after the execution of the list. Used
10088/// for OpenMP pre-init declarations/statements.
10089static void appendFlattenedStmtList(SmallVectorImpl<Stmt *> &TargetList,
10090 Stmt *Item) {
10091 // nullptr represents an empty list.
10092 if (!Item)
10093 return;
10094
10095 if (auto *CS = dyn_cast<CompoundStmt>(Val: Item))
10096 llvm::append_range(C&: TargetList, R: CS->body());
10097 else
10098 TargetList.push_back(Elt: Item);
10099}
10100
10101/// Build preinits statement for the given declarations.
10102static Stmt *
10103buildPreInits(ASTContext &Context,
10104 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
10105 if (!Captures.empty()) {
10106 SmallVector<Decl *, 16> PreInits;
10107 for (const auto &Pair : Captures)
10108 PreInits.push_back(Elt: Pair.second->getDecl());
10109 return buildPreInits(Context, PreInits);
10110 }
10111 return nullptr;
10112}
10113
10114/// Build pre-init statement for the given statements.
10115static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
10116 if (PreInits.empty())
10117 return nullptr;
10118
10119 SmallVector<Stmt *> Stmts;
10120 for (Stmt *S : PreInits)
10121 appendFlattenedStmtList(TargetList&: Stmts, Item: S);
10122 return CompoundStmt::Create(C: Context, Stmts: PreInits, FPFeatures: FPOptionsOverride(), LB: {}, RB: {});
10123}
10124
10125/// Build postupdate expression for the given list of postupdates expressions.
10126static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
10127 Expr *PostUpdate = nullptr;
10128 if (!PostUpdates.empty()) {
10129 for (Expr *E : PostUpdates) {
10130 Expr *ConvE = S.BuildCStyleCastExpr(
10131 LParenLoc: E->getExprLoc(),
10132 Ty: S.Context.getTrivialTypeSourceInfo(T: S.Context.VoidTy),
10133 RParenLoc: E->getExprLoc(), Op: E)
10134 .get();
10135 PostUpdate = PostUpdate
10136 ? S.CreateBuiltinBinOp(OpLoc: ConvE->getExprLoc(), Opc: BO_Comma,
10137 LHSExpr: PostUpdate, RHSExpr: ConvE)
10138 .get()
10139 : ConvE;
10140 }
10141 }
10142 return PostUpdate;
10143}
10144
10145/// Look for variables declared in the body parts of a for-loop nest. Used
10146/// for verifying loop nest structure before performing a loop collapse
10147/// operation.
10148class ForVarDeclFinder : public DynamicRecursiveASTVisitor {
10149 int NestingDepth = 0;
10150 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
10151
10152public:
10153 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
10154 : VarDecls(VD) {}
10155
10156 bool VisitForStmt(ForStmt *F) override {
10157 ++NestingDepth;
10158 TraverseStmt(S: F->getBody());
10159 --NestingDepth;
10160 return false;
10161 }
10162
10163 bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override {
10164 ++NestingDepth;
10165 TraverseStmt(S: RF->getBody());
10166 --NestingDepth;
10167 return false;
10168 }
10169
10170 bool VisitVarDecl(VarDecl *D) override {
10171 Decl *C = D->getCanonicalDecl();
10172 if (NestingDepth > 0)
10173 VarDecls.insert(Ptr: C);
10174 return true;
10175 }
10176};
10177
10178/// Called on a for stmt to check itself and nested loops (if any).
10179/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
10180/// number of collapsed loops otherwise.
10181static unsigned
10182checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
10183 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
10184 DSAStackTy &DSA,
10185 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
10186 OMPLoopBasedDirective::HelperExprs &Built) {
10187 // If either of the loop expressions exist and contain errors, we bail out
10188 // early because diagnostics have already been emitted and we can't reliably
10189 // check more about the loop.
10190 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
10191 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
10192 return 0;
10193
10194 unsigned NestedLoopCount = 1;
10195 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
10196 !isOpenMPLoopTransformationDirective(DKind);
10197 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
10198 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopInductionVars;
10199
10200 if (CollapseLoopCountExpr) {
10201 // Found 'collapse' clause - calculate collapse number.
10202 Expr::EvalResult Result;
10203 if (!CollapseLoopCountExpr->isValueDependent() &&
10204 CollapseLoopCountExpr->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext())) {
10205 NestedLoopCount = Result.Val.getInt().getLimitedValue();
10206
10207 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
10208 FVDF.TraverseStmt(S: AStmt);
10209 } else {
10210 Built.clear(/*Size=*/1);
10211 return 1;
10212 }
10213 }
10214 unsigned OrderedLoopCount = 1;
10215 if (OrderedLoopCountExpr) {
10216 // Found 'ordered' clause - calculate collapse number.
10217 Expr::EvalResult EVResult;
10218 if (!OrderedLoopCountExpr->isValueDependent() &&
10219 OrderedLoopCountExpr->EvaluateAsInt(Result&: EVResult,
10220 Ctx: SemaRef.getASTContext())) {
10221 llvm::APSInt Result = EVResult.Val.getInt();
10222 if (Result.getLimitedValue() < NestedLoopCount) {
10223 SemaRef.Diag(Loc: OrderedLoopCountExpr->getExprLoc(),
10224 DiagID: diag::err_omp_wrong_ordered_loop_count)
10225 << OrderedLoopCountExpr->getSourceRange();
10226 SemaRef.Diag(Loc: CollapseLoopCountExpr->getExprLoc(),
10227 DiagID: diag::note_collapse_loop_count)
10228 << CollapseLoopCountExpr->getSourceRange();
10229 }
10230 OrderedLoopCount = Result.getLimitedValue();
10231 } else {
10232 Built.clear(/*Size=*/1);
10233 return 1;
10234 }
10235 }
10236 // This is helper routine for loop directives (e.g., 'for', 'simd',
10237 // 'for simd', etc.).
10238 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
10239 unsigned NumLoops = std::max(a: OrderedLoopCount, b: NestedLoopCount);
10240 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
10241 if (!OMPLoopBasedDirective::doForAllLoops(
10242 CurStmt: AStmt->IgnoreContainers(
10243 IgnoreCaptured: !isOpenMPCanonicalLoopNestTransformationDirective(DKind)),
10244 TryImperfectlyNestedLoops: SupportsNonPerfectlyNested, NumLoops,
10245 Callback: [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
10246 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
10247 &IterSpaces, &Captures, &CollapsedLoopVarDecls,
10248 &CollapsedLoopInductionVars](unsigned Cnt, Stmt *Loop,
10249 Stmt *HintWrapper) {
10250 Stmt *CurStmt = HintWrapper ? HintWrapper : Loop;
10251 if (checkOpenMPIterationSpace(
10252 DKind, S: CurStmt, SemaRef, DSA, CurrentNestedLoopCount: Cnt, NestedLoopCount,
10253 TotalNestedLoopCount: NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
10254 VarsWithImplicitDSA, ResultIterSpaces: IterSpaces, Captures,
10255 CollapsedLoopVarDecls, CollapsedLoopInductionVars))
10256 return true;
10257 if (Cnt > 0 && Cnt >= NestedLoopCount &&
10258 IterSpaces[Cnt].CounterVar) {
10259 // Handle initialization of captured loop iterator variables.
10260 auto *DRE = cast<DeclRefExpr>(Val: IterSpaces[Cnt].CounterVar);
10261 if (isa<OMPCapturedExprDecl>(Val: DRE->getDecl())) {
10262 Captures[DRE] = DRE;
10263 }
10264 }
10265 return false;
10266 },
10267 OnTransformationCallback: [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
10268 Stmt *DependentPreInits = Transform->getPreInits();
10269 if (!DependentPreInits)
10270 return;
10271
10272 // Search for pre-init declared variables that need to be captured
10273 // to be referenceable inside the directive.
10274 SmallVector<Stmt *> Constituents;
10275 appendFlattenedStmtList(TargetList&: Constituents, Item: DependentPreInits);
10276 for (Stmt *S : Constituents) {
10277 if (auto *DC = dyn_cast<DeclStmt>(Val: S)) {
10278 for (Decl *C : DC->decls()) {
10279 auto *D = cast<VarDecl>(Val: C);
10280 DeclRefExpr *Ref = buildDeclRefExpr(
10281 S&: SemaRef, D, Ty: D->getType().getNonReferenceType(),
10282 Loc: cast<OMPExecutableDirective>(Val: Transform->getDirective())
10283 ->getBeginLoc());
10284 Captures[Ref] = Ref;
10285 }
10286 }
10287 }
10288 }))
10289 return 0;
10290
10291 Built.clear(/*size=*/Size: NestedLoopCount);
10292
10293 if (SemaRef.CurContext->isDependentContext())
10294 return NestedLoopCount;
10295
10296 // An example of what is generated for the following code:
10297 //
10298 // #pragma omp simd collapse(2) ordered(2)
10299 // for (i = 0; i < NI; ++i)
10300 // for (k = 0; k < NK; ++k)
10301 // for (j = J0; j < NJ; j+=2) {
10302 // <loop body>
10303 // }
10304 //
10305 // We generate the code below.
10306 // Note: the loop body may be outlined in CodeGen.
10307 // Note: some counters may be C++ classes, operator- is used to find number of
10308 // iterations and operator+= to calculate counter value.
10309 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
10310 // or i64 is currently supported).
10311 //
10312 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
10313 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
10314 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
10315 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
10316 // // similar updates for vars in clauses (e.g. 'linear')
10317 // <loop body (using local i and j)>
10318 // }
10319 // i = NI; // assign final values of counters
10320 // j = NJ;
10321 //
10322
10323 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
10324 // the iteration counts of the collapsed for loops.
10325 // Precondition tests if there is at least one iteration (all conditions are
10326 // true).
10327 auto PreCond = ExprResult(IterSpaces[0].PreCond);
10328 Expr *N0 = IterSpaces[0].NumIterations;
10329 ExprResult LastIteration32 = widenIterationCount(
10330 /*Bits=*/32,
10331 E: SemaRef
10332 .PerformImplicitConversion(From: N0->IgnoreImpCasts(), ToType: N0->getType(),
10333 Action: AssignmentAction::Converting,
10334 /*AllowExplicit=*/true)
10335 .get(),
10336 SemaRef);
10337 ExprResult LastIteration64 = widenIterationCount(
10338 /*Bits=*/64,
10339 E: SemaRef
10340 .PerformImplicitConversion(From: N0->IgnoreImpCasts(), ToType: N0->getType(),
10341 Action: AssignmentAction::Converting,
10342 /*AllowExplicit=*/true)
10343 .get(),
10344 SemaRef);
10345
10346 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
10347 return NestedLoopCount;
10348
10349 ASTContext &C = SemaRef.Context;
10350 bool AllCountsNeedLessThan32Bits = C.getTypeSize(T: N0->getType()) < 32;
10351
10352 Scope *CurScope = DSA.getCurScope();
10353 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10354 if (PreCond.isUsable()) {
10355 PreCond =
10356 SemaRef.BuildBinOp(S: CurScope, OpLoc: PreCond.get()->getExprLoc(), Opc: BO_LAnd,
10357 LHSExpr: PreCond.get(), RHSExpr: IterSpaces[Cnt].PreCond);
10358 }
10359 Expr *N = IterSpaces[Cnt].NumIterations;
10360 SourceLocation Loc = N->getExprLoc();
10361 AllCountsNeedLessThan32Bits &= C.getTypeSize(T: N->getType()) < 32;
10362 if (LastIteration32.isUsable())
10363 LastIteration32 = SemaRef.BuildBinOp(
10364 S: CurScope, OpLoc: Loc, Opc: BO_Mul, LHSExpr: LastIteration32.get(),
10365 RHSExpr: SemaRef
10366 .PerformImplicitConversion(From: N->IgnoreImpCasts(), ToType: N->getType(),
10367 Action: AssignmentAction::Converting,
10368 /*AllowExplicit=*/true)
10369 .get());
10370 if (LastIteration64.isUsable())
10371 LastIteration64 = SemaRef.BuildBinOp(
10372 S: CurScope, OpLoc: Loc, Opc: BO_Mul, LHSExpr: LastIteration64.get(),
10373 RHSExpr: SemaRef
10374 .PerformImplicitConversion(From: N->IgnoreImpCasts(), ToType: N->getType(),
10375 Action: AssignmentAction::Converting,
10376 /*AllowExplicit=*/true)
10377 .get());
10378 }
10379
10380 // Choose either the 32-bit or 64-bit version.
10381 ExprResult LastIteration = LastIteration64;
10382 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
10383 (LastIteration32.isUsable() &&
10384 C.getTypeSize(T: LastIteration32.get()->getType()) == 32 &&
10385 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10386 fitsInto(
10387 /*Bits=*/32,
10388 Signed: LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
10389 E: LastIteration64.get(), SemaRef))))
10390 LastIteration = LastIteration32;
10391 QualType VType = LastIteration.get()->getType();
10392 QualType RealVType = VType;
10393 QualType StrideVType = VType;
10394 if (isOpenMPTaskLoopDirective(DKind)) {
10395 VType =
10396 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
10397 StrideVType =
10398 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
10399 }
10400
10401 if (!LastIteration.isUsable())
10402 return 0;
10403
10404 // Save the number of iterations.
10405 ExprResult NumIterations = LastIteration;
10406 {
10407 LastIteration = SemaRef.BuildBinOp(
10408 S: CurScope, OpLoc: LastIteration.get()->getExprLoc(), Opc: BO_Sub,
10409 LHSExpr: LastIteration.get(),
10410 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
10411 if (!LastIteration.isUsable())
10412 return 0;
10413 }
10414
10415 // Calculate the last iteration number beforehand instead of doing this on
10416 // each iteration. Do not do this if the number of iterations may be kfold-ed.
10417 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(Ctx: SemaRef.Context);
10418 ExprResult CalcLastIteration;
10419 if (!IsConstant) {
10420 ExprResult SaveRef =
10421 tryBuildCapture(SemaRef, Capture: LastIteration.get(), Captures);
10422 LastIteration = SaveRef;
10423
10424 // Prepare SaveRef + 1.
10425 NumIterations = SemaRef.BuildBinOp(
10426 S: CurScope, OpLoc: SaveRef.get()->getExprLoc(), Opc: BO_Add, LHSExpr: SaveRef.get(),
10427 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
10428 if (!NumIterations.isUsable())
10429 return 0;
10430 }
10431
10432 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
10433
10434 // Build variables passed into runtime, necessary for worksharing directives.
10435 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10436 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
10437 isOpenMPDistributeDirective(DKind) ||
10438 isOpenMPGenericLoopDirective(DKind) ||
10439 isOpenMPLoopTransformationDirective(DKind)) {
10440 // Lower bound variable, initialized with zero.
10441 VarDecl *LBDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.lb");
10442 LB = buildDeclRefExpr(S&: SemaRef, D: LBDecl, Ty: VType, Loc: InitLoc);
10443 SemaRef.AddInitializerToDecl(dcl: LBDecl,
10444 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
10445 /*DirectInit=*/false);
10446
10447 // Upper bound variable, initialized with last iteration number.
10448 VarDecl *UBDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.ub");
10449 UB = buildDeclRefExpr(S&: SemaRef, D: UBDecl, Ty: VType, Loc: InitLoc);
10450 SemaRef.AddInitializerToDecl(dcl: UBDecl, init: LastIteration.get(),
10451 /*DirectInit=*/false);
10452
10453 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
10454 // This will be used to implement clause 'lastprivate'.
10455 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(DestWidth: 32, Signed: true);
10456 VarDecl *ILDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: Int32Ty, Name: ".omp.is_last");
10457 IL = buildDeclRefExpr(S&: SemaRef, D: ILDecl, Ty: Int32Ty, Loc: InitLoc);
10458 SemaRef.AddInitializerToDecl(dcl: ILDecl,
10459 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
10460 /*DirectInit=*/false);
10461
10462 // Stride variable returned by runtime (we initialize it to 1 by default).
10463 VarDecl *STDecl =
10464 buildVarDecl(SemaRef, Loc: InitLoc, Type: StrideVType, Name: ".omp.stride");
10465 ST = buildDeclRefExpr(S&: SemaRef, D: STDecl, Ty: StrideVType, Loc: InitLoc);
10466 SemaRef.AddInitializerToDecl(dcl: STDecl,
10467 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 1).get(),
10468 /*DirectInit=*/false);
10469
10470 // Build expression: UB = min(UB, LastIteration)
10471 // It is necessary for CodeGen of directives with static scheduling.
10472 ExprResult IsUBGreater = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_GT,
10473 LHSExpr: UB.get(), RHSExpr: LastIteration.get());
10474 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10475 QuestionLoc: LastIteration.get()->getExprLoc(), ColonLoc: InitLoc, CondExpr: IsUBGreater.get(),
10476 LHSExpr: LastIteration.get(), RHSExpr: UB.get());
10477 EUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: UB.get(),
10478 RHSExpr: CondOp.get());
10479 EUB = SemaRef.ActOnFinishFullExpr(Expr: EUB.get(), /*DiscardedValue=*/false);
10480
10481 // If we have a combined directive that combines 'distribute', 'for' or
10482 // 'simd' we need to be able to access the bounds of the schedule of the
10483 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10484 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10485 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10486 // Lower bound variable, initialized with zero.
10487 VarDecl *CombLBDecl =
10488 buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.comb.lb");
10489 CombLB = buildDeclRefExpr(S&: SemaRef, D: CombLBDecl, Ty: VType, Loc: InitLoc);
10490 SemaRef.AddInitializerToDecl(
10491 dcl: CombLBDecl, init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
10492 /*DirectInit=*/false);
10493
10494 // Upper bound variable, initialized with last iteration number.
10495 VarDecl *CombUBDecl =
10496 buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.comb.ub");
10497 CombUB = buildDeclRefExpr(S&: SemaRef, D: CombUBDecl, Ty: VType, Loc: InitLoc);
10498 SemaRef.AddInitializerToDecl(dcl: CombUBDecl, init: LastIteration.get(),
10499 /*DirectInit=*/false);
10500
10501 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10502 S: CurScope, OpLoc: InitLoc, Opc: BO_GT, LHSExpr: CombUB.get(), RHSExpr: LastIteration.get());
10503 ExprResult CombCondOp =
10504 SemaRef.ActOnConditionalOp(QuestionLoc: InitLoc, ColonLoc: InitLoc, CondExpr: CombIsUBGreater.get(),
10505 LHSExpr: LastIteration.get(), RHSExpr: CombUB.get());
10506 CombEUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: CombUB.get(),
10507 RHSExpr: CombCondOp.get());
10508 CombEUB =
10509 SemaRef.ActOnFinishFullExpr(Expr: CombEUB.get(), /*DiscardedValue=*/false);
10510
10511 const CapturedDecl *CD = cast<CapturedStmt>(Val: AStmt)->getCapturedDecl();
10512 // We expect to have at least 2 more parameters than the 'parallel'
10513 // directive does - the lower and upper bounds of the previous schedule.
10514 assert(CD->getNumParams() >= 4 &&
10515 "Unexpected number of parameters in loop combined directive");
10516
10517 // Set the proper type for the bounds given what we learned from the
10518 // enclosed loops.
10519 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/i: 2);
10520 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/i: 3);
10521
10522 // Previous lower and upper bounds are obtained from the region
10523 // parameters.
10524 PrevLB =
10525 buildDeclRefExpr(S&: SemaRef, D: PrevLBDecl, Ty: PrevLBDecl->getType(), Loc: InitLoc);
10526 PrevUB =
10527 buildDeclRefExpr(S&: SemaRef, D: PrevUBDecl, Ty: PrevUBDecl->getType(), Loc: InitLoc);
10528 }
10529 }
10530
10531 // Build the iteration variable and its initialization before loop.
10532 ExprResult IV;
10533 ExprResult Init, CombInit;
10534 {
10535 VarDecl *IVDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: RealVType, Name: ".omp.iv");
10536 IV = buildDeclRefExpr(S&: SemaRef, D: IVDecl, Ty: RealVType, Loc: InitLoc);
10537 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10538 isOpenMPGenericLoopDirective(DKind) ||
10539 isOpenMPTaskLoopDirective(DKind) ||
10540 isOpenMPDistributeDirective(DKind) ||
10541 isOpenMPLoopTransformationDirective(DKind))
10542 ? LB.get()
10543 : SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 0).get();
10544 Init = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: RHS);
10545 Init = SemaRef.ActOnFinishFullExpr(Expr: Init.get(), /*DiscardedValue=*/false);
10546
10547 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10548 Expr *CombRHS =
10549 (isOpenMPWorksharingDirective(DKind) ||
10550 isOpenMPGenericLoopDirective(DKind) ||
10551 isOpenMPTaskLoopDirective(DKind) ||
10552 isOpenMPDistributeDirective(DKind))
10553 ? CombLB.get()
10554 : SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 0).get();
10555 CombInit =
10556 SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: CombRHS);
10557 CombInit =
10558 SemaRef.ActOnFinishFullExpr(Expr: CombInit.get(), /*DiscardedValue=*/false);
10559 }
10560 }
10561
10562 bool UseStrictCompare =
10563 RealVType->hasUnsignedIntegerRepresentation() &&
10564 llvm::all_of(Range&: IterSpaces, P: [](const LoopIterationSpace &LIS) {
10565 return LIS.IsStrictCompare;
10566 });
10567 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10568 // unsigned IV)) for worksharing loops.
10569 SourceLocation CondLoc = AStmt->getBeginLoc();
10570 Expr *BoundUB = UB.get();
10571 if (UseStrictCompare) {
10572 BoundUB =
10573 SemaRef
10574 .BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundUB,
10575 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10576 .get();
10577 BoundUB =
10578 SemaRef.ActOnFinishFullExpr(Expr: BoundUB, /*DiscardedValue=*/false).get();
10579 }
10580 ExprResult Cond =
10581 (isOpenMPWorksharingDirective(DKind) ||
10582 isOpenMPGenericLoopDirective(DKind) ||
10583 isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
10584 isOpenMPLoopTransformationDirective(DKind))
10585 ? SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc,
10586 Opc: UseStrictCompare ? BO_LT : BO_LE, LHSExpr: IV.get(),
10587 RHSExpr: BoundUB)
10588 : SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LT, LHSExpr: IV.get(),
10589 RHSExpr: NumIterations.get());
10590 ExprResult CombDistCond;
10591 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10592 CombDistCond = SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LT, LHSExpr: IV.get(),
10593 RHSExpr: NumIterations.get());
10594 }
10595
10596 ExprResult CombCond;
10597 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10598 Expr *BoundCombUB = CombUB.get();
10599 if (UseStrictCompare) {
10600 BoundCombUB =
10601 SemaRef
10602 .BuildBinOp(
10603 S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundCombUB,
10604 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10605 .get();
10606 BoundCombUB =
10607 SemaRef.ActOnFinishFullExpr(Expr: BoundCombUB, /*DiscardedValue=*/false)
10608 .get();
10609 }
10610 CombCond =
10611 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE,
10612 LHSExpr: IV.get(), RHSExpr: BoundCombUB);
10613 }
10614 // Loop increment (IV = IV + 1)
10615 SourceLocation IncLoc = AStmt->getBeginLoc();
10616 ExprResult Inc =
10617 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: IV.get(),
10618 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: IncLoc, Val: 1).get());
10619 if (!Inc.isUsable())
10620 return 0;
10621 Inc = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: Inc.get());
10622 Inc = SemaRef.ActOnFinishFullExpr(Expr: Inc.get(), /*DiscardedValue=*/false);
10623 if (!Inc.isUsable())
10624 return 0;
10625
10626 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10627 // Used for directives with static scheduling.
10628 // In combined construct, add combined version that use CombLB and CombUB
10629 // base variables for the update
10630 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10631 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
10632 isOpenMPGenericLoopDirective(DKind) ||
10633 isOpenMPDistributeDirective(DKind) ||
10634 isOpenMPLoopTransformationDirective(DKind)) {
10635 // LB + ST
10636 NextLB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: LB.get(), RHSExpr: ST.get());
10637 if (!NextLB.isUsable())
10638 return 0;
10639 // LB = LB + ST
10640 NextLB =
10641 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: LB.get(), RHSExpr: NextLB.get());
10642 NextLB =
10643 SemaRef.ActOnFinishFullExpr(Expr: NextLB.get(), /*DiscardedValue=*/false);
10644 if (!NextLB.isUsable())
10645 return 0;
10646 // UB + ST
10647 NextUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: UB.get(), RHSExpr: ST.get());
10648 if (!NextUB.isUsable())
10649 return 0;
10650 // UB = UB + ST
10651 NextUB =
10652 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: UB.get(), RHSExpr: NextUB.get());
10653 NextUB =
10654 SemaRef.ActOnFinishFullExpr(Expr: NextUB.get(), /*DiscardedValue=*/false);
10655 if (!NextUB.isUsable())
10656 return 0;
10657 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10658 CombNextLB =
10659 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: CombLB.get(), RHSExpr: ST.get());
10660 if (!NextLB.isUsable())
10661 return 0;
10662 // LB = LB + ST
10663 CombNextLB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: CombLB.get(),
10664 RHSExpr: CombNextLB.get());
10665 CombNextLB = SemaRef.ActOnFinishFullExpr(Expr: CombNextLB.get(),
10666 /*DiscardedValue=*/false);
10667 if (!CombNextLB.isUsable())
10668 return 0;
10669 // UB + ST
10670 CombNextUB =
10671 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: CombUB.get(), RHSExpr: ST.get());
10672 if (!CombNextUB.isUsable())
10673 return 0;
10674 // UB = UB + ST
10675 CombNextUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: CombUB.get(),
10676 RHSExpr: CombNextUB.get());
10677 CombNextUB = SemaRef.ActOnFinishFullExpr(Expr: CombNextUB.get(),
10678 /*DiscardedValue=*/false);
10679 if (!CombNextUB.isUsable())
10680 return 0;
10681 }
10682 }
10683
10684 // Create increment expression for distribute loop when combined in a same
10685 // directive with for as IV = IV + ST; ensure upper bound expression based
10686 // on PrevUB instead of NumIterations - used to implement 'for' when found
10687 // in combination with 'distribute', like in 'distribute parallel for'
10688 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10689 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10690 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10691 DistCond = SemaRef.BuildBinOp(
10692 S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE, LHSExpr: IV.get(), RHSExpr: BoundUB);
10693 assert(DistCond.isUsable() && "distribute cond expr was not built");
10694
10695 DistInc =
10696 SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Add, LHSExpr: IV.get(), RHSExpr: ST.get());
10697 assert(DistInc.isUsable() && "distribute inc expr was not built");
10698 DistInc = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Assign, LHSExpr: IV.get(),
10699 RHSExpr: DistInc.get());
10700 DistInc =
10701 SemaRef.ActOnFinishFullExpr(Expr: DistInc.get(), /*DiscardedValue=*/false);
10702 assert(DistInc.isUsable() && "distribute inc expr was not built");
10703
10704 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10705 // construct
10706 ExprResult NewPrevUB = PrevUB;
10707 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10708 if (!SemaRef.Context.hasSameType(T1: UB.get()->getType(),
10709 T2: PrevUB.get()->getType())) {
10710 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10711 LParenLoc: DistEUBLoc,
10712 Ty: SemaRef.Context.getTrivialTypeSourceInfo(T: UB.get()->getType()),
10713 RParenLoc: DistEUBLoc, Op: NewPrevUB.get());
10714 if (!NewPrevUB.isUsable())
10715 return 0;
10716 }
10717 ExprResult IsUBGreater = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistEUBLoc, Opc: BO_GT,
10718 LHSExpr: UB.get(), RHSExpr: NewPrevUB.get());
10719 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10720 QuestionLoc: DistEUBLoc, ColonLoc: DistEUBLoc, CondExpr: IsUBGreater.get(), LHSExpr: NewPrevUB.get(), RHSExpr: UB.get());
10721 PrevEUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Assign, LHSExpr: UB.get(),
10722 RHSExpr: CondOp.get());
10723 PrevEUB =
10724 SemaRef.ActOnFinishFullExpr(Expr: PrevEUB.get(), /*DiscardedValue=*/false);
10725
10726 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10727 // parallel for is in combination with a distribute directive with
10728 // schedule(static, 1)
10729 Expr *BoundPrevUB = PrevUB.get();
10730 if (UseStrictCompare) {
10731 BoundPrevUB =
10732 SemaRef
10733 .BuildBinOp(
10734 S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundPrevUB,
10735 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10736 .get();
10737 BoundPrevUB =
10738 SemaRef.ActOnFinishFullExpr(Expr: BoundPrevUB, /*DiscardedValue=*/false)
10739 .get();
10740 }
10741 ParForInDistCond =
10742 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE,
10743 LHSExpr: IV.get(), RHSExpr: BoundPrevUB);
10744 }
10745
10746 // Build updates and final values of the loop counters.
10747 bool HasErrors = false;
10748 Built.Counters.resize(N: NestedLoopCount);
10749 Built.Inits.resize(N: NestedLoopCount);
10750 Built.Updates.resize(N: NestedLoopCount);
10751 Built.Finals.resize(N: NestedLoopCount);
10752 Built.DependentCounters.resize(N: NestedLoopCount);
10753 Built.DependentInits.resize(N: NestedLoopCount);
10754 Built.FinalsConditions.resize(N: NestedLoopCount);
10755 {
10756 // We implement the following algorithm for obtaining the
10757 // original loop iteration variable values based on the
10758 // value of the collapsed loop iteration variable IV.
10759 //
10760 // Let n+1 be the number of collapsed loops in the nest.
10761 // Iteration variables (I0, I1, .... In)
10762 // Iteration counts (N0, N1, ... Nn)
10763 //
10764 // Acc = IV;
10765 //
10766 // To compute Ik for loop k, 0 <= k <= n, generate:
10767 // Prod = N(k+1) * N(k+2) * ... * Nn;
10768 // Ik = Acc / Prod;
10769 // Acc -= Ik * Prod;
10770 //
10771 ExprResult Acc = IV;
10772 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10773 LoopIterationSpace &IS = IterSpaces[Cnt];
10774 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10775 ExprResult Iter;
10776
10777 // Compute prod
10778 ExprResult Prod = SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get();
10779 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10780 Prod = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Mul, LHSExpr: Prod.get(),
10781 RHSExpr: IterSpaces[K].NumIterations);
10782
10783 // Iter = Acc / Prod
10784 // If there is at least one more inner loop to avoid
10785 // multiplication by 1.
10786 if (Cnt + 1 < NestedLoopCount)
10787 Iter =
10788 SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Div, LHSExpr: Acc.get(), RHSExpr: Prod.get());
10789 else
10790 Iter = Acc;
10791 if (!Iter.isUsable()) {
10792 HasErrors = true;
10793 break;
10794 }
10795
10796 // Update Acc:
10797 // Acc -= Iter * Prod
10798 // Check if there is at least one more inner loop to avoid
10799 // multiplication by 1.
10800 if (Cnt + 1 < NestedLoopCount)
10801 Prod = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Mul, LHSExpr: Iter.get(),
10802 RHSExpr: Prod.get());
10803 else
10804 Prod = Iter;
10805 Acc = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Sub, LHSExpr: Acc.get(), RHSExpr: Prod.get());
10806
10807 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10808 auto *VD = cast<VarDecl>(Val: cast<DeclRefExpr>(Val: IS.CounterVar)->getDecl());
10809 DeclRefExpr *CounterVar = buildDeclRefExpr(
10810 S&: SemaRef, D: VD, Ty: IS.CounterVar->getType(), Loc: IS.CounterVar->getExprLoc(),
10811 /*RefersToCapture=*/true);
10812 ExprResult Init =
10813 buildCounterInit(SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar,
10814 Start: IS.CounterInit, IsNonRectangularLB: IS.IsNonRectangularLB, Captures);
10815 if (!Init.isUsable()) {
10816 HasErrors = true;
10817 break;
10818 }
10819 ExprResult Update = buildCounterUpdate(
10820 SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar, Start: IS.CounterInit, Iter,
10821 Step: IS.CounterStep, Subtract: IS.Subtract, IsNonRectangularLB: IS.IsNonRectangularLB, Captures: &Captures);
10822 if (!Update.isUsable()) {
10823 HasErrors = true;
10824 break;
10825 }
10826
10827 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10828 ExprResult Final =
10829 buildCounterUpdate(SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar,
10830 Start: IS.CounterInit, Iter: IS.NumIterations, Step: IS.CounterStep,
10831 Subtract: IS.Subtract, IsNonRectangularLB: IS.IsNonRectangularLB, Captures: &Captures);
10832 if (!Final.isUsable()) {
10833 HasErrors = true;
10834 break;
10835 }
10836
10837 if (!Update.isUsable() || !Final.isUsable()) {
10838 HasErrors = true;
10839 break;
10840 }
10841 // Save results
10842 Built.Counters[Cnt] = IS.CounterVar;
10843 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10844 Built.Inits[Cnt] = Init.get();
10845 Built.Updates[Cnt] = Update.get();
10846 Built.Finals[Cnt] = Final.get();
10847 Built.DependentCounters[Cnt] = nullptr;
10848 Built.DependentInits[Cnt] = nullptr;
10849 // Transfer the body-guard condition: the loop condition for
10850 // non-rectangular loops, the overshoot predicate for reinterpreted tiles,
10851 // null otherwise.
10852 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10853 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10854 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10855 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10856 }
10857 }
10858 }
10859
10860 if (HasErrors)
10861 return 0;
10862
10863 // Save results
10864 Built.IterationVarRef = IV.get();
10865 Built.LastIteration = LastIteration.get();
10866 Built.NumIterations = NumIterations.get();
10867 Built.CalcLastIteration = SemaRef
10868 .ActOnFinishFullExpr(Expr: CalcLastIteration.get(),
10869 /*DiscardedValue=*/false)
10870 .get();
10871 Built.PreCond = PreCond.get();
10872 Built.PreInits = buildPreInits(Context&: C, Captures);
10873 Built.Cond = Cond.get();
10874 Built.Init = Init.get();
10875 Built.Inc = Inc.get();
10876 Built.LB = LB.get();
10877 Built.UB = UB.get();
10878 Built.IL = IL.get();
10879 Built.ST = ST.get();
10880 Built.EUB = EUB.get();
10881 Built.NLB = NextLB.get();
10882 Built.NUB = NextUB.get();
10883 Built.PrevLB = PrevLB.get();
10884 Built.PrevUB = PrevUB.get();
10885 Built.DistInc = DistInc.get();
10886 Built.PrevEUB = PrevEUB.get();
10887 Built.DistCombinedFields.LB = CombLB.get();
10888 Built.DistCombinedFields.UB = CombUB.get();
10889 Built.DistCombinedFields.EUB = CombEUB.get();
10890 Built.DistCombinedFields.Init = CombInit.get();
10891 Built.DistCombinedFields.Cond = CombCond.get();
10892 Built.DistCombinedFields.NLB = CombNextLB.get();
10893 Built.DistCombinedFields.NUB = CombNextUB.get();
10894 Built.DistCombinedFields.DistCond = CombDistCond.get();
10895 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10896
10897 return NestedLoopCount;
10898}
10899
10900static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
10901 auto CollapseClauses =
10902 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10903 if (CollapseClauses.begin() != CollapseClauses.end())
10904 return (*CollapseClauses.begin())->getNumForLoops();
10905 return nullptr;
10906}
10907
10908static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
10909 auto OrderedClauses =
10910 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10911 if (OrderedClauses.begin() != OrderedClauses.end())
10912 return (*OrderedClauses.begin())->getNumForLoops();
10913 return nullptr;
10914}
10915
10916static bool checkSimdlenSafelenSpecified(Sema &S,
10917 const ArrayRef<OMPClause *> Clauses) {
10918 const OMPSafelenClause *Safelen = nullptr;
10919 const OMPSimdlenClause *Simdlen = nullptr;
10920
10921 for (const OMPClause *Clause : Clauses) {
10922 if (Clause->getClauseKind() == OMPC_safelen)
10923 Safelen = cast<OMPSafelenClause>(Val: Clause);
10924 else if (Clause->getClauseKind() == OMPC_simdlen)
10925 Simdlen = cast<OMPSimdlenClause>(Val: Clause);
10926 if (Safelen && Simdlen)
10927 break;
10928 }
10929
10930 if (Simdlen && Safelen) {
10931 const Expr *SimdlenLength = Simdlen->getSimdlen();
10932 const Expr *SafelenLength = Safelen->getSafelen();
10933 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10934 SimdlenLength->isInstantiationDependent() ||
10935 SimdlenLength->containsUnexpandedParameterPack())
10936 return false;
10937 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10938 SafelenLength->isInstantiationDependent() ||
10939 SafelenLength->containsUnexpandedParameterPack())
10940 return false;
10941 Expr::EvalResult SimdlenResult, SafelenResult;
10942 SimdlenLength->EvaluateAsInt(Result&: SimdlenResult, Ctx: S.Context);
10943 SafelenLength->EvaluateAsInt(Result&: SafelenResult, Ctx: S.Context);
10944 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10945 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10946 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10947 // If both simdlen and safelen clauses are specified, the value of the
10948 // simdlen parameter must be less than or equal to the value of the safelen
10949 // parameter.
10950 if (SimdlenRes > SafelenRes) {
10951 S.Diag(Loc: SimdlenLength->getExprLoc(),
10952 DiagID: diag::err_omp_wrong_simdlen_safelen_values)
10953 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10954 return true;
10955 }
10956 }
10957 return false;
10958}
10959
10960StmtResult SemaOpenMP::ActOnOpenMPSimdDirective(
10961 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10962 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10963 if (!AStmt)
10964 return StmtError();
10965
10966 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_simd, AStmt);
10967
10968 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10969 OMPLoopBasedDirective::HelperExprs B;
10970 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10971 // define the nested loops number.
10972 unsigned NestedLoopCount = checkOpenMPLoop(
10973 DKind: OMPD_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
10974 AStmt: CS, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
10975 if (NestedLoopCount == 0)
10976 return StmtError();
10977
10978 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10979 return StmtError();
10980
10981 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
10982 return StmtError();
10983
10984 auto *SimdDirective = OMPSimdDirective::Create(
10985 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10986 return SimdDirective;
10987}
10988
10989StmtResult SemaOpenMP::ActOnOpenMPForDirective(
10990 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10991 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10992 if (!AStmt)
10993 return StmtError();
10994
10995 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10996 OMPLoopBasedDirective::HelperExprs B;
10997 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10998 // define the nested loops number.
10999 unsigned NestedLoopCount = checkOpenMPLoop(
11000 DKind: OMPD_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
11001 AStmt, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
11002 if (NestedLoopCount == 0)
11003 return StmtError();
11004
11005 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11006 return StmtError();
11007
11008 auto *ForDirective = OMPForDirective::Create(
11009 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
11010 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11011 return ForDirective;
11012}
11013
11014StmtResult SemaOpenMP::ActOnOpenMPForSimdDirective(
11015 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11016 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11017 if (!AStmt)
11018 return StmtError();
11019
11020 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_for_simd, AStmt);
11021
11022 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11023 OMPLoopBasedDirective::HelperExprs B;
11024 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11025 // define the nested loops number.
11026 unsigned NestedLoopCount =
11027 checkOpenMPLoop(DKind: OMPD_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11028 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
11029 VarsWithImplicitDSA, Built&: B);
11030 if (NestedLoopCount == 0)
11031 return StmtError();
11032
11033 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11034 return StmtError();
11035
11036 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
11037 return StmtError();
11038
11039 return OMPForSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11040 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11041}
11042
11043static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind,
11044 Stmt *AStmt, DSAStackTy *Stack) {
11045 if (!AStmt)
11046 return true;
11047
11048 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11049 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
11050 auto BaseStmt = AStmt;
11051 while (auto *CS = dyn_cast_or_null<CapturedStmt>(Val: BaseStmt))
11052 BaseStmt = CS->getCapturedStmt();
11053 if (auto *C = dyn_cast_or_null<CompoundStmt>(Val: BaseStmt)) {
11054 auto S = C->children();
11055 if (S.begin() == S.end())
11056 return true;
11057 // All associated statements must be '#pragma omp section' except for
11058 // the first one.
11059 for (Stmt *SectionStmt : llvm::drop_begin(RangeOrContainer&: S)) {
11060 if (!SectionStmt || !isa<OMPSectionDirective>(Val: SectionStmt)) {
11061 if (SectionStmt)
11062 SemaRef.Diag(Loc: SectionStmt->getBeginLoc(),
11063 DiagID: diag::err_omp_sections_substmt_not_section)
11064 << getOpenMPDirectiveName(D: DKind, V: OMPVersion);
11065 return true;
11066 }
11067 cast<OMPSectionDirective>(Val: SectionStmt)
11068 ->setHasCancel(Stack->isCancelRegion());
11069 }
11070 } else {
11071 SemaRef.Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_sections_not_compound_stmt)
11072 << getOpenMPDirectiveName(D: DKind, V: OMPVersion);
11073 return true;
11074 }
11075 return false;
11076}
11077
11078StmtResult
11079SemaOpenMP::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
11080 Stmt *AStmt, SourceLocation StartLoc,
11081 SourceLocation EndLoc) {
11082 if (checkSectionsDirective(SemaRef, DKind: OMPD_sections, AStmt, DSAStack))
11083 return StmtError();
11084
11085 SemaRef.setFunctionHasBranchProtectedScope();
11086
11087 return OMPSectionsDirective::Create(
11088 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11089 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11090}
11091
11092StmtResult SemaOpenMP::ActOnOpenMPSectionDirective(Stmt *AStmt,
11093 SourceLocation StartLoc,
11094 SourceLocation EndLoc) {
11095 if (!AStmt)
11096 return StmtError();
11097
11098 SemaRef.setFunctionHasBranchProtectedScope();
11099 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
11100
11101 return OMPSectionDirective::Create(C: getASTContext(), StartLoc, EndLoc, AssociatedStmt: AStmt,
11102 DSAStack->isCancelRegion());
11103}
11104
11105static Expr *getDirectCallExpr(Expr *E) {
11106 E = E->IgnoreParenCasts()->IgnoreImplicit();
11107 if (auto *CE = dyn_cast<CallExpr>(Val: E))
11108 if (CE->getDirectCallee())
11109 return E;
11110 return nullptr;
11111}
11112
11113StmtResult
11114SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
11115 Stmt *AStmt, SourceLocation StartLoc,
11116 SourceLocation EndLoc) {
11117 if (!AStmt)
11118 return StmtError();
11119
11120 Stmt *S = cast<CapturedStmt>(Val: AStmt)->getCapturedStmt();
11121
11122 // 5.1 OpenMP
11123 // expression-stmt : an expression statement with one of the following forms:
11124 // expression = target-call ( [expression-list] );
11125 // target-call ( [expression-list] );
11126
11127 SourceLocation TargetCallLoc;
11128
11129 if (!SemaRef.CurContext->isDependentContext()) {
11130 Expr *TargetCall = nullptr;
11131
11132 auto *E = dyn_cast<Expr>(Val: S);
11133 if (!E) {
11134 Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_dispatch_statement_call);
11135 return StmtError();
11136 }
11137
11138 E = E->IgnoreParenCasts()->IgnoreImplicit();
11139
11140 if (auto *BO = dyn_cast<BinaryOperator>(Val: E)) {
11141 if (BO->getOpcode() == BO_Assign)
11142 TargetCall = getDirectCallExpr(E: BO->getRHS());
11143 } else {
11144 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(Val: E))
11145 if (COCE->getOperator() == OO_Equal)
11146 TargetCall = getDirectCallExpr(E: COCE->getArg(Arg: 1));
11147 if (!TargetCall)
11148 TargetCall = getDirectCallExpr(E);
11149 }
11150 if (!TargetCall) {
11151 Diag(Loc: E->getBeginLoc(), DiagID: diag::err_omp_dispatch_statement_call);
11152 return StmtError();
11153 }
11154 TargetCallLoc = TargetCall->getExprLoc();
11155 }
11156
11157 SemaRef.setFunctionHasBranchProtectedScope();
11158
11159 return OMPDispatchDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11160 Clauses, AssociatedStmt: AStmt, TargetCallLoc);
11161}
11162
11163static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
11164 OpenMPDirectiveKind K,
11165 DSAStackTy *Stack) {
11166 bool ErrorFound = false;
11167 for (OMPClause *C : Clauses) {
11168 if (auto *LPC = dyn_cast<OMPLastprivateClause>(Val: C)) {
11169 for (Expr *RefExpr : LPC->varlist()) {
11170 SourceLocation ELoc;
11171 SourceRange ERange;
11172 Expr *SimpleRefExpr = RefExpr;
11173 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange);
11174 if (ValueDecl *D = Res.first) {
11175 auto &&Info = Stack->isLoopControlVariable(D);
11176 if (!Info.first) {
11177 llvm::omp::Version OMPVersion = S.getLangOpts().getOpenMPVersion();
11178 S.Diag(Loc: ELoc, DiagID: diag::err_omp_lastprivate_loop_var_non_loop_iteration)
11179 << getOpenMPDirectiveName(D: K, V: OMPVersion);
11180 ErrorFound = true;
11181 }
11182 }
11183 }
11184 }
11185 }
11186 return ErrorFound;
11187}
11188
11189StmtResult SemaOpenMP::ActOnOpenMPGenericLoopDirective(
11190 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11191 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11192 if (!AStmt)
11193 return StmtError();
11194
11195 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11196 // A list item may not appear in a lastprivate clause unless it is the
11197 // loop iteration variable of a loop that is associated with the construct.
11198 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_loop, DSAStack))
11199 return StmtError();
11200
11201 setBranchProtectedScope(SemaRef, DKind: OMPD_loop, AStmt);
11202
11203 OMPLoopDirective::HelperExprs B;
11204 // In presence of clause 'collapse', it will define the nested loops number.
11205 unsigned NestedLoopCount = checkOpenMPLoop(
11206 DKind: OMPD_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
11207 AStmt, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
11208 if (NestedLoopCount == 0)
11209 return StmtError();
11210
11211 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11212 "omp loop exprs were not built");
11213
11214 return OMPGenericLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11215 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11216}
11217
11218/// Check the number of expressions specified in a multidimensional clause and
11219/// return whether an error was encountered.
11220static bool validateMultidimClauseExprs(
11221 SemaBase &SemaRef, OpenMPClauseKind ClauseKind,
11222 SourceLocation ClauseBeginLoc, ArrayRef<const Expr *> ClauseVarList,
11223 const Expr *DimsModifierExpr, const OMPXBareClause *BareClause = nullptr) {
11224 const uint64_t NumVars = ClauseVarList.size();
11225
11226 // The ompx_bare clause allows up to three expressions.
11227 if (BareClause) {
11228 if (NumVars > 3) {
11229 SemaRef.Diag(Loc: ClauseBeginLoc,
11230 DiagID: diag::err_ompx_more_than_three_expr_not_allowed)
11231 << getOpenMPClauseName(C: ClauseKind);
11232 return true;
11233 }
11234 return false;
11235 }
11236
11237 // By default, only one expression accepted.
11238 uint64_t MaxExprs = 1;
11239 if (DimsModifierExpr) {
11240 // Cannot verify the expected size yet.
11241 if (DimsModifierExpr->isInstantiationDependent())
11242 return false;
11243
11244 // The dims modifier determines the exact number of expressions.
11245 MaxExprs = DimsModifierExpr->EvaluateKnownConstInt(Ctx: SemaRef.getASTContext())
11246 .getExtValue();
11247 }
11248
11249 if (NumVars != MaxExprs) {
11250 SemaRef.Diag(Loc: ClauseBeginLoc, DiagID: diag::err_omp_unexpected_num_exprs)
11251 << getOpenMPClauseName(C: ClauseKind) << MaxExprs << NumVars;
11252 return true;
11253 }
11254 if (NumVars > 3) {
11255 SemaRef.Diag(Loc: ClauseBeginLoc, DiagID: diag::err_omp_max_three_exprs)
11256 << getOpenMPClauseName(C: ClauseKind);
11257 return true;
11258 }
11259 return false;
11260}
11261
11262/// Check the number of expressions specified in a multidimensional clause and
11263/// return whether an error was encountered.
11264template <typename ClauseT>
11265static bool validateMultidimClauseExprs(SemaBase &SemaRef,
11266 const ClauseT *Clause,
11267 const OMPXBareClause *BareClause) {
11268 if (!Clause)
11269 return false;
11270 return validateMultidimClauseExprs(
11271 SemaRef, Clause->getClauseKind(), Clause->getBeginLoc(),
11272 Clause->getVarRefs(), Clause->getDimsModifierExpr(), BareClause);
11273}
11274
11275/// Check the number of expressions specified in clauses that can contain
11276/// multidimensional values, e.g., num_teams and thread_limit. The function
11277/// returns true on error.
11278static bool validateMultidimClauses(SemaBase &SemaRef,
11279 ArrayRef<OMPClause *> Clauses,
11280 bool MayHaveBareClause = false) {
11281 auto BareClauseIt =
11282 MayHaveBareClause ? llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OMPXBareClause>)
11283 : Clauses.end();
11284 auto ThreadLimitIt =
11285 llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OMPThreadLimitClause>);
11286 auto NumTeamsIt = llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OMPNumTeamsClause>);
11287
11288 const auto *BareClause = BareClauseIt != Clauses.end()
11289 ? cast<OMPXBareClause>(Val: *BareClauseIt)
11290 : nullptr;
11291 const auto *ThreadLimitClause =
11292 ThreadLimitIt != Clauses.end()
11293 ? cast<OMPThreadLimitClause>(Val: *ThreadLimitIt)
11294 : nullptr;
11295 const auto *NumTeamsClause = NumTeamsIt != Clauses.end()
11296 ? cast<OMPNumTeamsClause>(Val: *NumTeamsIt)
11297 : nullptr;
11298
11299 if (BareClause) {
11300 if (!NumTeamsClause || !ThreadLimitClause) {
11301 SemaRef.Diag(Loc: BareClause->getBeginLoc(), DiagID: diag::err_ompx_bare_no_grid);
11302 return true;
11303 }
11304 if (ThreadLimitClause->getModifier() == OMPC_THREADLIMIT_dims ||
11305 NumTeamsClause->getModifier() == OMPC_NUMTEAMS_dims) {
11306 SemaRef.Diag(Loc: BareClause->getBeginLoc(), DiagID: diag::err_ompx_bare_no_dims);
11307 return true;
11308 }
11309 }
11310 return validateMultidimClauseExprs(SemaRef, Clause: ThreadLimitClause, BareClause) ||
11311 validateMultidimClauseExprs(SemaRef, Clause: NumTeamsClause, BareClause);
11312}
11313
11314StmtResult SemaOpenMP::ActOnOpenMPTeamsGenericLoopDirective(
11315 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11316 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11317 if (!AStmt)
11318 return StmtError();
11319
11320 if (validateMultidimClauses(SemaRef&: *this, Clauses))
11321 return StmtError();
11322
11323 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11324 // A list item may not appear in a lastprivate clause unless it is the
11325 // loop iteration variable of a loop that is associated with the construct.
11326 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_teams_loop, DSAStack))
11327 return StmtError();
11328
11329 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_teams_loop, AStmt);
11330
11331 OMPLoopDirective::HelperExprs B;
11332 // In presence of clause 'collapse', it will define the nested loops number.
11333 unsigned NestedLoopCount =
11334 checkOpenMPLoop(DKind: OMPD_teams_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11335 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11336 VarsWithImplicitDSA, Built&: B);
11337 if (NestedLoopCount == 0)
11338 return StmtError();
11339
11340 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11341 "omp loop exprs were not built");
11342
11343 DSAStack->setParentTeamsRegionLoc(StartLoc);
11344
11345 return OMPTeamsGenericLoopDirective::Create(
11346 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11347}
11348
11349StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsGenericLoopDirective(
11350 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11351 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11352 if (!AStmt)
11353 return StmtError();
11354
11355 if (validateMultidimClauses(SemaRef&: *this, Clauses))
11356 return StmtError();
11357
11358 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11359 // A list item may not appear in a lastprivate clause unless it is the
11360 // loop iteration variable of a loop that is associated with the construct.
11361 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_target_teams_loop,
11362 DSAStack))
11363 return StmtError();
11364
11365 CapturedStmt *CS =
11366 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams_loop, AStmt);
11367
11368 OMPLoopDirective::HelperExprs B;
11369 // In presence of clause 'collapse', it will define the nested loops number.
11370 unsigned NestedLoopCount =
11371 checkOpenMPLoop(DKind: OMPD_target_teams_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11372 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11373 VarsWithImplicitDSA, Built&: B);
11374 if (NestedLoopCount == 0)
11375 return StmtError();
11376
11377 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11378 "omp loop exprs were not built");
11379
11380 return OMPTargetTeamsGenericLoopDirective::Create(
11381 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
11382 CanBeParallelFor: teamsLoopCanBeParallelFor(AStmt, SemaRef));
11383}
11384
11385StmtResult SemaOpenMP::ActOnOpenMPParallelGenericLoopDirective(
11386 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11387 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11388 if (!AStmt)
11389 return StmtError();
11390
11391 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11392 // A list item may not appear in a lastprivate clause unless it is the
11393 // loop iteration variable of a loop that is associated with the construct.
11394 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_parallel_loop,
11395 DSAStack))
11396 return StmtError();
11397
11398 CapturedStmt *CS =
11399 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_loop, AStmt);
11400
11401 OMPLoopDirective::HelperExprs B;
11402 // In presence of clause 'collapse', it will define the nested loops number.
11403 unsigned NestedLoopCount =
11404 checkOpenMPLoop(DKind: OMPD_parallel_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11405 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11406 VarsWithImplicitDSA, Built&: B);
11407 if (NestedLoopCount == 0)
11408 return StmtError();
11409
11410 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11411 "omp loop exprs were not built");
11412
11413 return OMPParallelGenericLoopDirective::Create(
11414 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11415}
11416
11417StmtResult SemaOpenMP::ActOnOpenMPTargetParallelGenericLoopDirective(
11418 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11419 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11420 if (!AStmt)
11421 return StmtError();
11422
11423 if (validateMultidimClauses(SemaRef&: *this, Clauses))
11424 return StmtError();
11425
11426 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11427 // A list item may not appear in a lastprivate clause unless it is the
11428 // loop iteration variable of a loop that is associated with the construct.
11429 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_target_parallel_loop,
11430 DSAStack))
11431 return StmtError();
11432
11433 CapturedStmt *CS =
11434 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_loop, AStmt);
11435
11436 OMPLoopDirective::HelperExprs B;
11437 // In presence of clause 'collapse', it will define the nested loops number.
11438 unsigned NestedLoopCount =
11439 checkOpenMPLoop(DKind: OMPD_target_parallel_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11440 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11441 VarsWithImplicitDSA, Built&: B);
11442 if (NestedLoopCount == 0)
11443 return StmtError();
11444
11445 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11446 "omp loop exprs were not built");
11447
11448 return OMPTargetParallelGenericLoopDirective::Create(
11449 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11450}
11451
11452StmtResult SemaOpenMP::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
11453 Stmt *AStmt,
11454 SourceLocation StartLoc,
11455 SourceLocation EndLoc) {
11456 if (!AStmt)
11457 return StmtError();
11458
11459 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11460
11461 SemaRef.setFunctionHasBranchProtectedScope();
11462
11463 // OpenMP [2.7.3, single Construct, Restrictions]
11464 // The copyprivate clause must not be used with the nowait clause.
11465 const OMPClause *Nowait = nullptr;
11466 const OMPClause *Copyprivate = nullptr;
11467 for (const OMPClause *Clause : Clauses) {
11468 if (Clause->getClauseKind() == OMPC_nowait)
11469 Nowait = Clause;
11470 else if (Clause->getClauseKind() == OMPC_copyprivate)
11471 Copyprivate = Clause;
11472 if (Copyprivate && Nowait) {
11473 Diag(Loc: Copyprivate->getBeginLoc(),
11474 DiagID: diag::err_omp_single_copyprivate_with_nowait);
11475 Diag(Loc: Nowait->getBeginLoc(), DiagID: diag::note_omp_nowait_clause_here);
11476 return StmtError();
11477 }
11478 }
11479
11480 return OMPSingleDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11481 AssociatedStmt: AStmt);
11482}
11483
11484StmtResult SemaOpenMP::ActOnOpenMPMasterDirective(Stmt *AStmt,
11485 SourceLocation StartLoc,
11486 SourceLocation EndLoc) {
11487 if (!AStmt)
11488 return StmtError();
11489
11490 SemaRef.setFunctionHasBranchProtectedScope();
11491
11492 return OMPMasterDirective::Create(C: getASTContext(), StartLoc, EndLoc, AssociatedStmt: AStmt);
11493}
11494
11495StmtResult SemaOpenMP::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
11496 Stmt *AStmt,
11497 SourceLocation StartLoc,
11498 SourceLocation EndLoc) {
11499 if (!AStmt)
11500 return StmtError();
11501
11502 SemaRef.setFunctionHasBranchProtectedScope();
11503
11504 return OMPMaskedDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11505 AssociatedStmt: AStmt);
11506}
11507
11508StmtResult SemaOpenMP::ActOnOpenMPCriticalDirective(
11509 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11510 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11511 if (!AStmt)
11512 return StmtError();
11513
11514 bool ErrorFound = false;
11515 llvm::APSInt Hint;
11516 SourceLocation HintLoc;
11517 bool DependentHint = false;
11518 for (const OMPClause *C : Clauses) {
11519 if (C->getClauseKind() == OMPC_hint) {
11520 if (!DirName.getName()) {
11521 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_hint_clause_no_name);
11522 ErrorFound = true;
11523 }
11524 Expr *E = cast<OMPHintClause>(Val: C)->getHint();
11525 if (E->isTypeDependent() || E->isValueDependent() ||
11526 E->isInstantiationDependent()) {
11527 DependentHint = true;
11528 } else {
11529 Hint = E->EvaluateKnownConstInt(Ctx: getASTContext());
11530 HintLoc = C->getBeginLoc();
11531 }
11532 }
11533 }
11534 if (ErrorFound)
11535 return StmtError();
11536 const auto Pair = DSAStack->getCriticalWithHint(Name: DirName);
11537 if (Pair.first && DirName.getName() && !DependentHint) {
11538 if (llvm::APSInt::compareValues(I1: Hint, I2: Pair.second) != 0) {
11539 Diag(Loc: StartLoc, DiagID: diag::err_omp_critical_with_hint);
11540 if (HintLoc.isValid())
11541 Diag(Loc: HintLoc, DiagID: diag::note_omp_critical_hint_here)
11542 << 0 << toString(I: Hint, /*Radix=*/10, /*Signed=*/false);
11543 else
11544 Diag(Loc: StartLoc, DiagID: diag::note_omp_critical_no_hint) << 0;
11545 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11546 Diag(Loc: C->getBeginLoc(), DiagID: diag::note_omp_critical_hint_here)
11547 << 1
11548 << toString(I: C->getHint()->EvaluateKnownConstInt(Ctx: getASTContext()),
11549 /*Radix=*/10, /*Signed=*/false);
11550 } else {
11551 Diag(Loc: Pair.first->getBeginLoc(), DiagID: diag::note_omp_critical_no_hint) << 1;
11552 }
11553 }
11554 }
11555
11556 SemaRef.setFunctionHasBranchProtectedScope();
11557
11558 auto *Dir = OMPCriticalDirective::Create(C: getASTContext(), Name: DirName, StartLoc,
11559 EndLoc, Clauses, AssociatedStmt: AStmt);
11560 if (!Pair.first && DirName.getName() && !DependentHint)
11561 DSAStack->addCriticalWithHint(D: Dir, Hint);
11562 return Dir;
11563}
11564
11565StmtResult SemaOpenMP::ActOnOpenMPParallelForDirective(
11566 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11567 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11568 if (!AStmt)
11569 return StmtError();
11570
11571 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_for, AStmt);
11572
11573 OMPLoopBasedDirective::HelperExprs B;
11574 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11575 // define the nested loops number.
11576 unsigned NestedLoopCount =
11577 checkOpenMPLoop(DKind: OMPD_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11578 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt, SemaRef, DSA&: *DSAStack,
11579 VarsWithImplicitDSA, Built&: B);
11580 if (NestedLoopCount == 0)
11581 return StmtError();
11582
11583 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11584 return StmtError();
11585
11586 return OMPParallelForDirective::Create(
11587 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
11588 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11589}
11590
11591StmtResult SemaOpenMP::ActOnOpenMPParallelForSimdDirective(
11592 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11593 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11594 if (!AStmt)
11595 return StmtError();
11596
11597 CapturedStmt *CS =
11598 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_for_simd, AStmt);
11599
11600 OMPLoopBasedDirective::HelperExprs B;
11601 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11602 // define the nested loops number.
11603 unsigned NestedLoopCount =
11604 checkOpenMPLoop(DKind: OMPD_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11605 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
11606 VarsWithImplicitDSA, Built&: B);
11607 if (NestedLoopCount == 0)
11608 return StmtError();
11609
11610 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11611 return StmtError();
11612
11613 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
11614 return StmtError();
11615
11616 return OMPParallelForSimdDirective::Create(
11617 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11618}
11619
11620StmtResult SemaOpenMP::ActOnOpenMPParallelMasterDirective(
11621 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11622 SourceLocation EndLoc) {
11623 if (!AStmt)
11624 return StmtError();
11625
11626 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_master, AStmt);
11627
11628 return OMPParallelMasterDirective::Create(
11629 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11630 DSAStack->getTaskgroupReductionRef());
11631}
11632
11633StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedDirective(
11634 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11635 SourceLocation EndLoc) {
11636 if (!AStmt)
11637 return StmtError();
11638
11639 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_masked, AStmt);
11640
11641 return OMPParallelMaskedDirective::Create(
11642 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11643 DSAStack->getTaskgroupReductionRef());
11644}
11645
11646StmtResult SemaOpenMP::ActOnOpenMPParallelSectionsDirective(
11647 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11648 SourceLocation EndLoc) {
11649 if (checkSectionsDirective(SemaRef, DKind: OMPD_parallel_sections, AStmt, DSAStack))
11650 return StmtError();
11651
11652 SemaRef.setFunctionHasBranchProtectedScope();
11653
11654 return OMPParallelSectionsDirective::Create(
11655 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11656 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11657}
11658
11659/// Find and diagnose mutually exclusive clause kinds.
11660static bool checkMutuallyExclusiveClauses(
11661 Sema &S, ArrayRef<OMPClause *> Clauses,
11662 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11663 const OMPClause *PrevClause = nullptr;
11664 bool ErrorFound = false;
11665 for (const OMPClause *C : Clauses) {
11666 if (llvm::is_contained(Range&: MutuallyExclusiveClauses, Element: C->getClauseKind())) {
11667 if (!PrevClause) {
11668 PrevClause = C;
11669 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11670 S.Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_clauses_mutually_exclusive)
11671 << getOpenMPClauseNameForDiag(C: C->getClauseKind())
11672 << getOpenMPClauseNameForDiag(C: PrevClause->getClauseKind());
11673 S.Diag(Loc: PrevClause->getBeginLoc(), DiagID: diag::note_omp_previous_clause)
11674 << getOpenMPClauseNameForDiag(C: PrevClause->getClauseKind());
11675 ErrorFound = true;
11676 }
11677 }
11678 }
11679 return ErrorFound;
11680}
11681
11682StmtResult SemaOpenMP::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
11683 Stmt *AStmt,
11684 SourceLocation StartLoc,
11685 SourceLocation EndLoc) {
11686 if (!AStmt)
11687 return StmtError();
11688
11689 // OpenMP 5.0, 2.10.1 task Construct
11690 // If a detach clause appears on the directive, then a mergeable clause cannot
11691 // appear on the same directive.
11692 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
11693 MutuallyExclusiveClauses: {OMPC_detach, OMPC_mergeable}))
11694 return StmtError();
11695
11696 setBranchProtectedScope(SemaRef, DKind: OMPD_task, AStmt);
11697
11698 return OMPTaskDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11699 AssociatedStmt: AStmt, DSAStack->isCancelRegion());
11700}
11701
11702StmtResult SemaOpenMP::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
11703 SourceLocation EndLoc) {
11704 return OMPTaskyieldDirective::Create(C: getASTContext(), StartLoc, EndLoc);
11705}
11706
11707StmtResult SemaOpenMP::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
11708 SourceLocation EndLoc) {
11709 return OMPBarrierDirective::Create(C: getASTContext(), StartLoc, EndLoc);
11710}
11711
11712StmtResult SemaOpenMP::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
11713 SourceLocation StartLoc,
11714 SourceLocation EndLoc,
11715 bool InExContext) {
11716 const OMPAtClause *AtC =
11717 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11718
11719 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11720 Diag(Loc: AtC->getAtKindKwLoc(), DiagID: diag::err_omp_unexpected_execution_modifier);
11721 return StmtError();
11722 }
11723
11724 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11725 const OMPSeverityClause *SeverityC =
11726 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11727 const OMPMessageClause *MessageC =
11728 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11729 std::optional<std::string> SL =
11730 MessageC ? MessageC->tryEvaluateString(Ctx&: getASTContext()) : std::nullopt;
11731
11732 if (MessageC && !SL)
11733 Diag(Loc: MessageC->getMessageString()->getBeginLoc(),
11734 DiagID: diag::warn_clause_expected_string)
11735 << getOpenMPClauseNameForDiag(C: OMPC_message) << 1;
11736 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11737 Diag(Loc: SeverityC->getSeverityKindKwLoc(), DiagID: diag::warn_diagnose_if_succeeded)
11738 << SL.value_or(u: "WARNING");
11739 else
11740 Diag(Loc: StartLoc, DiagID: diag::err_diagnose_if_succeeded) << SL.value_or(u: "ERROR");
11741 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11742 return StmtError();
11743 }
11744
11745 return OMPErrorDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11746}
11747
11748StmtResult
11749SemaOpenMP::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
11750 SourceLocation StartLoc,
11751 SourceLocation EndLoc) {
11752 const OMPNowaitClause *NowaitC =
11753 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11754 bool HasDependC =
11755 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11756 .empty();
11757 if (NowaitC && !HasDependC) {
11758 Diag(Loc: StartLoc, DiagID: diag::err_omp_nowait_clause_without_depend);
11759 return StmtError();
11760 }
11761
11762 return OMPTaskwaitDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11763 Clauses);
11764}
11765
11766StmtResult
11767SemaOpenMP::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
11768 Stmt *AStmt, SourceLocation StartLoc,
11769 SourceLocation EndLoc) {
11770 if (!AStmt)
11771 return StmtError();
11772
11773 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11774
11775 SemaRef.setFunctionHasBranchProtectedScope();
11776
11777 return OMPTaskgroupDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11778 Clauses, AssociatedStmt: AStmt,
11779 DSAStack->getTaskgroupReductionRef());
11780}
11781
11782StmtResult SemaOpenMP::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
11783 SourceLocation StartLoc,
11784 SourceLocation EndLoc) {
11785 OMPFlushClause *FC = nullptr;
11786 OMPClause *OrderClause = nullptr;
11787 for (OMPClause *C : Clauses) {
11788 if (C->getClauseKind() == OMPC_flush)
11789 FC = cast<OMPFlushClause>(Val: C);
11790 else
11791 OrderClause = C;
11792 }
11793 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
11794 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11795 SourceLocation MemOrderLoc;
11796 for (const OMPClause *C : Clauses) {
11797 if (C->getClauseKind() == OMPC_acq_rel ||
11798 C->getClauseKind() == OMPC_acquire ||
11799 C->getClauseKind() == OMPC_release ||
11800 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11801 if (MemOrderKind != OMPC_unknown) {
11802 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_several_mem_order_clauses)
11803 << getOpenMPDirectiveName(D: OMPD_flush, V: OMPVersion) << 1
11804 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11805 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
11806 << getOpenMPClauseNameForDiag(C: MemOrderKind);
11807 } else {
11808 MemOrderKind = C->getClauseKind();
11809 MemOrderLoc = C->getBeginLoc();
11810 }
11811 }
11812 }
11813 if (FC && OrderClause) {
11814 Diag(Loc: FC->getLParenLoc(), DiagID: diag::err_omp_flush_order_clause_and_list)
11815 << getOpenMPClauseNameForDiag(C: OrderClause->getClauseKind());
11816 Diag(Loc: OrderClause->getBeginLoc(), DiagID: diag::note_omp_flush_order_clause_here)
11817 << getOpenMPClauseNameForDiag(C: OrderClause->getClauseKind());
11818 return StmtError();
11819 }
11820 return OMPFlushDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11821}
11822
11823StmtResult SemaOpenMP::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
11824 SourceLocation StartLoc,
11825 SourceLocation EndLoc) {
11826 if (Clauses.empty()) {
11827 Diag(Loc: StartLoc, DiagID: diag::err_omp_depobj_expected);
11828 return StmtError();
11829 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11830 Diag(Loc: Clauses[0]->getBeginLoc(), DiagID: diag::err_omp_depobj_expected);
11831 return StmtError();
11832 }
11833 // Only depobj expression and another single clause is allowed.
11834 if (Clauses.size() > 2) {
11835 Diag(Loc: Clauses[2]->getBeginLoc(),
11836 DiagID: diag::err_omp_depobj_single_clause_expected);
11837 return StmtError();
11838 } else if (Clauses.size() < 1) {
11839 Diag(Loc: Clauses[0]->getEndLoc(), DiagID: diag::err_omp_depobj_single_clause_expected);
11840 return StmtError();
11841 }
11842 return OMPDepobjDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11843}
11844
11845StmtResult SemaOpenMP::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
11846 SourceLocation StartLoc,
11847 SourceLocation EndLoc) {
11848 // Check that exactly one clause is specified.
11849 if (Clauses.size() != 1) {
11850 Diag(Loc: Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11851 DiagID: diag::err_omp_scan_single_clause_expected);
11852 return StmtError();
11853 }
11854 // Check that scan directive is used in the scope of the OpenMP loop body.
11855 if (Scope *S = DSAStack->getCurScope()) {
11856 Scope *ParentS = S->getParent();
11857 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11858 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11859 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
11860 return StmtError(Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_device_directive)
11861 << getOpenMPDirectiveName(D: OMPD_scan, V: OMPVersion) << 5);
11862 }
11863 }
11864 // Check that only one instance of scan directives is used in the same outer
11865 // region.
11866 if (DSAStack->doesParentHasScanDirective()) {
11867 Diag(Loc: StartLoc, DiagID: diag::err_omp_several_directives_in_region) << "scan";
11868 Diag(DSAStack->getParentScanDirectiveLoc(),
11869 DiagID: diag::note_omp_previous_directive)
11870 << "scan";
11871 return StmtError();
11872 }
11873 DSAStack->setParentHasScanDirective(StartLoc);
11874 return OMPScanDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11875}
11876
11877StmtResult
11878SemaOpenMP::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
11879 Stmt *AStmt, SourceLocation StartLoc,
11880 SourceLocation EndLoc) {
11881 const OMPClause *DependFound = nullptr;
11882 const OMPClause *DependSourceClause = nullptr;
11883 const OMPClause *DependSinkClause = nullptr;
11884 const OMPClause *DoacrossFound = nullptr;
11885 const OMPClause *DoacrossSourceClause = nullptr;
11886 const OMPClause *DoacrossSinkClause = nullptr;
11887 bool ErrorFound = false;
11888 const OMPThreadsClause *TC = nullptr;
11889 const OMPSIMDClause *SC = nullptr;
11890 for (const OMPClause *C : Clauses) {
11891 auto DOC = dyn_cast<OMPDoacrossClause>(Val: C);
11892 auto DC = dyn_cast<OMPDependClause>(Val: C);
11893 if (DC || DOC) {
11894 DependFound = DC ? C : nullptr;
11895 DoacrossFound = DOC ? C : nullptr;
11896 OMPDoacrossKind ODK;
11897 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11898 (DOC && (ODK.isSource(C: DOC)))) {
11899 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11900 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
11901 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_more_one_clause)
11902 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
11903 V: OMPVersion)
11904 << getOpenMPClauseNameForDiag(C: DC ? OMPC_depend : OMPC_doacross)
11905 << 2;
11906 ErrorFound = true;
11907 } else {
11908 if (DC)
11909 DependSourceClause = C;
11910 else
11911 DoacrossSourceClause = C;
11912 }
11913 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11914 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_sink_and_source_not_allowed)
11915 << (DC ? "depend" : "doacross") << 0;
11916 ErrorFound = true;
11917 }
11918 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11919 (DOC && (ODK.isSink(C: DOC) || ODK.isSinkIter(C: DOC)))) {
11920 if (DependSourceClause || DoacrossSourceClause) {
11921 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_sink_and_source_not_allowed)
11922 << (DC ? "depend" : "doacross") << 1;
11923 ErrorFound = true;
11924 }
11925 if (DC)
11926 DependSinkClause = C;
11927 else
11928 DoacrossSinkClause = C;
11929 }
11930 } else if (C->getClauseKind() == OMPC_threads) {
11931 TC = cast<OMPThreadsClause>(Val: C);
11932 } else if (C->getClauseKind() == OMPC_simd) {
11933 SC = cast<OMPSIMDClause>(Val: C);
11934 }
11935 }
11936 if (!ErrorFound && !SC &&
11937 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11938 // OpenMP [2.8.1,simd Construct, Restrictions]
11939 // An ordered construct with the simd clause is the only OpenMP construct
11940 // that can appear in the simd region.
11941 Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_simd)
11942 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11943 ErrorFound = true;
11944 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11945 SourceLocation Loc =
11946 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11947 Diag(Loc, DiagID: diag::err_omp_depend_clause_thread_simd)
11948 << getOpenMPClauseNameForDiag(C: DependFound ? OMPC_depend : OMPC_doacross)
11949 << getOpenMPClauseNameForDiag(C: TC ? TC->getClauseKind()
11950 : SC->getClauseKind());
11951 ErrorFound = true;
11952 } else if ((DependFound || DoacrossFound) &&
11953 !DSAStack->getParentOrderedRegionParam().first) {
11954 SourceLocation Loc =
11955 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11956 Diag(Loc, DiagID: diag::err_omp_ordered_directive_without_param)
11957 << getOpenMPClauseNameForDiag(C: DependFound ? OMPC_depend
11958 : OMPC_doacross);
11959 ErrorFound = true;
11960 } else if (TC || Clauses.empty()) {
11961 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11962 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11963 Diag(Loc: ErrLoc, DiagID: diag::err_omp_ordered_directive_with_param)
11964 << (TC != nullptr);
11965 Diag(Loc: Param->getBeginLoc(), DiagID: diag::note_omp_ordered_param) << 1;
11966 ErrorFound = true;
11967 }
11968 }
11969 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11970 return StmtError();
11971
11972 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11973 // During execution of an iteration of a worksharing-loop or a loop nest
11974 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11975 // must not execute more than one ordered region corresponding to an ordered
11976 // construct without a depend clause.
11977 if (!DependFound && !DoacrossFound) {
11978 if (DSAStack->doesParentHasOrderedDirective()) {
11979 Diag(Loc: StartLoc, DiagID: diag::err_omp_several_directives_in_region) << "ordered";
11980 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11981 DiagID: diag::note_omp_previous_directive)
11982 << "ordered";
11983 return StmtError();
11984 }
11985 DSAStack->setParentHasOrderedDirective(StartLoc);
11986 }
11987
11988 if (AStmt) {
11989 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11990
11991 SemaRef.setFunctionHasBranchProtectedScope();
11992 }
11993
11994 if (!AStmt)
11995 return OMPOrderedStandaloneDirective::Create(C: getASTContext(), StartLoc,
11996 EndLoc, Clauses);
11997 return OMPOrderedBlockAssocDirective::Create(C: getASTContext(), StartLoc,
11998 EndLoc, Clauses, AssociatedStmt: AStmt);
11999}
12000
12001namespace {
12002/// Helper class for checking expression in 'omp atomic [update]'
12003/// construct.
12004class OpenMPAtomicUpdateChecker {
12005 /// Error results for atomic update expressions.
12006 enum ExprAnalysisErrorCode {
12007 /// A statement is not an expression statement.
12008 NotAnExpression,
12009 /// Expression is not builtin binary or unary operation.
12010 NotABinaryOrUnaryExpression,
12011 /// Unary operation is not post-/pre- increment/decrement operation.
12012 NotAnUnaryIncDecExpression,
12013 /// An expression is not of scalar type.
12014 NotAScalarType,
12015 /// A binary operation is not an assignment operation.
12016 NotAnAssignmentOp,
12017 /// RHS part of the binary operation is not a binary expression.
12018 NotABinaryExpression,
12019 /// RHS part is not additive/multiplicative/shift/bitwise binary
12020 /// expression.
12021 NotABinaryOperator,
12022 /// RHS binary operation does not have reference to the updated LHS
12023 /// part.
12024 NotAnUpdateExpression,
12025 /// An expression contains semantical error not related to
12026 /// 'omp atomic [update]'
12027 NotAValidExpression,
12028 /// No errors is found.
12029 NoError
12030 };
12031 /// Reference to Sema.
12032 Sema &SemaRef;
12033 /// A location for note diagnostics (when error is found).
12034 SourceLocation NoteLoc;
12035 /// 'x' lvalue part of the source atomic expression.
12036 Expr *X;
12037 /// 'expr' rvalue part of the source atomic expression.
12038 Expr *E;
12039 /// Helper expression of the form
12040 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
12041 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
12042 Expr *UpdateExpr;
12043 /// Is 'x' a LHS in a RHS part of full update expression. It is
12044 /// important for non-associative operations.
12045 bool IsXLHSInRHSPart;
12046 BinaryOperatorKind Op;
12047 SourceLocation OpLoc;
12048 /// true if the source expression is a postfix unary operation, false
12049 /// if it is a prefix unary operation.
12050 bool IsPostfixUpdate;
12051
12052public:
12053 OpenMPAtomicUpdateChecker(Sema &SemaRef)
12054 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
12055 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
12056 /// Check specified statement that it is suitable for 'atomic update'
12057 /// constructs and extract 'x', 'expr' and Operation from the original
12058 /// expression. If DiagId and NoteId == 0, then only check is performed
12059 /// without error notification.
12060 /// \param DiagId Diagnostic which should be emitted if error is found.
12061 /// \param NoteId Diagnostic note for the main error message.
12062 /// \return true if statement is not an update expression, false otherwise.
12063 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
12064 /// Return the 'x' lvalue part of the source atomic expression.
12065 Expr *getX() const { return X; }
12066 /// Return the 'expr' rvalue part of the source atomic expression.
12067 Expr *getExpr() const { return E; }
12068 /// Return the update expression used in calculation of the updated
12069 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
12070 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
12071 Expr *getUpdateExpr() const { return UpdateExpr; }
12072 /// Return true if 'x' is LHS in RHS part of full update expression,
12073 /// false otherwise.
12074 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
12075
12076 /// true if the source expression is a postfix unary operation, false
12077 /// if it is a prefix unary operation.
12078 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12079
12080private:
12081 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
12082 unsigned NoteId = 0);
12083};
12084
12085bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
12086 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
12087 ExprAnalysisErrorCode ErrorFound = NoError;
12088 SourceLocation ErrorLoc, NoteLoc;
12089 SourceRange ErrorRange, NoteRange;
12090 // Allowed constructs are:
12091 // x = x binop expr;
12092 // x = expr binop x;
12093 if (AtomicBinOp->getOpcode() == BO_Assign) {
12094 X = AtomicBinOp->getLHS();
12095 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
12096 Val: AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
12097 if (AtomicInnerBinOp->isMultiplicativeOp() ||
12098 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
12099 AtomicInnerBinOp->isBitwiseOp()) {
12100 Op = AtomicInnerBinOp->getOpcode();
12101 OpLoc = AtomicInnerBinOp->getOperatorLoc();
12102 Expr *LHS = AtomicInnerBinOp->getLHS();
12103 Expr *RHS = AtomicInnerBinOp->getRHS();
12104 llvm::FoldingSetNodeID XId, LHSId, RHSId;
12105 X->IgnoreParenImpCasts()->Profile(ID&: XId, Context: SemaRef.getASTContext(),
12106 /*Canonical=*/true);
12107 LHS->IgnoreParenImpCasts()->Profile(ID&: LHSId, Context: SemaRef.getASTContext(),
12108 /*Canonical=*/true);
12109 RHS->IgnoreParenImpCasts()->Profile(ID&: RHSId, Context: SemaRef.getASTContext(),
12110 /*Canonical=*/true);
12111 if (XId == LHSId) {
12112 E = RHS;
12113 IsXLHSInRHSPart = true;
12114 } else if (XId == RHSId) {
12115 E = LHS;
12116 IsXLHSInRHSPart = false;
12117 } else {
12118 ErrorLoc = AtomicInnerBinOp->getExprLoc();
12119 ErrorRange = AtomicInnerBinOp->getSourceRange();
12120 NoteLoc = X->getExprLoc();
12121 NoteRange = X->getSourceRange();
12122 ErrorFound = NotAnUpdateExpression;
12123 }
12124 } else {
12125 ErrorLoc = AtomicInnerBinOp->getExprLoc();
12126 ErrorRange = AtomicInnerBinOp->getSourceRange();
12127 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
12128 NoteRange = SourceRange(NoteLoc, NoteLoc);
12129 ErrorFound = NotABinaryOperator;
12130 }
12131 } else {
12132 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
12133 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
12134 ErrorFound = NotABinaryExpression;
12135 }
12136 } else {
12137 ErrorLoc = AtomicBinOp->getExprLoc();
12138 ErrorRange = AtomicBinOp->getSourceRange();
12139 NoteLoc = AtomicBinOp->getOperatorLoc();
12140 NoteRange = SourceRange(NoteLoc, NoteLoc);
12141 ErrorFound = NotAnAssignmentOp;
12142 }
12143 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
12144 SemaRef.Diag(Loc: ErrorLoc, DiagID: DiagId) << ErrorRange;
12145 SemaRef.Diag(Loc: NoteLoc, DiagID: NoteId) << ErrorFound << NoteRange;
12146 return true;
12147 }
12148 if (SemaRef.CurContext->isDependentContext())
12149 E = X = UpdateExpr = nullptr;
12150 return ErrorFound != NoError;
12151}
12152
12153bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
12154 unsigned NoteId) {
12155 ExprAnalysisErrorCode ErrorFound = NoError;
12156 SourceLocation ErrorLoc, NoteLoc;
12157 SourceRange ErrorRange, NoteRange;
12158 // Allowed constructs are:
12159 // x++;
12160 // x--;
12161 // ++x;
12162 // --x;
12163 // x binop= expr;
12164 // x = x binop expr;
12165 // x = expr binop x;
12166 if (auto *AtomicBody = dyn_cast<Expr>(Val: S)) {
12167 AtomicBody = AtomicBody->IgnoreParenImpCasts();
12168 if (AtomicBody->getType()->isScalarType() ||
12169 AtomicBody->isInstantiationDependent()) {
12170 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
12171 Val: AtomicBody->IgnoreParenImpCasts())) {
12172 // Check for Compound Assignment Operation
12173 Op = BinaryOperator::getOpForCompoundAssignment(
12174 Opc: AtomicCompAssignOp->getOpcode());
12175 OpLoc = AtomicCompAssignOp->getOperatorLoc();
12176 E = AtomicCompAssignOp->getRHS();
12177 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
12178 IsXLHSInRHSPart = true;
12179 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
12180 Val: AtomicBody->IgnoreParenImpCasts())) {
12181 // Check for Binary Operation
12182 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
12183 return true;
12184 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
12185 Val: AtomicBody->IgnoreParenImpCasts())) {
12186 // Check for Unary Operation
12187 if (AtomicUnaryOp->isIncrementDecrementOp()) {
12188 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
12189 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
12190 OpLoc = AtomicUnaryOp->getOperatorLoc();
12191 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
12192 E = SemaRef.ActOnIntegerConstant(Loc: OpLoc, /*uint64_t Val=*/Val: 1).get();
12193 IsXLHSInRHSPart = true;
12194 } else {
12195 ErrorFound = NotAnUnaryIncDecExpression;
12196 ErrorLoc = AtomicUnaryOp->getExprLoc();
12197 ErrorRange = AtomicUnaryOp->getSourceRange();
12198 NoteLoc = AtomicUnaryOp->getOperatorLoc();
12199 NoteRange = SourceRange(NoteLoc, NoteLoc);
12200 }
12201 } else if (!AtomicBody->isInstantiationDependent()) {
12202 ErrorFound = NotABinaryOrUnaryExpression;
12203 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
12204 NoteRange = ErrorRange = AtomicBody->getSourceRange();
12205 } else if (AtomicBody->containsErrors()) {
12206 ErrorFound = NotAValidExpression;
12207 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
12208 NoteRange = ErrorRange = AtomicBody->getSourceRange();
12209 }
12210 } else {
12211 ErrorFound = NotAScalarType;
12212 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
12213 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12214 }
12215 } else {
12216 ErrorFound = NotAnExpression;
12217 NoteLoc = ErrorLoc = S->getBeginLoc();
12218 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12219 }
12220 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
12221 SemaRef.Diag(Loc: ErrorLoc, DiagID: DiagId) << ErrorRange;
12222 SemaRef.Diag(Loc: NoteLoc, DiagID: NoteId) << ErrorFound << NoteRange;
12223 return true;
12224 }
12225 if (SemaRef.CurContext->isDependentContext())
12226 E = X = UpdateExpr = nullptr;
12227 if (ErrorFound == NoError && E && X) {
12228 // Build an update expression of form 'OpaqueValueExpr(x) binop
12229 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
12230 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
12231 auto *OVEX = new (SemaRef.getASTContext())
12232 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
12233 auto *OVEExpr = new (SemaRef.getASTContext())
12234 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
12235 ExprResult Update =
12236 SemaRef.CreateBuiltinBinOp(OpLoc, Opc: Op, LHSExpr: IsXLHSInRHSPart ? OVEX : OVEExpr,
12237 RHSExpr: IsXLHSInRHSPart ? OVEExpr : OVEX);
12238 if (Update.isInvalid())
12239 return true;
12240 Update = SemaRef.PerformImplicitConversion(From: Update.get(), ToType: X->getType(),
12241 Action: AssignmentAction::Casting);
12242 if (Update.isInvalid())
12243 return true;
12244 UpdateExpr = Update.get();
12245 }
12246 return ErrorFound != NoError;
12247}
12248
12249/// Get the node id of the fixed point of an expression \a S.
12250llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
12251 llvm::FoldingSetNodeID Id;
12252 S->IgnoreParenImpCasts()->Profile(ID&: Id, Context, Canonical: true);
12253 return Id;
12254}
12255
12256/// Check if two expressions are same.
12257bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
12258 const Expr *RHS) {
12259 return getNodeId(Context, S: LHS) == getNodeId(Context, S: RHS);
12260}
12261
12262class OpenMPAtomicCompareChecker {
12263public:
12264 /// All kinds of errors that can occur in `atomic compare`
12265 enum ErrorTy {
12266 /// Empty compound statement.
12267 NoStmt = 0,
12268 /// More than one statement in a compound statement.
12269 MoreThanOneStmt,
12270 /// Not an assignment binary operator.
12271 NotAnAssignment,
12272 /// Not a conditional operator.
12273 NotCondOp,
12274 /// Wrong false expr. According to the spec, 'x' should be at the false
12275 /// expression of a conditional expression.
12276 WrongFalseExpr,
12277 /// The condition of a conditional expression is not a binary operator.
12278 NotABinaryOp,
12279 /// Invalid binary operator (not <, >, or ==).
12280 InvalidBinaryOp,
12281 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
12282 InvalidComparison,
12283 /// X is not a lvalue.
12284 XNotLValue,
12285 /// Not a scalar.
12286 NotScalar,
12287 /// Not an integer.
12288 NotInteger,
12289 /// 'else' statement is not expected.
12290 UnexpectedElse,
12291 /// Not an equality operator.
12292 NotEQ,
12293 /// Invalid assignment (not v == x).
12294 InvalidAssignment,
12295 /// Not if statement
12296 NotIfStmt,
12297 /// More than two statements in a compound statement.
12298 MoreThanTwoStmts,
12299 /// Not a compound statement.
12300 NotCompoundStmt,
12301 /// No else statement.
12302 NoElse,
12303 /// Not 'if (r)'.
12304 InvalidCondition,
12305 /// No error.
12306 NoError,
12307 };
12308
12309 struct ErrorInfoTy {
12310 ErrorTy Error;
12311 SourceLocation ErrorLoc;
12312 SourceRange ErrorRange;
12313 SourceLocation NoteLoc;
12314 SourceRange NoteRange;
12315 };
12316
12317 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
12318
12319 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
12320 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12321
12322 Expr *getX() const { return X; }
12323 Expr *getE() const { return E; }
12324 Expr *getD() const { return D; }
12325 Expr *getCond() const { return C; }
12326 bool isXBinopExpr() const { return IsXBinopExpr; }
12327
12328protected:
12329 /// Reference to ASTContext
12330 ASTContext &ContextRef;
12331 /// 'x' lvalue part of the source atomic expression.
12332 Expr *X = nullptr;
12333 /// 'expr' or 'e' rvalue part of the source atomic expression.
12334 Expr *E = nullptr;
12335 /// 'd' rvalue part of the source atomic expression.
12336 Expr *D = nullptr;
12337 /// 'cond' part of the source atomic expression. It is in one of the following
12338 /// forms:
12339 /// expr ordop x
12340 /// x ordop expr
12341 /// x == e
12342 /// e == x
12343 Expr *C = nullptr;
12344 /// True if the cond expr is in the form of 'x ordop expr'.
12345 bool IsXBinopExpr = true;
12346
12347 /// Check if it is a valid conditional update statement (cond-update-stmt).
12348 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
12349
12350 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
12351 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12352
12353 /// Check if all captured values have right type.
12354 bool checkType(ErrorInfoTy &ErrorInfo) const;
12355
12356 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
12357 bool ShouldBeLValue, bool ShouldBeInteger = false) {
12358 if (E->isInstantiationDependent())
12359 return true;
12360
12361 if (ShouldBeLValue && !E->isLValue()) {
12362 ErrorInfo.Error = ErrorTy::XNotLValue;
12363 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12364 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12365 return false;
12366 }
12367
12368 QualType QTy = E->getType();
12369 if (!QTy->isScalarType()) {
12370 ErrorInfo.Error = ErrorTy::NotScalar;
12371 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12372 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12373 return false;
12374 }
12375 if (ShouldBeInteger && !QTy->isIntegerType()) {
12376 ErrorInfo.Error = ErrorTy::NotInteger;
12377 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12378 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12379 return false;
12380 }
12381
12382 return true;
12383 }
12384};
12385
12386bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
12387 ErrorInfoTy &ErrorInfo) {
12388 auto *Then = S->getThen();
12389 if (auto *CS = dyn_cast<CompoundStmt>(Val: Then)) {
12390 if (CS->body_empty()) {
12391 ErrorInfo.Error = ErrorTy::NoStmt;
12392 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12393 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12394 return false;
12395 }
12396 if (CS->size() > 1) {
12397 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12398 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12399 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12400 return false;
12401 }
12402 Then = CS->body_front();
12403 }
12404
12405 auto *BO = dyn_cast<BinaryOperator>(Val: Then);
12406 if (!BO) {
12407 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12408 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12409 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12410 return false;
12411 }
12412 if (BO->getOpcode() != BO_Assign) {
12413 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12414 ErrorInfo.ErrorLoc = BO->getExprLoc();
12415 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12416 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12417 return false;
12418 }
12419
12420 X = BO->getLHS();
12421
12422 auto *Cond = dyn_cast<BinaryOperator>(Val: S->getCond());
12423 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: S->getCond());
12424 Expr *LHS = nullptr;
12425 Expr *RHS = nullptr;
12426 if (Cond) {
12427 LHS = Cond->getLHS();
12428 RHS = Cond->getRHS();
12429 } else if (Call) {
12430 LHS = Call->getArg(Arg: 0);
12431 RHS = Call->getArg(Arg: 1);
12432 } else {
12433 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12434 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12435 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12436 return false;
12437 }
12438
12439 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12440 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12441 C = S->getCond();
12442 D = BO->getRHS();
12443 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
12444 E = RHS;
12445 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12446 E = LHS;
12447 } else {
12448 ErrorInfo.Error = ErrorTy::InvalidComparison;
12449 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12450 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12451 S->getCond()->getSourceRange();
12452 return false;
12453 }
12454 } else if ((Cond &&
12455 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12456 (Call &&
12457 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12458 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12459 E = BO->getRHS();
12460 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS) &&
12461 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS)) {
12462 C = S->getCond();
12463 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: LHS) &&
12464 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12465 C = S->getCond();
12466 IsXBinopExpr = false;
12467 } else {
12468 ErrorInfo.Error = ErrorTy::InvalidComparison;
12469 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12470 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12471 S->getCond()->getSourceRange();
12472 return false;
12473 }
12474 } else {
12475 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12476 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12477 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12478 return false;
12479 }
12480
12481 if (S->getElse()) {
12482 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12483 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12484 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12485 return false;
12486 }
12487
12488 return true;
12489}
12490
12491bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12492 ErrorInfoTy &ErrorInfo) {
12493 auto *BO = dyn_cast<BinaryOperator>(Val: S);
12494 if (!BO) {
12495 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12496 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12497 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12498 return false;
12499 }
12500 if (BO->getOpcode() != BO_Assign) {
12501 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12502 ErrorInfo.ErrorLoc = BO->getExprLoc();
12503 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12504 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12505 return false;
12506 }
12507
12508 X = BO->getLHS();
12509
12510 auto *CO = dyn_cast<ConditionalOperator>(Val: BO->getRHS()->IgnoreParenImpCasts());
12511 if (!CO) {
12512 ErrorInfo.Error = ErrorTy::NotCondOp;
12513 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12514 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12515 return false;
12516 }
12517
12518 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: CO->getFalseExpr())) {
12519 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12520 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12521 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12522 CO->getFalseExpr()->getSourceRange();
12523 return false;
12524 }
12525
12526 auto *Cond = dyn_cast<BinaryOperator>(Val: CO->getCond());
12527 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: CO->getCond());
12528 Expr *LHS = nullptr;
12529 Expr *RHS = nullptr;
12530 if (Cond) {
12531 LHS = Cond->getLHS();
12532 RHS = Cond->getRHS();
12533 } else if (Call) {
12534 LHS = Call->getArg(Arg: 0);
12535 RHS = Call->getArg(Arg: 1);
12536 } else {
12537 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12538 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12539 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12540 CO->getCond()->getSourceRange();
12541 return false;
12542 }
12543
12544 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12545 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12546 C = CO->getCond();
12547 D = CO->getTrueExpr();
12548 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
12549 E = RHS;
12550 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12551 E = LHS;
12552 } else {
12553 ErrorInfo.Error = ErrorTy::InvalidComparison;
12554 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12555 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12556 CO->getCond()->getSourceRange();
12557 return false;
12558 }
12559 } else if ((Cond &&
12560 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12561 (Call &&
12562 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12563 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12564
12565 E = CO->getTrueExpr();
12566 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS) &&
12567 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS)) {
12568 C = CO->getCond();
12569 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: LHS) &&
12570 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12571 C = CO->getCond();
12572 IsXBinopExpr = false;
12573 } else {
12574 ErrorInfo.Error = ErrorTy::InvalidComparison;
12575 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12576 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12577 CO->getCond()->getSourceRange();
12578 return false;
12579 }
12580 } else {
12581 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12582 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12583 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12584 CO->getCond()->getSourceRange();
12585 return false;
12586 }
12587
12588 return true;
12589}
12590
12591bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12592 // 'x' and 'e' cannot be nullptr
12593 assert(X && E && "X and E cannot be nullptr");
12594
12595 if (!CheckValue(E: X, ErrorInfo, ShouldBeLValue: true))
12596 return false;
12597
12598 if (!CheckValue(E, ErrorInfo, ShouldBeLValue: false))
12599 return false;
12600
12601 if (D && !CheckValue(E: D, ErrorInfo, ShouldBeLValue: false))
12602 return false;
12603
12604 return true;
12605}
12606
12607bool OpenMPAtomicCompareChecker::checkStmt(
12608 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12609 auto *CS = dyn_cast<CompoundStmt>(Val: S);
12610 if (CS) {
12611 if (CS->body_empty()) {
12612 ErrorInfo.Error = ErrorTy::NoStmt;
12613 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12614 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12615 return false;
12616 }
12617
12618 if (CS->size() != 1) {
12619 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12620 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12621 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12622 return false;
12623 }
12624 S = CS->body_front();
12625 }
12626
12627 auto Res = false;
12628
12629 if (auto *IS = dyn_cast<IfStmt>(Val: S)) {
12630 // Check if the statement is in one of the following forms
12631 // (cond-update-stmt):
12632 // if (expr ordop x) { x = expr; }
12633 // if (x ordop expr) { x = expr; }
12634 // if (x == e) { x = d; }
12635 Res = checkCondUpdateStmt(S: IS, ErrorInfo);
12636 } else {
12637 // Check if the statement is in one of the following forms (cond-expr-stmt):
12638 // x = expr ordop x ? expr : x;
12639 // x = x ordop expr ? expr : x;
12640 // x = x == e ? d : x;
12641 Res = checkCondExprStmt(S, ErrorInfo);
12642 }
12643
12644 if (!Res)
12645 return false;
12646
12647 return checkType(ErrorInfo);
12648}
12649
12650class OpenMPAtomicCompareCaptureChecker final
12651 : public OpenMPAtomicCompareChecker {
12652public:
12653 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12654
12655 Expr *getV() const { return V; }
12656 Expr *getR() const { return R; }
12657 bool isFailOnly() const { return IsFailOnly; }
12658 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12659
12660 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12661 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12662
12663private:
12664 bool checkType(ErrorInfoTy &ErrorInfo);
12665
12666 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12667 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12668 // spec p.p. 82:
12669 // (1) { v = x; cond-update-stmt }
12670 // (2) { cond-update-stmt v = x; }
12671 // (3) if(x == e) { x = d; } else { v = x; }
12672 // (4) { r = x == e; if(r) { x = d; } }
12673 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12674
12675 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12676 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12677
12678 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12679 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12680 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12681
12682 /// 'v' lvalue part of the source atomic expression.
12683 Expr *V = nullptr;
12684 /// 'r' lvalue part of the source atomic expression.
12685 Expr *R = nullptr;
12686 /// If 'v' is only updated when the comparison fails.
12687 bool IsFailOnly = false;
12688 /// If original value of 'x' must be stored in 'v', not an updated one.
12689 bool IsPostfixUpdate = false;
12690};
12691
12692bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12693 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12694 return false;
12695
12696 if (V && !CheckValue(E: V, ErrorInfo, ShouldBeLValue: true))
12697 return false;
12698
12699 if (R && !CheckValue(E: R, ErrorInfo, ShouldBeLValue: true, ShouldBeInteger: true))
12700 return false;
12701
12702 return true;
12703}
12704
12705bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12706 ErrorInfoTy &ErrorInfo) {
12707 IsFailOnly = true;
12708
12709 auto *Then = S->getThen();
12710 if (auto *CS = dyn_cast<CompoundStmt>(Val: Then)) {
12711 if (CS->body_empty()) {
12712 ErrorInfo.Error = ErrorTy::NoStmt;
12713 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12714 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12715 return false;
12716 }
12717 if (CS->size() > 1) {
12718 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12719 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12720 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12721 return false;
12722 }
12723 Then = CS->body_front();
12724 }
12725
12726 auto *BO = dyn_cast<BinaryOperator>(Val: Then);
12727 if (!BO) {
12728 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12729 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12730 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12731 return false;
12732 }
12733 if (BO->getOpcode() != BO_Assign) {
12734 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12735 ErrorInfo.ErrorLoc = BO->getExprLoc();
12736 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12737 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12738 return false;
12739 }
12740
12741 X = BO->getLHS();
12742 D = BO->getRHS();
12743
12744 auto *Cond = dyn_cast<BinaryOperator>(Val: S->getCond());
12745 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: S->getCond());
12746 Expr *LHS = nullptr;
12747 Expr *RHS = nullptr;
12748 if (Cond) {
12749 LHS = Cond->getLHS();
12750 RHS = Cond->getRHS();
12751 } else if (Call) {
12752 LHS = Call->getArg(Arg: 0);
12753 RHS = Call->getArg(Arg: 1);
12754 } else {
12755 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12756 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12757 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12758 return false;
12759 }
12760 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12761 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12762 ErrorInfo.Error = ErrorTy::NotEQ;
12763 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12764 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12765 return false;
12766 }
12767
12768 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
12769 E = RHS;
12770 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12771 E = LHS;
12772 } else {
12773 ErrorInfo.Error = ErrorTy::InvalidComparison;
12774 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12775 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12776 return false;
12777 }
12778
12779 C = S->getCond();
12780
12781 if (!S->getElse()) {
12782 ErrorInfo.Error = ErrorTy::NoElse;
12783 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12784 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12785 return false;
12786 }
12787
12788 auto *Else = S->getElse();
12789 if (auto *CS = dyn_cast<CompoundStmt>(Val: Else)) {
12790 if (CS->body_empty()) {
12791 ErrorInfo.Error = ErrorTy::NoStmt;
12792 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12793 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12794 return false;
12795 }
12796 if (CS->size() > 1) {
12797 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12798 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12799 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12800 return false;
12801 }
12802 Else = CS->body_front();
12803 }
12804
12805 auto *ElseBO = dyn_cast<BinaryOperator>(Val: Else);
12806 if (!ElseBO) {
12807 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12808 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12809 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12810 return false;
12811 }
12812 if (ElseBO->getOpcode() != BO_Assign) {
12813 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12814 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12815 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12816 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12817 return false;
12818 }
12819
12820 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: ElseBO->getRHS())) {
12821 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12822 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12823 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12824 ElseBO->getRHS()->getSourceRange();
12825 return false;
12826 }
12827
12828 V = ElseBO->getLHS();
12829
12830 return checkType(ErrorInfo);
12831}
12832
12833bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12834 ErrorInfoTy &ErrorInfo) {
12835 // We don't check here as they should be already done before call this
12836 // function.
12837 auto *CS = cast<CompoundStmt>(Val: S);
12838 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12839 auto *S1 = cast<BinaryOperator>(Val: CS->body_front());
12840 auto *S2 = cast<IfStmt>(Val: CS->body_back());
12841 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12842
12843 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: S1->getLHS(), RHS: S2->getCond())) {
12844 ErrorInfo.Error = ErrorTy::InvalidCondition;
12845 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12846 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12847 return false;
12848 }
12849
12850 R = S1->getLHS();
12851
12852 auto *Then = S2->getThen();
12853 if (auto *ThenCS = dyn_cast<CompoundStmt>(Val: Then)) {
12854 if (ThenCS->body_empty()) {
12855 ErrorInfo.Error = ErrorTy::NoStmt;
12856 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12857 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12858 return false;
12859 }
12860 if (ThenCS->size() > 1) {
12861 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12862 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12863 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12864 return false;
12865 }
12866 Then = ThenCS->body_front();
12867 }
12868
12869 auto *ThenBO = dyn_cast<BinaryOperator>(Val: Then);
12870 if (!ThenBO) {
12871 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12872 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12873 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12874 return false;
12875 }
12876 if (ThenBO->getOpcode() != BO_Assign) {
12877 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12878 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12879 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12880 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12881 return false;
12882 }
12883
12884 X = ThenBO->getLHS();
12885 D = ThenBO->getRHS();
12886
12887 auto *BO = cast<BinaryOperator>(Val: S1->getRHS()->IgnoreImpCasts());
12888 if (BO->getOpcode() != BO_EQ) {
12889 ErrorInfo.Error = ErrorTy::NotEQ;
12890 ErrorInfo.ErrorLoc = BO->getExprLoc();
12891 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12892 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12893 return false;
12894 }
12895
12896 C = BO;
12897
12898 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: BO->getLHS())) {
12899 E = BO->getRHS();
12900 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: BO->getRHS())) {
12901 E = BO->getLHS();
12902 } else {
12903 ErrorInfo.Error = ErrorTy::InvalidComparison;
12904 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12905 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12906 return false;
12907 }
12908
12909 if (S2->getElse()) {
12910 IsFailOnly = true;
12911
12912 auto *Else = S2->getElse();
12913 if (auto *ElseCS = dyn_cast<CompoundStmt>(Val: Else)) {
12914 if (ElseCS->body_empty()) {
12915 ErrorInfo.Error = ErrorTy::NoStmt;
12916 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12917 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12918 return false;
12919 }
12920 if (ElseCS->size() > 1) {
12921 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12922 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12923 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12924 return false;
12925 }
12926 Else = ElseCS->body_front();
12927 }
12928
12929 auto *ElseBO = dyn_cast<BinaryOperator>(Val: Else);
12930 if (!ElseBO) {
12931 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12932 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12933 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12934 return false;
12935 }
12936 if (ElseBO->getOpcode() != BO_Assign) {
12937 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12938 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12939 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12940 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12941 return false;
12942 }
12943 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: ElseBO->getRHS())) {
12944 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12945 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12946 ErrorInfo.NoteLoc = X->getExprLoc();
12947 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12948 ErrorInfo.NoteRange = X->getSourceRange();
12949 return false;
12950 }
12951
12952 V = ElseBO->getLHS();
12953 }
12954
12955 return checkType(ErrorInfo);
12956}
12957
12958bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12959 ErrorInfoTy &ErrorInfo) {
12960 // if(x == e) { x = d; } else { v = x; }
12961 if (auto *IS = dyn_cast<IfStmt>(Val: S))
12962 return checkForm3(S: IS, ErrorInfo);
12963
12964 auto *CS = dyn_cast<CompoundStmt>(Val: S);
12965 if (!CS) {
12966 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12967 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12968 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12969 return false;
12970 }
12971 if (CS->body_empty()) {
12972 ErrorInfo.Error = ErrorTy::NoStmt;
12973 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12974 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12975 return false;
12976 }
12977
12978 // { if(x == e) { x = d; } else { v = x; } }
12979 if (CS->size() == 1) {
12980 auto *IS = dyn_cast<IfStmt>(Val: CS->body_front());
12981 if (!IS) {
12982 ErrorInfo.Error = ErrorTy::NotIfStmt;
12983 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12984 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12985 CS->body_front()->getSourceRange();
12986 return false;
12987 }
12988
12989 return checkForm3(S: IS, ErrorInfo);
12990 } else if (CS->size() == 2) {
12991 auto *S1 = CS->body_front();
12992 auto *S2 = CS->body_back();
12993
12994 Stmt *UpdateStmt = nullptr;
12995 Stmt *CondUpdateStmt = nullptr;
12996 Stmt *CondExprStmt = nullptr;
12997
12998 if (auto *BO = dyn_cast<BinaryOperator>(Val: S1)) {
12999 // It could be one of the following cases:
13000 // { v = x; cond-update-stmt }
13001 // { v = x; cond-expr-stmt }
13002 // { cond-expr-stmt; v = x; }
13003 // form 45
13004 if (isa<BinaryOperator>(Val: BO->getRHS()->IgnoreImpCasts()) ||
13005 isa<ConditionalOperator>(Val: BO->getRHS()->IgnoreImpCasts())) {
13006 // check if form 45
13007 if (isa<IfStmt>(Val: S2))
13008 return checkForm45(S: CS, ErrorInfo);
13009 // { cond-expr-stmt; v = x; }
13010 CondExprStmt = S1;
13011 UpdateStmt = S2;
13012 } else {
13013 IsPostfixUpdate = true;
13014 UpdateStmt = S1;
13015 if (isa<IfStmt>(Val: S2)) {
13016 // { v = x; cond-update-stmt }
13017 CondUpdateStmt = S2;
13018 } else {
13019 // { v = x; cond-expr-stmt }
13020 CondExprStmt = S2;
13021 }
13022 }
13023 } else {
13024 // { cond-update-stmt v = x; }
13025 UpdateStmt = S2;
13026 CondUpdateStmt = S1;
13027 }
13028
13029 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
13030 auto *IS = dyn_cast<IfStmt>(Val: CUS);
13031 if (!IS) {
13032 ErrorInfo.Error = ErrorTy::NotIfStmt;
13033 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
13034 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
13035 return false;
13036 }
13037
13038 return checkCondUpdateStmt(S: IS, ErrorInfo);
13039 };
13040
13041 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
13042 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
13043 auto *BO = dyn_cast<BinaryOperator>(Val: US);
13044 if (!BO) {
13045 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13046 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
13047 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
13048 return false;
13049 }
13050 if (BO->getOpcode() != BO_Assign) {
13051 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13052 ErrorInfo.ErrorLoc = BO->getExprLoc();
13053 ErrorInfo.NoteLoc = BO->getOperatorLoc();
13054 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13055 return false;
13056 }
13057 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: this->X, RHS: BO->getRHS())) {
13058 ErrorInfo.Error = ErrorTy::InvalidAssignment;
13059 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
13060 ErrorInfo.NoteLoc = this->X->getExprLoc();
13061 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
13062 ErrorInfo.NoteRange = this->X->getSourceRange();
13063 return false;
13064 }
13065
13066 this->V = BO->getLHS();
13067
13068 return true;
13069 };
13070
13071 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
13072 return false;
13073 if (CondExprStmt && !checkCondExprStmt(S: CondExprStmt, ErrorInfo))
13074 return false;
13075 if (!CheckUpdateStmt(UpdateStmt))
13076 return false;
13077 } else {
13078 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
13079 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13080 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13081 return false;
13082 }
13083
13084 return checkType(ErrorInfo);
13085}
13086} // namespace
13087
13088StmtResult SemaOpenMP::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
13089 Stmt *AStmt,
13090 SourceLocation StartLoc,
13091 SourceLocation EndLoc) {
13092 ASTContext &Context = getASTContext();
13093 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
13094 // Register location of the first atomic directive.
13095 DSAStack->addAtomicDirectiveLoc(Loc: StartLoc);
13096 if (!AStmt)
13097 return StmtError();
13098
13099 // 1.2.2 OpenMP Language Terminology
13100 // Structured block - An executable statement with a single entry at the
13101 // top and a single exit at the bottom.
13102 // The point of exit cannot be a branch out of the structured block.
13103 // longjmp() and throw() must not violate the entry/exit criteria.
13104 OpenMPClauseKind AtomicKind = OMPC_unknown;
13105 SourceLocation AtomicKindLoc;
13106 OpenMPClauseKind MemOrderKind = OMPC_unknown;
13107 SourceLocation MemOrderLoc;
13108 bool MutexClauseEncountered = false;
13109 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
13110 for (const OMPClause *C : Clauses) {
13111 switch (C->getClauseKind()) {
13112 case OMPC_read:
13113 case OMPC_write:
13114 case OMPC_update:
13115 MutexClauseEncountered = true;
13116 [[fallthrough]];
13117 case OMPC_capture:
13118 case OMPC_compare: {
13119 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
13120 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_several_clauses)
13121 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13122 Diag(Loc: AtomicKindLoc, DiagID: diag::note_omp_previous_mem_order_clause)
13123 << getOpenMPClauseNameForDiag(C: AtomicKind);
13124 } else {
13125 AtomicKind = C->getClauseKind();
13126 AtomicKindLoc = C->getBeginLoc();
13127 if (!EncounteredAtomicKinds.insert(V: C->getClauseKind()).second) {
13128 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_several_clauses)
13129 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13130 Diag(Loc: AtomicKindLoc, DiagID: diag::note_omp_previous_mem_order_clause)
13131 << getOpenMPClauseNameForDiag(C: AtomicKind);
13132 }
13133 }
13134 break;
13135 }
13136 case OMPC_weak:
13137 case OMPC_fail: {
13138 if (!EncounteredAtomicKinds.contains(V: OMPC_compare)) {
13139 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_no_compare)
13140 << getOpenMPClauseNameForDiag(C: C->getClauseKind())
13141 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13142 return StmtError();
13143 }
13144 break;
13145 }
13146 case OMPC_seq_cst:
13147 case OMPC_acq_rel:
13148 case OMPC_acquire:
13149 case OMPC_release:
13150 case OMPC_relaxed: {
13151 if (MemOrderKind != OMPC_unknown) {
13152 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_several_mem_order_clauses)
13153 << getOpenMPDirectiveName(D: OMPD_atomic, V: OMPVersion) << 0
13154 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13155 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
13156 << getOpenMPClauseNameForDiag(C: MemOrderKind);
13157 } else {
13158 MemOrderKind = C->getClauseKind();
13159 MemOrderLoc = C->getBeginLoc();
13160 }
13161 break;
13162 }
13163 // The following clauses are allowed, but we don't need to do anything here.
13164 case OMPC_hint:
13165 break;
13166 default:
13167 llvm_unreachable("unknown clause is encountered");
13168 }
13169 }
13170 bool IsCompareCapture = false;
13171 if (EncounteredAtomicKinds.contains(V: OMPC_compare) &&
13172 EncounteredAtomicKinds.contains(V: OMPC_capture)) {
13173 IsCompareCapture = true;
13174 AtomicKind = OMPC_compare;
13175 }
13176 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
13177 // If atomic-clause is read then memory-order-clause must not be acq_rel or
13178 // release.
13179 // If atomic-clause is write then memory-order-clause must not be acq_rel or
13180 // acquire.
13181 // If atomic-clause is update or not present then memory-order-clause must not
13182 // be acq_rel or acquire.
13183 if ((AtomicKind == OMPC_read &&
13184 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
13185 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
13186 AtomicKind == OMPC_unknown) &&
13187 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
13188 SourceLocation Loc = AtomicKindLoc;
13189 if (AtomicKind == OMPC_unknown)
13190 Loc = StartLoc;
13191 Diag(Loc, DiagID: diag::err_omp_atomic_incompatible_mem_order_clause)
13192 << getOpenMPClauseNameForDiag(C: AtomicKind)
13193 << (AtomicKind == OMPC_unknown ? 1 : 0)
13194 << getOpenMPClauseNameForDiag(C: MemOrderKind);
13195 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
13196 << getOpenMPClauseNameForDiag(C: MemOrderKind);
13197 }
13198
13199 Stmt *Body = AStmt;
13200 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: Body))
13201 Body = EWC->getSubExpr();
13202
13203 Expr *X = nullptr;
13204 Expr *V = nullptr;
13205 Expr *E = nullptr;
13206 Expr *UE = nullptr;
13207 Expr *D = nullptr;
13208 Expr *CE = nullptr;
13209 Expr *R = nullptr;
13210 bool IsXLHSInRHSPart = false;
13211 bool IsPostfixUpdate = false;
13212 bool IsFailOnly = false;
13213 // OpenMP [2.12.6, atomic Construct]
13214 // In the next expressions:
13215 // * x and v (as applicable) are both l-value expressions with scalar type.
13216 // * During the execution of an atomic region, multiple syntactic
13217 // occurrences of x must designate the same storage location.
13218 // * Neither of v and expr (as applicable) may access the storage location
13219 // designated by x.
13220 // * Neither of x and expr (as applicable) may access the storage location
13221 // designated by v.
13222 // * expr is an expression with scalar type.
13223 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
13224 // * binop, binop=, ++, and -- are not overloaded operators.
13225 // * The expression x binop expr must be numerically equivalent to x binop
13226 // (expr). This requirement is satisfied if the operators in expr have
13227 // precedence greater than binop, or by using parentheses around expr or
13228 // subexpressions of expr.
13229 // * The expression expr binop x must be numerically equivalent to (expr)
13230 // binop x. This requirement is satisfied if the operators in expr have
13231 // precedence equal to or greater than binop, or by using parentheses around
13232 // expr or subexpressions of expr.
13233 // * For forms that allow multiple occurrences of x, the number of times
13234 // that x is evaluated is unspecified.
13235 if (AtomicKind == OMPC_read) {
13236 enum {
13237 NotAnExpression,
13238 NotAnAssignmentOp,
13239 NotAScalarType,
13240 NotAnLValue,
13241 NoError
13242 } ErrorFound = NoError;
13243 SourceLocation ErrorLoc, NoteLoc;
13244 SourceRange ErrorRange, NoteRange;
13245 // If clause is read:
13246 // v = x;
13247 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
13248 const auto *AtomicBinOp =
13249 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
13250 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13251 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
13252 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
13253 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
13254 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
13255 if (!X->isLValue() || !V->isLValue()) {
13256 const Expr *NotLValueExpr = X->isLValue() ? V : X;
13257 ErrorFound = NotAnLValue;
13258 ErrorLoc = AtomicBinOp->getExprLoc();
13259 ErrorRange = AtomicBinOp->getSourceRange();
13260 NoteLoc = NotLValueExpr->getExprLoc();
13261 NoteRange = NotLValueExpr->getSourceRange();
13262 }
13263 } else if (!X->isInstantiationDependent() ||
13264 !V->isInstantiationDependent()) {
13265 const Expr *NotScalarExpr =
13266 (X->isInstantiationDependent() || X->getType()->isScalarType())
13267 ? V
13268 : X;
13269 ErrorFound = NotAScalarType;
13270 ErrorLoc = AtomicBinOp->getExprLoc();
13271 ErrorRange = AtomicBinOp->getSourceRange();
13272 NoteLoc = NotScalarExpr->getExprLoc();
13273 NoteRange = NotScalarExpr->getSourceRange();
13274 }
13275 } else if (!AtomicBody->isInstantiationDependent()) {
13276 ErrorFound = NotAnAssignmentOp;
13277 ErrorLoc = AtomicBody->getExprLoc();
13278 ErrorRange = AtomicBody->getSourceRange();
13279 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13280 : AtomicBody->getExprLoc();
13281 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13282 : AtomicBody->getSourceRange();
13283 }
13284 } else {
13285 ErrorFound = NotAnExpression;
13286 NoteLoc = ErrorLoc = Body->getBeginLoc();
13287 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
13288 }
13289 if (ErrorFound != NoError) {
13290 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_read_not_expression_statement)
13291 << ErrorRange;
13292 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_read_write)
13293 << ErrorFound << NoteRange;
13294 return StmtError();
13295 }
13296 if (SemaRef.CurContext->isDependentContext())
13297 V = X = nullptr;
13298 } else if (AtomicKind == OMPC_write) {
13299 enum {
13300 NotAnExpression,
13301 NotAnAssignmentOp,
13302 NotAScalarType,
13303 NotAnLValue,
13304 NoError
13305 } ErrorFound = NoError;
13306 SourceLocation ErrorLoc, NoteLoc;
13307 SourceRange ErrorRange, NoteRange;
13308 // If clause is write:
13309 // x = expr;
13310 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
13311 const auto *AtomicBinOp =
13312 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
13313 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13314 X = AtomicBinOp->getLHS();
13315 E = AtomicBinOp->getRHS();
13316 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
13317 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
13318 if (!X->isLValue()) {
13319 ErrorFound = NotAnLValue;
13320 ErrorLoc = AtomicBinOp->getExprLoc();
13321 ErrorRange = AtomicBinOp->getSourceRange();
13322 NoteLoc = X->getExprLoc();
13323 NoteRange = X->getSourceRange();
13324 }
13325 } else if (!X->isInstantiationDependent() ||
13326 !E->isInstantiationDependent()) {
13327 const Expr *NotScalarExpr =
13328 (X->isInstantiationDependent() || X->getType()->isScalarType())
13329 ? E
13330 : X;
13331 ErrorFound = NotAScalarType;
13332 ErrorLoc = AtomicBinOp->getExprLoc();
13333 ErrorRange = AtomicBinOp->getSourceRange();
13334 NoteLoc = NotScalarExpr->getExprLoc();
13335 NoteRange = NotScalarExpr->getSourceRange();
13336 }
13337 } else if (!AtomicBody->isInstantiationDependent()) {
13338 ErrorFound = NotAnAssignmentOp;
13339 ErrorLoc = AtomicBody->getExprLoc();
13340 ErrorRange = AtomicBody->getSourceRange();
13341 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13342 : AtomicBody->getExprLoc();
13343 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13344 : AtomicBody->getSourceRange();
13345 }
13346 } else {
13347 ErrorFound = NotAnExpression;
13348 NoteLoc = ErrorLoc = Body->getBeginLoc();
13349 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
13350 }
13351 if (ErrorFound != NoError) {
13352 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_write_not_expression_statement)
13353 << ErrorRange;
13354 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_read_write)
13355 << ErrorFound << NoteRange;
13356 return StmtError();
13357 }
13358 if (SemaRef.CurContext->isDependentContext())
13359 E = X = nullptr;
13360 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
13361 // If clause is update:
13362 // x++;
13363 // x--;
13364 // ++x;
13365 // --x;
13366 // x binop= expr;
13367 // x = x binop expr;
13368 // x = expr binop x;
13369 OpenMPAtomicUpdateChecker Checker(SemaRef);
13370 if (Checker.checkStatement(
13371 S: Body,
13372 DiagId: (AtomicKind == OMPC_update)
13373 ? diag::err_omp_atomic_update_not_expression_statement
13374 : diag::err_omp_atomic_not_expression_statement,
13375 NoteId: diag::note_omp_atomic_update))
13376 return StmtError();
13377 if (!SemaRef.CurContext->isDependentContext()) {
13378 E = Checker.getExpr();
13379 X = Checker.getX();
13380 UE = Checker.getUpdateExpr();
13381 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13382 }
13383 } else if (AtomicKind == OMPC_capture) {
13384 enum {
13385 NotAnAssignmentOp,
13386 NotACompoundStatement,
13387 NotTwoSubstatements,
13388 NotASpecificExpression,
13389 NoError
13390 } ErrorFound = NoError;
13391 SourceLocation ErrorLoc, NoteLoc;
13392 SourceRange ErrorRange, NoteRange;
13393 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
13394 // If clause is a capture:
13395 // v = x++;
13396 // v = x--;
13397 // v = ++x;
13398 // v = --x;
13399 // v = x binop= expr;
13400 // v = x = x binop expr;
13401 // v = x = expr binop x;
13402 const auto *AtomicBinOp =
13403 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
13404 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13405 V = AtomicBinOp->getLHS();
13406 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
13407 OpenMPAtomicUpdateChecker Checker(SemaRef);
13408 if (Checker.checkStatement(
13409 S: Body, DiagId: diag::err_omp_atomic_capture_not_expression_statement,
13410 NoteId: diag::note_omp_atomic_update))
13411 return StmtError();
13412 E = Checker.getExpr();
13413 X = Checker.getX();
13414 UE = Checker.getUpdateExpr();
13415 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13416 IsPostfixUpdate = Checker.isPostfixUpdate();
13417 } else if (!AtomicBody->isInstantiationDependent()) {
13418 ErrorLoc = AtomicBody->getExprLoc();
13419 ErrorRange = AtomicBody->getSourceRange();
13420 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13421 : AtomicBody->getExprLoc();
13422 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13423 : AtomicBody->getSourceRange();
13424 ErrorFound = NotAnAssignmentOp;
13425 }
13426 if (ErrorFound != NoError) {
13427 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_capture_not_expression_statement)
13428 << ErrorRange;
13429 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13430 return StmtError();
13431 }
13432 if (SemaRef.CurContext->isDependentContext())
13433 UE = V = E = X = nullptr;
13434 } else {
13435 // If clause is a capture:
13436 // { v = x; x = expr; }
13437 // { v = x; x++; }
13438 // { v = x; x--; }
13439 // { v = x; ++x; }
13440 // { v = x; --x; }
13441 // { v = x; x binop= expr; }
13442 // { v = x; x = x binop expr; }
13443 // { v = x; x = expr binop x; }
13444 // { x++; v = x; }
13445 // { x--; v = x; }
13446 // { ++x; v = x; }
13447 // { --x; v = x; }
13448 // { x binop= expr; v = x; }
13449 // { x = x binop expr; v = x; }
13450 // { x = expr binop x; v = x; }
13451 if (auto *CS = dyn_cast<CompoundStmt>(Val: Body)) {
13452 // Check that this is { expr1; expr2; }
13453 if (CS->size() == 2) {
13454 Stmt *First = CS->body_front();
13455 Stmt *Second = CS->body_back();
13456 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: First))
13457 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13458 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: Second))
13459 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13460 // Need to find what subexpression is 'v' and what is 'x'.
13461 OpenMPAtomicUpdateChecker Checker(SemaRef);
13462 bool IsUpdateExprFound = !Checker.checkStatement(S: Second);
13463 BinaryOperator *BinOp = nullptr;
13464 if (IsUpdateExprFound) {
13465 BinOp = dyn_cast<BinaryOperator>(Val: First);
13466 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13467 }
13468 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
13469 // { v = x; x++; }
13470 // { v = x; x--; }
13471 // { v = x; ++x; }
13472 // { v = x; --x; }
13473 // { v = x; x binop= expr; }
13474 // { v = x; x = x binop expr; }
13475 // { v = x; x = expr binop x; }
13476 // Check that the first expression has form v = x.
13477 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13478 llvm::FoldingSetNodeID XId, PossibleXId;
13479 Checker.getX()->Profile(ID&: XId, Context, /*Canonical=*/true);
13480 PossibleX->Profile(ID&: PossibleXId, Context, /*Canonical=*/true);
13481 IsUpdateExprFound = XId == PossibleXId;
13482 if (IsUpdateExprFound) {
13483 V = BinOp->getLHS();
13484 X = Checker.getX();
13485 E = Checker.getExpr();
13486 UE = Checker.getUpdateExpr();
13487 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13488 IsPostfixUpdate = true;
13489 }
13490 }
13491 if (!IsUpdateExprFound) {
13492 IsUpdateExprFound = !Checker.checkStatement(S: First);
13493 BinOp = nullptr;
13494 if (IsUpdateExprFound) {
13495 BinOp = dyn_cast<BinaryOperator>(Val: Second);
13496 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13497 }
13498 if (IsUpdateExprFound &&
13499 !SemaRef.CurContext->isDependentContext()) {
13500 // { x++; v = x; }
13501 // { x--; v = x; }
13502 // { ++x; v = x; }
13503 // { --x; v = x; }
13504 // { x binop= expr; v = x; }
13505 // { x = x binop expr; v = x; }
13506 // { x = expr binop x; v = x; }
13507 // Check that the second expression has form v = x.
13508 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13509 llvm::FoldingSetNodeID XId, PossibleXId;
13510 Checker.getX()->Profile(ID&: XId, Context, /*Canonical=*/true);
13511 PossibleX->Profile(ID&: PossibleXId, Context, /*Canonical=*/true);
13512 IsUpdateExprFound = XId == PossibleXId;
13513 if (IsUpdateExprFound) {
13514 V = BinOp->getLHS();
13515 X = Checker.getX();
13516 E = Checker.getExpr();
13517 UE = Checker.getUpdateExpr();
13518 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13519 IsPostfixUpdate = false;
13520 }
13521 }
13522 }
13523 if (!IsUpdateExprFound) {
13524 // { v = x; x = expr; }
13525 auto *FirstExpr = dyn_cast<Expr>(Val: First);
13526 auto *SecondExpr = dyn_cast<Expr>(Val: Second);
13527 if (!FirstExpr || !SecondExpr ||
13528 !(FirstExpr->isInstantiationDependent() ||
13529 SecondExpr->isInstantiationDependent())) {
13530 auto *FirstBinOp = dyn_cast<BinaryOperator>(Val: First);
13531 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13532 ErrorFound = NotAnAssignmentOp;
13533 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13534 : First->getBeginLoc();
13535 NoteRange = ErrorRange = FirstBinOp
13536 ? FirstBinOp->getSourceRange()
13537 : SourceRange(ErrorLoc, ErrorLoc);
13538 } else {
13539 auto *SecondBinOp = dyn_cast<BinaryOperator>(Val: Second);
13540 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13541 ErrorFound = NotAnAssignmentOp;
13542 NoteLoc = ErrorLoc = SecondBinOp
13543 ? SecondBinOp->getOperatorLoc()
13544 : Second->getBeginLoc();
13545 NoteRange = ErrorRange =
13546 SecondBinOp ? SecondBinOp->getSourceRange()
13547 : SourceRange(ErrorLoc, ErrorLoc);
13548 } else {
13549 Expr *PossibleXRHSInFirst =
13550 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13551 Expr *PossibleXLHSInSecond =
13552 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13553 llvm::FoldingSetNodeID X1Id, X2Id;
13554 PossibleXRHSInFirst->Profile(ID&: X1Id, Context,
13555 /*Canonical=*/true);
13556 PossibleXLHSInSecond->Profile(ID&: X2Id, Context,
13557 /*Canonical=*/true);
13558 IsUpdateExprFound = X1Id == X2Id;
13559 if (IsUpdateExprFound) {
13560 V = FirstBinOp->getLHS();
13561 X = SecondBinOp->getLHS();
13562 E = SecondBinOp->getRHS();
13563 UE = nullptr;
13564 IsXLHSInRHSPart = false;
13565 IsPostfixUpdate = true;
13566 } else {
13567 ErrorFound = NotASpecificExpression;
13568 ErrorLoc = FirstBinOp->getExprLoc();
13569 ErrorRange = FirstBinOp->getSourceRange();
13570 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13571 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13572 }
13573 }
13574 }
13575 }
13576 }
13577 } else {
13578 NoteLoc = ErrorLoc = Body->getBeginLoc();
13579 NoteRange = ErrorRange =
13580 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13581 ErrorFound = NotTwoSubstatements;
13582 }
13583 } else {
13584 NoteLoc = ErrorLoc = Body->getBeginLoc();
13585 NoteRange = ErrorRange =
13586 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13587 ErrorFound = NotACompoundStatement;
13588 }
13589 }
13590 if (ErrorFound != NoError) {
13591 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_capture_not_compound_statement)
13592 << ErrorRange;
13593 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13594 return StmtError();
13595 }
13596 if (SemaRef.CurContext->isDependentContext())
13597 UE = V = E = X = nullptr;
13598 } else if (AtomicKind == OMPC_compare) {
13599 if (IsCompareCapture) {
13600 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13601 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
13602 if (!Checker.checkStmt(S: Body, ErrorInfo)) {
13603 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_compare_capture)
13604 << ErrorInfo.ErrorRange;
13605 Diag(Loc: ErrorInfo.NoteLoc, DiagID: diag::note_omp_atomic_compare)
13606 << ErrorInfo.Error << ErrorInfo.NoteRange;
13607 return StmtError();
13608 }
13609 X = Checker.getX();
13610 E = Checker.getE();
13611 D = Checker.getD();
13612 CE = Checker.getCond();
13613 V = Checker.getV();
13614 R = Checker.getR();
13615 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13616 IsXLHSInRHSPart = Checker.isXBinopExpr();
13617 IsFailOnly = Checker.isFailOnly();
13618 IsPostfixUpdate = Checker.isPostfixUpdate();
13619 } else {
13620 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13621 OpenMPAtomicCompareChecker Checker(SemaRef);
13622 if (!Checker.checkStmt(S: Body, ErrorInfo)) {
13623 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_compare)
13624 << ErrorInfo.ErrorRange;
13625 Diag(Loc: ErrorInfo.NoteLoc, DiagID: diag::note_omp_atomic_compare)
13626 << ErrorInfo.Error << ErrorInfo.NoteRange;
13627 return StmtError();
13628 }
13629 X = Checker.getX();
13630 E = Checker.getE();
13631 D = Checker.getD();
13632 CE = Checker.getCond();
13633 // The weak clause may only appear if the resulting atomic operation is
13634 // an atomic conditional update for which the comparison tests for
13635 // equality. It was not possible to do this check in
13636 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13637 // could not be performed (Clauses are not available).
13638 auto *It = find_if(Range&: Clauses, P: [](OMPClause *C) {
13639 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13640 });
13641 if (It != Clauses.end()) {
13642 auto *Cond = dyn_cast<BinaryOperator>(Val: CE);
13643 if (Cond->getOpcode() != BO_EQ) {
13644 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13645 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13646 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13647 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13648
13649 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_weak_no_equality)
13650 << ErrorInfo.ErrorRange;
13651 return StmtError();
13652 }
13653 }
13654 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13655 IsXLHSInRHSPart = Checker.isXBinopExpr();
13656 }
13657 }
13658
13659 SemaRef.setFunctionHasBranchProtectedScope();
13660
13661 return OMPAtomicDirective::Create(
13662 C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
13663 Exprs: {.X: X, .V: V, .R: R, .E: E, .UE: UE, .D: D, .Cond: CE, .IsXLHSInRHSPart: IsXLHSInRHSPart, .IsPostfixUpdate: IsPostfixUpdate, .IsFailOnly: IsFailOnly});
13664}
13665
13666StmtResult SemaOpenMP::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
13667 Stmt *AStmt,
13668 SourceLocation StartLoc,
13669 SourceLocation EndLoc) {
13670 if (!AStmt)
13671 return StmtError();
13672
13673 if (validateMultidimClauses(SemaRef&: *this, Clauses))
13674 return StmtError();
13675
13676 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_target, AStmt);
13677
13678 // OpenMP [2.16, Nesting of Regions]
13679 // If specified, a teams construct must be contained within a target
13680 // construct. That target construct must contain no statements or directives
13681 // outside of the teams construct.
13682 if (DSAStack->hasInnerTeamsRegion()) {
13683 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13684 bool OMPTeamsFound = true;
13685 if (const auto *CS = dyn_cast<CompoundStmt>(Val: S)) {
13686 auto I = CS->body_begin();
13687 while (I != CS->body_end()) {
13688 const auto *OED = dyn_cast<OMPExecutableDirective>(Val: *I);
13689 bool IsTeams = OED && isOpenMPTeamsDirective(DKind: OED->getDirectiveKind());
13690 if (!IsTeams || I != CS->body_begin()) {
13691 OMPTeamsFound = false;
13692 if (IsTeams && I != CS->body_begin()) {
13693 // This is the two teams case. Since the InnerTeamsRegionLoc will
13694 // point to this second one reset the iterator to the other teams.
13695 --I;
13696 }
13697 break;
13698 }
13699 ++I;
13700 }
13701 assert(I != CS->body_end() && "Not found statement");
13702 S = *I;
13703 } else {
13704 const auto *OED = dyn_cast<OMPExecutableDirective>(Val: S);
13705 OMPTeamsFound = OED && isOpenMPTeamsDirective(DKind: OED->getDirectiveKind());
13706 }
13707 if (!OMPTeamsFound) {
13708 Diag(Loc: StartLoc, DiagID: diag::err_omp_target_contains_not_only_teams);
13709 Diag(DSAStack->getInnerTeamsRegionLoc(),
13710 DiagID: diag::note_omp_nested_teams_construct_here);
13711 Diag(Loc: S->getBeginLoc(), DiagID: diag::note_omp_nested_statement_here)
13712 << isa<OMPExecutableDirective>(Val: S);
13713 return StmtError();
13714 }
13715 }
13716
13717 return OMPTargetDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
13718 AssociatedStmt: AStmt);
13719}
13720
13721StmtResult SemaOpenMP::ActOnOpenMPTargetParallelDirective(
13722 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13723 SourceLocation EndLoc) {
13724 if (!AStmt)
13725 return StmtError();
13726
13727 if (validateMultidimClauses(SemaRef&: *this, Clauses))
13728 return StmtError();
13729
13730 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel, AStmt);
13731
13732 return OMPTargetParallelDirective::Create(
13733 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
13734 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13735}
13736
13737StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForDirective(
13738 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13739 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13740 if (!AStmt)
13741 return StmtError();
13742
13743 if (validateMultidimClauses(SemaRef&: *this, Clauses))
13744 return StmtError();
13745
13746 CapturedStmt *CS =
13747 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_for, AStmt);
13748
13749 OMPLoopBasedDirective::HelperExprs B;
13750 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13751 // define the nested loops number.
13752 unsigned NestedLoopCount =
13753 checkOpenMPLoop(DKind: OMPD_target_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13754 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
13755 VarsWithImplicitDSA, Built&: B);
13756 if (NestedLoopCount == 0)
13757 return StmtError();
13758
13759 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13760 return StmtError();
13761
13762 return OMPTargetParallelForDirective::Create(
13763 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13764 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13765}
13766
13767/// Check for existence of a map clause in the list of clauses.
13768static bool hasClauses(ArrayRef<OMPClause *> Clauses,
13769 const OpenMPClauseKind K) {
13770 return llvm::any_of(
13771 Range&: Clauses, P: [K](const OMPClause *C) { return C->getClauseKind() == K; });
13772}
13773
13774template <typename... Params>
13775static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
13776 const Params... ClauseTypes) {
13777 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13778}
13779
13780/// Check if the variables in the mapping clause are externally visible.
13781static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
13782 for (const OMPClause *C : Clauses) {
13783 if (auto *TC = dyn_cast<OMPToClause>(Val: C))
13784 return llvm::all_of(Range: TC->all_decls(), P: [](ValueDecl *VD) {
13785 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13786 (VD->isExternallyVisible() &&
13787 VD->getVisibility() != HiddenVisibility);
13788 });
13789 else if (auto *FC = dyn_cast<OMPFromClause>(Val: C))
13790 return llvm::all_of(Range: FC->all_decls(), P: [](ValueDecl *VD) {
13791 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13792 (VD->isExternallyVisible() &&
13793 VD->getVisibility() != HiddenVisibility);
13794 });
13795 }
13796
13797 return true;
13798}
13799
13800StmtResult
13801SemaOpenMP::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
13802 Stmt *AStmt, SourceLocation StartLoc,
13803 SourceLocation EndLoc) {
13804 if (!AStmt)
13805 return StmtError();
13806
13807 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13808
13809 // OpenMP [2.12.2, target data Construct, Restrictions]
13810 // At least one map, use_device_addr or use_device_ptr clause must appear on
13811 // the directive.
13812 if (!hasClauses(Clauses, K: OMPC_map, ClauseTypes: OMPC_use_device_ptr) &&
13813 (getLangOpts().OpenMP < 50 ||
13814 !hasClauses(Clauses, K: OMPC_use_device_addr))) {
13815 StringRef Expected;
13816 if (getLangOpts().OpenMP < 50)
13817 Expected = "'map' or 'use_device_ptr'";
13818 else
13819 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13820 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
13821 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
13822 << Expected << getOpenMPDirectiveName(D: OMPD_target_data, V: OMPVersion);
13823 return StmtError();
13824 }
13825
13826 SemaRef.setFunctionHasBranchProtectedScope();
13827
13828 return OMPTargetDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13829 Clauses, AssociatedStmt: AStmt);
13830}
13831
13832StmtResult SemaOpenMP::ActOnOpenMPTargetEnterDataDirective(
13833 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13834 SourceLocation EndLoc, Stmt *AStmt) {
13835 if (!AStmt)
13836 return StmtError();
13837
13838 setBranchProtectedScope(SemaRef, DKind: OMPD_target_enter_data, AStmt);
13839
13840 // OpenMP [2.10.2, Restrictions, p. 99]
13841 // At least one map clause must appear on the directive.
13842 if (!hasClauses(Clauses, K: OMPC_map)) {
13843 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
13844 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
13845 << "'map'"
13846 << getOpenMPDirectiveName(D: OMPD_target_enter_data, V: OMPVersion);
13847 return StmtError();
13848 }
13849
13850 return OMPTargetEnterDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13851 Clauses, AssociatedStmt: AStmt);
13852}
13853
13854StmtResult SemaOpenMP::ActOnOpenMPTargetExitDataDirective(
13855 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13856 SourceLocation EndLoc, Stmt *AStmt) {
13857 if (!AStmt)
13858 return StmtError();
13859
13860 setBranchProtectedScope(SemaRef, DKind: OMPD_target_exit_data, AStmt);
13861
13862 // OpenMP [2.10.3, Restrictions, p. 102]
13863 // At least one map clause must appear on the directive.
13864 if (!hasClauses(Clauses, K: OMPC_map)) {
13865 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
13866 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
13867 << "'map'" << getOpenMPDirectiveName(D: OMPD_target_exit_data, V: OMPVersion);
13868 return StmtError();
13869 }
13870
13871 return OMPTargetExitDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13872 Clauses, AssociatedStmt: AStmt);
13873}
13874
13875StmtResult SemaOpenMP::ActOnOpenMPTargetUpdateDirective(
13876 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13877 SourceLocation EndLoc, Stmt *AStmt) {
13878 if (!AStmt)
13879 return StmtError();
13880
13881 setBranchProtectedScope(SemaRef, DKind: OMPD_target_update, AStmt);
13882
13883 if (!hasClauses(Clauses, K: OMPC_to, ClauseTypes: OMPC_from)) {
13884 Diag(Loc: StartLoc, DiagID: diag::err_omp_at_least_one_motion_clause_required);
13885 return StmtError();
13886 }
13887
13888 if (!isClauseMappable(Clauses)) {
13889 Diag(Loc: StartLoc, DiagID: diag::err_omp_cannot_update_with_internal_linkage);
13890 return StmtError();
13891 }
13892
13893 return OMPTargetUpdateDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13894 Clauses, AssociatedStmt: AStmt);
13895}
13896
13897StmtResult SemaOpenMP::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
13898 Stmt *AStmt,
13899 SourceLocation StartLoc,
13900 SourceLocation EndLoc) {
13901 if (!AStmt)
13902 return StmtError();
13903
13904 if (validateMultidimClauses(SemaRef&: *this, Clauses))
13905 return StmtError();
13906
13907 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13908 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13909 Diag(Loc: StartLoc, DiagID: diag::warn_hip_omp_target_directives);
13910
13911 setBranchProtectedScope(SemaRef, DKind: OMPD_teams, AStmt);
13912
13913 DSAStack->setParentTeamsRegionLoc(StartLoc);
13914
13915 return OMPTeamsDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
13916 AssociatedStmt: AStmt);
13917}
13918
13919StmtResult SemaOpenMP::ActOnOpenMPCancellationPointDirective(
13920 SourceLocation StartLoc, SourceLocation EndLoc,
13921 OpenMPDirectiveKind CancelRegion) {
13922 if (DSAStack->isParentNowaitRegion()) {
13923 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_nowait) << 0;
13924 return StmtError();
13925 }
13926 if (DSAStack->isParentOrderedRegion()) {
13927 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_ordered) << 0;
13928 return StmtError();
13929 }
13930 return OMPCancellationPointDirective::Create(C: getASTContext(), StartLoc,
13931 EndLoc, CancelRegion);
13932}
13933
13934StmtResult SemaOpenMP::ActOnOpenMPCancelDirective(
13935 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13936 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13937 if (DSAStack->isParentNowaitRegion()) {
13938 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_nowait) << 1;
13939 return StmtError();
13940 }
13941 if (DSAStack->isParentOrderedRegion()) {
13942 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_ordered) << 1;
13943 return StmtError();
13944 }
13945 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13946 return OMPCancelDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
13947 CancelRegion);
13948}
13949
13950static bool checkReductionClauseWithNogroup(Sema &S,
13951 ArrayRef<OMPClause *> Clauses) {
13952 const OMPClause *ReductionClause = nullptr;
13953 const OMPClause *NogroupClause = nullptr;
13954 for (const OMPClause *C : Clauses) {
13955 if (C->getClauseKind() == OMPC_reduction) {
13956 ReductionClause = C;
13957 if (NogroupClause)
13958 break;
13959 continue;
13960 }
13961 if (C->getClauseKind() == OMPC_nogroup) {
13962 NogroupClause = C;
13963 if (ReductionClause)
13964 break;
13965 continue;
13966 }
13967 }
13968 if (ReductionClause && NogroupClause) {
13969 S.Diag(Loc: ReductionClause->getBeginLoc(), DiagID: diag::err_omp_reduction_with_nogroup)
13970 << SourceRange(NogroupClause->getBeginLoc(),
13971 NogroupClause->getEndLoc());
13972 return true;
13973 }
13974 return false;
13975}
13976
13977StmtResult SemaOpenMP::ActOnOpenMPTaskLoopDirective(
13978 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13979 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13980 if (!AStmt)
13981 return StmtError();
13982
13983 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13984 OMPLoopBasedDirective::HelperExprs B;
13985 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13986 // define the nested loops number.
13987 unsigned NestedLoopCount =
13988 checkOpenMPLoop(DKind: OMPD_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13989 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13990 DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
13991 if (NestedLoopCount == 0)
13992 return StmtError();
13993
13994 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13995 "omp for loop exprs were not built");
13996
13997 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13998 // The grainsize clause and num_tasks clause are mutually exclusive and may
13999 // not appear on the same taskloop directive.
14000 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14001 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14002 return StmtError();
14003 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14004 // If a reduction clause is present on the taskloop directive, the nogroup
14005 // clause must not be specified.
14006 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14007 return StmtError();
14008
14009 SemaRef.setFunctionHasBranchProtectedScope();
14010 return OMPTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14011 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14012 DSAStack->isCancelRegion());
14013}
14014
14015StmtResult SemaOpenMP::ActOnOpenMPTaskLoopSimdDirective(
14016 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14017 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14018 if (!AStmt)
14019 return StmtError();
14020
14021 CapturedStmt *CS =
14022 setBranchProtectedScope(SemaRef, DKind: OMPD_taskloop_simd, AStmt);
14023
14024 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14025 OMPLoopBasedDirective::HelperExprs B;
14026 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14027 // define the nested loops number.
14028 unsigned NestedLoopCount =
14029 checkOpenMPLoop(DKind: OMPD_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14030 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14031 VarsWithImplicitDSA, Built&: B);
14032 if (NestedLoopCount == 0)
14033 return StmtError();
14034
14035 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14036 return StmtError();
14037
14038 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14039 // The grainsize clause and num_tasks clause are mutually exclusive and may
14040 // not appear on the same taskloop directive.
14041 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14042 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14043 return StmtError();
14044 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14045 // If a reduction clause is present on the taskloop directive, the nogroup
14046 // clause must not be specified.
14047 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14048 return StmtError();
14049 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14050 return StmtError();
14051
14052 return OMPTaskLoopSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14053 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14054}
14055
14056StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopDirective(
14057 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14058 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14059 if (!AStmt)
14060 return StmtError();
14061
14062 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14063 OMPLoopBasedDirective::HelperExprs B;
14064 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14065 // define the nested loops number.
14066 unsigned NestedLoopCount =
14067 checkOpenMPLoop(DKind: OMPD_master_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14068 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
14069 DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14070 if (NestedLoopCount == 0)
14071 return StmtError();
14072
14073 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14074 "omp for loop exprs were not built");
14075
14076 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14077 // The grainsize clause and num_tasks clause are mutually exclusive and may
14078 // not appear on the same taskloop directive.
14079 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14080 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14081 return StmtError();
14082 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14083 // If a reduction clause is present on the taskloop directive, the nogroup
14084 // clause must not be specified.
14085 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14086 return StmtError();
14087
14088 SemaRef.setFunctionHasBranchProtectedScope();
14089 return OMPMasterTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14090 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14091 DSAStack->isCancelRegion());
14092}
14093
14094StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopDirective(
14095 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14096 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14097 if (!AStmt)
14098 return StmtError();
14099
14100 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14101 OMPLoopBasedDirective::HelperExprs B;
14102 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14103 // define the nested loops number.
14104 unsigned NestedLoopCount =
14105 checkOpenMPLoop(DKind: OMPD_masked_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14106 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
14107 DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14108 if (NestedLoopCount == 0)
14109 return StmtError();
14110
14111 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14112 "omp for loop exprs were not built");
14113
14114 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14115 // The grainsize clause and num_tasks clause are mutually exclusive and may
14116 // not appear on the same taskloop directive.
14117 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14118 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14119 return StmtError();
14120 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14121 // If a reduction clause is present on the taskloop directive, the nogroup
14122 // clause must not be specified.
14123 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14124 return StmtError();
14125
14126 SemaRef.setFunctionHasBranchProtectedScope();
14127 return OMPMaskedTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14128 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14129 DSAStack->isCancelRegion());
14130}
14131
14132StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopSimdDirective(
14133 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14134 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14135 if (!AStmt)
14136 return StmtError();
14137
14138 CapturedStmt *CS =
14139 setBranchProtectedScope(SemaRef, DKind: OMPD_master_taskloop_simd, AStmt);
14140
14141 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14142 OMPLoopBasedDirective::HelperExprs B;
14143 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14144 // define the nested loops number.
14145 unsigned NestedLoopCount =
14146 checkOpenMPLoop(DKind: OMPD_master_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14147 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14148 VarsWithImplicitDSA, Built&: B);
14149 if (NestedLoopCount == 0)
14150 return StmtError();
14151
14152 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14153 return StmtError();
14154
14155 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14156 // The grainsize clause and num_tasks clause are mutually exclusive and may
14157 // not appear on the same taskloop directive.
14158 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14159 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14160 return StmtError();
14161 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14162 // If a reduction clause is present on the taskloop directive, the nogroup
14163 // clause must not be specified.
14164 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14165 return StmtError();
14166 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14167 return StmtError();
14168
14169 return OMPMasterTaskLoopSimdDirective::Create(
14170 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14171}
14172
14173StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopSimdDirective(
14174 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14175 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14176 if (!AStmt)
14177 return StmtError();
14178
14179 CapturedStmt *CS =
14180 setBranchProtectedScope(SemaRef, DKind: OMPD_masked_taskloop_simd, AStmt);
14181
14182 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14183 OMPLoopBasedDirective::HelperExprs B;
14184 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14185 // define the nested loops number.
14186 unsigned NestedLoopCount =
14187 checkOpenMPLoop(DKind: OMPD_masked_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14188 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14189 VarsWithImplicitDSA, Built&: B);
14190 if (NestedLoopCount == 0)
14191 return StmtError();
14192
14193 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14194 return StmtError();
14195
14196 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14197 // The grainsize clause and num_tasks clause are mutually exclusive and may
14198 // not appear on the same taskloop directive.
14199 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14200 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14201 return StmtError();
14202 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14203 // If a reduction clause is present on the taskloop directive, the nogroup
14204 // clause must not be specified.
14205 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14206 return StmtError();
14207 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14208 return StmtError();
14209
14210 return OMPMaskedTaskLoopSimdDirective::Create(
14211 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14212}
14213
14214StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopDirective(
14215 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14216 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14217 if (!AStmt)
14218 return StmtError();
14219
14220 CapturedStmt *CS =
14221 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_master_taskloop, AStmt);
14222
14223 OMPLoopBasedDirective::HelperExprs B;
14224 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14225 // define the nested loops number.
14226 unsigned NestedLoopCount = checkOpenMPLoop(
14227 DKind: OMPD_parallel_master_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14228 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14229 VarsWithImplicitDSA, Built&: B);
14230 if (NestedLoopCount == 0)
14231 return StmtError();
14232
14233 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14234 "omp for loop exprs were not built");
14235
14236 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14237 // The grainsize clause and num_tasks clause are mutually exclusive and may
14238 // not appear on the same taskloop directive.
14239 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14240 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14241 return StmtError();
14242 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14243 // If a reduction clause is present on the taskloop directive, the nogroup
14244 // clause must not be specified.
14245 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14246 return StmtError();
14247
14248 return OMPParallelMasterTaskLoopDirective::Create(
14249 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14250 DSAStack->isCancelRegion());
14251}
14252
14253StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopDirective(
14254 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14255 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14256 if (!AStmt)
14257 return StmtError();
14258
14259 CapturedStmt *CS =
14260 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_masked_taskloop, AStmt);
14261
14262 OMPLoopBasedDirective::HelperExprs B;
14263 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14264 // define the nested loops number.
14265 unsigned NestedLoopCount = checkOpenMPLoop(
14266 DKind: OMPD_parallel_masked_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14267 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14268 VarsWithImplicitDSA, Built&: B);
14269 if (NestedLoopCount == 0)
14270 return StmtError();
14271
14272 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14273 "omp for loop exprs were not built");
14274
14275 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14276 // The grainsize clause and num_tasks clause are mutually exclusive and may
14277 // not appear on the same taskloop directive.
14278 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14279 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14280 return StmtError();
14281 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14282 // If a reduction clause is present on the taskloop directive, the nogroup
14283 // clause must not be specified.
14284 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14285 return StmtError();
14286
14287 return OMPParallelMaskedTaskLoopDirective::Create(
14288 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14289 DSAStack->isCancelRegion());
14290}
14291
14292StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
14293 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14294 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14295 if (!AStmt)
14296 return StmtError();
14297
14298 CapturedStmt *CS = setBranchProtectedScope(
14299 SemaRef, DKind: OMPD_parallel_master_taskloop_simd, AStmt);
14300
14301 OMPLoopBasedDirective::HelperExprs B;
14302 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14303 // define the nested loops number.
14304 unsigned NestedLoopCount = checkOpenMPLoop(
14305 DKind: OMPD_parallel_master_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14306 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14307 VarsWithImplicitDSA, Built&: B);
14308 if (NestedLoopCount == 0)
14309 return StmtError();
14310
14311 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14312 return StmtError();
14313
14314 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14315 // The grainsize clause and num_tasks clause are mutually exclusive and may
14316 // not appear on the same taskloop directive.
14317 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14318 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14319 return StmtError();
14320 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14321 // If a reduction clause is present on the taskloop directive, the nogroup
14322 // clause must not be specified.
14323 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14324 return StmtError();
14325 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14326 return StmtError();
14327
14328 return OMPParallelMasterTaskLoopSimdDirective::Create(
14329 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14330}
14331
14332StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
14333 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14334 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14335 if (!AStmt)
14336 return StmtError();
14337
14338 CapturedStmt *CS = setBranchProtectedScope(
14339 SemaRef, DKind: OMPD_parallel_masked_taskloop_simd, AStmt);
14340
14341 OMPLoopBasedDirective::HelperExprs B;
14342 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14343 // define the nested loops number.
14344 unsigned NestedLoopCount = checkOpenMPLoop(
14345 DKind: OMPD_parallel_masked_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14346 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14347 VarsWithImplicitDSA, Built&: B);
14348 if (NestedLoopCount == 0)
14349 return StmtError();
14350
14351 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14352 return StmtError();
14353
14354 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14355 // The grainsize clause and num_tasks clause are mutually exclusive and may
14356 // not appear on the same taskloop directive.
14357 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14358 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14359 return StmtError();
14360 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14361 // If a reduction clause is present on the taskloop directive, the nogroup
14362 // clause must not be specified.
14363 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14364 return StmtError();
14365 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14366 return StmtError();
14367
14368 return OMPParallelMaskedTaskLoopSimdDirective::Create(
14369 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14370}
14371
14372StmtResult SemaOpenMP::ActOnOpenMPDistributeDirective(
14373 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14374 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14375 if (!AStmt)
14376 return StmtError();
14377
14378 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14379 OMPLoopBasedDirective::HelperExprs B;
14380 // In presence of clause 'collapse' with number of loops, it will
14381 // define the nested loops number.
14382 unsigned NestedLoopCount =
14383 checkOpenMPLoop(DKind: OMPD_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14384 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt,
14385 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14386 if (NestedLoopCount == 0)
14387 return StmtError();
14388
14389 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14390 "omp for loop exprs were not built");
14391
14392 SemaRef.setFunctionHasBranchProtectedScope();
14393 auto *DistributeDirective = OMPDistributeDirective::Create(
14394 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14395 return DistributeDirective;
14396}
14397
14398StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForDirective(
14399 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14400 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14401 if (!AStmt)
14402 return StmtError();
14403
14404 CapturedStmt *CS =
14405 setBranchProtectedScope(SemaRef, DKind: OMPD_distribute_parallel_for, AStmt);
14406
14407 OMPLoopBasedDirective::HelperExprs B;
14408 // In presence of clause 'collapse' with number of loops, it will
14409 // define the nested loops number.
14410 unsigned NestedLoopCount = checkOpenMPLoop(
14411 DKind: OMPD_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14412 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14413 VarsWithImplicitDSA, Built&: B);
14414 if (NestedLoopCount == 0)
14415 return StmtError();
14416
14417 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14418 "omp for loop exprs were not built");
14419
14420 return OMPDistributeParallelForDirective::Create(
14421 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14422 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14423}
14424
14425StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForSimdDirective(
14426 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14427 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14428 if (!AStmt)
14429 return StmtError();
14430
14431 CapturedStmt *CS = setBranchProtectedScope(
14432 SemaRef, DKind: OMPD_distribute_parallel_for_simd, AStmt);
14433
14434 OMPLoopBasedDirective::HelperExprs B;
14435 // In presence of clause 'collapse' with number of loops, it will
14436 // define the nested loops number.
14437 unsigned NestedLoopCount = checkOpenMPLoop(
14438 DKind: OMPD_distribute_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14439 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14440 VarsWithImplicitDSA, Built&: B);
14441 if (NestedLoopCount == 0)
14442 return StmtError();
14443
14444 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14445 return StmtError();
14446
14447 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14448 return StmtError();
14449
14450 return OMPDistributeParallelForSimdDirective::Create(
14451 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14452}
14453
14454StmtResult SemaOpenMP::ActOnOpenMPDistributeSimdDirective(
14455 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14456 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14457 if (!AStmt)
14458 return StmtError();
14459
14460 CapturedStmt *CS =
14461 setBranchProtectedScope(SemaRef, DKind: OMPD_distribute_simd, AStmt);
14462
14463 OMPLoopBasedDirective::HelperExprs B;
14464 // In presence of clause 'collapse' with number of loops, it will
14465 // define the nested loops number.
14466 unsigned NestedLoopCount =
14467 checkOpenMPLoop(DKind: OMPD_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14468 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
14469 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14470 if (NestedLoopCount == 0)
14471 return StmtError();
14472
14473 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14474 return StmtError();
14475
14476 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14477 return StmtError();
14478
14479 return OMPDistributeSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14480 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14481}
14482
14483StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForSimdDirective(
14484 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14485 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14486 if (!AStmt)
14487 return StmtError();
14488
14489 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14490 return StmtError();
14491
14492 CapturedStmt *CS =
14493 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_for_simd, AStmt);
14494
14495 OMPLoopBasedDirective::HelperExprs B;
14496 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14497 // define the nested loops number.
14498 unsigned NestedLoopCount = checkOpenMPLoop(
14499 DKind: OMPD_target_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14500 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
14501 VarsWithImplicitDSA, Built&: B);
14502 if (NestedLoopCount == 0)
14503 return StmtError();
14504
14505 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14506 return StmtError();
14507
14508 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14509 return StmtError();
14510
14511 return OMPTargetParallelForSimdDirective::Create(
14512 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14513}
14514
14515StmtResult SemaOpenMP::ActOnOpenMPTargetSimdDirective(
14516 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14517 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14518 if (!AStmt)
14519 return StmtError();
14520
14521 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14522 return StmtError();
14523
14524 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_target_simd, AStmt);
14525
14526 OMPLoopBasedDirective::HelperExprs B;
14527 // In presence of clause 'collapse' with number of loops, it will define the
14528 // nested loops number.
14529 unsigned NestedLoopCount =
14530 checkOpenMPLoop(DKind: OMPD_target_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14531 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
14532 VarsWithImplicitDSA, Built&: B);
14533 if (NestedLoopCount == 0)
14534 return StmtError();
14535
14536 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14537 return StmtError();
14538
14539 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14540 return StmtError();
14541
14542 return OMPTargetSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14543 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14544}
14545
14546StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeDirective(
14547 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14548 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14549 if (!AStmt)
14550 return StmtError();
14551
14552 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14553 return StmtError();
14554
14555 CapturedStmt *CS =
14556 setBranchProtectedScope(SemaRef, DKind: OMPD_teams_distribute, AStmt);
14557
14558 OMPLoopBasedDirective::HelperExprs B;
14559 // In presence of clause 'collapse' with number of loops, it will
14560 // define the nested loops number.
14561 unsigned NestedLoopCount =
14562 checkOpenMPLoop(DKind: OMPD_teams_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14563 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
14564 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14565 if (NestedLoopCount == 0)
14566 return StmtError();
14567
14568 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14569 "omp teams distribute loop exprs were not built");
14570
14571 DSAStack->setParentTeamsRegionLoc(StartLoc);
14572
14573 return OMPTeamsDistributeDirective::Create(
14574 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14575}
14576
14577StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeSimdDirective(
14578 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14579 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14580 if (!AStmt)
14581 return StmtError();
14582
14583 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14584 return StmtError();
14585
14586 CapturedStmt *CS =
14587 setBranchProtectedScope(SemaRef, DKind: OMPD_teams_distribute_simd, AStmt);
14588
14589 OMPLoopBasedDirective::HelperExprs B;
14590 // In presence of clause 'collapse' with number of loops, it will
14591 // define the nested loops number.
14592 unsigned NestedLoopCount = checkOpenMPLoop(
14593 DKind: OMPD_teams_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14594 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14595 VarsWithImplicitDSA, Built&: B);
14596 if (NestedLoopCount == 0)
14597 return StmtError();
14598
14599 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14600 return StmtError();
14601
14602 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14603 return StmtError();
14604
14605 DSAStack->setParentTeamsRegionLoc(StartLoc);
14606
14607 return OMPTeamsDistributeSimdDirective::Create(
14608 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14609}
14610
14611StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
14612 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14613 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14614 if (!AStmt)
14615 return StmtError();
14616
14617 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14618 return StmtError();
14619
14620 CapturedStmt *CS = setBranchProtectedScope(
14621 SemaRef, DKind: OMPD_teams_distribute_parallel_for_simd, AStmt);
14622
14623 OMPLoopBasedDirective::HelperExprs B;
14624 // In presence of clause 'collapse' with number of loops, it will
14625 // define the nested loops number.
14626 unsigned NestedLoopCount = checkOpenMPLoop(
14627 DKind: OMPD_teams_distribute_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14628 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14629 VarsWithImplicitDSA, Built&: B);
14630 if (NestedLoopCount == 0)
14631 return StmtError();
14632
14633 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14634 return StmtError();
14635
14636 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14637 return StmtError();
14638
14639 DSAStack->setParentTeamsRegionLoc(StartLoc);
14640
14641 return OMPTeamsDistributeParallelForSimdDirective::Create(
14642 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14643}
14644
14645StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForDirective(
14646 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14647 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14648 if (!AStmt)
14649 return StmtError();
14650
14651 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14652 return StmtError();
14653
14654 CapturedStmt *CS = setBranchProtectedScope(
14655 SemaRef, DKind: OMPD_teams_distribute_parallel_for, AStmt);
14656
14657 OMPLoopBasedDirective::HelperExprs B;
14658 // In presence of clause 'collapse' with number of loops, it will
14659 // define the nested loops number.
14660 unsigned NestedLoopCount = checkOpenMPLoop(
14661 DKind: OMPD_teams_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14662 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14663 VarsWithImplicitDSA, Built&: B);
14664
14665 if (NestedLoopCount == 0)
14666 return StmtError();
14667
14668 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14669 "omp for loop exprs were not built");
14670
14671 DSAStack->setParentTeamsRegionLoc(StartLoc);
14672
14673 return OMPTeamsDistributeParallelForDirective::Create(
14674 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14675 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14676}
14677
14678StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDirective(
14679 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14680 SourceLocation EndLoc) {
14681 if (!AStmt)
14682 return StmtError();
14683
14684 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams, AStmt);
14685
14686 if (validateMultidimClauses(SemaRef&: *this, Clauses, /*MayHaveBareClause=*/true))
14687 return StmtError();
14688
14689 return OMPTargetTeamsDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14690 Clauses, AssociatedStmt: AStmt);
14691}
14692
14693StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeDirective(
14694 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14695 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14696 if (!AStmt)
14697 return StmtError();
14698
14699 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14700 return StmtError();
14701
14702 CapturedStmt *CS =
14703 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams_distribute, AStmt);
14704
14705 OMPLoopBasedDirective::HelperExprs B;
14706 // In presence of clause 'collapse' with number of loops, it will
14707 // define the nested loops number.
14708 unsigned NestedLoopCount = checkOpenMPLoop(
14709 DKind: OMPD_target_teams_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14710 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14711 VarsWithImplicitDSA, Built&: B);
14712 if (NestedLoopCount == 0)
14713 return StmtError();
14714
14715 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14716 "omp target teams distribute loop exprs were not built");
14717
14718 return OMPTargetTeamsDistributeDirective::Create(
14719 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14720}
14721
14722StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14723 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14724 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14725 if (!AStmt)
14726 return StmtError();
14727
14728 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14729 return StmtError();
14730
14731 CapturedStmt *CS = setBranchProtectedScope(
14732 SemaRef, DKind: OMPD_target_teams_distribute_parallel_for, AStmt);
14733
14734 OMPLoopBasedDirective::HelperExprs B;
14735 // In presence of clause 'collapse' with number of loops, it will
14736 // define the nested loops number.
14737 unsigned NestedLoopCount = checkOpenMPLoop(
14738 DKind: OMPD_target_teams_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14739 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14740 VarsWithImplicitDSA, Built&: B);
14741 if (NestedLoopCount == 0)
14742 return StmtError();
14743
14744 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14745 return StmtError();
14746
14747 return OMPTargetTeamsDistributeParallelForDirective::Create(
14748 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14749 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14750}
14751
14752StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14753 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14754 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14755 if (!AStmt)
14756 return StmtError();
14757
14758 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14759 return StmtError();
14760
14761 CapturedStmt *CS = setBranchProtectedScope(
14762 SemaRef, DKind: OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14763
14764 OMPLoopBasedDirective::HelperExprs B;
14765 // In presence of clause 'collapse' with number of loops, it will
14766 // define the nested loops number.
14767 unsigned NestedLoopCount =
14768 checkOpenMPLoop(DKind: OMPD_target_teams_distribute_parallel_for_simd,
14769 CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14770 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
14771 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14772 if (NestedLoopCount == 0)
14773 return StmtError();
14774
14775 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14776 return StmtError();
14777
14778 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14779 return StmtError();
14780
14781 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14782 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14783}
14784
14785StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14786 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14787 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14788 if (!AStmt)
14789 return StmtError();
14790
14791 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14792 return StmtError();
14793
14794 CapturedStmt *CS = setBranchProtectedScope(
14795 SemaRef, DKind: OMPD_target_teams_distribute_simd, AStmt);
14796
14797 OMPLoopBasedDirective::HelperExprs B;
14798 // In presence of clause 'collapse' with number of loops, it will
14799 // define the nested loops number.
14800 unsigned NestedLoopCount = checkOpenMPLoop(
14801 DKind: OMPD_target_teams_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14802 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14803 VarsWithImplicitDSA, Built&: B);
14804 if (NestedLoopCount == 0)
14805 return StmtError();
14806
14807 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14808 return StmtError();
14809
14810 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14811 return StmtError();
14812
14813 return OMPTargetTeamsDistributeSimdDirective::Create(
14814 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14815}
14816
14817/// Updates OriginalInits by checking Transform against loop transformation
14818/// directives and appending their pre-inits if a match is found.
14819static void updatePreInits(OMPLoopTransformationDirective *Transform,
14820 SmallVectorImpl<Stmt *> &PreInits) {
14821 Stmt *Dir = Transform->getDirective();
14822 switch (Dir->getStmtClass()) {
14823#define STMT(CLASS, PARENT)
14824#define ABSTRACT_STMT(CLASS)
14825#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14826 case Stmt::CLASS##Class: \
14827 appendFlattenedStmtList(PreInits, \
14828 static_cast<const CLASS *>(Dir)->getPreInits()); \
14829 break;
14830#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14831 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14832#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14833 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14834#include "clang/AST/StmtNodes.inc"
14835#undef COMMON_OMP_LOOP_TRANSFORMATION
14836 default:
14837 llvm_unreachable("Not a loop transformation");
14838 }
14839}
14840
14841bool SemaOpenMP::checkTransformableLoopNest(
14842 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14843 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14844 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *>> &OriginalInits) {
14845 OriginalInits.emplace_back();
14846 bool Result = OMPLoopBasedDirective::doForAllLoops(
14847 CurStmt: AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14848 Callback: [this, &LoopHelpers, &Body, &OriginalInits,
14849 Kind](unsigned Cnt, Stmt *CurStmt, Stmt *HintWrapper) {
14850 // The start of this loop is a floor set in the enclosing tile's body.
14851 // Loop analysis reads a start only once, so the nest would repeat the
14852 // first tile. Reject instead of emitting wrong loops.
14853 if (HintWrapper) {
14854 SemaRef.Diag(Loc: CurStmt->getBeginLoc(),
14855 DiagID: diag::err_omp_collapse_stacked_tile)
14856 << /*LoopTransform=*/1;
14857 return true;
14858 }
14859 VarsWithInheritedDSAType TmpDSA;
14860 unsigned SingleNumLoops =
14861 checkOpenMPLoop(DKind: Kind, CollapseLoopCountExpr: nullptr, OrderedLoopCountExpr: nullptr, AStmt: CurStmt, SemaRef, DSA&: *DSAStack,
14862 VarsWithImplicitDSA&: TmpDSA, Built&: LoopHelpers[Cnt]);
14863 if (SingleNumLoops == 0)
14864 return true;
14865 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14866 if (auto *For = dyn_cast<ForStmt>(Val: CurStmt)) {
14867 OriginalInits.back().push_back(Elt: For->getInit());
14868 Body = For->getBody();
14869 } else {
14870 assert(isa<CXXForRangeStmt>(CurStmt) &&
14871 "Expected canonical for or range-based for loops.");
14872 auto *CXXFor = cast<CXXForRangeStmt>(Val: CurStmt);
14873 OriginalInits.back().push_back(Elt: CXXFor->getBeginStmt());
14874 Body = CXXFor->getBody();
14875 }
14876 OriginalInits.emplace_back();
14877 return false;
14878 },
14879 OnTransformationCallback: [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14880 updatePreInits(Transform, PreInits&: OriginalInits.back());
14881 });
14882 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14883 OriginalInits.pop_back();
14884 return Result;
14885}
14886
14887/// Counts the total number of OpenMP canonical nested loops, including the
14888/// outermost loop (the original loop). PRECONDITION of this visitor is that it
14889/// must be invoked from the original loop to be analyzed. The traversal stops
14890/// for Decl's and Expr's given that they may contain inner loops that must not
14891/// be counted.
14892///
14893/// Example AST structure for the code:
14894///
14895/// int main() {
14896/// #pragma omp fuse
14897/// {
14898/// for (int i = 0; i < 100; i++) { <-- Outer loop
14899/// []() {
14900/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (1)
14901/// };
14902/// for(int j = 0; j < 5; ++j) {} <-- Inner loop
14903/// }
14904/// for (int r = 0; i < 100; i++) { <-- Outer loop
14905/// struct LocalClass {
14906/// void bar() {
14907/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (2)
14908/// }
14909/// };
14910/// for(int k = 0; k < 10; ++k) {} <-- Inner loop
14911/// {x = 5; for(k = 0; k < 10; ++k) x += k; x}; <-- NOT A LOOP (3)
14912/// }
14913/// }
14914/// }
14915/// (1) because in a different function (here: a lambda)
14916/// (2) because in a different function (here: class method)
14917/// (3) because considered to be intervening-code of non-perfectly nested loop
14918/// Result: Loop 'i' contains 2 loops, Loop 'r' also contains 2 loops.
14919class NestedLoopCounterVisitor final : public DynamicRecursiveASTVisitor {
14920private:
14921 unsigned NestedLoopCount = 0;
14922
14923public:
14924 explicit NestedLoopCounterVisitor() = default;
14925
14926 unsigned getNestedLoopCount() const { return NestedLoopCount; }
14927
14928 bool VisitForStmt(ForStmt *FS) override {
14929 ++NestedLoopCount;
14930 return true;
14931 }
14932
14933 bool VisitCXXForRangeStmt(CXXForRangeStmt *FRS) override {
14934 ++NestedLoopCount;
14935 return true;
14936 }
14937
14938 bool TraverseStmt(Stmt *S) override {
14939 if (!S)
14940 return true;
14941
14942 // Skip traversal of all expressions, including special cases like
14943 // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
14944 // may contain inner statements (and even loops), but they are not part
14945 // of the syntactic body of the surrounding loop structure.
14946 // Therefore must not be counted.
14947 if (isa<Expr>(Val: S))
14948 return true;
14949
14950 // Only recurse into CompoundStmt (block {}) and loop bodies.
14951 if (isa<CompoundStmt, ForStmt, CXXForRangeStmt>(Val: S)) {
14952 return DynamicRecursiveASTVisitor::TraverseStmt(S);
14953 }
14954
14955 // Stop traversal of the rest of statements, that break perfect
14956 // loop nesting, such as control flow (IfStmt, SwitchStmt...).
14957 return true;
14958 }
14959
14960 bool TraverseDecl(Decl *D) override {
14961 // Stop in the case of finding a declaration, it is not important
14962 // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
14963 // FunctionDecl...).
14964 return true;
14965 }
14966};
14967
14968bool SemaOpenMP::analyzeLoopSequence(Stmt *LoopSeqStmt,
14969 LoopSequenceAnalysis &SeqAnalysis,
14970 ASTContext &Context,
14971 OpenMPDirectiveKind Kind) {
14972 VarsWithInheritedDSAType TmpDSA;
14973 // Helper Lambda to handle storing initialization and body statements for
14974 // both ForStmt and CXXForRangeStmt.
14975 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14976 if (auto *For = dyn_cast<ForStmt>(Val: LoopStmt)) {
14977 Analysis.OriginalInits.push_back(Elt: For->getInit());
14978 Analysis.TheForStmt = For;
14979 } else {
14980 auto *CXXFor = cast<CXXForRangeStmt>(Val: LoopStmt);
14981 Analysis.OriginalInits.push_back(Elt: CXXFor->getBeginStmt());
14982 Analysis.TheForStmt = CXXFor;
14983 }
14984 };
14985
14986 // Helper lambda functions to encapsulate the processing of different
14987 // derivations of the canonical loop sequence grammar
14988 // Modularized code for handling loop generation and transformations.
14989 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14990 auto *LoopTransform = cast<OMPLoopTransformationDirective>(Val: Child);
14991 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14992 unsigned NumGeneratedTopLevelLoops =
14993 LoopTransform->getNumGeneratedTopLevelLoops();
14994 // Handle the case where transformed statement is not available due to
14995 // dependent contexts
14996 if (!TransformedStmt) {
14997 if (NumGeneratedTopLevelLoops > 0) {
14998 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14999 return true;
15000 }
15001 // Unroll full (0 loops produced)
15002 Diag(Loc: Child->getBeginLoc(), DiagID: diag::err_omp_not_for)
15003 << 0 << getOpenMPDirectiveName(D: Kind);
15004 return false;
15005 }
15006 // Handle loop transformations with multiple loop nests
15007 // Unroll full
15008 if (!NumGeneratedTopLevelLoops) {
15009 Diag(Loc: Child->getBeginLoc(), DiagID: diag::err_omp_not_for)
15010 << 0 << getOpenMPDirectiveName(D: Kind);
15011 return false;
15012 }
15013 // Loop transformatons such as split or loopranged fuse
15014 if (NumGeneratedTopLevelLoops > 1) {
15015 // Get the preinits related to this loop sequence generating
15016 // loop transformation (i.e loopranged fuse, split...)
15017 // These preinits differ slightly from regular inits/pre-inits related
15018 // to single loop generating loop transformations (interchange, unroll)
15019 // given that they are not bounded to a particular loop nest
15020 // so they need to be treated independently
15021 updatePreInits(Transform: LoopTransform, PreInits&: SeqAnalysis.LoopSequencePreInits);
15022 return analyzeLoopSequence(LoopSeqStmt: TransformedStmt, SeqAnalysis, Context, Kind);
15023 }
15024 // Vast majority: (Tile, Unroll, Stripe, Reverse, Interchange, Fuse all)
15025 // Process the transformed loop statement
15026 LoopAnalysis &NewTransformedSingleLoop =
15027 SeqAnalysis.Loops.emplace_back(Args&: Child);
15028 unsigned IsCanonical = checkOpenMPLoop(
15029 DKind: Kind, CollapseLoopCountExpr: nullptr, OrderedLoopCountExpr: nullptr, AStmt: TransformedStmt, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA&: TmpDSA,
15030 Built&: NewTransformedSingleLoop.HelperExprs);
15031
15032 if (!IsCanonical)
15033 return false;
15034
15035 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
15036 updatePreInits(Transform: LoopTransform, PreInits&: NewTransformedSingleLoop.TransformsPreInits);
15037
15038 SeqAnalysis.LoopSeqSize++;
15039 return true;
15040 };
15041
15042 // Modularized code for handling regular canonical loops.
15043 auto AnalyzeRegularLoop = [&](Stmt *Child) {
15044 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Args&: Child);
15045 unsigned IsCanonical =
15046 checkOpenMPLoop(DKind: Kind, CollapseLoopCountExpr: nullptr, OrderedLoopCountExpr: nullptr, AStmt: Child, SemaRef, DSA&: *DSAStack,
15047 VarsWithImplicitDSA&: TmpDSA, Built&: NewRegularLoop.HelperExprs);
15048
15049 if (!IsCanonical)
15050 return false;
15051
15052 StoreLoopStatements(NewRegularLoop, Child);
15053 NestedLoopCounterVisitor NLCV;
15054 NLCV.TraverseStmt(S: Child);
15055 return true;
15056 };
15057
15058 // High level grammar validation.
15059 for (Stmt *Child : LoopSeqStmt->children()) {
15060 if (!Child)
15061 continue;
15062 // Skip over non-loop-sequence statements.
15063 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(S: Child)) {
15064 Child = Child->IgnoreContainers();
15065 // Ignore empty compound statement.
15066 if (!Child)
15067 continue;
15068 // In the case of a nested loop sequence ignoring containers would not
15069 // be enough, a recurisve transversal of the loop sequence is required.
15070 if (isa<CompoundStmt>(Val: Child)) {
15071 if (!analyzeLoopSequence(LoopSeqStmt: Child, SeqAnalysis, Context, Kind))
15072 return false;
15073 // Already been treated, skip this children
15074 continue;
15075 }
15076 }
15077 // Regular loop sequence handling.
15078 if (LoopSequenceAnalysis::isLoopSequenceDerivation(S: Child)) {
15079 if (LoopAnalysis::isLoopTransformation(S: Child)) {
15080 if (!AnalyzeLoopGeneration(Child))
15081 return false;
15082 // AnalyzeLoopGeneration updates SeqAnalysis.LoopSeqSize accordingly.
15083 } else {
15084 if (!AnalyzeRegularLoop(Child))
15085 return false;
15086 SeqAnalysis.LoopSeqSize++;
15087 }
15088 } else {
15089 // Report error for invalid statement inside canonical loop sequence.
15090 Diag(Loc: Child->getBeginLoc(), DiagID: diag::err_omp_not_for)
15091 << 0 << getOpenMPDirectiveName(D: Kind);
15092 return false;
15093 }
15094 }
15095 return true;
15096}
15097
15098bool SemaOpenMP::checkTransformableLoopSequence(
15099 OpenMPDirectiveKind Kind, Stmt *AStmt, LoopSequenceAnalysis &SeqAnalysis,
15100 ASTContext &Context) {
15101 // Following OpenMP 6.0 API Specification, a Canonical Loop Sequence follows
15102 // the grammar:
15103 //
15104 // canonical-loop-sequence:
15105 // {
15106 // loop-sequence+
15107 // }
15108 // where loop-sequence can be any of the following:
15109 // 1. canonical-loop-sequence
15110 // 2. loop-nest
15111 // 3. loop-sequence-generating-construct (i.e OMPLoopTransformationDirective)
15112 //
15113 // To recognise and traverse this structure the helper function
15114 // analyzeLoopSequence serves as the recurisve entry point
15115 // and tries to match the input AST to the canonical loop sequence grammar
15116 // structure. This function will perform both a semantic and syntactical
15117 // analysis of the given statement according to OpenMP 6.0 definition of
15118 // the aforementioned canonical loop sequence.
15119
15120 // We expect an outer compound statement.
15121 if (!isa<CompoundStmt>(Val: AStmt)) {
15122 Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_not_a_loop_sequence)
15123 << getOpenMPDirectiveName(D: Kind);
15124 return false;
15125 }
15126
15127 // Recursive entry point to process the main loop sequence
15128 if (!analyzeLoopSequence(LoopSeqStmt: AStmt, SeqAnalysis, Context, Kind))
15129 return false;
15130
15131 // Diagnose an empty loop sequence.
15132 if (!SeqAnalysis.LoopSeqSize) {
15133 Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_empty_loop_sequence)
15134 << getOpenMPDirectiveName(D: Kind);
15135 return false;
15136 }
15137 return true;
15138}
15139
15140/// Add preinit statements that need to be propagated from the selected loop.
15141static void addLoopPreInits(ASTContext &Context,
15142 OMPLoopBasedDirective::HelperExprs &LoopHelper,
15143 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
15144 SmallVectorImpl<Stmt *> &PreInits) {
15145
15146 // For range-based for-statements, ensure that their syntactic sugar is
15147 // executed by adding them as pre-init statements.
15148 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt)) {
15149 Stmt *RangeInit = CXXRangeFor->getInit();
15150 if (RangeInit)
15151 PreInits.push_back(Elt: RangeInit);
15152
15153 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
15154 PreInits.push_back(Elt: new (Context) DeclStmt(RangeStmt->getDeclGroup(),
15155 RangeStmt->getBeginLoc(),
15156 RangeStmt->getEndLoc()));
15157
15158 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
15159 PreInits.push_back(Elt: new (Context) DeclStmt(RangeEnd->getDeclGroup(),
15160 RangeEnd->getBeginLoc(),
15161 RangeEnd->getEndLoc()));
15162 }
15163
15164 llvm::append_range(C&: PreInits, R&: OriginalInit);
15165
15166 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
15167 if (auto *PI = cast_or_null<DeclStmt>(Val: LoopHelper.PreInits)) {
15168 PreInits.push_back(Elt: new (Context) DeclStmt(
15169 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
15170 }
15171
15172 // Gather declarations for the data members used as counters.
15173 for (Expr *CounterRef : LoopHelper.Counters) {
15174 auto *CounterDecl = cast<DeclRefExpr>(Val: CounterRef)->getDecl();
15175 if (isa<OMPCapturedExprDecl>(Val: CounterDecl))
15176 PreInits.push_back(Elt: new (Context) DeclStmt(
15177 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
15178 }
15179}
15180
15181/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
15182/// loop of a construct.
15183static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
15184 size_t NumLoops = LoopStmts.size();
15185 OMPLoopBasedDirective::doForAllLoops(
15186 CurStmt: AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
15187 Callback: [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
15188 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
15189 LoopStmts[Cnt] = CurStmt;
15190 return false;
15191 });
15192 assert(!is_contained(LoopStmts, nullptr) &&
15193 "Expecting a loop statement for each affected loop");
15194}
15195
15196/// Build and return a DeclRefExpr for the floor induction variable using the
15197/// SemaRef and the provided parameters.
15198static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
15199 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
15200 return buildDeclRefExpr(S&: SemaRef, D: FloorIndVars[I], Ty: IVTy,
15201 Loc: OrigCntVar->getExprLoc());
15202}
15203
15204StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
15205 Stmt *AStmt,
15206 SourceLocation StartLoc,
15207 SourceLocation EndLoc) {
15208 ASTContext &Context = getASTContext();
15209 Scope *CurScope = SemaRef.getCurScope();
15210
15211 const auto *SizesClause =
15212 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15213 if (!SizesClause ||
15214 llvm::any_of(Range: SizesClause->getSizesRefs(), P: [](Expr *E) { return !E; }))
15215 return StmtError();
15216 unsigned NumLoops = SizesClause->getNumSizes();
15217
15218 // Empty statement should only be possible if there already was an error.
15219 if (!AStmt)
15220 return StmtError();
15221
15222 // Verify and diagnose loop nest.
15223 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
15224 Stmt *Body = nullptr;
15225 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
15226 if (!checkTransformableLoopNest(Kind: OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
15227 OriginalInits))
15228 return StmtError();
15229
15230 // Delay tiling to when template is completely instantiated.
15231 if (SemaRef.CurContext->isDependentContext())
15232 return OMPTileDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15233 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
15234
15235 assert(LoopHelpers.size() == NumLoops &&
15236 "Expecting loop iteration space dimensionality to match number of "
15237 "affected loops");
15238 assert(OriginalInits.size() == NumLoops &&
15239 "Expecting loop iteration space dimensionality to match number of "
15240 "affected loops");
15241
15242 // Collect all affected loop statements.
15243 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15244 collectLoopStmts(AStmt, LoopStmts);
15245
15246 SmallVector<Stmt *, 4> PreInits;
15247 CaptureVars CopyTransformer(SemaRef);
15248
15249 // Create iteration variables for the generated loops.
15250 SmallVector<VarDecl *, 4> FloorIndVars;
15251 SmallVector<VarDecl *, 4> TileIndVars;
15252 FloorIndVars.resize(N: NumLoops);
15253 TileIndVars.resize(N: NumLoops);
15254 for (unsigned I = 0; I < NumLoops; ++I) {
15255 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15256
15257 assert(LoopHelper.Counters.size() == 1 &&
15258 "Expect single-dimensional loop iteration space");
15259 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15260 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15261 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15262 QualType CntTy = IterVarRef->getType();
15263
15264 // Iteration variable for the floor (i.e. outer) loop.
15265 {
15266 std::string FloorCntName =
15267 (Twine(".floor_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15268 VarDecl *FloorCntDecl =
15269 buildVarDecl(SemaRef, Loc: {}, Type: CntTy, Name: FloorCntName, Attrs: nullptr, OrigRef: OrigCntVar);
15270 FloorIndVars[I] = FloorCntDecl;
15271 }
15272
15273 // Iteration variable for the tile (i.e. inner) loop.
15274 {
15275 std::string TileCntName =
15276 (Twine(".tile_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15277
15278 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15279 // used by the expressions to derive the original iteration variable's
15280 // value from the logical iteration number.
15281 auto *TileCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
15282 TileCntDecl->setDeclName(
15283 &SemaRef.PP.getIdentifierTable().get(Name: TileCntName));
15284 TileIndVars[I] = TileCntDecl;
15285 }
15286
15287 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
15288 PreInits);
15289 }
15290
15291 // Once the original iteration values are set, append the innermost body.
15292 Stmt *Inner = Body;
15293
15294 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
15295 SizesClause, CurScope](int I) -> Expr * {
15296 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
15297
15298 if (DimTileSizeExpr->containsErrors())
15299 return nullptr;
15300
15301 if (isa<ConstantExpr>(Val: DimTileSizeExpr))
15302 return AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr));
15303
15304 // When the tile size is not a constant but a variable, it is possible to
15305 // pass non-positive numbers. For instance:
15306 // \code{c}
15307 // int a = 0;
15308 // #pragma omp tile sizes(a)
15309 // for (int i = 0; i < 42; ++i)
15310 // body(i);
15311 // \endcode
15312 // Although there is no meaningful interpretation of the tile size, the body
15313 // should still be executed 42 times to avoid surprises. To preserve the
15314 // invariant that every loop iteration is executed exactly once and not
15315 // cause an infinite loop, apply a minimum tile size of one.
15316 // Build expr:
15317 // \code{c}
15318 // (TS <= 0) ? 1 : TS
15319 // \endcode
15320 QualType DimTy = DimTileSizeExpr->getType();
15321 uint64_t DimWidth = Context.getTypeSize(T: DimTy);
15322 IntegerLiteral *Zero = IntegerLiteral::Create(
15323 C: Context, V: llvm::APInt::getZero(numBits: DimWidth), type: DimTy, l: {});
15324 IntegerLiteral *One =
15325 IntegerLiteral::Create(C: Context, V: llvm::APInt(DimWidth, 1), type: DimTy, l: {});
15326 Expr *Cond = AssertSuccess(R: SemaRef.BuildBinOp(
15327 S: CurScope, OpLoc: {}, Opc: BO_LE,
15328 LHSExpr: AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr)), RHSExpr: Zero));
15329 Expr *MinOne = new (Context) ConditionalOperator(
15330 Cond, {}, One, {},
15331 AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr)), DimTy,
15332 VK_PRValue, OK_Ordinary);
15333 return MinOne;
15334 };
15335
15336 // Create tile loops from the inside to the outside.
15337 //
15338 // Each intra-tile loop is emitted in its natural min-bounded form, which has
15339 // no per-iteration body predicate and vectorizes well when run directly:
15340 // for (.tile.iv = .floor.iv; .tile.iv < min(.floor.iv + T, N); ++.tile.iv)
15341 //
15342 // A loop-associated directive that *consumes* this loop (e.g. `collapse`)
15343 // instead needs a constant, floor-independent trip count to linearize the
15344 // nest, which the min() bound cannot give it. Rather than change the
15345 // emitted loop, we attach a droppable OMPInvariantPredicateBoundAttr hint
15346 // below carrying an equivalent rectangular reinterpretation:
15347 // RectCond : .tile.iv < .floor.iv + T -- rectangular bound, analyzed by
15348 // checkOpenMPIterationSpace in place of the stored condition
15349 // TileSize : T -- constant per-tile trip count
15350 // Predicate : .tile.iv < N -- remainder-tile overshoot,
15351 // applied as a body guard instead of shortening the trip count;
15352 // omitted when N is known to be a multiple of T, as there is
15353 // then no partial tile to guard against
15354 // Because the reinterpreted lower bound is still `.floor.iv`,
15355 // checkOpenMPIterationSpace sets IsNonRectangularLB on the matching floor
15356 // counter, so a collapsed `.tile.iv` re-reads the floor's current value
15357 // instead of a stale preheader snapshot. Collapsing through stacked tiles
15358 // (tile-of-tile) is not supported: the inner floor is not itself a collapsed
15359 // counter.
15360 for (int I = NumLoops - 1; I >= 0; --I) {
15361 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15362 Expr *NumIterations = LoopHelper.NumIterations;
15363 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15364 QualType IVTy = NumIterations->getType();
15365 Stmt *LoopStmt = LoopStmts[I];
15366
15367 // Commonly used variables. One of the constraints of an AST is that every
15368 // node object must appear at most once, hence we define a lambda that
15369 // creates a new AST node at every use.
15370 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
15371 OrigCntVar]() {
15372 return buildDeclRefExpr(S&: SemaRef, D: TileIndVars[I], Ty: IVTy,
15373 Loc: OrigCntVar->getExprLoc());
15374 };
15375
15376 // For init-statement: auto .tile.iv = .floor.iv
15377 SemaRef.AddInitializerToDecl(
15378 dcl: TileIndVars[I],
15379 init: SemaRef
15380 .DefaultLvalueConversion(
15381 E: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15382 .get(),
15383 /*DirectInit=*/false);
15384 Decl *CounterDecl = TileIndVars[I];
15385 StmtResult InitStmt = new (Context)
15386 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15387 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15388 if (!InitStmt.isUsable())
15389 return StmtError();
15390
15391 // For cond-expression:
15392 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
15393 Expr *DimTileSize = MakeDimTileSize(I);
15394 if (!DimTileSize)
15395 return StmtError();
15396 ExprResult EndOfTile = SemaRef.BuildBinOp(
15397 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
15398 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15399 RHSExpr: DimTileSize);
15400 if (!EndOfTile.isUsable())
15401 return StmtError();
15402 ExprResult IsPartialTile =
15403 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15404 LHSExpr: NumIterations, RHSExpr: EndOfTile.get());
15405 if (!IsPartialTile.isUsable())
15406 return StmtError();
15407 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
15408 QuestionLoc: LoopHelper.Cond->getBeginLoc(), ColonLoc: LoopHelper.Cond->getEndLoc(),
15409 CondExpr: IsPartialTile.get(), LHSExpr: NumIterations, RHSExpr: EndOfTile.get());
15410 if (!MinTileAndIterSpace.isUsable())
15411 return StmtError();
15412 ExprResult CondExpr =
15413 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15414 LHSExpr: MakeTileIVRef(), RHSExpr: MinTileAndIterSpace.get());
15415 if (!CondExpr.isUsable())
15416 return StmtError();
15417
15418 // For incr-statement: ++.tile.iv
15419 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15420 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeTileIVRef());
15421 if (!IncrStmt.isUsable())
15422 return StmtError();
15423
15424 // Build OMPInvariantPredicateBoundAttr hint (RectCond, TileSize,
15425 // Predicate).
15426 Expr *RectDimTileSize = MakeDimTileSize(I);
15427 if (!RectDimTileSize)
15428 return StmtError();
15429 ExprResult RectEndOfTile = SemaRef.BuildBinOp(
15430 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
15431 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15432 RHSExpr: RectDimTileSize);
15433 if (!RectEndOfTile.isUsable())
15434 return StmtError();
15435 ExprResult RectCond =
15436 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15437 LHSExpr: MakeTileIVRef(), RHSExpr: RectEndOfTile.get());
15438 Expr *TileSizeExpr = MakeDimTileSize(I);
15439 if (!TileSizeExpr)
15440 return StmtError();
15441 ExprResult TileSize = SemaRef.PerformImplicitConversion(
15442 From: TileSizeExpr, ToType: IVTy, Action: AssignmentAction::Converting,
15443 /*AllowExplicit=*/true);
15444 if (!RectCond.isUsable() || !TileSize.isUsable())
15445 return StmtError();
15446
15447 // The overshoot guard is only needed if the last tile can be partial. When
15448 // both the trip count and the tile size are known at compile time and the
15449 // former is a multiple of the latter, every tile is full, so leave the
15450 // predicate out. A dependent or run-time value makes
15451 // the evaluation fail, which keeps the guard.
15452 bool NoPartialTile = false;
15453 Expr::EvalResult TileSizeVal, NumIterationsVal;
15454 if (TileSizeExpr->EvaluateAsInt(Result&: TileSizeVal, Ctx: Context) &&
15455 NumIterations->EvaluateAsInt(Result&: NumIterationsVal, Ctx: Context)) {
15456 llvm::APSInt TS = TileSizeVal.Val.getInt();
15457 llvm::APSInt N = NumIterationsVal.Val.getInt();
15458 unsigned Width = std::max(a: TS.getBitWidth(), b: N.getBitWidth());
15459 TS = TS.extend(width: Width);
15460 N = N.extend(width: Width);
15461 NoPartialTile =
15462 TS.isStrictlyPositive() && N.isStrictlyPositive() && N.urem(RHS: TS) == 0;
15463 }
15464
15465 ExprResult Predicate;
15466 if (!NoPartialTile) {
15467 Predicate = SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(),
15468 Opc: BO_LT, LHSExpr: MakeTileIVRef(), RHSExpr: NumIterations);
15469 if (!Predicate.isUsable())
15470 return StmtError();
15471 }
15472
15473 // Statements to set the original iteration variable's value from the
15474 // logical iteration number.
15475 // Generated for loop is:
15476 // \code
15477 // Original_for_init;
15478 // for (auto .tile.iv = .floor.iv;
15479 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
15480 // ++.tile.iv) {
15481 // Original_Body;
15482 // Original_counter_update;
15483 // }
15484 // \endcode
15485 // FIXME: If the innermost body is an loop itself, inserting these
15486 // statements stops it being recognized as a perfectly nested loop (e.g.
15487 // for applying tiling again). If this is the case, sink the expressions
15488 // further into the inner loop.
15489 SmallVector<Stmt *, 4> BodyParts;
15490 BodyParts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
15491 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
15492 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
15493 BodyParts.push_back(Elt: Inner);
15494 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
15495 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
15496 Inner = new (Context)
15497 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15498 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15499 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15500
15501 // Attach the droppable reinterpretation attribute to the intra-tile loop.
15502 auto *Hint = OMPInvariantPredicateBoundAttr::CreateImplicit(
15503 Ctx&: Context, RectCond: RectCond.get(), TileSize: TileSize.get(),
15504 Predicate: Predicate.isUsable() ? Predicate.get() : nullptr,
15505 Range: Inner->getSourceRange());
15506 Inner =
15507 AttributedStmt::Create(C: Context, Loc: Inner->getBeginLoc(), Attrs: {Hint}, SubStmt: Inner);
15508 }
15509
15510 // Create floor loops from the inside to the outside.
15511 for (int I = NumLoops - 1; I >= 0; --I) {
15512 auto &LoopHelper = LoopHelpers[I];
15513 Expr *NumIterations = LoopHelper.NumIterations;
15514 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15515 QualType IVTy = NumIterations->getType();
15516
15517 // For init-statement: auto .floor.iv = 0
15518 SemaRef.AddInitializerToDecl(
15519 dcl: FloorIndVars[I],
15520 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
15521 /*DirectInit=*/false);
15522 Decl *CounterDecl = FloorIndVars[I];
15523 StmtResult InitStmt = new (Context)
15524 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15525 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15526 if (!InitStmt.isUsable())
15527 return StmtError();
15528
15529 // For cond-expression: .floor.iv < NumIterations
15530 ExprResult CondExpr = SemaRef.BuildBinOp(
15531 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15532 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15533 RHSExpr: NumIterations);
15534 if (!CondExpr.isUsable())
15535 return StmtError();
15536
15537 // For incr-statement: .floor.iv += DimTileSize
15538 Expr *DimTileSize = MakeDimTileSize(I);
15539 if (!DimTileSize)
15540 return StmtError();
15541 ExprResult IncrStmt = SemaRef.BuildBinOp(
15542 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
15543 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15544 RHSExpr: DimTileSize);
15545 if (!IncrStmt.isUsable())
15546 return StmtError();
15547
15548 Inner = new (Context)
15549 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15550 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15551 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15552 }
15553
15554 return OMPTileDirective::Create(C: Context, StartLoc, EndLoc, Clauses, NumLoops,
15555 AssociatedStmt: AStmt, TransformedStmt: Inner,
15556 PreInits: buildPreInits(Context, PreInits));
15557}
15558
15559StmtResult SemaOpenMP::ActOnOpenMPStripeDirective(ArrayRef<OMPClause *> Clauses,
15560 Stmt *AStmt,
15561 SourceLocation StartLoc,
15562 SourceLocation EndLoc) {
15563 ASTContext &Context = getASTContext();
15564 Scope *CurScope = SemaRef.getCurScope();
15565
15566 const auto *SizesClause =
15567 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15568 if (!SizesClause ||
15569 llvm::any_of(Range: SizesClause->getSizesRefs(), P: [](const Expr *SizeExpr) {
15570 return !SizeExpr || SizeExpr->containsErrors();
15571 }))
15572 return StmtError();
15573 unsigned NumLoops = SizesClause->getNumSizes();
15574
15575 // Empty statement should only be possible if there already was an error.
15576 if (!AStmt)
15577 return StmtError();
15578
15579 // Verify and diagnose loop nest.
15580 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
15581 Stmt *Body = nullptr;
15582 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
15583 if (!checkTransformableLoopNest(Kind: OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15584 Body, OriginalInits))
15585 return StmtError();
15586
15587 // Delay striping to when template is completely instantiated.
15588 if (SemaRef.CurContext->isDependentContext())
15589 return OMPStripeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15590 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
15591
15592 assert(LoopHelpers.size() == NumLoops &&
15593 "Expecting loop iteration space dimensionality to match number of "
15594 "affected loops");
15595 assert(OriginalInits.size() == NumLoops &&
15596 "Expecting loop iteration space dimensionality to match number of "
15597 "affected loops");
15598
15599 // Collect all affected loop statements.
15600 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15601 collectLoopStmts(AStmt, LoopStmts);
15602
15603 SmallVector<Stmt *, 4> PreInits;
15604 CaptureVars CopyTransformer(SemaRef);
15605
15606 // Create iteration variables for the generated loops.
15607 SmallVector<VarDecl *, 4> FloorIndVars;
15608 SmallVector<VarDecl *, 4> StripeIndVars;
15609 FloorIndVars.resize(N: NumLoops);
15610 StripeIndVars.resize(N: NumLoops);
15611 for (unsigned I : llvm::seq<unsigned>(Size: NumLoops)) {
15612 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15613
15614 assert(LoopHelper.Counters.size() == 1 &&
15615 "Expect single-dimensional loop iteration space");
15616 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15617 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15618 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15619 QualType CntTy = IterVarRef->getType();
15620
15621 // Iteration variable for the stripe (i.e. outer) loop.
15622 {
15623 std::string FloorCntName =
15624 (Twine(".floor_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15625 VarDecl *FloorCntDecl =
15626 buildVarDecl(SemaRef, Loc: {}, Type: CntTy, Name: FloorCntName, Attrs: nullptr, OrigRef: OrigCntVar);
15627 FloorIndVars[I] = FloorCntDecl;
15628 }
15629
15630 // Iteration variable for the stripe (i.e. inner) loop.
15631 {
15632 std::string StripeCntName =
15633 (Twine(".stripe_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15634
15635 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15636 // used by the expressions to derive the original iteration variable's
15637 // value from the logical iteration number.
15638 auto *StripeCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
15639 StripeCntDecl->setDeclName(
15640 &SemaRef.PP.getIdentifierTable().get(Name: StripeCntName));
15641 StripeIndVars[I] = StripeCntDecl;
15642 }
15643
15644 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
15645 PreInits);
15646 }
15647
15648 // Once the original iteration values are set, append the innermost body.
15649 Stmt *Inner = Body;
15650
15651 auto MakeDimStripeSize = [&](int I) -> Expr * {
15652 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15653 if (isa<ConstantExpr>(Val: DimStripeSizeExpr))
15654 return AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr));
15655
15656 // When the stripe size is not a constant but a variable, it is possible to
15657 // pass non-positive numbers. For instance:
15658 // \code{c}
15659 // int a = 0;
15660 // #pragma omp stripe sizes(a)
15661 // for (int i = 0; i < 42; ++i)
15662 // body(i);
15663 // \endcode
15664 // Although there is no meaningful interpretation of the stripe size, the
15665 // body should still be executed 42 times to avoid surprises. To preserve
15666 // the invariant that every loop iteration is executed exactly once and not
15667 // cause an infinite loop, apply a minimum stripe size of one.
15668 // Build expr:
15669 // \code{c}
15670 // (TS <= 0) ? 1 : TS
15671 // \endcode
15672 QualType DimTy = DimStripeSizeExpr->getType();
15673 uint64_t DimWidth = Context.getTypeSize(T: DimTy);
15674 IntegerLiteral *Zero = IntegerLiteral::Create(
15675 C: Context, V: llvm::APInt::getZero(numBits: DimWidth), type: DimTy, l: {});
15676 IntegerLiteral *One =
15677 IntegerLiteral::Create(C: Context, V: llvm::APInt(DimWidth, 1), type: DimTy, l: {});
15678 Expr *Cond = AssertSuccess(R: SemaRef.BuildBinOp(
15679 S: CurScope, OpLoc: {}, Opc: BO_LE,
15680 LHSExpr: AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr)), RHSExpr: Zero));
15681 Expr *MinOne = new (Context) ConditionalOperator(
15682 Cond, {}, One, {},
15683 AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr)), DimTy,
15684 VK_PRValue, OK_Ordinary);
15685 return MinOne;
15686 };
15687
15688 // Create stripe loops from the inside to the outside.
15689 for (int I = NumLoops - 1; I >= 0; --I) {
15690 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15691 Expr *NumIterations = LoopHelper.NumIterations;
15692 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15693 QualType IVTy = NumIterations->getType();
15694 Stmt *LoopStmt = LoopStmts[I];
15695
15696 // For init-statement: auto .stripe.iv = .floor.iv
15697 SemaRef.AddInitializerToDecl(
15698 dcl: StripeIndVars[I],
15699 init: SemaRef
15700 .DefaultLvalueConversion(
15701 E: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15702 .get(),
15703 /*DirectInit=*/false);
15704 Decl *CounterDecl = StripeIndVars[I];
15705 StmtResult InitStmt = new (Context)
15706 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15707 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15708 if (!InitStmt.isUsable())
15709 return StmtError();
15710
15711 // For cond-expression:
15712 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
15713 ExprResult EndOfStripe = SemaRef.BuildBinOp(
15714 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
15715 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15716 RHSExpr: MakeDimStripeSize(I));
15717 if (!EndOfStripe.isUsable())
15718 return StmtError();
15719 ExprResult IsPartialStripe =
15720 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15721 LHSExpr: NumIterations, RHSExpr: EndOfStripe.get());
15722 if (!IsPartialStripe.isUsable())
15723 return StmtError();
15724 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
15725 QuestionLoc: LoopHelper.Cond->getBeginLoc(), ColonLoc: LoopHelper.Cond->getEndLoc(),
15726 CondExpr: IsPartialStripe.get(), LHSExpr: NumIterations, RHSExpr: EndOfStripe.get());
15727 if (!MinStripeAndIterSpace.isUsable())
15728 return StmtError();
15729 ExprResult CondExpr = SemaRef.BuildBinOp(
15730 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15731 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars: StripeIndVars, I, IVTy, OrigCntVar),
15732 RHSExpr: MinStripeAndIterSpace.get());
15733 if (!CondExpr.isUsable())
15734 return StmtError();
15735
15736 // For incr-statement: ++.stripe.iv
15737 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15738 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc,
15739 Input: makeFloorIVRef(SemaRef, FloorIndVars: StripeIndVars, I, IVTy, OrigCntVar));
15740 if (!IncrStmt.isUsable())
15741 return StmtError();
15742
15743 // Statements to set the original iteration variable's value from the
15744 // logical iteration number.
15745 // Generated for loop is:
15746 // \code
15747 // Original_for_init;
15748 // for (auto .stripe.iv = .floor.iv;
15749 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
15750 // ++.stripe.iv) {
15751 // Original_Body;
15752 // Original_counter_update;
15753 // }
15754 // \endcode
15755 // FIXME: If the innermost body is a loop itself, inserting these
15756 // statements stops it being recognized as a perfectly nested loop (e.g.
15757 // for applying another loop transformation). If this is the case, sink the
15758 // expressions further into the inner loop.
15759 SmallVector<Stmt *, 4> BodyParts;
15760 BodyParts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
15761 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
15762 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
15763 BodyParts.push_back(Elt: Inner);
15764 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
15765 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
15766 Inner = new (Context)
15767 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15768 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15769 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15770 }
15771
15772 // Create grid loops from the inside to the outside.
15773 for (int I = NumLoops - 1; I >= 0; --I) {
15774 auto &LoopHelper = LoopHelpers[I];
15775 Expr *NumIterations = LoopHelper.NumIterations;
15776 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15777 QualType IVTy = NumIterations->getType();
15778
15779 // For init-statement: auto .grid.iv = 0
15780 SemaRef.AddInitializerToDecl(
15781 dcl: FloorIndVars[I],
15782 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
15783 /*DirectInit=*/false);
15784 Decl *CounterDecl = FloorIndVars[I];
15785 StmtResult InitStmt = new (Context)
15786 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15787 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15788 if (!InitStmt.isUsable())
15789 return StmtError();
15790
15791 // For cond-expression: .floor.iv < NumIterations
15792 ExprResult CondExpr = SemaRef.BuildBinOp(
15793 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15794 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15795 RHSExpr: NumIterations);
15796 if (!CondExpr.isUsable())
15797 return StmtError();
15798
15799 // For incr-statement: .floor.iv += DimStripeSize
15800 ExprResult IncrStmt = SemaRef.BuildBinOp(
15801 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
15802 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15803 RHSExpr: MakeDimStripeSize(I));
15804 if (!IncrStmt.isUsable())
15805 return StmtError();
15806
15807 Inner = new (Context)
15808 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15809 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15810 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15811 }
15812
15813 return OMPStripeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15814 NumLoops, AssociatedStmt: AStmt, TransformedStmt: Inner,
15815 PreInits: buildPreInits(Context, PreInits));
15816}
15817
15818StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
15819 Stmt *AStmt,
15820 SourceLocation StartLoc,
15821 SourceLocation EndLoc) {
15822 ASTContext &Context = getASTContext();
15823 Scope *CurScope = SemaRef.getCurScope();
15824 // Empty statement should only be possible if there already was an error.
15825 if (!AStmt)
15826 return StmtError();
15827
15828 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
15829 MutuallyExclusiveClauses: {OMPC_partial, OMPC_full}))
15830 return StmtError();
15831
15832 const OMPFullClause *FullClause =
15833 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15834 const OMPPartialClause *PartialClause =
15835 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15836 assert(!(FullClause && PartialClause) &&
15837 "mutual exclusivity must have been checked before");
15838
15839 constexpr unsigned NumLoops = 1;
15840 Stmt *Body = nullptr;
15841 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
15842 NumLoops);
15843 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15844 if (!checkTransformableLoopNest(Kind: OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15845 Body, OriginalInits))
15846 return StmtError();
15847
15848 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15849
15850 // Delay unrolling to when template is completely instantiated.
15851 if (SemaRef.CurContext->isDependentContext())
15852 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
15853 NumGeneratedTopLevelLoops, TransformedStmt: nullptr,
15854 PreInits: nullptr);
15855
15856 assert(LoopHelpers.size() == NumLoops &&
15857 "Expecting a single-dimensional loop iteration space");
15858 assert(OriginalInits.size() == NumLoops &&
15859 "Expecting a single-dimensional loop iteration space");
15860 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15861
15862 if (FullClause) {
15863 if (!VerifyPositiveIntegerConstantInClause(
15864 Op: LoopHelper.NumIterations, CKind: OMPC_full, /*StrictlyPositive=*/false,
15865 /*SuppressExprDiags=*/true)
15866 .isUsable()) {
15867 Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_unroll_full_variable_trip_count);
15868 Diag(Loc: FullClause->getBeginLoc(), DiagID: diag::note_omp_directive_here)
15869 << "#pragma omp unroll full";
15870 return StmtError();
15871 }
15872 }
15873
15874 // The generated loop may only be passed to other loop-associated directive
15875 // when a partial clause is specified. Without the requirement it is
15876 // sufficient to generate loop unroll metadata at code-generation.
15877 if (NumGeneratedTopLevelLoops == 0)
15878 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
15879 NumGeneratedTopLevelLoops, TransformedStmt: nullptr,
15880 PreInits: nullptr);
15881
15882 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15883 // associated with another loop directive.
15884 //
15885 // The canonical loop analysis return by checkTransformableLoopNest assumes
15886 // the following structure to be the same loop without transformations or
15887 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15888 // LoopHelper.Counters;
15889 // for (; IV < LoopHelper.NumIterations; ++IV) {
15890 // LoopHelper.Updates;
15891 // Body;
15892 // }
15893 // \endcode
15894 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15895 // and referenced by LoopHelper.IterationVarRef.
15896 //
15897 // The unrolling directive transforms this into the following loop:
15898 // \code
15899 // OriginalInits; \
15900 // LoopHelper.PreInits; > NewPreInits
15901 // LoopHelper.Counters; /
15902 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15903 // #pragma clang loop unroll_count(Factor)
15904 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15905 // {
15906 // LoopHelper.Updates;
15907 // Body;
15908 // }
15909 // }
15910 // \endcode
15911 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15912 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15913 // references it. If the partially unrolled loop is associated with another
15914 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15915 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15916 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15917 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15918 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15919 // property of the OMPLoopBasedDirective instead of statements in
15920 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15921 // of a canonical loop nest where these PreInits are emitted before the
15922 // outermost directive.
15923
15924 // Find the loop statement.
15925 Stmt *LoopStmt = nullptr;
15926 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
15927
15928 // Determine the PreInit declarations.
15929 SmallVector<Stmt *, 4> PreInits;
15930 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
15931
15932 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15933 QualType IVTy = IterationVarRef->getType();
15934 assert(LoopHelper.Counters.size() == 1 &&
15935 "Expecting a single-dimensional loop iteration space");
15936 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15937
15938 // Determine the unroll factor.
15939 uint64_t Factor;
15940 SourceLocation FactorLoc;
15941 if (Expr *FactorVal = PartialClause->getFactor();
15942 FactorVal && !FactorVal->containsErrors()) {
15943 Factor = FactorVal->getIntegerConstantExpr(Ctx: Context)->getZExtValue();
15944 FactorLoc = FactorVal->getExprLoc();
15945 } else {
15946 // TODO: Use a better profitability model.
15947 Factor = 2;
15948 }
15949 assert(Factor > 0 && "Expected positive unroll factor");
15950 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15951 return IntegerLiteral::Create(
15952 C: getASTContext(), V: llvm::APInt(getASTContext().getIntWidth(T: IVTy), Factor),
15953 type: IVTy, l: FactorLoc);
15954 };
15955
15956 // Iteration variable SourceLocations.
15957 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15958 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15959 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15960
15961 // Internal variable names.
15962 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15963 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15964 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15965
15966 // Create the iteration variable for the unrolled loop.
15967 VarDecl *OuterIVDecl =
15968 buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: OuterIVName, Attrs: nullptr, OrigRef: OrigVar);
15969 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15970 return buildDeclRefExpr(S&: SemaRef, D: OuterIVDecl, Ty: IVTy, Loc: OrigVarLoc);
15971 };
15972
15973 // Iteration variable for the inner loop: Reuse the iteration variable created
15974 // by checkOpenMPLoop.
15975 auto *InnerIVDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
15976 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name: InnerIVName));
15977 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15978 return buildDeclRefExpr(S&: SemaRef, D: InnerIVDecl, Ty: IVTy, Loc: OrigVarLoc);
15979 };
15980
15981 // Make a copy of the NumIterations expression for each use: By the AST
15982 // constraints, every expression object in a DeclContext must be unique.
15983 CaptureVars CopyTransformer(SemaRef);
15984 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15985 return AssertSuccess(
15986 R: CopyTransformer.TransformExpr(E: LoopHelper.NumIterations));
15987 };
15988
15989 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15990 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(E: MakeOuterRef());
15991 SemaRef.AddInitializerToDecl(dcl: InnerIVDecl, init: LValueConv.get(),
15992 /*DirectInit=*/false);
15993 StmtResult InnerInit = new (Context)
15994 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15995 if (!InnerInit.isUsable())
15996 return StmtError();
15997
15998 // Inner For cond-expression:
15999 // \code
16000 // .unroll_inner.iv < .unrolled.iv + Factor &&
16001 // .unroll_inner.iv < NumIterations
16002 // \endcode
16003 // This conjunction of two conditions allows ScalarEvolution to derive the
16004 // maximum trip count of the inner loop.
16005 ExprResult EndOfTile =
16006 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
16007 LHSExpr: MakeOuterRef(), RHSExpr: MakeFactorExpr());
16008 if (!EndOfTile.isUsable())
16009 return StmtError();
16010 ExprResult InnerCond1 =
16011 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
16012 LHSExpr: MakeInnerRef(), RHSExpr: EndOfTile.get());
16013 if (!InnerCond1.isUsable())
16014 return StmtError();
16015 ExprResult InnerCond2 =
16016 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
16017 LHSExpr: MakeInnerRef(), RHSExpr: MakeNumIterations());
16018 if (!InnerCond2.isUsable())
16019 return StmtError();
16020 ExprResult InnerCond =
16021 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LAnd,
16022 LHSExpr: InnerCond1.get(), RHSExpr: InnerCond2.get());
16023 if (!InnerCond.isUsable())
16024 return StmtError();
16025
16026 // Inner For incr-statement: ++.unroll_inner.iv
16027 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
16028 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeInnerRef());
16029 if (!InnerIncr.isUsable())
16030 return StmtError();
16031
16032 // Inner For statement.
16033 SmallVector<Stmt *> InnerBodyStmts;
16034 InnerBodyStmts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
16035 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
16036 InnerBodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
16037 InnerBodyStmts.push_back(Elt: Body);
16038 CompoundStmt *InnerBody =
16039 CompoundStmt::Create(C: getASTContext(), Stmts: InnerBodyStmts, FPFeatures: FPOptionsOverride(),
16040 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
16041 ForStmt *InnerFor = new (Context)
16042 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
16043 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
16044 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16045
16046 // Unroll metadata for the inner loop.
16047 // This needs to take into account the remainder portion of the unrolled loop,
16048 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
16049 // supports multiple loop exits. Instead, unroll using a factor equivalent to
16050 // the maximum trip count, which will also generate a remainder loop. Just
16051 // `unroll(enable)` (which could have been useful if the user has not
16052 // specified a concrete factor; even though the outer loop cannot be
16053 // influenced anymore, would avoid more code bloat than necessary) will refuse
16054 // the loop because "Won't unroll; remainder loop could not be generated when
16055 // assuming runtime trip count". Even if it did work, it must not choose a
16056 // larger unroll factor than the maximum loop length, or it would always just
16057 // execute the remainder loop.
16058 LoopHintAttr *UnrollHintAttr =
16059 LoopHintAttr::CreateImplicit(Ctx&: Context, Option: LoopHintAttr::UnrollCount,
16060 State: LoopHintAttr::Numeric, Value: MakeFactorExpr());
16061 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
16062 C: getASTContext(), Loc: StartLoc, Attrs: {UnrollHintAttr}, SubStmt: InnerFor);
16063
16064 // Outer For init-statement: auto .unrolled.iv = 0
16065 SemaRef.AddInitializerToDecl(
16066 dcl: OuterIVDecl,
16067 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
16068 /*DirectInit=*/false);
16069 StmtResult OuterInit = new (Context)
16070 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
16071 if (!OuterInit.isUsable())
16072 return StmtError();
16073
16074 // Outer For cond-expression: .unrolled.iv < NumIterations
16075 ExprResult OuterConde =
16076 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
16077 LHSExpr: MakeOuterRef(), RHSExpr: MakeNumIterations());
16078 if (!OuterConde.isUsable())
16079 return StmtError();
16080
16081 // Outer For incr-statement: .unrolled.iv += Factor
16082 ExprResult OuterIncr =
16083 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
16084 LHSExpr: MakeOuterRef(), RHSExpr: MakeFactorExpr());
16085 if (!OuterIncr.isUsable())
16086 return StmtError();
16087
16088 // Outer For statement.
16089 ForStmt *OuterFor = new (Context)
16090 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
16091 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
16092 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16093
16094 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
16095 NumGeneratedTopLevelLoops, TransformedStmt: OuterFor,
16096 PreInits: buildPreInits(Context, PreInits));
16097}
16098
16099StmtResult SemaOpenMP::ActOnOpenMPReverseDirective(Stmt *AStmt,
16100 SourceLocation StartLoc,
16101 SourceLocation EndLoc) {
16102 ASTContext &Context = getASTContext();
16103 Scope *CurScope = SemaRef.getCurScope();
16104
16105 // Empty statement should only be possible if there already was an error.
16106 if (!AStmt)
16107 return StmtError();
16108
16109 constexpr unsigned NumLoops = 1;
16110 Stmt *Body = nullptr;
16111 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
16112 NumLoops);
16113 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
16114 if (!checkTransformableLoopNest(Kind: OMPD_reverse, AStmt, NumLoops, LoopHelpers,
16115 Body, OriginalInits))
16116 return StmtError();
16117
16118 // Delay applying the transformation to when template is completely
16119 // instantiated.
16120 if (SemaRef.CurContext->isDependentContext())
16121 return OMPReverseDirective::Create(C: Context, StartLoc, EndLoc, AssociatedStmt: AStmt,
16122 NumLoops, TransformedStmt: nullptr, PreInits: nullptr);
16123
16124 assert(LoopHelpers.size() == NumLoops &&
16125 "Expecting a single-dimensional loop iteration space");
16126 assert(OriginalInits.size() == NumLoops &&
16127 "Expecting a single-dimensional loop iteration space");
16128 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
16129
16130 // Find the loop statement.
16131 Stmt *LoopStmt = nullptr;
16132 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
16133
16134 // Determine the PreInit declarations.
16135 SmallVector<Stmt *> PreInits;
16136 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
16137
16138 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
16139 QualType IVTy = IterationVarRef->getType();
16140 uint64_t IVWidth = Context.getTypeSize(T: IVTy);
16141 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
16142
16143 // Iteration variable SourceLocations.
16144 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
16145 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
16146 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
16147
16148 // Locations pointing to the transformation.
16149 SourceLocation TransformLoc = StartLoc;
16150 SourceLocation TransformLocBegin = StartLoc;
16151 SourceLocation TransformLocEnd = EndLoc;
16152
16153 // Internal variable names.
16154 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
16155 SmallString<64> ForwardIVName(".forward.iv.");
16156 ForwardIVName += OrigVarName;
16157 SmallString<64> ReversedIVName(".reversed.iv.");
16158 ReversedIVName += OrigVarName;
16159
16160 // LoopHelper.Updates will read the logical iteration number from
16161 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
16162 // that logical iteration from it, then assign it to the user loop counter
16163 // variable. We cannot directly use LoopHelper.IterationVarRef as the
16164 // induction variable of the generated loop because it may cause an underflow:
16165 // \code{.c}
16166 // for (unsigned i = 0; i < n; ++i)
16167 // body(i);
16168 // \endcode
16169 //
16170 // Naive reversal:
16171 // \code{.c}
16172 // for (unsigned i = n-1; i >= 0; --i)
16173 // body(i);
16174 // \endcode
16175 //
16176 // Instead, we introduce a new iteration variable representing the logical
16177 // iteration counter of the original loop, convert it to the logical iteration
16178 // number of the reversed loop, then let LoopHelper.Updates compute the user's
16179 // loop iteration variable from it.
16180 // \code{.cpp}
16181 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
16182 // auto .reversed.iv = n - .forward.iv - 1;
16183 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
16184 // body(i); // Body
16185 // }
16186 // \endcode
16187
16188 // Subexpressions with more than one use. One of the constraints of an AST is
16189 // that every node object must appear at most once, hence we define a lambda
16190 // that creates a new AST node at every use.
16191 CaptureVars CopyTransformer(SemaRef);
16192 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
16193 return AssertSuccess(
16194 R: CopyTransformer.TransformExpr(E: LoopHelper.NumIterations));
16195 };
16196
16197 // Create the iteration variable for the forward loop (from 0 to n-1).
16198 VarDecl *ForwardIVDecl =
16199 buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: ForwardIVName, Attrs: nullptr, OrigRef: OrigVar);
16200 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
16201 OrigVarLoc]() {
16202 return buildDeclRefExpr(S&: SemaRef, D: ForwardIVDecl, Ty: IVTy, Loc: OrigVarLoc);
16203 };
16204
16205 // Iteration variable for the reversed induction variable (from n-1 downto 0):
16206 // Reuse the iteration variable created by checkOpenMPLoop.
16207 auto *ReversedIVDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
16208 ReversedIVDecl->setDeclName(
16209 &SemaRef.PP.getIdentifierTable().get(Name: ReversedIVName));
16210
16211 // For init-statement:
16212 // \code{.cpp}
16213 // auto .forward.iv = 0;
16214 // \endcode
16215 auto *Zero = IntegerLiteral::Create(C: Context, V: llvm::APInt::getZero(numBits: IVWidth),
16216 type: ForwardIVDecl->getType(), l: OrigVarLoc);
16217 SemaRef.AddInitializerToDecl(dcl: ForwardIVDecl, init: Zero, /*DirectInit=*/false);
16218 StmtResult Init = new (Context)
16219 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
16220 if (!Init.isUsable())
16221 return StmtError();
16222
16223 // Forward iv cond-expression:
16224 // \code{.cpp}
16225 // .forward.iv < MakeNumIterations()
16226 // \endcode
16227 ExprResult Cond =
16228 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
16229 LHSExpr: MakeForwardRef(), RHSExpr: MakeNumIterations());
16230 if (!Cond.isUsable())
16231 return StmtError();
16232
16233 // Forward incr-statement:
16234 // \code{.c}
16235 // ++.forward.iv
16236 // \endcode
16237 ExprResult Incr = SemaRef.BuildUnaryOp(S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(),
16238 Opc: UO_PreInc, Input: MakeForwardRef());
16239 if (!Incr.isUsable())
16240 return StmtError();
16241
16242 // Reverse the forward-iv:
16243 // \code{.cpp}
16244 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
16245 // \endcode
16246 auto *One = IntegerLiteral::Create(C: Context, V: llvm::APInt(IVWidth, 1), type: IVTy,
16247 l: TransformLoc);
16248 ExprResult Minus = SemaRef.BuildBinOp(S: CurScope, OpLoc: TransformLoc, Opc: BO_Sub,
16249 LHSExpr: MakeNumIterations(), RHSExpr: One);
16250 if (!Minus.isUsable())
16251 return StmtError();
16252 Minus = SemaRef.BuildBinOp(S: CurScope, OpLoc: TransformLoc, Opc: BO_Sub, LHSExpr: Minus.get(),
16253 RHSExpr: MakeForwardRef());
16254 if (!Minus.isUsable())
16255 return StmtError();
16256 StmtResult InitReversed = new (Context) DeclStmt(
16257 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
16258 if (!InitReversed.isUsable())
16259 return StmtError();
16260 SemaRef.AddInitializerToDecl(dcl: ReversedIVDecl, init: Minus.get(),
16261 /*DirectInit=*/false);
16262
16263 // The new loop body.
16264 SmallVector<Stmt *, 4> BodyStmts;
16265 BodyStmts.reserve(N: LoopHelper.Updates.size() + 2 +
16266 (isa<CXXForRangeStmt>(Val: LoopStmt) ? 1 : 0));
16267 BodyStmts.push_back(Elt: InitReversed.get());
16268 llvm::append_range(C&: BodyStmts, R&: LoopHelper.Updates);
16269 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
16270 BodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
16271 BodyStmts.push_back(Elt: Body);
16272 auto *ReversedBody =
16273 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
16274 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
16275
16276 // Finally create the reversed For-statement.
16277 auto *ReversedFor = new (Context)
16278 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
16279 ReversedBody, LoopHelper.Init->getBeginLoc(),
16280 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16281 return OMPReverseDirective::Create(C: Context, StartLoc, EndLoc, AssociatedStmt: AStmt, NumLoops,
16282 TransformedStmt: ReversedFor,
16283 PreInits: buildPreInits(Context, PreInits));
16284}
16285
16286/// Build the AST for \#pragma omp split counts(c1, c2, ...).
16287///
16288/// Splits the single associated loop into N consecutive loops, where N is the
16289/// number of count expressions.
16290StmtResult SemaOpenMP::ActOnOpenMPSplitDirective(ArrayRef<OMPClause *> Clauses,
16291 Stmt *AStmt,
16292 SourceLocation StartLoc,
16293 SourceLocation EndLoc) {
16294 ASTContext &Context = getASTContext();
16295 Scope *CurScope = SemaRef.getCurScope();
16296
16297 // Empty statement should only be possible if there already was an error.
16298 if (!AStmt)
16299 return StmtError();
16300
16301 const auto *CountsClause =
16302 OMPExecutableDirective::getSingleClause<OMPCountsClause>(Clauses);
16303 if (!CountsClause)
16304 return StmtError();
16305
16306 // Split applies to a single loop; check it is transformable and get helpers.
16307 constexpr unsigned NumLoops = 1;
16308 Stmt *Body = nullptr;
16309 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
16310 NumLoops);
16311 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
16312 if (!checkTransformableLoopNest(Kind: OMPD_split, AStmt, NumLoops, LoopHelpers,
16313 Body, OriginalInits))
16314 return StmtError();
16315
16316 // Delay applying the transformation to when template is completely
16317 // instantiated.
16318 if (SemaRef.CurContext->isDependentContext())
16319 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16320 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16321
16322 assert(LoopHelpers.size() == NumLoops &&
16323 "Expecting a single-dimensional loop iteration space");
16324 assert(OriginalInits.size() == NumLoops &&
16325 "Expecting a single-dimensional loop iteration space");
16326 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
16327
16328 // Find the loop statement.
16329 Stmt *LoopStmt = nullptr;
16330 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
16331
16332 // Determine the PreInit declarations.
16333 SmallVector<Stmt *> PreInits;
16334 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
16335
16336 // Type and name of the original loop variable; we create one IV per segment
16337 // and assign it to the original var so the body sees the same name.
16338 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
16339 QualType IVTy = IterationVarRef->getType();
16340 uint64_t IVWidth = Context.getTypeSize(T: IVTy);
16341 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
16342
16343 // Iteration variable SourceLocations.
16344 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
16345 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
16346 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
16347 // Internal variable names.
16348 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
16349
16350 if (!CountsClause->hasOmpFill())
16351 return StmtError();
16352 unsigned FillIdx = *CountsClause->getOmpFillIndex();
16353
16354 unsigned NumItems = CountsClause->getNumCounts();
16355 SmallVector<uint64_t, 4> CountValues(NumItems, 0);
16356 ArrayRef<Expr *> Refs = CountsClause->getCountsRefs();
16357 for (unsigned I = 0; I < NumItems; ++I) {
16358 if (I == FillIdx)
16359 continue;
16360 Expr *CountExpr = Refs[I];
16361 if (!CountExpr)
16362 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16363 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16364 std::optional<llvm::APSInt> OptVal =
16365 CountExpr->getIntegerConstantExpr(Ctx: Context);
16366 if (!OptVal || OptVal->isNegative())
16367 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16368 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16369 CountValues[I] = OptVal->getZExtValue();
16370 }
16371
16372 Expr *NumIterExpr = LoopHelper.NumIterations;
16373
16374 uint64_t RightSum = 0;
16375 for (unsigned I = FillIdx + 1; I < NumItems; ++I)
16376 RightSum += CountValues[I];
16377
16378 auto MakeIntLit = [&](uint64_t Val) {
16379 return IntegerLiteral::Create(C: Context, V: llvm::APInt(IVWidth, Val), type: IVTy,
16380 l: OrigVarLoc);
16381 };
16382
16383 size_t NumSegments = NumItems;
16384 SmallVector<Stmt *, 4> SplitLoops;
16385
16386 auto *IterVarDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
16387 SplitLoops.push_back(Elt: new (Context) DeclStmt(DeclGroupRef(IterVarDecl),
16388 IterationVarRef->getBeginLoc(),
16389 IterationVarRef->getEndLoc()));
16390
16391 uint64_t LeftAccum = 0;
16392 uint64_t RightRemaining = RightSum;
16393
16394 for (size_t Seg = 0; Seg < NumSegments; ++Seg) {
16395 Expr *StartExpr = nullptr;
16396 Expr *EndExpr = nullptr;
16397
16398 if (Seg < FillIdx) {
16399 StartExpr = MakeIntLit(LeftAccum);
16400 LeftAccum += CountValues[Seg];
16401 EndExpr = MakeIntLit(LeftAccum);
16402 } else if (Seg == FillIdx) {
16403 StartExpr = MakeIntLit(LeftAccum);
16404 if (RightRemaining == 0) {
16405 EndExpr = NumIterExpr;
16406 } else {
16407 ExprResult Sub =
16408 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16409 RHSExpr: MakeIntLit(RightRemaining));
16410 if (!Sub.isUsable())
16411 return StmtError();
16412 EndExpr = Sub.get();
16413 }
16414 } else {
16415 if (RightRemaining == RightSum) {
16416 if (RightSum == 0)
16417 StartExpr = NumIterExpr;
16418 else {
16419 ExprResult Sub =
16420 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16421 RHSExpr: MakeIntLit(RightRemaining));
16422 if (!Sub.isUsable())
16423 return StmtError();
16424 StartExpr = Sub.get();
16425 }
16426 } else {
16427 ExprResult Sub =
16428 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16429 RHSExpr: MakeIntLit(RightRemaining));
16430 if (!Sub.isUsable())
16431 return StmtError();
16432 StartExpr = Sub.get();
16433 }
16434 RightRemaining -= CountValues[Seg];
16435 if (RightRemaining == 0)
16436 EndExpr = NumIterExpr;
16437 else {
16438 ExprResult Sub =
16439 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16440 RHSExpr: MakeIntLit(RightRemaining));
16441 if (!Sub.isUsable())
16442 return StmtError();
16443 EndExpr = Sub.get();
16444 }
16445 }
16446
16447 SmallString<64> IVName(".split.iv.");
16448 IVName += (Twine(Seg) + "." + OrigVarName).str();
16449 VarDecl *IVDecl = buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: IVName, Attrs: nullptr, OrigRef: OrigVar);
16450 auto MakeIVRef = [&SemaRef = this->SemaRef, IVDecl, IVTy, OrigVarLoc]() {
16451 return buildDeclRefExpr(S&: SemaRef, D: IVDecl, Ty: IVTy, Loc: OrigVarLoc);
16452 };
16453
16454 SemaRef.AddInitializerToDecl(dcl: IVDecl, init: StartExpr, /*DirectInit=*/false);
16455 StmtResult InitStmt = new (Context)
16456 DeclStmt(DeclGroupRef(IVDecl), OrigVarLocBegin, OrigVarLocEnd);
16457 if (!InitStmt.isUsable())
16458 return StmtError();
16459
16460 ExprResult CondExpr = SemaRef.BuildBinOp(
16461 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT, LHSExpr: MakeIVRef(), RHSExpr: EndExpr);
16462 if (!CondExpr.isUsable())
16463 return StmtError();
16464
16465 ExprResult IncrExpr = SemaRef.BuildUnaryOp(
16466 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeIVRef());
16467 if (!IncrExpr.isUsable())
16468 return StmtError();
16469
16470 ExprResult IVAssign = SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Assign,
16471 LHSExpr: IterationVarRef, RHSExpr: MakeIVRef());
16472 if (!IVAssign.isUsable())
16473 return StmtError();
16474
16475 SmallVector<Stmt *, 4> BodyStmts;
16476 BodyStmts.push_back(Elt: IVAssign.get());
16477 BodyStmts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
16478 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt)) {
16479 if (Seg == 0) {
16480 BodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
16481 } else {
16482 VarDecl *LoopVar = CXXRangeFor->getLoopVariable();
16483 DeclRefExpr *LVRef = buildDeclRefExpr(
16484 S&: SemaRef, D: LoopVar, Ty: LoopVar->getType().getNonReferenceType(),
16485 Loc: OrigVarLoc);
16486 ExprResult LVAssign = SemaRef.BuildBinOp(
16487 S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Assign, LHSExpr: LVRef, RHSExpr: LoopVar->getInit());
16488 if (!LVAssign.isUsable())
16489 return StmtError();
16490 BodyStmts.push_back(Elt: LVAssign.get());
16491 }
16492 }
16493 BodyStmts.push_back(Elt: Body);
16494
16495 auto *LoopBody =
16496 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
16497 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
16498
16499 auto *For = new (Context)
16500 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
16501 IncrExpr.get(), LoopBody, LoopHelper.Init->getBeginLoc(),
16502 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16503 SplitLoops.push_back(Elt: For);
16504 }
16505
16506 auto *SplitStmt = CompoundStmt::Create(
16507 C: Context, Stmts: SplitLoops, FPFeatures: FPOptionsOverride(),
16508 LB: SplitLoops.front()->getBeginLoc(), RB: SplitLoops.back()->getEndLoc());
16509
16510 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses, NumLoops,
16511 AssociatedStmt: AStmt, TransformedStmt: SplitStmt,
16512 PreInits: buildPreInits(Context, PreInits));
16513}
16514
16515StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
16516 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
16517 SourceLocation EndLoc) {
16518 ASTContext &Context = getASTContext();
16519 DeclContext *CurContext = SemaRef.CurContext;
16520 Scope *CurScope = SemaRef.getCurScope();
16521
16522 // Empty statement should only be possible if there already was an error.
16523 if (!AStmt)
16524 return StmtError();
16525
16526 // interchange without permutation clause swaps two loops.
16527 const OMPPermutationClause *PermutationClause =
16528 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
16529 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
16530
16531 // Verify and diagnose loop nest.
16532 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
16533 Stmt *Body = nullptr;
16534 SmallVector<SmallVector<Stmt *>, 2> OriginalInits;
16535 if (!checkTransformableLoopNest(Kind: OMPD_interchange, AStmt, NumLoops,
16536 LoopHelpers, Body, OriginalInits))
16537 return StmtError();
16538
16539 // Delay interchange to when template is completely instantiated.
16540 if (CurContext->isDependentContext())
16541 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16542 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16543
16544 // An invalid expression in the permutation clause is set to nullptr in
16545 // ActOnOpenMPPermutationClause.
16546 if (PermutationClause &&
16547 llvm::is_contained(Range: PermutationClause->getArgsRefs(), Element: nullptr))
16548 return StmtError();
16549
16550 assert(LoopHelpers.size() == NumLoops &&
16551 "Expecting loop iteration space dimensionaly to match number of "
16552 "affected loops");
16553 assert(OriginalInits.size() == NumLoops &&
16554 "Expecting loop iteration space dimensionaly to match number of "
16555 "affected loops");
16556
16557 // Decode the permutation clause.
16558 SmallVector<uint64_t, 2> Permutation;
16559 if (!PermutationClause) {
16560 Permutation = {1, 0};
16561 } else {
16562 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
16563 llvm::BitVector Flags(PermArgs.size());
16564 for (Expr *PermArg : PermArgs) {
16565 std::optional<llvm::APSInt> PermCstExpr =
16566 PermArg->getIntegerConstantExpr(Ctx: Context);
16567 if (!PermCstExpr)
16568 continue;
16569 uint64_t PermInt = PermCstExpr->getZExtValue();
16570 assert(1 <= PermInt && PermInt <= NumLoops &&
16571 "Must be a permutation; diagnostic emitted in "
16572 "ActOnOpenMPPermutationClause");
16573 if (Flags[PermInt - 1]) {
16574 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
16575 Diag(Loc: PermArg->getExprLoc(),
16576 DiagID: diag::err_omp_interchange_permutation_value_repeated)
16577 << PermInt << ExprRange;
16578 continue;
16579 }
16580 Flags[PermInt - 1] = true;
16581
16582 Permutation.push_back(Elt: PermInt - 1);
16583 }
16584
16585 if (Permutation.size() != NumLoops)
16586 return StmtError();
16587 }
16588
16589 // Nothing to transform with trivial permutation.
16590 if (NumLoops <= 1 || llvm::all_of(Range: llvm::enumerate(First&: Permutation), P: [](auto P) {
16591 auto [Idx, Arg] = P;
16592 return Idx == Arg;
16593 }))
16594 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16595 NumLoops, AssociatedStmt: AStmt, TransformedStmt: AStmt, PreInits: nullptr);
16596
16597 // Find the affected loops.
16598 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
16599 collectLoopStmts(AStmt, LoopStmts);
16600
16601 // Collect pre-init statements on the order before the permuation.
16602 SmallVector<Stmt *> PreInits;
16603 for (auto I : llvm::seq<int>(Size: NumLoops)) {
16604 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16605
16606 assert(LoopHelper.Counters.size() == 1 &&
16607 "Single-dimensional loop iteration space expected");
16608
16609 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
16610 PreInits);
16611 }
16612
16613 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
16614 CaptureVars CopyTransformer(SemaRef);
16615
16616 // Create the permuted loops from the inside to the outside of the
16617 // interchanged loop nest. Body of the innermost new loop is the original
16618 // innermost body.
16619 Stmt *Inner = Body;
16620 for (auto TargetIdx : llvm::reverse(C: llvm::seq<int>(Size: NumLoops))) {
16621 // Get the original loop that belongs to this new position.
16622 uint64_t SourceIdx = Permutation[TargetIdx];
16623 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
16624 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
16625 assert(SourceHelper.Counters.size() == 1 &&
16626 "Single-dimensional loop iteration space expected");
16627 auto *OrigCntVar = cast<DeclRefExpr>(Val: SourceHelper.Counters.front());
16628
16629 // Normalized loop counter variable: From 0 to n-1, always an integer type.
16630 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: SourceHelper.IterationVarRef);
16631 QualType IVTy = IterVarRef->getType();
16632 assert(IVTy->isIntegerType() &&
16633 "Expected the logical iteration counter to be an integer");
16634
16635 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
16636 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
16637
16638 // Make a copy of the NumIterations expression for each use: By the AST
16639 // constraints, every expression object in a DeclContext must be unique.
16640 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
16641 return AssertSuccess(
16642 R: CopyTransformer.TransformExpr(E: SourceHelper.NumIterations));
16643 };
16644
16645 // Iteration variable for the permuted loop. Reuse the one from
16646 // checkOpenMPLoop which will also be used to update the original loop
16647 // variable.
16648 SmallString<64> PermutedCntName(".permuted_");
16649 PermutedCntName.append(Refs: {llvm::utostr(X: TargetIdx), ".iv.", OrigVarName});
16650 auto *PermutedCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
16651 PermutedCntDecl->setDeclName(
16652 &SemaRef.PP.getIdentifierTable().get(Name: PermutedCntName));
16653 PermutedIndVars[TargetIdx] = PermutedCntDecl;
16654 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
16655 return buildDeclRefExpr(S&: SemaRef, D: PermutedCntDecl, Ty: IVTy, Loc: OrigVarLoc);
16656 };
16657
16658 // For init-statement:
16659 // \code
16660 // auto .permuted_{target}.iv = 0
16661 // \endcode
16662 ExprResult Zero = SemaRef.ActOnIntegerConstant(Loc: OrigVarLoc, Val: 0);
16663 if (!Zero.isUsable())
16664 return StmtError();
16665 SemaRef.AddInitializerToDecl(dcl: PermutedCntDecl, init: Zero.get(),
16666 /*DirectInit=*/false);
16667 StmtResult InitStmt = new (Context)
16668 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
16669 OrigCntVar->getEndLoc());
16670 if (!InitStmt.isUsable())
16671 return StmtError();
16672
16673 // For cond-expression:
16674 // \code
16675 // .permuted_{target}.iv < MakeNumIterations()
16676 // \endcode
16677 ExprResult CondExpr =
16678 SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceHelper.Cond->getExprLoc(), Opc: BO_LT,
16679 LHSExpr: MakePermutedRef(), RHSExpr: MakeNumIterations());
16680 if (!CondExpr.isUsable())
16681 return StmtError();
16682
16683 // For incr-statement:
16684 // \code
16685 // ++.tile.iv
16686 // \endcode
16687 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
16688 S: CurScope, OpLoc: SourceHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakePermutedRef());
16689 if (!IncrStmt.isUsable())
16690 return StmtError();
16691
16692 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
16693 SourceHelper.Updates.end());
16694 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: SourceLoopStmt))
16695 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
16696 BodyParts.push_back(Elt: Inner);
16697 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
16698 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
16699 Inner = new (Context) ForStmt(
16700 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
16701 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
16702 SourceHelper.Inc->getEndLoc());
16703 }
16704
16705 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16706 NumLoops, AssociatedStmt: AStmt, TransformedStmt: Inner,
16707 PreInits: buildPreInits(Context, PreInits));
16708}
16709
16710StmtResult SemaOpenMP::ActOnOpenMPFuseDirective(ArrayRef<OMPClause *> Clauses,
16711 Stmt *AStmt,
16712 SourceLocation StartLoc,
16713 SourceLocation EndLoc) {
16714
16715 ASTContext &Context = getASTContext();
16716 DeclContext *CurrContext = SemaRef.CurContext;
16717 Scope *CurScope = SemaRef.getCurScope();
16718 CaptureVars CopyTransformer(SemaRef);
16719
16720 // Ensure the structured block is not empty
16721 if (!AStmt)
16722 return StmtError();
16723
16724 // Defer transformation in dependent contexts
16725 // The NumLoopNests argument is set to a placeholder 1 (even though
16726 // using looprange fuse could yield up to 3 top level loop nests)
16727 // because a dependent context could prevent determining its true value
16728 if (CurrContext->isDependentContext())
16729 return OMPFuseDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16730 /* NumLoops */ NumGeneratedTopLevelLoops: 1, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16731
16732 // Validate that the potential loop sequence is transformable for fusion
16733 // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops
16734 LoopSequenceAnalysis SeqAnalysis;
16735 if (!checkTransformableLoopSequence(Kind: OMPD_fuse, AStmt, SeqAnalysis, Context))
16736 return StmtError();
16737
16738 // SeqAnalysis.LoopSeqSize exists mostly to handle dependent contexts,
16739 // otherwise it must be the same as SeqAnalysis.Loops.size().
16740 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16741 "Inconsistent size of the loop sequence and the number of loops "
16742 "found in the sequence");
16743
16744 // Handle clauses, which can be any of the following: [looprange, apply]
16745 const auto *LRC =
16746 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16747
16748 // The clause arguments are invalidated if any error arises
16749 // such as non-constant or non-positive arguments
16750 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16751 return StmtError();
16752
16753 // Delayed semantic check of LoopRange constraint
16754 // Evaluates the loop range arguments and returns the first and count values
16755 auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count,
16756 uint64_t &FirstVal,
16757 uint64_t &CountVal) {
16758 llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Ctx: Context);
16759 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Ctx: Context);
16760 FirstVal = FirstInt.getZExtValue();
16761 CountVal = CountInt.getZExtValue();
16762 };
16763
16764 // OpenMP [6.0, Restrictions]
16765 // first + count - 1 must not evaluate to a value greater than the
16766 // loop sequence length of the associated canonical loop sequence.
16767 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16768 unsigned NumLoops) -> bool {
16769 return FirstVal + CountVal - 1 <= NumLoops;
16770 };
16771 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16772
16773 // Validates the loop range after evaluating the semantic information
16774 // and ensures that the range is valid for the given loop sequence size.
16775 // Expressions are evaluated at compile time to obtain constant values.
16776 if (LRC) {
16777 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16778 CountVal);
16779 if (CountVal == 1)
16780 SemaRef.Diag(Loc: LRC->getCountLoc(), DiagID: diag::warn_omp_redundant_fusion)
16781 << getOpenMPDirectiveName(D: OMPD_fuse);
16782
16783 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16784 SemaRef.Diag(Loc: LRC->getFirstLoc(), DiagID: diag::err_omp_invalid_looprange)
16785 << getOpenMPDirectiveName(D: OMPD_fuse) << FirstVal
16786 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16787 return StmtError();
16788 }
16789
16790 LastVal = FirstVal + CountVal - 1;
16791 }
16792
16793 // Complete fusion generates a single canonical loop nest
16794 // However looprange clause may generate several loop nests
16795 unsigned NumGeneratedTopLevelLoops =
16796 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16797
16798 // Emit a warning for redundant loop fusion when the sequence contains only
16799 // one loop.
16800 if (SeqAnalysis.LoopSeqSize == 1)
16801 SemaRef.Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::warn_omp_redundant_fusion)
16802 << getOpenMPDirectiveName(D: OMPD_fuse);
16803
16804 // Select the type with the largest bit width among all induction variables
16805 QualType IVType =
16806 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16807 for (unsigned I : llvm::seq<unsigned>(Begin: FirstVal, End: LastVal)) {
16808 QualType CurrentIVType =
16809 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16810 if (Context.getTypeSize(T: CurrentIVType) > Context.getTypeSize(T: IVType)) {
16811 IVType = CurrentIVType;
16812 }
16813 }
16814 uint64_t IVBitWidth = Context.getIntWidth(T: IVType);
16815
16816 // Create pre-init declarations for all loops lower bounds, upper bounds,
16817 // strides and num-iterations for every top level loop in the fusion
16818 SmallVector<VarDecl *, 4> LBVarDecls;
16819 SmallVector<VarDecl *, 4> STVarDecls;
16820 SmallVector<VarDecl *, 4> NIVarDecls;
16821 SmallVector<VarDecl *, 4> UBVarDecls;
16822 SmallVector<VarDecl *, 4> IVVarDecls;
16823
16824 // Helper lambda to create variables for bounds, strides, and other
16825 // expressions. Generates both the variable declaration and the corresponding
16826 // initialization statement.
16827 auto CreateHelperVarAndStmt =
16828 [&, &SemaRef = SemaRef](Expr *ExprToCopy, const std::string &BaseName,
16829 unsigned I, bool NeedsNewVD = false) {
16830 Expr *TransformedExpr =
16831 AssertSuccess(R: CopyTransformer.TransformExpr(E: ExprToCopy));
16832 if (!TransformedExpr)
16833 return std::pair<VarDecl *, StmtResult>(nullptr, StmtError());
16834
16835 auto Name = (Twine(".omp.") + BaseName + std::to_string(val: I)).str();
16836
16837 VarDecl *VD;
16838 if (NeedsNewVD) {
16839 VD = buildVarDecl(SemaRef, Loc: SourceLocation(), Type: IVType, Name);
16840 SemaRef.AddInitializerToDecl(dcl: VD, init: TransformedExpr, DirectInit: false);
16841 } else {
16842 // Create a unique variable name
16843 DeclRefExpr *DRE = cast<DeclRefExpr>(Val: TransformedExpr);
16844 VD = cast<VarDecl>(Val: DRE->getDecl());
16845 VD->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name));
16846 }
16847 // Create the corresponding declaration statement
16848 StmtResult DeclStmt = new (Context) class DeclStmt(
16849 DeclGroupRef(VD), SourceLocation(), SourceLocation());
16850 return std::make_pair(x&: VD, y&: DeclStmt);
16851 };
16852
16853 // PreInits hold a sequence of variable declarations that must be executed
16854 // before the fused loop begins. These include bounds, strides, and other
16855 // helper variables required for the transformation. Other loop transforms
16856 // also contain their own preinits
16857 SmallVector<Stmt *> PreInits;
16858
16859 // Update the general preinits using the preinits generated by loop sequence
16860 // generating loop transformations. These preinits differ slightly from
16861 // single-loop transformation preinits, as they can be detached from a
16862 // specific loop inside multiple generated loop nests. This happens
16863 // because certain helper variables, like '.omp.fuse.max', are introduced to
16864 // handle fused iteration spaces and may not be directly tied to a single
16865 // original loop. The preinit structure must ensure that hidden variables
16866 // like '.omp.fuse.max' are still properly handled.
16867 // Transformations that apply this concept: Loopranged Fuse, Split
16868 llvm::append_range(C&: PreInits, R&: SeqAnalysis.LoopSequencePreInits);
16869
16870 // Process each single loop to generate and collect declarations
16871 // and statements for all helper expressions related to
16872 // particular single loop nests
16873
16874 // Also In the case of the fused loops, we keep track of their original
16875 // inits by appending them to their preinits statement, and in the case of
16876 // transformations, also append their preinits (which contain the original
16877 // loop initialization statement or other statements)
16878
16879 // Firstly we need to set TransformIndex to match the begining of the
16880 // looprange section
16881 unsigned int TransformIndex = 0;
16882 for (unsigned I : llvm::seq<unsigned>(Size: FirstVal - 1)) {
16883 if (SeqAnalysis.Loops[I].isLoopTransformation())
16884 ++TransformIndex;
16885 }
16886
16887 for (unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16888 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16889 addLoopPreInits(Context, LoopHelper&: SeqAnalysis.Loops[I].HelperExprs,
16890 LoopStmt: SeqAnalysis.Loops[I].TheForStmt,
16891 OriginalInit: SeqAnalysis.Loops[I].OriginalInits, PreInits);
16892 } else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16893 // For transformed loops, insert both pre-inits and original inits.
16894 // Order matters: pre-inits may define variables used in the original
16895 // inits such as upper bounds...
16896 SmallVector<Stmt *> &TransformPreInit =
16897 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16898 llvm::append_range(C&: PreInits, R&: TransformPreInit);
16899
16900 addLoopPreInits(Context, LoopHelper&: SeqAnalysis.Loops[I].HelperExprs,
16901 LoopStmt: SeqAnalysis.Loops[I].TheForStmt,
16902 OriginalInit: SeqAnalysis.Loops[I].OriginalInits, PreInits);
16903 }
16904 auto [UBVD, UBDStmt] =
16905 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB, "ub", J);
16906 auto [LBVD, LBDStmt] =
16907 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB, "lb", J);
16908 auto [STVD, STDStmt] =
16909 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST, "st", J);
16910 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16911 SeqAnalysis.Loops[I].HelperExprs.NumIterations, "ni", J, true);
16912 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16913 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef, "iv", J);
16914
16915 assert(LBVD && STVD && NIVD && IVVD &&
16916 "OpenMP Fuse Helper variables creation failed");
16917
16918 UBVarDecls.push_back(Elt: UBVD);
16919 LBVarDecls.push_back(Elt: LBVD);
16920 STVarDecls.push_back(Elt: STVD);
16921 NIVarDecls.push_back(Elt: NIVD);
16922 IVVarDecls.push_back(Elt: IVVD);
16923
16924 PreInits.push_back(Elt: LBDStmt.get());
16925 PreInits.push_back(Elt: STDStmt.get());
16926 PreInits.push_back(Elt: NIDStmt.get());
16927 PreInits.push_back(Elt: IVDStmt.get());
16928 }
16929
16930 auto MakeVarDeclRef = [&SemaRef = this->SemaRef](VarDecl *VD) {
16931 return buildDeclRefExpr(S&: SemaRef, D: VD, Ty: VD->getType(), Loc: VD->getLocation(),
16932 RefersToCapture: false);
16933 };
16934
16935 // Following up the creation of the final fused loop will be performed
16936 // which has the following shape (considering the selected loops):
16937 //
16938 // for (fuse.index = 0; fuse.index < max(ni0, ni1..., nik); ++fuse.index) {
16939 // if (fuse.index < ni0){
16940 // iv0 = lb0 + st0 * fuse.index;
16941 // original.index0 = iv0
16942 // body(0);
16943 // }
16944 // if (fuse.index < ni1){
16945 // iv1 = lb1 + st1 * fuse.index;
16946 // original.index1 = iv1
16947 // body(1);
16948 // }
16949 //
16950 // ...
16951 //
16952 // if (fuse.index < nik){
16953 // ivk = lbk + stk * fuse.index;
16954 // original.indexk = ivk
16955 // body(k); Expr *InitVal = IntegerLiteral::Create(Context,
16956 // llvm::APInt(IVWidth, 0),
16957 // }
16958
16959 // 1. Create the initialized fuse index
16960 StringRef IndexName = ".omp.fuse.index";
16961 Expr *InitVal = IntegerLiteral::Create(C: Context, V: llvm::APInt(IVBitWidth, 0),
16962 type: IVType, l: SourceLocation());
16963 VarDecl *IndexDecl =
16964 buildVarDecl(SemaRef, Loc: {}, Type: IVType, Name: IndexName, Attrs: nullptr, OrigRef: nullptr);
16965 SemaRef.AddInitializerToDecl(dcl: IndexDecl, init: InitVal, DirectInit: false);
16966 StmtResult InitStmt = new (Context)
16967 DeclStmt(DeclGroupRef(IndexDecl), SourceLocation(), SourceLocation());
16968
16969 if (!InitStmt.isUsable())
16970 return StmtError();
16971
16972 auto MakeIVRef = [&SemaRef = this->SemaRef, IndexDecl, IVType,
16973 Loc = InitVal->getExprLoc()]() {
16974 return buildDeclRefExpr(S&: SemaRef, D: IndexDecl, Ty: IVType, Loc, RefersToCapture: false);
16975 };
16976
16977 // 2. Iteratively compute the max number of logical iterations Max(NI_1, NI_2,
16978 // ..., NI_k)
16979 //
16980 // This loop accumulates the maximum value across multiple expressions,
16981 // ensuring each step constructs a unique AST node for correctness. By using
16982 // intermediate temporary variables and conditional operators, we maintain
16983 // distinct nodes and avoid duplicating subtrees, For instance, max(a,b,c):
16984 // omp.temp0 = max(a, b)
16985 // omp.temp1 = max(omp.temp0, c)
16986 // omp.fuse.max = max(omp.temp1, omp.temp0)
16987
16988 ExprResult MaxExpr;
16989 // I is the range of loops in the sequence that we fuse.
16990 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16991 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16992 QualType NITy = NIRef->getType();
16993
16994 if (MaxExpr.isUnset()) {
16995 // Initialize MaxExpr with the first NI expression
16996 MaxExpr = NIRef;
16997 } else {
16998 // Create a new acummulator variable t_i = MaxExpr
16999 std::string TempName = (Twine(".omp.temp.") + Twine(J)).str();
17000 VarDecl *TempDecl =
17001 buildVarDecl(SemaRef, Loc: {}, Type: NITy, Name: TempName, Attrs: nullptr, OrigRef: nullptr);
17002 TempDecl->setInit(MaxExpr.get());
17003 DeclRefExpr *TempRef =
17004 buildDeclRefExpr(S&: SemaRef, D: TempDecl, Ty: NITy, Loc: SourceLocation(), RefersToCapture: false);
17005 DeclRefExpr *TempRef2 =
17006 buildDeclRefExpr(S&: SemaRef, D: TempDecl, Ty: NITy, Loc: SourceLocation(), RefersToCapture: false);
17007 // Add a DeclStmt to PreInits to ensure the variable is declared.
17008 StmtResult TempStmt = new (Context)
17009 DeclStmt(DeclGroupRef(TempDecl), SourceLocation(), SourceLocation());
17010
17011 if (!TempStmt.isUsable())
17012 return StmtError();
17013 PreInits.push_back(Elt: TempStmt.get());
17014
17015 // Build MaxExpr <-(MaxExpr > NIRef ? MaxExpr : NIRef)
17016 ExprResult Comparison =
17017 SemaRef.BuildBinOp(S: nullptr, OpLoc: SourceLocation(), Opc: BO_GT, LHSExpr: TempRef, RHSExpr: NIRef);
17018 // Handle any errors in Comparison creation
17019 if (!Comparison.isUsable())
17020 return StmtError();
17021
17022 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
17023 // Update MaxExpr using a conditional expression to hold the max value
17024 MaxExpr = new (Context) ConditionalOperator(
17025 Comparison.get(), SourceLocation(), TempRef2, SourceLocation(),
17026 NIRef2->getExprStmt(), NITy, VK_LValue, OK_Ordinary);
17027
17028 if (!MaxExpr.isUsable())
17029 return StmtError();
17030 }
17031 }
17032 if (!MaxExpr.isUsable())
17033 return StmtError();
17034
17035 // 3. Declare the max variable
17036 const std::string MaxName = Twine(".omp.fuse.max").str();
17037 VarDecl *MaxDecl =
17038 buildVarDecl(SemaRef, Loc: {}, Type: IVType, Name: MaxName, Attrs: nullptr, OrigRef: nullptr);
17039 MaxDecl->setInit(MaxExpr.get());
17040 DeclRefExpr *MaxRef = buildDeclRefExpr(S&: SemaRef, D: MaxDecl, Ty: IVType, Loc: {}, RefersToCapture: false);
17041 StmtResult MaxStmt = new (Context)
17042 DeclStmt(DeclGroupRef(MaxDecl), SourceLocation(), SourceLocation());
17043
17044 if (MaxStmt.isInvalid())
17045 return StmtError();
17046 PreInits.push_back(Elt: MaxStmt.get());
17047
17048 // 4. Create condition Expr: index < n_max
17049 ExprResult CondExpr = SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_LT,
17050 LHSExpr: MakeIVRef(), RHSExpr: MaxRef);
17051 if (!CondExpr.isUsable())
17052 return StmtError();
17053
17054 // 5. Increment Expr: ++index
17055 ExprResult IncrExpr =
17056 SemaRef.BuildUnaryOp(S: CurScope, OpLoc: SourceLocation(), Opc: UO_PreInc, Input: MakeIVRef());
17057 if (!IncrExpr.isUsable())
17058 return StmtError();
17059
17060 // 6. Build the Fused Loop Body
17061 // The final fused loop iterates over the maximum logical range. Inside the
17062 // loop, each original loop's index is calculated dynamically, and its body
17063 // is executed conditionally.
17064 //
17065 // Each sub-loop's body is guarded by a conditional statement to ensure
17066 // it executes only within its logical iteration range:
17067 //
17068 // if (fuse.index < ni_k){
17069 // iv_k = lb_k + st_k * fuse.index;
17070 // original.index = iv_k
17071 // body(k);
17072 // }
17073
17074 CompoundStmt *FusedBody = nullptr;
17075 SmallVector<Stmt *, 4> FusedBodyStmts;
17076 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
17077 // Assingment of the original sub-loop index to compute the logical index
17078 // IV_k = LB_k + omp.fuse.index * ST_k
17079 ExprResult IdxExpr =
17080 SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_Mul,
17081 LHSExpr: MakeVarDeclRef(STVarDecls[J]), RHSExpr: MakeIVRef());
17082 if (!IdxExpr.isUsable())
17083 return StmtError();
17084 IdxExpr = SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_Add,
17085 LHSExpr: MakeVarDeclRef(LBVarDecls[J]), RHSExpr: IdxExpr.get());
17086
17087 if (!IdxExpr.isUsable())
17088 return StmtError();
17089 IdxExpr = SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_Assign,
17090 LHSExpr: MakeVarDeclRef(IVVarDecls[J]), RHSExpr: IdxExpr.get());
17091 if (!IdxExpr.isUsable())
17092 return StmtError();
17093
17094 // Update the original i_k = IV_k
17095 SmallVector<Stmt *, 4> BodyStmts;
17096 BodyStmts.push_back(Elt: IdxExpr.get());
17097 llvm::append_range(C&: BodyStmts, R&: SeqAnalysis.Loops[I].HelperExprs.Updates);
17098
17099 // If the loop is a CXXForRangeStmt then the iterator variable is needed
17100 if (auto *SourceCXXFor =
17101 dyn_cast<CXXForRangeStmt>(Val: SeqAnalysis.Loops[I].TheForStmt))
17102 BodyStmts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
17103
17104 Stmt *Body =
17105 (isa<ForStmt>(Val: SeqAnalysis.Loops[I].TheForStmt))
17106 ? cast<ForStmt>(Val: SeqAnalysis.Loops[I].TheForStmt)->getBody()
17107 : cast<CXXForRangeStmt>(Val: SeqAnalysis.Loops[I].TheForStmt)->getBody();
17108 BodyStmts.push_back(Elt: Body);
17109
17110 CompoundStmt *CombinedBody =
17111 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
17112 LB: SourceLocation(), RB: SourceLocation());
17113 ExprResult Condition =
17114 SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_LT, LHSExpr: MakeIVRef(),
17115 RHSExpr: MakeVarDeclRef(NIVarDecls[J]));
17116
17117 if (!Condition.isUsable())
17118 return StmtError();
17119
17120 IfStmt *IfStatement = IfStmt::Create(
17121 Ctx: Context, IL: SourceLocation(), Kind: IfStatementKind::Ordinary, Init: nullptr, Var: nullptr,
17122 Cond: Condition.get(), LPL: SourceLocation(), RPL: SourceLocation(), Then: CombinedBody,
17123 EL: SourceLocation(), Else: nullptr);
17124
17125 FusedBodyStmts.push_back(Elt: IfStatement);
17126 }
17127 FusedBody = CompoundStmt::Create(C: Context, Stmts: FusedBodyStmts, FPFeatures: FPOptionsOverride(),
17128 LB: SourceLocation(), RB: SourceLocation());
17129
17130 // 7. Construct the final fused loop
17131 ForStmt *FusedForStmt = new (Context)
17132 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, IncrExpr.get(),
17133 FusedBody, InitStmt.get()->getBeginLoc(), SourceLocation(),
17134 IncrExpr.get()->getEndLoc());
17135
17136 // In the case of looprange, the result of fuse won't simply
17137 // be a single loop (ForStmt), but rather a loop sequence
17138 // (CompoundStmt) of 3 parts: the pre-fusion loops, the fused loop
17139 // and the post-fusion loops, preserving its original order.
17140 //
17141 // Note: If looprange clause produces a single fused loop nest then
17142 // this compound statement wrapper is unnecessary (Therefore this
17143 // treatment is skipped)
17144
17145 Stmt *FusionStmt = FusedForStmt;
17146 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
17147 SmallVector<Stmt *, 4> FinalLoops;
17148
17149 // Reset the transform index
17150 TransformIndex = 0;
17151
17152 // Collect all non-fused loops before and after the fused region.
17153 // Pre-fusion and post-fusion loops are inserted in order exploiting their
17154 // symmetry, along with their corresponding transformation pre-inits if
17155 // needed. The fused loop is added between the two regions.
17156 for (unsigned I : llvm::seq<unsigned>(Size: SeqAnalysis.LoopSeqSize)) {
17157 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
17158 // Update the Transformation counter to skip already treated
17159 // loop transformations
17160 if (!SeqAnalysis.Loops[I].isLoopTransformation())
17161 ++TransformIndex;
17162 continue;
17163 }
17164
17165 // No need to handle:
17166 // Regular loops: they are kept intact as-is.
17167 // Loop-sequence-generating transformations: already handled earlier.
17168 // Only TransformSingleLoop requires inserting pre-inits here
17169 if (SeqAnalysis.Loops[I].isRegularLoop()) {
17170 const auto &TransformPreInit =
17171 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
17172 if (!TransformPreInit.empty())
17173 llvm::append_range(C&: PreInits, R: TransformPreInit);
17174 }
17175
17176 FinalLoops.push_back(Elt: SeqAnalysis.Loops[I].TheForStmt);
17177 }
17178
17179 FinalLoops.insert(I: FinalLoops.begin() + (FirstVal - 1), Elt: FusedForStmt);
17180 FusionStmt = CompoundStmt::Create(C: Context, Stmts: FinalLoops, FPFeatures: FPOptionsOverride(),
17181 LB: SourceLocation(), RB: SourceLocation());
17182 }
17183 return OMPFuseDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
17184 NumGeneratedTopLevelLoops, AssociatedStmt: AStmt, TransformedStmt: FusionStmt,
17185 PreInits: buildPreInits(Context, PreInits));
17186}
17187
17188OMPClause *SemaOpenMP::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
17189 Expr *Expr,
17190 SourceLocation StartLoc,
17191 SourceLocation LParenLoc,
17192 SourceLocation EndLoc) {
17193 OMPClause *Res = nullptr;
17194 switch (Kind) {
17195 case OMPC_final:
17196 Res = ActOnOpenMPFinalClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
17197 break;
17198 case OMPC_safelen:
17199 Res = ActOnOpenMPSafelenClause(Length: Expr, StartLoc, LParenLoc, EndLoc);
17200 break;
17201 case OMPC_simdlen:
17202 Res = ActOnOpenMPSimdlenClause(Length: Expr, StartLoc, LParenLoc, EndLoc);
17203 break;
17204 case OMPC_allocator:
17205 Res = ActOnOpenMPAllocatorClause(Allocator: Expr, StartLoc, LParenLoc, EndLoc);
17206 break;
17207 case OMPC_collapse:
17208 Res = ActOnOpenMPCollapseClause(NumForLoops: Expr, StartLoc, LParenLoc, EndLoc);
17209 break;
17210 case OMPC_ordered:
17211 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, NumForLoops: Expr);
17212 break;
17213 case OMPC_nowait:
17214 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc, LParenLoc, Condition: Expr);
17215 break;
17216 case OMPC_priority:
17217 Res = ActOnOpenMPPriorityClause(Priority: Expr, StartLoc, LParenLoc, EndLoc);
17218 break;
17219 case OMPC_hint:
17220 Res = ActOnOpenMPHintClause(Hint: Expr, StartLoc, LParenLoc, EndLoc);
17221 break;
17222 case OMPC_depobj:
17223 Res = ActOnOpenMPDepobjClause(Depobj: Expr, StartLoc, LParenLoc, EndLoc);
17224 break;
17225 case OMPC_detach:
17226 Res = ActOnOpenMPDetachClause(Evt: Expr, StartLoc, LParenLoc, EndLoc);
17227 break;
17228 case OMPC_novariants:
17229 Res = ActOnOpenMPNovariantsClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
17230 break;
17231 case OMPC_nocontext:
17232 Res = ActOnOpenMPNocontextClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
17233 break;
17234 case OMPC_filter:
17235 Res = ActOnOpenMPFilterClause(ThreadID: Expr, StartLoc, LParenLoc, EndLoc);
17236 break;
17237 case OMPC_partial:
17238 Res = ActOnOpenMPPartialClause(FactorExpr: Expr, StartLoc, LParenLoc, EndLoc);
17239 break;
17240 case OMPC_message:
17241 Res = ActOnOpenMPMessageClause(MS: Expr, StartLoc, LParenLoc, EndLoc);
17242 break;
17243 case OMPC_align:
17244 Res = ActOnOpenMPAlignClause(Alignment: Expr, StartLoc, LParenLoc, EndLoc);
17245 break;
17246 case OMPC_ompx_dyn_cgroup_mem:
17247 Res = ActOnOpenMPXDynCGroupMemClause(Size: Expr, StartLoc, LParenLoc, EndLoc);
17248 break;
17249 case OMPC_holds:
17250 Res = ActOnOpenMPHoldsClause(E: Expr, StartLoc, LParenLoc, EndLoc);
17251 break;
17252 case OMPC_transparent:
17253 Res = ActOnOpenMPTransparentClause(Transparent: Expr, StartLoc, LParenLoc, EndLoc);
17254 break;
17255 case OMPC_dyn_groupprivate:
17256 case OMPC_grainsize:
17257 case OMPC_num_tasks:
17258 case OMPC_num_threads:
17259 case OMPC_device:
17260 case OMPC_if:
17261 case OMPC_default:
17262 case OMPC_proc_bind:
17263 case OMPC_schedule:
17264 case OMPC_private:
17265 case OMPC_firstprivate:
17266 case OMPC_lastprivate:
17267 case OMPC_shared:
17268 case OMPC_reduction:
17269 case OMPC_task_reduction:
17270 case OMPC_in_reduction:
17271 case OMPC_linear:
17272 case OMPC_aligned:
17273 case OMPC_copyin:
17274 case OMPC_copyprivate:
17275 case OMPC_untied:
17276 case OMPC_mergeable:
17277 case OMPC_threadprivate:
17278 case OMPC_groupprivate:
17279 case OMPC_sizes:
17280 case OMPC_allocate:
17281 case OMPC_flush:
17282 case OMPC_read:
17283 case OMPC_write:
17284 case OMPC_update:
17285 case OMPC_capture:
17286 case OMPC_compare:
17287 case OMPC_seq_cst:
17288 case OMPC_acq_rel:
17289 case OMPC_acquire:
17290 case OMPC_release:
17291 case OMPC_relaxed:
17292 case OMPC_depend:
17293 case OMPC_threads:
17294 case OMPC_simd:
17295 case OMPC_map:
17296 case OMPC_nogroup:
17297 case OMPC_dist_schedule:
17298 case OMPC_defaultmap:
17299 case OMPC_unknown:
17300 case OMPC_uniform:
17301 case OMPC_to:
17302 case OMPC_from:
17303 case OMPC_use_device_ptr:
17304 case OMPC_use_device_addr:
17305 case OMPC_is_device_ptr:
17306 case OMPC_unified_address:
17307 case OMPC_unified_shared_memory:
17308 case OMPC_reverse_offload:
17309 case OMPC_dynamic_allocators:
17310 case OMPC_atomic_default_mem_order:
17311 case OMPC_self_maps:
17312 case OMPC_device_type:
17313 case OMPC_match:
17314 case OMPC_nontemporal:
17315 case OMPC_order:
17316 case OMPC_at:
17317 case OMPC_severity:
17318 case OMPC_destroy:
17319 case OMPC_inclusive:
17320 case OMPC_exclusive:
17321 case OMPC_uses_allocators:
17322 case OMPC_affinity:
17323 case OMPC_when:
17324 case OMPC_bind:
17325 case OMPC_num_teams:
17326 case OMPC_thread_limit:
17327 default:
17328 llvm_unreachable("Clause is not allowed.");
17329 }
17330 return Res;
17331}
17332
17333// An OpenMP directive such as 'target parallel' has two captured regions:
17334// for the 'target' and 'parallel' respectively. This function returns
17335// the region in which to capture expressions associated with a clause.
17336// A return value of OMPD_unknown signifies that the expression should not
17337// be captured.
17338static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
17339 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
17340 llvm::omp::Version OMPVersion,
17341 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
17342 assert(isAllowedClauseForDirective(DKind, CKind, OMPVersion) &&
17343 "Invalid directive with CKind-clause");
17344
17345 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
17346 if (NameModifier != OMPD_unknown &&
17347 !isAllowedClauseForDirective(D: NameModifier, C: CKind, V: OMPVersion))
17348 return OMPD_unknown;
17349
17350 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(D: DKind);
17351
17352 // [5.2:341:24-30]
17353 // If the clauses have expressions on them, such as for various clauses where
17354 // the argument of the clause is an expression, or lower-bound, length, or
17355 // stride expressions inside array sections (or subscript and stride
17356 // expressions in subscript-triplet for Fortran), or linear-step or alignment
17357 // expressions, the expressions are evaluated immediately before the construct
17358 // to which the clause has been split or duplicated per the above rules
17359 // (therefore inside of the outer leaf constructs). However, the expressions
17360 // inside the num_teams and thread_limit clauses are always evaluated before
17361 // the outermost leaf construct.
17362
17363 // Process special cases first.
17364 switch (CKind) {
17365 case OMPC_if:
17366 switch (DKind) {
17367 case OMPD_teams_loop:
17368 case OMPD_target_teams_loop:
17369 // For [target] teams loop, assume capture region is 'teams' so it's
17370 // available for codegen later to use if/when necessary.
17371 return OMPD_teams;
17372 case OMPD_target_update:
17373 case OMPD_target_enter_data:
17374 case OMPD_target_exit_data:
17375 return OMPD_task;
17376 default:
17377 break;
17378 }
17379 break;
17380 case OMPC_num_teams:
17381 case OMPC_thread_limit:
17382 case OMPC_ompx_dyn_cgroup_mem:
17383 case OMPC_dyn_groupprivate:
17384 // TODO: This may need to consider teams too.
17385 if (Leafs[0] == OMPD_target)
17386 return OMPD_target;
17387 break;
17388 case OMPC_device:
17389 if (Leafs[0] == OMPD_target ||
17390 llvm::is_contained(Set: {OMPD_dispatch, OMPD_target_update,
17391 OMPD_target_enter_data, OMPD_target_exit_data},
17392 Element: DKind))
17393 return OMPD_task;
17394 break;
17395 case OMPC_novariants:
17396 case OMPC_nocontext:
17397 if (DKind == OMPD_dispatch)
17398 return OMPD_task;
17399 break;
17400 case OMPC_when:
17401 if (DKind == OMPD_metadirective)
17402 return OMPD_metadirective;
17403 break;
17404 case OMPC_filter:
17405 return OMPD_unknown;
17406 default:
17407 break;
17408 }
17409
17410 // If none of the special cases above applied, and DKind is a capturing
17411 // directive, find the innermost enclosing leaf construct that allows the
17412 // clause, and returns the corresponding capture region.
17413
17414 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
17415 // Find the index in "Leafs" of the last leaf that allows the given
17416 // clause. The search will only include indexes [0, EndIdx).
17417 // EndIdx may be set to the index of the NameModifier, if present.
17418 int InnermostIdx = [&]() {
17419 for (int I = EndIdx - 1; I >= 0; --I) {
17420 if (isAllowedClauseForDirective(D: Leafs[I], C: Clause, V: OMPVersion))
17421 return I;
17422 }
17423 return -1;
17424 }();
17425
17426 // Find the nearest enclosing capture region.
17427 SmallVector<OpenMPDirectiveKind, 2> Regions;
17428 for (int I = InnermostIdx - 1; I >= 0; --I) {
17429 if (!isOpenMPCapturingDirective(DKind: Leafs[I]))
17430 continue;
17431 Regions.clear();
17432 getOpenMPCaptureRegions(CaptureRegions&: Regions, DKind: Leafs[I]);
17433 if (Regions[0] != OMPD_unknown)
17434 return Regions.back();
17435 }
17436 return OMPD_unknown;
17437 };
17438
17439 if (isOpenMPCapturingDirective(DKind)) {
17440 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
17441 for (int I = 0, E = Leafs.size(); I != E; ++I) {
17442 if (Leafs[I] == Dir)
17443 return I + 1;
17444 }
17445 return 0;
17446 };
17447
17448 int End = NameModifier == OMPD_unknown ? Leafs.size()
17449 : GetLeafIndex(NameModifier);
17450 return GetEnclosingRegion(End, CKind);
17451 }
17452
17453 return OMPD_unknown;
17454}
17455
17456OMPClause *SemaOpenMP::ActOnOpenMPIfClause(
17457 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
17458 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
17459 SourceLocation ColonLoc, SourceLocation EndLoc) {
17460 Expr *ValExpr = Condition;
17461 Stmt *HelperValStmt = nullptr;
17462 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17463 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17464 !Condition->isInstantiationDependent() &&
17465 !Condition->containsUnexpandedParameterPack()) {
17466 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
17467 if (Val.isInvalid())
17468 return nullptr;
17469
17470 ValExpr = Val.get();
17471
17472 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17473 CaptureRegion = getOpenMPCaptureRegionForClause(
17474 DKind, CKind: OMPC_if, OMPVersion: getLangOpts().getOpenMPVersion(), NameModifier);
17475 if (CaptureRegion != OMPD_unknown &&
17476 !SemaRef.CurContext->isDependentContext()) {
17477 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17478 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17479 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17480 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
17481 }
17482 }
17483
17484 return new (getASTContext())
17485 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
17486 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
17487}
17488
17489OMPClause *SemaOpenMP::ActOnOpenMPFinalClause(Expr *Condition,
17490 SourceLocation StartLoc,
17491 SourceLocation LParenLoc,
17492 SourceLocation EndLoc) {
17493 Expr *ValExpr = Condition;
17494 Stmt *HelperValStmt = nullptr;
17495 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17496 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17497 !Condition->isInstantiationDependent() &&
17498 !Condition->containsUnexpandedParameterPack()) {
17499 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
17500 if (Val.isInvalid())
17501 return nullptr;
17502
17503 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
17504
17505 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17506 CaptureRegion = getOpenMPCaptureRegionForClause(
17507 DKind, CKind: OMPC_final, OMPVersion: getLangOpts().getOpenMPVersion());
17508 if (CaptureRegion != OMPD_unknown &&
17509 !SemaRef.CurContext->isDependentContext()) {
17510 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17511 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17512 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17513 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
17514 }
17515 }
17516
17517 return new (getASTContext()) OMPFinalClause(
17518 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17519}
17520
17521ExprResult
17522SemaOpenMP::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
17523 Expr *Op) {
17524 if (!Op)
17525 return ExprError();
17526
17527 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
17528 public:
17529 IntConvertDiagnoser()
17530 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
17531 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
17532 QualType T) override {
17533 return S.Diag(Loc, DiagID: diag::err_omp_not_integral) << T;
17534 }
17535 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
17536 QualType T) override {
17537 return S.Diag(Loc, DiagID: diag::err_omp_incomplete_type) << T;
17538 }
17539 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
17540 QualType T,
17541 QualType ConvTy) override {
17542 return S.Diag(Loc, DiagID: diag::err_omp_explicit_conversion) << T << ConvTy;
17543 }
17544 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
17545 QualType ConvTy) override {
17546 return S.Diag(Loc: Conv->getLocation(), DiagID: diag::note_omp_conversion_here)
17547 << ConvTy->isEnumeralType() << ConvTy;
17548 }
17549 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
17550 QualType T) override {
17551 return S.Diag(Loc, DiagID: diag::err_omp_ambiguous_conversion) << T;
17552 }
17553 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
17554 QualType ConvTy) override {
17555 return S.Diag(Loc: Conv->getLocation(), DiagID: diag::note_omp_conversion_here)
17556 << ConvTy->isEnumeralType() << ConvTy;
17557 }
17558 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
17559 QualType) override {
17560 llvm_unreachable("conversion functions are permitted");
17561 }
17562 } ConvertDiagnoser;
17563 return SemaRef.PerformContextualImplicitConversion(Loc, FromE: Op, Converter&: ConvertDiagnoser);
17564}
17565
17566static bool
17567isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
17568 bool StrictlyPositive, bool BuildCapture = false,
17569 OpenMPDirectiveKind DKind = OMPD_unknown,
17570 OpenMPDirectiveKind *CaptureRegion = nullptr,
17571 Stmt **HelperValStmt = nullptr) {
17572 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
17573 !ValExpr->isInstantiationDependent()) {
17574 SourceLocation Loc = ValExpr->getExprLoc();
17575 ExprResult Value =
17576 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, Op: ValExpr);
17577 if (Value.isInvalid())
17578 return false;
17579
17580 ValExpr = Value.get();
17581 // The expression must evaluate to a non-negative integer value.
17582 if (std::optional<llvm::APSInt> Result =
17583 ValExpr->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
17584 if (Result->isSigned() &&
17585 !((!StrictlyPositive && Result->isNonNegative()) ||
17586 (StrictlyPositive && Result->isStrictlyPositive()))) {
17587 SemaRef.Diag(Loc, DiagID: diag::err_omp_negative_expression_in_clause)
17588 << getOpenMPClauseNameForDiag(C: CKind) << (StrictlyPositive ? 1 : 0)
17589 << ValExpr->getSourceRange();
17590 return false;
17591 }
17592 }
17593 if (!BuildCapture)
17594 return true;
17595 *CaptureRegion = getOpenMPCaptureRegionForClause(
17596 DKind, CKind, OMPVersion: SemaRef.getLangOpts().getOpenMPVersion());
17597 if (*CaptureRegion != OMPD_unknown &&
17598 !SemaRef.CurContext->isDependentContext()) {
17599 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17600 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17601 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17602 *HelperValStmt = buildPreInits(Context&: SemaRef.Context, Captures);
17603 }
17604 }
17605 return true;
17606}
17607
17608static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
17609 unsigned Last,
17610 ArrayRef<unsigned> Exclude = {}) {
17611 SmallString<256> Buffer;
17612 llvm::raw_svector_ostream Out(Buffer);
17613 unsigned Skipped = Exclude.size();
17614 for (unsigned I = First; I < Last; ++I) {
17615 if (llvm::is_contained(Range&: Exclude, Element: I)) {
17616 --Skipped;
17617 continue;
17618 }
17619 Out << "'" << getOpenMPSimpleClauseTypeName(Kind: K, Type: I) << "'";
17620 if (I + Skipped + 2 == Last)
17621 Out << " or ";
17622 else if (I + Skipped + 1 != Last)
17623 Out << ", ";
17624 }
17625 return std::string(Out.str());
17626}
17627
17628OMPClause *SemaOpenMP::ActOnOpenMPNumThreadsClause(
17629 ArrayRef<Expr *> VarList, OpenMPNumThreadsClauseModifier SimpleModifier,
17630 SourceLocation SimpleModifierLoc,
17631 OpenMPNumThreadsClauseModifier ComplexModifier, Expr *ComplexModifierExpr,
17632 SourceLocation ComplexModifierLoc, SourceLocation StartLoc,
17633 SourceLocation LParenLoc, SourceLocation EndLoc) {
17634 // Check that modifiers were correctly specified.
17635 if (ComplexModifierLoc.isValid() &&
17636 (ComplexModifier != OMPC_NUMTHREADS_dims || !ComplexModifierExpr)) {
17637 Diag(Loc: ComplexModifierLoc, DiagID: diag::err_omp_malformed_complex_modifier)
17638 << getOpenMPSimpleClauseTypeName(Kind: OMPC_num_threads, Type: OMPC_NUMTHREADS_dims)
17639 << getOpenMPClauseName(C: OMPC_num_threads);
17640 return nullptr;
17641 }
17642 if (SimpleModifierLoc.isValid() && SimpleModifier == OMPC_NUMTHREADS_dims) {
17643 Diag(Loc: SimpleModifierLoc, DiagID: diag::err_omp_malformed_complex_modifier)
17644 << getOpenMPSimpleClauseTypeName(Kind: OMPC_num_threads, Type: OMPC_NUMTHREADS_dims)
17645 << getOpenMPClauseName(C: OMPC_num_threads);
17646 return nullptr;
17647 }
17648 if (SimpleModifierLoc.isValid() && SimpleModifier != OMPC_NUMTHREADS_strict) {
17649 Diag(Loc: SimpleModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
17650 << getOpenMPSimpleClauseTypeName(Kind: OMPC_num_threads,
17651 Type: OMPC_NUMTHREADS_strict)
17652 << getOpenMPClauseName(C: OMPC_num_threads);
17653 return nullptr;
17654 }
17655
17656 if (VarList.empty())
17657 return nullptr;
17658
17659 SmallVector<Expr *, 3> Vars(VarList.begin(), VarList.end());
17660 for (Expr *&ValExpr : Vars) {
17661 // OpenMP [2.5, Restrictions]
17662 // The num_threads expression must evaluate to a positive integer value.
17663 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_num_threads,
17664 /*StrictlyPositive=*/true))
17665 return nullptr;
17666 }
17667
17668 if (ComplexModifier == OMPC_NUMTHREADS_dims) {
17669 ExprResult Res = ActOnOpenMPDimsModifier(Kind: OMPC_num_threads, Modifier: ComplexModifier,
17670 ModifierExpr: ComplexModifierExpr,
17671 ModifierLoc: ComplexModifierLoc, VarList: Vars, VarListEndLoc: EndLoc);
17672 if (Res.isInvalid())
17673 return nullptr;
17674 ComplexModifierExpr = Res.get();
17675
17676 if (validateMultidimClauseExprs(SemaRef&: *this, ClauseKind: OMPC_num_threads, ClauseBeginLoc: StartLoc, ClauseVarList: Vars,
17677 DimsModifierExpr: ComplexModifierExpr))
17678 return nullptr;
17679 }
17680 if (SimpleModifier == OMPC_NUMTHREADS_strict && getLangOpts().OpenMP < 60) {
17681 Diag(Loc: SimpleModifierLoc, DiagID: diag::err_omp_modifier_requires_version)
17682 << getOpenMPSimpleClauseTypeName(Kind: OMPC_num_threads, Type: SimpleModifier)
17683 << getOpenMPClauseName(C: OMPC_num_threads) << "6.0";
17684 return nullptr;
17685 }
17686
17687 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17688 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
17689 DKind, CKind: OMPC_num_threads, OMPVersion: getLangOpts().getOpenMPVersion());
17690 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
17691 return OMPNumThreadsClause::Create(
17692 C: getASTContext(), CaptureRegion, StartLoc, LParenLoc, EndLoc, VL: Vars,
17693 PrescriptivenessModifier: SimpleModifier, DimsModifier: ComplexModifier, PrescriptivenessModifierLoc: SimpleModifierLoc, DimsModifierLoc: ComplexModifierLoc,
17694 DimsModifierExpr: ComplexModifierExpr, /*PreInit=*/nullptr);
17695
17696 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17697 for (Expr *&ValExpr : Vars) {
17698 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17699 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17700 }
17701 if (ComplexModifierExpr) {
17702 ComplexModifierExpr = SemaRef.MakeFullExpr(Arg: ComplexModifierExpr).get();
17703 ComplexModifierExpr =
17704 tryBuildCapture(SemaRef, Capture: ComplexModifierExpr, Captures).get();
17705 }
17706 Stmt *PreInit = buildPreInits(Context&: getASTContext(), Captures);
17707
17708 return OMPNumThreadsClause::Create(
17709 C: getASTContext(), CaptureRegion, StartLoc, LParenLoc, EndLoc, VL: Vars,
17710 PrescriptivenessModifier: SimpleModifier, DimsModifier: ComplexModifier, PrescriptivenessModifierLoc: SimpleModifierLoc, DimsModifierLoc: ComplexModifierLoc,
17711 DimsModifierExpr: ComplexModifierExpr, PreInit);
17712}
17713
17714ExprResult SemaOpenMP::VerifyPositiveIntegerConstantInClause(
17715 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
17716 bool SuppressExprDiags) {
17717 if (!E)
17718 return ExprError();
17719 if (E->isValueDependent() || E->isTypeDependent() ||
17720 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
17721 return E;
17722
17723 llvm::APSInt Result;
17724 ExprResult ICE;
17725 if (SuppressExprDiags) {
17726 // Use a custom diagnoser that suppresses 'note' diagnostics about the
17727 // expression.
17728 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
17729 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
17730 SemaBase::SemaDiagnosticBuilder
17731 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
17732 llvm_unreachable("Diagnostic suppressed");
17733 }
17734 } Diagnoser;
17735 ICE = SemaRef.VerifyIntegerConstantExpression(E, Result: &Result, Diagnoser,
17736 CanFold: AllowFoldKind::Allow);
17737 } else {
17738 ICE =
17739 SemaRef.VerifyIntegerConstantExpression(E, Result: &Result,
17740 /*FIXME*/ CanFold: AllowFoldKind::Allow);
17741 }
17742 if (ICE.isInvalid())
17743 return ExprError();
17744
17745 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
17746 (!StrictlyPositive && !Result.isNonNegative())) {
17747 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_negative_expression_in_clause)
17748 << getOpenMPClauseNameForDiag(C: CKind) << (StrictlyPositive ? 1 : 0)
17749 << E->getSourceRange();
17750 return ExprError();
17751 }
17752 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
17753 CKind == OMPC_allocate) &&
17754 !Result.isPowerOf2()) {
17755 Diag(Loc: E->getExprLoc(), DiagID: diag::warn_omp_alignment_not_power_of_two)
17756 << E->getSourceRange();
17757 return ExprError();
17758 }
17759
17760 if (!Result.isRepresentableByInt64()) {
17761 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_large_expression_in_clause)
17762 << getOpenMPClauseNameForDiag(C: CKind) << E->getSourceRange();
17763 return ExprError();
17764 }
17765
17766 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
17767 DSAStack->setAssociatedLoops(Result.getExtValue());
17768 else if (CKind == OMPC_ordered)
17769 DSAStack->setAssociatedLoops(Result.getExtValue());
17770 return ICE;
17771}
17772
17773void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
17774
17775void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
17776
17777int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
17778
17779void SemaOpenMP::ActOnOpenMPDeviceNum(Expr *DeviceNumExpr) {
17780 llvm::APSInt Result;
17781 Expr::EvalResult EvalResult;
17782 // Evaluate the expression to an integer value
17783 if (!DeviceNumExpr->isValueDependent() &&
17784 DeviceNumExpr->EvaluateAsInt(Result&: EvalResult, Ctx: SemaRef.Context)) {
17785 // The device expression must evaluate to a non-negative integer value.
17786 Result = EvalResult.Val.getInt();
17787 if (Result.isNonNegative()) {
17788 setOpenMPDeviceNum(Result.getZExtValue());
17789 } else {
17790 Diag(Loc: DeviceNumExpr->getExprLoc(),
17791 DiagID: diag::err_omp_negative_expression_in_clause)
17792 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
17793 }
17794 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(Val: DeviceNumExpr)) {
17795 // Check if the expression is an identifier
17796 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
17797 if (IdInfo) {
17798 setOpenMPDeviceNumID(IdInfo->getName());
17799 }
17800 } else {
17801 Diag(Loc: DeviceNumExpr->getExprLoc(), DiagID: diag::err_expected_expression);
17802 }
17803}
17804
17805OMPClause *SemaOpenMP::ActOnOpenMPSafelenClause(Expr *Len,
17806 SourceLocation StartLoc,
17807 SourceLocation LParenLoc,
17808 SourceLocation EndLoc) {
17809 // OpenMP [2.8.1, simd construct, Description]
17810 // The parameter of the safelen clause must be a constant
17811 // positive integer expression.
17812 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(E: Len, CKind: OMPC_safelen);
17813 if (Safelen.isInvalid())
17814 return nullptr;
17815 return new (getASTContext())
17816 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
17817}
17818
17819OMPClause *SemaOpenMP::ActOnOpenMPSimdlenClause(Expr *Len,
17820 SourceLocation StartLoc,
17821 SourceLocation LParenLoc,
17822 SourceLocation EndLoc) {
17823 // OpenMP [2.8.1, simd construct, Description]
17824 // The parameter of the simdlen clause must be a constant
17825 // positive integer expression.
17826 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(E: Len, CKind: OMPC_simdlen);
17827 if (Simdlen.isInvalid())
17828 return nullptr;
17829 return new (getASTContext())
17830 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
17831}
17832
17833/// Tries to find omp_allocator_handle_t type.
17834static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
17835 DSAStackTy *Stack) {
17836 if (!Stack->getOMPAllocatorHandleT().isNull())
17837 return true;
17838
17839 // Set the allocator handle type.
17840 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_allocator_handle_t");
17841 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
17842 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
17843 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found)
17844 << "omp_allocator_handle_t";
17845 return false;
17846 }
17847 QualType AllocatorHandleEnumTy = PT.get();
17848 AllocatorHandleEnumTy.addConst();
17849
17850 // Fill the predefined allocator map.
17851 bool ErrorFound = false;
17852 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17853 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
17854 StringRef Allocator =
17855 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(Val: AllocatorKind);
17856 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Name: Allocator);
17857 auto *VD = dyn_cast_or_null<ValueDecl>(
17858 Val: S.LookupSingleName(S: S.TUScope, Name: AllocatorName, Loc, NameKind: Sema::LookupAnyName));
17859 if (!VD) {
17860 ErrorFound = true;
17861 break;
17862 }
17863 QualType AllocatorType =
17864 VD->getType().getNonLValueExprType(Context: S.getASTContext());
17865 ExprResult Res = S.BuildDeclRefExpr(D: VD, Ty: AllocatorType, VK: VK_LValue, Loc);
17866 if (!Res.isUsable()) {
17867 ErrorFound = true;
17868 break;
17869 }
17870 Res = S.PerformImplicitConversion(From: Res.get(), ToType: AllocatorHandleEnumTy,
17871 Action: AssignmentAction::Initializing,
17872 /*AllowExplicit=*/true);
17873 if (!Res.isUsable()) {
17874 ErrorFound = true;
17875 break;
17876 }
17877 Stack->setAllocator(AllocatorKind, Allocator: Res.get());
17878 }
17879 if (ErrorFound) {
17880 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found)
17881 << "omp_allocator_handle_t";
17882 return false;
17883 }
17884
17885 // Record the type only now. It is what tells a later call that the map above
17886 // is ready to be read, so setting it before the map is filled would let that
17887 // call proceed on a map this one gave up on halfway through.
17888 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17889
17890 return true;
17891}
17892
17893OMPClause *SemaOpenMP::ActOnOpenMPAllocatorClause(Expr *A,
17894 SourceLocation StartLoc,
17895 SourceLocation LParenLoc,
17896 SourceLocation EndLoc) {
17897 // OpenMP [2.11.3, allocate Directive, Description]
17898 // allocator is an expression of omp_allocator_handle_t type.
17899 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: A->getExprLoc(), DSAStack))
17900 return nullptr;
17901
17902 ExprResult Allocator = SemaRef.DefaultLvalueConversion(E: A);
17903 if (Allocator.isInvalid())
17904 return nullptr;
17905 Allocator = SemaRef.PerformImplicitConversion(
17906 From: Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
17907 Action: AssignmentAction::Initializing,
17908 /*AllowExplicit=*/true);
17909 if (Allocator.isInvalid())
17910 return nullptr;
17911 return new (getASTContext())
17912 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
17913}
17914
17915OMPClause *SemaOpenMP::ActOnOpenMPCollapseClause(Expr *NumForLoops,
17916 SourceLocation StartLoc,
17917 SourceLocation LParenLoc,
17918 SourceLocation EndLoc) {
17919 // OpenMP [2.7.1, loop construct, Description]
17920 // OpenMP [2.8.1, simd construct, Description]
17921 // OpenMP [2.9.6, distribute construct, Description]
17922 // The parameter of the collapse clause must be a constant
17923 // positive integer expression.
17924 ExprResult NumForLoopsResult =
17925 VerifyPositiveIntegerConstantInClause(E: NumForLoops, CKind: OMPC_collapse);
17926 if (NumForLoopsResult.isInvalid())
17927 return nullptr;
17928 return new (getASTContext())
17929 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
17930}
17931
17932OMPClause *SemaOpenMP::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
17933 SourceLocation EndLoc,
17934 SourceLocation LParenLoc,
17935 Expr *NumForLoops) {
17936 // OpenMP [2.7.1, loop construct, Description]
17937 // OpenMP [2.8.1, simd construct, Description]
17938 // OpenMP [2.9.6, distribute construct, Description]
17939 // The parameter of the ordered clause must be a constant
17940 // positive integer expression if any.
17941 if (NumForLoops && LParenLoc.isValid()) {
17942 ExprResult NumForLoopsResult =
17943 VerifyPositiveIntegerConstantInClause(E: NumForLoops, CKind: OMPC_ordered);
17944 if (NumForLoopsResult.isInvalid())
17945 return nullptr;
17946 NumForLoops = NumForLoopsResult.get();
17947 } else {
17948 NumForLoops = nullptr;
17949 }
17950 auto *Clause =
17951 OMPOrderedClause::Create(C: getASTContext(), Num: NumForLoops,
17952 NumLoops: NumForLoops ? DSAStack->getAssociatedLoops() : 0,
17953 StartLoc, LParenLoc, EndLoc);
17954 DSAStack->setOrderedRegion(/*IsOrdered=*/true, Param: NumForLoops, Clause);
17955 return Clause;
17956}
17957
17958OMPClause *SemaOpenMP::ActOnOpenMPSimpleClause(
17959 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
17960 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17961 OMPClause *Res = nullptr;
17962 switch (Kind) {
17963 case OMPC_proc_bind:
17964 Res = ActOnOpenMPProcBindClause(Kind: static_cast<ProcBindKind>(Argument),
17965 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17966 break;
17967 case OMPC_atomic_default_mem_order:
17968 Res = ActOnOpenMPAtomicDefaultMemOrderClause(
17969 Kind: static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
17970 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17971 break;
17972 case OMPC_fail:
17973 Res = ActOnOpenMPFailClause(Kind: static_cast<OpenMPClauseKind>(Argument),
17974 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17975 break;
17976 case OMPC_update_depend_objects:
17977 Res = ActOnOpenMPUpdateDependObjectsClause(
17978 Kind: static_cast<OpenMPDependClauseKind>(Argument), KindLoc: ArgumentLoc, StartLoc,
17979 LParenLoc, EndLoc);
17980 break;
17981 case OMPC_bind:
17982 Res = ActOnOpenMPBindClause(Kind: static_cast<OpenMPBindClauseKind>(Argument),
17983 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17984 break;
17985 case OMPC_at:
17986 Res = ActOnOpenMPAtClause(Kind: static_cast<OpenMPAtClauseKind>(Argument),
17987 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17988 break;
17989 case OMPC_severity:
17990 Res = ActOnOpenMPSeverityClause(
17991 Kind: static_cast<OpenMPSeverityClauseKind>(Argument), KindLoc: ArgumentLoc, StartLoc,
17992 LParenLoc, EndLoc);
17993 break;
17994 case OMPC_threadset:
17995 Res = ActOnOpenMPThreadsetClause(Kind: static_cast<OpenMPThreadsetKind>(Argument),
17996 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17997 break;
17998 case OMPC_if:
17999 case OMPC_final:
18000 case OMPC_num_threads:
18001 case OMPC_safelen:
18002 case OMPC_simdlen:
18003 case OMPC_sizes:
18004 case OMPC_allocator:
18005 case OMPC_collapse:
18006 case OMPC_schedule:
18007 case OMPC_private:
18008 case OMPC_firstprivate:
18009 case OMPC_lastprivate:
18010 case OMPC_shared:
18011 case OMPC_reduction:
18012 case OMPC_task_reduction:
18013 case OMPC_in_reduction:
18014 case OMPC_linear:
18015 case OMPC_aligned:
18016 case OMPC_copyin:
18017 case OMPC_copyprivate:
18018 case OMPC_ordered:
18019 case OMPC_nowait:
18020 case OMPC_untied:
18021 case OMPC_mergeable:
18022 case OMPC_threadprivate:
18023 case OMPC_groupprivate:
18024 case OMPC_allocate:
18025 case OMPC_flush:
18026 case OMPC_depobj:
18027 case OMPC_read:
18028 case OMPC_write:
18029 case OMPC_capture:
18030 case OMPC_compare:
18031 case OMPC_update:
18032 case OMPC_seq_cst:
18033 case OMPC_acq_rel:
18034 case OMPC_acquire:
18035 case OMPC_release:
18036 case OMPC_relaxed:
18037 case OMPC_depend:
18038 case OMPC_device:
18039 case OMPC_threads:
18040 case OMPC_simd:
18041 case OMPC_map:
18042 case OMPC_num_teams:
18043 case OMPC_thread_limit:
18044 case OMPC_priority:
18045 case OMPC_grainsize:
18046 case OMPC_nogroup:
18047 case OMPC_num_tasks:
18048 case OMPC_hint:
18049 case OMPC_dist_schedule:
18050 case OMPC_default:
18051 case OMPC_defaultmap:
18052 case OMPC_unknown:
18053 case OMPC_uniform:
18054 case OMPC_to:
18055 case OMPC_from:
18056 case OMPC_use_device_ptr:
18057 case OMPC_use_device_addr:
18058 case OMPC_is_device_ptr:
18059 case OMPC_has_device_addr:
18060 case OMPC_unified_address:
18061 case OMPC_unified_shared_memory:
18062 case OMPC_reverse_offload:
18063 case OMPC_dynamic_allocators:
18064 case OMPC_self_maps:
18065 case OMPC_device_type:
18066 case OMPC_match:
18067 case OMPC_nontemporal:
18068 case OMPC_destroy:
18069 case OMPC_novariants:
18070 case OMPC_nocontext:
18071 case OMPC_detach:
18072 case OMPC_inclusive:
18073 case OMPC_exclusive:
18074 case OMPC_uses_allocators:
18075 case OMPC_affinity:
18076 case OMPC_when:
18077 case OMPC_message:
18078 default:
18079 llvm_unreachable("Clause is not allowed.");
18080 }
18081 return Res;
18082}
18083
18084OMPClause *SemaOpenMP::ActOnOpenMPDefaultClause(
18085 llvm::omp::DefaultKind M, SourceLocation MLoc,
18086 OpenMPDefaultClauseVariableCategory VCKind, SourceLocation VCKindLoc,
18087 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
18088 if (M == OMP_DEFAULT_unknown) {
18089 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
18090 << getListOfPossibleValues(K: OMPC_default, /*First=*/0,
18091 /*Last=*/unsigned(OMP_DEFAULT_unknown))
18092 << getOpenMPClauseNameForDiag(C: OMPC_default);
18093 return nullptr;
18094 }
18095 if (VCKind == OMPC_DEFAULT_VC_unknown) {
18096 Diag(Loc: VCKindLoc, DiagID: diag::err_omp_default_vc)
18097 << getOpenMPSimpleClauseTypeName(Kind: OMPC_default, Type: unsigned(M));
18098 return nullptr;
18099 }
18100
18101 bool IsTargetDefault =
18102 getLangOpts().OpenMP >= 60 &&
18103 isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective());
18104
18105 // OpenMP 6.0, page 224, lines 3-4 default Clause, Semantics
18106 // If data-sharing-attribute is shared then the clause has no effect
18107 // on a target construct;
18108 if (IsTargetDefault && M == OMP_DEFAULT_shared)
18109 return nullptr;
18110
18111 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
18112 OpenMPDefaultClauseVariableCategory VCKind) {
18113 OpenMPDefaultmapClauseModifier DefMapMod;
18114 OpenMPDefaultmapClauseKind DefMapKind;
18115 // default data-sharing-attribute
18116 switch (M) {
18117 case OMP_DEFAULT_none:
18118 if (IsTargetDefault)
18119 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
18120 else
18121 DSAStack->setDefaultDSANone(MLoc);
18122 break;
18123 case OMP_DEFAULT_firstprivate:
18124 if (IsTargetDefault)
18125 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
18126 else
18127 DSAStack->setDefaultDSAFirstPrivate(MLoc);
18128 break;
18129 case OMP_DEFAULT_private:
18130 if (IsTargetDefault)
18131 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
18132 else
18133 DSAStack->setDefaultDSAPrivate(MLoc);
18134 break;
18135 case OMP_DEFAULT_shared:
18136 assert(!IsTargetDefault && "DSA shared invalid with target directive");
18137 DSAStack->setDefaultDSAShared(MLoc);
18138 break;
18139 default:
18140 llvm_unreachable("unexpected DSA in OpenMP default clause");
18141 }
18142 // default variable-category
18143 switch (VCKind) {
18144 case OMPC_DEFAULT_VC_aggregate:
18145 if (IsTargetDefault)
18146 DefMapKind = OMPC_DEFAULTMAP_aggregate;
18147 else
18148 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
18149 break;
18150 case OMPC_DEFAULT_VC_pointer:
18151 if (IsTargetDefault)
18152 DefMapKind = OMPC_DEFAULTMAP_pointer;
18153 else
18154 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
18155 break;
18156 case OMPC_DEFAULT_VC_scalar:
18157 if (IsTargetDefault)
18158 DefMapKind = OMPC_DEFAULTMAP_scalar;
18159 else
18160 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
18161 break;
18162 case OMPC_DEFAULT_VC_all:
18163 if (IsTargetDefault)
18164 DefMapKind = OMPC_DEFAULTMAP_all;
18165 else
18166 DSAStack->setDefaultDSAVCAll(VCKindLoc);
18167 break;
18168 default:
18169 llvm_unreachable("unexpected variable category in OpenMP default clause");
18170 }
18171 // OpenMP 6.0, page 224, lines 4-5 default Clause, Semantics
18172 // otherwise, its effect on a target construct is equivalent to
18173 // specifying the defaultmap clause with the same data-sharing-attribute
18174 // and variable-category.
18175 //
18176 // If earlier than OpenMP 6.0, or not a target directive, the default DSA
18177 // is/was set as before.
18178 if (IsTargetDefault) {
18179 if (DefMapKind == OMPC_DEFAULTMAP_all) {
18180 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: OMPC_DEFAULTMAP_aggregate, Loc: MLoc);
18181 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: OMPC_DEFAULTMAP_scalar, Loc: MLoc);
18182 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: OMPC_DEFAULTMAP_pointer, Loc: MLoc);
18183 } else {
18184 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: DefMapKind, Loc: MLoc);
18185 }
18186 }
18187 };
18188
18189 SetDefaultClauseAttrs(M, VCKind);
18190 return new (getASTContext())
18191 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
18192}
18193
18194OMPClause *SemaOpenMP::ActOnOpenMPThreadsetClause(OpenMPThreadsetKind Kind,
18195 SourceLocation KindLoc,
18196 SourceLocation StartLoc,
18197 SourceLocation LParenLoc,
18198 SourceLocation EndLoc) {
18199 if (Kind == OMPC_THREADSET_unknown) {
18200 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
18201 << getListOfPossibleValues(K: OMPC_threadset, /*First=*/0,
18202 /*Last=*/unsigned(OMPC_THREADSET_unknown))
18203 << getOpenMPClauseName(C: OMPC_threadset);
18204 return nullptr;
18205 }
18206
18207 return new (getASTContext())
18208 OMPThreadsetClause(Kind, KindLoc, StartLoc, LParenLoc, EndLoc);
18209}
18210
18211static OMPClause *
18212createTransparentClause(Sema &SemaRef, ASTContext &Ctx, Expr *ImpexTypeArg,
18213 Stmt *HelperValStmt, OpenMPDirectiveKind CaptureRegion,
18214 SourceLocation StartLoc, SourceLocation LParenLoc,
18215 SourceLocation EndLoc) {
18216 ExprResult ER = SemaRef.DefaultLvalueConversion(E: ImpexTypeArg);
18217 if (ER.isInvalid())
18218 return nullptr;
18219
18220 return new (Ctx) OMPTransparentClause(ER.get(), HelperValStmt, CaptureRegion,
18221 StartLoc, LParenLoc, EndLoc);
18222}
18223
18224OMPClause *SemaOpenMP::ActOnOpenMPTransparentClause(Expr *ImpexTypeArg,
18225 SourceLocation StartLoc,
18226 SourceLocation LParenLoc,
18227 SourceLocation EndLoc) {
18228 Stmt *HelperValStmt = nullptr;
18229 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18230 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
18231 DKind, CKind: OMPC_transparent, OMPVersion: getLangOpts().getOpenMPVersion());
18232 if (CaptureRegion != OMPD_unknown &&
18233 !SemaRef.CurContext->isDependentContext()) {
18234 Expr *ValExpr = SemaRef.MakeFullExpr(Arg: ImpexTypeArg).get();
18235 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18236 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
18237 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
18238 }
18239 if (!ImpexTypeArg) {
18240 return new (getASTContext())
18241 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
18242 StartLoc, LParenLoc, EndLoc);
18243 }
18244 QualType Ty = ImpexTypeArg->getType();
18245
18246 if (const auto *TT = Ty->getAs<TypedefType>()) {
18247 const TypedefNameDecl *TypedefDecl = TT->getDecl();
18248 llvm::StringRef TypedefName = TypedefDecl->getName();
18249 IdentifierInfo &II = SemaRef.PP.getIdentifierTable().get(Name: TypedefName);
18250 ParsedType ImpexTy =
18251 SemaRef.getTypeName(II, NameLoc: StartLoc, S: SemaRef.getCurScope());
18252 if (!ImpexTy.getAsOpaquePtr() || ImpexTy.get().isNull()) {
18253 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_implied_type_not_found)
18254 << TypedefName;
18255 return nullptr;
18256 }
18257 return new (getASTContext())
18258 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
18259 StartLoc, LParenLoc, EndLoc);
18260 }
18261
18262 if (Ty->isEnumeralType())
18263 return createTransparentClause(SemaRef, Ctx&: getASTContext(), ImpexTypeArg,
18264 HelperValStmt, CaptureRegion, StartLoc,
18265 LParenLoc, EndLoc);
18266 if (Ty->isIntegerType()) {
18267 if (isNonNegativeIntegerValue(ValExpr&: ImpexTypeArg, SemaRef, CKind: OMPC_transparent,
18268 /*StrictlyPositive=*/false)) {
18269 ExprResult Value =
18270 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc: StartLoc,
18271 Op: ImpexTypeArg);
18272 if (std::optional<llvm::APSInt> Result =
18273 Value.get()->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
18274 if (Result->isNegative() ||
18275 Result >
18276 static_cast<int64_t>(SemaOpenMP::OpenMPImpexType::OMP_Export))
18277 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_transparent_invalid_value);
18278 }
18279 return new (getASTContext())
18280 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
18281 StartLoc, LParenLoc, EndLoc);
18282 }
18283 }
18284 if (!isNonNegativeIntegerValue(ValExpr&: ImpexTypeArg, SemaRef, CKind: OMPC_transparent,
18285 /*StrictlyPositive=*/true))
18286 return nullptr;
18287 return new (getASTContext()) OMPTransparentClause(
18288 ImpexTypeArg, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18289}
18290
18291OMPClause *SemaOpenMP::ActOnOpenMPProcBindClause(ProcBindKind Kind,
18292 SourceLocation KindKwLoc,
18293 SourceLocation StartLoc,
18294 SourceLocation LParenLoc,
18295 SourceLocation EndLoc) {
18296 if (Kind == OMP_PROC_BIND_unknown) {
18297 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
18298 << getListOfPossibleValues(K: OMPC_proc_bind,
18299 /*First=*/unsigned(OMP_PROC_BIND_master),
18300 /*Last=*/
18301 unsigned(getLangOpts().OpenMP > 50
18302 ? OMP_PROC_BIND_primary
18303 : OMP_PROC_BIND_spread) +
18304 1)
18305 << getOpenMPClauseNameForDiag(C: OMPC_proc_bind);
18306 return nullptr;
18307 }
18308 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
18309 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
18310 << getListOfPossibleValues(K: OMPC_proc_bind,
18311 /*First=*/unsigned(OMP_PROC_BIND_master),
18312 /*Last=*/
18313 unsigned(OMP_PROC_BIND_spread) + 1)
18314 << getOpenMPClauseNameForDiag(C: OMPC_proc_bind);
18315 return new (getASTContext())
18316 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
18317}
18318
18319OMPClause *SemaOpenMP::ActOnOpenMPAtomicDefaultMemOrderClause(
18320 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
18321 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
18322 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
18323 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
18324 << getListOfPossibleValues(
18325 K: OMPC_atomic_default_mem_order, /*First=*/0,
18326 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
18327 << getOpenMPClauseNameForDiag(C: OMPC_atomic_default_mem_order);
18328 return nullptr;
18329 }
18330 return new (getASTContext()) OMPAtomicDefaultMemOrderClause(
18331 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
18332}
18333
18334OMPClause *SemaOpenMP::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
18335 SourceLocation KindKwLoc,
18336 SourceLocation StartLoc,
18337 SourceLocation LParenLoc,
18338 SourceLocation EndLoc) {
18339 if (Kind == OMPC_AT_unknown) {
18340 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
18341 << getListOfPossibleValues(K: OMPC_at, /*First=*/0,
18342 /*Last=*/OMPC_AT_unknown)
18343 << getOpenMPClauseNameForDiag(C: OMPC_at);
18344 return nullptr;
18345 }
18346 return new (getASTContext())
18347 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
18348}
18349
18350OMPClause *SemaOpenMP::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
18351 SourceLocation KindKwLoc,
18352 SourceLocation StartLoc,
18353 SourceLocation LParenLoc,
18354 SourceLocation EndLoc) {
18355 if (Kind == OMPC_SEVERITY_unknown) {
18356 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
18357 << getListOfPossibleValues(K: OMPC_severity, /*First=*/0,
18358 /*Last=*/OMPC_SEVERITY_unknown)
18359 << getOpenMPClauseNameForDiag(C: OMPC_severity);
18360 return nullptr;
18361 }
18362 return new (getASTContext())
18363 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
18364}
18365
18366OMPClause *SemaOpenMP::ActOnOpenMPMessageClause(Expr *ME,
18367 SourceLocation StartLoc,
18368 SourceLocation LParenLoc,
18369 SourceLocation EndLoc) {
18370 assert(ME && "NULL expr in Message clause");
18371 QualType Type = ME->getType();
18372 if ((!Type->isPointerType() && !Type->isArrayType()) ||
18373 !Type->getPointeeOrArrayElementType()->isAnyCharacterType()) {
18374 Diag(Loc: ME->getBeginLoc(), DiagID: diag::warn_clause_expected_string)
18375 << getOpenMPClauseNameForDiag(C: OMPC_message) << 0;
18376 return nullptr;
18377 }
18378
18379 Stmt *HelperValStmt = nullptr;
18380
18381 // Depending on whether this clause appears in an executable context or not,
18382 // we may or may not build a capture.
18383 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18384 OpenMPDirectiveKind CaptureRegion =
18385 DKind == OMPD_unknown
18386 ? OMPD_unknown
18387 : getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_message,
18388 OMPVersion: getLangOpts().getOpenMPVersion());
18389 if (CaptureRegion != OMPD_unknown &&
18390 !SemaRef.CurContext->isDependentContext()) {
18391 ME = SemaRef.MakeFullExpr(Arg: ME).get();
18392 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18393 ME = tryBuildCapture(SemaRef, Capture: ME, Captures).get();
18394 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
18395 }
18396
18397 // Convert array type to pointer type if needed.
18398 ME = SemaRef.DefaultFunctionArrayLvalueConversion(E: ME).get();
18399
18400 return new (getASTContext()) OMPMessageClause(
18401 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18402}
18403
18404OMPClause *SemaOpenMP::ActOnOpenMPOrderClause(
18405 OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind,
18406 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
18407 SourceLocation KindLoc, SourceLocation EndLoc) {
18408 if (Kind != OMPC_ORDER_concurrent ||
18409 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
18410 // Kind should be concurrent,
18411 // Modifiers introduced in OpenMP 5.1
18412 static_assert(OMPC_ORDER_unknown > 0,
18413 "OMPC_ORDER_unknown not greater than 0");
18414
18415 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
18416 << getListOfPossibleValues(K: OMPC_order,
18417 /*First=*/0,
18418 /*Last=*/OMPC_ORDER_unknown)
18419 << getOpenMPClauseNameForDiag(C: OMPC_order);
18420 return nullptr;
18421 }
18422 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
18423 MLoc.isValid()) {
18424 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
18425 << getListOfPossibleValues(K: OMPC_order,
18426 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
18427 /*Last=*/OMPC_ORDER_MODIFIER_last)
18428 << getOpenMPClauseNameForDiag(C: OMPC_order);
18429 } else if (getLangOpts().OpenMP >= 50) {
18430 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
18431 if (DSAStack->getCurScope()) {
18432 // mark the current scope with 'order' flag
18433 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
18434 DSAStack->getCurScope()->setFlags(existingFlags |
18435 Scope::OpenMPOrderClauseScope);
18436 }
18437 }
18438 return new (getASTContext()) OMPOrderClause(
18439 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
18440}
18441
18442OMPClause *SemaOpenMP::ActOnOpenMPUpdateDependObjectsClause(
18443 OpenMPDependClauseKind Kind, SourceLocation KindKwLoc,
18444 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
18445 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
18446 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
18447 SmallVector<unsigned> Except = {
18448 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
18449 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
18450 if (getLangOpts().OpenMP < 51)
18451 Except.push_back(Elt: OMPC_DEPEND_inoutset);
18452 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
18453 << getListOfPossibleValues(K: OMPC_depend, /*First=*/0,
18454 /*Last=*/OMPC_DEPEND_unknown, Exclude: Except)
18455 << getOpenMPClauseNameForDiag(C: OMPC_update_depend_objects);
18456 return nullptr;
18457 }
18458 return OMPUpdateDependObjectsClause::Create(
18459 C: getASTContext(), StartLoc, LParenLoc, ArgumentLoc: KindKwLoc, DK: Kind, EndLoc);
18460}
18461
18462OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
18463 SourceLocation StartLoc,
18464 SourceLocation LParenLoc,
18465 SourceLocation EndLoc) {
18466 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
18467
18468 for (Expr *&SizeExpr : SanitizedSizeExprs) {
18469 // Skip if already sanitized, e.g. during a partial template instantiation.
18470 if (!SizeExpr)
18471 continue;
18472
18473 bool IsValid = isNonNegativeIntegerValue(ValExpr&: SizeExpr, SemaRef, CKind: OMPC_sizes,
18474 /*StrictlyPositive=*/true);
18475
18476 // isNonNegativeIntegerValue returns true for non-integral types (but still
18477 // emits error diagnostic), so check for the expected type explicitly.
18478 QualType SizeTy = SizeExpr->getType();
18479 if (!SizeTy->isIntegerType())
18480 IsValid = false;
18481
18482 // Handling in templates is tricky. There are four possibilities to
18483 // consider:
18484 //
18485 // 1a. The expression is valid and we are in a instantiated template or not
18486 // in a template:
18487 // Pass valid expression to be further analysed later in Sema.
18488 // 1b. The expression is valid and we are in a template (including partial
18489 // instantiation):
18490 // isNonNegativeIntegerValue skipped any checks so there is no
18491 // guarantee it will be correct after instantiation.
18492 // ActOnOpenMPSizesClause will be called again at instantiation when
18493 // it is not in a dependent context anymore. This may cause warnings
18494 // to be emitted multiple times.
18495 // 2a. The expression is invalid and we are in an instantiated template or
18496 // not in a template:
18497 // Invalidate the expression with a clearly wrong value (nullptr) so
18498 // later in Sema we do not have to do the same validity analysis again
18499 // or crash from unexpected data. Error diagnostics have already been
18500 // emitted.
18501 // 2b. The expression is invalid and we are in a template (including partial
18502 // instantiation):
18503 // Pass the invalid expression as-is, template instantiation may
18504 // replace unexpected types/values with valid ones. The directives
18505 // with this clause must not try to use these expressions in dependent
18506 // contexts, but delay analysis until full instantiation.
18507 if (!SizeExpr->isInstantiationDependent() && !IsValid)
18508 SizeExpr = nullptr;
18509 }
18510
18511 return OMPSizesClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
18512 Sizes: SanitizedSizeExprs);
18513}
18514
18515OMPClause *SemaOpenMP::ActOnOpenMPCountsClause(ArrayRef<Expr *> CountExprs,
18516 SourceLocation StartLoc,
18517 SourceLocation LParenLoc,
18518 SourceLocation EndLoc,
18519 std::optional<unsigned> FillIdx,
18520 SourceLocation FillLoc,
18521 unsigned FillCount) {
18522 SmallVector<Expr *> SanitizedCountExprs(CountExprs);
18523
18524 // OpenMP 6.0: each list item in counts(...) is either the omp_fill keyword
18525 // or an integral constant expression (non-negative). Runtime variables are
18526 // not permitted; this matches split codegen, which needs segment sizes at
18527 // compile time.
18528 for (unsigned I = 0; I < SanitizedCountExprs.size(); ++I) {
18529 Expr *&CountExpr = SanitizedCountExprs[I];
18530 if (FillIdx && I == *FillIdx)
18531 continue;
18532 if (!CountExpr)
18533 continue;
18534
18535 ExprResult Verified = VerifyPositiveIntegerConstantInClause(
18536 E: CountExpr, CKind: OMPC_counts, /*StrictlyPositive=*/false);
18537 if (Verified.isInvalid())
18538 CountExpr = nullptr;
18539 else
18540 CountExpr = Verified.get();
18541 }
18542
18543 if (FillCount != 1) {
18544 Diag(Loc: FillCount == 0 ? StartLoc : FillLoc,
18545 DiagID: diag::err_omp_split_counts_not_one_omp_fill);
18546 }
18547
18548 return OMPCountsClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
18549 Counts: SanitizedCountExprs, FillIdx, FillLoc);
18550}
18551
18552OMPClause *SemaOpenMP::ActOnOpenMPPermutationClause(ArrayRef<Expr *> PermExprs,
18553 SourceLocation StartLoc,
18554 SourceLocation LParenLoc,
18555 SourceLocation EndLoc) {
18556 size_t NumLoops = PermExprs.size();
18557 SmallVector<Expr *> SanitizedPermExprs;
18558 llvm::append_range(C&: SanitizedPermExprs, R&: PermExprs);
18559
18560 for (Expr *&PermExpr : SanitizedPermExprs) {
18561 // Skip if template-dependent or already sanitized, e.g. during a partial
18562 // template instantiation.
18563 if (!PermExpr || PermExpr->isInstantiationDependent())
18564 continue;
18565
18566 llvm::APSInt PermVal;
18567 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
18568 E: PermExpr, Result: &PermVal, CanFold: AllowFoldKind::Allow);
18569 bool IsValid = PermEvalExpr.isUsable();
18570 if (IsValid)
18571 PermExpr = PermEvalExpr.get();
18572
18573 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
18574 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
18575 PermEvalExpr.get()->getEndLoc());
18576 Diag(Loc: PermEvalExpr.get()->getExprLoc(),
18577 DiagID: diag::err_omp_interchange_permutation_value_range)
18578 << NumLoops << ExprRange;
18579 IsValid = false;
18580 }
18581
18582 if (!PermExpr->isInstantiationDependent() && !IsValid)
18583 PermExpr = nullptr;
18584 }
18585
18586 return OMPPermutationClause::Create(C: getASTContext(), StartLoc, LParenLoc,
18587 EndLoc, Args: SanitizedPermExprs);
18588}
18589
18590OMPClause *SemaOpenMP::ActOnOpenMPFullClause(SourceLocation StartLoc,
18591 SourceLocation EndLoc) {
18592 return OMPFullClause::Create(C: getASTContext(), StartLoc, EndLoc);
18593}
18594
18595OMPClause *SemaOpenMP::ActOnOpenMPPartialClause(Expr *FactorExpr,
18596 SourceLocation StartLoc,
18597 SourceLocation LParenLoc,
18598 SourceLocation EndLoc) {
18599 if (FactorExpr) {
18600 // If an argument is specified, it must be a constant (or an unevaluated
18601 // template expression).
18602 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
18603 E: FactorExpr, CKind: OMPC_partial, /*StrictlyPositive=*/true);
18604 if (FactorResult.isInvalid())
18605 return nullptr;
18606 FactorExpr = FactorResult.get();
18607 }
18608
18609 return OMPPartialClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
18610 Factor: FactorExpr);
18611}
18612
18613OMPClause *SemaOpenMP::ActOnOpenMPLoopRangeClause(
18614 Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc,
18615 SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc) {
18616
18617 // OpenMP [6.0, Restrictions]
18618 // First and Count must be integer expressions with positive value
18619 ExprResult FirstVal =
18620 VerifyPositiveIntegerConstantInClause(E: First, CKind: OMPC_looprange);
18621 if (FirstVal.isInvalid())
18622 First = nullptr;
18623
18624 ExprResult CountVal =
18625 VerifyPositiveIntegerConstantInClause(E: Count, CKind: OMPC_looprange);
18626 if (CountVal.isInvalid())
18627 Count = nullptr;
18628
18629 // OpenMP [6.0, Restrictions]
18630 // first + count - 1 must not evaluate to a value greater than the
18631 // loop sequence length of the associated canonical loop sequence.
18632 // This check must be performed afterwards due to the delayed
18633 // parsing and computation of the associated loop sequence
18634 return OMPLoopRangeClause::Create(C: getASTContext(), StartLoc, LParenLoc,
18635 FirstLoc, CountLoc, EndLoc, First, Count);
18636}
18637
18638OMPClause *SemaOpenMP::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
18639 SourceLocation LParenLoc,
18640 SourceLocation EndLoc) {
18641 ExprResult AlignVal;
18642 AlignVal = VerifyPositiveIntegerConstantInClause(E: A, CKind: OMPC_align);
18643 if (AlignVal.isInvalid())
18644 return nullptr;
18645 return OMPAlignClause::Create(C: getASTContext(), A: AlignVal.get(), StartLoc,
18646 LParenLoc, EndLoc);
18647}
18648
18649OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause(
18650 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
18651 SourceLocation StartLoc, SourceLocation LParenLoc,
18652 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
18653 SourceLocation EndLoc) {
18654 OMPClause *Res = nullptr;
18655 switch (Kind) {
18656 case OMPC_schedule: {
18657 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
18658 assert(Argument.size() == NumberOfElements &&
18659 ArgumentLoc.size() == NumberOfElements);
18660 Res = ActOnOpenMPScheduleClause(
18661 M1: static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
18662 M2: static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
18663 Kind: static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), ChunkSize: Expr,
18664 StartLoc, LParenLoc, M1Loc: ArgumentLoc[Modifier1], M2Loc: ArgumentLoc[Modifier2],
18665 KindLoc: ArgumentLoc[ScheduleKind], CommaLoc: DelimLoc, EndLoc);
18666 break;
18667 }
18668 case OMPC_if:
18669 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
18670 Res = ActOnOpenMPIfClause(NameModifier: static_cast<OpenMPDirectiveKind>(Argument.back()),
18671 Condition: Expr, StartLoc, LParenLoc, NameModifierLoc: ArgumentLoc.back(),
18672 ColonLoc: DelimLoc, EndLoc);
18673 break;
18674 case OMPC_dist_schedule:
18675 Res = ActOnOpenMPDistScheduleClause(
18676 Kind: static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), ChunkSize: Expr,
18677 StartLoc, LParenLoc, KindLoc: ArgumentLoc.back(), CommaLoc: DelimLoc, EndLoc);
18678 break;
18679 case OMPC_default:
18680 enum { DefaultModifier, DefaultVarCategory };
18681 Res = ActOnOpenMPDefaultClause(
18682 M: static_cast<llvm::omp::DefaultKind>(Argument[DefaultModifier]),
18683 MLoc: ArgumentLoc[DefaultModifier],
18684 VCKind: static_cast<OpenMPDefaultClauseVariableCategory>(
18685 Argument[DefaultVarCategory]),
18686 VCKindLoc: ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
18687 break;
18688 case OMPC_defaultmap:
18689 enum { Modifier, DefaultmapKind };
18690 Res = ActOnOpenMPDefaultmapClause(
18691 M: static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
18692 Kind: static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
18693 StartLoc, LParenLoc, MLoc: ArgumentLoc[Modifier], KindLoc: ArgumentLoc[DefaultmapKind],
18694 EndLoc);
18695 break;
18696 case OMPC_order:
18697 enum { OrderModifier, OrderKind };
18698 Res = ActOnOpenMPOrderClause(
18699 Modifier: static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
18700 Kind: static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
18701 LParenLoc, MLoc: ArgumentLoc[OrderModifier], KindLoc: ArgumentLoc[OrderKind], EndLoc);
18702 break;
18703 case OMPC_device:
18704 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
18705 Res = ActOnOpenMPDeviceClause(
18706 Modifier: static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Device: Expr,
18707 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
18708 break;
18709 case OMPC_grainsize:
18710 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
18711 "Modifier for grainsize clause and its location are expected.");
18712 Res = ActOnOpenMPGrainsizeClause(
18713 Modifier: static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Size: Expr,
18714 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
18715 break;
18716 case OMPC_num_tasks:
18717 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
18718 "Modifier for num_tasks clause and its location are expected.");
18719 Res = ActOnOpenMPNumTasksClause(
18720 Modifier: static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), NumTasks: Expr,
18721 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
18722 break;
18723 case OMPC_dyn_groupprivate: {
18724 enum { Modifier1, Modifier2, NumberOfElements };
18725 assert(Argument.size() == NumberOfElements &&
18726 ArgumentLoc.size() == NumberOfElements &&
18727 "Modifiers for dyn_groupprivate clause and their locations are "
18728 "expected.");
18729 Res = ActOnOpenMPDynGroupprivateClause(
18730 M1: static_cast<OpenMPDynGroupprivateClauseModifier>(Argument[Modifier1]),
18731 M2: static_cast<OpenMPDynGroupprivateClauseFallbackModifier>(
18732 Argument[Modifier2]),
18733 Size: Expr, StartLoc, LParenLoc, M1Loc: ArgumentLoc[Modifier1],
18734 M2Loc: ArgumentLoc[Modifier2], EndLoc);
18735 break;
18736 }
18737 case OMPC_final:
18738 case OMPC_safelen:
18739 case OMPC_simdlen:
18740 case OMPC_sizes:
18741 case OMPC_allocator:
18742 case OMPC_collapse:
18743 case OMPC_proc_bind:
18744 case OMPC_private:
18745 case OMPC_firstprivate:
18746 case OMPC_lastprivate:
18747 case OMPC_shared:
18748 case OMPC_reduction:
18749 case OMPC_task_reduction:
18750 case OMPC_in_reduction:
18751 case OMPC_linear:
18752 case OMPC_aligned:
18753 case OMPC_copyin:
18754 case OMPC_copyprivate:
18755 case OMPC_ordered:
18756 case OMPC_nowait:
18757 case OMPC_untied:
18758 case OMPC_mergeable:
18759 case OMPC_threadprivate:
18760 case OMPC_groupprivate:
18761 case OMPC_allocate:
18762 case OMPC_flush:
18763 case OMPC_depobj:
18764 case OMPC_read:
18765 case OMPC_write:
18766 case OMPC_update:
18767 case OMPC_capture:
18768 case OMPC_compare:
18769 case OMPC_seq_cst:
18770 case OMPC_acq_rel:
18771 case OMPC_acquire:
18772 case OMPC_release:
18773 case OMPC_relaxed:
18774 case OMPC_depend:
18775 case OMPC_threads:
18776 case OMPC_simd:
18777 case OMPC_map:
18778 case OMPC_num_teams:
18779 case OMPC_thread_limit:
18780 case OMPC_priority:
18781 case OMPC_nogroup:
18782 case OMPC_hint:
18783 case OMPC_unknown:
18784 case OMPC_uniform:
18785 case OMPC_to:
18786 case OMPC_from:
18787 case OMPC_use_device_ptr:
18788 case OMPC_use_device_addr:
18789 case OMPC_is_device_ptr:
18790 case OMPC_has_device_addr:
18791 case OMPC_unified_address:
18792 case OMPC_unified_shared_memory:
18793 case OMPC_reverse_offload:
18794 case OMPC_dynamic_allocators:
18795 case OMPC_atomic_default_mem_order:
18796 case OMPC_self_maps:
18797 case OMPC_device_type:
18798 case OMPC_match:
18799 case OMPC_nontemporal:
18800 case OMPC_at:
18801 case OMPC_severity:
18802 case OMPC_message:
18803 case OMPC_destroy:
18804 case OMPC_novariants:
18805 case OMPC_nocontext:
18806 case OMPC_detach:
18807 case OMPC_inclusive:
18808 case OMPC_exclusive:
18809 case OMPC_uses_allocators:
18810 case OMPC_affinity:
18811 case OMPC_when:
18812 case OMPC_bind:
18813 default:
18814 llvm_unreachable("Clause is not allowed.");
18815 }
18816 return Res;
18817}
18818
18819static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
18820 OpenMPScheduleClauseModifier M2,
18821 SourceLocation M1Loc, SourceLocation M2Loc) {
18822 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
18823 SmallVector<unsigned, 2> Excluded;
18824 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
18825 Excluded.push_back(Elt: M2);
18826 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
18827 Excluded.push_back(Elt: OMPC_SCHEDULE_MODIFIER_monotonic);
18828 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
18829 Excluded.push_back(Elt: OMPC_SCHEDULE_MODIFIER_nonmonotonic);
18830 S.Diag(Loc: M1Loc, DiagID: diag::err_omp_unexpected_clause_value)
18831 << getListOfPossibleValues(K: OMPC_schedule,
18832 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
18833 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
18834 Exclude: Excluded)
18835 << getOpenMPClauseNameForDiag(C: OMPC_schedule);
18836 return true;
18837 }
18838 return false;
18839}
18840
18841OMPClause *SemaOpenMP::ActOnOpenMPScheduleClause(
18842 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
18843 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
18844 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
18845 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
18846 if (checkScheduleModifiers(S&: SemaRef, M1, M2, M1Loc, M2Loc) ||
18847 checkScheduleModifiers(S&: SemaRef, M1: M2, M2: M1, M1Loc: M2Loc, M2Loc: M1Loc))
18848 return nullptr;
18849 // OpenMP, 2.7.1, Loop Construct, Restrictions
18850 // Either the monotonic modifier or the nonmonotonic modifier can be specified
18851 // but not both.
18852 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
18853 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
18854 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
18855 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
18856 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
18857 Diag(Loc: M2Loc, DiagID: diag::err_omp_unexpected_schedule_modifier)
18858 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule, Type: M2)
18859 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule, Type: M1);
18860 return nullptr;
18861 }
18862 if (Kind == OMPC_SCHEDULE_unknown) {
18863 std::string Values;
18864 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
18865 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
18866 Values = getListOfPossibleValues(K: OMPC_schedule, /*First=*/0,
18867 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
18868 Exclude);
18869 } else {
18870 Values = getListOfPossibleValues(K: OMPC_schedule, /*First=*/0,
18871 /*Last=*/OMPC_SCHEDULE_unknown);
18872 }
18873 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
18874 << Values << getOpenMPClauseNameForDiag(C: OMPC_schedule);
18875 return nullptr;
18876 }
18877 // OpenMP, 2.7.1, Loop Construct, Restrictions
18878 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
18879 // schedule(guided).
18880 // OpenMP 5.0 does not have this restriction.
18881 if (getLangOpts().OpenMP < 50 &&
18882 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
18883 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
18884 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
18885 Diag(Loc: M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
18886 DiagID: diag::err_omp_schedule_nonmonotonic_static);
18887 return nullptr;
18888 }
18889 Expr *ValExpr = ChunkSize;
18890 Stmt *HelperValStmt = nullptr;
18891 if (ChunkSize) {
18892 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
18893 !ChunkSize->isInstantiationDependent() &&
18894 !ChunkSize->containsUnexpandedParameterPack()) {
18895 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
18896 ExprResult Val =
18897 PerformOpenMPImplicitIntegerConversion(Loc: ChunkSizeLoc, Op: ChunkSize);
18898 if (Val.isInvalid())
18899 return nullptr;
18900
18901 ValExpr = Val.get();
18902
18903 // OpenMP [2.7.1, Restrictions]
18904 // chunk_size must be a loop invariant integer expression with a positive
18905 // value.
18906 if (std::optional<llvm::APSInt> Result =
18907 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
18908 if (Result->isSigned() && !Result->isStrictlyPositive()) {
18909 Diag(Loc: ChunkSizeLoc, DiagID: diag::err_omp_negative_expression_in_clause)
18910 << "schedule" << 1 << ChunkSize->getSourceRange();
18911 return nullptr;
18912 }
18913 } else if (getOpenMPCaptureRegionForClause(
18914 DSAStack->getCurrentDirective(), CKind: OMPC_schedule,
18915 OMPVersion: getLangOpts().getOpenMPVersion()) != OMPD_unknown &&
18916 !SemaRef.CurContext->isDependentContext()) {
18917 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
18918 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18919 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
18920 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
18921 }
18922 }
18923 }
18924
18925 return new (getASTContext())
18926 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
18927 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
18928}
18929
18930OMPClause *SemaOpenMP::ActOnOpenMPClause(OpenMPClauseKind Kind,
18931 SourceLocation StartLoc,
18932 SourceLocation EndLoc) {
18933 OMPClause *Res = nullptr;
18934 switch (Kind) {
18935 case OMPC_ordered:
18936 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
18937 break;
18938 case OMPC_nowait:
18939 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc,
18940 /*LParenLoc=*/SourceLocation(),
18941 /*Condition=*/nullptr);
18942 break;
18943 case OMPC_untied:
18944 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
18945 break;
18946 case OMPC_mergeable:
18947 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
18948 break;
18949 case OMPC_read:
18950 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
18951 break;
18952 case OMPC_write:
18953 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
18954 break;
18955 case OMPC_update:
18956 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
18957 break;
18958 case OMPC_capture:
18959 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
18960 break;
18961 case OMPC_compare:
18962 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
18963 break;
18964 case OMPC_fail:
18965 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
18966 break;
18967 case OMPC_seq_cst:
18968 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
18969 break;
18970 case OMPC_acq_rel:
18971 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
18972 break;
18973 case OMPC_acquire:
18974 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
18975 break;
18976 case OMPC_release:
18977 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
18978 break;
18979 case OMPC_relaxed:
18980 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
18981 break;
18982 case OMPC_weak:
18983 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
18984 break;
18985 case OMPC_threads:
18986 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
18987 break;
18988 case OMPC_simd:
18989 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
18990 break;
18991 case OMPC_nogroup:
18992 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
18993 break;
18994 case OMPC_unified_address:
18995 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
18996 break;
18997 case OMPC_unified_shared_memory:
18998 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18999 break;
19000 case OMPC_reverse_offload:
19001 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
19002 break;
19003 case OMPC_dynamic_allocators:
19004 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
19005 break;
19006 case OMPC_self_maps:
19007 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
19008 break;
19009 case OMPC_destroy:
19010 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
19011 /*LParenLoc=*/SourceLocation(),
19012 /*VarLoc=*/SourceLocation(), EndLoc);
19013 break;
19014 case OMPC_full:
19015 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
19016 break;
19017 case OMPC_partial:
19018 Res = ActOnOpenMPPartialClause(FactorExpr: nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
19019 break;
19020 case OMPC_ompx_bare:
19021 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
19022 break;
19023 case OMPC_if:
19024 case OMPC_final:
19025 case OMPC_num_threads:
19026 case OMPC_safelen:
19027 case OMPC_simdlen:
19028 case OMPC_sizes:
19029 case OMPC_allocator:
19030 case OMPC_collapse:
19031 case OMPC_schedule:
19032 case OMPC_private:
19033 case OMPC_firstprivate:
19034 case OMPC_lastprivate:
19035 case OMPC_shared:
19036 case OMPC_reduction:
19037 case OMPC_task_reduction:
19038 case OMPC_in_reduction:
19039 case OMPC_linear:
19040 case OMPC_aligned:
19041 case OMPC_copyin:
19042 case OMPC_copyprivate:
19043 case OMPC_default:
19044 case OMPC_proc_bind:
19045 case OMPC_threadprivate:
19046 case OMPC_groupprivate:
19047 case OMPC_allocate:
19048 case OMPC_flush:
19049 case OMPC_depobj:
19050 case OMPC_depend:
19051 case OMPC_device:
19052 case OMPC_map:
19053 case OMPC_num_teams:
19054 case OMPC_thread_limit:
19055 case OMPC_priority:
19056 case OMPC_grainsize:
19057 case OMPC_num_tasks:
19058 case OMPC_hint:
19059 case OMPC_dist_schedule:
19060 case OMPC_defaultmap:
19061 case OMPC_unknown:
19062 case OMPC_uniform:
19063 case OMPC_to:
19064 case OMPC_from:
19065 case OMPC_use_device_ptr:
19066 case OMPC_use_device_addr:
19067 case OMPC_is_device_ptr:
19068 case OMPC_has_device_addr:
19069 case OMPC_atomic_default_mem_order:
19070 case OMPC_device_type:
19071 case OMPC_match:
19072 case OMPC_nontemporal:
19073 case OMPC_order:
19074 case OMPC_at:
19075 case OMPC_severity:
19076 case OMPC_message:
19077 case OMPC_novariants:
19078 case OMPC_nocontext:
19079 case OMPC_detach:
19080 case OMPC_inclusive:
19081 case OMPC_exclusive:
19082 case OMPC_uses_allocators:
19083 case OMPC_affinity:
19084 case OMPC_when:
19085 case OMPC_ompx_dyn_cgroup_mem:
19086 case OMPC_dyn_groupprivate:
19087 default:
19088 llvm_unreachable("Clause is not allowed.");
19089 }
19090 return Res;
19091}
19092
19093OMPClause *SemaOpenMP::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
19094 SourceLocation EndLoc,
19095 SourceLocation LParenLoc,
19096 Expr *Condition) {
19097 Expr *ValExpr = Condition;
19098 if (Condition && LParenLoc.isValid()) {
19099 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
19100 !Condition->isInstantiationDependent() &&
19101 !Condition->containsUnexpandedParameterPack()) {
19102 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
19103 if (Val.isInvalid())
19104 return nullptr;
19105
19106 ValExpr = Val.get();
19107 }
19108 }
19109 DSAStack->setNowaitRegion();
19110 return new (getASTContext())
19111 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
19112}
19113
19114OMPClause *SemaOpenMP::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
19115 SourceLocation EndLoc) {
19116 DSAStack->setUntiedRegion();
19117 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
19118}
19119
19120OMPClause *SemaOpenMP::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
19121 SourceLocation EndLoc) {
19122 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
19123}
19124
19125OMPClause *SemaOpenMP::ActOnOpenMPReadClause(SourceLocation StartLoc,
19126 SourceLocation EndLoc) {
19127 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
19128}
19129
19130OMPClause *SemaOpenMP::ActOnOpenMPWriteClause(SourceLocation StartLoc,
19131 SourceLocation EndLoc) {
19132 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
19133}
19134
19135OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
19136 SourceLocation EndLoc) {
19137 return new (getASTContext()) OMPUpdateClause(StartLoc, EndLoc);
19138}
19139
19140OMPClause *SemaOpenMP::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
19141 SourceLocation EndLoc) {
19142 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
19143}
19144
19145OMPClause *SemaOpenMP::ActOnOpenMPCompareClause(SourceLocation StartLoc,
19146 SourceLocation EndLoc) {
19147 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
19148}
19149
19150OMPClause *SemaOpenMP::ActOnOpenMPFailClause(SourceLocation StartLoc,
19151 SourceLocation EndLoc) {
19152 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
19153}
19154
19155OMPClause *SemaOpenMP::ActOnOpenMPFailClause(OpenMPClauseKind Parameter,
19156 SourceLocation KindLoc,
19157 SourceLocation StartLoc,
19158 SourceLocation LParenLoc,
19159 SourceLocation EndLoc) {
19160
19161 if (!checkFailClauseParameter(FailClauseParameter: Parameter)) {
19162 Diag(Loc: KindLoc, DiagID: diag::err_omp_atomic_fail_wrong_or_no_clauses);
19163 return nullptr;
19164 }
19165 return new (getASTContext())
19166 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
19167}
19168
19169OMPClause *SemaOpenMP::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
19170 SourceLocation EndLoc) {
19171 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
19172}
19173
19174OMPClause *SemaOpenMP::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
19175 SourceLocation EndLoc) {
19176 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
19177}
19178
19179OMPClause *SemaOpenMP::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
19180 SourceLocation EndLoc) {
19181 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
19182}
19183
19184OMPClause *SemaOpenMP::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
19185 SourceLocation EndLoc) {
19186 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
19187}
19188
19189OMPClause *SemaOpenMP::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
19190 SourceLocation EndLoc) {
19191 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
19192}
19193
19194OMPClause *SemaOpenMP::ActOnOpenMPWeakClause(SourceLocation StartLoc,
19195 SourceLocation EndLoc) {
19196 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
19197}
19198
19199OMPClause *SemaOpenMP::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
19200 SourceLocation EndLoc) {
19201 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
19202}
19203
19204OMPClause *SemaOpenMP::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
19205 SourceLocation EndLoc) {
19206 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
19207}
19208
19209OMPClause *SemaOpenMP::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
19210 SourceLocation EndLoc) {
19211 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
19212}
19213
19214OMPClause *SemaOpenMP::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
19215 SourceLocation EndLoc) {
19216 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
19217}
19218
19219OMPClause *
19220SemaOpenMP::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
19221 SourceLocation EndLoc) {
19222 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
19223}
19224
19225OMPClause *SemaOpenMP::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
19226 SourceLocation EndLoc) {
19227 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
19228}
19229
19230OMPClause *
19231SemaOpenMP::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
19232 SourceLocation EndLoc) {
19233 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
19234}
19235
19236OMPClause *SemaOpenMP::ActOnOpenMPSelfMapsClause(SourceLocation StartLoc,
19237 SourceLocation EndLoc) {
19238 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
19239}
19240
19241StmtResult
19242SemaOpenMP::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
19243 SourceLocation StartLoc,
19244 SourceLocation EndLoc) {
19245
19246 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
19247 // At least one action-clause must appear on a directive.
19248 if (!hasClauses(Clauses, K: OMPC_init, ClauseTypes: OMPC_use, ClauseTypes: OMPC_destroy, ClauseTypes: OMPC_nowait)) {
19249 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
19250 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
19251 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
19252 << Expected << getOpenMPDirectiveName(D: OMPD_interop, V: OMPVersion);
19253 return StmtError();
19254 }
19255
19256 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
19257 // A depend clause can only appear on the directive if a targetsync
19258 // interop-type is present or the interop-var was initialized with
19259 // the targetsync interop-type.
19260
19261 // If there is any 'init' clause diagnose if there is no 'init' clause with
19262 // interop-type of 'targetsync'. Cases involving other directives cannot be
19263 // diagnosed.
19264 const OMPDependClause *DependClause = nullptr;
19265 bool HasInitClause = false;
19266 bool IsTargetSync = false;
19267 for (const OMPClause *C : Clauses) {
19268 if (IsTargetSync)
19269 break;
19270 if (const auto *InitClause = dyn_cast<OMPInitClause>(Val: C)) {
19271 HasInitClause = true;
19272 if (InitClause->getIsTargetSync())
19273 IsTargetSync = true;
19274 } else if (const auto *DC = dyn_cast<OMPDependClause>(Val: C)) {
19275 DependClause = DC;
19276 }
19277 }
19278 if (DependClause && HasInitClause && !IsTargetSync) {
19279 Diag(Loc: DependClause->getBeginLoc(), DiagID: diag::err_omp_interop_bad_depend_clause);
19280 return StmtError();
19281 }
19282
19283 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
19284 // Each interop-var may be specified for at most one action-clause of each
19285 // interop construct.
19286 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
19287 for (OMPClause *C : Clauses) {
19288 OpenMPClauseKind ClauseKind = C->getClauseKind();
19289 std::pair<ValueDecl *, bool> DeclResult;
19290 SourceLocation ELoc;
19291 SourceRange ERange;
19292
19293 if (ClauseKind == OMPC_init) {
19294 auto *E = cast<OMPInitClause>(Val: C)->getInteropVar();
19295 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
19296 } else if (ClauseKind == OMPC_use) {
19297 auto *E = cast<OMPUseClause>(Val: C)->getInteropVar();
19298 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
19299 } else if (ClauseKind == OMPC_destroy) {
19300 auto *E = cast<OMPDestroyClause>(Val: C)->getInteropVar();
19301 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
19302 }
19303
19304 if (DeclResult.first) {
19305 if (!InteropVars.insert(Ptr: DeclResult.first).second) {
19306 Diag(Loc: ELoc, DiagID: diag::err_omp_interop_var_multiple_actions)
19307 << DeclResult.first;
19308 return StmtError();
19309 }
19310 }
19311 }
19312
19313 return OMPInteropDirective::Create(C: getASTContext(), StartLoc, EndLoc,
19314 Clauses);
19315}
19316
19317static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
19318 SourceLocation VarLoc,
19319 OpenMPClauseKind Kind) {
19320 SourceLocation ELoc;
19321 SourceRange ERange;
19322 Expr *RefExpr = InteropVarExpr;
19323 auto Res = getPrivateItem(S&: SemaRef, RefExpr, ELoc, ERange,
19324 /*AllowArraySection=*/false,
19325 /*AllowAssumedSizeArray=*/false,
19326 /*DiagType=*/"omp_interop_t");
19327
19328 if (Res.second) {
19329 // It will be analyzed later.
19330 return true;
19331 }
19332
19333 if (!Res.first)
19334 return false;
19335
19336 // Interop variable should be of type omp_interop_t.
19337 bool HasError = false;
19338 QualType InteropType;
19339 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get(Name: "omp_interop_t"),
19340 VarLoc, Sema::LookupOrdinaryName);
19341 if (SemaRef.LookupName(R&: Result, S: SemaRef.getCurScope())) {
19342 NamedDecl *ND = Result.getFoundDecl();
19343 if (const auto *TD = dyn_cast<TypeDecl>(Val: ND)) {
19344 InteropType = QualType(TD->getTypeForDecl(), 0);
19345 } else {
19346 HasError = true;
19347 }
19348 } else {
19349 HasError = true;
19350 }
19351
19352 if (HasError) {
19353 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_implied_type_not_found)
19354 << "omp_interop_t";
19355 return false;
19356 }
19357
19358 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
19359 if (!SemaRef.Context.hasSameType(T1: InteropType, T2: VarType)) {
19360 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_interop_variable_wrong_type);
19361 return false;
19362 }
19363
19364 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
19365 // The interop-var passed to init or destroy must be non-const.
19366 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
19367 isConstNotMutableType(SemaRef, Type: InteropVarExpr->getType())) {
19368 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_interop_variable_expected)
19369 << /*non-const*/ 1;
19370 return false;
19371 }
19372 return true;
19373}
19374
19375OMPClause *SemaOpenMP::ActOnOpenMPInitClause(
19376 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
19377 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
19378
19379 if (!isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_init))
19380 return nullptr;
19381
19382 if (!checkPreferTypeArgs(S&: *this, Info: InteropInfo))
19383 return nullptr;
19384
19385 return OMPInitClause::Create(C: getASTContext(), InteropVar, InteropInfo,
19386 StartLoc, LParenLoc, VarLoc, EndLoc);
19387}
19388
19389OMPClause *SemaOpenMP::ActOnOpenMPUseClause(Expr *InteropVar,
19390 SourceLocation StartLoc,
19391 SourceLocation LParenLoc,
19392 SourceLocation VarLoc,
19393 SourceLocation EndLoc) {
19394
19395 if (!isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_use))
19396 return nullptr;
19397
19398 return new (getASTContext())
19399 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
19400}
19401
19402OMPClause *SemaOpenMP::ActOnOpenMPDestroyClause(Expr *InteropVar,
19403 SourceLocation StartLoc,
19404 SourceLocation LParenLoc,
19405 SourceLocation VarLoc,
19406 SourceLocation EndLoc) {
19407 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
19408 DSAStack->getCurrentDirective() == OMPD_depobj) {
19409 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
19410 Diag(Loc: StartLoc, DiagID: diag::err_omp_expected_clause_argument)
19411 << getOpenMPClauseNameForDiag(C: OMPC_destroy)
19412 << getOpenMPDirectiveName(D: OMPD_depobj, V: OMPVersion);
19413 return nullptr;
19414 }
19415 if (InteropVar &&
19416 !isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_destroy))
19417 return nullptr;
19418
19419 return new (getASTContext())
19420 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
19421}
19422
19423OMPClause *SemaOpenMP::ActOnOpenMPNovariantsClause(Expr *Condition,
19424 SourceLocation StartLoc,
19425 SourceLocation LParenLoc,
19426 SourceLocation EndLoc) {
19427 Expr *ValExpr = Condition;
19428 Stmt *HelperValStmt = nullptr;
19429 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
19430 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
19431 !Condition->isInstantiationDependent() &&
19432 !Condition->containsUnexpandedParameterPack()) {
19433 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
19434 if (Val.isInvalid())
19435 return nullptr;
19436
19437 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
19438
19439 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19440 CaptureRegion = getOpenMPCaptureRegionForClause(
19441 DKind, CKind: OMPC_novariants, OMPVersion: getLangOpts().getOpenMPVersion());
19442 if (CaptureRegion != OMPD_unknown &&
19443 !SemaRef.CurContext->isDependentContext()) {
19444 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
19445 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19446 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
19447 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
19448 }
19449 }
19450
19451 return new (getASTContext()) OMPNovariantsClause(
19452 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19453}
19454
19455OMPClause *SemaOpenMP::ActOnOpenMPNocontextClause(Expr *Condition,
19456 SourceLocation StartLoc,
19457 SourceLocation LParenLoc,
19458 SourceLocation EndLoc) {
19459 Expr *ValExpr = Condition;
19460 Stmt *HelperValStmt = nullptr;
19461 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
19462 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
19463 !Condition->isInstantiationDependent() &&
19464 !Condition->containsUnexpandedParameterPack()) {
19465 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
19466 if (Val.isInvalid())
19467 return nullptr;
19468
19469 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
19470
19471 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19472 CaptureRegion = getOpenMPCaptureRegionForClause(
19473 DKind, CKind: OMPC_nocontext, OMPVersion: getLangOpts().getOpenMPVersion());
19474 if (CaptureRegion != OMPD_unknown &&
19475 !SemaRef.CurContext->isDependentContext()) {
19476 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
19477 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19478 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
19479 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
19480 }
19481 }
19482
19483 return new (getASTContext()) OMPNocontextClause(
19484 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19485}
19486
19487OMPClause *SemaOpenMP::ActOnOpenMPFilterClause(Expr *ThreadID,
19488 SourceLocation StartLoc,
19489 SourceLocation LParenLoc,
19490 SourceLocation EndLoc) {
19491 Expr *ValExpr = ThreadID;
19492 Stmt *HelperValStmt = nullptr;
19493
19494 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19495 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
19496 DKind, CKind: OMPC_filter, OMPVersion: getLangOpts().getOpenMPVersion());
19497 if (CaptureRegion != OMPD_unknown &&
19498 !SemaRef.CurContext->isDependentContext()) {
19499 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
19500 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19501 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
19502 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
19503 }
19504
19505 return new (getASTContext()) OMPFilterClause(
19506 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19507}
19508
19509OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
19510 ArrayRef<Expr *> VarList,
19511 const OMPVarListLocTy &Locs,
19512 OpenMPVarListDataTy &Data) {
19513 SourceLocation StartLoc = Locs.StartLoc;
19514 SourceLocation LParenLoc = Locs.LParenLoc;
19515 SourceLocation EndLoc = Locs.EndLoc;
19516 OMPClause *Res = nullptr;
19517 int ExtraModifier = Data.ExtraModifier;
19518 int OriginalSharingModifier = Data.OriginalSharingModifier;
19519 Expr *ExtraModifierExpr = Data.ExtraModifierExpr;
19520 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
19521 SourceLocation ColonLoc = Data.ColonLoc;
19522 switch (Kind) {
19523 case OMPC_private:
19524 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
19525 break;
19526 case OMPC_firstprivate:
19527 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
19528 break;
19529 case OMPC_lastprivate:
19530 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
19531 "Unexpected lastprivate modifier.");
19532 Res = ActOnOpenMPLastprivateClause(
19533 VarList, LPKind: static_cast<OpenMPLastprivateModifier>(ExtraModifier),
19534 LPKindLoc: ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
19535 break;
19536 case OMPC_shared:
19537 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
19538 break;
19539 case OMPC_reduction:
19540 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
19541 "Unexpected lastprivate modifier.");
19542 Res = ActOnOpenMPReductionClause(
19543 VarList,
19544 Modifiers: OpenMPVarListDataTy::OpenMPReductionClauseModifiers(
19545 ExtraModifier, OriginalSharingModifier),
19546 StartLoc, LParenLoc, ModifierLoc: ExtraModifierLoc, ColonLoc, EndLoc,
19547 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
19548 break;
19549 case OMPC_task_reduction:
19550 Res = ActOnOpenMPTaskReductionClause(
19551 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
19552 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
19553 break;
19554 case OMPC_in_reduction:
19555 Res = ActOnOpenMPInReductionClause(
19556 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
19557 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
19558 break;
19559 case OMPC_linear:
19560 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
19561 "Unexpected linear modifier.");
19562 Res = ActOnOpenMPLinearClause(
19563 VarList, Step: Data.DepModOrTailExpr, StartLoc, LParenLoc,
19564 LinKind: static_cast<OpenMPLinearClauseKind>(ExtraModifier), LinLoc: ExtraModifierLoc,
19565 ColonLoc, StepModifierLoc: Data.StepModifierLoc, EndLoc);
19566 break;
19567 case OMPC_aligned:
19568 Res = ActOnOpenMPAlignedClause(VarList, Alignment: Data.DepModOrTailExpr, StartLoc,
19569 LParenLoc, ColonLoc, EndLoc);
19570 break;
19571 case OMPC_copyin:
19572 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
19573 break;
19574 case OMPC_copyprivate:
19575 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
19576 break;
19577 case OMPC_flush:
19578 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
19579 break;
19580 case OMPC_depend:
19581 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
19582 "Unexpected depend modifier.");
19583 Res = ActOnOpenMPDependClause(
19584 Data: {.DepKind: static_cast<OpenMPDependClauseKind>(ExtraModifier), .DepLoc: ExtraModifierLoc,
19585 .ColonLoc: ColonLoc, .OmpAllMemoryLoc: Data.OmpAllMemoryLoc},
19586 DepModifier: Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
19587 break;
19588 case OMPC_map:
19589 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
19590 "Unexpected map modifier.");
19591 Res = ActOnOpenMPMapClause(
19592 IteratorModifier: Data.IteratorExpr, MapTypeModifiers: Data.MapTypeModifiers, MapTypeModifiersLoc: Data.MapTypeModifiersLoc,
19593 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId,
19594 MapType: static_cast<OpenMPMapClauseKind>(ExtraModifier), IsMapTypeImplicit: Data.IsMapTypeImplicit,
19595 MapLoc: ExtraModifierLoc, ColonLoc, VarList, Locs);
19596 break;
19597 case OMPC_to:
19598 Res = ActOnOpenMPToClause(
19599 MotionModifiers: Data.MotionModifiers, MotionModifiersLoc: Data.MotionModifiersLoc, IteratorModifier: Data.IteratorExpr,
19600 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId, ColonLoc,
19601 VarList, Locs);
19602 break;
19603 case OMPC_from:
19604 Res = ActOnOpenMPFromClause(
19605 MotionModifiers: Data.MotionModifiers, MotionModifiersLoc: Data.MotionModifiersLoc, IteratorModifier: Data.IteratorExpr,
19606 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId, ColonLoc,
19607 VarList, Locs);
19608 break;
19609 case OMPC_use_device_ptr:
19610 assert(0 <= Data.ExtraModifier &&
19611 Data.ExtraModifier <= OMPC_USE_DEVICE_PTR_FALLBACK_unknown &&
19612 "Unexpected use_device_ptr fallback modifier.");
19613 Res = ActOnOpenMPUseDevicePtrClause(
19614 VarList, Locs,
19615 FallbackModifier: static_cast<OpenMPUseDevicePtrFallbackModifier>(Data.ExtraModifier),
19616 FallbackModifierLoc: Data.ExtraModifierLoc);
19617 break;
19618 case OMPC_use_device_addr:
19619 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
19620 break;
19621 case OMPC_is_device_ptr:
19622 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
19623 break;
19624 case OMPC_has_device_addr:
19625 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
19626 break;
19627 case OMPC_allocate: {
19628 OpenMPAllocateClauseModifier Modifier1 = OMPC_ALLOCATE_unknown;
19629 OpenMPAllocateClauseModifier Modifier2 = OMPC_ALLOCATE_unknown;
19630 SourceLocation Modifier1Loc, Modifier2Loc;
19631 if (!Data.AllocClauseModifiers.empty()) {
19632 assert(Data.AllocClauseModifiers.size() <= 2 &&
19633 "More allocate modifiers than expected");
19634 Modifier1 = Data.AllocClauseModifiers[0];
19635 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
19636 if (Data.AllocClauseModifiers.size() == 2) {
19637 Modifier2 = Data.AllocClauseModifiers[1];
19638 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
19639 }
19640 }
19641 Res = ActOnOpenMPAllocateClause(
19642 Allocator: Data.DepModOrTailExpr, Alignment: Data.AllocateAlignment, FirstModifier: Modifier1, FirstModifierLoc: Modifier1Loc,
19643 SecondModifier: Modifier2, SecondModifierLoc: Modifier2Loc, VarList, StartLoc, ColonLoc: LParenLoc, LParenLoc: ColonLoc,
19644 EndLoc);
19645 break;
19646 }
19647 case OMPC_nontemporal:
19648 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
19649 break;
19650 case OMPC_inclusive:
19651 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
19652 break;
19653 case OMPC_exclusive:
19654 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
19655 break;
19656 case OMPC_affinity:
19657 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
19658 Modifier: Data.DepModOrTailExpr, Locators: VarList);
19659 break;
19660 case OMPC_doacross:
19661 Res = ActOnOpenMPDoacrossClause(
19662 DepType: static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
19663 DepLoc: ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
19664 break;
19665 case OMPC_num_teams:
19666 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_NUMTEAMS_unknown &&
19667 "Unexpected num_teams modifier.");
19668 Res = ActOnOpenMPNumTeamsClause(
19669 VarList,
19670 Modifier: static_cast<OpenMPNumTeamsClauseModifier>(Data.ExtraModifierArray[0]),
19671 ModifierExpr: Data.ExtraModifierExprArray[0], ModifierLoc: Data.ExtraModifierLocArray[0],
19672 ModifierExtra: static_cast<OpenMPNumTeamsClauseModifier>(Data.ExtraModifierArray[1]),
19673 ModifierExtraExpr: Data.ExtraModifierExprArray[1], ModifierExtraLoc: Data.ExtraModifierLocArray[1], StartLoc,
19674 LParenLoc, EndLoc);
19675 break;
19676 case OMPC_thread_limit:
19677 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_THREADLIMIT_unknown &&
19678 "Unexpected thread_limit modifier.");
19679 Res = ActOnOpenMPThreadLimitClause(
19680 VarList, Modifier: static_cast<OpenMPThreadLimitClauseModifier>(ExtraModifier),
19681 ModifierExpr: ExtraModifierExpr, ModifierLoc: ExtraModifierLoc, StartLoc, LParenLoc, EndLoc);
19682 break;
19683 case OMPC_num_threads:
19684 assert(0 <= Data.ExtraModifierArray[0] &&
19685 Data.ExtraModifierArray[0] <= OMPC_NUMTHREADS_unknown &&
19686 0 <= Data.ExtraModifierArray[1] &&
19687 Data.ExtraModifierArray[1] <= OMPC_NUMTHREADS_unknown &&
19688 "Unexpected num_threads modifier.");
19689 Res = ActOnOpenMPNumThreadsClause(
19690 VarList,
19691 SimpleModifier: static_cast<OpenMPNumThreadsClauseModifier>(Data.ExtraModifierArray[0]),
19692 SimpleModifierLoc: Data.ExtraModifierLocArray[0],
19693 ComplexModifier: static_cast<OpenMPNumThreadsClauseModifier>(Data.ExtraModifierArray[1]),
19694 ComplexModifierExpr: Data.ExtraModifierExprArray[1], ComplexModifierLoc: Data.ExtraModifierLocArray[1], StartLoc,
19695 LParenLoc, EndLoc);
19696 break;
19697 case OMPC_if:
19698 case OMPC_depobj:
19699 case OMPC_final:
19700 case OMPC_safelen:
19701 case OMPC_simdlen:
19702 case OMPC_sizes:
19703 case OMPC_allocator:
19704 case OMPC_collapse:
19705 case OMPC_default:
19706 case OMPC_proc_bind:
19707 case OMPC_schedule:
19708 case OMPC_ordered:
19709 case OMPC_nowait:
19710 case OMPC_untied:
19711 case OMPC_mergeable:
19712 case OMPC_threadprivate:
19713 case OMPC_groupprivate:
19714 case OMPC_read:
19715 case OMPC_write:
19716 case OMPC_update:
19717 case OMPC_capture:
19718 case OMPC_compare:
19719 case OMPC_seq_cst:
19720 case OMPC_acq_rel:
19721 case OMPC_acquire:
19722 case OMPC_release:
19723 case OMPC_relaxed:
19724 case OMPC_device:
19725 case OMPC_threads:
19726 case OMPC_simd:
19727 case OMPC_priority:
19728 case OMPC_grainsize:
19729 case OMPC_nogroup:
19730 case OMPC_num_tasks:
19731 case OMPC_hint:
19732 case OMPC_dist_schedule:
19733 case OMPC_defaultmap:
19734 case OMPC_unknown:
19735 case OMPC_uniform:
19736 case OMPC_unified_address:
19737 case OMPC_unified_shared_memory:
19738 case OMPC_reverse_offload:
19739 case OMPC_dynamic_allocators:
19740 case OMPC_atomic_default_mem_order:
19741 case OMPC_self_maps:
19742 case OMPC_device_type:
19743 case OMPC_match:
19744 case OMPC_order:
19745 case OMPC_at:
19746 case OMPC_severity:
19747 case OMPC_message:
19748 case OMPC_destroy:
19749 case OMPC_novariants:
19750 case OMPC_nocontext:
19751 case OMPC_detach:
19752 case OMPC_uses_allocators:
19753 case OMPC_when:
19754 case OMPC_bind:
19755 default:
19756 llvm_unreachable("Clause is not allowed.");
19757 }
19758 return Res;
19759}
19760
19761ExprResult SemaOpenMP::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
19762 ExprObjectKind OK,
19763 SourceLocation Loc) {
19764 ExprResult Res = SemaRef.BuildDeclRefExpr(
19765 D: Capture, Ty: Capture->getType().getNonReferenceType(), VK: VK_LValue, Loc);
19766 if (!Res.isUsable())
19767 return ExprError();
19768 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
19769 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: Loc, Opc: UO_Deref, InputExpr: Res.get());
19770 if (!Res.isUsable())
19771 return ExprError();
19772 }
19773 if (VK != VK_LValue && Res.get()->isGLValue()) {
19774 Res = SemaRef.DefaultLvalueConversion(E: Res.get());
19775 if (!Res.isUsable())
19776 return ExprError();
19777 }
19778 return Res;
19779}
19780
19781OMPClause *SemaOpenMP::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
19782 SourceLocation StartLoc,
19783 SourceLocation LParenLoc,
19784 SourceLocation EndLoc) {
19785 SmallVector<Expr *, 8> Vars;
19786 SmallVector<Expr *, 8> PrivateCopies;
19787 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
19788 bool IsImplicitClause =
19789 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
19790 for (Expr *RefExpr : VarList) {
19791 assert(RefExpr && "NULL expr in OpenMP private clause.");
19792 SourceLocation ELoc;
19793 SourceRange ERange;
19794 Expr *SimpleRefExpr = RefExpr;
19795 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
19796 if (Res.second) {
19797 // It will be analyzed later.
19798 Vars.push_back(Elt: RefExpr);
19799 PrivateCopies.push_back(Elt: nullptr);
19800 }
19801 ValueDecl *D = Res.first;
19802 if (!D)
19803 continue;
19804
19805 QualType Type = D->getType();
19806 auto *VD = dyn_cast<VarDecl>(Val: D);
19807
19808 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19809 // A variable that appears in a private clause must not have an incomplete
19810 // type or a reference type.
19811 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
19812 DiagID: diag::err_omp_private_incomplete_type))
19813 continue;
19814 Type = Type.getNonReferenceType();
19815
19816 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19817 // A variable that is privatized must not have a const-qualified type
19818 // unless it is of class type with a mutable member. This restriction does
19819 // not apply to the firstprivate clause.
19820 //
19821 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
19822 // A variable that appears in a private clause must not have a
19823 // const-qualified type unless it is of class type with a mutable member.
19824 if (rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_private, ELoc))
19825 continue;
19826
19827 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19828 // in a Construct]
19829 // Variables with the predetermined data-sharing attributes may not be
19830 // listed in data-sharing attributes clauses, except for the cases
19831 // listed below. For these exceptions only, listing a predetermined
19832 // variable in a data-sharing attribute clause is allowed and overrides
19833 // the variable's predetermined data-sharing attributes.
19834 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19835 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
19836 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
19837 << getOpenMPClauseNameForDiag(C: DVar.CKind)
19838 << getOpenMPClauseNameForDiag(C: OMPC_private);
19839 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19840 continue;
19841 }
19842
19843 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19844 // Variably modified types are not supported for tasks.
19845 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
19846 isOpenMPTaskingDirective(Kind: CurrDir)) {
19847 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
19848 << getOpenMPClauseNameForDiag(C: OMPC_private) << Type
19849 << getOpenMPDirectiveName(D: CurrDir, V: OMPVersion);
19850 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19851 VarDecl::DeclarationOnly;
19852 Diag(Loc: D->getLocation(),
19853 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19854 << D;
19855 continue;
19856 }
19857
19858 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19859 // A list item cannot appear in both a map clause and a data-sharing
19860 // attribute clause on the same construct
19861 //
19862 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19863 // A list item cannot appear in both a map clause and a data-sharing
19864 // attribute clause on the same construct unless the construct is a
19865 // combined construct.
19866 if ((getLangOpts().OpenMP <= 45 &&
19867 isOpenMPTargetExecutionDirective(DKind: CurrDir)) ||
19868 CurrDir == OMPD_target) {
19869 OpenMPClauseKind ConflictKind;
19870 if (DSAStack->checkMappableExprComponentListsForDecl(
19871 VD, /*CurrentRegionOnly=*/true,
19872 Check: [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
19873 OpenMPClauseKind WhereFoundClauseKind) -> bool {
19874 ConflictKind = WhereFoundClauseKind;
19875 return true;
19876 })) {
19877 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
19878 << getOpenMPClauseNameForDiag(C: OMPC_private)
19879 << getOpenMPClauseNameForDiag(C: ConflictKind)
19880 << getOpenMPDirectiveName(D: CurrDir, V: OMPVersion);
19881 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19882 continue;
19883 }
19884 }
19885
19886 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
19887 // A variable of class type (or array thereof) that appears in a private
19888 // clause requires an accessible, unambiguous default constructor for the
19889 // class type.
19890 // Generate helper private variable and initialize it with the default
19891 // value. The address of the original variable is replaced by the address of
19892 // the new private variable in CodeGen. This new variable is not added to
19893 // IdResolver, so the code in the OpenMP region uses original variable for
19894 // proper diagnostics.
19895 Type = Type.getUnqualifiedType();
19896 VarDecl *VDPrivate =
19897 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
19898 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
19899 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
19900 SemaRef.ActOnUninitializedDecl(dcl: VDPrivate);
19901 if (VDPrivate->isInvalidDecl())
19902 continue;
19903 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19904 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(), Loc: ELoc);
19905
19906 DeclRefExpr *Ref = nullptr;
19907 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19908 auto *FD = dyn_cast<FieldDecl>(Val: D);
19909 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19910 if (VD)
19911 Ref = buildDeclRefExpr(S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(),
19912 Loc: RefExpr->getExprLoc());
19913 else
19914 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
19915 }
19916 if (!IsImplicitClause)
19917 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_private, PrivateCopy: Ref);
19918 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
19919 ? RefExpr->IgnoreParens()
19920 : Ref);
19921 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
19922 }
19923
19924 if (Vars.empty())
19925 return nullptr;
19926
19927 return OMPPrivateClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
19928 VL: Vars, PrivateVL: PrivateCopies);
19929}
19930
19931OMPClause *SemaOpenMP::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
19932 SourceLocation StartLoc,
19933 SourceLocation LParenLoc,
19934 SourceLocation EndLoc) {
19935 SmallVector<Expr *, 8> Vars;
19936 SmallVector<Expr *, 8> PrivateCopies;
19937 SmallVector<Expr *, 8> Inits;
19938 SmallVector<Decl *, 4> ExprCaptures;
19939 bool IsImplicitClause =
19940 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
19941 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
19942 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
19943
19944 for (Expr *RefExpr : VarList) {
19945 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
19946 SourceLocation ELoc;
19947 SourceRange ERange;
19948 Expr *SimpleRefExpr = RefExpr;
19949 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
19950 if (Res.second) {
19951 // It will be analyzed later.
19952 Vars.push_back(Elt: RefExpr);
19953 PrivateCopies.push_back(Elt: nullptr);
19954 Inits.push_back(Elt: nullptr);
19955 }
19956 ValueDecl *D = Res.first;
19957 if (!D)
19958 continue;
19959
19960 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
19961 QualType Type = D->getType();
19962 auto *VD = dyn_cast<VarDecl>(Val: D);
19963
19964 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19965 // A variable that appears in a private clause must not have an incomplete
19966 // type or a reference type.
19967 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
19968 DiagID: diag::err_omp_firstprivate_incomplete_type))
19969 continue;
19970 Type = Type.getNonReferenceType();
19971
19972 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
19973 // A variable of class type (or array thereof) that appears in a private
19974 // clause requires an accessible, unambiguous copy constructor for the
19975 // class type.
19976 QualType ElemType =
19977 getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
19978
19979 // If an implicit firstprivate variable found it was checked already.
19980 DSAStackTy::DSAVarData TopDVar;
19981 if (!IsImplicitClause) {
19982 DSAStackTy::DSAVarData DVar =
19983 DSAStack->getTopDSA(D, /*FromParent=*/false);
19984 TopDVar = DVar;
19985 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19986 bool IsConstant = ElemType.isConstant(Ctx: getASTContext());
19987 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
19988 // A list item that specifies a given variable may not appear in more
19989 // than one clause on the same directive, except that a variable may be
19990 // specified in both firstprivate and lastprivate clauses.
19991 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19992 // A list item may appear in a firstprivate or lastprivate clause but not
19993 // both.
19994 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
19995 (isOpenMPDistributeDirective(DKind: CurrDir) ||
19996 DVar.CKind != OMPC_lastprivate) &&
19997 DVar.RefExpr) {
19998 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
19999 << getOpenMPClauseNameForDiag(C: DVar.CKind)
20000 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
20001 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20002 continue;
20003 }
20004
20005 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
20006 // in a Construct]
20007 // Variables with the predetermined data-sharing attributes may not be
20008 // listed in data-sharing attributes clauses, except for the cases
20009 // listed below. For these exceptions only, listing a predetermined
20010 // variable in a data-sharing attribute clause is allowed and overrides
20011 // the variable's predetermined data-sharing attributes.
20012 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
20013 // in a Construct, C/C++, p.2]
20014 // Variables with const-qualified type having no mutable member may be
20015 // listed in a firstprivate clause, even if they are static data members.
20016 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
20017 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
20018 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
20019 << getOpenMPClauseNameForDiag(C: DVar.CKind)
20020 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
20021 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20022 continue;
20023 }
20024
20025 // OpenMP [2.9.3.4, Restrictions, p.2]
20026 // A list item that is private within a parallel region must not appear
20027 // in a firstprivate clause on a worksharing construct if any of the
20028 // worksharing regions arising from the worksharing construct ever bind
20029 // to any of the parallel regions arising from the parallel construct.
20030 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
20031 // A list item that is private within a teams region must not appear in a
20032 // firstprivate clause on a distribute construct if any of the distribute
20033 // regions arising from the distribute construct ever bind to any of the
20034 // teams regions arising from the teams construct.
20035 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
20036 // A list item that appears in a reduction clause of a teams construct
20037 // must not appear in a firstprivate clause on a distribute construct if
20038 // any of the distribute regions arising from the distribute construct
20039 // ever bind to any of the teams regions arising from the teams construct.
20040 if ((isOpenMPWorksharingDirective(DKind: CurrDir) ||
20041 isOpenMPDistributeDirective(DKind: CurrDir)) &&
20042 !isOpenMPParallelDirective(DKind: CurrDir) &&
20043 !isOpenMPTeamsDirective(DKind: CurrDir)) {
20044 DVar = DSAStack->getImplicitDSA(D, FromParent: true);
20045 if (DVar.CKind != OMPC_shared &&
20046 (isOpenMPParallelDirective(DKind: DVar.DKind) ||
20047 isOpenMPTeamsDirective(DKind: DVar.DKind) ||
20048 DVar.DKind == OMPD_unknown)) {
20049 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
20050 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate)
20051 << getOpenMPClauseNameForDiag(C: OMPC_shared);
20052 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20053 continue;
20054 }
20055 }
20056 // OpenMP [2.9.3.4, Restrictions, p.3]
20057 // A list item that appears in a reduction clause of a parallel construct
20058 // must not appear in a firstprivate clause on a worksharing or task
20059 // construct if any of the worksharing or task regions arising from the
20060 // worksharing or task construct ever bind to any of the parallel regions
20061 // arising from the parallel construct.
20062 // OpenMP [2.9.3.4, Restrictions, p.4]
20063 // A list item that appears in a reduction clause in worksharing
20064 // construct must not appear in a firstprivate clause in a task construct
20065 // encountered during execution of any of the worksharing regions arising
20066 // from the worksharing construct.
20067 if (isOpenMPTaskingDirective(Kind: CurrDir)) {
20068 DVar = DSAStack->hasInnermostDSA(
20069 D,
20070 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
20071 return C == OMPC_reduction && !AppliedToPointee;
20072 },
20073 DPred: [](OpenMPDirectiveKind K) {
20074 return isOpenMPParallelDirective(DKind: K) ||
20075 isOpenMPWorksharingDirective(DKind: K) ||
20076 isOpenMPTeamsDirective(DKind: K);
20077 },
20078 /*FromParent=*/true);
20079 if (DVar.CKind == OMPC_reduction &&
20080 (isOpenMPParallelDirective(DKind: DVar.DKind) ||
20081 isOpenMPWorksharingDirective(DKind: DVar.DKind) ||
20082 isOpenMPTeamsDirective(DKind: DVar.DKind))) {
20083 Diag(Loc: ELoc, DiagID: diag::err_omp_parallel_reduction_in_task_firstprivate)
20084 << getOpenMPDirectiveName(D: DVar.DKind, V: OMPVersion);
20085 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20086 continue;
20087 }
20088 }
20089
20090 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
20091 // A list item cannot appear in both a map clause and a data-sharing
20092 // attribute clause on the same construct
20093 //
20094 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
20095 // A list item cannot appear in both a map clause and a data-sharing
20096 // attribute clause on the same construct unless the construct is a
20097 // combined construct.
20098 if ((getLangOpts().OpenMP <= 45 &&
20099 isOpenMPTargetExecutionDirective(DKind: CurrDir)) ||
20100 CurrDir == OMPD_target) {
20101 OpenMPClauseKind ConflictKind;
20102 if (DSAStack->checkMappableExprComponentListsForDecl(
20103 VD, /*CurrentRegionOnly=*/true,
20104 Check: [&ConflictKind](
20105 OMPClauseMappableExprCommon::MappableExprComponentListRef,
20106 OpenMPClauseKind WhereFoundClauseKind) {
20107 ConflictKind = WhereFoundClauseKind;
20108 return true;
20109 })) {
20110 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
20111 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate)
20112 << getOpenMPClauseNameForDiag(C: ConflictKind)
20113 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
20114 V: OMPVersion);
20115 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20116 continue;
20117 }
20118 }
20119 }
20120
20121 // Variably modified types are not supported for tasks.
20122 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
20123 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
20124 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
20125 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate) << Type
20126 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
20127 V: OMPVersion);
20128 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20129 VarDecl::DeclarationOnly;
20130 Diag(Loc: D->getLocation(),
20131 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20132 << D;
20133 continue;
20134 }
20135
20136 Type = Type.getUnqualifiedType();
20137 VarDecl *VDPrivate =
20138 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
20139 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
20140 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
20141 // Generate helper private variable and initialize it with the value of the
20142 // original variable. The address of the original variable is replaced by
20143 // the address of the new private variable in the CodeGen. This new variable
20144 // is not added to IdResolver, so the code in the OpenMP region uses
20145 // original variable for proper diagnostics and variable capturing.
20146 Expr *VDInitRefExpr = nullptr;
20147 // For arrays generate initializer for single element and replace it by the
20148 // original array element in CodeGen.
20149 if (Type->isArrayType()) {
20150 VarDecl *VDInit =
20151 buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type: ElemType, Name: D->getName());
20152 VDInitRefExpr = buildDeclRefExpr(S&: SemaRef, D: VDInit, Ty: ElemType, Loc: ELoc);
20153 Expr *Init = SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get();
20154 ElemType = ElemType.getUnqualifiedType();
20155 VarDecl *VDInitTemp = buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(),
20156 Type: ElemType, Name: ".firstprivate.temp");
20157 InitializedEntity Entity =
20158 InitializedEntity::InitializeVariable(Var: VDInitTemp);
20159 InitializationKind Kind = InitializationKind::CreateCopy(InitLoc: ELoc, EqualLoc: ELoc);
20160
20161 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
20162 ExprResult Result = InitSeq.Perform(S&: SemaRef, Entity, Kind, Args: Init);
20163 if (Result.isInvalid())
20164 VDPrivate->setInvalidDecl();
20165 else
20166 VDPrivate->setInit(Result.getAs<Expr>());
20167 // Remove temp variable declaration.
20168 getASTContext().Deallocate(Ptr: VDInitTemp);
20169 } else {
20170 VarDecl *VDInit = buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type,
20171 Name: ".firstprivate.temp");
20172 VDInitRefExpr = buildDeclRefExpr(S&: SemaRef, D: VDInit, Ty: RefExpr->getType(),
20173 Loc: RefExpr->getExprLoc());
20174 SemaRef.AddInitializerToDecl(
20175 dcl: VDPrivate, init: SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get(),
20176 /*DirectInit=*/false);
20177 }
20178 if (VDPrivate->isInvalidDecl()) {
20179 if (IsImplicitClause) {
20180 Diag(Loc: RefExpr->getExprLoc(),
20181 DiagID: diag::note_omp_task_predetermined_firstprivate_here);
20182 }
20183 continue;
20184 }
20185 SemaRef.CurContext->addDecl(D: VDPrivate);
20186 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
20187 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(),
20188 Loc: RefExpr->getExprLoc());
20189 DeclRefExpr *Ref = nullptr;
20190 if (!VD && !SemaRef.CurContext->isDependentContext()) {
20191 if (TopDVar.CKind == OMPC_lastprivate) {
20192 Ref = TopDVar.PrivateCopy;
20193 } else {
20194 auto *FD = dyn_cast<FieldDecl>(Val: D);
20195 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
20196 if (VD)
20197 Ref =
20198 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(),
20199 Loc: RefExpr->getExprLoc());
20200 else
20201 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
20202 if (VD || !isOpenMPCapturedDecl(D))
20203 ExprCaptures.push_back(Elt: Ref->getDecl());
20204 }
20205 }
20206 if (!IsImplicitClause)
20207 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
20208 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
20209 ? RefExpr->IgnoreParens()
20210 : Ref);
20211 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
20212 Inits.push_back(Elt: VDInitRefExpr);
20213 }
20214
20215 if (Vars.empty())
20216 return nullptr;
20217
20218 return OMPFirstprivateClause::Create(
20219 C: getASTContext(), StartLoc, LParenLoc, EndLoc, VL: Vars, PrivateVL: PrivateCopies, InitVL: Inits,
20220 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures));
20221}
20222
20223OMPClause *SemaOpenMP::ActOnOpenMPLastprivateClause(
20224 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
20225 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
20226 SourceLocation LParenLoc, SourceLocation EndLoc) {
20227 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
20228 assert(ColonLoc.isValid() && "Colon location must be valid.");
20229 Diag(Loc: LPKindLoc, DiagID: diag::err_omp_unexpected_clause_value)
20230 << getListOfPossibleValues(K: OMPC_lastprivate, /*First=*/0,
20231 /*Last=*/OMPC_LASTPRIVATE_unknown)
20232 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate);
20233 return nullptr;
20234 }
20235
20236 SmallVector<Expr *, 8> Vars;
20237 SmallVector<Expr *, 8> SrcExprs;
20238 SmallVector<Expr *, 8> DstExprs;
20239 SmallVector<Expr *, 8> AssignmentOps;
20240 SmallVector<Decl *, 4> ExprCaptures;
20241 SmallVector<Expr *, 4> ExprPostUpdates;
20242 for (Expr *RefExpr : VarList) {
20243 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
20244 SourceLocation ELoc;
20245 SourceRange ERange;
20246 Expr *SimpleRefExpr = RefExpr;
20247 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
20248 if (Res.second) {
20249 // It will be analyzed later.
20250 Vars.push_back(Elt: RefExpr);
20251 SrcExprs.push_back(Elt: nullptr);
20252 DstExprs.push_back(Elt: nullptr);
20253 AssignmentOps.push_back(Elt: nullptr);
20254 }
20255 ValueDecl *D = Res.first;
20256 if (!D)
20257 continue;
20258
20259 QualType Type = D->getType();
20260 auto *VD = dyn_cast<VarDecl>(Val: D);
20261
20262 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
20263 // A variable that appears in a lastprivate clause must not have an
20264 // incomplete type or a reference type.
20265 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
20266 DiagID: diag::err_omp_lastprivate_incomplete_type))
20267 continue;
20268 Type = Type.getNonReferenceType();
20269
20270 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20271 // A variable that is privatized must not have a const-qualified type
20272 // unless it is of class type with a mutable member. This restriction does
20273 // not apply to the firstprivate clause.
20274 //
20275 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
20276 // A variable that appears in a lastprivate clause must not have a
20277 // const-qualified type unless it is of class type with a mutable member.
20278 if (rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_lastprivate, ELoc))
20279 continue;
20280
20281 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
20282 // A list item that appears in a lastprivate clause with the conditional
20283 // modifier must be a scalar variable.
20284 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
20285 Diag(Loc: ELoc, DiagID: diag::err_omp_lastprivate_conditional_non_scalar);
20286 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20287 VarDecl::DeclarationOnly;
20288 Diag(Loc: D->getLocation(),
20289 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20290 << D;
20291 continue;
20292 }
20293
20294 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
20295 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
20296 // in a Construct]
20297 // Variables with the predetermined data-sharing attributes may not be
20298 // listed in data-sharing attributes clauses, except for the cases
20299 // listed below.
20300 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
20301 // A list item may appear in a firstprivate or lastprivate clause but not
20302 // both.
20303 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20304 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
20305 (isOpenMPDistributeDirective(DKind: CurrDir) ||
20306 DVar.CKind != OMPC_firstprivate) &&
20307 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
20308 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
20309 << getOpenMPClauseNameForDiag(C: DVar.CKind)
20310 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate);
20311 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20312 continue;
20313 }
20314
20315 // OpenMP [2.14.3.5, Restrictions, p.2]
20316 // A list item that is private within a parallel region, or that appears in
20317 // the reduction clause of a parallel construct, must not appear in a
20318 // lastprivate clause on a worksharing construct if any of the corresponding
20319 // worksharing regions ever binds to any of the corresponding parallel
20320 // regions.
20321 DSAStackTy::DSAVarData TopDVar = DVar;
20322 if (isOpenMPWorksharingDirective(DKind: CurrDir) &&
20323 !isOpenMPParallelDirective(DKind: CurrDir) &&
20324 !isOpenMPTeamsDirective(DKind: CurrDir)) {
20325 DVar = DSAStack->getImplicitDSA(D, FromParent: true);
20326 if (DVar.CKind != OMPC_shared) {
20327 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
20328 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate)
20329 << getOpenMPClauseNameForDiag(C: OMPC_shared);
20330 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20331 continue;
20332 }
20333 }
20334
20335 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
20336 // A variable of class type (or array thereof) that appears in a
20337 // lastprivate clause requires an accessible, unambiguous default
20338 // constructor for the class type, unless the list item is also specified
20339 // in a firstprivate clause.
20340 // A variable of class type (or array thereof) that appears in a
20341 // lastprivate clause requires an accessible, unambiguous copy assignment
20342 // operator for the class type.
20343 Type = getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
20344 VarDecl *SrcVD = buildVarDecl(SemaRef, Loc: ERange.getBegin(),
20345 Type: Type.getUnqualifiedType(), Name: ".lastprivate.src",
20346 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
20347 DeclRefExpr *PseudoSrcExpr =
20348 buildDeclRefExpr(S&: SemaRef, D: SrcVD, Ty: Type.getUnqualifiedType(), Loc: ELoc);
20349 VarDecl *DstVD =
20350 buildVarDecl(SemaRef, Loc: ERange.getBegin(), Type, Name: ".lastprivate.dst",
20351 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
20352 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: Type, Loc: ELoc);
20353 // For arrays generate assignment operation for single element and replace
20354 // it by the original array element in CodeGen.
20355 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, OpLoc: ELoc, Opc: BO_Assign,
20356 LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
20357 if (AssignmentOp.isInvalid())
20358 continue;
20359 AssignmentOp = SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: ELoc,
20360 /*DiscardedValue=*/false);
20361 if (AssignmentOp.isInvalid())
20362 continue;
20363
20364 DeclRefExpr *Ref = nullptr;
20365 if (!VD && !SemaRef.CurContext->isDependentContext()) {
20366 if (TopDVar.CKind == OMPC_firstprivate) {
20367 Ref = TopDVar.PrivateCopy;
20368 } else {
20369 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
20370 if (!isOpenMPCapturedDecl(D))
20371 ExprCaptures.push_back(Elt: Ref->getDecl());
20372 }
20373 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
20374 (!isOpenMPCapturedDecl(D) &&
20375 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
20376 ExprResult RefRes = SemaRef.DefaultLvalueConversion(E: Ref);
20377 if (!RefRes.isUsable())
20378 continue;
20379 ExprResult PostUpdateRes =
20380 SemaRef.BuildBinOp(DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign,
20381 LHSExpr: SimpleRefExpr, RHSExpr: RefRes.get());
20382 if (!PostUpdateRes.isUsable())
20383 continue;
20384 ExprPostUpdates.push_back(
20385 Elt: SemaRef.IgnoredValueConversions(E: PostUpdateRes.get()).get());
20386 }
20387 }
20388 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_lastprivate, PrivateCopy: Ref);
20389 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
20390 ? RefExpr->IgnoreParens()
20391 : Ref);
20392 SrcExprs.push_back(Elt: PseudoSrcExpr);
20393 DstExprs.push_back(Elt: PseudoDstExpr);
20394 AssignmentOps.push_back(Elt: AssignmentOp.get());
20395 }
20396
20397 if (Vars.empty())
20398 return nullptr;
20399
20400 return OMPLastprivateClause::Create(
20401 C: getASTContext(), StartLoc, LParenLoc, EndLoc, VL: Vars, SrcExprs, DstExprs,
20402 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
20403 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures),
20404 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: ExprPostUpdates));
20405}
20406
20407OMPClause *SemaOpenMP::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
20408 SourceLocation StartLoc,
20409 SourceLocation LParenLoc,
20410 SourceLocation EndLoc) {
20411 SmallVector<Expr *, 8> Vars;
20412 for (Expr *RefExpr : VarList) {
20413 assert(RefExpr && "NULL expr in OpenMP shared clause.");
20414 SourceLocation ELoc;
20415 SourceRange ERange;
20416 Expr *SimpleRefExpr = RefExpr;
20417 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
20418 if (Res.second) {
20419 // It will be analyzed later.
20420 Vars.push_back(Elt: RefExpr);
20421 }
20422 ValueDecl *D = Res.first;
20423 if (!D)
20424 continue;
20425
20426 auto *VD = dyn_cast<VarDecl>(Val: D);
20427 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
20428 // in a Construct]
20429 // Variables with the predetermined data-sharing attributes may not be
20430 // listed in data-sharing attributes clauses, except for the cases
20431 // listed below. For these exceptions only, listing a predetermined
20432 // variable in a data-sharing attribute clause is allowed and overrides
20433 // the variable's predetermined data-sharing attributes.
20434 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20435 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
20436 DVar.RefExpr) {
20437 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
20438 << getOpenMPClauseNameForDiag(C: DVar.CKind)
20439 << getOpenMPClauseNameForDiag(C: OMPC_shared);
20440 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20441 continue;
20442 }
20443
20444 DeclRefExpr *Ref = nullptr;
20445 if (!VD && isOpenMPCapturedDecl(D) &&
20446 !SemaRef.CurContext->isDependentContext())
20447 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
20448 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_shared, PrivateCopy: Ref);
20449 Vars.push_back(Elt: (VD || !Ref || SemaRef.CurContext->isDependentContext())
20450 ? RefExpr->IgnoreParens()
20451 : Ref);
20452 }
20453
20454 if (Vars.empty())
20455 return nullptr;
20456
20457 return OMPSharedClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
20458 VL: Vars);
20459}
20460
20461namespace {
20462class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
20463 DSAStackTy *Stack;
20464
20465public:
20466 bool VisitDeclRefExpr(DeclRefExpr *E) {
20467 if (auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
20468 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D: VD, /*FromParent=*/false);
20469 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
20470 return false;
20471 if (DVar.CKind != OMPC_unknown)
20472 return true;
20473 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
20474 D: VD,
20475 CPred: [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
20476 return isOpenMPPrivate(Kind: C) && !AppliedToPointee;
20477 },
20478 DPred: [](OpenMPDirectiveKind) { return true; },
20479 /*FromParent=*/true);
20480 return DVarPrivate.CKind != OMPC_unknown;
20481 }
20482 return false;
20483 }
20484 bool VisitStmt(Stmt *S) {
20485 for (Stmt *Child : S->children()) {
20486 if (Child && Visit(S: Child))
20487 return true;
20488 }
20489 return false;
20490 }
20491 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
20492};
20493} // namespace
20494
20495namespace {
20496// Transform MemberExpression for specified FieldDecl of current class to
20497// DeclRefExpr to specified OMPCapturedExprDecl.
20498class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
20499 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
20500 ValueDecl *Field = nullptr;
20501 DeclRefExpr *CapturedExpr = nullptr;
20502
20503public:
20504 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
20505 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
20506
20507 ExprResult TransformMemberExpr(MemberExpr *E) {
20508 if (isa<CXXThisExpr>(Val: E->getBase()->IgnoreParenImpCasts()) &&
20509 E->getMemberDecl() == Field) {
20510 CapturedExpr = buildCapture(S&: SemaRef, D: Field, CaptureExpr: E, /*WithInit=*/false);
20511 return CapturedExpr;
20512 }
20513 return BaseTransform::TransformMemberExpr(E);
20514 }
20515 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
20516};
20517} // namespace
20518
20519template <typename T, typename U>
20520static T filterLookupForUDReductionAndMapper(
20521 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
20522 for (U &Set : Lookups) {
20523 for (auto *D : Set) {
20524 if (T Res = Gen(cast<ValueDecl>(D)))
20525 return Res;
20526 }
20527 }
20528 return T();
20529}
20530
20531static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
20532 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
20533
20534 for (auto *RD : D->redecls()) {
20535 // Don't bother with extra checks if we already know this one isn't visible.
20536 if (RD == D)
20537 continue;
20538
20539 auto ND = cast<NamedDecl>(Val: RD);
20540 if (LookupResult::isVisible(SemaRef, D: ND))
20541 return ND;
20542 }
20543
20544 return nullptr;
20545}
20546
20547static void
20548argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
20549 SourceLocation Loc, QualType Ty,
20550 SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
20551 // Find all of the associated namespaces and classes based on the
20552 // arguments we have.
20553 Sema::AssociatedNamespaceSet AssociatedNamespaces;
20554 Sema::AssociatedClassSet AssociatedClasses;
20555 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
20556 SemaRef.FindAssociatedClassesAndNamespaces(InstantiationLoc: Loc, Args: &OVE, AssociatedNamespaces,
20557 AssociatedClasses);
20558
20559 // C++ [basic.lookup.argdep]p3:
20560 // Let X be the lookup set produced by unqualified lookup (3.4.1)
20561 // and let Y be the lookup set produced by argument dependent
20562 // lookup (defined as follows). If X contains [...] then Y is
20563 // empty. Otherwise Y is the set of declarations found in the
20564 // namespaces associated with the argument types as described
20565 // below. The set of declarations found by the lookup of the name
20566 // is the union of X and Y.
20567 //
20568 // Here, we compute Y and add its members to the overloaded
20569 // candidate set.
20570 for (auto *NS : AssociatedNamespaces) {
20571 // When considering an associated namespace, the lookup is the
20572 // same as the lookup performed when the associated namespace is
20573 // used as a qualifier (3.4.3.2) except that:
20574 //
20575 // -- Any using-directives in the associated namespace are
20576 // ignored.
20577 //
20578 // -- Any namespace-scope friend functions declared in
20579 // associated classes are visible within their respective
20580 // namespaces even if they are not visible during an ordinary
20581 // lookup (11.4).
20582 DeclContext::lookup_result R = NS->lookup(Name: Id.getName());
20583 for (auto *D : R) {
20584 auto *Underlying = D;
20585 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
20586 Underlying = USD->getTargetDecl();
20587
20588 if (!isa<OMPDeclareReductionDecl>(Val: Underlying) &&
20589 !isa<OMPDeclareMapperDecl>(Val: Underlying))
20590 continue;
20591
20592 if (!SemaRef.isVisible(D)) {
20593 D = findAcceptableDecl(SemaRef, D);
20594 if (!D)
20595 continue;
20596 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
20597 Underlying = USD->getTargetDecl();
20598 }
20599 Lookups.emplace_back();
20600 Lookups.back().addDecl(D: Underlying);
20601 }
20602 }
20603}
20604
20605static ExprResult
20606buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
20607 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
20608 const DeclarationNameInfo &ReductionId, QualType Ty,
20609 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
20610 if (ReductionIdScopeSpec.isInvalid())
20611 return ExprError();
20612 SmallVector<UnresolvedSet<8>, 4> Lookups;
20613 if (S) {
20614 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
20615 Lookup.suppressDiagnostics();
20616 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &ReductionIdScopeSpec,
20617 /*ObjectType=*/QualType())) {
20618 NamedDecl *D = Lookup.getRepresentativeDecl();
20619 do {
20620 S = S->getParent();
20621 } while (S && !S->isDeclScope(D));
20622 if (S)
20623 S = S->getParent();
20624 Lookups.emplace_back();
20625 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
20626 Lookup.clear();
20627 }
20628 } else if (auto *ULE =
20629 cast_or_null<UnresolvedLookupExpr>(Val: UnresolvedReduction)) {
20630 Lookups.push_back(Elt: UnresolvedSet<8>());
20631 Decl *PrevD = nullptr;
20632 for (NamedDecl *D : ULE->decls()) {
20633 if (D == PrevD)
20634 Lookups.push_back(Elt: UnresolvedSet<8>());
20635 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Val: D))
20636 Lookups.back().addDecl(D: DRD);
20637 PrevD = D;
20638 }
20639 }
20640 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
20641 Ty->isInstantiationDependentType() ||
20642 Ty->containsUnexpandedParameterPack() ||
20643 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
20644 return !D->isInvalidDecl() &&
20645 (D->getType()->isDependentType() ||
20646 D->getType()->isInstantiationDependentType() ||
20647 D->getType()->containsUnexpandedParameterPack());
20648 })) {
20649 UnresolvedSet<8> ResSet;
20650 for (const UnresolvedSet<8> &Set : Lookups) {
20651 if (Set.empty())
20652 continue;
20653 ResSet.append(I: Set.begin(), E: Set.end());
20654 // The last item marks the end of all declarations at the specified scope.
20655 ResSet.addDecl(D: Set[Set.size() - 1]);
20656 }
20657 return UnresolvedLookupExpr::Create(
20658 Context: SemaRef.Context, /*NamingClass=*/nullptr,
20659 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: SemaRef.Context), NameInfo: ReductionId,
20660 /*ADL=*/RequiresADL: true, Begin: ResSet.begin(), End: ResSet.end(), /*KnownDependent=*/false,
20661 /*KnownInstantiationDependent=*/false);
20662 }
20663 // Lookup inside the classes.
20664 // C++ [over.match.oper]p3:
20665 // For a unary operator @ with an operand of a type whose
20666 // cv-unqualified version is T1, and for a binary operator @ with
20667 // a left operand of a type whose cv-unqualified version is T1 and
20668 // a right operand of a type whose cv-unqualified version is T2,
20669 // three sets of candidate functions, designated member
20670 // candidates, non-member candidates and built-in candidates, are
20671 // constructed as follows:
20672 // -- If T1 is a complete class type or a class currently being
20673 // defined, the set of member candidates is the result of the
20674 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
20675 // the set of member candidates is empty.
20676 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
20677 Lookup.suppressDiagnostics();
20678 if (Ty->isRecordType()) {
20679 // Complete the type if it can be completed.
20680 // If the type is neither complete nor being defined, bail out now.
20681 bool IsComplete = SemaRef.isCompleteType(Loc, T: Ty);
20682 auto *RD = Ty->castAsRecordDecl();
20683 if (IsComplete || RD->isBeingDefined()) {
20684 Lookup.clear();
20685 SemaRef.LookupQualifiedName(R&: Lookup, LookupCtx: RD);
20686 if (Lookup.empty()) {
20687 Lookups.emplace_back();
20688 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
20689 }
20690 }
20691 }
20692 // Perform ADL.
20693 if (SemaRef.getLangOpts().CPlusPlus)
20694 argumentDependentLookup(SemaRef, Id: ReductionId, Loc, Ty, Lookups);
20695 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20696 Lookups, Gen: [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
20697 if (!D->isInvalidDecl() &&
20698 SemaRef.Context.hasSameType(T1: D->getType(), T2: Ty))
20699 return D;
20700 return nullptr;
20701 }))
20702 return SemaRef.BuildDeclRefExpr(D: VD, Ty: VD->getType().getNonReferenceType(),
20703 VK: VK_LValue, Loc);
20704 if (SemaRef.getLangOpts().CPlusPlus) {
20705 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20706 Lookups, Gen: [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
20707 if (!D->isInvalidDecl() &&
20708 SemaRef.IsDerivedFrom(Loc, Derived: Ty, Base: D->getType()) &&
20709 !Ty.isMoreQualifiedThan(other: D->getType(),
20710 Ctx: SemaRef.getASTContext()))
20711 return D;
20712 return nullptr;
20713 })) {
20714 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
20715 /*DetectVirtual=*/false);
20716 if (SemaRef.IsDerivedFrom(Loc, Derived: Ty, Base: VD->getType(), Paths)) {
20717 if (!Paths.isAmbiguous(BaseType: SemaRef.Context.getCanonicalType(
20718 T: VD->getType().getUnqualifiedType()))) {
20719 if (SemaRef.CheckBaseClassAccess(
20720 AccessLoc: Loc, Base: VD->getType(), Derived: Ty, Path: Paths.front(),
20721 /*DiagID=*/0) != Sema::AR_inaccessible) {
20722 SemaRef.BuildBasePathArray(Paths, BasePath);
20723 return SemaRef.BuildDeclRefExpr(
20724 D: VD, Ty: VD->getType().getNonReferenceType(), VK: VK_LValue, Loc);
20725 }
20726 }
20727 }
20728 }
20729 }
20730 if (ReductionIdScopeSpec.isSet()) {
20731 SemaRef.Diag(Loc, DiagID: diag::err_omp_not_resolved_reduction_identifier)
20732 << Ty << Range;
20733 return ExprError();
20734 }
20735 return ExprEmpty();
20736}
20737
20738namespace {
20739/// Data for the reduction-based clauses.
20740struct ReductionData {
20741 /// List of original reduction items.
20742 SmallVector<Expr *, 8> Vars;
20743 /// List of private copies of the reduction items.
20744 SmallVector<Expr *, 8> Privates;
20745 /// LHS expressions for the reduction_op expressions.
20746 SmallVector<Expr *, 8> LHSs;
20747 /// RHS expressions for the reduction_op expressions.
20748 SmallVector<Expr *, 8> RHSs;
20749 /// Reduction operation expression.
20750 SmallVector<Expr *, 8> ReductionOps;
20751 /// inscan copy operation expressions.
20752 SmallVector<Expr *, 8> InscanCopyOps;
20753 /// inscan copy temp array expressions for prefix sums.
20754 SmallVector<Expr *, 8> InscanCopyArrayTemps;
20755 /// inscan copy temp array element expressions for prefix sums.
20756 SmallVector<Expr *, 8> InscanCopyArrayElems;
20757 /// Taskgroup descriptors for the corresponding reduction items in
20758 /// in_reduction clauses.
20759 SmallVector<Expr *, 8> TaskgroupDescriptors;
20760 /// List of captures for clause.
20761 SmallVector<Decl *, 4> ExprCaptures;
20762 /// List of postupdate expressions.
20763 SmallVector<Expr *, 4> ExprPostUpdates;
20764 /// Reduction modifier.
20765 unsigned RedModifier = 0;
20766 /// Original modifier.
20767 unsigned OrigSharingModifier = 0;
20768 /// Private Variable Reduction
20769 SmallVector<bool, 8> IsPrivateVarReduction;
20770 ReductionData() = delete;
20771 /// Reserves required memory for the reduction data.
20772 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
20773 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
20774 Vars.reserve(N: Size);
20775 Privates.reserve(N: Size);
20776 LHSs.reserve(N: Size);
20777 RHSs.reserve(N: Size);
20778 ReductionOps.reserve(N: Size);
20779 IsPrivateVarReduction.reserve(N: Size);
20780 if (RedModifier == OMPC_REDUCTION_inscan) {
20781 InscanCopyOps.reserve(N: Size);
20782 InscanCopyArrayTemps.reserve(N: Size);
20783 InscanCopyArrayElems.reserve(N: Size);
20784 }
20785 TaskgroupDescriptors.reserve(N: Size);
20786 ExprCaptures.reserve(N: Size);
20787 ExprPostUpdates.reserve(N: Size);
20788 }
20789 /// Stores reduction item and reduction operation only (required for dependent
20790 /// reduction item).
20791 void push(Expr *Item, Expr *ReductionOp) {
20792 Vars.emplace_back(Args&: Item);
20793 Privates.emplace_back(Args: nullptr);
20794 LHSs.emplace_back(Args: nullptr);
20795 RHSs.emplace_back(Args: nullptr);
20796 ReductionOps.emplace_back(Args&: ReductionOp);
20797 IsPrivateVarReduction.emplace_back(Args: false);
20798 TaskgroupDescriptors.emplace_back(Args: nullptr);
20799 if (RedModifier == OMPC_REDUCTION_inscan) {
20800 InscanCopyOps.push_back(Elt: nullptr);
20801 InscanCopyArrayTemps.push_back(Elt: nullptr);
20802 InscanCopyArrayElems.push_back(Elt: nullptr);
20803 }
20804 }
20805 /// Stores reduction data.
20806 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
20807 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
20808 Expr *CopyArrayElem, bool IsPrivate) {
20809 Vars.emplace_back(Args&: Item);
20810 Privates.emplace_back(Args&: Private);
20811 LHSs.emplace_back(Args&: LHS);
20812 RHSs.emplace_back(Args&: RHS);
20813 ReductionOps.emplace_back(Args&: ReductionOp);
20814 TaskgroupDescriptors.emplace_back(Args&: TaskgroupDescriptor);
20815 if (RedModifier == OMPC_REDUCTION_inscan) {
20816 InscanCopyOps.push_back(Elt: CopyOp);
20817 InscanCopyArrayTemps.push_back(Elt: CopyArrayTemp);
20818 InscanCopyArrayElems.push_back(Elt: CopyArrayElem);
20819 } else {
20820 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
20821 CopyArrayElem == nullptr &&
20822 "Copy operation must be used for inscan reductions only.");
20823 }
20824 IsPrivateVarReduction.emplace_back(Args&: IsPrivate);
20825 }
20826};
20827} // namespace
20828
20829static bool checkOMPArraySectionConstantForReduction(
20830 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
20831 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
20832 const Expr *Length = OASE->getLength();
20833 if (Length == nullptr) {
20834 // For array sections of the form [1:] or [:], we would need to analyze
20835 // the lower bound...
20836 if (OASE->getColonLocFirst().isValid())
20837 return false;
20838
20839 // This is an array subscript which has implicit length 1!
20840 SingleElement = true;
20841 ArraySizes.push_back(Elt: llvm::APSInt::get(X: 1));
20842 } else {
20843 Expr::EvalResult Result;
20844 if (!Length->EvaluateAsInt(Result, Ctx: Context))
20845 return false;
20846
20847 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
20848 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
20849 ArraySizes.push_back(Elt: ConstantLengthValue);
20850 }
20851
20852 // Get the base of this array section and walk up from there.
20853 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
20854
20855 // We require length = 1 for all array sections except the right-most to
20856 // guarantee that the memory region is contiguous and has no holes in it.
20857 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Val: Base)) {
20858 Length = TempOASE->getLength();
20859 if (Length == nullptr) {
20860 // For array sections of the form [1:] or [:], we would need to analyze
20861 // the lower bound...
20862 if (OASE->getColonLocFirst().isValid())
20863 return false;
20864
20865 // This is an array subscript which has implicit length 1!
20866 llvm::APSInt ConstantOne = llvm::APSInt::get(X: 1);
20867 ArraySizes.push_back(Elt: ConstantOne);
20868 } else {
20869 Expr::EvalResult Result;
20870 if (!Length->EvaluateAsInt(Result, Ctx: Context))
20871 return false;
20872
20873 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
20874 if (ConstantLengthValue.getSExtValue() != 1)
20875 return false;
20876
20877 ArraySizes.push_back(Elt: ConstantLengthValue);
20878 }
20879 Base = TempOASE->getBase()->IgnoreParenImpCasts();
20880 }
20881
20882 // If we have a single element, we don't need to add the implicit lengths.
20883 if (!SingleElement) {
20884 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base)) {
20885 // Has implicit length 1!
20886 llvm::APSInt ConstantOne = llvm::APSInt::get(X: 1);
20887 ArraySizes.push_back(Elt: ConstantOne);
20888 Base = TempASE->getBase()->IgnoreParenImpCasts();
20889 }
20890 }
20891
20892 // This array section can be privatized as a single value or as a constant
20893 // sized array.
20894 return true;
20895}
20896
20897static BinaryOperatorKind
20898getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
20899 if (BOK == BO_Add)
20900 return BO_AddAssign;
20901 if (BOK == BO_Mul)
20902 return BO_MulAssign;
20903 if (BOK == BO_And)
20904 return BO_AndAssign;
20905 if (BOK == BO_Or)
20906 return BO_OrAssign;
20907 if (BOK == BO_Xor)
20908 return BO_XorAssign;
20909 return BOK;
20910}
20911
20912static bool actOnOMPReductionKindClause(
20913 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
20914 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20915 SourceLocation ColonLoc, SourceLocation EndLoc,
20916 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20917 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
20918 DeclarationName DN = ReductionId.getName();
20919 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
20920 BinaryOperatorKind BOK = BO_Comma;
20921
20922 ASTContext &Context = S.Context;
20923 // OpenMP [2.14.3.6, reduction clause]
20924 // C
20925 // reduction-identifier is either an identifier or one of the following
20926 // operators: +, -, *, &, |, ^, && and ||
20927 // C++
20928 // reduction-identifier is either an id-expression or one of the following
20929 // operators: +, -, *, &, |, ^, && and ||
20930 switch (OOK) {
20931 case OO_Plus:
20932 BOK = BO_Add;
20933 break;
20934 case OO_Minus:
20935 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
20936 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
20937 // reduction identifier.
20938 if (S.LangOpts.OpenMP > 52)
20939 BOK = BO_Comma;
20940 else
20941 BOK = BO_Add;
20942 break;
20943 case OO_Star:
20944 BOK = BO_Mul;
20945 break;
20946 case OO_Amp:
20947 BOK = BO_And;
20948 break;
20949 case OO_Pipe:
20950 BOK = BO_Or;
20951 break;
20952 case OO_Caret:
20953 BOK = BO_Xor;
20954 break;
20955 case OO_AmpAmp:
20956 BOK = BO_LAnd;
20957 break;
20958 case OO_PipePipe:
20959 BOK = BO_LOr;
20960 break;
20961 case OO_New:
20962 case OO_Delete:
20963 case OO_Array_New:
20964 case OO_Array_Delete:
20965 case OO_Slash:
20966 case OO_Percent:
20967 case OO_Tilde:
20968 case OO_Exclaim:
20969 case OO_Equal:
20970 case OO_Less:
20971 case OO_Greater:
20972 case OO_LessEqual:
20973 case OO_GreaterEqual:
20974 case OO_PlusEqual:
20975 case OO_MinusEqual:
20976 case OO_StarEqual:
20977 case OO_SlashEqual:
20978 case OO_PercentEqual:
20979 case OO_CaretEqual:
20980 case OO_AmpEqual:
20981 case OO_PipeEqual:
20982 case OO_LessLess:
20983 case OO_GreaterGreater:
20984 case OO_LessLessEqual:
20985 case OO_GreaterGreaterEqual:
20986 case OO_EqualEqual:
20987 case OO_ExclaimEqual:
20988 case OO_Spaceship:
20989 case OO_PlusPlus:
20990 case OO_MinusMinus:
20991 case OO_Comma:
20992 case OO_ArrowStar:
20993 case OO_Arrow:
20994 case OO_Call:
20995 case OO_Subscript:
20996 case OO_Conditional:
20997 case OO_Coawait:
20998 case NUM_OVERLOADED_OPERATORS:
20999 llvm_unreachable("Unexpected reduction identifier");
21000 case OO_None:
21001 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
21002 if (II->isStr(Str: "max"))
21003 BOK = BO_GT;
21004 else if (II->isStr(Str: "min"))
21005 BOK = BO_LT;
21006 }
21007 break;
21008 }
21009
21010 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
21011 // A reduction clause with the minus (-) operator was deprecated
21012 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
21013 S.Diag(Loc: ReductionId.getLoc(), DiagID: diag::warn_omp_minus_in_reduction_deprecated);
21014
21015 SourceRange ReductionIdRange;
21016 if (ReductionIdScopeSpec.isValid())
21017 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
21018 else
21019 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
21020 ReductionIdRange.setEnd(ReductionId.getEndLoc());
21021
21022 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
21023 bool FirstIter = true;
21024 for (Expr *RefExpr : VarList) {
21025 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
21026 // OpenMP [2.1, C/C++]
21027 // A list item is a variable or array section, subject to the restrictions
21028 // specified in Section 2.4 on page 42 and in each of the sections
21029 // describing clauses and directives for which a list appears.
21030 // OpenMP [2.14.3.3, Restrictions, p.1]
21031 // A variable that is part of another variable (as an array or
21032 // structure element) cannot appear in a private clause.
21033 if (!FirstIter && IR != ER)
21034 ++IR;
21035 FirstIter = false;
21036 SourceLocation ELoc;
21037 SourceRange ERange;
21038 bool IsPrivate = false;
21039 Expr *SimpleRefExpr = RefExpr;
21040 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
21041 /*AllowArraySection=*/true);
21042 if (Res.second) {
21043 // Try to find 'declare reduction' corresponding construct before using
21044 // builtin/overloaded operators.
21045 QualType Type = Context.DependentTy;
21046 CXXCastPath BasePath;
21047 ExprResult DeclareReductionRef = buildDeclareReductionRef(
21048 SemaRef&: S, Loc: ELoc, Range: ERange, S: Stack->getCurScope(), ReductionIdScopeSpec,
21049 ReductionId, Ty: Type, BasePath, UnresolvedReduction: IR == ER ? nullptr : *IR);
21050 Expr *ReductionOp = nullptr;
21051 if (S.CurContext->isDependentContext() &&
21052 (DeclareReductionRef.isUnset() ||
21053 isa<UnresolvedLookupExpr>(Val: DeclareReductionRef.get())))
21054 ReductionOp = DeclareReductionRef.get();
21055 // It will be analyzed later.
21056 RD.push(Item: RefExpr, ReductionOp);
21057 }
21058 ValueDecl *D = Res.first;
21059 if (!D)
21060 continue;
21061
21062 Expr *TaskgroupDescriptor = nullptr;
21063 QualType Type;
21064 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: RefExpr->IgnoreParens());
21065 auto *OASE = dyn_cast<ArraySectionExpr>(Val: RefExpr->IgnoreParens());
21066 if (ASE) {
21067 Type = ASE->getType().getNonReferenceType();
21068 } else if (OASE) {
21069 QualType BaseType =
21070 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
21071 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21072 Type = ATy->getElementType();
21073 else
21074 Type = BaseType->getPointeeType();
21075 Type = Type.getNonReferenceType();
21076 } else {
21077 Type = Context.getBaseElementType(QT: D->getType().getNonReferenceType());
21078 }
21079 auto *VD = dyn_cast<VarDecl>(Val: D);
21080
21081 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
21082 // A variable that appears in a private clause must not have an incomplete
21083 // type or a reference type.
21084 if (S.RequireCompleteType(Loc: ELoc, T: D->getType(),
21085 DiagID: diag::err_omp_reduction_incomplete_type))
21086 continue;
21087 // OpenMP [2.14.3.6, reduction clause, Restrictions]
21088 // A list item that appears in a reduction clause must not be
21089 // const-qualified.
21090 if (rejectConstNotMutableType(SemaRef&: S, D, Type, CKind: ClauseKind, ELoc,
21091 /*AcceptIfMutable=*/false, ListItemNotVar: ASE || OASE))
21092 continue;
21093
21094 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
21095 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
21096 // If a list-item is a reference type then it must bind to the same object
21097 // for all threads of the team.
21098 if (!ASE && !OASE) {
21099 if (VD) {
21100 VarDecl *VDDef = VD->getDefinition();
21101 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
21102 DSARefChecker Check(Stack);
21103 if (Check.Visit(S: VDDef->getInit())) {
21104 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_ref_type_arg)
21105 << getOpenMPClauseNameForDiag(C: ClauseKind) << ERange;
21106 S.Diag(Loc: VDDef->getLocation(), DiagID: diag::note_defined_here) << VDDef;
21107 continue;
21108 }
21109 }
21110 }
21111
21112 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
21113 // in a Construct]
21114 // Variables with the predetermined data-sharing attributes may not be
21115 // listed in data-sharing attributes clauses, except for the cases
21116 // listed below. For these exceptions only, listing a predetermined
21117 // variable in a data-sharing attribute clause is allowed and overrides
21118 // the variable's predetermined data-sharing attributes.
21119 // OpenMP [2.14.3.6, Restrictions, p.3]
21120 // Any number of reduction clauses can be specified on the directive,
21121 // but a list item can appear only once in the reduction clauses for that
21122 // directive.
21123 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
21124 if (DVar.CKind == OMPC_reduction) {
21125 S.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced)
21126 << getOpenMPClauseNameForDiag(C: ClauseKind);
21127 if (DVar.RefExpr)
21128 S.Diag(Loc: DVar.RefExpr->getExprLoc(), DiagID: diag::note_omp_referenced);
21129 continue;
21130 }
21131 if (DVar.CKind != OMPC_unknown) {
21132 S.Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
21133 << getOpenMPClauseNameForDiag(C: DVar.CKind)
21134 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
21135 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
21136 continue;
21137 }
21138
21139 // OpenMP [2.14.3.6, Restrictions, p.1]
21140 // A list item that appears in a reduction clause of a worksharing
21141 // construct must be shared in the parallel regions to which any of the
21142 // worksharing regions arising from the worksharing construct bind.
21143
21144 if (S.getLangOpts().OpenMP <= 52 &&
21145 isOpenMPWorksharingDirective(DKind: CurrDir) &&
21146 !isOpenMPParallelDirective(DKind: CurrDir) &&
21147 !isOpenMPTeamsDirective(DKind: CurrDir)) {
21148 DVar = Stack->getImplicitDSA(D, FromParent: true);
21149 if (DVar.CKind != OMPC_shared) {
21150 S.Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
21151 << getOpenMPClauseNameForDiag(C: OMPC_reduction)
21152 << getOpenMPClauseNameForDiag(C: OMPC_shared);
21153 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
21154 continue;
21155 }
21156 } else if (isOpenMPWorksharingDirective(DKind: CurrDir) &&
21157 !isOpenMPParallelDirective(DKind: CurrDir) &&
21158 !isOpenMPTeamsDirective(DKind: CurrDir)) {
21159 // OpenMP 6.0 [ 7.6.10 ]
21160 // Support Reduction over private variables with reduction clause.
21161 // A list item in a reduction clause can now be private in the enclosing
21162 // context. For orphaned constructs it is assumed to be shared unless
21163 // the original(private) modifier appears in the clause.
21164 DVar = Stack->getImplicitDSA(D, FromParent: true);
21165 // Determine if the variable should be considered private
21166 IsPrivate = DVar.CKind != OMPC_shared;
21167 bool IsOrphaned = false;
21168 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
21169 IsOrphaned = ParentDir == OMPD_unknown;
21170 if ((IsOrphaned &&
21171 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
21172 IsPrivate = true;
21173 }
21174 } else {
21175 // Threadprivates cannot be shared between threads, so dignose if the base
21176 // is a threadprivate variable.
21177 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
21178 if (DVar.CKind == OMPC_threadprivate) {
21179 S.Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
21180 << getOpenMPClauseNameForDiag(C: DVar.CKind)
21181 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
21182 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
21183 continue;
21184 }
21185 }
21186
21187 // Try to find 'declare reduction' corresponding construct before using
21188 // builtin/overloaded operators.
21189 CXXCastPath BasePath;
21190 ExprResult DeclareReductionRef = buildDeclareReductionRef(
21191 SemaRef&: S, Loc: ELoc, Range: ERange, S: Stack->getCurScope(), ReductionIdScopeSpec,
21192 ReductionId, Ty: Type, BasePath, UnresolvedReduction: IR == ER ? nullptr : *IR);
21193 if (DeclareReductionRef.isInvalid())
21194 continue;
21195 if (S.CurContext->isDependentContext() &&
21196 (DeclareReductionRef.isUnset() ||
21197 isa<UnresolvedLookupExpr>(Val: DeclareReductionRef.get()))) {
21198 RD.push(Item: RefExpr, ReductionOp: DeclareReductionRef.get());
21199 // Handle non-dependent inscan reduction variables in dependent contexts.
21200 if (RD.RedModifier == OMPC_REDUCTION_inscan)
21201 Stack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_reduction, PrivateCopy: nullptr,
21202 Modifier: RD.RedModifier, AppliedToPointee: ASE || OASE);
21203 continue;
21204 }
21205 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
21206 // Not allowed reduction identifier is found.
21207 if (S.LangOpts.OpenMP > 52)
21208 S.Diag(Loc: ReductionId.getBeginLoc(),
21209 DiagID: diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
21210 << Type << ReductionIdRange;
21211 else
21212 S.Diag(Loc: ReductionId.getBeginLoc(),
21213 DiagID: diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
21214 << Type << ReductionIdRange;
21215 continue;
21216 }
21217
21218 // OpenMP [2.14.3.6, reduction clause, Restrictions]
21219 // The type of a list item that appears in a reduction clause must be valid
21220 // for the reduction-identifier. For a max or min reduction in C, the type
21221 // of the list item must be an allowed arithmetic data type: char, int,
21222 // float, double, or _Bool, possibly modified with long, short, signed, or
21223 // unsigned. For a max or min reduction in C++, the type of the list item
21224 // must be an allowed arithmetic data type: char, wchar_t, int, float,
21225 // double, or bool, possibly modified with long, short, signed, or unsigned.
21226 if (DeclareReductionRef.isUnset()) {
21227 if ((BOK == BO_GT || BOK == BO_LT) &&
21228 !(Type->isScalarType() ||
21229 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
21230 S.Diag(Loc: ELoc, DiagID: diag::err_omp_clause_not_arithmetic_type_arg)
21231 << getOpenMPClauseNameForDiag(C: ClauseKind)
21232 << S.getLangOpts().CPlusPlus;
21233 if (!ASE && !OASE) {
21234 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
21235 VarDecl::DeclarationOnly;
21236 S.Diag(Loc: D->getLocation(),
21237 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21238 << D;
21239 }
21240 continue;
21241 }
21242 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
21243 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
21244 S.Diag(Loc: ELoc, DiagID: diag::err_omp_clause_floating_type_arg)
21245 << getOpenMPClauseNameForDiag(C: ClauseKind);
21246 if (!ASE && !OASE) {
21247 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
21248 VarDecl::DeclarationOnly;
21249 S.Diag(Loc: D->getLocation(),
21250 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21251 << D;
21252 }
21253 continue;
21254 }
21255 }
21256
21257 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
21258 VarDecl *LHSVD = buildVarDecl(SemaRef&: S, Loc: ELoc, Type, Name: ".reduction.lhs",
21259 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
21260 VarDecl *RHSVD = buildVarDecl(SemaRef&: S, Loc: ELoc, Type, Name: D->getName(),
21261 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
21262 QualType PrivateTy = Type;
21263
21264 // Try if we can determine constant lengths for all array sections and avoid
21265 // the VLA.
21266 bool ConstantLengthOASE = false;
21267 if (OASE) {
21268 bool SingleElement;
21269 llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
21270 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
21271 Context, OASE, SingleElement, ArraySizes);
21272
21273 // If we don't have a single element, we must emit a constant array type.
21274 if (ConstantLengthOASE && !SingleElement) {
21275 for (llvm::APSInt &Size : ArraySizes)
21276 PrivateTy = Context.getConstantArrayType(EltTy: PrivateTy, ArySize: Size, SizeExpr: nullptr,
21277 ASM: ArraySizeModifier::Normal,
21278 /*IndexTypeQuals=*/0);
21279 }
21280 }
21281
21282 if ((OASE && !ConstantLengthOASE) ||
21283 (!OASE && !ASE &&
21284 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
21285 if (!Context.getTargetInfo().isVLASupported()) {
21286 if (isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective())) {
21287 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_vla_unsupported) << !!OASE;
21288 S.Diag(Loc: ELoc, DiagID: diag::note_vla_unsupported);
21289 continue;
21290 } else {
21291 S.targetDiag(Loc: ELoc, DiagID: diag::err_omp_reduction_vla_unsupported) << !!OASE;
21292 S.targetDiag(Loc: ELoc, DiagID: diag::note_vla_unsupported);
21293 }
21294 }
21295 // For arrays/array sections only:
21296 // Create pseudo array type for private copy. The size for this array will
21297 // be generated during codegen.
21298 // For array subscripts or single variables Private Ty is the same as Type
21299 // (type of the variable or single array element).
21300 PrivateTy = Context.getVariableArrayType(
21301 EltTy: Type,
21302 NumElts: new (Context)
21303 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
21304 ASM: ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
21305 } else if (!ASE && !OASE &&
21306 Context.getAsArrayType(T: D->getType().getNonReferenceType())) {
21307 PrivateTy = D->getType().getNonReferenceType();
21308 }
21309 // Private copy.
21310 VarDecl *PrivateVD =
21311 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: PrivateTy, Name: D->getName(),
21312 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
21313 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
21314 // Add initializer for private variable.
21315 Expr *Init = nullptr;
21316 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, D: LHSVD, Ty: Type, Loc: ELoc);
21317 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, D: RHSVD, Ty: Type, Loc: ELoc);
21318 if (DeclareReductionRef.isUsable()) {
21319 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
21320 auto *DRD = cast<OMPDeclareReductionDecl>(Val: DRDRef->getDecl());
21321 if (DRD->getInitializer()) {
21322 Init = DRDRef;
21323 RHSVD->setInit(DRDRef);
21324 RHSVD->setInitStyle(VarDecl::CallInit);
21325 }
21326 } else {
21327 switch (BOK) {
21328 case BO_Add:
21329 case BO_Xor:
21330 case BO_Or:
21331 case BO_LOr:
21332 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
21333 if (Type->isScalarType() || Type->isAnyComplexType())
21334 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/0).get();
21335 break;
21336 case BO_Mul:
21337 // '*' reduction op - initializer is '1'.
21338 // For C++ class types (e.g. std::complex) the OpenMP built-in
21339 // reduction identifiers are an extension: the standard only defines
21340 // identities for arithmetic (and, in Clang, _Complex) types. Without
21341 // an explicit initializer the private copy would be value-initialized,
21342 // which yields the *additive* identity (e.g. std::complex(0,0)) and is
21343 // wrong for multiplication. Initialize from the integer literal '1'
21344 // instead and let the converting constructor build the multiplicative
21345 // identity (e.g. std::complex(1) == (1,0)).
21346 if (Type->isScalarType() || Type->isAnyComplexType()) {
21347 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
21348 } else if (S.getLangOpts().CPlusPlus && Type->isRecordType()) {
21349 // Only use '1' when the type is actually copy-initializable from it.
21350 // Otherwise fall back to value-initialization (the previous behavior)
21351 // rather than rejecting the reduction, so a class that used to
21352 // compile keeps compiling. Such a class keeps its (possibly
21353 // incorrect) value-initialized identity, matching the pre-existing
21354 // behavior; BO_Add likewise relies on value-initialization for class
21355 // types.
21356 Expr *One = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
21357 InitializedEntity Entity =
21358 InitializedEntity::InitializeTemporary(Type);
21359 InitializationKind Kind = InitializationKind::CreateCopy(InitLoc: ELoc, EqualLoc: ELoc);
21360 InitializationSequence Seq(S, Entity, Kind, One);
21361 if (Seq)
21362 Init = One;
21363 }
21364 break;
21365 case BO_LAnd:
21366 if (Type->isScalarType() || Type->isAnyComplexType()) {
21367 // '&&' reduction ops - initializer is '1'.
21368 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
21369 }
21370 break;
21371 case BO_And: {
21372 // '&' reduction op - initializer is '~0'.
21373 QualType OrigType = Type;
21374 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
21375 Type = ComplexTy->getElementType();
21376 if (Type->isRealFloatingType()) {
21377 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
21378 Semantics: Context.getFloatTypeSemantics(T: Type));
21379 Init = FloatingLiteral::Create(C: Context, V: InitValue, /*isexact=*/true,
21380 Type, L: ELoc);
21381 } else if (Type->isScalarType()) {
21382 uint64_t Size = Context.getTypeSize(T: Type);
21383 QualType IntTy = Context.getIntTypeForBitwidth(DestWidth: Size, /*Signed=*/0);
21384 llvm::APInt InitValue = llvm::APInt::getAllOnes(numBits: Size);
21385 Init = IntegerLiteral::Create(C: Context, V: InitValue, type: IntTy, l: ELoc);
21386 }
21387 if (Init && OrigType->isAnyComplexType()) {
21388 // Init = 0xFFFF + 0xFFFFi;
21389 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
21390 Init = S.CreateBuiltinBinOp(OpLoc: ELoc, Opc: BO_Add, LHSExpr: Init, RHSExpr: Im).get();
21391 }
21392 Type = OrigType;
21393 break;
21394 }
21395 case BO_LT:
21396 case BO_GT: {
21397 // 'min' reduction op - initializer is 'Largest representable number in
21398 // the reduction list item type'.
21399 // 'max' reduction op - initializer is 'Least representable number in
21400 // the reduction list item type'.
21401 if (Type->isIntegerType() || Type->isPointerType()) {
21402 bool IsSigned = Type->hasSignedIntegerRepresentation();
21403 uint64_t Size = Context.getTypeSize(T: Type);
21404 QualType IntTy =
21405 Context.getIntTypeForBitwidth(DestWidth: Size, /*Signed=*/IsSigned);
21406 llvm::APInt InitValue =
21407 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(numBits: Size)
21408 : llvm::APInt::getMinValue(numBits: Size)
21409 : IsSigned ? llvm::APInt::getSignedMaxValue(numBits: Size)
21410 : llvm::APInt::getMaxValue(numBits: Size);
21411 Init = IntegerLiteral::Create(C: Context, V: InitValue, type: IntTy, l: ELoc);
21412 if (Type->isPointerType()) {
21413 // Cast to pointer type.
21414 ExprResult CastExpr = S.BuildCStyleCastExpr(
21415 LParenLoc: ELoc, Ty: Context.getTrivialTypeSourceInfo(T: Type, Loc: ELoc), RParenLoc: ELoc, Op: Init);
21416 if (CastExpr.isInvalid())
21417 continue;
21418 Init = CastExpr.get();
21419 }
21420 } else if (Type->isRealFloatingType()) {
21421 llvm::APFloat InitValue = llvm::APFloat::getLargest(
21422 Sem: Context.getFloatTypeSemantics(T: Type), Negative: BOK != BO_LT);
21423 Init = FloatingLiteral::Create(C: Context, V: InitValue, /*isexact=*/true,
21424 Type, L: ELoc);
21425 }
21426 break;
21427 }
21428 case BO_PtrMemD:
21429 case BO_PtrMemI:
21430 case BO_MulAssign:
21431 case BO_Div:
21432 case BO_Rem:
21433 case BO_Sub:
21434 case BO_Shl:
21435 case BO_Shr:
21436 case BO_LE:
21437 case BO_GE:
21438 case BO_EQ:
21439 case BO_NE:
21440 case BO_Cmp:
21441 case BO_AndAssign:
21442 case BO_XorAssign:
21443 case BO_OrAssign:
21444 case BO_Assign:
21445 case BO_AddAssign:
21446 case BO_SubAssign:
21447 case BO_DivAssign:
21448 case BO_RemAssign:
21449 case BO_ShlAssign:
21450 case BO_ShrAssign:
21451 case BO_Comma:
21452 llvm_unreachable("Unexpected reduction operation");
21453 }
21454 }
21455 if (Init && DeclareReductionRef.isUnset()) {
21456 S.AddInitializerToDecl(dcl: RHSVD, init: Init, /*DirectInit=*/false);
21457 // Store initializer for single element in private copy. Will be used
21458 // during codegen.
21459 PrivateVD->setInit(RHSVD->getInit());
21460 PrivateVD->setInitStyle(RHSVD->getInitStyle());
21461 } else if (!Init) {
21462 S.ActOnUninitializedDecl(dcl: RHSVD);
21463 // Store initializer for single element in private copy. Will be used
21464 // during codegen.
21465 PrivateVD->setInit(RHSVD->getInit());
21466 PrivateVD->setInitStyle(RHSVD->getInitStyle());
21467 }
21468 if (RHSVD->isInvalidDecl())
21469 continue;
21470 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
21471 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_id_not_compatible)
21472 << Type << ReductionIdRange;
21473 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
21474 VarDecl::DeclarationOnly;
21475 S.Diag(Loc: D->getLocation(),
21476 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21477 << D;
21478 continue;
21479 }
21480 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, D: PrivateVD, Ty: PrivateTy, Loc: ELoc);
21481 ExprResult ReductionOp;
21482 if (DeclareReductionRef.isUsable()) {
21483 QualType RedTy = DeclareReductionRef.get()->getType();
21484 QualType PtrRedTy = Context.getPointerType(T: RedTy);
21485 ExprResult LHS = S.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: LHSDRE);
21486 ExprResult RHS = S.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: RHSDRE);
21487 if (!BasePath.empty()) {
21488 LHS = S.DefaultLvalueConversion(E: LHS.get());
21489 RHS = S.DefaultLvalueConversion(E: RHS.get());
21490 LHS = ImplicitCastExpr::Create(
21491 Context, T: PtrRedTy, Kind: CK_UncheckedDerivedToBase, Operand: LHS.get(), BasePath: &BasePath,
21492 Cat: LHS.get()->getValueKind(), FPO: FPOptionsOverride());
21493 RHS = ImplicitCastExpr::Create(
21494 Context, T: PtrRedTy, Kind: CK_UncheckedDerivedToBase, Operand: RHS.get(), BasePath: &BasePath,
21495 Cat: RHS.get()->getValueKind(), FPO: FPOptionsOverride());
21496 }
21497 FunctionProtoType::ExtProtoInfo EPI;
21498 QualType Params[] = {PtrRedTy, PtrRedTy};
21499 QualType FnTy = Context.getFunctionType(ResultTy: Context.VoidTy, Args: Params, EPI);
21500 auto *OVE = new (Context) OpaqueValueExpr(
21501 ELoc, Context.getPointerType(T: FnTy), VK_PRValue, OK_Ordinary,
21502 S.DefaultLvalueConversion(E: DeclareReductionRef.get()).get());
21503 Expr *Args[] = {LHS.get(), RHS.get()};
21504 ReductionOp =
21505 CallExpr::Create(Ctx: Context, Fn: OVE, Args, Ty: Context.VoidTy, VK: VK_PRValue, RParenLoc: ELoc,
21506 FPFeatures: S.CurFPFeatureOverrides());
21507 } else {
21508 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
21509 if (Type->isRecordType() && CombBOK != BOK) {
21510 Sema::TentativeAnalysisScope Trap(S);
21511 ReductionOp =
21512 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
21513 Opc: CombBOK, LHSExpr: LHSDRE, RHSExpr: RHSDRE);
21514 }
21515 if (!ReductionOp.isUsable()) {
21516 ReductionOp =
21517 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(), Opc: BOK,
21518 LHSExpr: LHSDRE, RHSExpr: RHSDRE);
21519 if (ReductionOp.isUsable()) {
21520 if (BOK != BO_LT && BOK != BO_GT) {
21521 ReductionOp =
21522 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
21523 Opc: BO_Assign, LHSExpr: LHSDRE, RHSExpr: ReductionOp.get());
21524 } else {
21525 auto *ConditionalOp = new (Context)
21526 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
21527 RHSDRE, Type, VK_LValue, OK_Ordinary);
21528 ReductionOp =
21529 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
21530 Opc: BO_Assign, LHSExpr: LHSDRE, RHSExpr: ConditionalOp);
21531 }
21532 }
21533 }
21534 if (ReductionOp.isUsable())
21535 ReductionOp = S.ActOnFinishFullExpr(Expr: ReductionOp.get(),
21536 /*DiscardedValue=*/false);
21537 if (!ReductionOp.isUsable())
21538 continue;
21539 }
21540
21541 // Add copy operations for inscan reductions.
21542 // LHS = RHS;
21543 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
21544 if (ClauseKind == OMPC_reduction &&
21545 RD.RedModifier == OMPC_REDUCTION_inscan) {
21546 ExprResult RHS = S.DefaultLvalueConversion(E: RHSDRE);
21547 CopyOpRes = S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: LHSDRE,
21548 RHSExpr: RHS.get());
21549 if (!CopyOpRes.isUsable())
21550 continue;
21551 CopyOpRes =
21552 S.ActOnFinishFullExpr(Expr: CopyOpRes.get(), /*DiscardedValue=*/true);
21553 if (!CopyOpRes.isUsable())
21554 continue;
21555 // For simd directive and simd-based directives in simd mode no need to
21556 // construct temp array, need just a single temp element.
21557 if (Stack->getCurrentDirective() == OMPD_simd ||
21558 (S.getLangOpts().OpenMPSimd &&
21559 isOpenMPSimdDirective(DKind: Stack->getCurrentDirective()))) {
21560 VarDecl *TempArrayVD =
21561 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: PrivateTy, Name: D->getName(),
21562 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
21563 // Add a constructor to the temp decl.
21564 S.ActOnUninitializedDecl(dcl: TempArrayVD);
21565 TempArrayRes = buildDeclRefExpr(S, D: TempArrayVD, Ty: PrivateTy, Loc: ELoc);
21566 } else {
21567 // Build temp array for prefix sum.
21568 auto *Dim = new (S.Context)
21569 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
21570 QualType ArrayTy = S.Context.getVariableArrayType(
21571 EltTy: PrivateTy, NumElts: Dim, ASM: ArraySizeModifier::Normal,
21572 /*IndexTypeQuals=*/0);
21573 VarDecl *TempArrayVD =
21574 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: ArrayTy, Name: D->getName(),
21575 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
21576 // Add a constructor to the temp decl.
21577 S.ActOnUninitializedDecl(dcl: TempArrayVD);
21578 TempArrayRes = buildDeclRefExpr(S, D: TempArrayVD, Ty: ArrayTy, Loc: ELoc);
21579 TempArrayElem =
21580 S.DefaultFunctionArrayLvalueConversion(E: TempArrayRes.get());
21581 auto *Idx = new (S.Context)
21582 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
21583 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(Base: TempArrayElem.get(),
21584 LLoc: ELoc, Idx, RLoc: ELoc);
21585 }
21586 }
21587
21588 // OpenMP [2.15.4.6, Restrictions, p.2]
21589 // A list item that appears in an in_reduction clause of a task construct
21590 // must appear in a task_reduction clause of a construct associated with a
21591 // taskgroup region that includes the participating task in its taskgroup
21592 // set. The construct associated with the innermost region that meets this
21593 // condition must specify the same reduction-identifier as the in_reduction
21594 // clause.
21595 if (ClauseKind == OMPC_in_reduction) {
21596 SourceRange ParentSR;
21597 BinaryOperatorKind ParentBOK;
21598 const Expr *ParentReductionOp = nullptr;
21599 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
21600 DSAStackTy::DSAVarData ParentBOKDSA =
21601 Stack->getTopMostTaskgroupReductionData(D, SR&: ParentSR, BOK&: ParentBOK,
21602 TaskgroupDescriptor&: ParentBOKTD);
21603 DSAStackTy::DSAVarData ParentReductionOpDSA =
21604 Stack->getTopMostTaskgroupReductionData(
21605 D, SR&: ParentSR, ReductionRef&: ParentReductionOp, TaskgroupDescriptor&: ParentReductionOpTD);
21606 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
21607 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
21608 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
21609 (DeclareReductionRef.isUsable() && IsParentBOK) ||
21610 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
21611 bool EmitError = true;
21612 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
21613 llvm::FoldingSetNodeID RedId, ParentRedId;
21614 ParentReductionOp->Profile(ID&: ParentRedId, Context, /*Canonical=*/true);
21615 DeclareReductionRef.get()->Profile(ID&: RedId, Context,
21616 /*Canonical=*/true);
21617 EmitError = RedId != ParentRedId;
21618 }
21619 if (EmitError) {
21620 S.Diag(Loc: ReductionId.getBeginLoc(),
21621 DiagID: diag::err_omp_reduction_identifier_mismatch)
21622 << ReductionIdRange << RefExpr->getSourceRange();
21623 S.Diag(Loc: ParentSR.getBegin(),
21624 DiagID: diag::note_omp_previous_reduction_identifier)
21625 << ParentSR
21626 << (IsParentBOK ? ParentBOKDSA.RefExpr
21627 : ParentReductionOpDSA.RefExpr)
21628 ->getSourceRange();
21629 continue;
21630 }
21631 }
21632 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
21633 }
21634
21635 DeclRefExpr *Ref = nullptr;
21636 Expr *VarsExpr = RefExpr->IgnoreParens();
21637 if (!VD && !S.CurContext->isDependentContext()) {
21638 if (ASE || OASE) {
21639 TransformExprToCaptures RebuildToCapture(S, D);
21640 VarsExpr =
21641 RebuildToCapture.TransformExpr(E: RefExpr->IgnoreParens()).get();
21642 Ref = RebuildToCapture.getCapturedExpr();
21643 } else {
21644 VarsExpr = Ref = buildCapture(S, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
21645 }
21646 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
21647 RD.ExprCaptures.emplace_back(Args: Ref->getDecl());
21648 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
21649 ExprResult RefRes = S.DefaultLvalueConversion(E: Ref);
21650 if (!RefRes.isUsable())
21651 continue;
21652 ExprResult PostUpdateRes =
21653 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: SimpleRefExpr,
21654 RHSExpr: RefRes.get());
21655 if (!PostUpdateRes.isUsable())
21656 continue;
21657 if (isOpenMPTaskingDirective(Kind: Stack->getCurrentDirective()) ||
21658 Stack->getCurrentDirective() == OMPD_taskgroup) {
21659 S.Diag(Loc: RefExpr->getExprLoc(),
21660 DiagID: diag::err_omp_reduction_non_addressable_expression)
21661 << RefExpr->getSourceRange();
21662 continue;
21663 }
21664 RD.ExprPostUpdates.emplace_back(
21665 Args: S.IgnoredValueConversions(E: PostUpdateRes.get()).get());
21666 }
21667 }
21668 }
21669 // All reduction items are still marked as reduction (to do not increase
21670 // code base size).
21671 unsigned Modifier = RD.RedModifier;
21672 // Consider task_reductions as reductions with task modifier. Required for
21673 // correct analysis of in_reduction clauses.
21674 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
21675 Modifier = OMPC_REDUCTION_task;
21676 Stack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_reduction, PrivateCopy: Ref, Modifier,
21677 AppliedToPointee: ASE || OASE);
21678 if (Modifier == OMPC_REDUCTION_task &&
21679 (CurrDir == OMPD_taskgroup ||
21680 ((isOpenMPParallelDirective(DKind: CurrDir) ||
21681 isOpenMPWorksharingDirective(DKind: CurrDir)) &&
21682 !isOpenMPSimdDirective(DKind: CurrDir)))) {
21683 if (DeclareReductionRef.isUsable())
21684 Stack->addTaskgroupReductionData(D, SR: ReductionIdRange,
21685 ReductionRef: DeclareReductionRef.get());
21686 else
21687 Stack->addTaskgroupReductionData(D, SR: ReductionIdRange, BOK);
21688 }
21689 RD.push(Item: VarsExpr, Private: PrivateDRE, LHS: LHSDRE, RHS: RHSDRE, ReductionOp: ReductionOp.get(),
21690 TaskgroupDescriptor, CopyOp: CopyOpRes.get(), CopyArrayTemp: TempArrayRes.get(),
21691 CopyArrayElem: TempArrayElem.get(), IsPrivate);
21692 }
21693 return RD.Vars.empty();
21694}
21695
21696OMPClause *SemaOpenMP::ActOnOpenMPReductionClause(
21697 ArrayRef<Expr *> VarList,
21698 OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers,
21699 SourceLocation StartLoc, SourceLocation LParenLoc,
21700 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
21701 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
21702 ArrayRef<Expr *> UnresolvedReductions) {
21703 OpenMPReductionClauseModifier Modifier =
21704 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
21705 OpenMPOriginalSharingModifier OriginalSharingModifier =
21706 static_cast<OpenMPOriginalSharingModifier>(
21707 Modifiers.OriginalSharingModifier);
21708 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
21709 Diag(Loc: LParenLoc, DiagID: diag::err_omp_unexpected_clause_value)
21710 << getListOfPossibleValues(K: OMPC_reduction, /*First=*/0,
21711 /*Last=*/OMPC_REDUCTION_unknown)
21712 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
21713 return nullptr;
21714 }
21715 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
21716 // A reduction clause with the inscan reduction-modifier may only appear on a
21717 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
21718 // construct, a parallel worksharing-loop construct or a parallel
21719 // worksharing-loop SIMD construct.
21720 if (Modifier == OMPC_REDUCTION_inscan &&
21721 (DSAStack->getCurrentDirective() != OMPD_for &&
21722 DSAStack->getCurrentDirective() != OMPD_for_simd &&
21723 DSAStack->getCurrentDirective() != OMPD_simd &&
21724 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
21725 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
21726 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_wrong_inscan_reduction);
21727 return nullptr;
21728 }
21729 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
21730 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_reduction, VarList,
21731 StartLoc, LParenLoc, ColonLoc, EndLoc,
21732 ReductionIdScopeSpec, ReductionId,
21733 UnresolvedReductions, RD))
21734 return nullptr;
21735
21736 return OMPReductionClause::Create(
21737 C: getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
21738 Modifier, VL: RD.Vars,
21739 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
21740 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps, CopyOps: RD.InscanCopyOps,
21741 CopyArrayTemps: RD.InscanCopyArrayTemps, CopyArrayElems: RD.InscanCopyArrayElems,
21742 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
21743 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates), IsPrivateVarReduction: RD.IsPrivateVarReduction,
21744 OriginalSharingModifier);
21745}
21746
21747OMPClause *SemaOpenMP::ActOnOpenMPTaskReductionClause(
21748 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21749 SourceLocation ColonLoc, SourceLocation EndLoc,
21750 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
21751 ArrayRef<Expr *> UnresolvedReductions) {
21752 ReductionData RD(VarList.size());
21753 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_task_reduction,
21754 VarList, StartLoc, LParenLoc, ColonLoc,
21755 EndLoc, ReductionIdScopeSpec, ReductionId,
21756 UnresolvedReductions, RD))
21757 return nullptr;
21758
21759 return OMPTaskReductionClause::Create(
21760 C: getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, VL: RD.Vars,
21761 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
21762 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps,
21763 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
21764 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates));
21765}
21766
21767OMPClause *SemaOpenMP::ActOnOpenMPInReductionClause(
21768 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21769 SourceLocation ColonLoc, SourceLocation EndLoc,
21770 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
21771 ArrayRef<Expr *> UnresolvedReductions) {
21772 ReductionData RD(VarList.size());
21773 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_in_reduction, VarList,
21774 StartLoc, LParenLoc, ColonLoc, EndLoc,
21775 ReductionIdScopeSpec, ReductionId,
21776 UnresolvedReductions, RD))
21777 return nullptr;
21778
21779 return OMPInReductionClause::Create(
21780 C: getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, VL: RD.Vars,
21781 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
21782 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps, TaskgroupDescriptors: RD.TaskgroupDescriptors,
21783 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
21784 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates));
21785}
21786
21787bool SemaOpenMP::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
21788 SourceLocation LinLoc) {
21789 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
21790 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
21791 Diag(Loc: LinLoc, DiagID: diag::err_omp_wrong_linear_modifier)
21792 << getLangOpts().CPlusPlus;
21793 return true;
21794 }
21795 return false;
21796}
21797
21798bool SemaOpenMP::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
21799 OpenMPLinearClauseKind LinKind,
21800 QualType Type, bool IsDeclareSimd) {
21801 const auto *VD = dyn_cast_or_null<VarDecl>(Val: D);
21802 // A variable must not have an incomplete type or a reference type.
21803 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
21804 DiagID: diag::err_omp_linear_incomplete_type))
21805 return true;
21806 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
21807 !Type->isReferenceType()) {
21808 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_linear_modifier_non_reference)
21809 << Type << getOpenMPSimpleClauseTypeName(Kind: OMPC_linear, Type: LinKind);
21810 return true;
21811 }
21812 Type = Type.getNonReferenceType();
21813
21814 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
21815 // A variable that is privatized must not have a const-qualified type
21816 // unless it is of class type with a mutable member. This restriction does
21817 // not apply to the firstprivate clause, nor to the linear clause on
21818 // declarative directives (like declare simd).
21819 if (!IsDeclareSimd &&
21820 rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_linear, ELoc))
21821 return true;
21822
21823 // A list item must be of integral or pointer type.
21824 Type = Type.getUnqualifiedType().getCanonicalType();
21825 const auto *Ty = Type.getTypePtrOrNull();
21826 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
21827 !Ty->isIntegralType(Ctx: getASTContext()) && !Ty->isPointerType())) {
21828 Diag(Loc: ELoc, DiagID: diag::err_omp_linear_expected_int_or_ptr) << Type;
21829 if (D) {
21830 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21831 VarDecl::DeclarationOnly;
21832 Diag(Loc: D->getLocation(),
21833 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21834 << D;
21835 }
21836 return true;
21837 }
21838 return false;
21839}
21840
21841OMPClause *SemaOpenMP::ActOnOpenMPLinearClause(
21842 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
21843 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
21844 SourceLocation LinLoc, SourceLocation ColonLoc,
21845 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
21846 SmallVector<Expr *, 8> Vars;
21847 SmallVector<Expr *, 8> Privates;
21848 SmallVector<Expr *, 8> Inits;
21849 SmallVector<Decl *, 4> ExprCaptures;
21850 SmallVector<Expr *, 4> ExprPostUpdates;
21851 // OpenMP 5.2 [Section 5.4.6, linear clause]
21852 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
21853 // 'ref'
21854 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
21855 getLangOpts().OpenMP >= 52)
21856 Diag(Loc: Step->getBeginLoc(), DiagID: diag::err_omp_step_simple_modifier_exclusive);
21857 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
21858 LinKind = OMPC_LINEAR_val;
21859 for (Expr *RefExpr : VarList) {
21860 assert(RefExpr && "NULL expr in OpenMP linear clause.");
21861 SourceLocation ELoc;
21862 SourceRange ERange;
21863 Expr *SimpleRefExpr = RefExpr;
21864 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
21865 if (Res.second) {
21866 // It will be analyzed later.
21867 Vars.push_back(Elt: RefExpr);
21868 Privates.push_back(Elt: nullptr);
21869 Inits.push_back(Elt: nullptr);
21870 }
21871 ValueDecl *D = Res.first;
21872 if (!D)
21873 continue;
21874
21875 QualType Type = D->getType();
21876 auto *VD = dyn_cast<VarDecl>(Val: D);
21877
21878 // OpenMP [2.14.3.7, linear clause]
21879 // A list-item cannot appear in more than one linear clause.
21880 // A list-item that appears in a linear clause cannot appear in any
21881 // other data-sharing attribute clause.
21882 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
21883 if (DVar.RefExpr) {
21884 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
21885 << getOpenMPClauseNameForDiag(C: DVar.CKind)
21886 << getOpenMPClauseNameForDiag(C: OMPC_linear);
21887 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
21888 continue;
21889 }
21890
21891 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
21892 continue;
21893 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
21894
21895 // Build private copy of original var.
21896 VarDecl *Private =
21897 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
21898 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
21899 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
21900 DeclRefExpr *PrivateRef = buildDeclRefExpr(S&: SemaRef, D: Private, Ty: Type, Loc: ELoc);
21901 // Build var to save initial value.
21902 VarDecl *Init = buildVarDecl(SemaRef, Loc: ELoc, Type, Name: ".linear.start");
21903 Expr *InitExpr;
21904 DeclRefExpr *Ref = nullptr;
21905 if (!VD && !SemaRef.CurContext->isDependentContext()) {
21906 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
21907 if (!isOpenMPCapturedDecl(D)) {
21908 ExprCaptures.push_back(Elt: Ref->getDecl());
21909 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
21910 ExprResult RefRes = SemaRef.DefaultLvalueConversion(E: Ref);
21911 if (!RefRes.isUsable())
21912 continue;
21913 ExprResult PostUpdateRes =
21914 SemaRef.BuildBinOp(DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign,
21915 LHSExpr: SimpleRefExpr, RHSExpr: RefRes.get());
21916 if (!PostUpdateRes.isUsable())
21917 continue;
21918 ExprPostUpdates.push_back(
21919 Elt: SemaRef.IgnoredValueConversions(E: PostUpdateRes.get()).get());
21920 }
21921 }
21922 }
21923 if (LinKind == OMPC_LINEAR_uval)
21924 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
21925 else
21926 InitExpr = VD ? SimpleRefExpr : Ref;
21927 SemaRef.AddInitializerToDecl(
21928 dcl: Init, init: SemaRef.DefaultLvalueConversion(E: InitExpr).get(),
21929 /*DirectInit=*/false);
21930 DeclRefExpr *InitRef = buildDeclRefExpr(S&: SemaRef, D: Init, Ty: Type, Loc: ELoc);
21931
21932 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_linear, PrivateCopy: Ref);
21933 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
21934 ? RefExpr->IgnoreParens()
21935 : Ref);
21936 Privates.push_back(Elt: PrivateRef);
21937 Inits.push_back(Elt: InitRef);
21938 }
21939
21940 if (Vars.empty())
21941 return nullptr;
21942
21943 Expr *StepExpr = Step;
21944 Expr *CalcStepExpr = nullptr;
21945 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
21946 !Step->isInstantiationDependent() &&
21947 !Step->containsUnexpandedParameterPack()) {
21948 SourceLocation StepLoc = Step->getBeginLoc();
21949 ExprResult Val = PerformOpenMPImplicitIntegerConversion(Loc: StepLoc, Op: Step);
21950 if (Val.isInvalid())
21951 return nullptr;
21952 StepExpr = Val.get();
21953
21954 // Build var to save the step value.
21955 VarDecl *SaveVar =
21956 buildVarDecl(SemaRef, Loc: StepLoc, Type: StepExpr->getType(), Name: ".linear.step");
21957 ExprResult SaveRef =
21958 buildDeclRefExpr(S&: SemaRef, D: SaveVar, Ty: StepExpr->getType(), Loc: StepLoc);
21959 ExprResult CalcStep = SemaRef.BuildBinOp(
21960 S: SemaRef.getCurScope(), OpLoc: StepLoc, Opc: BO_Assign, LHSExpr: SaveRef.get(), RHSExpr: StepExpr);
21961 CalcStep =
21962 SemaRef.ActOnFinishFullExpr(Expr: CalcStep.get(), /*DiscardedValue=*/false);
21963
21964 // Warn about zero linear step (it would be probably better specified as
21965 // making corresponding variables 'const').
21966 if (std::optional<llvm::APSInt> Result =
21967 StepExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
21968 if (!Result->isNegative() && !Result->isStrictlyPositive())
21969 Diag(Loc: StepLoc, DiagID: diag::warn_omp_linear_step_zero)
21970 << Vars[0] << (Vars.size() > 1);
21971 } else if (CalcStep.isUsable()) {
21972 // Calculate the step beforehand instead of doing this on each iteration.
21973 // (This is not used if the number of iterations may be kfold-ed).
21974 CalcStepExpr = CalcStep.get();
21975 }
21976 }
21977
21978 return OMPLinearClause::Create(C: getASTContext(), StartLoc, LParenLoc, Modifier: LinKind,
21979 ModifierLoc: LinLoc, ColonLoc, StepModifierLoc, EndLoc,
21980 VL: Vars, PL: Privates, IL: Inits, Step: StepExpr, CalcStep: CalcStepExpr,
21981 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures),
21982 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: ExprPostUpdates));
21983}
21984
21985static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
21986 Expr *NumIterations, Sema &SemaRef,
21987 Scope *S, DSAStackTy *Stack) {
21988 // Walk the vars and build update/final expressions for the CodeGen.
21989 SmallVector<Expr *, 8> Updates;
21990 SmallVector<Expr *, 8> Finals;
21991 SmallVector<Expr *, 8> UsedExprs;
21992 Expr *Step = Clause.getStep();
21993 Expr *CalcStep = Clause.getCalcStep();
21994 // OpenMP [2.14.3.7, linear clause]
21995 // If linear-step is not specified it is assumed to be 1.
21996 if (!Step)
21997 Step = SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get();
21998 else if (CalcStep)
21999 Step = cast<BinaryOperator>(Val: CalcStep)->getLHS();
22000 bool HasErrors = false;
22001 auto CurInit = Clause.inits().begin();
22002 auto CurPrivate = Clause.privates().begin();
22003 OpenMPLinearClauseKind LinKind = Clause.getModifier();
22004 for (Expr *RefExpr : Clause.varlist()) {
22005 SourceLocation ELoc;
22006 SourceRange ERange;
22007 Expr *SimpleRefExpr = RefExpr;
22008 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
22009 ValueDecl *D = Res.first;
22010 if (Res.second || !D) {
22011 Updates.push_back(Elt: nullptr);
22012 Finals.push_back(Elt: nullptr);
22013 HasErrors = true;
22014 continue;
22015 }
22016 auto &&Info = Stack->isLoopControlVariable(D);
22017 // OpenMP [2.15.11, distribute simd Construct]
22018 // A list item may not appear in a linear clause, unless it is the loop
22019 // iteration variable.
22020 if (isOpenMPDistributeDirective(DKind: Stack->getCurrentDirective()) &&
22021 isOpenMPSimdDirective(DKind: Stack->getCurrentDirective()) && !Info.first) {
22022 SemaRef.Diag(Loc: ELoc,
22023 DiagID: diag::err_omp_linear_distribute_var_non_loop_iteration);
22024 Updates.push_back(Elt: nullptr);
22025 Finals.push_back(Elt: nullptr);
22026 HasErrors = true;
22027 continue;
22028 }
22029 Expr *InitExpr = *CurInit;
22030
22031 // Build privatized reference to the current linear var.
22032 auto *DE = cast<DeclRefExpr>(Val: SimpleRefExpr);
22033 Expr *CapturedRef;
22034 if (LinKind == OMPC_LINEAR_uval)
22035 CapturedRef = cast<VarDecl>(Val: DE->getDecl())->getInit();
22036 else
22037 CapturedRef =
22038 buildDeclRefExpr(S&: SemaRef, D: cast<VarDecl>(Val: DE->getDecl()),
22039 Ty: DE->getType().getUnqualifiedType(), Loc: DE->getExprLoc(),
22040 /*RefersToCapture=*/true);
22041
22042 // Build update: Var = InitExpr + IV * Step
22043 ExprResult Update;
22044 if (!Info.first)
22045 Update = buildCounterUpdate(
22046 SemaRef, S, Loc: RefExpr->getExprLoc(), VarRef: *CurPrivate, Start: InitExpr, Iter: IV, Step,
22047 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
22048 else
22049 Update = *CurPrivate;
22050 Update = SemaRef.ActOnFinishFullExpr(Expr: Update.get(), CC: DE->getBeginLoc(),
22051 /*DiscardedValue=*/false);
22052
22053 // Build final: Var = PrivCopy;
22054 ExprResult Final;
22055 if (!Info.first)
22056 Final = SemaRef.BuildBinOp(
22057 S, OpLoc: RefExpr->getExprLoc(), Opc: BO_Assign, LHSExpr: CapturedRef,
22058 RHSExpr: SemaRef.DefaultLvalueConversion(E: *CurPrivate).get());
22059 else
22060 Final = *CurPrivate;
22061 Final = SemaRef.ActOnFinishFullExpr(Expr: Final.get(), CC: DE->getBeginLoc(),
22062 /*DiscardedValue=*/false);
22063
22064 if (!Update.isUsable() || !Final.isUsable()) {
22065 Updates.push_back(Elt: nullptr);
22066 Finals.push_back(Elt: nullptr);
22067 UsedExprs.push_back(Elt: nullptr);
22068 HasErrors = true;
22069 } else {
22070 Updates.push_back(Elt: Update.get());
22071 Finals.push_back(Elt: Final.get());
22072 if (!Info.first)
22073 UsedExprs.push_back(Elt: SimpleRefExpr);
22074 }
22075 ++CurInit;
22076 ++CurPrivate;
22077 }
22078 if (Expr *S = Clause.getStep())
22079 UsedExprs.push_back(Elt: S);
22080 // Fill the remaining part with the nullptr.
22081 UsedExprs.append(NumInputs: Clause.varlist_size() + 1 - UsedExprs.size(), Elt: nullptr);
22082 Clause.setUpdates(Updates);
22083 Clause.setFinals(Finals);
22084 Clause.setUsedExprs(UsedExprs);
22085 return HasErrors;
22086}
22087
22088OMPClause *SemaOpenMP::ActOnOpenMPAlignedClause(
22089 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
22090 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
22091 SmallVector<Expr *, 8> Vars;
22092 for (Expr *RefExpr : VarList) {
22093 assert(RefExpr && "NULL expr in OpenMP aligned clause.");
22094 SourceLocation ELoc;
22095 SourceRange ERange;
22096 Expr *SimpleRefExpr = RefExpr;
22097 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
22098 if (Res.second) {
22099 // It will be analyzed later.
22100 Vars.push_back(Elt: RefExpr);
22101 }
22102 ValueDecl *D = Res.first;
22103 if (!D)
22104 continue;
22105
22106 QualType QType = D->getType();
22107 auto *VD = dyn_cast<VarDecl>(Val: D);
22108
22109 // OpenMP [2.8.1, simd construct, Restrictions]
22110 // The type of list items appearing in the aligned clause must be
22111 // array, pointer, reference to array, or reference to pointer.
22112 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
22113 const Type *Ty = QType.getTypePtrOrNull();
22114 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
22115 Diag(Loc: ELoc, DiagID: diag::err_omp_aligned_expected_array_or_ptr)
22116 << QType << getLangOpts().CPlusPlus << ERange;
22117 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
22118 VarDecl::DeclarationOnly;
22119 Diag(Loc: D->getLocation(),
22120 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
22121 << D;
22122 continue;
22123 }
22124
22125 // OpenMP [2.8.1, simd construct, Restrictions]
22126 // A list-item cannot appear in more than one aligned clause.
22127 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, NewDE: SimpleRefExpr)) {
22128 Diag(Loc: ELoc, DiagID: diag::err_omp_used_in_clause_twice)
22129 << 0 << getOpenMPClauseNameForDiag(C: OMPC_aligned) << ERange;
22130 Diag(Loc: PrevRef->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
22131 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
22132 continue;
22133 }
22134
22135 DeclRefExpr *Ref = nullptr;
22136 if (!VD && isOpenMPCapturedDecl(D))
22137 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
22138 Vars.push_back(Elt: SemaRef
22139 .DefaultFunctionArrayConversion(
22140 E: (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
22141 .get());
22142 }
22143
22144 // OpenMP [2.8.1, simd construct, Description]
22145 // The parameter of the aligned clause, alignment, must be a constant
22146 // positive integer expression.
22147 // If no optional parameter is specified, implementation-defined default
22148 // alignments for SIMD instructions on the target platforms are assumed.
22149 if (Alignment != nullptr) {
22150 ExprResult AlignResult =
22151 VerifyPositiveIntegerConstantInClause(E: Alignment, CKind: OMPC_aligned);
22152 if (AlignResult.isInvalid())
22153 return nullptr;
22154 Alignment = AlignResult.get();
22155 }
22156 if (Vars.empty())
22157 return nullptr;
22158
22159 return OMPAlignedClause::Create(C: getASTContext(), StartLoc, LParenLoc,
22160 ColonLoc, EndLoc, VL: Vars, A: Alignment);
22161}
22162
22163OMPClause *SemaOpenMP::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
22164 SourceLocation StartLoc,
22165 SourceLocation LParenLoc,
22166 SourceLocation EndLoc) {
22167 SmallVector<Expr *, 8> Vars;
22168 SmallVector<Expr *, 8> SrcExprs;
22169 SmallVector<Expr *, 8> DstExprs;
22170 SmallVector<Expr *, 8> AssignmentOps;
22171 for (Expr *RefExpr : VarList) {
22172 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
22173 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
22174 // It will be analyzed later.
22175 Vars.push_back(Elt: RefExpr);
22176 SrcExprs.push_back(Elt: nullptr);
22177 DstExprs.push_back(Elt: nullptr);
22178 AssignmentOps.push_back(Elt: nullptr);
22179 continue;
22180 }
22181
22182 SourceLocation ELoc = RefExpr->getExprLoc();
22183 // OpenMP [2.1, C/C++]
22184 // A list item is a variable name.
22185 // OpenMP [2.14.4.1, Restrictions, p.1]
22186 // A list item that appears in a copyin clause must be threadprivate.
22187 auto *DE = dyn_cast<DeclRefExpr>(Val: RefExpr);
22188 if (!DE || !isa<VarDecl>(Val: DE->getDecl())) {
22189 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_var_name_member_expr)
22190 << 0 << RefExpr->getSourceRange();
22191 continue;
22192 }
22193
22194 Decl *D = DE->getDecl();
22195 auto *VD = cast<VarDecl>(Val: D);
22196
22197 QualType Type = VD->getType();
22198 if (Type->isDependentType() || Type->isInstantiationDependentType()) {
22199 // It will be analyzed later.
22200 Vars.push_back(Elt: DE);
22201 SrcExprs.push_back(Elt: nullptr);
22202 DstExprs.push_back(Elt: nullptr);
22203 AssignmentOps.push_back(Elt: nullptr);
22204 continue;
22205 }
22206
22207 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
22208 // A list item that appears in a copyin clause must be threadprivate.
22209 if (!DSAStack->isThreadPrivate(D: VD)) {
22210 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
22211 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
22212 << getOpenMPClauseNameForDiag(C: OMPC_copyin)
22213 << getOpenMPDirectiveName(D: OMPD_threadprivate, V: OMPVersion);
22214 continue;
22215 }
22216
22217 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
22218 // A variable of class type (or array thereof) that appears in a
22219 // copyin clause requires an accessible, unambiguous copy assignment
22220 // operator for the class type.
22221 QualType ElemType =
22222 getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
22223 VarDecl *SrcVD =
22224 buildVarDecl(SemaRef, Loc: DE->getBeginLoc(), Type: ElemType.getUnqualifiedType(),
22225 Name: ".copyin.src", Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr);
22226 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
22227 S&: SemaRef, D: SrcVD, Ty: ElemType.getUnqualifiedType(), Loc: DE->getExprLoc());
22228 VarDecl *DstVD =
22229 buildVarDecl(SemaRef, Loc: DE->getBeginLoc(), Type: ElemType, Name: ".copyin.dst",
22230 Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr);
22231 DeclRefExpr *PseudoDstExpr =
22232 buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: ElemType, Loc: DE->getExprLoc());
22233 // For arrays generate assignment operation for single element and replace
22234 // it by the original array element in CodeGen.
22235 ExprResult AssignmentOp =
22236 SemaRef.BuildBinOp(/*S=*/nullptr, OpLoc: DE->getExprLoc(), Opc: BO_Assign,
22237 LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
22238 if (AssignmentOp.isInvalid())
22239 continue;
22240 AssignmentOp =
22241 SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: DE->getExprLoc(),
22242 /*DiscardedValue=*/false);
22243 if (AssignmentOp.isInvalid())
22244 continue;
22245
22246 DSAStack->addDSA(D: VD, E: DE, A: OMPC_copyin);
22247 Vars.push_back(Elt: DE);
22248 SrcExprs.push_back(Elt: PseudoSrcExpr);
22249 DstExprs.push_back(Elt: PseudoDstExpr);
22250 AssignmentOps.push_back(Elt: AssignmentOp.get());
22251 }
22252
22253 if (Vars.empty())
22254 return nullptr;
22255
22256 return OMPCopyinClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
22257 VL: Vars, SrcExprs, DstExprs, AssignmentOps);
22258}
22259
22260OMPClause *SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
22261 SourceLocation StartLoc,
22262 SourceLocation LParenLoc,
22263 SourceLocation EndLoc) {
22264 SmallVector<Expr *, 8> Vars;
22265 SmallVector<Expr *, 8> SrcExprs;
22266 SmallVector<Expr *, 8> DstExprs;
22267 SmallVector<Expr *, 8> AssignmentOps;
22268 for (Expr *RefExpr : VarList) {
22269 assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
22270 SourceLocation ELoc;
22271 SourceRange ERange;
22272 Expr *SimpleRefExpr = RefExpr;
22273 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
22274 if (Res.second) {
22275 // It will be analyzed later.
22276 Vars.push_back(Elt: RefExpr);
22277 SrcExprs.push_back(Elt: nullptr);
22278 DstExprs.push_back(Elt: nullptr);
22279 AssignmentOps.push_back(Elt: nullptr);
22280 }
22281 ValueDecl *D = Res.first;
22282 if (!D)
22283 continue;
22284
22285 QualType Type = D->getType();
22286 auto *VD = dyn_cast<VarDecl>(Val: D);
22287
22288 // OpenMP [2.14.4.2, Restrictions, p.2]
22289 // A list item that appears in a copyprivate clause may not appear in a
22290 // private or firstprivate clause on the single construct.
22291 if (!VD || !DSAStack->isThreadPrivate(D: VD)) {
22292 DSAStackTy::DSAVarData DVar =
22293 DSAStack->getTopDSA(D, /*FromParent=*/false);
22294 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
22295 DVar.RefExpr) {
22296 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
22297 << getOpenMPClauseNameForDiag(C: DVar.CKind)
22298 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate);
22299 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
22300 continue;
22301 }
22302
22303 // OpenMP [2.11.4.2, Restrictions, p.1]
22304 // All list items that appear in a copyprivate clause must be either
22305 // threadprivate or private in the enclosing context.
22306 if (DVar.CKind == OMPC_unknown) {
22307 DVar = DSAStack->getImplicitDSA(D, FromParent: false);
22308 if (DVar.CKind == OMPC_shared) {
22309 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
22310 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate)
22311 << "threadprivate or private in the enclosing context";
22312 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
22313 continue;
22314 }
22315 }
22316 }
22317
22318 // Variably modified types are not supported.
22319 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
22320 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
22321 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
22322 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate) << Type
22323 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
22324 V: OMPVersion);
22325 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
22326 VarDecl::DeclarationOnly;
22327 Diag(Loc: D->getLocation(),
22328 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
22329 << D;
22330 continue;
22331 }
22332
22333 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
22334 // A variable of class type (or array thereof) that appears in a
22335 // copyin clause requires an accessible, unambiguous copy assignment
22336 // operator for the class type.
22337 Type = getASTContext()
22338 .getBaseElementType(QT: Type.getNonReferenceType())
22339 .getUnqualifiedType();
22340 VarDecl *SrcVD =
22341 buildVarDecl(SemaRef, Loc: RefExpr->getBeginLoc(), Type, Name: ".copyprivate.src",
22342 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
22343 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(S&: SemaRef, D: SrcVD, Ty: Type, Loc: ELoc);
22344 VarDecl *DstVD =
22345 buildVarDecl(SemaRef, Loc: RefExpr->getBeginLoc(), Type, Name: ".copyprivate.dst",
22346 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
22347 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: Type, Loc: ELoc);
22348 ExprResult AssignmentOp = SemaRef.BuildBinOp(
22349 DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
22350 if (AssignmentOp.isInvalid())
22351 continue;
22352 AssignmentOp = SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: ELoc,
22353 /*DiscardedValue=*/false);
22354 if (AssignmentOp.isInvalid())
22355 continue;
22356
22357 // No need to mark vars as copyprivate, they are already threadprivate or
22358 // implicitly private.
22359 assert(VD || isOpenMPCapturedDecl(D));
22360 Vars.push_back(
22361 Elt: VD ? RefExpr->IgnoreParens()
22362 : buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false));
22363 SrcExprs.push_back(Elt: PseudoSrcExpr);
22364 DstExprs.push_back(Elt: PseudoDstExpr);
22365 AssignmentOps.push_back(Elt: AssignmentOp.get());
22366 }
22367
22368 if (Vars.empty())
22369 return nullptr;
22370
22371 return OMPCopyprivateClause::Create(C: getASTContext(), StartLoc, LParenLoc,
22372 EndLoc, VL: Vars, SrcExprs, DstExprs,
22373 AssignmentOps);
22374}
22375
22376OMPClause *SemaOpenMP::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
22377 SourceLocation StartLoc,
22378 SourceLocation LParenLoc,
22379 SourceLocation EndLoc) {
22380 if (VarList.empty())
22381 return nullptr;
22382
22383 return OMPFlushClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
22384 VL: VarList);
22385}
22386
22387/// Tries to find omp_depend_t. type.
22388static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
22389 bool Diagnose = true) {
22390 QualType OMPDependT = Stack->getOMPDependT();
22391 if (!OMPDependT.isNull())
22392 return true;
22393 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_depend_t");
22394 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
22395 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22396 if (Diagnose)
22397 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_depend_t";
22398 return false;
22399 }
22400 Stack->setOMPDependT(PT.get());
22401 return true;
22402}
22403
22404OMPClause *SemaOpenMP::ActOnOpenMPDepobjClause(Expr *Depobj,
22405 SourceLocation StartLoc,
22406 SourceLocation LParenLoc,
22407 SourceLocation EndLoc) {
22408 if (!Depobj)
22409 return nullptr;
22410
22411 bool OMPDependTFound = findOMPDependT(S&: SemaRef, Loc: StartLoc, DSAStack);
22412
22413 // OpenMP 5.0, 2.17.10.1 depobj Construct
22414 // depobj is an lvalue expression of type omp_depend_t.
22415 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
22416 !Depobj->isInstantiationDependent() &&
22417 !Depobj->containsUnexpandedParameterPack() &&
22418 (OMPDependTFound && !getASTContext().typesAreCompatible(
22419 DSAStack->getOMPDependT(), T2: Depobj->getType(),
22420 /*CompareUnqualified=*/true))) {
22421 Diag(Loc: Depobj->getExprLoc(), DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
22422 << 0 << Depobj->getType() << Depobj->getSourceRange();
22423 }
22424
22425 if (!Depobj->isLValue()) {
22426 Diag(Loc: Depobj->getExprLoc(), DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
22427 << 1 << Depobj->getSourceRange();
22428 }
22429
22430 return OMPDepobjClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
22431 Depobj);
22432}
22433
22434namespace {
22435// Utility struct that gathers the related info for doacross clause.
22436struct DoacrossDataInfoTy {
22437 // The list of expressions.
22438 SmallVector<Expr *, 8> Vars;
22439 // The OperatorOffset for doacross loop.
22440 DSAStackTy::OperatorOffsetTy OpsOffs;
22441 // The depended loop count.
22442 llvm::APSInt TotalDepCount;
22443};
22444} // namespace
22445static DoacrossDataInfoTy
22446ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource,
22447 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
22448 SourceLocation EndLoc) {
22449
22450 SmallVector<Expr *, 8> Vars;
22451 DSAStackTy::OperatorOffsetTy OpsOffs;
22452 llvm::APSInt DepCounter(/*BitWidth=*/32);
22453 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
22454
22455 if (const Expr *OrderedCountExpr =
22456 Stack->getParentOrderedRegionParam().first) {
22457 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Ctx: SemaRef.Context);
22458 TotalDepCount.setIsUnsigned(/*Val=*/true);
22459 }
22460
22461 for (Expr *RefExpr : VarList) {
22462 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
22463 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
22464 // It will be analyzed later.
22465 Vars.push_back(Elt: RefExpr);
22466 continue;
22467 }
22468
22469 SourceLocation ELoc = RefExpr->getExprLoc();
22470 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
22471 if (!IsSource) {
22472 if (Stack->getParentOrderedRegionParam().first &&
22473 DepCounter >= TotalDepCount) {
22474 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_unexpected_expr);
22475 continue;
22476 }
22477 ++DepCounter;
22478 // OpenMP [2.13.9, Summary]
22479 // depend(dependence-type : vec), where dependence-type is:
22480 // 'sink' and where vec is the iteration vector, which has the form:
22481 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
22482 // where n is the value specified by the ordered clause in the loop
22483 // directive, xi denotes the loop iteration variable of the i-th nested
22484 // loop associated with the loop directive, and di is a constant
22485 // non-negative integer.
22486 if (SemaRef.CurContext->isDependentContext()) {
22487 // It will be analyzed later.
22488 Vars.push_back(Elt: RefExpr);
22489 continue;
22490 }
22491 SimpleExpr = SimpleExpr->IgnoreImplicit();
22492 OverloadedOperatorKind OOK = OO_None;
22493 SourceLocation OOLoc;
22494 Expr *LHS = SimpleExpr;
22495 Expr *RHS = nullptr;
22496 if (auto *BO = dyn_cast<BinaryOperator>(Val: SimpleExpr)) {
22497 OOK = BinaryOperator::getOverloadedOperator(Opc: BO->getOpcode());
22498 OOLoc = BO->getOperatorLoc();
22499 LHS = BO->getLHS()->IgnoreParenImpCasts();
22500 RHS = BO->getRHS()->IgnoreParenImpCasts();
22501 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Val: SimpleExpr)) {
22502 OOK = OCE->getOperator();
22503 OOLoc = OCE->getOperatorLoc();
22504 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
22505 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
22506 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Val: SimpleExpr)) {
22507 OOK = MCE->getMethodDecl()
22508 ->getNameInfo()
22509 .getName()
22510 .getCXXOverloadedOperator();
22511 OOLoc = MCE->getCallee()->getExprLoc();
22512 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
22513 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
22514 }
22515 SourceLocation ELoc;
22516 SourceRange ERange;
22517 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: LHS, ELoc, ERange);
22518 if (Res.second) {
22519 // It will be analyzed later.
22520 Vars.push_back(Elt: RefExpr);
22521 }
22522 ValueDecl *D = Res.first;
22523 if (!D)
22524 continue;
22525
22526 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
22527 SemaRef.Diag(Loc: OOLoc, DiagID: diag::err_omp_depend_sink_expected_plus_minus);
22528 continue;
22529 }
22530 if (RHS) {
22531 ExprResult RHSRes =
22532 SemaRef.OpenMP().VerifyPositiveIntegerConstantInClause(
22533 E: RHS, CKind: OMPC_depend, /*StrictlyPositive=*/false);
22534 if (RHSRes.isInvalid())
22535 continue;
22536 }
22537 if (!SemaRef.CurContext->isDependentContext() &&
22538 Stack->getParentOrderedRegionParam().first &&
22539 DepCounter != Stack->isParentLoopControlVariable(D).first) {
22540 const ValueDecl *VD =
22541 Stack->getParentLoopControlVariable(I: DepCounter.getZExtValue());
22542 if (VD)
22543 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
22544 << 1 << VD;
22545 else
22546 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
22547 << 0;
22548 continue;
22549 }
22550 OpsOffs.emplace_back(Args&: RHS, Args&: OOK);
22551 }
22552 Vars.push_back(Elt: RefExpr->IgnoreParenImpCasts());
22553 }
22554 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
22555 TotalDepCount > VarList.size() &&
22556 Stack->getParentOrderedRegionParam().first &&
22557 Stack->getParentLoopControlVariable(I: VarList.size() + 1)) {
22558 SemaRef.Diag(Loc: EndLoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
22559 << 1 << Stack->getParentLoopControlVariable(I: VarList.size() + 1);
22560 }
22561 return {.Vars: Vars, .OpsOffs: OpsOffs, .TotalDepCount: TotalDepCount};
22562}
22563
22564OMPClause *SemaOpenMP::ActOnOpenMPDependClause(
22565 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
22566 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
22567 SourceLocation EndLoc) {
22568 OpenMPDependClauseKind DepKind = Data.DepKind;
22569 SourceLocation DepLoc = Data.DepLoc;
22570 if (DSAStack->getCurrentDirective() == OMPD_ordered_standalone &&
22571 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
22572 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
22573 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(C: OMPC_depend);
22574 return nullptr;
22575 }
22576 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
22577 DepKind == OMPC_DEPEND_mutexinoutset) {
22578 Diag(Loc: DepLoc, DiagID: diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
22579 return nullptr;
22580 }
22581 if ((DSAStack->getCurrentDirective() != OMPD_ordered_standalone ||
22582 DSAStack->getCurrentDirective() == OMPD_depobj) &&
22583 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
22584 DepKind == OMPC_DEPEND_sink ||
22585 ((getLangOpts().OpenMP < 50 ||
22586 DSAStack->getCurrentDirective() == OMPD_depobj) &&
22587 DepKind == OMPC_DEPEND_depobj))) {
22588 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
22589 OMPC_DEPEND_outallmemory,
22590 OMPC_DEPEND_inoutallmemory};
22591 if (getLangOpts().OpenMP < 50 ||
22592 DSAStack->getCurrentDirective() == OMPD_depobj)
22593 Except.push_back(Elt: OMPC_DEPEND_depobj);
22594 if (getLangOpts().OpenMP < 51)
22595 Except.push_back(Elt: OMPC_DEPEND_inoutset);
22596 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
22597 ? "depend modifier(iterator) or "
22598 : "";
22599 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
22600 << Expected + getListOfPossibleValues(K: OMPC_depend, /*First=*/0,
22601 /*Last=*/OMPC_DEPEND_unknown,
22602 Exclude: Except)
22603 << getOpenMPClauseNameForDiag(C: OMPC_depend);
22604 return nullptr;
22605 }
22606 if (DepModifier &&
22607 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
22608 Diag(Loc: DepModifier->getExprLoc(),
22609 DiagID: diag::err_omp_depend_sink_source_with_modifier);
22610 return nullptr;
22611 }
22612 if (DepModifier &&
22613 !DepModifier->getType()->isSpecificBuiltinType(K: BuiltinType::OMPIterator))
22614 Diag(Loc: DepModifier->getExprLoc(), DiagID: diag::err_omp_depend_modifier_not_iterator);
22615
22616 SmallVector<Expr *, 8> Vars;
22617 DSAStackTy::OperatorOffsetTy OpsOffs;
22618 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
22619
22620 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
22621 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
22622 SemaRef, IsSource: DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
22623 Vars = VarOffset.Vars;
22624 OpsOffs = VarOffset.OpsOffs;
22625 TotalDepCount = VarOffset.TotalDepCount;
22626 } else {
22627 for (Expr *RefExpr : VarList) {
22628 assert(RefExpr && "NULL expr in OpenMP depend clause.");
22629 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
22630 // It will be analyzed later.
22631 Vars.push_back(Elt: RefExpr);
22632 continue;
22633 }
22634
22635 SourceLocation ELoc = RefExpr->getExprLoc();
22636 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
22637 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
22638 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
22639 if (OMPDependTFound)
22640 OMPDependTFound = findOMPDependT(S&: SemaRef, Loc: StartLoc, DSAStack,
22641 Diagnose: DepKind == OMPC_DEPEND_depobj);
22642 if (DepKind == OMPC_DEPEND_depobj) {
22643 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
22644 // List items used in depend clauses with the depobj dependence type
22645 // must be expressions of the omp_depend_t type.
22646 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
22647 !RefExpr->isInstantiationDependent() &&
22648 !RefExpr->containsUnexpandedParameterPack() &&
22649 (OMPDependTFound &&
22650 !getASTContext().hasSameUnqualifiedType(
22651 DSAStack->getOMPDependT(), T2: RefExpr->getType()))) {
22652 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
22653 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
22654 continue;
22655 }
22656 if (!RefExpr->isLValue()) {
22657 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
22658 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
22659 continue;
22660 }
22661 } else {
22662 // OpenMP 5.0 [2.17.11, Restrictions]
22663 // List items used in depend clauses cannot be zero-length array
22664 // sections.
22665 QualType ExprTy = RefExpr->getType().getNonReferenceType();
22666 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: SimpleExpr);
22667 if (OASE) {
22668 QualType BaseType =
22669 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
22670 if (BaseType.isNull())
22671 return nullptr;
22672 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22673 ExprTy = ATy->getElementType();
22674 else
22675 ExprTy = BaseType->getPointeeType();
22676 if (BaseType.isNull() || ExprTy.isNull())
22677 return nullptr;
22678 ExprTy = ExprTy.getNonReferenceType();
22679 const Expr *Length = OASE->getLength();
22680 Expr::EvalResult Result;
22681 if (Length && !Length->isValueDependent() &&
22682 Length->EvaluateAsInt(Result, Ctx: getASTContext()) &&
22683 Result.Val.getInt().isZero()) {
22684 Diag(Loc: ELoc,
22685 DiagID: diag::err_omp_depend_zero_length_array_section_not_allowed)
22686 << SimpleExpr->getSourceRange();
22687 continue;
22688 }
22689 }
22690
22691 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
22692 // List items used in depend clauses with the in, out, inout,
22693 // inoutset, or mutexinoutset dependence types cannot be
22694 // expressions of the omp_depend_t type.
22695 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
22696 !RefExpr->isInstantiationDependent() &&
22697 !RefExpr->containsUnexpandedParameterPack() &&
22698 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
22699 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
22700 ExprTy.getTypePtr()))) {
22701 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
22702 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22703 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22704 << RefExpr->getSourceRange();
22705 continue;
22706 }
22707
22708 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: SimpleExpr);
22709 if (ASE && !ASE->getBase()->isTypeDependent() &&
22710 !ASE->getBase()
22711 ->getType()
22712 .getNonReferenceType()
22713 ->isPointerType() &&
22714 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
22715 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
22716 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22717 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22718 << RefExpr->getSourceRange();
22719 continue;
22720 }
22721
22722 ExprResult Res;
22723 {
22724 Sema::TentativeAnalysisScope Trap(SemaRef);
22725 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf,
22726 InputExpr: RefExpr->IgnoreParenImpCasts());
22727 }
22728 if (!Res.isUsable() && !isa<ArraySectionExpr>(Val: SimpleExpr) &&
22729 !isa<OMPArrayShapingExpr>(Val: SimpleExpr)) {
22730 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
22731 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22732 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22733 << RefExpr->getSourceRange();
22734 continue;
22735 }
22736 }
22737 }
22738 Vars.push_back(Elt: RefExpr->IgnoreParenImpCasts());
22739 }
22740 }
22741
22742 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
22743 DepKind != OMPC_DEPEND_outallmemory &&
22744 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
22745 return nullptr;
22746
22747 auto *C = OMPDependClause::Create(
22748 C: getASTContext(), StartLoc, LParenLoc, EndLoc,
22749 Data: {.DepKind: DepKind, .DepLoc: DepLoc, .ColonLoc: Data.ColonLoc, .OmpAllMemoryLoc: Data.OmpAllMemoryLoc}, DepModifier, VL: Vars,
22750 NumLoops: TotalDepCount.getZExtValue());
22751 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
22752 DSAStack->isParentOrderedRegion())
22753 DSAStack->addDoacrossDependClause(C, OpsOffs);
22754 return C;
22755}
22756
22757OMPClause *SemaOpenMP::ActOnOpenMPDeviceClause(
22758 OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc,
22759 SourceLocation LParenLoc, SourceLocation ModifierLoc,
22760 SourceLocation EndLoc) {
22761 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
22762 "Unexpected device modifier in OpenMP < 50.");
22763
22764 bool ErrorFound = false;
22765 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
22766 std::string Values =
22767 getListOfPossibleValues(K: OMPC_device, /*First=*/0, Last: OMPC_DEVICE_unknown);
22768 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
22769 << Values << getOpenMPClauseNameForDiag(C: OMPC_device);
22770 ErrorFound = true;
22771 }
22772
22773 Expr *ValExpr = Device;
22774 Stmt *HelperValStmt = nullptr;
22775
22776 // OpenMP 5.2 [1.3, Execution Model]: a conforming device number is either
22777 // a non-negative integer that is less than or equal to omp_get_num_devices()
22778 // or equal to omp_initial_device or omp_invalid_device. The predefined
22779 // identifiers were introduced in OpenMP 5.2; earlier versions require a
22780 // non-negative integer.
22781 if (getLangOpts().OpenMP >= 52) {
22782 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
22783 !ValExpr->isInstantiationDependent()) {
22784 SourceLocation Loc = ValExpr->getExprLoc();
22785 ExprResult Value = PerformOpenMPImplicitIntegerConversion(Loc, Op: ValExpr);
22786 if (Value.isInvalid()) {
22787 ErrorFound = true;
22788 } else {
22789 ValExpr = Value.get();
22790 if (std::optional<llvm::APSInt> Result =
22791 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
22792 if (Result->isSigned() && Result->slt(RHS: -2)) {
22793 Diag(Loc, DiagID: diag::err_omp_device_expression_invalid)
22794 << ValExpr->getSourceRange();
22795 ErrorFound = true;
22796 }
22797 }
22798 }
22799 }
22800 } else {
22801 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_device,
22802 /*StrictlyPositive=*/false) ||
22803 ErrorFound;
22804 }
22805 if (ErrorFound)
22806 return nullptr;
22807
22808 // OpenMP 5.0 [2.12.5, Restrictions]
22809 // In case of ancestor device-modifier, a requires directive with
22810 // the reverse_offload clause must be specified.
22811 if (Modifier == OMPC_DEVICE_ancestor) {
22812 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
22813 SemaRef.targetDiag(
22814 Loc: StartLoc,
22815 DiagID: diag::err_omp_device_ancestor_without_requires_reverse_offload);
22816 ErrorFound = true;
22817 }
22818 }
22819
22820 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22821 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
22822 DKind, CKind: OMPC_device, OMPVersion: getLangOpts().getOpenMPVersion());
22823 if (CaptureRegion != OMPD_unknown &&
22824 !SemaRef.CurContext->isDependentContext()) {
22825 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
22826 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22827 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
22828 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
22829 }
22830
22831 return new (getASTContext())
22832 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
22833 LParenLoc, ModifierLoc, EndLoc);
22834}
22835
22836static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
22837 DSAStackTy *Stack, QualType QTy,
22838 bool FullCheck = true) {
22839 if (SemaRef.RequireCompleteType(Loc: SL, T: QTy, DiagID: diag::err_incomplete_type))
22840 return false;
22841 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
22842 !QTy.isTriviallyCopyableType(Context: SemaRef.Context))
22843 SemaRef.Diag(Loc: SL, DiagID: diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
22844 return true;
22845}
22846
22847/// Return true if it can be proven that the provided array expression
22848/// (array section or array subscript) does NOT specify the whole size of the
22849/// array whose base type is \a BaseQTy.
22850static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
22851 const Expr *E,
22852 QualType BaseQTy) {
22853 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: E);
22854
22855 // If this is an array subscript, it refers to the whole size if the size of
22856 // the dimension is constant and equals 1. Also, an array section assumes the
22857 // format of an array subscript if no colon is used.
22858 if (isa<ArraySubscriptExpr>(Val: E) ||
22859 (OASE && OASE->getColonLocFirst().isInvalid())) {
22860 if (const auto *ATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr()))
22861 return ATy->getSExtSize() != 1;
22862 // Size can't be evaluated statically.
22863 return false;
22864 }
22865
22866 assert(OASE && "Expecting array section if not an array subscript.");
22867 const Expr *LowerBound = OASE->getLowerBound();
22868 const Expr *Length = OASE->getLength();
22869
22870 // If there is a lower bound that does not evaluates to zero, we are not
22871 // covering the whole dimension.
22872 if (LowerBound) {
22873 Expr::EvalResult Result;
22874 if (!LowerBound->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
22875 return false; // Can't get the integer value as a constant.
22876
22877 llvm::APSInt ConstLowerBound = Result.Val.getInt();
22878 if (ConstLowerBound.getSExtValue())
22879 return true;
22880 }
22881
22882 // If we don't have a length we covering the whole dimension.
22883 if (!Length)
22884 return false;
22885
22886 // If the base is a pointer, we don't have a way to get the size of the
22887 // pointee.
22888 if (BaseQTy->isPointerType())
22889 return false;
22890
22891 // We can only check if the length is the same as the size of the dimension
22892 // if we have a constant array.
22893 const auto *CATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr());
22894 if (!CATy)
22895 return false;
22896
22897 Expr::EvalResult Result;
22898 if (!Length->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
22899 return false; // Can't get the integer value as a constant.
22900
22901 llvm::APSInt ConstLength = Result.Val.getInt();
22902 return CATy->getSExtSize() != ConstLength.getSExtValue();
22903}
22904
22905// Return true if it can be proven that the provided array expression (array
22906// section or array subscript) does NOT specify a single element of the array
22907// whose base type is \a BaseQTy.
22908static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
22909 const Expr *E,
22910 QualType BaseQTy) {
22911 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: E);
22912
22913 // An array subscript always refer to a single element. Also, an array section
22914 // assumes the format of an array subscript if no colon is used.
22915 if (isa<ArraySubscriptExpr>(Val: E) ||
22916 (OASE && OASE->getColonLocFirst().isInvalid()))
22917 return false;
22918
22919 assert(OASE && "Expecting array section if not an array subscript.");
22920 const Expr *Length = OASE->getLength();
22921
22922 // If we don't have a length we have to check if the array has unitary size
22923 // for this dimension. Also, we should always expect a length if the base type
22924 // is pointer.
22925 if (!Length) {
22926 if (const auto *ATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr()))
22927 return ATy->getSExtSize() != 1;
22928 // We cannot assume anything.
22929 return false;
22930 }
22931
22932 // Check if the length evaluates to 1.
22933 Expr::EvalResult Result;
22934 if (!Length->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
22935 return false; // Can't get the integer value as a constant.
22936
22937 llvm::APSInt ConstLength = Result.Val.getInt();
22938 return ConstLength.getSExtValue() != 1;
22939}
22940
22941// The base of elements of list in a map clause have to be either:
22942// - a reference to variable or field.
22943// - a member expression.
22944// - an array expression.
22945//
22946// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
22947// reference to 'r'.
22948//
22949// If we have:
22950//
22951// struct SS {
22952// Bla S;
22953// foo() {
22954// #pragma omp target map (S.Arr[:12]);
22955// }
22956// }
22957//
22958// We want to retrieve the member expression 'this->S';
22959
22960// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
22961// If a list item is an array section, it must specify contiguous storage.
22962//
22963// For this restriction it is sufficient that we make sure only references
22964// to variables or fields and array expressions, and that no array sections
22965// exist except in the rightmost expression (unless they cover the whole
22966// dimension of the array). E.g. these would be invalid:
22967//
22968// r.ArrS[3:5].Arr[6:7]
22969//
22970// r.ArrS[3:5].x
22971//
22972// but these would be valid:
22973// r.ArrS[3].Arr[6:7]
22974//
22975// r.ArrS[3].x
22976namespace {
22977class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
22978 Sema &SemaRef;
22979 OpenMPClauseKind CKind = OMPC_unknown;
22980 OpenMPDirectiveKind DKind = OMPD_unknown;
22981 OMPClauseMappableExprCommon::MappableExprComponentList &Components;
22982 bool IsNonContiguous = false;
22983 bool NoDiagnose = false;
22984 const Expr *RelevantExpr = nullptr;
22985 bool AllowUnitySizeArraySection = true;
22986 bool AllowWholeSizeArraySection = true;
22987 bool AllowAnotherPtr = true;
22988 SourceLocation ELoc;
22989 SourceRange ERange;
22990
22991 void emitErrorMsg() {
22992 // If nothing else worked, this is not a valid map clause expression.
22993 if (SemaRef.getLangOpts().OpenMP < 50) {
22994 SemaRef.Diag(Loc: ELoc,
22995 DiagID: diag::err_omp_expected_named_var_member_or_array_expression)
22996 << ERange;
22997 } else {
22998 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22999 << getOpenMPClauseNameForDiag(C: CKind) << ERange;
23000 }
23001 }
23002
23003public:
23004 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
23005 if (!isa<VarDecl>(Val: DRE->getDecl())) {
23006 emitErrorMsg();
23007 return false;
23008 }
23009 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
23010 RelevantExpr = DRE;
23011 // Record the component.
23012 Components.emplace_back(Args&: DRE, Args: DRE->getDecl(), Args&: IsNonContiguous);
23013 return true;
23014 }
23015
23016 bool VisitMemberExpr(MemberExpr *ME) {
23017 Expr *E = ME;
23018 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
23019
23020 if (isa<CXXThisExpr>(Val: BaseE)) {
23021 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
23022 // We found a base expression: this->Val.
23023 RelevantExpr = ME;
23024 } else {
23025 E = BaseE;
23026 }
23027
23028 if (!isa<FieldDecl>(Val: ME->getMemberDecl())) {
23029 if (!NoDiagnose) {
23030 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_access_to_data_field)
23031 << ME->getSourceRange();
23032 return false;
23033 }
23034 if (RelevantExpr)
23035 return false;
23036 return Visit(S: E);
23037 }
23038
23039 auto *FD = cast<FieldDecl>(Val: ME->getMemberDecl());
23040
23041 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
23042 // A bit-field cannot appear in a map clause.
23043 //
23044 if (FD->isBitField()) {
23045 if (!NoDiagnose) {
23046 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_bit_fields_forbidden_in_clause)
23047 << ME->getSourceRange() << getOpenMPClauseNameForDiag(C: CKind);
23048 return false;
23049 }
23050 if (RelevantExpr)
23051 return false;
23052 return Visit(S: E);
23053 }
23054
23055 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
23056 // If the type of a list item is a reference to a type T then the type
23057 // will be considered to be T for all purposes of this clause.
23058 QualType CurType = BaseE->getType().getNonReferenceType();
23059
23060 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
23061 // A list item cannot be a variable that is a member of a structure with
23062 // a union type.
23063 //
23064 if (CurType->isUnionType()) {
23065 if (!NoDiagnose) {
23066 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_union_type_not_allowed)
23067 << ME->getSourceRange();
23068 return false;
23069 }
23070 return RelevantExpr || Visit(S: E);
23071 }
23072
23073 // If we got a member expression, we should not expect any array section
23074 // before that:
23075 //
23076 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
23077 // If a list item is an element of a structure, only the rightmost symbol
23078 // of the variable reference can be an array section.
23079 //
23080 AllowUnitySizeArraySection = false;
23081 AllowWholeSizeArraySection = false;
23082
23083 // Record the component.
23084 Components.emplace_back(Args&: ME, Args&: FD, Args&: IsNonContiguous);
23085 return RelevantExpr || Visit(S: E);
23086 }
23087
23088 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
23089 Expr *E = AE->getBase()->IgnoreParenImpCasts();
23090
23091 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
23092 if (!NoDiagnose) {
23093 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
23094 << 0 << AE->getSourceRange();
23095 return false;
23096 }
23097 return RelevantExpr || Visit(S: E);
23098 }
23099
23100 // If we got an array subscript that express the whole dimension we
23101 // can have any array expressions before. If it only expressing part of
23102 // the dimension, we can only have unitary-size array expressions.
23103 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, E: AE, BaseQTy: E->getType()))
23104 AllowWholeSizeArraySection = false;
23105
23106 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E->IgnoreParenCasts())) {
23107 Expr::EvalResult Result;
23108 if (!AE->getIdx()->isValueDependent() &&
23109 AE->getIdx()->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()) &&
23110 !Result.Val.getInt().isZero()) {
23111 SemaRef.Diag(Loc: AE->getIdx()->getExprLoc(),
23112 DiagID: diag::err_omp_invalid_map_this_expr);
23113 SemaRef.Diag(Loc: AE->getIdx()->getExprLoc(),
23114 DiagID: diag::note_omp_invalid_subscript_on_this_ptr_map);
23115 }
23116 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
23117 RelevantExpr = TE;
23118 }
23119
23120 // Record the component - we don't have any declaration associated.
23121 Components.emplace_back(Args&: AE, Args: nullptr, Args&: IsNonContiguous);
23122
23123 return RelevantExpr || Visit(S: E);
23124 }
23125
23126 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
23127 // After OMP 5.0 Array section in reduction clause will be implicitly
23128 // mapped
23129 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
23130 "Array sections cannot be implicitly mapped.");
23131 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
23132 QualType CurType =
23133 ArraySectionExpr::getBaseOriginalType(Base: E).getCanonicalType();
23134
23135 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
23136 // If the type of a list item is a reference to a type T then the type
23137 // will be considered to be T for all purposes of this clause.
23138 if (CurType->isReferenceType())
23139 CurType = CurType->getPointeeType();
23140
23141 bool IsPointer = CurType->isAnyPointerType();
23142
23143 if (!IsPointer && !CurType->isArrayType()) {
23144 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
23145 << 0 << OASE->getSourceRange();
23146 return false;
23147 }
23148
23149 bool NotWhole =
23150 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, E: OASE, BaseQTy: CurType);
23151 bool NotUnity =
23152 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, E: OASE, BaseQTy: CurType);
23153
23154 if (AllowWholeSizeArraySection) {
23155 // Any array section is currently allowed. Allowing a whole size array
23156 // section implies allowing a unity array section as well.
23157 //
23158 // If this array section refers to the whole dimension we can still
23159 // accept other array sections before this one, except if the base is a
23160 // pointer. Otherwise, only unitary sections are accepted.
23161 if (NotWhole || IsPointer)
23162 AllowWholeSizeArraySection = false;
23163 } else if (DKind == OMPD_target_update &&
23164 SemaRef.getLangOpts().OpenMP >= 50) {
23165 if (IsPointer && !AllowAnotherPtr)
23166 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_section_length_undefined)
23167 << /*array of unknown bound */ 1;
23168 else
23169 IsNonContiguous = true;
23170 } else if (AllowUnitySizeArraySection && NotUnity) {
23171 // A unity or whole array section is not allowed and that is not
23172 // compatible with the properties of the current array section.
23173 if (NoDiagnose)
23174 return false;
23175 SemaRef.Diag(Loc: ELoc,
23176 DiagID: diag::err_array_section_does_not_specify_contiguous_storage)
23177 << OASE->getSourceRange();
23178 return false;
23179 }
23180
23181 if (IsPointer)
23182 AllowAnotherPtr = false;
23183
23184 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E)) {
23185 Expr::EvalResult ResultR;
23186 Expr::EvalResult ResultL;
23187 if (!OASE->getLength()->isValueDependent() &&
23188 OASE->getLength()->EvaluateAsInt(Result&: ResultR, Ctx: SemaRef.getASTContext()) &&
23189 !ResultR.Val.getInt().isOne()) {
23190 SemaRef.Diag(Loc: OASE->getLength()->getExprLoc(),
23191 DiagID: diag::err_omp_invalid_map_this_expr);
23192 SemaRef.Diag(Loc: OASE->getLength()->getExprLoc(),
23193 DiagID: diag::note_omp_invalid_length_on_this_ptr_mapping);
23194 }
23195 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
23196 OASE->getLowerBound()->EvaluateAsInt(Result&: ResultL,
23197 Ctx: SemaRef.getASTContext()) &&
23198 !ResultL.Val.getInt().isZero()) {
23199 SemaRef.Diag(Loc: OASE->getLowerBound()->getExprLoc(),
23200 DiagID: diag::err_omp_invalid_map_this_expr);
23201 SemaRef.Diag(Loc: OASE->getLowerBound()->getExprLoc(),
23202 DiagID: diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
23203 }
23204 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
23205 RelevantExpr = TE;
23206 }
23207
23208 // Record the component - we don't have any declaration associated.
23209 Components.emplace_back(Args&: OASE, Args: nullptr, /*IsNonContiguous=*/Args: false);
23210 return RelevantExpr || Visit(S: E);
23211 }
23212 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
23213 Expr *Base = E->getBase();
23214
23215 // Record the component - we don't have any declaration associated.
23216 Components.emplace_back(Args&: E, Args: nullptr, Args&: IsNonContiguous);
23217
23218 return Visit(S: Base->IgnoreParenImpCasts());
23219 }
23220
23221 bool VisitUnaryOperator(UnaryOperator *UO) {
23222 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
23223 UO->getOpcode() != UO_Deref) {
23224 emitErrorMsg();
23225 return false;
23226 }
23227 if (!RelevantExpr) {
23228 // Record the component if haven't found base decl.
23229 Components.emplace_back(Args&: UO, Args: nullptr, /*IsNonContiguous=*/Args: false);
23230 }
23231 return RelevantExpr || Visit(S: UO->getSubExpr()->IgnoreParenImpCasts());
23232 }
23233 bool VisitBinaryOperator(BinaryOperator *BO) {
23234 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
23235 emitErrorMsg();
23236 return false;
23237 }
23238
23239 // Pointer arithmetic is the only thing we expect to happen here so after we
23240 // make sure the binary operator is a pointer type, the only thing we need
23241 // to do is to visit the subtree that has the same type as root (so that we
23242 // know the other subtree is just an offset)
23243 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
23244 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
23245 Components.emplace_back(Args&: BO, Args: nullptr, Args: false);
23246 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
23247 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
23248 "Either LHS or RHS have base decl inside");
23249 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
23250 return RelevantExpr || Visit(S: LE);
23251 return RelevantExpr || Visit(S: RE);
23252 }
23253 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
23254 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
23255 RelevantExpr = CTE;
23256 Components.emplace_back(Args&: CTE, Args: nullptr, Args&: IsNonContiguous);
23257 return true;
23258 }
23259 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
23260 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
23261 Components.emplace_back(Args&: COCE, Args: nullptr, Args&: IsNonContiguous);
23262 return true;
23263 }
23264 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
23265 Expr *Source = E->getSourceExpr();
23266 if (!Source) {
23267 emitErrorMsg();
23268 return false;
23269 }
23270 return Visit(S: Source);
23271 }
23272 bool VisitStmt(Stmt *) {
23273 emitErrorMsg();
23274 return false;
23275 }
23276 const Expr *getFoundBase() const { return RelevantExpr; }
23277 explicit MapBaseChecker(
23278 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
23279 OMPClauseMappableExprCommon::MappableExprComponentList &Components,
23280 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
23281 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
23282 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
23283};
23284} // namespace
23285
23286/// Return the expression of the base of the mappable expression or null if it
23287/// cannot be determined and do all the necessary checks to see if the
23288/// expression is valid as a standalone mappable expression. In the process,
23289/// record all the components of the expression.
23290static const Expr *checkMapClauseExpressionBase(
23291 Sema &SemaRef, Expr *E,
23292 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
23293 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
23294 SourceLocation ELoc = E->getExprLoc();
23295 SourceRange ERange = E->getSourceRange();
23296 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
23297 ERange);
23298 if (Checker.Visit(S: E->IgnoreParens())) {
23299 // Check if the highest dimension array section has length specified
23300 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
23301 (CKind == OMPC_to || CKind == OMPC_from)) {
23302 auto CI = CurComponents.rbegin();
23303 auto CE = CurComponents.rend();
23304 for (; CI != CE; ++CI) {
23305 const auto *OASE =
23306 dyn_cast<ArraySectionExpr>(Val: CI->getAssociatedExpression());
23307 if (!OASE)
23308 continue;
23309 if (OASE && OASE->getLength())
23310 break;
23311 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_array_section_does_not_specify_length)
23312 << ERange;
23313 }
23314 }
23315 return Checker.getFoundBase();
23316 }
23317 return nullptr;
23318}
23319
23320// Return true if expression E associated with value VD has conflicts with other
23321// map information.
23322static bool checkMapConflicts(
23323 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
23324 bool CurrentRegionOnly,
23325 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
23326 OpenMPClauseKind CKind) {
23327 assert(VD && E);
23328 SourceLocation ELoc = E->getExprLoc();
23329 SourceRange ERange = E->getSourceRange();
23330
23331 // In order to easily check the conflicts we need to match each component of
23332 // the expression under test with the components of the expressions that are
23333 // already in the stack.
23334
23335 assert(!CurComponents.empty() && "Map clause expression with no components!");
23336 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
23337 "Map clause expression with unexpected base!");
23338
23339 // Variables to help detecting enclosing problems in data environment nests.
23340 bool IsEnclosedByDataEnvironmentExpr = false;
23341 const Expr *EnclosingExpr = nullptr;
23342
23343 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
23344 VD, CurrentRegionOnly,
23345 Check: [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
23346 ERange, CKind, &EnclosingExpr,
23347 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
23348 StackComponents,
23349 OpenMPClauseKind Kind) {
23350 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
23351 return false;
23352 assert(!StackComponents.empty() &&
23353 "Map clause expression with no components!");
23354 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
23355 "Map clause expression with unexpected base!");
23356 (void)VD;
23357
23358 // The whole expression in the stack.
23359 const Expr *RE = StackComponents.front().getAssociatedExpression();
23360
23361 // Expressions must start from the same base. Here we detect at which
23362 // point both expressions diverge from each other and see if we can
23363 // detect if the memory referred to both expressions is contiguous and
23364 // do not overlap.
23365 auto CI = CurComponents.rbegin();
23366 auto CE = CurComponents.rend();
23367 auto SI = StackComponents.rbegin();
23368 auto SE = StackComponents.rend();
23369 for (; CI != CE && SI != SE; ++CI, ++SI) {
23370
23371 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
23372 // At most one list item can be an array item derived from a given
23373 // variable in map clauses of the same construct.
23374 if (CurrentRegionOnly &&
23375 (isa<ArraySubscriptExpr>(Val: CI->getAssociatedExpression()) ||
23376 isa<ArraySectionExpr>(Val: CI->getAssociatedExpression()) ||
23377 isa<OMPArrayShapingExpr>(Val: CI->getAssociatedExpression())) &&
23378 (isa<ArraySubscriptExpr>(Val: SI->getAssociatedExpression()) ||
23379 isa<ArraySectionExpr>(Val: SI->getAssociatedExpression()) ||
23380 isa<OMPArrayShapingExpr>(Val: SI->getAssociatedExpression()))) {
23381 SemaRef.Diag(Loc: CI->getAssociatedExpression()->getExprLoc(),
23382 DiagID: diag::err_omp_multiple_array_items_in_map_clause)
23383 << CI->getAssociatedExpression()->getSourceRange();
23384 SemaRef.Diag(Loc: SI->getAssociatedExpression()->getExprLoc(),
23385 DiagID: diag::note_used_here)
23386 << SI->getAssociatedExpression()->getSourceRange();
23387 return true;
23388 }
23389
23390 // Do both expressions have the same kind?
23391 if (CI->getAssociatedExpression()->getStmtClass() !=
23392 SI->getAssociatedExpression()->getStmtClass())
23393 break;
23394
23395 // Are we dealing with different variables/fields?
23396 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
23397 break;
23398 }
23399 // Check if the extra components of the expressions in the enclosing
23400 // data environment are redundant for the current base declaration.
23401 // If they are, the maps completely overlap, which is legal.
23402 for (; SI != SE; ++SI) {
23403 QualType Type;
23404 if (const auto *ASE =
23405 dyn_cast<ArraySubscriptExpr>(Val: SI->getAssociatedExpression())) {
23406 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
23407 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
23408 Val: SI->getAssociatedExpression())) {
23409 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
23410 Type = ArraySectionExpr::getBaseOriginalType(Base: E).getCanonicalType();
23411 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
23412 Val: SI->getAssociatedExpression())) {
23413 Type = OASE->getBase()->getType()->getPointeeType();
23414 }
23415 if (Type.isNull() || Type->isAnyPointerType() ||
23416 checkArrayExpressionDoesNotReferToWholeSize(
23417 SemaRef, E: SI->getAssociatedExpression(), BaseQTy: Type))
23418 break;
23419 }
23420
23421 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
23422 // List items of map clauses in the same construct must not share
23423 // original storage.
23424 //
23425 // If the expressions are exactly the same or one is a subset of the
23426 // other, it means they are sharing storage.
23427 if (CI == CE && SI == SE) {
23428 if (CurrentRegionOnly) {
23429 if (CKind == OMPC_map) {
23430 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << ERange;
23431 } else {
23432 assert(CKind == OMPC_to || CKind == OMPC_from);
23433 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced_in_target_update)
23434 << ERange;
23435 }
23436 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
23437 << RE->getSourceRange();
23438 return true;
23439 }
23440 // If we find the same expression in the enclosing data environment,
23441 // that is legal.
23442 IsEnclosedByDataEnvironmentExpr = true;
23443 return false;
23444 }
23445
23446 QualType DerivedType =
23447 std::prev(x: CI)->getAssociatedDeclaration()->getType();
23448 SourceLocation DerivedLoc =
23449 std::prev(x: CI)->getAssociatedExpression()->getExprLoc();
23450
23451 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
23452 // If the type of a list item is a reference to a type T then the type
23453 // will be considered to be T for all purposes of this clause.
23454 DerivedType = DerivedType.getNonReferenceType();
23455
23456 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
23457 // A variable for which the type is pointer and an array section
23458 // derived from that variable must not appear as list items of map
23459 // clauses of the same construct.
23460 //
23461 // Also, cover one of the cases in:
23462 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
23463 // If any part of the original storage of a list item has corresponding
23464 // storage in the device data environment, all of the original storage
23465 // must have corresponding storage in the device data environment.
23466 //
23467 if (DerivedType->isAnyPointerType()) {
23468 if (CI == CE || SI == SE) {
23469 SemaRef.Diag(
23470 Loc: DerivedLoc,
23471 DiagID: diag::err_omp_pointer_mapped_along_with_derived_section)
23472 << DerivedLoc;
23473 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
23474 << RE->getSourceRange();
23475 return true;
23476 }
23477 if (CI->getAssociatedExpression()->getStmtClass() !=
23478 SI->getAssociatedExpression()->getStmtClass() ||
23479 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
23480 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
23481 assert(CI != CE && SI != SE);
23482 SemaRef.Diag(Loc: DerivedLoc, DiagID: diag::err_omp_same_pointer_dereferenced)
23483 << DerivedLoc;
23484 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
23485 << RE->getSourceRange();
23486 return true;
23487 }
23488 }
23489
23490 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
23491 // List items of map clauses in the same construct must not share
23492 // original storage.
23493 //
23494 // An expression is a subset of the other.
23495 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
23496 if (CKind == OMPC_map) {
23497 if (CI != CE || SI != SE) {
23498 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
23499 // a pointer.
23500 auto Begin =
23501 CI != CE ? CurComponents.begin() : StackComponents.begin();
23502 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
23503 auto It = Begin;
23504 while (It != End && !It->getAssociatedDeclaration())
23505 std::advance(i&: It, n: 1);
23506 assert(It != End &&
23507 "Expected at least one component with the declaration.");
23508 if (It != Begin && It->getAssociatedDeclaration()
23509 ->getType()
23510 .getCanonicalType()
23511 ->isAnyPointerType()) {
23512 IsEnclosedByDataEnvironmentExpr = false;
23513 EnclosingExpr = nullptr;
23514 return false;
23515 }
23516 }
23517 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << ERange;
23518 } else {
23519 assert(CKind == OMPC_to || CKind == OMPC_from);
23520 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced_in_target_update)
23521 << ERange;
23522 }
23523 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
23524 << RE->getSourceRange();
23525 return true;
23526 }
23527
23528 // The current expression uses the same base as other expression in the
23529 // data environment but does not contain it completely.
23530 if (!CurrentRegionOnly && SI != SE)
23531 EnclosingExpr = RE;
23532
23533 // The current expression is a subset of the expression in the data
23534 // environment.
23535 IsEnclosedByDataEnvironmentExpr |=
23536 (!CurrentRegionOnly && CI != CE && SI == SE);
23537
23538 return false;
23539 });
23540
23541 if (CurrentRegionOnly)
23542 return FoundError;
23543
23544 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
23545 // If any part of the original storage of a list item has corresponding
23546 // storage in the device data environment, all of the original storage must
23547 // have corresponding storage in the device data environment.
23548 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
23549 // If a list item is an element of a structure, and a different element of
23550 // the structure has a corresponding list item in the device data environment
23551 // prior to a task encountering the construct associated with the map clause,
23552 // then the list item must also have a corresponding list item in the device
23553 // data environment prior to the task encountering the construct.
23554 //
23555 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
23556 SemaRef.Diag(Loc: ELoc,
23557 DiagID: diag::err_omp_original_storage_is_shared_and_does_not_contain)
23558 << ERange;
23559 SemaRef.Diag(Loc: EnclosingExpr->getExprLoc(), DiagID: diag::note_used_here)
23560 << EnclosingExpr->getSourceRange();
23561 return true;
23562 }
23563
23564 return FoundError;
23565}
23566
23567// Look up the user-defined mapper given the mapper name and mapped type, and
23568// build a reference to it.
23569static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
23570 CXXScopeSpec &MapperIdScopeSpec,
23571 const DeclarationNameInfo &MapperId,
23572 QualType Type,
23573 Expr *UnresolvedMapper) {
23574 if (MapperIdScopeSpec.isInvalid())
23575 return ExprError();
23576 // Get the actual type for the array type.
23577 if (Type->isArrayType()) {
23578 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
23579 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
23580 }
23581 // Find all user-defined mappers with the given MapperId.
23582 SmallVector<UnresolvedSet<8>, 4> Lookups;
23583 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
23584 Lookup.suppressDiagnostics();
23585 if (S) {
23586 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &MapperIdScopeSpec,
23587 /*ObjectType=*/QualType())) {
23588 NamedDecl *D = Lookup.getRepresentativeDecl();
23589 while (S && !S->isDeclScope(D))
23590 S = S->getParent();
23591 if (S)
23592 S = S->getParent();
23593 Lookups.emplace_back();
23594 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
23595 Lookup.clear();
23596 }
23597 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(Val: UnresolvedMapper)) {
23598 // Extract the user-defined mappers with the given MapperId.
23599 Lookups.push_back(Elt: UnresolvedSet<8>());
23600 for (NamedDecl *D : ULE->decls()) {
23601 auto *DMD = cast<OMPDeclareMapperDecl>(Val: D);
23602 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
23603 Lookups.back().addDecl(D: DMD);
23604 }
23605 }
23606 // Defer the lookup for dependent types. The results will be passed through
23607 // UnresolvedMapper on instantiation.
23608 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
23609 Type->isInstantiationDependentType() ||
23610 Type->containsUnexpandedParameterPack() ||
23611 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
23612 return !D->isInvalidDecl() &&
23613 (D->getType()->isDependentType() ||
23614 D->getType()->isInstantiationDependentType() ||
23615 D->getType()->containsUnexpandedParameterPack());
23616 })) {
23617 UnresolvedSet<8> URS;
23618 for (const UnresolvedSet<8> &Set : Lookups) {
23619 if (Set.empty())
23620 continue;
23621 URS.append(I: Set.begin(), E: Set.end());
23622 }
23623 return UnresolvedLookupExpr::Create(
23624 Context: SemaRef.Context, /*NamingClass=*/nullptr,
23625 QualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: SemaRef.Context), NameInfo: MapperId,
23626 /*ADL=*/RequiresADL: false, Begin: URS.begin(), End: URS.end(), /*KnownDependent=*/false,
23627 /*KnownInstantiationDependent=*/false);
23628 }
23629 SourceLocation Loc = MapperId.getLoc();
23630 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23631 // The type must be of struct, union or class type in C and C++
23632 if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
23633 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
23634 SemaRef.Diag(Loc, DiagID: diag::err_omp_mapper_wrong_type);
23635 return ExprError();
23636 }
23637 // Perform argument dependent lookup.
23638 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
23639 argumentDependentLookup(SemaRef, Id: MapperId, Loc, Ty: Type, Lookups);
23640 // Return the first user-defined mapper with the desired type.
23641 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
23642 Lookups, Gen: [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
23643 if (!D->isInvalidDecl() &&
23644 SemaRef.Context.hasSameType(T1: D->getType(), T2: Type))
23645 return D;
23646 return nullptr;
23647 }))
23648 return SemaRef.BuildDeclRefExpr(D: VD, Ty: Type, VK: VK_LValue, Loc);
23649 // Find the first user-defined mapper with a type derived from the desired
23650 // type.
23651 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
23652 Lookups, Gen: [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
23653 if (!D->isInvalidDecl() &&
23654 SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: D->getType()) &&
23655 !Type.isMoreQualifiedThan(other: D->getType(),
23656 Ctx: SemaRef.getASTContext()))
23657 return D;
23658 return nullptr;
23659 })) {
23660 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
23661 /*DetectVirtual=*/false);
23662 if (SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: VD->getType(), Paths)) {
23663 if (!Paths.isAmbiguous(BaseType: SemaRef.Context.getCanonicalType(
23664 T: VD->getType().getUnqualifiedType()))) {
23665 if (SemaRef.CheckBaseClassAccess(
23666 AccessLoc: Loc, Base: VD->getType(), Derived: Type, Path: Paths.front(),
23667 /*DiagID=*/0) != Sema::AR_inaccessible) {
23668 return SemaRef.BuildDeclRefExpr(D: VD, Ty: Type, VK: VK_LValue, Loc);
23669 }
23670 }
23671 }
23672 }
23673 // Report error if a mapper is specified, but cannot be found.
23674 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
23675 SemaRef.Diag(Loc, DiagID: diag::err_omp_invalid_mapper)
23676 << Type << MapperId.getName();
23677 return ExprError();
23678 }
23679 return ExprEmpty();
23680}
23681
23682namespace {
23683// Utility struct that gathers all the related lists associated with a mappable
23684// expression.
23685struct MappableVarListInfo {
23686 // The list of expressions.
23687 ArrayRef<Expr *> VarList;
23688 // The list of processed expressions.
23689 SmallVector<Expr *, 16> ProcessedVarList;
23690 // The mappble components for each expression.
23691 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
23692 // The base declaration of the variable.
23693 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
23694 // The reference to the user-defined mapper associated with every expression.
23695 SmallVector<Expr *, 16> UDMapperList;
23696
23697 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
23698 // We have a list of components and base declarations for each entry in the
23699 // variable list.
23700 VarComponents.reserve(N: VarList.size());
23701 VarBaseDeclarations.reserve(N: VarList.size());
23702 }
23703};
23704} // namespace
23705
23706static DeclRefExpr *buildImplicitMap(Sema &S, QualType BaseType,
23707 DSAStackTy *Stack,
23708 SmallVectorImpl<OMPClause *> &Maps) {
23709
23710 const RecordDecl *RD = BaseType->getAsRecordDecl();
23711 SourceRange Range = RD->getSourceRange();
23712 DeclarationNameInfo ImplicitName;
23713 // Dummy variable _s for Mapper.
23714 VarDecl *VD = buildVarDecl(SemaRef&: S, Loc: Range.getEnd(), Type: BaseType, Name: "_s");
23715 DeclRefExpr *MapperVarRef =
23716 buildDeclRefExpr(S, D: VD, Ty: BaseType, Loc: SourceLocation());
23717
23718 // Create implicit map clause for mapper.
23719 SmallVector<Expr *, 4> SExprs;
23720 for (auto *FD : RD->fields()) {
23721 Expr *BE = S.BuildMemberExpr(
23722 Base: MapperVarRef, /*IsArrow=*/false, OpLoc: Range.getBegin(),
23723 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: Range.getBegin(), Member: FD,
23724 FoundDecl: DeclAccessPair::make(D: FD, AS: FD->getAccess()),
23725 /*HadMultipleCandidates=*/false,
23726 MemberNameInfo: DeclarationNameInfo(FD->getDeclName(), FD->getSourceRange().getBegin()),
23727 Ty: FD->getType(), VK: VK_LValue, OK: OK_Ordinary);
23728 SExprs.push_back(Elt: BE);
23729 }
23730 CXXScopeSpec MapperIdScopeSpec;
23731 DeclarationNameInfo MapperId;
23732 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
23733
23734 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
23735 IteratorModifier: nullptr, MapTypeModifiers: OMPC_MAP_MODIFIER_unknown, MapTypeModifiersLoc: SourceLocation(), MapperIdScopeSpec,
23736 MapperId, MapType: DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
23737 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(), VarList: SExprs,
23738 Locs: OMPVarListLocTy());
23739 Maps.push_back(Elt: MapClause);
23740 return MapperVarRef;
23741}
23742
23743static ExprResult buildImplicitMapper(Sema &S, QualType BaseType,
23744 DSAStackTy *Stack) {
23745
23746 // Build impilicit map for mapper
23747 SmallVector<OMPClause *, 4> Maps;
23748 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
23749
23750 const RecordDecl *RD = BaseType->getAsRecordDecl();
23751 // AST context is RD's ParentASTContext().
23752 ASTContext &Ctx = RD->getParentASTContext();
23753 // DeclContext is RD's DeclContext.
23754 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
23755
23756 // Create implicit default mapper for "RD".
23757 DeclarationName MapperId;
23758 auto &DeclNames = Ctx.DeclarationNames;
23759 MapperId = DeclNames.getIdentifier(ID: &Ctx.Idents.get(Name: "default"));
23760 auto *DMD = OMPDeclareMapperDecl::Create(C&: Ctx, DC: DCT, L: SourceLocation(), Name: MapperId,
23761 T: BaseType, VarName: MapperId, Clauses: Maps, PrevDeclInScope: nullptr);
23762 Scope *Scope = S.getScopeForContext(Ctx: DCT);
23763 if (Scope)
23764 S.PushOnScopeChains(D: DMD, S: Scope, /*AddToContext=*/false);
23765 DCT->addDecl(D: DMD);
23766 DMD->setAccess(clang::AS_none);
23767 auto *VD = cast<DeclRefExpr>(Val: MapperVarRef)->getDecl();
23768 VD->setDeclContext(DMD);
23769 VD->setLexicalDeclContext(DMD);
23770 DMD->addDecl(D: VD);
23771 DMD->setMapperVarRef(MapperVarRef);
23772 FieldDecl *FD = *RD->field_begin();
23773 // create mapper refence.
23774 return DeclRefExpr::Create(Context: Ctx, QualifierLoc: NestedNameSpecifierLoc{}, TemplateKWLoc: FD->getLocation(),
23775 D: DMD, RefersToEnclosingVariableOrCapture: false, NameLoc: SourceLocation(), T: BaseType, VK: VK_LValue);
23776}
23777
23778// Look up the user-defined mapper given the mapper name and mapper type,
23779// return true if found one.
23780static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
23781 CXXScopeSpec &MapperIdScopeSpec,
23782 const DeclarationNameInfo &MapperId,
23783 QualType Type) {
23784 // Find all user-defined mappers with the given MapperId.
23785 SmallVector<UnresolvedSet<8>, 4> Lookups;
23786 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
23787 Lookup.suppressDiagnostics();
23788 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &MapperIdScopeSpec,
23789 /*ObjectType=*/QualType())) {
23790 NamedDecl *D = Lookup.getRepresentativeDecl();
23791 while (S && !S->isDeclScope(D))
23792 S = S->getParent();
23793 if (S)
23794 S = S->getParent();
23795 Lookups.emplace_back();
23796 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
23797 Lookup.clear();
23798 }
23799 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
23800 Type->isInstantiationDependentType() ||
23801 Type->containsUnexpandedParameterPack() ||
23802 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
23803 return !D->isInvalidDecl() &&
23804 (D->getType()->isDependentType() ||
23805 D->getType()->isInstantiationDependentType() ||
23806 D->getType()->containsUnexpandedParameterPack());
23807 }))
23808 return false;
23809 // Perform argument dependent lookup.
23810 SourceLocation Loc = MapperId.getLoc();
23811 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
23812 argumentDependentLookup(SemaRef, Id: MapperId, Loc, Ty: Type, Lookups);
23813 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
23814 Lookups, Gen: [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
23815 if (!D->isInvalidDecl() &&
23816 SemaRef.Context.hasSameType(T1: D->getType(), T2: Type))
23817 return D;
23818 return nullptr;
23819 }))
23820 return true;
23821 // Find the first user-defined mapper with a type derived from the desired
23822 // type.
23823 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
23824 Lookups, Gen: [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
23825 if (!D->isInvalidDecl() &&
23826 SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: D->getType()) &&
23827 !Type.isMoreQualifiedThan(other: D->getType(), Ctx: SemaRef.getASTContext()))
23828 return D;
23829 return nullptr;
23830 });
23831 if (!VD)
23832 return false;
23833 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
23834 /*DetectVirtual=*/false);
23835 if (SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: VD->getType(), Paths)) {
23836 bool IsAmbiguous = !Paths.isAmbiguous(
23837 BaseType: SemaRef.Context.getCanonicalType(T: VD->getType().getUnqualifiedType()));
23838 if (IsAmbiguous)
23839 return false;
23840 if (SemaRef.CheckBaseClassAccess(AccessLoc: Loc, Base: VD->getType(), Derived: Type, Path: Paths.front(),
23841 /*DiagID=*/0) != Sema::AR_inaccessible)
23842 return true;
23843 }
23844 return false;
23845}
23846
23847static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
23848 QualType CanonType, const Expr *E) {
23849
23850 // DFS over data members in structures/classes.
23851 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(1,
23852 {CanonType, nullptr});
23853 llvm::DenseMap<const Type *, bool> Visited;
23854 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
23855 while (!Types.empty()) {
23856 auto [BaseType, CurFD] = Types.pop_back_val();
23857 while (ParentChain.back().second == 0)
23858 ParentChain.pop_back();
23859 --ParentChain.back().second;
23860 if (BaseType.isNull())
23861 continue;
23862 // Only structs/classes are allowed to have mappers.
23863 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
23864 if (!RD)
23865 continue;
23866 auto It = Visited.find(Val: BaseType.getTypePtr());
23867 if (It == Visited.end()) {
23868 // Try to find the associated user-defined mapper.
23869 CXXScopeSpec MapperIdScopeSpec;
23870 DeclarationNameInfo DefaultMapperId;
23871 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
23872 ID: &S.Context.Idents.get(Name: "default")));
23873 DefaultMapperId.setLoc(E->getExprLoc());
23874 bool HasUDMapper =
23875 hasUserDefinedMapper(SemaRef&: S, S: Stack->getCurScope(), MapperIdScopeSpec,
23876 MapperId: DefaultMapperId, Type: BaseType);
23877 It = Visited.try_emplace(Key: BaseType.getTypePtr(), Args&: HasUDMapper).first;
23878 }
23879 // Found default mapper.
23880 if (It->second)
23881 return true;
23882 // Check for the "default" mapper for data members.
23883 bool FirstIter = true;
23884 for (FieldDecl *FD : RD->fields()) {
23885 if (!FD)
23886 continue;
23887 QualType FieldTy = FD->getType();
23888 if (FieldTy.isNull() ||
23889 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
23890 continue;
23891 if (FirstIter) {
23892 FirstIter = false;
23893 ParentChain.emplace_back(Args&: CurFD, Args: 1);
23894 } else {
23895 ++ParentChain.back().second;
23896 }
23897 Types.emplace_back(Args&: FieldTy, Args&: FD);
23898 }
23899 }
23900 return false;
23901}
23902
23903// Check the validity of the provided variable list for the provided clause kind
23904// \a CKind. In the check process the valid expressions, mappable expression
23905// components, variables, and user-defined mappers are extracted and used to
23906// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
23907// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
23908// and \a MapperId are expected to be valid if the clause kind is 'map'.
23909static void checkMappableExpressionList(
23910 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
23911 MappableVarListInfo &MVLI, SourceLocation StartLoc,
23912 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
23913 ArrayRef<Expr *> UnresolvedMappers,
23914 OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
23915 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
23916 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
23917 // We only expect mappable expressions in 'to', 'from', 'map', and
23918 // 'use_device_addr' clauses.
23919 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from ||
23920 CKind == OMPC_use_device_addr) &&
23921 "Unexpected clause kind with mappable expressions!");
23922 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
23923
23924 // If the identifier of user-defined mapper is not specified, it is "default".
23925 // We do not change the actual name in this clause to distinguish whether a
23926 // mapper is specified explicitly, i.e., it is not explicitly specified when
23927 // MapperId.getName() is empty.
23928 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
23929 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
23930 MapperId.setName(DeclNames.getIdentifier(
23931 ID: &SemaRef.getASTContext().Idents.get(Name: "default")));
23932 MapperId.setLoc(StartLoc);
23933 }
23934
23935 // Iterators to find the current unresolved mapper expression.
23936 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
23937 bool UpdateUMIt = false;
23938 Expr *UnresolvedMapper = nullptr;
23939
23940 bool HasHoldModifier =
23941 llvm::is_contained(Range&: Modifiers, Element: OMPC_MAP_MODIFIER_ompx_hold);
23942
23943 // Keep track of the mappable components and base declarations in this clause.
23944 // Each entry in the list is going to have a list of components associated. We
23945 // record each set of the components so that we can build the clause later on.
23946 // In the end we should have the same amount of declarations and component
23947 // lists.
23948
23949 for (Expr *RE : MVLI.VarList) {
23950 assert(RE && "Null expr in omp to/from/map clause");
23951 SourceLocation ELoc = RE->getExprLoc();
23952
23953 // Find the current unresolved mapper expression.
23954 if (UpdateUMIt && UMIt != UMEnd) {
23955 UMIt++;
23956 assert(
23957 UMIt != UMEnd &&
23958 "Expect the size of UnresolvedMappers to match with that of VarList");
23959 }
23960 UpdateUMIt = true;
23961 if (UMIt != UMEnd)
23962 UnresolvedMapper = *UMIt;
23963
23964 const Expr *VE = RE->IgnoreParenLValueCasts();
23965
23966 if (VE->isValueDependent() || VE->isTypeDependent() ||
23967 VE->isInstantiationDependent() ||
23968 VE->containsUnexpandedParameterPack()) {
23969 // Try to find the associated user-defined mapper.
23970 ExprResult ER = buildUserDefinedMapperRef(
23971 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23972 Type: VE->getType().getCanonicalType(), UnresolvedMapper);
23973 if (ER.isInvalid())
23974 continue;
23975 MVLI.UDMapperList.push_back(Elt: ER.get());
23976 // We can only analyze this information once the missing information is
23977 // resolved.
23978 MVLI.ProcessedVarList.push_back(Elt: RE);
23979 continue;
23980 }
23981
23982 Expr *SimpleExpr = RE->IgnoreParenCasts();
23983
23984 if (!RE->isLValue()) {
23985 if (SemaRef.getLangOpts().OpenMP < 50) {
23986 SemaRef.Diag(
23987 Loc: ELoc, DiagID: diag::err_omp_expected_named_var_member_or_array_expression)
23988 << RE->getSourceRange();
23989 } else {
23990 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_non_lvalue_in_map_or_motion_clauses)
23991 << getOpenMPClauseNameForDiag(C: CKind) << RE->getSourceRange();
23992 }
23993 continue;
23994 }
23995
23996 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
23997 ValueDecl *CurDeclaration = nullptr;
23998
23999 // Obtain the array or member expression bases if required. Also, fill the
24000 // components array with all the components identified in the process.
24001 const Expr *BE =
24002 checkMapClauseExpressionBase(SemaRef, E: SimpleExpr, CurComponents, CKind,
24003 DKind: DSAS->getCurrentDirective(), NoDiagnose);
24004 if (!BE)
24005 continue;
24006
24007 assert(!CurComponents.empty() &&
24008 "Invalid mappable expression information.");
24009
24010 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: BE)) {
24011 // Add store "this" pointer to class in DSAStackTy for future checking
24012 DSAS->addMappedClassesQualTypes(QT: TE->getType());
24013 // Try to find the associated user-defined mapper.
24014 ExprResult ER = buildUserDefinedMapperRef(
24015 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
24016 Type: VE->getType().getCanonicalType(), UnresolvedMapper);
24017 if (ER.isInvalid())
24018 continue;
24019 MVLI.UDMapperList.push_back(Elt: ER.get());
24020 // Skip restriction checking for variable or field declarations
24021 MVLI.ProcessedVarList.push_back(Elt: RE);
24022 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
24023 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
24024 in_end: CurComponents.end());
24025 MVLI.VarBaseDeclarations.push_back(Elt: nullptr);
24026 continue;
24027 }
24028
24029 // For the following checks, we rely on the base declaration which is
24030 // expected to be associated with the last component. The declaration is
24031 // expected to be a variable or a field (if 'this' is being mapped).
24032 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
24033 assert(CurDeclaration && "Null decl on map clause.");
24034 assert(
24035 CurDeclaration->isCanonicalDecl() &&
24036 "Expecting components to have associated only canonical declarations.");
24037
24038 auto *VD = dyn_cast<VarDecl>(Val: CurDeclaration);
24039 const auto *FD = dyn_cast<FieldDecl>(Val: CurDeclaration);
24040
24041 assert((VD || FD) && "Only variables or fields are expected here!");
24042 (void)FD;
24043
24044 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
24045 // threadprivate variables cannot appear in a map clause.
24046 // OpenMP 4.5 [2.10.5, target update Construct]
24047 // threadprivate variables cannot appear in a from clause.
24048 if (VD && DSAS->isThreadPrivate(D: VD)) {
24049 if (NoDiagnose)
24050 continue;
24051 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(D: VD, /*FromParent=*/false);
24052 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_threadprivate_in_clause)
24053 << getOpenMPClauseNameForDiag(C: CKind);
24054 reportOriginalDsa(SemaRef, Stack: DSAS, D: VD, DVar);
24055 continue;
24056 }
24057
24058 // OpenMP 6.0 [7.9.6, map Clause, Restrictions, p. 386]
24059 // A device-local variable must not appear as a list item in a map clause.
24060 if (VD && CKind == OMPC_map) {
24061 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
24062 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
24063 if (*Res == OMPDeclareTargetDeclAttr::MT_Local) {
24064 if (NoDiagnose)
24065 continue;
24066 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_device_local_in_clause)
24067 << VD << getOpenMPClauseNameForDiag(C: CKind);
24068 continue;
24069 }
24070 }
24071 }
24072
24073 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
24074 // A list item cannot appear in both a map clause and a data-sharing
24075 // attribute clause on the same construct.
24076
24077 // Check conflicts with other map clause expressions. We check the conflicts
24078 // with the current construct separately from the enclosing data
24079 // environment, because the restrictions are different. We only have to
24080 // check conflicts across regions for the map clauses.
24081 if (checkMapConflicts(SemaRef, DSAS, VD: CurDeclaration, E: SimpleExpr,
24082 /*CurrentRegionOnly=*/true, CurComponents, CKind))
24083 break;
24084 if (CKind == OMPC_map &&
24085 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
24086 checkMapConflicts(SemaRef, DSAS, VD: CurDeclaration, E: SimpleExpr,
24087 /*CurrentRegionOnly=*/false, CurComponents, CKind))
24088 break;
24089
24090 // OpenMP 4.5 [2.10.5, target update Construct]
24091 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
24092 // If the type of a list item is a reference to a type T then the type will
24093 // be considered to be T for all purposes of this clause.
24094 auto I = llvm::find_if(
24095 Range&: CurComponents,
24096 P: [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
24097 return MC.getAssociatedDeclaration();
24098 });
24099 assert(I != CurComponents.end() && "Null decl on map clause.");
24100 (void)I;
24101 QualType Type;
24102 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: VE->IgnoreParens());
24103 auto *OASE = dyn_cast<ArraySectionExpr>(Val: VE->IgnoreParens());
24104 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(Val: VE->IgnoreParens());
24105 if (ASE) {
24106 Type = ASE->getType().getNonReferenceType();
24107 } else if (OASE) {
24108 QualType BaseType =
24109 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
24110 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
24111 Type = ATy->getElementType();
24112 else
24113 Type = BaseType->getPointeeType();
24114 Type = Type.getNonReferenceType();
24115 } else if (OAShE) {
24116 Type = OAShE->getBase()->getType()->getPointeeType();
24117 } else {
24118 Type = VE->getType();
24119 }
24120
24121 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
24122 // A list item in a to or from clause must have a mappable type.
24123 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
24124 // A list item must have a mappable type.
24125 if (!checkTypeMappable(SL: VE->getExprLoc(), SR: VE->getSourceRange(), SemaRef,
24126 Stack: DSAS, QTy: Type, /*FullCheck=*/true))
24127 continue;
24128
24129 if (CKind == OMPC_map) {
24130 // target enter data
24131 // OpenMP [2.10.2, Restrictions, p. 99]
24132 // A map-type must be specified in all map clauses and must be either
24133 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
24134 // no map type is present.
24135 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
24136 if (DKind == OMPD_target_enter_data &&
24137 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
24138 SemaRef.getLangOpts().OpenMP >= 52)) {
24139 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
24140 << (IsMapTypeImplicit ? 1 : 0)
24141 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
24142 << getOpenMPDirectiveName(D: DKind, V: OMPVersion);
24143 continue;
24144 }
24145
24146 // target exit_data
24147 // OpenMP [2.10.3, Restrictions, p. 102]
24148 // A map-type must be specified in all map clauses and must be either
24149 // from, release, or delete. Starting with OpenMP 5.2 the default map
24150 // type is `from` if no map type is present.
24151 if (DKind == OMPD_target_exit_data &&
24152 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
24153 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
24154 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
24155 << (IsMapTypeImplicit ? 1 : 0)
24156 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
24157 << getOpenMPDirectiveName(D: DKind, V: OMPVersion);
24158 continue;
24159 }
24160
24161 // The 'ompx_hold' modifier is specifically intended to be used on a
24162 // 'target' or 'target data' directive to prevent data from being unmapped
24163 // during the associated statement. It is not permitted on a 'target
24164 // enter data' or 'target exit data' directive, which have no associated
24165 // statement.
24166 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
24167 HasHoldModifier) {
24168 SemaRef.Diag(Loc: StartLoc,
24169 DiagID: diag::err_omp_invalid_map_type_modifier_for_directive)
24170 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map,
24171 Type: OMPC_MAP_MODIFIER_ompx_hold)
24172 << getOpenMPDirectiveName(D: DKind, V: OMPVersion);
24173 continue;
24174 }
24175
24176 // target, target data
24177 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
24178 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
24179 // A map-type in a map clause must be to, from, tofrom or alloc
24180 if ((DKind == OMPD_target_data ||
24181 isOpenMPTargetExecutionDirective(DKind)) &&
24182 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
24183 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
24184 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
24185 << (IsMapTypeImplicit ? 1 : 0)
24186 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
24187 << getOpenMPDirectiveName(D: DKind, V: OMPVersion);
24188 continue;
24189 }
24190
24191 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
24192 // A list item cannot appear in both a map clause and a data-sharing
24193 // attribute clause on the same construct
24194 //
24195 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
24196 // A list item cannot appear in both a map clause and a data-sharing
24197 // attribute clause on the same construct unless the construct is a
24198 // combined construct.
24199 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
24200 isOpenMPTargetExecutionDirective(DKind)) ||
24201 DKind == OMPD_target)) {
24202 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(D: VD, /*FromParent=*/false);
24203 if (isOpenMPPrivate(Kind: DVar.CKind)) {
24204 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
24205 << getOpenMPClauseNameForDiag(C: DVar.CKind)
24206 << getOpenMPClauseNameForDiag(C: OMPC_map)
24207 << getOpenMPDirectiveName(D: DSAS->getCurrentDirective(),
24208 V: OMPVersion);
24209 reportOriginalDsa(SemaRef, Stack: DSAS, D: CurDeclaration, DVar);
24210 continue;
24211 }
24212 }
24213 }
24214
24215 // Try to find the associated user-defined mapper.
24216 ExprResult ER = buildUserDefinedMapperRef(
24217 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
24218 Type: Type.getCanonicalType(), UnresolvedMapper);
24219 if (ER.isInvalid())
24220 continue;
24221
24222 // If no user-defined mapper is found, we need to create an implicit one for
24223 // arrays/array-sections on structs that have members that have
24224 // user-defined mappers. This is needed to ensure that the mapper for the
24225 // member is invoked when mapping each element of the array/array-section.
24226 if (!ER.get()) {
24227 QualType BaseType;
24228
24229 if (isa<ArraySectionExpr>(Val: VE)) {
24230 BaseType = VE->getType().getCanonicalType();
24231 if (BaseType->isSpecificBuiltinType(K: BuiltinType::ArraySection)) {
24232 const auto *OASE = cast<ArraySectionExpr>(Val: VE->IgnoreParenImpCasts());
24233 QualType BType =
24234 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
24235 QualType ElemType;
24236 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
24237 ElemType = ATy->getElementType();
24238 else
24239 ElemType = BType->getPointeeType();
24240 BaseType = ElemType.getCanonicalType();
24241 }
24242 } else if (VE->getType()->isArrayType()) {
24243 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
24244 const QualType ElemType = AT->getElementType();
24245 BaseType = ElemType.getCanonicalType();
24246 }
24247
24248 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
24249 isImplicitMapperNeeded(S&: SemaRef, Stack: DSAS, CanonType: BaseType, E: VE)) {
24250 ER = buildImplicitMapper(S&: SemaRef, BaseType, Stack: DSAS);
24251 }
24252 }
24253 MVLI.UDMapperList.push_back(Elt: ER.get());
24254
24255 // Save the current expression.
24256 MVLI.ProcessedVarList.push_back(Elt: RE);
24257
24258 // Store the components in the stack so that they can be used to check
24259 // against other clauses later on.
24260 DSAS->addMappableExpressionComponents(VD: CurDeclaration, Components: CurComponents,
24261 /*WhereFoundClauseKind=*/OMPC_map);
24262
24263 // Save the components and declaration to create the clause. For purposes of
24264 // the clause creation, any component list that has base 'this' uses
24265 // null as base declaration.
24266 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
24267 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
24268 in_end: CurComponents.end());
24269 MVLI.VarBaseDeclarations.push_back(Elt: isa<MemberExpr>(Val: BE) ? nullptr
24270 : CurDeclaration);
24271 }
24272}
24273
24274OMPClause *SemaOpenMP::ActOnOpenMPMapClause(
24275 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
24276 ArrayRef<SourceLocation> MapTypeModifiersLoc,
24277 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
24278 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
24279 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
24280 const OMPVarListLocTy &Locs, bool NoDiagnose,
24281 ArrayRef<Expr *> UnresolvedMappers) {
24282 OpenMPMapModifierKind Modifiers[] = {
24283 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
24284 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
24285 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
24286 OMPC_MAP_MODIFIER_unknown};
24287 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
24288
24289 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
24290 K: BuiltinType::OMPIterator))
24291 Diag(Loc: IteratorModifier->getExprLoc(),
24292 DiagID: diag::err_omp_map_modifier_not_iterator);
24293
24294 // Process map-type-modifiers, flag errors for duplicate modifiers.
24295 unsigned Count = 0;
24296 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
24297 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
24298 llvm::is_contained(Range&: Modifiers, Element: MapTypeModifiers[I])) {
24299 Diag(Loc: MapTypeModifiersLoc[I], DiagID: diag::err_omp_duplicate_map_type_modifier);
24300 continue;
24301 }
24302 assert(Count < NumberOfOMPMapClauseModifiers &&
24303 "Modifiers exceed the allowed number of map type modifiers");
24304 Modifiers[Count] = MapTypeModifiers[I];
24305 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
24306 ++Count;
24307 }
24308
24309 MappableVarListInfo MVLI(VarList);
24310 // Per OpenMP 6.0 p299 lines 3-4, a list item with the const specifier and
24311 // no mutable members is ignored for 'from' clauses. A const-qualified
24312 // variable cannot be modified on the device, so copying back to the host
24313 // is unnecessary and potentially unsafe. Strip the FROM component:
24314 // map(tofrom:) -> map(to:), map(from:) -> map(alloc:).
24315 for (auto *E : VarList) {
24316 if ((MapType == OMPC_MAP_from || MapType == OMPC_MAP_tofrom) &&
24317 hasConstQualifiedMappingType(T: E->getType()))
24318 MapType = (MapType == OMPC_MAP_tofrom) ? OMPC_MAP_to : OMPC_MAP_alloc;
24319 }
24320 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_map, MVLI, StartLoc: Locs.StartLoc,
24321 MapperIdScopeSpec, MapperId, UnresolvedMappers,
24322 MapType, Modifiers, IsMapTypeImplicit,
24323 NoDiagnose);
24324
24325 // We need to produce a map clause even if we don't have variables so that
24326 // other diagnostics related with non-existing map clauses are accurate.
24327 return OMPMapClause::Create(
24328 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
24329 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, IteratorModifier, MapModifiers: Modifiers,
24330 MapModifiersLoc: ModifiersLoc, UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()),
24331 MapperId, Type: MapType, TypeIsImplicit: IsMapTypeImplicit, TypeLoc: MapLoc);
24332}
24333
24334QualType SemaOpenMP::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
24335 TypeResult ParsedType) {
24336 assert(ParsedType.isUsable());
24337
24338 QualType ReductionType = SemaRef.GetTypeFromParser(Ty: ParsedType.get());
24339 if (ReductionType.isNull())
24340 return QualType();
24341
24342 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
24343 // A type name in a declare reduction directive cannot be a function type, an
24344 // array type, a reference type, or a type qualified with const, volatile or
24345 // restrict.
24346 if (ReductionType.hasQualifiers()) {
24347 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 0;
24348 return QualType();
24349 }
24350
24351 if (ReductionType->isFunctionType()) {
24352 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 1;
24353 return QualType();
24354 }
24355 if (ReductionType->isReferenceType()) {
24356 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 2;
24357 return QualType();
24358 }
24359 if (ReductionType->isArrayType()) {
24360 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 3;
24361 return QualType();
24362 }
24363 return ReductionType;
24364}
24365
24366SemaOpenMP::DeclGroupPtrTy
24367SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveStart(
24368 Scope *S, DeclContext *DC, DeclarationName Name,
24369 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
24370 AccessSpecifier AS, Decl *PrevDeclInScope) {
24371 SmallVector<Decl *, 8> Decls;
24372 Decls.reserve(N: ReductionTypes.size());
24373
24374 LookupResult Lookup(SemaRef, Name, SourceLocation(),
24375 Sema::LookupOMPReductionName,
24376 SemaRef.forRedeclarationInCurContext());
24377 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
24378 // A reduction-identifier may not be re-declared in the current scope for the
24379 // same type or for a type that is compatible according to the base language
24380 // rules.
24381 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
24382 OMPDeclareReductionDecl *PrevDRD = nullptr;
24383 bool InCompoundScope = true;
24384 if (S != nullptr) {
24385 // Find previous declaration with the same name not referenced in other
24386 // declarations.
24387 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
24388 InCompoundScope =
24389 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
24390 SemaRef.LookupName(R&: Lookup, S);
24391 SemaRef.FilterLookupForScope(R&: Lookup, Ctx: DC, S, /*ConsiderLinkage=*/false,
24392 /*AllowInlineNamespace=*/false);
24393 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
24394 LookupResult::Filter Filter = Lookup.makeFilter();
24395 while (Filter.hasNext()) {
24396 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Val: Filter.next());
24397 if (InCompoundScope) {
24398 UsedAsPrevious.try_emplace(Key: PrevDecl, Args: false);
24399 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
24400 UsedAsPrevious[D] = true;
24401 }
24402 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
24403 PrevDecl->getLocation();
24404 }
24405 Filter.done();
24406 if (InCompoundScope) {
24407 for (const auto &PrevData : UsedAsPrevious) {
24408 if (!PrevData.second) {
24409 PrevDRD = PrevData.first;
24410 break;
24411 }
24412 }
24413 }
24414 } else if (PrevDeclInScope != nullptr) {
24415 auto *PrevDRDInScope = PrevDRD =
24416 cast<OMPDeclareReductionDecl>(Val: PrevDeclInScope);
24417 do {
24418 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
24419 PrevDRDInScope->getLocation();
24420 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
24421 } while (PrevDRDInScope != nullptr);
24422 }
24423 for (const auto &TyData : ReductionTypes) {
24424 const auto I = PreviousRedeclTypes.find(Val: TyData.first.getCanonicalType());
24425 bool Invalid = false;
24426 if (I != PreviousRedeclTypes.end()) {
24427 Diag(Loc: TyData.second, DiagID: diag::err_omp_declare_reduction_redefinition)
24428 << TyData.first;
24429 Diag(Loc: I->second, DiagID: diag::note_previous_definition);
24430 Invalid = true;
24431 }
24432 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
24433 auto *DRD = OMPDeclareReductionDecl::Create(
24434 C&: getASTContext(), DC, L: TyData.second, Name, T: TyData.first, PrevDeclInScope: PrevDRD);
24435 DC->addDecl(D: DRD);
24436 DRD->setAccess(AS);
24437 Decls.push_back(Elt: DRD);
24438 if (Invalid)
24439 DRD->setInvalidDecl();
24440 else
24441 PrevDRD = DRD;
24442 }
24443
24444 return DeclGroupPtrTy::make(
24445 P: DeclGroupRef::Create(C&: getASTContext(), Decls: Decls.begin(), NumDecls: Decls.size()));
24446}
24447
24448void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
24449 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
24450
24451 // Enter new function scope.
24452 SemaRef.PushFunctionScope();
24453 SemaRef.setFunctionHasBranchProtectedScope();
24454 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
24455
24456 if (S != nullptr)
24457 SemaRef.PushDeclContext(S, DC: DRD);
24458 else
24459 SemaRef.CurContext = DRD;
24460
24461 SemaRef.PushExpressionEvaluationContext(
24462 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
24463
24464 QualType ReductionType = DRD->getType();
24465 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
24466 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
24467 // uses semantics of argument handles by value, but it should be passed by
24468 // reference. C lang does not support references, so pass all parameters as
24469 // pointers.
24470 // Create 'T omp_in;' variable.
24471 VarDecl *OmpInParm =
24472 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_in");
24473 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
24474 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
24475 // uses semantics of argument handles by value, but it should be passed by
24476 // reference. C lang does not support references, so pass all parameters as
24477 // pointers.
24478 // Create 'T omp_out;' variable.
24479 VarDecl *OmpOutParm =
24480 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_out");
24481 if (S != nullptr) {
24482 SemaRef.PushOnScopeChains(D: OmpInParm, S);
24483 SemaRef.PushOnScopeChains(D: OmpOutParm, S);
24484 } else {
24485 DRD->addDecl(D: OmpInParm);
24486 DRD->addDecl(D: OmpOutParm);
24487 }
24488 Expr *InE =
24489 ::buildDeclRefExpr(S&: SemaRef, D: OmpInParm, Ty: ReductionType, Loc: D->getLocation());
24490 Expr *OutE =
24491 ::buildDeclRefExpr(S&: SemaRef, D: OmpOutParm, Ty: ReductionType, Loc: D->getLocation());
24492 DRD->setCombinerData(InE, OutE);
24493}
24494
24495void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D,
24496 Expr *Combiner) {
24497 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
24498 SemaRef.DiscardCleanupsInEvaluationContext();
24499 SemaRef.PopExpressionEvaluationContext();
24500
24501 SemaRef.PopDeclContext();
24502 SemaRef.PopFunctionScopeInfo();
24503
24504 if (Combiner != nullptr)
24505 DRD->setCombiner(Combiner);
24506 else
24507 DRD->setInvalidDecl();
24508}
24509
24510VarDecl *SemaOpenMP::ActOnOpenMPDeclareReductionInitializerStart(Scope *S,
24511 Decl *D) {
24512 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
24513
24514 // Enter new function scope.
24515 SemaRef.PushFunctionScope();
24516 SemaRef.setFunctionHasBranchProtectedScope();
24517
24518 if (S != nullptr)
24519 SemaRef.PushDeclContext(S, DC: DRD);
24520 else
24521 SemaRef.CurContext = DRD;
24522
24523 SemaRef.PushExpressionEvaluationContext(
24524 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
24525
24526 QualType ReductionType = DRD->getType();
24527 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
24528 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
24529 // uses semantics of argument handles by value, but it should be passed by
24530 // reference. C lang does not support references, so pass all parameters as
24531 // pointers.
24532 // Create 'T omp_priv;' variable.
24533 VarDecl *OmpPrivParm =
24534 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_priv");
24535 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
24536 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
24537 // uses semantics of argument handles by value, but it should be passed by
24538 // reference. C lang does not support references, so pass all parameters as
24539 // pointers.
24540 // Create 'T omp_orig;' variable.
24541 VarDecl *OmpOrigParm =
24542 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_orig");
24543 if (S != nullptr) {
24544 SemaRef.PushOnScopeChains(D: OmpPrivParm, S);
24545 SemaRef.PushOnScopeChains(D: OmpOrigParm, S);
24546 } else {
24547 DRD->addDecl(D: OmpPrivParm);
24548 DRD->addDecl(D: OmpOrigParm);
24549 }
24550 Expr *OrigE =
24551 ::buildDeclRefExpr(S&: SemaRef, D: OmpOrigParm, Ty: ReductionType, Loc: D->getLocation());
24552 Expr *PrivE =
24553 ::buildDeclRefExpr(S&: SemaRef, D: OmpPrivParm, Ty: ReductionType, Loc: D->getLocation());
24554 DRD->setInitializerData(OrigE, PrivE);
24555 return OmpPrivParm;
24556}
24557
24558void SemaOpenMP::ActOnOpenMPDeclareReductionInitializerEnd(
24559 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
24560 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
24561 SemaRef.DiscardCleanupsInEvaluationContext();
24562 SemaRef.PopExpressionEvaluationContext();
24563
24564 SemaRef.PopDeclContext();
24565 SemaRef.PopFunctionScopeInfo();
24566
24567 if (Initializer != nullptr) {
24568 DRD->setInitializer(E: Initializer, IK: OMPDeclareReductionInitKind::Call);
24569 } else if (OmpPrivParm->hasInit()) {
24570 DRD->setInitializer(E: OmpPrivParm->getInit(),
24571 IK: OmpPrivParm->isDirectInit()
24572 ? OMPDeclareReductionInitKind::Direct
24573 : OMPDeclareReductionInitKind::Copy);
24574 } else {
24575 DRD->setInvalidDecl();
24576 }
24577}
24578
24579SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveEnd(
24580 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
24581 for (Decl *D : DeclReductions.get()) {
24582 if (IsValid) {
24583 if (S)
24584 SemaRef.PushOnScopeChains(D: cast<OMPDeclareReductionDecl>(Val: D), S,
24585 /*AddToContext=*/false);
24586 } else {
24587 D->setInvalidDecl();
24588 }
24589 }
24590 return DeclReductions;
24591}
24592
24593TypeResult SemaOpenMP::ActOnOpenMPDeclareMapperVarDecl(Scope *S,
24594 Declarator &D) {
24595 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
24596 QualType T = TInfo->getType();
24597 if (D.isInvalidType())
24598 return true;
24599
24600 if (getLangOpts().CPlusPlus) {
24601 // Check that there are no default arguments (C++ only).
24602 SemaRef.CheckExtraCXXDefaultArguments(D);
24603 }
24604
24605 return SemaRef.CreateParsedType(T, TInfo);
24606}
24607
24608QualType SemaOpenMP::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
24609 TypeResult ParsedType) {
24610 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
24611
24612 QualType MapperType = SemaRef.GetTypeFromParser(Ty: ParsedType.get());
24613 assert(!MapperType.isNull() && "Expect valid mapper type");
24614
24615 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
24616 // The type must be of struct, union or class type in C and C++
24617 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
24618 Diag(Loc: TyLoc, DiagID: diag::err_omp_mapper_wrong_type);
24619 return QualType();
24620 }
24621 return MapperType;
24622}
24623
24624SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareMapperDirective(
24625 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
24626 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
24627 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
24628 LookupResult Lookup(SemaRef, Name, SourceLocation(),
24629 Sema::LookupOMPMapperName,
24630 SemaRef.forRedeclarationInCurContext());
24631 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
24632 // A mapper-identifier may not be redeclared in the current scope for the
24633 // same type or for a type that is compatible according to the base language
24634 // rules.
24635 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
24636 OMPDeclareMapperDecl *PrevDMD = nullptr;
24637 bool InCompoundScope = true;
24638 if (S != nullptr) {
24639 // Find previous declaration with the same name not referenced in other
24640 // declarations.
24641 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
24642 InCompoundScope =
24643 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
24644 SemaRef.LookupName(R&: Lookup, S);
24645 SemaRef.FilterLookupForScope(R&: Lookup, Ctx: DC, S, /*ConsiderLinkage=*/false,
24646 /*AllowInlineNamespace=*/false);
24647 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
24648 LookupResult::Filter Filter = Lookup.makeFilter();
24649 while (Filter.hasNext()) {
24650 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Val: Filter.next());
24651 if (InCompoundScope) {
24652 UsedAsPrevious.try_emplace(Key: PrevDecl, Args: false);
24653 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
24654 UsedAsPrevious[D] = true;
24655 }
24656 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
24657 PrevDecl->getLocation();
24658 }
24659 Filter.done();
24660 if (InCompoundScope) {
24661 for (const auto &PrevData : UsedAsPrevious) {
24662 if (!PrevData.second) {
24663 PrevDMD = PrevData.first;
24664 break;
24665 }
24666 }
24667 }
24668 } else if (PrevDeclInScope) {
24669 auto *PrevDMDInScope = PrevDMD =
24670 cast<OMPDeclareMapperDecl>(Val: PrevDeclInScope);
24671 do {
24672 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
24673 PrevDMDInScope->getLocation();
24674 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
24675 } while (PrevDMDInScope != nullptr);
24676 }
24677 const auto I = PreviousRedeclTypes.find(Val: MapperType.getCanonicalType());
24678 bool Invalid = false;
24679 if (I != PreviousRedeclTypes.end()) {
24680 Diag(Loc: StartLoc, DiagID: diag::err_omp_declare_mapper_redefinition)
24681 << MapperType << Name;
24682 Diag(Loc: I->second, DiagID: diag::note_previous_definition);
24683 Invalid = true;
24684 }
24685 // Build expressions for implicit maps of data members with 'default'
24686 // mappers.
24687 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
24688 if (getLangOpts().OpenMP >= 50)
24689 processImplicitMapsWithDefaultMappers(S&: SemaRef, DSAStack,
24690 Clauses&: ClausesWithImplicit);
24691 auto *DMD = OMPDeclareMapperDecl::Create(C&: getASTContext(), DC, L: StartLoc, Name,
24692 T: MapperType, VarName: VN, Clauses: ClausesWithImplicit,
24693 PrevDeclInScope: PrevDMD);
24694 if (S)
24695 SemaRef.PushOnScopeChains(D: DMD, S);
24696 else
24697 DC->addDecl(D: DMD);
24698 DMD->setAccess(AS);
24699 if (Invalid)
24700 DMD->setInvalidDecl();
24701
24702 auto *VD = cast<DeclRefExpr>(Val: MapperVarRef)->getDecl();
24703 VD->setDeclContext(DMD);
24704 VD->setLexicalDeclContext(DMD);
24705 DMD->addDecl(D: VD);
24706 DMD->setMapperVarRef(MapperVarRef);
24707
24708 return DeclGroupPtrTy::make(P: DeclGroupRef(DMD));
24709}
24710
24711ExprResult SemaOpenMP::ActOnOpenMPDeclareMapperDirectiveVarDecl(
24712 Scope *S, QualType MapperType, SourceLocation StartLoc,
24713 DeclarationName VN) {
24714 TypeSourceInfo *TInfo =
24715 getASTContext().getTrivialTypeSourceInfo(T: MapperType, Loc: StartLoc);
24716 auto *VD = VarDecl::Create(
24717 C&: getASTContext(), DC: getASTContext().getTranslationUnitDecl(), StartLoc,
24718 IdLoc: StartLoc, Id: VN.getAsIdentifierInfo(), T: MapperType, TInfo, S: SC_None);
24719 if (S)
24720 SemaRef.PushOnScopeChains(D: VD, S, /*AddToContext=*/false);
24721 Expr *E = buildDeclRefExpr(S&: SemaRef, D: VD, Ty: MapperType, Loc: StartLoc);
24722 DSAStack->addDeclareMapperVarRef(Ref: E);
24723 return E;
24724}
24725
24726void SemaOpenMP::ActOnOpenMPIteratorVarDecl(VarDecl *VD) {
24727 bool IsGlobalVar =
24728 !VD->isLocalVarDecl() && VD->getDeclContext()->isTranslationUnit();
24729 if (DSAStack->getDeclareMapperVarRef()) {
24730 if (IsGlobalVar)
24731 SemaRef.Consumer.HandleTopLevelDecl(D: DeclGroupRef(VD));
24732 DSAStack->addIteratorVarDecl(VD);
24733 } else {
24734 // Currently, only declare mapper handles global-scope iterator vars.
24735 assert(!IsGlobalVar && "Only declare mapper handles TU-scope iterators.");
24736 }
24737}
24738
24739bool SemaOpenMP::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
24740 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
24741 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
24742 if (const auto *DRE = cast_or_null<DeclRefExpr>(Val: Ref)) {
24743 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
24744 return true;
24745 if (VD->isUsableInConstantExpressions(C: getASTContext()))
24746 return true;
24747 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
24748 return true;
24749 return false;
24750 }
24751 return true;
24752}
24753
24754const ValueDecl *SemaOpenMP::getOpenMPDeclareMapperVarName() const {
24755 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
24756 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
24757}
24758
24759ExprResult SemaOpenMP::ActOnOpenMPDimsModifier(OpenMPClauseKind ClauseKind,
24760 int Modifier, Expr *ModifierExpr,
24761 SourceLocation ModifierLoc,
24762 ArrayRef<Expr *> VarList,
24763 SourceLocation VarListEndLoc) {
24764 assert(ModifierExpr && "Unexpected modifier expression.");
24765
24766 if (getLangOpts().OpenMP < 61) {
24767 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_modifier_requires_version)
24768 << getOpenMPSimpleClauseTypeName(Kind: ClauseKind, Type: Modifier)
24769 << getOpenMPClauseName(C: ClauseKind) << "6.1";
24770 return ExprError();
24771 }
24772
24773 ExprResult DimsRes = VerifyPositiveIntegerConstantInClause(
24774 E: ModifierExpr, CKind: ClauseKind, /*StrictlyPositive=*/true,
24775 /*SuppressExprDiags=*/false);
24776 if (DimsRes.isInvalid())
24777 return ExprError();
24778
24779 ModifierExpr = DimsRes.get();
24780 if (ModifierExpr->isInstantiationDependent())
24781 return DimsRes;
24782
24783 uint64_t NumDims =
24784 ModifierExpr->EvaluateKnownConstInt(Ctx: getASTContext()).getExtValue();
24785 if (NumDims == VarList.size())
24786 return DimsRes;
24787
24788 Diag(Loc: VarListEndLoc, DiagID: diag::err_omp_unexpected_num_exprs)
24789 << getOpenMPClauseName(C: ClauseKind) << NumDims << VarList.size();
24790 return ExprError();
24791}
24792
24793OMPClause *SemaOpenMP::ActOnOpenMPNumTeamsClause(
24794 ArrayRef<Expr *> VarList, OpenMPNumTeamsClauseModifier Modifier,
24795 Expr *ModifierExpr, SourceLocation ModifierLoc,
24796 OpenMPNumTeamsClauseModifier ModifierExtra, Expr *,
24797 SourceLocation ModifierExtraLoc, SourceLocation StartLoc,
24798 SourceLocation LParenLoc, SourceLocation EndLoc) {
24799 if (VarList.empty())
24800 return nullptr;
24801
24802 for (Expr *ValExpr : VarList) {
24803 // OpenMP [teams Construct, Restrictions]
24804 // The num_teams expression must evaluate to a positive integer value.
24805 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_num_teams,
24806 /*StrictlyPositive=*/true))
24807 return nullptr;
24808 }
24809
24810 // OpenMP [teams Construct, Restrictions]
24811 // The lower-bound modifier cannot be specified if the dims modifier is
24812 // specified.
24813 if (Modifier != OMPC_NUMTEAMS_unknown &&
24814 ModifierExtra != OMPC_NUMTEAMS_unknown) {
24815 Diag(Loc: ModifierExtraLoc, DiagID: diag::err_omp_incompatible_modifiers)
24816 << getOpenMPSimpleClauseTypeName(Kind: llvm::omp::OMPC_num_teams,
24817 Type: ModifierExtra)
24818 << getOpenMPSimpleClauseTypeName(Kind: llvm::omp::OMPC_num_teams, Type: Modifier)
24819 << getOpenMPClauseName(C: llvm::omp::OMPC_num_teams);
24820 ModifierExtra = OMPC_NUMTEAMS_unknown;
24821 ModifierExtraLoc = SourceLocation();
24822 }
24823
24824 if (Modifier == OMPC_NUMTEAMS_dims) {
24825 ExprResult Res = ActOnOpenMPDimsModifier(
24826 ClauseKind: OMPC_num_teams, Modifier, ModifierExpr, ModifierLoc, VarList, VarListEndLoc: EndLoc);
24827 if (Res.isInvalid())
24828 return nullptr;
24829 ModifierExpr = Res.get();
24830 } else if (Modifier == OMPC_NUMTEAMS_lower_bound) {
24831 assert(ModifierExpr && "Unexpected modifier expression.");
24832
24833 if (getLangOpts().OpenMP < 51) {
24834 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_modifier_requires_version)
24835 << getOpenMPSimpleClauseTypeName(Kind: llvm::omp::OMPC_num_teams, Type: Modifier)
24836 << getOpenMPClauseName(C: llvm::omp::OMPC_num_teams) << "5.1";
24837 return nullptr;
24838 }
24839
24840 // OpenMP [teams Construct, Restrictions]
24841 // The lower-bound expression in num_teams must evaluate to a positive
24842 // integer value.
24843 if (!isNonNegativeIntegerValue(ValExpr&: ModifierExpr, SemaRef, CKind: OMPC_num_teams,
24844 /*StrictlyPositive=*/true))
24845 return nullptr;
24846
24847 // OpenMP 5.2: Validate lower-bound is less than or equal to upper-bound.
24848 Expr *LowerBound = ModifierExpr;
24849 Expr *UpperBound = VarList[0];
24850
24851 // Check if both are compile-time constants for validation.
24852 if (!LowerBound->isValueDependent() && !UpperBound->isValueDependent() &&
24853 LowerBound->isIntegerConstantExpr(Ctx: getASTContext()) &&
24854 UpperBound->isIntegerConstantExpr(Ctx: getASTContext())) {
24855
24856 // Get the actual constant values.
24857 llvm::APSInt LowerVal =
24858 LowerBound->EvaluateKnownConstInt(Ctx: getASTContext());
24859 llvm::APSInt UpperVal =
24860 UpperBound->EvaluateKnownConstInt(Ctx: getASTContext());
24861
24862 if (LowerVal > UpperVal) {
24863 Diag(Loc: LowerBound->getExprLoc(),
24864 DiagID: diag::err_omp_num_teams_lower_bound_larger)
24865 << LowerBound->getSourceRange() << UpperBound->getSourceRange();
24866 return nullptr;
24867 }
24868 }
24869 }
24870
24871 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24872 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
24873 DKind, CKind: OMPC_num_teams, OMPVersion: getLangOpts().getOpenMPVersion());
24874 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
24875 return OMPNumTeamsClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
24876 LParenLoc, EndLoc, VL: VarList, Modifier,
24877 ModifierExpr, ModifierLoc,
24878 /*PreInit=*/nullptr);
24879
24880 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24881 SmallVector<Expr *, 3> Vars;
24882 for (Expr *ValExpr : VarList) {
24883 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
24884 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
24885 Vars.push_back(Elt: ValExpr);
24886 }
24887
24888 if (ModifierExpr) {
24889 ModifierExpr = SemaRef.MakeFullExpr(Arg: ModifierExpr).get();
24890 ModifierExpr = tryBuildCapture(SemaRef, Capture: ModifierExpr, Captures).get();
24891 }
24892
24893 Stmt *PreInit = buildPreInits(Context&: getASTContext(), Captures);
24894 return OMPNumTeamsClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
24895 LParenLoc, EndLoc, VL: Vars, Modifier,
24896 ModifierExpr, ModifierLoc, PreInit);
24897}
24898
24899OMPClause *SemaOpenMP::ActOnOpenMPThreadLimitClause(
24900 ArrayRef<Expr *> VarList, OpenMPThreadLimitClauseModifier Modifier,
24901 Expr *ModifierExpr, SourceLocation ModifierLoc, SourceLocation StartLoc,
24902 SourceLocation LParenLoc, SourceLocation EndLoc) {
24903 if (VarList.empty())
24904 return nullptr;
24905
24906 for (Expr *ValExpr : VarList) {
24907 // OpenMP [teams Constrcut, Restrictions]
24908 // The thread_limit expression must evaluate to a positive integer value.
24909 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_thread_limit,
24910 /*StrictlyPositive=*/true))
24911 return nullptr;
24912 }
24913
24914 if (Modifier == OMPC_THREADLIMIT_dims) {
24915 ExprResult Res =
24916 ActOnOpenMPDimsModifier(ClauseKind: OMPC_thread_limit, Modifier, ModifierExpr,
24917 ModifierLoc, VarList, VarListEndLoc: EndLoc);
24918 if (Res.isInvalid())
24919 return nullptr;
24920 ModifierExpr = Res.get();
24921 }
24922
24923 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24924 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
24925 DKind, CKind: OMPC_thread_limit, OMPVersion: getLangOpts().getOpenMPVersion());
24926 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
24927 return OMPThreadLimitClause::Create(C: getASTContext(), CaptureRegion,
24928 StartLoc, LParenLoc, EndLoc, VL: VarList,
24929 Modifier, ModifierExpr, ModifierLoc,
24930 /*PreInit=*/nullptr);
24931
24932 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24933 SmallVector<Expr *, 3> Vars;
24934 for (Expr *ValExpr : VarList) {
24935 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
24936 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
24937 Vars.push_back(Elt: ValExpr);
24938 }
24939
24940 if (ModifierExpr) {
24941 ModifierExpr = SemaRef.MakeFullExpr(Arg: ModifierExpr).get();
24942 ModifierExpr = tryBuildCapture(SemaRef, Capture: ModifierExpr, Captures).get();
24943 }
24944
24945 Stmt *PreInit = buildPreInits(Context&: getASTContext(), Captures);
24946 return OMPThreadLimitClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
24947 LParenLoc, EndLoc, VL: Vars, Modifier,
24948 ModifierExpr, ModifierLoc, PreInit);
24949}
24950
24951OMPClause *SemaOpenMP::ActOnOpenMPPriorityClause(Expr *Priority,
24952 SourceLocation StartLoc,
24953 SourceLocation LParenLoc,
24954 SourceLocation EndLoc) {
24955 Expr *ValExpr = Priority;
24956 Stmt *HelperValStmt = nullptr;
24957 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24958
24959 // OpenMP [2.9.1, task Constrcut]
24960 // The priority-value is a non-negative numerical scalar expression.
24961 if (!isNonNegativeIntegerValue(
24962 ValExpr, SemaRef, CKind: OMPC_priority,
24963 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
24964 DSAStack->getCurrentDirective(), CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
24965 return nullptr;
24966
24967 return new (getASTContext()) OMPPriorityClause(
24968 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24969}
24970
24971OMPClause *SemaOpenMP::ActOnOpenMPGrainsizeClause(
24972 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
24973 SourceLocation StartLoc, SourceLocation LParenLoc,
24974 SourceLocation ModifierLoc, SourceLocation EndLoc) {
24975 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
24976 "Unexpected grainsize modifier in OpenMP < 51.");
24977
24978 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
24979 std::string Values = getListOfPossibleValues(K: OMPC_grainsize, /*First=*/0,
24980 Last: OMPC_GRAINSIZE_unknown);
24981 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
24982 << Values << getOpenMPClauseNameForDiag(C: OMPC_grainsize);
24983 return nullptr;
24984 }
24985
24986 Expr *ValExpr = Grainsize;
24987 Stmt *HelperValStmt = nullptr;
24988 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24989
24990 // OpenMP [2.9.2, taskloop Constrcut]
24991 // The parameter of the grainsize clause must be a positive integer
24992 // expression.
24993 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_grainsize,
24994 /*StrictlyPositive=*/true,
24995 /*BuildCapture=*/true,
24996 DSAStack->getCurrentDirective(),
24997 CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
24998 return nullptr;
24999
25000 return new (getASTContext())
25001 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
25002 StartLoc, LParenLoc, ModifierLoc, EndLoc);
25003}
25004
25005OMPClause *SemaOpenMP::ActOnOpenMPNumTasksClause(
25006 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
25007 SourceLocation StartLoc, SourceLocation LParenLoc,
25008 SourceLocation ModifierLoc, SourceLocation EndLoc) {
25009 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
25010 "Unexpected num_tasks modifier in OpenMP < 51.");
25011
25012 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
25013 std::string Values = getListOfPossibleValues(K: OMPC_num_tasks, /*First=*/0,
25014 Last: OMPC_NUMTASKS_unknown);
25015 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
25016 << Values << getOpenMPClauseNameForDiag(C: OMPC_num_tasks);
25017 return nullptr;
25018 }
25019
25020 Expr *ValExpr = NumTasks;
25021 Stmt *HelperValStmt = nullptr;
25022 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
25023
25024 // OpenMP [2.9.2, taskloop Constrcut]
25025 // The parameter of the num_tasks clause must be a positive integer
25026 // expression.
25027 if (!isNonNegativeIntegerValue(
25028 ValExpr, SemaRef, CKind: OMPC_num_tasks,
25029 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
25030 DSAStack->getCurrentDirective(), CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
25031 return nullptr;
25032
25033 return new (getASTContext())
25034 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
25035 StartLoc, LParenLoc, ModifierLoc, EndLoc);
25036}
25037
25038OMPClause *SemaOpenMP::ActOnOpenMPHintClause(Expr *Hint,
25039 SourceLocation StartLoc,
25040 SourceLocation LParenLoc,
25041 SourceLocation EndLoc) {
25042 // OpenMP [2.13.2, critical construct, Description]
25043 // ... where hint-expression is an integer constant expression that evaluates
25044 // to a valid lock hint.
25045 ExprResult HintExpr =
25046 VerifyPositiveIntegerConstantInClause(E: Hint, CKind: OMPC_hint, StrictlyPositive: false);
25047 if (HintExpr.isInvalid())
25048 return nullptr;
25049 return new (getASTContext())
25050 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
25051}
25052
25053/// Tries to find omp_event_handle_t type.
25054static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
25055 DSAStackTy *Stack) {
25056 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
25057 if (!OMPEventHandleT.isNull())
25058 return true;
25059 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_event_handle_t");
25060 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
25061 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
25062 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
25063 return false;
25064 }
25065 Stack->setOMPEventHandleT(PT.get());
25066 return true;
25067}
25068
25069OMPClause *SemaOpenMP::ActOnOpenMPDetachClause(Expr *Evt,
25070 SourceLocation StartLoc,
25071 SourceLocation LParenLoc,
25072 SourceLocation EndLoc) {
25073 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
25074 !Evt->isInstantiationDependent() &&
25075 !Evt->containsUnexpandedParameterPack()) {
25076 if (!findOMPEventHandleT(S&: SemaRef, Loc: Evt->getExprLoc(), DSAStack))
25077 return nullptr;
25078 // OpenMP 5.0, 2.10.1 task Construct.
25079 // event-handle is a variable of the omp_event_handle_t type.
25080 auto *Ref = dyn_cast<DeclRefExpr>(Val: Evt->IgnoreParenImpCasts());
25081 if (!Ref) {
25082 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
25083 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
25084 return nullptr;
25085 }
25086 auto *VD = dyn_cast_or_null<VarDecl>(Val: Ref->getDecl());
25087 if (!VD) {
25088 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
25089 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
25090 return nullptr;
25091 }
25092 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
25093 T2: VD->getType()) ||
25094 VD->getType().isConstant(Ctx: getASTContext())) {
25095 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
25096 << "omp_event_handle_t" << 1 << VD->getType()
25097 << Evt->getSourceRange();
25098 return nullptr;
25099 }
25100 // OpenMP 5.0, 2.10.1 task Construct
25101 // [detach clause]... The event-handle will be considered as if it was
25102 // specified on a firstprivate clause.
25103 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
25104 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
25105 DVar.RefExpr) {
25106 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
25107 << getOpenMPClauseNameForDiag(C: DVar.CKind)
25108 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
25109 reportOriginalDsa(SemaRef, DSAStack, D: VD, DVar);
25110 return nullptr;
25111 }
25112 }
25113
25114 return new (getASTContext())
25115 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
25116}
25117
25118OMPClause *SemaOpenMP::ActOnOpenMPDistScheduleClause(
25119 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
25120 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
25121 SourceLocation EndLoc) {
25122 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
25123 std::string Values;
25124 Values += "'";
25125 Values += getOpenMPSimpleClauseTypeName(Kind: OMPC_dist_schedule, Type: 0);
25126 Values += "'";
25127 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
25128 << Values << getOpenMPClauseNameForDiag(C: OMPC_dist_schedule);
25129 return nullptr;
25130 }
25131 Expr *ValExpr = ChunkSize;
25132 Stmt *HelperValStmt = nullptr;
25133 if (ChunkSize) {
25134 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
25135 !ChunkSize->isInstantiationDependent() &&
25136 !ChunkSize->containsUnexpandedParameterPack()) {
25137 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
25138 ExprResult Val =
25139 PerformOpenMPImplicitIntegerConversion(Loc: ChunkSizeLoc, Op: ChunkSize);
25140 if (Val.isInvalid())
25141 return nullptr;
25142
25143 ValExpr = Val.get();
25144
25145 // OpenMP [2.7.1, Restrictions]
25146 // chunk_size must be a loop invariant integer expression with a positive
25147 // value.
25148 if (std::optional<llvm::APSInt> Result =
25149 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
25150 if (Result->isSigned() && !Result->isStrictlyPositive()) {
25151 Diag(Loc: ChunkSizeLoc, DiagID: diag::err_omp_negative_expression_in_clause)
25152 << "dist_schedule" << /*strictly positive*/ 1
25153 << ChunkSize->getSourceRange();
25154 return nullptr;
25155 }
25156 } else if (getOpenMPCaptureRegionForClause(
25157 DSAStack->getCurrentDirective(), CKind: OMPC_dist_schedule,
25158 OMPVersion: getLangOpts().getOpenMPVersion()) != OMPD_unknown &&
25159 !SemaRef.CurContext->isDependentContext()) {
25160 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
25161 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25162 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
25163 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
25164 }
25165 }
25166 }
25167
25168 return new (getASTContext())
25169 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
25170 Kind, ValExpr, HelperValStmt);
25171}
25172
25173OMPClause *SemaOpenMP::ActOnOpenMPDefaultmapClause(
25174 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
25175 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
25176 SourceLocation KindLoc, SourceLocation EndLoc) {
25177 if (getLangOpts().OpenMP < 50) {
25178 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
25179 Kind != OMPC_DEFAULTMAP_scalar) {
25180 std::string Value;
25181 SourceLocation Loc;
25182 Value += "'";
25183 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
25184 Value += getOpenMPSimpleClauseTypeName(Kind: OMPC_defaultmap,
25185 Type: OMPC_DEFAULTMAP_MODIFIER_tofrom);
25186 Loc = MLoc;
25187 } else {
25188 Value += getOpenMPSimpleClauseTypeName(Kind: OMPC_defaultmap,
25189 Type: OMPC_DEFAULTMAP_scalar);
25190 Loc = KindLoc;
25191 }
25192 Value += "'";
25193 Diag(Loc, DiagID: diag::err_omp_unexpected_clause_value)
25194 << Value << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25195 return nullptr;
25196 }
25197 } else {
25198 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
25199 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
25200 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
25201 if (!isDefaultmapKind || !isDefaultmapModifier) {
25202 StringRef KindValue = getLangOpts().OpenMP < 52
25203 ? "'scalar', 'aggregate', 'pointer'"
25204 : "'scalar', 'aggregate', 'pointer', 'all'";
25205 if (getLangOpts().OpenMP == 50) {
25206 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
25207 "'firstprivate', 'none', 'default'";
25208 if (!isDefaultmapKind && isDefaultmapModifier) {
25209 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
25210 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25211 } else if (isDefaultmapKind && !isDefaultmapModifier) {
25212 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
25213 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25214 } else {
25215 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
25216 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25217 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
25218 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25219 }
25220 } else {
25221 StringRef ModifierValue =
25222 getLangOpts().OpenMP < 60
25223 ? "'alloc', 'from', 'to', 'tofrom', "
25224 "'firstprivate', 'none', 'default', 'present'"
25225 : "'storage', 'from', 'to', 'tofrom', "
25226 "'firstprivate', 'private', 'none', 'default', 'present'";
25227 if (!isDefaultmapKind && isDefaultmapModifier) {
25228 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
25229 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25230 } else if (isDefaultmapKind && !isDefaultmapModifier) {
25231 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
25232 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25233 } else {
25234 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
25235 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25236 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
25237 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25238 }
25239 }
25240 return nullptr;
25241 }
25242
25243 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
25244 // At most one defaultmap clause for each category can appear on the
25245 // directive.
25246 if (DSAStack->checkDefaultmapCategory(VariableCategory: Kind)) {
25247 Diag(Loc: StartLoc, DiagID: diag::err_omp_one_defaultmap_each_category);
25248 return nullptr;
25249 }
25250 }
25251 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
25252 // Variable category is not specified - mark all categories.
25253 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_aggregate, Loc: StartLoc);
25254 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_scalar, Loc: StartLoc);
25255 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_pointer, Loc: StartLoc);
25256 } else {
25257 DSAStack->setDefaultDMAAttr(M, Kind, Loc: StartLoc);
25258 }
25259
25260 return new (getASTContext())
25261 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
25262}
25263
25264bool SemaOpenMP::ActOnStartOpenMPDeclareTargetContext(
25265 DeclareTargetContextInfo &DTCI) {
25266 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
25267 if (!CurLexicalContext->isFileContext() &&
25268 !CurLexicalContext->isExternCContext() &&
25269 !CurLexicalContext->isExternCXXContext() &&
25270 !isa<CXXRecordDecl>(Val: CurLexicalContext) &&
25271 !isa<ClassTemplateDecl>(Val: CurLexicalContext) &&
25272 !isa<ClassTemplatePartialSpecializationDecl>(Val: CurLexicalContext) &&
25273 !isa<ClassTemplateSpecializationDecl>(Val: CurLexicalContext)) {
25274 Diag(Loc: DTCI.Loc, DiagID: diag::err_omp_region_not_file_context);
25275 return false;
25276 }
25277
25278 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
25279 if (getLangOpts().HIP)
25280 Diag(Loc: DTCI.Loc, DiagID: diag::warn_hip_omp_target_directives);
25281
25282 DeclareTargetNesting.push_back(Elt: DTCI);
25283 return true;
25284}
25285
25286const SemaOpenMP::DeclareTargetContextInfo
25287SemaOpenMP::ActOnOpenMPEndDeclareTargetDirective() {
25288 assert(!DeclareTargetNesting.empty() &&
25289 "check isInOpenMPDeclareTargetContext() first!");
25290 return DeclareTargetNesting.pop_back_val();
25291}
25292
25293void SemaOpenMP::ActOnFinishedOpenMPDeclareTargetContext(
25294 DeclareTargetContextInfo &DTCI) {
25295 for (auto &It : DTCI.ExplicitlyMapped)
25296 ActOnOpenMPDeclareTargetName(ND: It.first, Loc: It.second.Loc, MT: It.second.MT, DTCI);
25297}
25298
25299void SemaOpenMP::DiagnoseUnterminatedOpenMPDeclareTarget() {
25300 if (DeclareTargetNesting.empty())
25301 return;
25302 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
25303 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
25304 Diag(Loc: DTCI.Loc, DiagID: diag::warn_omp_unterminated_declare_target)
25305 << getOpenMPDirectiveName(D: DTCI.Kind, V: OMPVersion);
25306}
25307
25308NamedDecl *SemaOpenMP::lookupOpenMPDeclareTargetName(
25309 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
25310 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
25311 SemaRef.LookupParsedName(R&: Lookup, S: CurScope, SS: &ScopeSpec,
25312 /*ObjectType=*/QualType(),
25313 /*AllowBuiltinCreation=*/true);
25314
25315 if (Lookup.isAmbiguous())
25316 return nullptr;
25317 Lookup.suppressDiagnostics();
25318
25319 if (!Lookup.isSingleResult()) {
25320 VarOrFuncDeclFilterCCC CCC(SemaRef);
25321 if (TypoCorrection Corrected =
25322 SemaRef.CorrectTypo(Typo: Id, LookupKind: Sema::LookupOrdinaryName, S: CurScope, SS: nullptr,
25323 CCC, Mode: CorrectTypoKind::ErrorRecovery)) {
25324 SemaRef.diagnoseTypo(Correction: Corrected,
25325 TypoDiag: SemaRef.PDiag(DiagID: diag::err_undeclared_var_use_suggest)
25326 << Id.getName());
25327 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: Corrected.getCorrectionDecl());
25328 return nullptr;
25329 }
25330
25331 Diag(Loc: Id.getLoc(), DiagID: diag::err_undeclared_var_use) << Id.getName();
25332 return nullptr;
25333 }
25334
25335 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
25336 if (!isa<VarDecl>(Val: ND) && !isa<FunctionDecl>(Val: ND) &&
25337 !isa<FunctionTemplateDecl>(Val: ND)) {
25338 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_invalid_target_decl) << Id.getName();
25339 return nullptr;
25340 }
25341 return ND;
25342}
25343
25344void SemaOpenMP::ActOnOpenMPDeclareTargetName(
25345 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
25346 DeclareTargetContextInfo &DTCI) {
25347 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
25348 isa<FunctionTemplateDecl>(ND)) &&
25349 "Expected variable, function or function template.");
25350
25351 if (auto *VD = dyn_cast<VarDecl>(Val: ND)) {
25352 // Only global variables can be marked as declare target.
25353 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
25354 !VD->isStaticDataMember()) {
25355 Diag(Loc, DiagID: diag::err_omp_declare_target_has_local_vars)
25356 << VD->getNameAsString();
25357 return;
25358 }
25359 }
25360 // Diagnose marking after use as it may lead to incorrect diagnosis and
25361 // codegen.
25362 if (getLangOpts().OpenMP >= 50 &&
25363 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
25364 Diag(Loc, DiagID: diag::warn_omp_declare_target_after_first_use);
25365
25366 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
25367 if (getLangOpts().HIP)
25368 Diag(Loc, DiagID: diag::warn_hip_omp_target_directives);
25369
25370 // 'local' is incompatible with 'device_type(host)' because 'local'
25371 // variables exist only on the device.
25372 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
25373 DTCI.DT == OMPDeclareTargetDeclAttr::DT_Host) {
25374 Diag(Loc, DiagID: diag::err_omp_declare_target_local_host_only);
25375 return;
25376 }
25377
25378 // Explicit declare target lists have precedence.
25379 const unsigned Level = -1;
25380
25381 auto *VD = cast<ValueDecl>(Val: ND);
25382 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
25383 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
25384 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
25385 (*ActiveAttr)->getLevel() == Level) {
25386 Diag(Loc, DiagID: diag::err_omp_device_type_mismatch)
25387 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(Val: DTCI.DT)
25388 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
25389 Val: (*ActiveAttr)->getDevType());
25390 return;
25391 }
25392 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
25393 (*ActiveAttr)->getLevel() == Level) {
25394 Diag(Loc, DiagID: diag::err_omp_declare_target_var_in_both_clauses)
25395 << ND
25396 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(
25397 Val: (*ActiveAttr)->getMapType())
25398 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(Val: MT);
25399 return;
25400 }
25401
25402 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
25403 return;
25404
25405 Expr *IndirectE = nullptr;
25406 bool IsIndirect = false;
25407 if (DTCI.Indirect) {
25408 IndirectE = *DTCI.Indirect;
25409 if (!IndirectE)
25410 IsIndirect = true;
25411 }
25412 // FIXME: 'local' with 'device_type(nohost)' is not yet fully supported
25413 // in codegen. Treat as 'device_type(any)' for now. The variable will
25414 // exist on both host and device, but the host copy is unused.
25415 auto DT = DTCI.DT;
25416 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
25417 DT == OMPDeclareTargetDeclAttr::DT_NoHost) {
25418 Diag(Loc, DiagID: diag::warn_omp_declare_target_local_nohost);
25419 DT = OMPDeclareTargetDeclAttr::DT_Any;
25420 }
25421
25422 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
25423 Ctx&: getASTContext(), MapType: MT, DevType: DT, IndirectExpr: IndirectE, Indirect: IsIndirect, Level,
25424 Range: SourceRange(Loc, Loc));
25425 ND->addAttr(A);
25426 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
25427 ML->DeclarationMarkedOpenMPDeclareTarget(D: ND, Attr: A);
25428 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: ND, IdLoc: Loc);
25429 if (auto *VD = dyn_cast<VarDecl>(Val: ND);
25430 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
25431 VD->hasGlobalStorage())
25432 ActOnOpenMPDeclareTargetInitializer(D: ND);
25433}
25434
25435static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
25436 Sema &SemaRef, Decl *D) {
25437 if (!D || !isa<VarDecl>(Val: D))
25438 return;
25439 auto *VD = cast<VarDecl>(Val: D);
25440 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
25441 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
25442 if (SemaRef.LangOpts.OpenMP >= 50 &&
25443 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
25444 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
25445 VD->hasGlobalStorage()) {
25446 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
25447 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter &&
25448 *MapTy != OMPDeclareTargetDeclAttr::MT_Local)) {
25449 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
25450 // If a lambda declaration and definition appears between a
25451 // declare target directive and the matching end declare target
25452 // directive, all variables that are captured by the lambda
25453 // expression must also appear in a to clause.
25454 SemaRef.Diag(Loc: VD->getLocation(),
25455 DiagID: diag::err_omp_lambda_capture_in_declare_target_not_to);
25456 SemaRef.Diag(Loc: SL, DiagID: diag::note_var_explicitly_captured_here)
25457 << VD << 0 << SR;
25458 return;
25459 }
25460 }
25461 if (MapTy)
25462 return;
25463 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::warn_omp_not_in_target_context);
25464 SemaRef.Diag(Loc: SL, DiagID: diag::note_used_here) << SR;
25465}
25466
25467static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
25468 Sema &SemaRef, DSAStackTy *Stack,
25469 ValueDecl *VD) {
25470 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
25471 checkTypeMappable(SL, SR, SemaRef, Stack, QTy: VD->getType(),
25472 /*FullCheck=*/false);
25473}
25474
25475void SemaOpenMP::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
25476 SourceLocation IdLoc) {
25477 if (!D || D->isInvalidDecl())
25478 return;
25479 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
25480 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
25481 if (auto *VD = dyn_cast<VarDecl>(Val: D)) {
25482 // Only global variables can be marked as declare target.
25483 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
25484 !VD->isStaticDataMember())
25485 return;
25486 // 2.10.6: threadprivate variable cannot appear in a declare target
25487 // directive.
25488 if (DSAStack->isThreadPrivate(D: VD)) {
25489 Diag(Loc: SL, DiagID: diag::err_omp_threadprivate_in_target);
25490 reportOriginalDsa(SemaRef, DSAStack, D: VD, DSAStack->getTopDSA(D: VD, FromParent: false));
25491 return;
25492 }
25493 }
25494 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: D))
25495 D = FTD->getTemplatedDecl();
25496 if (auto *FD = dyn_cast<FunctionDecl>(Val: D)) {
25497 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
25498 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD: FD);
25499 if (IdLoc.isValid() && Res &&
25500 (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
25501 *Res == OMPDeclareTargetDeclAttr::MT_Local)) {
25502 Diag(Loc: IdLoc, DiagID: diag::err_omp_function_in_target_clause_list)
25503 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(Val: *Res);
25504 Diag(Loc: FD->getLocation(), DiagID: diag::note_defined_here) << FD;
25505 return;
25506 }
25507 }
25508 if (auto *VD = dyn_cast<ValueDecl>(Val: D)) {
25509 // Problem if any with var declared with incomplete type will be reported
25510 // as normal, so no need to check it here.
25511 if ((E || !VD->getType()->isIncompleteType()) &&
25512 !checkValueDeclInTarget(SL, SR, SemaRef, DSAStack, VD))
25513 return;
25514 if (!E && isInOpenMPDeclareTargetContext()) {
25515 // Checking declaration inside declare target region.
25516 if (isa<VarDecl>(Val: D) || isa<FunctionDecl>(Val: D) ||
25517 isa<FunctionTemplateDecl>(Val: D)) {
25518 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
25519 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
25520 unsigned Level = DeclareTargetNesting.size();
25521 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
25522 return;
25523 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
25524 Expr *IndirectE = nullptr;
25525 bool IsIndirect = false;
25526 if (DTCI.Indirect) {
25527 IndirectE = *DTCI.Indirect;
25528 if (!IndirectE)
25529 IsIndirect = true;
25530 }
25531 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
25532 Ctx&: getASTContext(),
25533 MapType: getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
25534 : OMPDeclareTargetDeclAttr::MT_To,
25535 DevType: DTCI.DT, IndirectExpr: IndirectE, Indirect: IsIndirect, Level,
25536 Range: SourceRange(DTCI.Loc, DTCI.Loc));
25537 D->addAttr(A);
25538 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
25539 ML->DeclarationMarkedOpenMPDeclareTarget(D, Attr: A);
25540 }
25541 return;
25542 }
25543 }
25544 if (!E)
25545 return;
25546 checkDeclInTargetContext(SL: E->getExprLoc(), SR: E->getSourceRange(), SemaRef, D);
25547}
25548
25549/// This class visits every VarDecl that the initializer references and adds
25550/// OMPDeclareTargetDeclAttr to each of them.
25551class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
25552 SmallVector<VarDecl *> DeclVector;
25553 Attr *A;
25554
25555public:
25556 /// A StmtVisitor class function that visits all DeclRefExpr and adds
25557 /// OMPDeclareTargetDeclAttr to them.
25558 void VisitDeclRefExpr(DeclRefExpr *Node) {
25559 if (auto *VD = dyn_cast<VarDecl>(Val: Node->getDecl())) {
25560 VD->addAttr(A);
25561 DeclVector.push_back(Elt: VD);
25562 }
25563 }
25564 /// A function that iterates across each of the Expr's children.
25565 void VisitExpr(Expr *Ex) {
25566 for (auto *Child : Ex->children()) {
25567 Visit(S: Child);
25568 }
25569 }
25570 /// A function that keeps a record of all the Decls that are variables, has
25571 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
25572 /// each Decl one at a time and use the inherited 'visit' functions to look
25573 /// for DeclRefExpr.
25574 void declareTargetInitializer(Decl *TD) {
25575 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
25576 DeclVector.push_back(Elt: cast<VarDecl>(Val: TD));
25577 llvm::SmallDenseSet<Decl *> Visited;
25578 while (!DeclVector.empty()) {
25579 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
25580 if (!Visited.insert(V: TargetVarDecl).second)
25581 continue;
25582
25583 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
25584 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
25585 if (Expr *Ex = TargetVarDecl->getInit())
25586 Visit(S: Ex);
25587 }
25588 }
25589 }
25590};
25591
25592/// Adding OMPDeclareTargetDeclAttr to variables with static storage
25593/// duration that are referenced in the initializer expression list of
25594/// variables with static storage duration in declare target directive.
25595void SemaOpenMP::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) {
25596 GlobalDeclRefChecker Checker;
25597 if (isa<VarDecl>(Val: TargetDecl))
25598 Checker.declareTargetInitializer(TD: TargetDecl);
25599}
25600
25601OMPClause *SemaOpenMP::ActOnOpenMPToClause(
25602 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
25603 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
25604 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
25605 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
25606 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
25607 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
25608 OMPC_MOTION_MODIFIER_unknown,
25609 OMPC_MOTION_MODIFIER_unknown};
25610 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
25611
25612 // Process motion-modifiers, flag errors for duplicate modifiers.
25613 unsigned Count = 0;
25614 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
25615 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
25616 llvm::is_contained(Range&: Modifiers, Element: MotionModifiers[I])) {
25617 Diag(Loc: MotionModifiersLoc[I], DiagID: diag::err_omp_duplicate_motion_modifier);
25618 continue;
25619 }
25620 assert(Count < NumberOfOMPMotionModifiers &&
25621 "Modifiers exceed the allowed number of motion modifiers");
25622 Modifiers[Count] = MotionModifiers[I];
25623 ModifiersLoc[Count] = MotionModifiersLoc[I];
25624 ++Count;
25625 }
25626
25627 MappableVarListInfo MVLI(VarList);
25628 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_to, MVLI, StartLoc: Locs.StartLoc,
25629 MapperIdScopeSpec, MapperId, UnresolvedMappers);
25630 if (MVLI.ProcessedVarList.empty())
25631 return nullptr;
25632 if (IteratorExpr)
25633 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: IteratorExpr))
25634 if (auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
25635 DSAStack->addIteratorVarDecl(VD);
25636 return OMPToClause::Create(
25637 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25638 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, IteratorModifier: IteratorExpr, MotionModifiers: Modifiers,
25639 MotionModifiersLoc: ModifiersLoc, UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()),
25640 MapperId);
25641}
25642
25643OMPClause *SemaOpenMP::ActOnOpenMPFromClause(
25644 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
25645 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
25646 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
25647 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
25648 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
25649 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
25650 OMPC_MOTION_MODIFIER_unknown,
25651 OMPC_MOTION_MODIFIER_unknown};
25652 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
25653
25654 // Process motion-modifiers, flag errors for duplicate modifiers.
25655 unsigned Count = 0;
25656 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
25657 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
25658 llvm::is_contained(Range&: Modifiers, Element: MotionModifiers[I])) {
25659 Diag(Loc: MotionModifiersLoc[I], DiagID: diag::err_omp_duplicate_motion_modifier);
25660 continue;
25661 }
25662 assert(Count < NumberOfOMPMotionModifiers &&
25663 "Modifiers exceed the allowed number of motion modifiers");
25664 Modifiers[Count] = MotionModifiers[I];
25665 ModifiersLoc[Count] = MotionModifiersLoc[I];
25666 ++Count;
25667 }
25668
25669 MappableVarListInfo MVLI(VarList);
25670 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_from, MVLI, StartLoc: Locs.StartLoc,
25671 MapperIdScopeSpec, MapperId, UnresolvedMappers);
25672 if (MVLI.ProcessedVarList.empty())
25673 return nullptr;
25674 if (IteratorExpr)
25675 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: IteratorExpr))
25676 if (auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
25677 DSAStack->addIteratorVarDecl(VD);
25678 return OMPFromClause::Create(
25679 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25680 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, IteratorExpr, MotionModifiers: Modifiers,
25681 MotionModifiersLoc: ModifiersLoc, UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()),
25682 MapperId);
25683}
25684
25685OMPClause *SemaOpenMP::ActOnOpenMPUseDevicePtrClause(
25686 ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs,
25687 OpenMPUseDevicePtrFallbackModifier FallbackModifier,
25688 SourceLocation FallbackModifierLoc) {
25689 MappableVarListInfo MVLI(VarList);
25690 SmallVector<Expr *, 8> PrivateCopies;
25691 SmallVector<Expr *, 8> Inits;
25692
25693 for (Expr *RefExpr : VarList) {
25694 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
25695 SourceLocation ELoc;
25696 SourceRange ERange;
25697 Expr *SimpleRefExpr = RefExpr;
25698 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
25699 if (Res.second) {
25700 // It will be analyzed later.
25701 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
25702 PrivateCopies.push_back(Elt: nullptr);
25703 Inits.push_back(Elt: nullptr);
25704 }
25705 ValueDecl *D = Res.first;
25706 if (!D)
25707 continue;
25708
25709 QualType Type = D->getType();
25710 Type = Type.getNonReferenceType().getUnqualifiedType();
25711
25712 auto *VD = dyn_cast<VarDecl>(Val: D);
25713
25714 // Item should be a pointer or reference to pointer.
25715 if (!Type->isPointerType()) {
25716 Diag(Loc: ELoc, DiagID: diag::err_omp_usedeviceptr_not_a_pointer)
25717 << 0 << RefExpr->getSourceRange();
25718 continue;
25719 }
25720
25721 // Build the private variable and the expression that refers to it.
25722 auto VDPrivate =
25723 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
25724 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
25725 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
25726 if (VDPrivate->isInvalidDecl())
25727 continue;
25728
25729 SemaRef.CurContext->addDecl(D: VDPrivate);
25730 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
25731 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(), Loc: ELoc);
25732
25733 // Add temporary variable to initialize the private copy of the pointer.
25734 VarDecl *VDInit =
25735 buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type, Name: ".devptr.temp");
25736 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
25737 S&: SemaRef, D: VDInit, Ty: RefExpr->getType(), Loc: RefExpr->getExprLoc());
25738 SemaRef.AddInitializerToDecl(
25739 dcl: VDPrivate, init: SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get(),
25740 /*DirectInit=*/false);
25741
25742 // If required, build a capture to implement the privatization initialized
25743 // with the current list item value.
25744 DeclRefExpr *Ref = nullptr;
25745 if (!VD)
25746 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
25747 MVLI.ProcessedVarList.push_back(Elt: VD ? RefExpr->IgnoreParens() : Ref);
25748 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
25749 Inits.push_back(Elt: VDInitRefExpr);
25750
25751 // We need to add a data sharing attribute for this variable to make sure it
25752 // is correctly captured. A variable that shows up in a use_device_ptr has
25753 // similar properties of a first private variable.
25754 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
25755
25756 // Create a mappable component for the list item. List items in this clause
25757 // only need a component.
25758 MVLI.VarBaseDeclarations.push_back(Elt: D);
25759 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
25760 MVLI.VarComponents.back().emplace_back(Args&: SimpleRefExpr, Args&: D,
25761 /*IsNonContiguous=*/Args: false);
25762 }
25763
25764 if (MVLI.ProcessedVarList.empty())
25765 return nullptr;
25766
25767 return OMPUseDevicePtrClause::Create(
25768 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, PrivateVars: PrivateCopies, Inits,
25769 Declarations: MVLI.VarBaseDeclarations, ComponentLists: MVLI.VarComponents, FallbackModifier,
25770 FallbackModifierLoc);
25771}
25772
25773OMPClause *
25774SemaOpenMP::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
25775 const OMPVarListLocTy &Locs) {
25776 MappableVarListInfo MVLI(VarList);
25777
25778 for (Expr *RefExpr : VarList) {
25779 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
25780 SourceLocation ELoc;
25781 SourceRange ERange;
25782 Expr *SimpleRefExpr = RefExpr;
25783 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
25784 /*AllowArraySection=*/true,
25785 /*AllowAssumedSizeArray=*/true);
25786 if (Res.second) {
25787 // It will be analyzed later.
25788 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
25789 }
25790 ValueDecl *D = Res.first;
25791 if (!D)
25792 continue;
25793 auto *VD = dyn_cast<VarDecl>(Val: D);
25794
25795 // If required, build a capture to implement the privatization initialized
25796 // with the current list item value.
25797 DeclRefExpr *Ref = nullptr;
25798 if (!VD)
25799 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
25800 MVLI.ProcessedVarList.push_back(Elt: VD ? RefExpr->IgnoreParens() : Ref);
25801
25802 // We need to add a data sharing attribute for this variable to make sure it
25803 // is correctly captured. A variable that shows up in a use_device_addr has
25804 // similar properties of a first private variable.
25805 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
25806
25807 // Use the map-like approach to fully populate VarComponents
25808 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
25809
25810 const Expr *BE = checkMapClauseExpressionBase(
25811 SemaRef, E: RefExpr, CurComponents, CKind: OMPC_use_device_addr,
25812 DSAStack->getCurrentDirective(),
25813 /*NoDiagnose=*/false);
25814
25815 if (!BE)
25816 continue;
25817
25818 assert(!CurComponents.empty() &&
25819 "use_device_addr clause expression with no components!");
25820
25821 // OpenMP use_device_addr: If a list item is an array section, the array
25822 // base must be a base language identifier. We caught the cases where
25823 // the array-section has a base-variable in getPrivateItem. e.g.
25824 // struct S {
25825 // int a[10];
25826 // }; S s1;
25827 // ... use_device_addr(s1.a[0]) // not ok, caught already
25828 //
25829 // But we still neeed to verify that the base-pointer is also a
25830 // base-language identifier, and catch cases like:
25831 // int *pa[10]; *p;
25832 // ... use_device_addr(pa[1][2]) // not ok, base-pointer is pa[1]
25833 // ... use_device_addr(p[1]) // ok
25834 // ... use_device_addr(this->p[1]) // ok
25835 auto AttachPtrResult = OMPClauseMappableExprCommon::findAttachPtrExpr(
25836 Components: CurComponents, DSAStack->getCurrentDirective());
25837 const Expr *AttachPtrExpr = AttachPtrResult.first;
25838
25839 if (AttachPtrExpr) {
25840 const Expr *BaseExpr = AttachPtrExpr->IgnoreParenImpCasts();
25841 bool IsValidBase = false;
25842
25843 if (isa<DeclRefExpr>(Val: BaseExpr))
25844 IsValidBase = true;
25845 else if (const auto *ME = dyn_cast<MemberExpr>(Val: BaseExpr);
25846 ME && isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
25847 IsValidBase = true;
25848
25849 if (!IsValidBase) {
25850 SemaRef.Diag(Loc: ELoc,
25851 DiagID: diag::err_omp_expected_base_pointer_var_name_member_expr)
25852 << (SemaRef.getCurrentThisType().isNull() ? 0 : 1)
25853 << AttachPtrExpr->getSourceRange();
25854 continue;
25855 }
25856 }
25857
25858 // Get the declaration from the components
25859 ValueDecl *CurDeclaration = CurComponents.back().getAssociatedDeclaration();
25860 assert((isa<CXXThisExpr>(BE) || CurDeclaration) &&
25861 "Unexpected null decl for use_device_addr clause.");
25862
25863 MVLI.VarBaseDeclarations.push_back(Elt: CurDeclaration);
25864 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
25865 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
25866 in_end: CurComponents.end());
25867 }
25868
25869 if (MVLI.ProcessedVarList.empty())
25870 return nullptr;
25871
25872 return OMPUseDeviceAddrClause::Create(
25873 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25874 ComponentLists: MVLI.VarComponents);
25875}
25876
25877OMPClause *
25878SemaOpenMP::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
25879 const OMPVarListLocTy &Locs) {
25880 MappableVarListInfo MVLI(VarList);
25881 for (Expr *RefExpr : VarList) {
25882 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
25883 SourceLocation ELoc;
25884 SourceRange ERange;
25885 Expr *SimpleRefExpr = RefExpr;
25886 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
25887 if (Res.second) {
25888 // It will be analyzed later.
25889 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
25890 }
25891 ValueDecl *D = Res.first;
25892 if (!D)
25893 continue;
25894
25895 QualType Type = D->getType();
25896 // item should be a pointer or array or reference to pointer or array
25897 if (!Type.getNonReferenceType()->isPointerType() &&
25898 !Type.getNonReferenceType()->isArrayType()) {
25899 Diag(Loc: ELoc, DiagID: diag::err_omp_argument_type_isdeviceptr)
25900 << 0 << RefExpr->getSourceRange();
25901 continue;
25902 }
25903
25904 // Check if the declaration in the clause does not show up in any data
25905 // sharing attribute.
25906 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
25907 if (isOpenMPPrivate(Kind: DVar.CKind)) {
25908 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
25909 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
25910 << getOpenMPClauseNameForDiag(C: DVar.CKind)
25911 << getOpenMPClauseNameForDiag(C: OMPC_is_device_ptr)
25912 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
25913 V: OMPVersion);
25914 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
25915 continue;
25916 }
25917
25918 const Expr *ConflictExpr;
25919 if (DSAStack->checkMappableExprComponentListsForDecl(
25920 VD: D, /*CurrentRegionOnly=*/true,
25921 Check: [&ConflictExpr](
25922 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
25923 OpenMPClauseKind) -> bool {
25924 ConflictExpr = R.front().getAssociatedExpression();
25925 return true;
25926 })) {
25927 Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
25928 Diag(Loc: ConflictExpr->getExprLoc(), DiagID: diag::note_used_here)
25929 << ConflictExpr->getSourceRange();
25930 continue;
25931 }
25932
25933 // Store the components in the stack so that they can be used to check
25934 // against other clauses later on.
25935 OMPClauseMappableExprCommon::MappableComponent MC(
25936 SimpleRefExpr, D, /*IsNonContiguous=*/false);
25937 DSAStack->addMappableExpressionComponents(
25938 VD: D, Components: MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
25939
25940 // Record the expression we've just processed.
25941 MVLI.ProcessedVarList.push_back(Elt: SimpleRefExpr);
25942
25943 // Create a mappable component for the list item. List items in this clause
25944 // only need a component. We use a null declaration to signal fields in
25945 // 'this'.
25946 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
25947 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
25948 "Unexpected device pointer expression!");
25949 MVLI.VarBaseDeclarations.push_back(
25950 Elt: isa<DeclRefExpr>(Val: SimpleRefExpr) ? D : nullptr);
25951 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
25952 MVLI.VarComponents.back().push_back(Elt: MC);
25953 }
25954
25955 if (MVLI.ProcessedVarList.empty())
25956 return nullptr;
25957
25958 return OMPIsDevicePtrClause::Create(
25959 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25960 ComponentLists: MVLI.VarComponents);
25961}
25962
25963OMPClause *
25964SemaOpenMP::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
25965 const OMPVarListLocTy &Locs) {
25966 MappableVarListInfo MVLI(VarList);
25967 for (Expr *RefExpr : VarList) {
25968 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
25969 SourceLocation ELoc;
25970 SourceRange ERange;
25971 Expr *SimpleRefExpr = RefExpr;
25972 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
25973 /*AllowArraySection=*/true);
25974 if (Res.second) {
25975 // It will be analyzed later.
25976 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
25977 }
25978 ValueDecl *D = Res.first;
25979 if (!D)
25980 continue;
25981
25982 // Check if the declaration in the clause does not show up in any data
25983 // sharing attribute.
25984 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
25985 if (isOpenMPPrivate(Kind: DVar.CKind)) {
25986 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
25987 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
25988 << getOpenMPClauseNameForDiag(C: DVar.CKind)
25989 << getOpenMPClauseNameForDiag(C: OMPC_has_device_addr)
25990 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
25991 V: OMPVersion);
25992 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
25993 continue;
25994 }
25995
25996 const Expr *ConflictExpr;
25997 if (DSAStack->checkMappableExprComponentListsForDecl(
25998 VD: D, /*CurrentRegionOnly=*/true,
25999 Check: [&ConflictExpr](
26000 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
26001 OpenMPClauseKind) -> bool {
26002 ConflictExpr = R.front().getAssociatedExpression();
26003 return true;
26004 })) {
26005 Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
26006 Diag(Loc: ConflictExpr->getExprLoc(), DiagID: diag::note_used_here)
26007 << ConflictExpr->getSourceRange();
26008 continue;
26009 }
26010
26011 // Store the components in the stack so that they can be used to check
26012 // against other clauses later on.
26013 Expr *Component = SimpleRefExpr;
26014 auto *VD = dyn_cast<VarDecl>(Val: D);
26015 if (VD && (isa<ArraySectionExpr>(Val: RefExpr->IgnoreParenImpCasts()) ||
26016 isa<ArraySubscriptExpr>(Val: RefExpr->IgnoreParenImpCasts())))
26017 Component =
26018 SemaRef.DefaultFunctionArrayLvalueConversion(E: SimpleRefExpr).get();
26019 OMPClauseMappableExprCommon::MappableComponent MC(
26020 Component, D, /*IsNonContiguous=*/false);
26021 DSAStack->addMappableExpressionComponents(
26022 VD: D, Components: MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
26023
26024 // Record the expression we've just processed.
26025 if (!VD && !SemaRef.CurContext->isDependentContext()) {
26026 DeclRefExpr *Ref =
26027 buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
26028 assert(Ref && "has_device_addr capture failed");
26029 MVLI.ProcessedVarList.push_back(Elt: Ref);
26030 } else
26031 MVLI.ProcessedVarList.push_back(Elt: RefExpr->IgnoreParens());
26032
26033 // Create a mappable component for the list item. List items in this clause
26034 // only need a component. We use a null declaration to signal fields in
26035 // 'this'.
26036 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
26037 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
26038 "Unexpected device pointer expression!");
26039 MVLI.VarBaseDeclarations.push_back(
26040 Elt: isa<DeclRefExpr>(Val: SimpleRefExpr) ? D : nullptr);
26041 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
26042 MVLI.VarComponents.back().push_back(Elt: MC);
26043 }
26044
26045 if (MVLI.ProcessedVarList.empty())
26046 return nullptr;
26047
26048 return OMPHasDeviceAddrClause::Create(
26049 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
26050 ComponentLists: MVLI.VarComponents);
26051}
26052
26053OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause(
26054 Expr *Allocator, Expr *Alignment,
26055 OpenMPAllocateClauseModifier FirstAllocateModifier,
26056 SourceLocation FirstAllocateModifierLoc,
26057 OpenMPAllocateClauseModifier SecondAllocateModifier,
26058 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
26059 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
26060 SourceLocation EndLoc) {
26061 if (Allocator) {
26062 // Allocator expression is dependent - skip it for now and build the
26063 // allocator when instantiated.
26064 bool AllocDependent =
26065 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
26066 Allocator->isInstantiationDependent() ||
26067 Allocator->containsUnexpandedParameterPack());
26068 if (!AllocDependent) {
26069 // OpenMP [2.11.4 allocate Clause, Description]
26070 // allocator is an expression of omp_allocator_handle_t type.
26071 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: Allocator->getExprLoc(), DSAStack))
26072 return nullptr;
26073
26074 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(E: Allocator);
26075 if (AllocatorRes.isInvalid())
26076 return nullptr;
26077 AllocatorRes = SemaRef.PerformImplicitConversion(
26078 From: AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
26079 Action: AssignmentAction::Initializing,
26080 /*AllowExplicit=*/true);
26081 if (AllocatorRes.isInvalid())
26082 return nullptr;
26083 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
26084 }
26085 } else {
26086 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
26087 // allocate clauses that appear on a target construct or on constructs in a
26088 // target region must specify an allocator expression unless a requires
26089 // directive with the dynamic_allocators clause is present in the same
26090 // compilation unit.
26091 if (getLangOpts().OpenMPIsTargetDevice &&
26092 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
26093 SemaRef.targetDiag(Loc: StartLoc, DiagID: diag::err_expected_allocator_expression);
26094 }
26095 if (Alignment) {
26096 bool AlignmentDependent = Alignment->isTypeDependent() ||
26097 Alignment->isValueDependent() ||
26098 Alignment->isInstantiationDependent() ||
26099 Alignment->containsUnexpandedParameterPack();
26100 if (!AlignmentDependent) {
26101 ExprResult AlignResult =
26102 VerifyPositiveIntegerConstantInClause(E: Alignment, CKind: OMPC_allocate);
26103 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
26104 }
26105 }
26106 // Analyze and build list of variables.
26107 SmallVector<Expr *, 8> Vars;
26108 for (Expr *RefExpr : VarList) {
26109 assert(RefExpr && "NULL expr in OpenMP allocate clause.");
26110 SourceLocation ELoc;
26111 SourceRange ERange;
26112 Expr *SimpleRefExpr = RefExpr;
26113 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
26114 if (Res.second) {
26115 // It will be analyzed later.
26116 Vars.push_back(Elt: RefExpr);
26117 }
26118 ValueDecl *D = Res.first;
26119 if (!D)
26120 continue;
26121
26122 auto *VD = dyn_cast<VarDecl>(Val: D);
26123 DeclRefExpr *Ref = nullptr;
26124 if (!VD && !SemaRef.CurContext->isDependentContext())
26125 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
26126 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
26127 ? RefExpr->IgnoreParens()
26128 : Ref);
26129 }
26130
26131 if (Vars.empty())
26132 return nullptr;
26133
26134 if (Allocator)
26135 DSAStack->addInnerAllocatorExpr(E: Allocator);
26136
26137 return OMPAllocateClause::Create(
26138 C: getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
26139 Modifier1: FirstAllocateModifier, Modifier1Loc: FirstAllocateModifierLoc, Modifier2: SecondAllocateModifier,
26140 Modifier2Loc: SecondAllocateModifierLoc, EndLoc, VL: Vars);
26141}
26142
26143OMPClause *SemaOpenMP::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
26144 SourceLocation StartLoc,
26145 SourceLocation LParenLoc,
26146 SourceLocation EndLoc) {
26147 SmallVector<Expr *, 8> Vars;
26148 for (Expr *RefExpr : VarList) {
26149 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
26150 SourceLocation ELoc;
26151 SourceRange ERange;
26152 Expr *SimpleRefExpr = RefExpr;
26153 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
26154 if (Res.second)
26155 // It will be analyzed later.
26156 Vars.push_back(Elt: RefExpr);
26157 ValueDecl *D = Res.first;
26158 if (!D)
26159 continue;
26160
26161 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
26162 // A list-item cannot appear in more than one nontemporal clause.
26163 if (const Expr *PrevRef =
26164 DSAStack->addUniqueNontemporal(D, NewDE: SimpleRefExpr)) {
26165 Diag(Loc: ELoc, DiagID: diag::err_omp_used_in_clause_twice)
26166 << 0 << getOpenMPClauseNameForDiag(C: OMPC_nontemporal) << ERange;
26167 Diag(Loc: PrevRef->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
26168 << getOpenMPClauseNameForDiag(C: OMPC_nontemporal);
26169 continue;
26170 }
26171
26172 Vars.push_back(Elt: RefExpr);
26173 }
26174
26175 if (Vars.empty())
26176 return nullptr;
26177
26178 return OMPNontemporalClause::Create(C: getASTContext(), StartLoc, LParenLoc,
26179 EndLoc, VL: Vars);
26180}
26181
26182StmtResult SemaOpenMP::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
26183 Stmt *AStmt,
26184 SourceLocation StartLoc,
26185 SourceLocation EndLoc) {
26186 if (!AStmt)
26187 return StmtError();
26188
26189 SemaRef.setFunctionHasBranchProtectedScope();
26190
26191 return OMPScopeDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
26192 AssociatedStmt: AStmt);
26193}
26194
26195OMPClause *SemaOpenMP::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
26196 SourceLocation StartLoc,
26197 SourceLocation LParenLoc,
26198 SourceLocation EndLoc) {
26199 SmallVector<Expr *, 8> Vars;
26200 for (Expr *RefExpr : VarList) {
26201 assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
26202 SourceLocation ELoc;
26203 SourceRange ERange;
26204 Expr *SimpleRefExpr = RefExpr;
26205 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
26206 /*AllowArraySection=*/true);
26207 if (Res.second)
26208 // It will be analyzed later.
26209 Vars.push_back(Elt: RefExpr);
26210 ValueDecl *D = Res.first;
26211 if (!D)
26212 continue;
26213
26214 const DSAStackTy::DSAVarData DVar =
26215 DSAStack->getTopDSA(D, /*FromParent=*/true);
26216 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
26217 // A list item that appears in the inclusive or exclusive clause must appear
26218 // in a reduction clause with the inscan modifier on the enclosing
26219 // worksharing-loop, worksharing-loop SIMD, or simd construct.
26220 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
26221 Diag(Loc: ELoc, DiagID: diag::err_omp_inclusive_exclusive_not_reduction)
26222 << RefExpr->getSourceRange();
26223
26224 if (DSAStack->getParentDirective() != OMPD_unknown)
26225 DSAStack->markDeclAsUsedInScanDirective(D);
26226 Vars.push_back(Elt: RefExpr);
26227 }
26228
26229 if (Vars.empty())
26230 return nullptr;
26231
26232 return OMPInclusiveClause::Create(C: getASTContext(), StartLoc, LParenLoc,
26233 EndLoc, VL: Vars);
26234}
26235
26236OMPClause *SemaOpenMP::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
26237 SourceLocation StartLoc,
26238 SourceLocation LParenLoc,
26239 SourceLocation EndLoc) {
26240 SmallVector<Expr *, 8> Vars;
26241 for (Expr *RefExpr : VarList) {
26242 assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
26243 SourceLocation ELoc;
26244 SourceRange ERange;
26245 Expr *SimpleRefExpr = RefExpr;
26246 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
26247 /*AllowArraySection=*/true);
26248 if (Res.second)
26249 // It will be analyzed later.
26250 Vars.push_back(Elt: RefExpr);
26251 ValueDecl *D = Res.first;
26252 if (!D)
26253 continue;
26254
26255 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
26256 DSAStackTy::DSAVarData DVar;
26257 if (ParentDirective != OMPD_unknown)
26258 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
26259 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
26260 // A list item that appears in the inclusive or exclusive clause must appear
26261 // in a reduction clause with the inscan modifier on the enclosing
26262 // worksharing-loop, worksharing-loop SIMD, or simd construct.
26263 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
26264 DVar.Modifier != OMPC_REDUCTION_inscan) {
26265 Diag(Loc: ELoc, DiagID: diag::err_omp_inclusive_exclusive_not_reduction)
26266 << RefExpr->getSourceRange();
26267 } else {
26268 DSAStack->markDeclAsUsedInScanDirective(D);
26269 }
26270 Vars.push_back(Elt: RefExpr);
26271 }
26272
26273 if (Vars.empty())
26274 return nullptr;
26275
26276 return OMPExclusiveClause::Create(C: getASTContext(), StartLoc, LParenLoc,
26277 EndLoc, VL: Vars);
26278}
26279
26280/// Tries to find omp_alloctrait_t type.
26281static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
26282 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
26283 if (!OMPAlloctraitT.isNull())
26284 return true;
26285 IdentifierInfo &II = S.PP.getIdentifierTable().get(Name: "omp_alloctrait_t");
26286 ParsedType PT = S.getTypeName(II, NameLoc: Loc, S: S.getCurScope());
26287 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
26288 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
26289 return false;
26290 }
26291 Stack->setOMPAlloctraitT(PT.get());
26292 return true;
26293}
26294
26295OMPClause *SemaOpenMP::ActOnOpenMPUsesAllocatorClause(
26296 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
26297 ArrayRef<UsesAllocatorsData> Data) {
26298 ASTContext &Context = getASTContext();
26299 // OpenMP [2.12.5, target Construct]
26300 // allocator is an identifier of omp_allocator_handle_t type.
26301 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: StartLoc, DSAStack))
26302 return nullptr;
26303 // OpenMP [2.12.5, target Construct]
26304 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
26305 if (llvm::any_of(
26306 Range&: Data,
26307 P: [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
26308 !findOMPAlloctraitT(S&: SemaRef, Loc: StartLoc, DSAStack))
26309 return nullptr;
26310 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
26311 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
26312 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
26313 StringRef Allocator =
26314 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(Val: AllocatorKind);
26315 DeclarationName AllocatorName = &Context.Idents.get(Name: Allocator);
26316 PredefinedAllocators.insert(Ptr: SemaRef.LookupSingleName(
26317 S: SemaRef.TUScope, Name: AllocatorName, Loc: StartLoc, NameKind: Sema::LookupAnyName));
26318 }
26319
26320 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
26321 for (const UsesAllocatorsData &D : Data) {
26322 Expr *AllocatorExpr = nullptr;
26323 // Check allocator expression.
26324 if (D.Allocator->isTypeDependent()) {
26325 AllocatorExpr = D.Allocator;
26326 } else {
26327 // Traits were specified - need to assign new allocator to the specified
26328 // allocator, so it must be an lvalue.
26329 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
26330 auto *DRE = dyn_cast<DeclRefExpr>(Val: AllocatorExpr);
26331 bool IsPredefinedAllocator = false;
26332 if (DRE) {
26333 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
26334 getAllocatorKind(S&: SemaRef, DSAStack, Allocator: AllocatorExpr);
26335 IsPredefinedAllocator =
26336 AllocatorTy !=
26337 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
26338 }
26339 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
26340 QualType AllocatorExprType = AllocatorExpr->getType();
26341 bool IsTypeCompatible = IsPredefinedAllocator;
26342 IsTypeCompatible = IsTypeCompatible ||
26343 Context.hasSameUnqualifiedType(T1: AllocatorExprType,
26344 T2: OMPAllocatorHandleT);
26345 IsTypeCompatible =
26346 IsTypeCompatible ||
26347 Context.typesAreCompatible(T1: AllocatorExprType, T2: OMPAllocatorHandleT);
26348 bool IsNonConstantLValue =
26349 !AllocatorExprType.isConstant(Ctx: Context) && AllocatorExpr->isLValue();
26350 if (!DRE || !IsTypeCompatible ||
26351 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
26352 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::err_omp_var_expected)
26353 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
26354 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
26355 continue;
26356 }
26357 // OpenMP [2.12.5, target Construct]
26358 // Predefined allocators appearing in a uses_allocators clause cannot have
26359 // traits specified.
26360 if (IsPredefinedAllocator && D.AllocatorTraits) {
26361 Diag(Loc: D.AllocatorTraits->getExprLoc(),
26362 DiagID: diag::err_omp_predefined_allocator_with_traits)
26363 << D.AllocatorTraits->getSourceRange();
26364 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::note_omp_predefined_allocator)
26365 << cast<NamedDecl>(Val: DRE->getDecl())->getName()
26366 << D.Allocator->getSourceRange();
26367 continue;
26368 }
26369 // OpenMP [2.12.5, target Construct]
26370 // Non-predefined allocators appearing in a uses_allocators clause must
26371 // have traits specified.
26372 if (getLangOpts().OpenMP < 52) {
26373 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
26374 Diag(Loc: D.Allocator->getExprLoc(),
26375 DiagID: diag::err_omp_nonpredefined_allocator_without_traits);
26376 continue;
26377 }
26378 }
26379 // No allocator traits - just convert it to rvalue.
26380 if (!D.AllocatorTraits)
26381 AllocatorExpr = SemaRef.DefaultLvalueConversion(E: AllocatorExpr).get();
26382 DSAStack->addUsesAllocatorsDecl(
26383 D: DRE->getDecl(),
26384 Kind: IsPredefinedAllocator
26385 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
26386 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
26387 }
26388 Expr *AllocatorTraitsExpr = nullptr;
26389 if (D.AllocatorTraits) {
26390 if (D.AllocatorTraits->isTypeDependent()) {
26391 AllocatorTraitsExpr = D.AllocatorTraits;
26392 } else {
26393 // OpenMP [2.12.5, target Construct]
26394 // Arrays that contain allocator traits that appear in a uses_allocators
26395 // clause must be constant arrays, have constant values and be defined
26396 // in the same scope as the construct in which the clause appears.
26397 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
26398 // Check that traits expr is a constant array.
26399 QualType TraitTy;
26400 if (const ArrayType *Ty =
26401 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
26402 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Val: Ty))
26403 TraitTy = ConstArrayTy->getElementType();
26404 if (TraitTy.isNull() ||
26405 !(Context.hasSameUnqualifiedType(T1: TraitTy,
26406 DSAStack->getOMPAlloctraitT()) ||
26407 Context.typesAreCompatible(T1: TraitTy, DSAStack->getOMPAlloctraitT(),
26408 /*CompareUnqualified=*/true))) {
26409 Diag(Loc: D.AllocatorTraits->getExprLoc(),
26410 DiagID: diag::err_omp_expected_array_alloctraits)
26411 << AllocatorTraitsExpr->getType();
26412 continue;
26413 }
26414 // Do not map by default allocator traits if it is a standalone
26415 // variable.
26416 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: AllocatorTraitsExpr))
26417 DSAStack->addUsesAllocatorsDecl(
26418 D: DRE->getDecl(),
26419 Kind: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
26420 }
26421 }
26422 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
26423 NewD.Allocator = AllocatorExpr;
26424 NewD.AllocatorTraits = AllocatorTraitsExpr;
26425 NewD.LParenLoc = D.LParenLoc;
26426 NewD.RParenLoc = D.RParenLoc;
26427 }
26428 return OMPUsesAllocatorsClause::Create(C: getASTContext(), StartLoc, LParenLoc,
26429 EndLoc, Data: NewData);
26430}
26431
26432OMPClause *SemaOpenMP::ActOnOpenMPAffinityClause(
26433 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
26434 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
26435 SmallVector<Expr *, 8> Vars;
26436 for (Expr *RefExpr : Locators) {
26437 assert(RefExpr && "NULL expr in OpenMP affinity clause.");
26438 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr) || RefExpr->isTypeDependent()) {
26439 // It will be analyzed later.
26440 Vars.push_back(Elt: RefExpr);
26441 continue;
26442 }
26443
26444 SourceLocation ELoc = RefExpr->getExprLoc();
26445 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
26446
26447 if (!SimpleExpr->isLValue()) {
26448 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
26449 << 1 << 0 << RefExpr->getSourceRange();
26450 continue;
26451 }
26452
26453 ExprResult Res;
26454 {
26455 Sema::TentativeAnalysisScope Trap(SemaRef);
26456 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: SimpleExpr);
26457 }
26458 if (!Res.isUsable() && !isa<ArraySectionExpr>(Val: SimpleExpr) &&
26459 !isa<OMPArrayShapingExpr>(Val: SimpleExpr)) {
26460 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
26461 << 1 << 0 << RefExpr->getSourceRange();
26462 continue;
26463 }
26464 Vars.push_back(Elt: SimpleExpr);
26465 }
26466
26467 return OMPAffinityClause::Create(C: getASTContext(), StartLoc, LParenLoc,
26468 ColonLoc, EndLoc, Modifier, Locators: Vars);
26469}
26470
26471OMPClause *SemaOpenMP::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
26472 SourceLocation KindLoc,
26473 SourceLocation StartLoc,
26474 SourceLocation LParenLoc,
26475 SourceLocation EndLoc) {
26476 if (Kind == OMPC_BIND_unknown) {
26477 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
26478 << getListOfPossibleValues(K: OMPC_bind, /*First=*/0,
26479 /*Last=*/unsigned(OMPC_BIND_unknown))
26480 << getOpenMPClauseNameForDiag(C: OMPC_bind);
26481 return nullptr;
26482 }
26483
26484 return OMPBindClause::Create(C: getASTContext(), K: Kind, KLoc: KindLoc, StartLoc,
26485 LParenLoc, EndLoc);
26486}
26487
26488OMPClause *SemaOpenMP::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
26489 SourceLocation StartLoc,
26490 SourceLocation LParenLoc,
26491 SourceLocation EndLoc) {
26492 Expr *ValExpr = Size;
26493 Stmt *HelperValStmt = nullptr;
26494
26495 // OpenMP [2.5, Restrictions]
26496 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
26497 // value.
26498 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_ompx_dyn_cgroup_mem,
26499 /*StrictlyPositive=*/false))
26500 return nullptr;
26501
26502 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
26503 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
26504 DKind, CKind: OMPC_ompx_dyn_cgroup_mem, OMPVersion: getLangOpts().getOpenMPVersion());
26505 if (CaptureRegion != OMPD_unknown &&
26506 !SemaRef.CurContext->isDependentContext()) {
26507 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
26508 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26509 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
26510 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
26511 }
26512
26513 return new (getASTContext()) OMPXDynCGroupMemClause(
26514 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
26515}
26516
26517OMPClause *SemaOpenMP::ActOnOpenMPDynGroupprivateClause(
26518 OpenMPDynGroupprivateClauseModifier M1,
26519 OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size,
26520 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
26521 SourceLocation M2Loc, SourceLocation EndLoc) {
26522
26523 if ((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ||
26524 (M2Loc.isValid() && M2 == OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown)) {
26525 std::string Values = getListOfPossibleValues(
26526 K: OMPC_dyn_groupprivate, /*First=*/0, Last: OMPC_DYN_GROUPPRIVATE_unknown);
26527 Diag(Loc: (M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ? M1Loc
26528 : M2Loc,
26529 DiagID: diag::err_omp_unexpected_clause_value)
26530 << Values << getOpenMPClauseName(C: OMPC_dyn_groupprivate);
26531 return nullptr;
26532 }
26533
26534 Expr *ValExpr = Size;
26535 Stmt *HelperValStmt = nullptr;
26536
26537 // OpenMP [2.5, Restrictions]
26538 // The dyn_groupprivate expression must evaluate to a positive integer
26539 // value.
26540 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_dyn_groupprivate,
26541 /*StrictlyPositive=*/false))
26542 return nullptr;
26543
26544 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
26545 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
26546 DKind, CKind: OMPC_dyn_groupprivate, OMPVersion: getLangOpts().getOpenMPVersion());
26547 if (CaptureRegion != OMPD_unknown &&
26548 !SemaRef.CurContext->isDependentContext()) {
26549 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
26550 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26551 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
26552 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
26553 }
26554
26555 return new (getASTContext()) OMPDynGroupprivateClause(
26556 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
26557 M1Loc, M2, M2Loc);
26558}
26559
26560OMPClause *SemaOpenMP::ActOnOpenMPDoacrossClause(
26561 OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
26562 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
26563 SourceLocation LParenLoc, SourceLocation EndLoc) {
26564
26565 if (DSAStack->getCurrentDirective() == OMPD_ordered_standalone &&
26566 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
26567 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
26568 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
26569 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
26570 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(C: OMPC_doacross);
26571 return nullptr;
26572 }
26573
26574 SmallVector<Expr *, 8> Vars;
26575 DSAStackTy::OperatorOffsetTy OpsOffs;
26576 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
26577 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
26578 SemaRef,
26579 IsSource: DepType == OMPC_DOACROSS_source ||
26580 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
26581 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
26582 VarList, DSAStack, EndLoc);
26583 Vars = VarOffset.Vars;
26584 OpsOffs = VarOffset.OpsOffs;
26585 TotalDepCount = VarOffset.TotalDepCount;
26586 auto *C = OMPDoacrossClause::Create(C: getASTContext(), StartLoc, LParenLoc,
26587 EndLoc, DepType, DepLoc, ColonLoc, VL: Vars,
26588 NumLoops: TotalDepCount.getZExtValue());
26589 if (DSAStack->isParentOrderedRegion())
26590 DSAStack->addDoacrossDependClause(C, OpsOffs);
26591 return C;
26592}
26593
26594OMPClause *SemaOpenMP::ActOnOpenMPXAttributeClause(ArrayRef<const Attr *> Attrs,
26595 SourceLocation StartLoc,
26596 SourceLocation LParenLoc,
26597 SourceLocation EndLoc) {
26598 return new (getASTContext())
26599 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
26600}
26601
26602OMPClause *SemaOpenMP::ActOnOpenMPXBareClause(SourceLocation StartLoc,
26603 SourceLocation EndLoc) {
26604 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
26605}
26606
26607OMPClause *SemaOpenMP::ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc,
26608 SourceLocation LParenLoc,
26609 SourceLocation EndLoc) {
26610 if (E->HasSideEffects(Ctx: getASTContext()))
26611 Diag(Loc: E->getBeginLoc(), DiagID: diag::warn_assume_side_effects)
26612 << "holds" << E->getSourceRange();
26613 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
26614}
26615
26616OMPClause *SemaOpenMP::ActOnOpenMPDirectivePresenceClause(
26617 OpenMPClauseKind CK, llvm::ArrayRef<OpenMPDirectiveKind> DKVec,
26618 SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc) {
26619 switch (CK) {
26620 case OMPC_absent:
26621 return OMPAbsentClause::Create(C: getASTContext(), DKVec, Loc, LLoc, RLoc);
26622 case OMPC_contains:
26623 return OMPContainsClause::Create(C: getASTContext(), DKVec, Loc, LLoc, RLoc);
26624 default:
26625 llvm_unreachable("Unexpected OpenMP clause");
26626 }
26627}
26628
26629OMPClause *SemaOpenMP::ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK,
26630 SourceLocation Loc,
26631 SourceLocation RLoc) {
26632 switch (CK) {
26633 case OMPC_no_openmp:
26634 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
26635 case OMPC_no_openmp_routines:
26636 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
26637 case OMPC_no_parallelism:
26638 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
26639 case OMPC_no_openmp_constructs:
26640 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
26641 default:
26642 llvm_unreachable("Unexpected OpenMP clause");
26643 }
26644}
26645
26646ExprResult SemaOpenMP::ActOnOMPArraySectionExpr(
26647 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
26648 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
26649 Expr *Stride, SourceLocation RBLoc) {
26650 ASTContext &Context = getASTContext();
26651 if (Base->hasPlaceholderType() &&
26652 !Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
26653 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base);
26654 if (Result.isInvalid())
26655 return ExprError();
26656 Base = Result.get();
26657 }
26658 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
26659 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: LowerBound);
26660 if (Result.isInvalid())
26661 return ExprError();
26662 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26663 if (Result.isInvalid())
26664 return ExprError();
26665 LowerBound = Result.get();
26666 }
26667 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
26668 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Length);
26669 if (Result.isInvalid())
26670 return ExprError();
26671 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26672 if (Result.isInvalid())
26673 return ExprError();
26674 Length = Result.get();
26675 }
26676 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
26677 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Stride);
26678 if (Result.isInvalid())
26679 return ExprError();
26680 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26681 if (Result.isInvalid())
26682 return ExprError();
26683 Stride = Result.get();
26684 }
26685
26686 // Build an unanalyzed expression if either operand is type-dependent.
26687 if (Base->isTypeDependent() ||
26688 (LowerBound &&
26689 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
26690 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
26691 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
26692 return new (Context) ArraySectionExpr(
26693 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
26694 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
26695 }
26696
26697 // Perform default conversions.
26698 QualType OriginalTy = ArraySectionExpr::getBaseOriginalType(Base);
26699 QualType ResultTy;
26700 if (OriginalTy->isAnyPointerType()) {
26701 ResultTy = OriginalTy->getPointeeType();
26702 } else if (OriginalTy->isArrayType()) {
26703 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
26704 } else {
26705 return ExprError(
26706 Diag(Loc: Base->getExprLoc(), DiagID: diag::err_omp_typecheck_section_value)
26707 << Base->getSourceRange());
26708 }
26709 // C99 6.5.2.1p1
26710 if (LowerBound) {
26711 auto Res = PerformOpenMPImplicitIntegerConversion(Loc: LowerBound->getExprLoc(),
26712 Op: LowerBound);
26713 if (Res.isInvalid())
26714 return ExprError(Diag(Loc: LowerBound->getExprLoc(),
26715 DiagID: diag::err_omp_typecheck_section_not_integer)
26716 << 0 << LowerBound->getSourceRange());
26717 LowerBound = Res.get();
26718
26719 if (LowerBound->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
26720 LowerBound->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
26721 Diag(Loc: LowerBound->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
26722 << 0 << LowerBound->getSourceRange();
26723 }
26724 if (Length) {
26725 auto Res =
26726 PerformOpenMPImplicitIntegerConversion(Loc: Length->getExprLoc(), Op: Length);
26727 if (Res.isInvalid())
26728 return ExprError(Diag(Loc: Length->getExprLoc(),
26729 DiagID: diag::err_omp_typecheck_section_not_integer)
26730 << 1 << Length->getSourceRange());
26731 Length = Res.get();
26732
26733 if (Length->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
26734 Length->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
26735 Diag(Loc: Length->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
26736 << 1 << Length->getSourceRange();
26737 }
26738 if (Stride) {
26739 ExprResult Res =
26740 PerformOpenMPImplicitIntegerConversion(Loc: Stride->getExprLoc(), Op: Stride);
26741 if (Res.isInvalid())
26742 return ExprError(Diag(Loc: Stride->getExprLoc(),
26743 DiagID: diag::err_omp_typecheck_section_not_integer)
26744 << 1 << Stride->getSourceRange());
26745 Stride = Res.get();
26746
26747 if (Stride->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
26748 Stride->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
26749 Diag(Loc: Stride->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
26750 << 1 << Stride->getSourceRange();
26751 }
26752
26753 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
26754 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
26755 // type. Note that functions are not objects, and that (in C99 parlance)
26756 // incomplete types are not object types.
26757 if (ResultTy->isFunctionType()) {
26758 Diag(Loc: Base->getExprLoc(), DiagID: diag::err_omp_section_function_type)
26759 << ResultTy << Base->getSourceRange();
26760 return ExprError();
26761 }
26762
26763 if (SemaRef.RequireCompleteType(Loc: Base->getExprLoc(), T: ResultTy,
26764 DiagID: diag::err_omp_section_incomplete_type, Args: Base))
26765 return ExprError();
26766
26767 if (LowerBound && !OriginalTy->isAnyPointerType()) {
26768 Expr::EvalResult Result;
26769 if (LowerBound->EvaluateAsInt(Result, Ctx: Context)) {
26770 // OpenMP 5.0, [2.1.5 Array Sections]
26771 // The array section must be a subset of the original array.
26772 llvm::APSInt LowerBoundValue = Result.Val.getInt();
26773 if (LowerBoundValue.isNegative()) {
26774 Diag(Loc: LowerBound->getExprLoc(),
26775 DiagID: diag::err_omp_section_not_subset_of_array)
26776 << LowerBound->getSourceRange();
26777 return ExprError();
26778 }
26779 }
26780 }
26781
26782 if (Length) {
26783 Expr::EvalResult Result;
26784 if (Length->EvaluateAsInt(Result, Ctx: Context)) {
26785 // OpenMP 5.0, [2.1.5 Array Sections]
26786 // The length must evaluate to non-negative integers.
26787 llvm::APSInt LengthValue = Result.Val.getInt();
26788 if (LengthValue.isNegative()) {
26789 Diag(Loc: Length->getExprLoc(), DiagID: diag::err_omp_section_length_negative)
26790 << toString(I: LengthValue, /*Radix=*/10, /*Signed=*/true)
26791 << Length->getSourceRange();
26792 return ExprError();
26793 }
26794 }
26795 } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
26796 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
26797 !OriginalTy->isVariableArrayType()))) {
26798 // OpenMP 5.0, [2.1.5 Array Sections]
26799 // When the size of the array dimension is not known, the length must be
26800 // specified explicitly.
26801 Diag(Loc: ColonLocFirst, DiagID: diag::err_omp_section_length_undefined)
26802 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
26803 return ExprError();
26804 }
26805
26806 if (Stride) {
26807 Expr::EvalResult Result;
26808 if (Stride->EvaluateAsInt(Result, Ctx: Context)) {
26809 // OpenMP 5.0, [2.1.5 Array Sections]
26810 // The stride must evaluate to a positive integer.
26811 llvm::APSInt StrideValue = Result.Val.getInt();
26812 if (!StrideValue.isStrictlyPositive()) {
26813 Diag(Loc: Stride->getExprLoc(), DiagID: diag::err_omp_section_stride_non_positive)
26814 << toString(I: StrideValue, /*Radix=*/10, /*Signed=*/true)
26815 << Stride->getSourceRange();
26816 return ExprError();
26817 }
26818 }
26819 }
26820
26821 if (!Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
26822 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(E: Base);
26823 if (Result.isInvalid())
26824 return ExprError();
26825 Base = Result.get();
26826 }
26827 return new (Context) ArraySectionExpr(
26828 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
26829 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
26830}
26831
26832ExprResult SemaOpenMP::ActOnOMPArrayShapingExpr(
26833 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
26834 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
26835 ASTContext &Context = getASTContext();
26836 if (Base->hasPlaceholderType()) {
26837 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base);
26838 if (Result.isInvalid())
26839 return ExprError();
26840 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26841 if (Result.isInvalid())
26842 return ExprError();
26843 Base = Result.get();
26844 }
26845 QualType BaseTy = Base->getType();
26846 // Delay analysis of the types/expressions if instantiation/specialization is
26847 // required.
26848 if (!BaseTy->isPointerType() && Base->isTypeDependent())
26849 return OMPArrayShapingExpr::Create(Context, T: Context.DependentTy, Op: Base,
26850 L: LParenLoc, R: RParenLoc, Dims, BracketRanges: Brackets);
26851 if (!BaseTy->isPointerType() ||
26852 (!Base->isTypeDependent() &&
26853 BaseTy->getPointeeType()->isIncompleteType()))
26854 return ExprError(Diag(Loc: Base->getExprLoc(),
26855 DiagID: diag::err_omp_non_pointer_type_array_shaping_base)
26856 << Base->getSourceRange());
26857
26858 SmallVector<Expr *, 4> NewDims;
26859 bool ErrorFound = false;
26860 for (Expr *Dim : Dims) {
26861 if (Dim->hasPlaceholderType()) {
26862 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Dim);
26863 if (Result.isInvalid()) {
26864 ErrorFound = true;
26865 continue;
26866 }
26867 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26868 if (Result.isInvalid()) {
26869 ErrorFound = true;
26870 continue;
26871 }
26872 Dim = Result.get();
26873 }
26874 if (!Dim->isTypeDependent()) {
26875 ExprResult Result =
26876 PerformOpenMPImplicitIntegerConversion(Loc: Dim->getExprLoc(), Op: Dim);
26877 if (Result.isInvalid()) {
26878 ErrorFound = true;
26879 Diag(Loc: Dim->getExprLoc(), DiagID: diag::err_omp_typecheck_shaping_not_integer)
26880 << Dim->getSourceRange();
26881 continue;
26882 }
26883 Dim = Result.get();
26884 Expr::EvalResult EvResult;
26885 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(Result&: EvResult, Ctx: Context)) {
26886 // OpenMP 5.0, [2.1.4 Array Shaping]
26887 // Each si is an integral type expression that must evaluate to a
26888 // positive integer.
26889 llvm::APSInt Value = EvResult.Val.getInt();
26890 if (!Value.isStrictlyPositive()) {
26891 Diag(Loc: Dim->getExprLoc(), DiagID: diag::err_omp_shaping_dimension_not_positive)
26892 << toString(I: Value, /*Radix=*/10, /*Signed=*/true)
26893 << Dim->getSourceRange();
26894 ErrorFound = true;
26895 continue;
26896 }
26897 }
26898 }
26899 NewDims.push_back(Elt: Dim);
26900 }
26901 if (ErrorFound)
26902 return ExprError();
26903 return OMPArrayShapingExpr::Create(Context, T: Context.OMPArrayShapingTy, Op: Base,
26904 L: LParenLoc, R: RParenLoc, Dims: NewDims, BracketRanges: Brackets);
26905}
26906
26907ExprResult SemaOpenMP::ActOnOMPIteratorExpr(Scope *S,
26908 SourceLocation IteratorKwLoc,
26909 SourceLocation LLoc,
26910 SourceLocation RLoc,
26911 ArrayRef<OMPIteratorData> Data) {
26912 ASTContext &Context = getASTContext();
26913 SmallVector<OMPIteratorExpr::IteratorDefinition, 4> ID;
26914 bool IsCorrect = true;
26915 for (const OMPIteratorData &D : Data) {
26916 TypeSourceInfo *TInfo = nullptr;
26917 SourceLocation StartLoc;
26918 QualType DeclTy;
26919 if (!D.Type.getAsOpaquePtr()) {
26920 // OpenMP 5.0, 2.1.6 Iterators
26921 // In an iterator-specifier, if the iterator-type is not specified then
26922 // the type of that iterator is of int type.
26923 DeclTy = Context.IntTy;
26924 StartLoc = D.DeclIdentLoc;
26925 } else {
26926 DeclTy = Sema::GetTypeFromParser(Ty: D.Type, TInfo: &TInfo);
26927 StartLoc = TInfo->getTypeLoc().getBeginLoc();
26928 }
26929
26930 bool IsDeclTyDependent = DeclTy->isDependentType() ||
26931 DeclTy->containsUnexpandedParameterPack() ||
26932 DeclTy->isInstantiationDependentType();
26933 if (!IsDeclTyDependent) {
26934 if (!DeclTy->isIntegralType(Ctx: Context) && !DeclTy->isAnyPointerType()) {
26935 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
26936 // The iterator-type must be an integral or pointer type.
26937 Diag(Loc: StartLoc, DiagID: diag::err_omp_iterator_not_integral_or_pointer)
26938 << DeclTy;
26939 IsCorrect = false;
26940 continue;
26941 }
26942 if (DeclTy.isConstant(Ctx: Context)) {
26943 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
26944 // The iterator-type must not be const qualified.
26945 Diag(Loc: StartLoc, DiagID: diag::err_omp_iterator_not_integral_or_pointer)
26946 << DeclTy;
26947 IsCorrect = false;
26948 continue;
26949 }
26950 }
26951
26952 // Iterator declaration.
26953 assert(D.DeclIdent && "Identifier expected.");
26954 // Always try to create iterator declarator to avoid extra error messages
26955 // about unknown declarations use.
26956 auto *VD =
26957 VarDecl::Create(C&: Context, DC: SemaRef.CurContext, StartLoc, IdLoc: D.DeclIdentLoc,
26958 Id: D.DeclIdent, T: DeclTy, TInfo, S: SC_None);
26959 VD->setImplicit();
26960 if (S) {
26961 // Check for conflicting previous declaration.
26962 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
26963 LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
26964 RedeclarationKind::ForVisibleRedeclaration);
26965 Previous.suppressDiagnostics();
26966 SemaRef.LookupName(R&: Previous, S);
26967
26968 SemaRef.FilterLookupForScope(R&: Previous, Ctx: SemaRef.CurContext, S,
26969 /*ConsiderLinkage=*/false,
26970 /*AllowInlineNamespace=*/false);
26971 if (!Previous.empty()) {
26972 NamedDecl *Old = Previous.getRepresentativeDecl();
26973 Diag(Loc: D.DeclIdentLoc, DiagID: diag::err_redefinition) << VD->getDeclName();
26974 Diag(Loc: Old->getLocation(), DiagID: diag::note_previous_definition);
26975 } else {
26976 SemaRef.PushOnScopeChains(D: VD, S);
26977 }
26978 } else {
26979 SemaRef.CurContext->addDecl(D: VD);
26980 }
26981
26982 /// Act on the iterator variable declaration.
26983 ActOnOpenMPIteratorVarDecl(VD);
26984
26985 Expr *Begin = D.Range.Begin;
26986 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
26987 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
26988 From: Begin, ToType: DeclTy, Action: AssignmentAction::Converting);
26989 Begin = BeginRes.get();
26990 }
26991 Expr *End = D.Range.End;
26992 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
26993 ExprResult EndRes = SemaRef.PerformImplicitConversion(
26994 From: End, ToType: DeclTy, Action: AssignmentAction::Converting);
26995 End = EndRes.get();
26996 }
26997 Expr *Step = D.Range.Step;
26998 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
26999 if (!Step->getType()->isIntegralType(Ctx: Context)) {
27000 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_iterator_step_not_integral)
27001 << Step << Step->getSourceRange();
27002 IsCorrect = false;
27003 continue;
27004 }
27005 std::optional<llvm::APSInt> Result =
27006 Step->getIntegerConstantExpr(Ctx: Context);
27007 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
27008 // If the step expression of a range-specification equals zero, the
27009 // behavior is unspecified.
27010 if (Result && Result->isZero()) {
27011 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_iterator_step_constant_zero)
27012 << Step << Step->getSourceRange();
27013 IsCorrect = false;
27014 continue;
27015 }
27016 }
27017 if (!Begin || !End || !IsCorrect) {
27018 IsCorrect = false;
27019 continue;
27020 }
27021 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
27022 IDElem.IteratorDecl = VD;
27023 IDElem.AssignmentLoc = D.AssignLoc;
27024 IDElem.Range.Begin = Begin;
27025 IDElem.Range.End = End;
27026 IDElem.Range.Step = Step;
27027 IDElem.ColonLoc = D.ColonLoc;
27028 IDElem.SecondColonLoc = D.SecColonLoc;
27029 }
27030 if (!IsCorrect) {
27031 // Invalidate all created iterator declarations if error is found.
27032 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
27033 if (Decl *ID = D.IteratorDecl)
27034 ID->setInvalidDecl();
27035 }
27036 return ExprError();
27037 }
27038 SmallVector<OMPIteratorHelperData, 4> Helpers;
27039 if (!SemaRef.CurContext->isDependentContext()) {
27040 // Build number of ityeration for each iteration range.
27041 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
27042 // ((Begini-Stepi-1-Endi) / -Stepi);
27043 for (OMPIteratorExpr::IteratorDefinition &D : ID) {
27044 // (Endi - Begini)
27045 ExprResult Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Sub,
27046 LHSExpr: D.Range.End, RHSExpr: D.Range.Begin);
27047 if (!Res.isUsable()) {
27048 IsCorrect = false;
27049 continue;
27050 }
27051 ExprResult St, St1;
27052 if (D.Range.Step) {
27053 St = D.Range.Step;
27054 // (Endi - Begini) + Stepi
27055 Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add, LHSExpr: Res.get(),
27056 RHSExpr: St.get());
27057 if (!Res.isUsable()) {
27058 IsCorrect = false;
27059 continue;
27060 }
27061 // (Endi - Begini) + Stepi - 1
27062 Res = SemaRef.CreateBuiltinBinOp(
27063 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: Res.get(),
27064 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 1).get());
27065 if (!Res.isUsable()) {
27066 IsCorrect = false;
27067 continue;
27068 }
27069 // ((Endi - Begini) + Stepi - 1) / Stepi
27070 Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Div, LHSExpr: Res.get(),
27071 RHSExpr: St.get());
27072 if (!Res.isUsable()) {
27073 IsCorrect = false;
27074 continue;
27075 }
27076 St1 = SemaRef.CreateBuiltinUnaryOp(OpLoc: D.AssignmentLoc, Opc: UO_Minus,
27077 InputExpr: D.Range.Step);
27078 // (Begini - Endi)
27079 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
27080 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: D.Range.Begin, RHSExpr: D.Range.End);
27081 if (!Res1.isUsable()) {
27082 IsCorrect = false;
27083 continue;
27084 }
27085 // (Begini - Endi) - Stepi
27086 Res1 = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add, LHSExpr: Res1.get(),
27087 RHSExpr: St1.get());
27088 if (!Res1.isUsable()) {
27089 IsCorrect = false;
27090 continue;
27091 }
27092 // (Begini - Endi) - Stepi - 1
27093 Res1 = SemaRef.CreateBuiltinBinOp(
27094 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: Res1.get(),
27095 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 1).get());
27096 if (!Res1.isUsable()) {
27097 IsCorrect = false;
27098 continue;
27099 }
27100 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
27101 Res1 = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Div, LHSExpr: Res1.get(),
27102 RHSExpr: St1.get());
27103 if (!Res1.isUsable()) {
27104 IsCorrect = false;
27105 continue;
27106 }
27107 // Stepi > 0.
27108 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
27109 OpLoc: D.AssignmentLoc, Opc: BO_GT, LHSExpr: D.Range.Step,
27110 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 0).get());
27111 if (!CmpRes.isUsable()) {
27112 IsCorrect = false;
27113 continue;
27114 }
27115 Res = SemaRef.ActOnConditionalOp(QuestionLoc: D.AssignmentLoc, ColonLoc: D.AssignmentLoc,
27116 CondExpr: CmpRes.get(), LHSExpr: Res.get(), RHSExpr: Res1.get());
27117 if (!Res.isUsable()) {
27118 IsCorrect = false;
27119 continue;
27120 }
27121 }
27122 Res = SemaRef.ActOnFinishFullExpr(Expr: Res.get(), /*DiscardedValue=*/false);
27123 if (!Res.isUsable()) {
27124 IsCorrect = false;
27125 continue;
27126 }
27127
27128 // Build counter update.
27129 // Build counter.
27130 auto *CounterVD = VarDecl::Create(C&: Context, DC: SemaRef.CurContext,
27131 StartLoc: D.IteratorDecl->getBeginLoc(),
27132 IdLoc: D.IteratorDecl->getBeginLoc(), Id: nullptr,
27133 T: Res.get()->getType(), TInfo: nullptr, S: SC_None);
27134 CounterVD->setImplicit();
27135 ExprResult RefRes =
27136 SemaRef.BuildDeclRefExpr(D: CounterVD, Ty: CounterVD->getType(), VK: VK_LValue,
27137 Loc: D.IteratorDecl->getBeginLoc());
27138 // Build counter update.
27139 // I = Begini + counter * Stepi;
27140 ExprResult UpdateRes;
27141 if (D.Range.Step) {
27142 UpdateRes = SemaRef.CreateBuiltinBinOp(
27143 OpLoc: D.AssignmentLoc, Opc: BO_Mul,
27144 LHSExpr: SemaRef.DefaultLvalueConversion(E: RefRes.get()).get(), RHSExpr: St.get());
27145 } else {
27146 UpdateRes = SemaRef.DefaultLvalueConversion(E: RefRes.get());
27147 }
27148 if (!UpdateRes.isUsable()) {
27149 IsCorrect = false;
27150 continue;
27151 }
27152 UpdateRes = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add,
27153 LHSExpr: D.Range.Begin, RHSExpr: UpdateRes.get());
27154 if (!UpdateRes.isUsable()) {
27155 IsCorrect = false;
27156 continue;
27157 }
27158 ExprResult VDRes =
27159 SemaRef.BuildDeclRefExpr(D: cast<VarDecl>(Val: D.IteratorDecl),
27160 Ty: cast<VarDecl>(Val: D.IteratorDecl)->getType(),
27161 VK: VK_LValue, Loc: D.IteratorDecl->getBeginLoc());
27162 UpdateRes = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Assign,
27163 LHSExpr: VDRes.get(), RHSExpr: UpdateRes.get());
27164 if (!UpdateRes.isUsable()) {
27165 IsCorrect = false;
27166 continue;
27167 }
27168 UpdateRes =
27169 SemaRef.ActOnFinishFullExpr(Expr: UpdateRes.get(), /*DiscardedValue=*/true);
27170 if (!UpdateRes.isUsable()) {
27171 IsCorrect = false;
27172 continue;
27173 }
27174 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
27175 OpLoc: D.AssignmentLoc, Opc: UO_PreInc, InputExpr: RefRes.get());
27176 if (!CounterUpdateRes.isUsable()) {
27177 IsCorrect = false;
27178 continue;
27179 }
27180 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(Expr: CounterUpdateRes.get(),
27181 /*DiscardedValue=*/true);
27182 if (!CounterUpdateRes.isUsable()) {
27183 IsCorrect = false;
27184 continue;
27185 }
27186 OMPIteratorHelperData &HD = Helpers.emplace_back();
27187 HD.CounterVD = CounterVD;
27188 HD.Upper = Res.get();
27189 HD.Update = UpdateRes.get();
27190 HD.CounterUpdate = CounterUpdateRes.get();
27191 }
27192 } else {
27193 Helpers.assign(NumElts: ID.size(), Elt: {});
27194 }
27195 if (!IsCorrect) {
27196 // Invalidate all created iterator declarations if error is found.
27197 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
27198 if (Decl *ID = D.IteratorDecl)
27199 ID->setInvalidDecl();
27200 }
27201 return ExprError();
27202 }
27203 return OMPIteratorExpr::Create(Context, T: Context.OMPIteratorTy, IteratorKwLoc,
27204 L: LLoc, R: RLoc, Data: ID, Helpers);
27205}
27206
27207/// Check if \p AssumptionStr is a known assumption and warn if not.
27208static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc,
27209 StringRef AssumptionStr) {
27210 if (llvm::getKnownAssumptionStrings().count(Key: AssumptionStr))
27211 return;
27212
27213 unsigned BestEditDistance = 3;
27214 StringRef Suggestion;
27215 for (const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
27216 unsigned EditDistance =
27217 AssumptionStr.edit_distance(Other: KnownAssumptionIt.getKey());
27218 if (EditDistance < BestEditDistance) {
27219 Suggestion = KnownAssumptionIt.getKey();
27220 BestEditDistance = EditDistance;
27221 }
27222 }
27223
27224 if (!Suggestion.empty())
27225 S.Diag(Loc, DiagID: diag::warn_omp_assume_attribute_string_unknown_suggested)
27226 << AssumptionStr << Suggestion;
27227 else
27228 S.Diag(Loc, DiagID: diag::warn_omp_assume_attribute_string_unknown)
27229 << AssumptionStr;
27230}
27231
27232void SemaOpenMP::handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL) {
27233 // Handle the case where the attribute has a text message.
27234 StringRef Str;
27235 SourceLocation AttrStrLoc;
27236 if (!SemaRef.checkStringLiteralArgumentAttr(Attr: AL, ArgNum: 0, Str, ArgLocation: &AttrStrLoc))
27237 return;
27238
27239 checkOMPAssumeAttr(S&: SemaRef, Loc: AttrStrLoc, AssumptionStr: Str);
27240
27241 D->addAttr(A: ::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
27242}
27243
27244SemaOpenMP::SemaOpenMP(Sema &S)
27245 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
27246