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/CXXInheritance.h"
21#include "clang/AST/Decl.h"
22#include "clang/AST/DeclCXX.h"
23#include "clang/AST/DeclOpenMP.h"
24#include "clang/AST/DynamicRecursiveASTVisitor.h"
25#include "clang/AST/OpenMPClause.h"
26#include "clang/AST/StmtCXX.h"
27#include "clang/AST/StmtOpenMP.h"
28#include "clang/AST/StmtVisitor.h"
29#include "clang/Basic/DiagnosticSema.h"
30#include "clang/Basic/OpenMPKinds.h"
31#include "clang/Basic/PartialDiagnostic.h"
32#include "clang/Basic/TargetInfo.h"
33#include "clang/Sema/EnterExpressionEvaluationContext.h"
34#include "clang/Sema/Initialization.h"
35#include "clang/Sema/Lookup.h"
36#include "clang/Sema/ParsedAttr.h"
37#include "clang/Sema/Scope.h"
38#include "clang/Sema/ScopeInfo.h"
39#include "clang/Sema/Sema.h"
40#include "llvm/ADT/IndexedMap.h"
41#include "llvm/ADT/PointerEmbeddedInt.h"
42#include "llvm/ADT/STLExtras.h"
43#include "llvm/ADT/Sequence.h"
44#include "llvm/ADT/SetVector.h"
45#include "llvm/ADT/SmallSet.h"
46#include "llvm/ADT/StringExtras.h"
47#include "llvm/Frontend/OpenMP/OMPAssume.h"
48#include "llvm/Frontend/OpenMP/OMPConstants.h"
49#include "llvm/IR/Assumptions.h"
50#include <optional>
51
52using namespace clang;
53using namespace llvm::omp;
54
55//===----------------------------------------------------------------------===//
56// Stack of data-sharing attributes for variables
57//===----------------------------------------------------------------------===//
58
59static const Expr *checkMapClauseExpressionBase(
60 Sema &SemaRef, Expr *E,
61 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
62 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
63
64static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C);
65
66namespace {
67/// Default data sharing attributes, which can be applied to directive.
68enum DefaultDataSharingAttributes {
69 DSA_unspecified = 0, /// Data sharing attribute not specified.
70 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
71 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
72 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
73 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
74};
75
76/// Variable Category attributes to restrict the modifier of the
77/// default clause (DefaultDataSharingAttributes)
78/// Not mentioning any Variable category attribute indicates
79/// the modifier (DefaultDataSharingAttributes) is for all variables.
80enum DefaultDataSharingVCAttributes {
81 DSA_VC_all = 0, /// for all variables.
82 DSA_VC_aggregate, /// for aggregate variables.
83 DSA_VC_pointer, /// for pointer variables.
84 DSA_VC_scalar, /// for scalar variables.
85};
86
87/// Stack for tracking declarations used in OpenMP directives and
88/// clauses and their data-sharing attributes.
89class DSAStackTy {
90public:
91 struct DSAVarData {
92 OpenMPDirectiveKind DKind = OMPD_unknown;
93 OpenMPClauseKind CKind = OMPC_unknown;
94 unsigned Modifier = 0;
95 const Expr *RefExpr = nullptr;
96 DeclRefExpr *PrivateCopy = nullptr;
97 SourceLocation ImplicitDSALoc;
98 bool AppliedToPointee = false;
99 DSAVarData() = default;
100 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
101 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
102 SourceLocation ImplicitDSALoc, unsigned Modifier,
103 bool AppliedToPointee)
104 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
105 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
106 AppliedToPointee(AppliedToPointee) {}
107 };
108 using OperatorOffsetTy =
109 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
110 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
111 /// Kind of the declaration used in the uses_allocators clauses.
112 enum class UsesAllocatorsDeclKind {
113 /// Predefined allocator
114 PredefinedAllocator,
115 /// User-defined allocator
116 UserDefinedAllocator,
117 /// The declaration that represent allocator trait
118 AllocatorTrait,
119 };
120
121private:
122 struct DSAInfo {
123 OpenMPClauseKind Attributes = OMPC_unknown;
124 unsigned Modifier = 0;
125 /// Pointer to a reference expression and a flag which shows that the
126 /// variable is marked as lastprivate(true) or not (false).
127 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
128 DeclRefExpr *PrivateCopy = nullptr;
129 /// true if the attribute is applied to the pointee, not the variable
130 /// itself.
131 bool AppliedToPointee = false;
132 };
133 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
134 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
135 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
136 using LoopControlVariablesMapTy =
137 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
138 /// Struct that associates a component with the clause kind where they are
139 /// found.
140 struct MappedExprComponentTy {
141 OMPClauseMappableExprCommon::MappableExprComponentLists Components;
142 OpenMPClauseKind Kind = OMPC_unknown;
143 };
144 using MappedExprComponentsTy =
145 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
146 using CriticalsWithHintsTy =
147 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
148 struct ReductionData {
149 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
150 SourceRange ReductionRange;
151 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
152 ReductionData() = default;
153 void set(BinaryOperatorKind BO, SourceRange RR) {
154 ReductionRange = RR;
155 ReductionOp = BO;
156 }
157 void set(const Expr *RefExpr, SourceRange RR) {
158 ReductionRange = RR;
159 ReductionOp = RefExpr;
160 }
161 };
162 using DeclReductionMapTy =
163 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
164 struct DefaultmapInfo {
165 OpenMPDefaultmapClauseModifier ImplicitBehavior =
166 OMPC_DEFAULTMAP_MODIFIER_unknown;
167 SourceLocation SLoc;
168 DefaultmapInfo() = default;
169 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
170 : ImplicitBehavior(M), SLoc(Loc) {}
171 };
172
173 struct SharingMapTy {
174 DeclSAMapTy SharingMap;
175 DeclReductionMapTy ReductionMap;
176 UsedRefMapTy AlignedMap;
177 UsedRefMapTy NontemporalMap;
178 MappedExprComponentsTy MappedExprComponents;
179 LoopControlVariablesMapTy LCVMap;
180 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
181 SourceLocation DefaultAttrLoc;
182 DefaultDataSharingVCAttributes DefaultVCAttr = DSA_VC_all;
183 SourceLocation DefaultAttrVCLoc;
184 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
185 OpenMPDirectiveKind Directive = OMPD_unknown;
186 DeclarationNameInfo DirectiveName;
187 Scope *CurScope = nullptr;
188 DeclContext *Context = nullptr;
189 SourceLocation ConstructLoc;
190 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
191 /// get the data (loop counters etc.) about enclosing loop-based construct.
192 /// This data is required during codegen.
193 DoacrossClauseMapTy DoacrossDepends;
194 /// First argument (Expr *) contains optional argument of the
195 /// 'ordered' clause, the second one is true if the regions has 'ordered'
196 /// clause, false otherwise.
197 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
198 bool RegionHasOrderConcurrent = false;
199 unsigned AssociatedLoops = 1;
200 bool HasMutipleLoops = false;
201 const Decl *PossiblyLoopCounter = nullptr;
202 bool NowaitRegion = false;
203 bool UntiedRegion = false;
204 bool CancelRegion = false;
205 bool LoopStart = false;
206 bool BodyComplete = false;
207 SourceLocation PrevScanLocation;
208 SourceLocation PrevOrderedLocation;
209 SourceLocation InnerTeamsRegionLoc;
210 /// Reference to the taskgroup task_reduction reference expression.
211 Expr *TaskgroupReductionRef = nullptr;
212 llvm::DenseSet<QualType> MappedClassesQualTypes;
213 SmallVector<Expr *, 4> InnerUsedAllocators;
214 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
215 /// List of globals marked as declare target link in this target region
216 /// (isOpenMPTargetExecutionDirective(Directive) == true).
217 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
218 /// List of decls used in inclusive/exclusive clauses of the scan directive.
219 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
220 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
221 UsesAllocatorsDecls;
222 /// Data is required on creating capture fields for implicit
223 /// default first|private clause.
224 struct ImplicitDefaultFDInfoTy {
225 /// Field decl.
226 const FieldDecl *FD = nullptr;
227 /// Nesting stack level
228 size_t StackLevel = 0;
229 /// Capture variable decl.
230 VarDecl *VD = nullptr;
231 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
232 VarDecl *VD)
233 : FD(FD), StackLevel(StackLevel), VD(VD) {}
234 };
235 /// List of captured fields
236 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
237 ImplicitDefaultFirstprivateFDs;
238 Expr *DeclareMapperVar = nullptr;
239 SmallVector<VarDecl *, 16> IteratorVarDecls;
240 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
241 Scope *CurScope, SourceLocation Loc)
242 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
243 ConstructLoc(Loc) {}
244 SharingMapTy() = default;
245 };
246
247 using StackTy = SmallVector<SharingMapTy, 4>;
248
249 /// Stack of used declaration and their data-sharing attributes.
250 DeclSAMapTy Threadprivates;
251 DeclSAMapTy Groupprivates;
252 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
253 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
254 /// true, if check for DSA must be from parent directive, false, if
255 /// from current directive.
256 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
257 Sema &SemaRef;
258 bool ForceCapturing = false;
259 /// true if all the variables in the target executable directives must be
260 /// captured by reference.
261 bool ForceCaptureByReferenceInTargetExecutable = false;
262 CriticalsWithHintsTy Criticals;
263 unsigned IgnoredStackElements = 0;
264
265 /// Iterators over the stack iterate in order from innermost to outermost
266 /// directive.
267 using const_iterator = StackTy::const_reverse_iterator;
268 const_iterator begin() const {
269 return Stack.empty() ? const_iterator()
270 : Stack.back().first.rbegin() + IgnoredStackElements;
271 }
272 const_iterator end() const {
273 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
274 }
275 using iterator = StackTy::reverse_iterator;
276 iterator begin() {
277 return Stack.empty() ? iterator()
278 : Stack.back().first.rbegin() + IgnoredStackElements;
279 }
280 iterator end() {
281 return Stack.empty() ? iterator() : Stack.back().first.rend();
282 }
283
284 // Convenience operations to get at the elements of the stack.
285
286 bool isStackEmpty() const {
287 return Stack.empty() ||
288 Stack.back().second != CurrentNonCapturingFunctionScope ||
289 Stack.back().first.size() <= IgnoredStackElements;
290 }
291 size_t getStackSize() const {
292 return isStackEmpty() ? 0
293 : Stack.back().first.size() - IgnoredStackElements;
294 }
295
296 SharingMapTy *getTopOfStackOrNull() {
297 size_t Size = getStackSize();
298 if (Size == 0)
299 return nullptr;
300 return &Stack.back().first[Size - 1];
301 }
302 const SharingMapTy *getTopOfStackOrNull() const {
303 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
304 }
305 SharingMapTy &getTopOfStack() {
306 assert(!isStackEmpty() && "no current directive");
307 return *getTopOfStackOrNull();
308 }
309 const SharingMapTy &getTopOfStack() const {
310 return const_cast<DSAStackTy &>(*this).getTopOfStack();
311 }
312
313 SharingMapTy *getSecondOnStackOrNull() {
314 size_t Size = getStackSize();
315 if (Size <= 1)
316 return nullptr;
317 return &Stack.back().first[Size - 2];
318 }
319 const SharingMapTy *getSecondOnStackOrNull() const {
320 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
321 }
322
323 /// Get the stack element at a certain level (previously returned by
324 /// \c getNestingLevel).
325 ///
326 /// Note that nesting levels count from outermost to innermost, and this is
327 /// the reverse of our iteration order where new inner levels are pushed at
328 /// the front of the stack.
329 SharingMapTy &getStackElemAtLevel(unsigned Level) {
330 assert(Level < getStackSize() && "no such stack element");
331 return Stack.back().first[Level];
332 }
333 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
334 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
335 }
336
337 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
338
339 /// Checks if the variable is a local for OpenMP region.
340 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
341
342 /// Vector of previously declared requires directives
343 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
344 /// omp_allocator_handle_t type.
345 QualType OMPAllocatorHandleT;
346 /// omp_depend_t type.
347 QualType OMPDependT;
348 /// omp_event_handle_t type.
349 QualType OMPEventHandleT;
350 /// omp_alloctrait_t type.
351 QualType OMPAlloctraitT;
352 /// Expression for the predefined allocators.
353 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
354 nullptr};
355 /// Vector of previously encountered target directives
356 SmallVector<SourceLocation, 2> TargetLocations;
357 SourceLocation AtomicLocation;
358 /// Vector of declare variant construct traits.
359 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
360
361public:
362 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
363
364 /// Sets omp_allocator_handle_t type.
365 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
366 /// Gets omp_allocator_handle_t type.
367 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
368 /// Sets omp_alloctrait_t type.
369 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
370 /// Gets omp_alloctrait_t type.
371 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
372 /// Sets the given default allocator.
373 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
374 Expr *Allocator) {
375 OMPPredefinedAllocators[AllocatorKind] = Allocator;
376 }
377 /// Returns the specified default allocator.
378 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
379 return OMPPredefinedAllocators[AllocatorKind];
380 }
381 /// Sets omp_depend_t type.
382 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
383 /// Gets omp_depend_t type.
384 QualType getOMPDependT() const { return OMPDependT; }
385
386 /// Sets omp_event_handle_t type.
387 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
388 /// Gets omp_event_handle_t type.
389 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
390
391 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
392 OpenMPClauseKind getClauseParsingMode() const {
393 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
394 return ClauseKindMode;
395 }
396 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
397
398 bool isBodyComplete() const {
399 const SharingMapTy *Top = getTopOfStackOrNull();
400 return Top && Top->BodyComplete;
401 }
402 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
403
404 bool isForceVarCapturing() const { return ForceCapturing; }
405 void setForceVarCapturing(bool V) { ForceCapturing = V; }
406
407 void setForceCaptureByReferenceInTargetExecutable(bool V) {
408 ForceCaptureByReferenceInTargetExecutable = V;
409 }
410 bool isForceCaptureByReferenceInTargetExecutable() const {
411 return ForceCaptureByReferenceInTargetExecutable;
412 }
413
414 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
415 Scope *CurScope, SourceLocation Loc) {
416 assert(!IgnoredStackElements &&
417 "cannot change stack while ignoring elements");
418 if (Stack.empty() ||
419 Stack.back().second != CurrentNonCapturingFunctionScope)
420 Stack.emplace_back(Args: StackTy(), Args&: CurrentNonCapturingFunctionScope);
421 Stack.back().first.emplace_back(Args&: DKind, Args: DirName, Args&: CurScope, Args&: Loc);
422 Stack.back().first.back().DefaultAttrLoc = Loc;
423 }
424
425 void pop() {
426 assert(!IgnoredStackElements &&
427 "cannot change stack while ignoring elements");
428 assert(!Stack.back().first.empty() &&
429 "Data-sharing attributes stack is empty!");
430 Stack.back().first.pop_back();
431 }
432
433 /// RAII object to temporarily leave the scope of a directive when we want to
434 /// logically operate in its parent.
435 class ParentDirectiveScope {
436 DSAStackTy &Self;
437 bool Active;
438
439 public:
440 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
441 : Self(Self), Active(false) {
442 if (Activate)
443 enable();
444 }
445 ~ParentDirectiveScope() { disable(); }
446 void disable() {
447 if (Active) {
448 --Self.IgnoredStackElements;
449 Active = false;
450 }
451 }
452 void enable() {
453 if (!Active) {
454 ++Self.IgnoredStackElements;
455 Active = true;
456 }
457 }
458 };
459
460 /// Marks that we're started loop parsing.
461 void loopInit() {
462 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
463 "Expected loop-based directive.");
464 getTopOfStack().LoopStart = true;
465 }
466 /// Start capturing of the variables in the loop context.
467 void loopStart() {
468 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
469 "Expected loop-based directive.");
470 getTopOfStack().LoopStart = false;
471 }
472 /// true, if variables are captured, false otherwise.
473 bool isLoopStarted() const {
474 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
475 "Expected loop-based directive.");
476 return !getTopOfStack().LoopStart;
477 }
478 /// Marks (or clears) declaration as possibly loop counter.
479 void resetPossibleLoopCounter(const Decl *D = nullptr) {
480 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
481 }
482 /// Gets the possible loop counter decl.
483 const Decl *getPossiblyLoopCounter() const {
484 return getTopOfStack().PossiblyLoopCounter;
485 }
486 /// Start new OpenMP region stack in new non-capturing function.
487 void pushFunction() {
488 assert(!IgnoredStackElements &&
489 "cannot change stack while ignoring elements");
490 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
491 assert(!isa<CapturingScopeInfo>(CurFnScope));
492 CurrentNonCapturingFunctionScope = CurFnScope;
493 }
494 /// Pop region stack for non-capturing function.
495 void popFunction(const FunctionScopeInfo *OldFSI) {
496 assert(!IgnoredStackElements &&
497 "cannot change stack while ignoring elements");
498 if (!Stack.empty() && Stack.back().second == OldFSI) {
499 assert(Stack.back().first.empty());
500 Stack.pop_back();
501 }
502 CurrentNonCapturingFunctionScope = nullptr;
503 for (const FunctionScopeInfo *FSI : llvm::reverse(C&: SemaRef.FunctionScopes)) {
504 if (!isa<CapturingScopeInfo>(Val: FSI)) {
505 CurrentNonCapturingFunctionScope = FSI;
506 break;
507 }
508 }
509 }
510
511 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
512 Criticals.try_emplace(Key: D->getDirectiveName().getAsString(), Args&: D, Args&: Hint);
513 }
514 std::pair<const OMPCriticalDirective *, llvm::APSInt>
515 getCriticalWithHint(const DeclarationNameInfo &Name) const {
516 auto I = Criticals.find(Key: Name.getAsString());
517 if (I != Criticals.end())
518 return I->second;
519 return std::make_pair(x: nullptr, y: llvm::APSInt());
520 }
521 /// If 'aligned' declaration for given variable \a D was not seen yet,
522 /// add it and return NULL; otherwise return previous occurrence's expression
523 /// for diagnostics.
524 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
525 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
526 /// add it and return NULL; otherwise return previous occurrence's expression
527 /// for diagnostics.
528 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
529
530 /// Register specified variable as loop control variable.
531 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
532 /// Check if the specified variable is a loop control variable for
533 /// current region.
534 /// \return The index of the loop control variable in the list of associated
535 /// for-loops (from outer to inner).
536 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
537 /// Check if the specified variable is a loop control variable for
538 /// parent region.
539 /// \return The index of the loop control variable in the list of associated
540 /// for-loops (from outer to inner).
541 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
542 /// Check if the specified variable is a loop control variable for
543 /// current region.
544 /// \return The index of the loop control variable in the list of associated
545 /// for-loops (from outer to inner).
546 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
547 unsigned Level) const;
548 /// Get the loop control variable for the I-th loop (or nullptr) in
549 /// parent directive.
550 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
551
552 /// Marks the specified decl \p D as used in scan directive.
553 void markDeclAsUsedInScanDirective(ValueDecl *D) {
554 if (SharingMapTy *Stack = getSecondOnStackOrNull())
555 Stack->UsedInScanDirective.insert(V: D);
556 }
557
558 /// Checks if the specified declaration was used in the inner scan directive.
559 bool isUsedInScanDirective(ValueDecl *D) const {
560 if (const SharingMapTy *Stack = getTopOfStackOrNull())
561 return Stack->UsedInScanDirective.contains(V: D);
562 return false;
563 }
564
565 /// Adds explicit data sharing attribute to the specified declaration.
566 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
567 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
568 bool AppliedToPointee = false);
569
570 /// Adds additional information for the reduction items with the reduction id
571 /// represented as an operator.
572 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
573 BinaryOperatorKind BOK);
574 /// Adds additional information for the reduction items with the reduction id
575 /// represented as reduction identifier.
576 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
577 const Expr *ReductionRef);
578 /// Returns the location and reduction operation from the innermost parent
579 /// region for the given \p D.
580 const DSAVarData
581 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
582 BinaryOperatorKind &BOK,
583 Expr *&TaskgroupDescriptor) const;
584 /// Returns the location and reduction operation from the innermost parent
585 /// region for the given \p D.
586 const DSAVarData
587 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
588 const Expr *&ReductionRef,
589 Expr *&TaskgroupDescriptor) const;
590 /// Return reduction reference expression for the current taskgroup or
591 /// parallel/worksharing directives with task reductions.
592 Expr *getTaskgroupReductionRef() const {
593 assert((getTopOfStack().Directive == OMPD_taskgroup ||
594 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
595 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
596 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
597 "taskgroup reference expression requested for non taskgroup or "
598 "parallel/worksharing directive.");
599 return getTopOfStack().TaskgroupReductionRef;
600 }
601 /// Checks if the given \p VD declaration is actually a taskgroup reduction
602 /// descriptor variable at the \p Level of OpenMP regions.
603 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
604 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
605 cast<DeclRefExpr>(Val: getStackElemAtLevel(Level).TaskgroupReductionRef)
606 ->getDecl() == VD;
607 }
608
609 /// Returns data sharing attributes from top of the stack for the
610 /// specified declaration.
611 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
612 /// Returns data-sharing attributes for the specified declaration.
613 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
614 /// Returns data-sharing attributes for the specified declaration.
615 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
616 /// Checks if the specified variables has data-sharing attributes which
617 /// match specified \a CPred predicate in any directive which matches \a DPred
618 /// predicate.
619 const DSAVarData
620 hasDSA(ValueDecl *D,
621 const llvm::function_ref<bool(OpenMPClauseKind, bool,
622 DefaultDataSharingAttributes)>
623 CPred,
624 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
625 bool FromParent) const;
626 /// Checks if the specified variables has data-sharing attributes which
627 /// match specified \a CPred predicate in any innermost directive which
628 /// matches \a DPred predicate.
629 const DSAVarData
630 hasInnermostDSA(ValueDecl *D,
631 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
632 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
633 bool FromParent) const;
634 /// Checks if the specified variables has explicit data-sharing
635 /// attributes which match specified \a CPred predicate at the specified
636 /// OpenMP region.
637 bool
638 hasExplicitDSA(const ValueDecl *D,
639 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
640 unsigned Level, bool NotLastprivate = false) const;
641
642 /// Returns true if the directive at level \Level matches in the
643 /// specified \a DPred predicate.
644 bool hasExplicitDirective(
645 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
646 unsigned Level) const;
647
648 /// Finds a directive which matches specified \a DPred predicate.
649 bool hasDirective(
650 const llvm::function_ref<bool(
651 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
652 DPred,
653 bool FromParent) const;
654
655 /// Returns currently analyzed directive.
656 OpenMPDirectiveKind getCurrentDirective() const {
657 const SharingMapTy *Top = getTopOfStackOrNull();
658 return Top ? Top->Directive : OMPD_unknown;
659 }
660 /// Returns directive kind at specified level.
661 OpenMPDirectiveKind getDirective(unsigned Level) const {
662 assert(!isStackEmpty() && "No directive at specified level.");
663 return getStackElemAtLevel(Level).Directive;
664 }
665 /// Returns the capture region at the specified level.
666 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
667 unsigned OpenMPCaptureLevel) const {
668 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
669 getOpenMPCaptureRegions(CaptureRegions, DKind: getDirective(Level));
670 return CaptureRegions[OpenMPCaptureLevel];
671 }
672 /// Returns parent directive.
673 OpenMPDirectiveKind getParentDirective() const {
674 const SharingMapTy *Parent = getSecondOnStackOrNull();
675 return Parent ? Parent->Directive : OMPD_unknown;
676 }
677
678 /// Add requires decl to internal vector
679 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(Elt: RD); }
680
681 /// Checks if the defined 'requires' directive has specified type of clause.
682 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
683 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
684 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
685 return isa<ClauseType>(C);
686 });
687 });
688 }
689
690 /// Checks for a duplicate clause amongst previously declared requires
691 /// directives
692 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
693 bool IsDuplicate = false;
694 for (OMPClause *CNew : ClauseList) {
695 for (const OMPRequiresDecl *D : RequiresDecls) {
696 for (const OMPClause *CPrev : D->clauselists()) {
697 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
698 SemaRef.Diag(Loc: CNew->getBeginLoc(),
699 DiagID: diag::err_omp_requires_clause_redeclaration)
700 << getOpenMPClauseNameForDiag(C: CNew->getClauseKind());
701 SemaRef.Diag(Loc: CPrev->getBeginLoc(),
702 DiagID: diag::note_omp_requires_previous_clause)
703 << getOpenMPClauseNameForDiag(C: CPrev->getClauseKind());
704 IsDuplicate = true;
705 }
706 }
707 }
708 }
709 return IsDuplicate;
710 }
711
712 /// Add location of previously encountered target to internal vector
713 void addTargetDirLocation(SourceLocation LocStart) {
714 TargetLocations.push_back(Elt: LocStart);
715 }
716
717 /// Add location for the first encountered atomic directive.
718 void addAtomicDirectiveLoc(SourceLocation Loc) {
719 if (AtomicLocation.isInvalid())
720 AtomicLocation = Loc;
721 }
722
723 /// Returns the location of the first encountered atomic directive in the
724 /// module.
725 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
726
727 // Return previously encountered target region locations.
728 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
729 return TargetLocations;
730 }
731
732 /// Set default data sharing attribute to none.
733 void setDefaultDSANone(SourceLocation Loc) {
734 getTopOfStack().DefaultAttr = DSA_none;
735 getTopOfStack().DefaultAttrLoc = Loc;
736 }
737 /// Set default data sharing attribute to shared.
738 void setDefaultDSAShared(SourceLocation Loc) {
739 getTopOfStack().DefaultAttr = DSA_shared;
740 getTopOfStack().DefaultAttrLoc = Loc;
741 }
742 /// Set default data sharing attribute to private.
743 void setDefaultDSAPrivate(SourceLocation Loc) {
744 getTopOfStack().DefaultAttr = DSA_private;
745 getTopOfStack().DefaultAttrLoc = Loc;
746 }
747 /// Set default data sharing attribute to firstprivate.
748 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
749 getTopOfStack().DefaultAttr = DSA_firstprivate;
750 getTopOfStack().DefaultAttrLoc = Loc;
751 }
752 /// Set default data sharing variable category attribute to aggregate.
753 void setDefaultDSAVCAggregate(SourceLocation VCLoc) {
754 getTopOfStack().DefaultVCAttr = DSA_VC_aggregate;
755 getTopOfStack().DefaultAttrVCLoc = VCLoc;
756 }
757 /// Set default data sharing variable category attribute to all.
758 void setDefaultDSAVCAll(SourceLocation VCLoc) {
759 getTopOfStack().DefaultVCAttr = DSA_VC_all;
760 getTopOfStack().DefaultAttrVCLoc = VCLoc;
761 }
762 /// Set default data sharing variable category attribute to pointer.
763 void setDefaultDSAVCPointer(SourceLocation VCLoc) {
764 getTopOfStack().DefaultVCAttr = DSA_VC_pointer;
765 getTopOfStack().DefaultAttrVCLoc = VCLoc;
766 }
767 /// Set default data sharing variable category attribute to scalar.
768 void setDefaultDSAVCScalar(SourceLocation VCLoc) {
769 getTopOfStack().DefaultVCAttr = DSA_VC_scalar;
770 getTopOfStack().DefaultAttrVCLoc = VCLoc;
771 }
772 /// Set default data mapping attribute to Modifier:Kind
773 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
774 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
775 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
776 DMI.ImplicitBehavior = M;
777 DMI.SLoc = Loc;
778 }
779 /// Check whether the implicit-behavior has been set in defaultmap
780 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
781 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
782 return getTopOfStack()
783 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
784 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
785 getTopOfStack()
786 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
787 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
788 getTopOfStack()
789 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
790 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
791 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
792 OMPC_DEFAULTMAP_MODIFIER_unknown;
793 }
794
795 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
796 return ConstructTraits;
797 }
798 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
799 bool ScopeEntry) {
800 if (ScopeEntry)
801 ConstructTraits.append(in_start: Traits.begin(), in_end: Traits.end());
802 else
803 for (llvm::omp::TraitProperty Trait : llvm::reverse(C&: Traits)) {
804 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
805 assert(Top == Trait && "Something left a trait on the stack!");
806 (void)Trait;
807 (void)Top;
808 }
809 }
810
811 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
812 return getStackSize() <= Level ? DSA_unspecified
813 : getStackElemAtLevel(Level).DefaultAttr;
814 }
815 DefaultDataSharingAttributes getDefaultDSA() const {
816 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
817 }
818 SourceLocation getDefaultDSALocation() const {
819 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
820 }
821 OpenMPDefaultmapClauseModifier
822 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
823 return isStackEmpty()
824 ? OMPC_DEFAULTMAP_MODIFIER_unknown
825 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
826 }
827 OpenMPDefaultmapClauseModifier
828 getDefaultmapModifierAtLevel(unsigned Level,
829 OpenMPDefaultmapClauseKind Kind) const {
830 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
831 }
832 bool isDefaultmapCapturedByRef(unsigned Level,
833 OpenMPDefaultmapClauseKind Kind) const {
834 OpenMPDefaultmapClauseModifier M =
835 getDefaultmapModifierAtLevel(Level, Kind);
836 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
837 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
838 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
839 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
840 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
841 (M == OMPC_DEFAULTMAP_MODIFIER_present) ||
842 (M == OMPC_DEFAULTMAP_MODIFIER_storage);
843 }
844 return true;
845 }
846 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
847 OpenMPDefaultmapClauseKind Kind) {
848 switch (Kind) {
849 case OMPC_DEFAULTMAP_scalar:
850 case OMPC_DEFAULTMAP_pointer:
851 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
852 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
853 (M == OMPC_DEFAULTMAP_MODIFIER_default);
854 case OMPC_DEFAULTMAP_aggregate:
855 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
856 default:
857 break;
858 }
859 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
860 }
861 bool mustBeFirstprivateAtLevel(unsigned Level,
862 OpenMPDefaultmapClauseKind Kind) const {
863 OpenMPDefaultmapClauseModifier M =
864 getDefaultmapModifierAtLevel(Level, Kind);
865 return mustBeFirstprivateBase(M, Kind);
866 }
867 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
868 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
869 return mustBeFirstprivateBase(M, Kind);
870 }
871
872 /// Checks if the specified variable is a threadprivate.
873 bool isThreadPrivate(VarDecl *D) {
874 const DSAVarData DVar = getTopDSA(D, FromParent: false);
875 return isOpenMPThreadPrivate(Kind: DVar.CKind);
876 }
877
878 /// Marks current region as ordered (it has an 'ordered' clause).
879 void setOrderedRegion(bool IsOrdered, const Expr *Param,
880 OMPOrderedClause *Clause) {
881 if (IsOrdered)
882 getTopOfStack().OrderedRegion.emplace(args&: Param, args&: Clause);
883 else
884 getTopOfStack().OrderedRegion.reset();
885 }
886 /// Returns true, if region is ordered (has associated 'ordered' clause),
887 /// false - otherwise.
888 bool isOrderedRegion() const {
889 if (const SharingMapTy *Top = getTopOfStackOrNull())
890 return Top->OrderedRegion.has_value();
891 return false;
892 }
893 /// Returns optional parameter for the ordered region.
894 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
895 if (const SharingMapTy *Top = getTopOfStackOrNull())
896 if (Top->OrderedRegion)
897 return *Top->OrderedRegion;
898 return std::make_pair(x: nullptr, y: nullptr);
899 }
900 /// Returns true, if parent region is ordered (has associated
901 /// 'ordered' clause), false - otherwise.
902 bool isParentOrderedRegion() const {
903 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
904 return Parent->OrderedRegion.has_value();
905 return false;
906 }
907 /// Returns optional parameter for the ordered region.
908 std::pair<const Expr *, OMPOrderedClause *>
909 getParentOrderedRegionParam() const {
910 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
911 if (Parent->OrderedRegion)
912 return *Parent->OrderedRegion;
913 return std::make_pair(x: nullptr, y: nullptr);
914 }
915 /// Marks current region as having an 'order' clause.
916 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
917 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
918 }
919 /// Returns true, if parent region is order (has associated
920 /// 'order' clause), false - otherwise.
921 bool isParentOrderConcurrent() const {
922 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
923 return Parent->RegionHasOrderConcurrent;
924 return false;
925 }
926 /// Marks current region as nowait (it has a 'nowait' clause).
927 void setNowaitRegion(bool IsNowait = true) {
928 getTopOfStack().NowaitRegion = IsNowait;
929 }
930 /// Returns true, if parent region is nowait (has associated
931 /// 'nowait' clause), false - otherwise.
932 bool isParentNowaitRegion() const {
933 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
934 return Parent->NowaitRegion;
935 return false;
936 }
937 /// Marks current region as untied (it has a 'untied' clause).
938 void setUntiedRegion(bool IsUntied = true) {
939 getTopOfStack().UntiedRegion = IsUntied;
940 }
941 /// Return true if current region is untied.
942 bool isUntiedRegion() const {
943 const SharingMapTy *Top = getTopOfStackOrNull();
944 return Top ? Top->UntiedRegion : false;
945 }
946 /// Marks parent region as cancel region.
947 void setParentCancelRegion(bool Cancel = true) {
948 if (SharingMapTy *Parent = getSecondOnStackOrNull())
949 Parent->CancelRegion |= Cancel;
950 }
951 /// Return true if current region has inner cancel construct.
952 bool isCancelRegion() const {
953 const SharingMapTy *Top = getTopOfStackOrNull();
954 return Top ? Top->CancelRegion : false;
955 }
956
957 /// Mark that parent region already has scan directive.
958 void setParentHasScanDirective(SourceLocation Loc) {
959 if (SharingMapTy *Parent = getSecondOnStackOrNull())
960 Parent->PrevScanLocation = Loc;
961 }
962 /// Return true if current region has inner cancel construct.
963 bool doesParentHasScanDirective() const {
964 const SharingMapTy *Top = getSecondOnStackOrNull();
965 return Top ? Top->PrevScanLocation.isValid() : false;
966 }
967 /// Return true if current region has inner cancel construct.
968 SourceLocation getParentScanDirectiveLoc() const {
969 const SharingMapTy *Top = getSecondOnStackOrNull();
970 return Top ? Top->PrevScanLocation : SourceLocation();
971 }
972 /// Mark that parent region already has ordered directive.
973 void setParentHasOrderedDirective(SourceLocation Loc) {
974 if (SharingMapTy *Parent = getSecondOnStackOrNull())
975 Parent->PrevOrderedLocation = Loc;
976 }
977 /// Return true if current region has inner ordered construct.
978 bool doesParentHasOrderedDirective() const {
979 const SharingMapTy *Top = getSecondOnStackOrNull();
980 return Top ? Top->PrevOrderedLocation.isValid() : false;
981 }
982 /// Returns the location of the previously specified ordered directive.
983 SourceLocation getParentOrderedDirectiveLoc() const {
984 const SharingMapTy *Top = getSecondOnStackOrNull();
985 return Top ? Top->PrevOrderedLocation : SourceLocation();
986 }
987
988 /// Set collapse value for the region.
989 void setAssociatedLoops(unsigned Val) {
990 getTopOfStack().AssociatedLoops = Val;
991 if (Val > 1)
992 getTopOfStack().HasMutipleLoops = true;
993 }
994 /// Return collapse value for region.
995 unsigned getAssociatedLoops() const {
996 const SharingMapTy *Top = getTopOfStackOrNull();
997 return Top ? Top->AssociatedLoops : 0;
998 }
999 /// Returns true if the construct is associated with multiple loops.
1000 bool hasMutipleLoops() const {
1001 const SharingMapTy *Top = getTopOfStackOrNull();
1002 return Top ? Top->HasMutipleLoops : false;
1003 }
1004
1005 /// Marks current target region as one with closely nested teams
1006 /// region.
1007 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
1008 if (SharingMapTy *Parent = getSecondOnStackOrNull())
1009 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
1010 }
1011 /// Returns true, if current region has closely nested teams region.
1012 bool hasInnerTeamsRegion() const {
1013 return getInnerTeamsRegionLoc().isValid();
1014 }
1015 /// Returns location of the nested teams region (if any).
1016 SourceLocation getInnerTeamsRegionLoc() const {
1017 const SharingMapTy *Top = getTopOfStackOrNull();
1018 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1019 }
1020
1021 Scope *getCurScope() const {
1022 const SharingMapTy *Top = getTopOfStackOrNull();
1023 return Top ? Top->CurScope : nullptr;
1024 }
1025 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1026 SourceLocation getConstructLoc() const {
1027 const SharingMapTy *Top = getTopOfStackOrNull();
1028 return Top ? Top->ConstructLoc : SourceLocation();
1029 }
1030
1031 /// Do the check specified in \a Check to all component lists and return true
1032 /// if any issue is found.
1033 bool checkMappableExprComponentListsForDecl(
1034 const ValueDecl *VD, bool CurrentRegionOnly,
1035 const llvm::function_ref<
1036 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1037 OpenMPClauseKind)>
1038 Check) const {
1039 if (isStackEmpty())
1040 return false;
1041 auto SI = begin();
1042 auto SE = end();
1043
1044 if (SI == SE)
1045 return false;
1046
1047 if (CurrentRegionOnly)
1048 SE = std::next(x: SI);
1049 else
1050 std::advance(i&: SI, n: 1);
1051
1052 for (; SI != SE; ++SI) {
1053 auto MI = SI->MappedExprComponents.find(Val: VD);
1054 if (MI != SI->MappedExprComponents.end())
1055 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1056 MI->second.Components)
1057 if (Check(L, MI->second.Kind))
1058 return true;
1059 }
1060 return false;
1061 }
1062
1063 /// Do the check specified in \a Check to all component lists at a given level
1064 /// and return true if any issue is found.
1065 bool checkMappableExprComponentListsForDeclAtLevel(
1066 const ValueDecl *VD, unsigned Level,
1067 const llvm::function_ref<
1068 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1069 OpenMPClauseKind)>
1070 Check) const {
1071 if (getStackSize() <= Level)
1072 return false;
1073
1074 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1075 auto MI = StackElem.MappedExprComponents.find(Val: VD);
1076 if (MI != StackElem.MappedExprComponents.end())
1077 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1078 MI->second.Components)
1079 if (Check(L, MI->second.Kind))
1080 return true;
1081 return false;
1082 }
1083
1084 /// Create a new mappable expression component list associated with a given
1085 /// declaration and initialize it with the provided list of components.
1086 void addMappableExpressionComponents(
1087 const ValueDecl *VD,
1088 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
1089 OpenMPClauseKind WhereFoundClauseKind) {
1090 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1091 // Create new entry and append the new components there.
1092 MEC.Components.resize(N: MEC.Components.size() + 1);
1093 MEC.Components.back().append(in_start: Components.begin(), in_end: Components.end());
1094 MEC.Kind = WhereFoundClauseKind;
1095 }
1096
1097 unsigned getNestingLevel() const {
1098 assert(!isStackEmpty());
1099 return getStackSize() - 1;
1100 }
1101 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1102 SharingMapTy *Parent = getSecondOnStackOrNull();
1103 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1104 Parent->DoacrossDepends.try_emplace(Key: C, Args: OpsOffs);
1105 }
1106 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1107 getDoacrossDependClauses() const {
1108 const SharingMapTy &StackElem = getTopOfStack();
1109 if (isOpenMPWorksharingDirective(DKind: StackElem.Directive)) {
1110 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1111 return llvm::make_range(x: Ref.begin(), y: Ref.end());
1112 }
1113 return llvm::make_range(x: StackElem.DoacrossDepends.end(),
1114 y: StackElem.DoacrossDepends.end());
1115 }
1116
1117 // Store types of classes which have been explicitly mapped
1118 void addMappedClassesQualTypes(QualType QT) {
1119 SharingMapTy &StackElem = getTopOfStack();
1120 StackElem.MappedClassesQualTypes.insert(V: QT);
1121 }
1122
1123 // Return set of mapped classes types
1124 bool isClassPreviouslyMapped(QualType QT) const {
1125 const SharingMapTy &StackElem = getTopOfStack();
1126 return StackElem.MappedClassesQualTypes.contains(V: QT);
1127 }
1128
1129 /// Adds global declare target to the parent target region.
1130 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1131 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1132 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1133 "Expected declare target link global.");
1134 for (auto &Elem : *this) {
1135 if (isOpenMPTargetExecutionDirective(DKind: Elem.Directive)) {
1136 Elem.DeclareTargetLinkVarDecls.push_back(Elt: E);
1137 return;
1138 }
1139 }
1140 }
1141
1142 /// Returns the list of globals with declare target link if current directive
1143 /// is target.
1144 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1145 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1146 "Expected target executable directive.");
1147 return getTopOfStack().DeclareTargetLinkVarDecls;
1148 }
1149
1150 /// Adds list of allocators expressions.
1151 void addInnerAllocatorExpr(Expr *E) {
1152 getTopOfStack().InnerUsedAllocators.push_back(Elt: E);
1153 }
1154 /// Return list of used allocators.
1155 ArrayRef<Expr *> getInnerAllocators() const {
1156 return getTopOfStack().InnerUsedAllocators;
1157 }
1158 /// Marks the declaration as implicitly firstprivate nin the task-based
1159 /// regions.
1160 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1161 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(V: D);
1162 }
1163 /// Checks if the decl is implicitly firstprivate in the task-based region.
1164 bool isImplicitTaskFirstprivate(Decl *D) const {
1165 return getTopOfStack().ImplicitTaskFirstprivates.contains(V: D);
1166 }
1167
1168 /// Marks decl as used in uses_allocators clause as the allocator.
1169 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1170 getTopOfStack().UsesAllocatorsDecls.try_emplace(Key: D, Args&: Kind);
1171 }
1172 /// Checks if specified decl is used in uses allocator clause as the
1173 /// allocator.
1174 std::optional<UsesAllocatorsDeclKind>
1175 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1176 const SharingMapTy &StackElem = getTopOfStack();
1177 auto I = StackElem.UsesAllocatorsDecls.find(Val: D);
1178 if (I == StackElem.UsesAllocatorsDecls.end())
1179 return std::nullopt;
1180 return I->getSecond();
1181 }
1182 std::optional<UsesAllocatorsDeclKind>
1183 isUsesAllocatorsDecl(const Decl *D) const {
1184 const SharingMapTy &StackElem = getTopOfStack();
1185 auto I = StackElem.UsesAllocatorsDecls.find(Val: D);
1186 if (I == StackElem.UsesAllocatorsDecls.end())
1187 return std::nullopt;
1188 return I->getSecond();
1189 }
1190
1191 void addDeclareMapperVarRef(Expr *Ref) {
1192 SharingMapTy &StackElem = getTopOfStack();
1193 StackElem.DeclareMapperVar = Ref;
1194 }
1195 const Expr *getDeclareMapperVarRef() const {
1196 const SharingMapTy *Top = getTopOfStackOrNull();
1197 return Top ? Top->DeclareMapperVar : nullptr;
1198 }
1199
1200 /// Add a new iterator variable.
1201 void addIteratorVarDecl(VarDecl *VD) {
1202 SharingMapTy &StackElem = getTopOfStack();
1203 StackElem.IteratorVarDecls.push_back(Elt: VD->getCanonicalDecl());
1204 }
1205 /// Check if variable declaration is an iterator VarDecl.
1206 bool isIteratorVarDecl(const VarDecl *VD) const {
1207 const SharingMapTy *Top = getTopOfStackOrNull();
1208 if (!Top)
1209 return false;
1210
1211 return llvm::is_contained(Range: Top->IteratorVarDecls, Element: VD->getCanonicalDecl());
1212 }
1213 /// get captured field from ImplicitDefaultFirstprivateFDs
1214 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1215 const_iterator I = begin();
1216 const_iterator EndI = end();
1217 size_t StackLevel = getStackSize();
1218 for (; I != EndI; ++I) {
1219 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1220 break;
1221 StackLevel--;
1222 }
1223 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1224 if (I == EndI)
1225 return nullptr;
1226 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1227 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1228 return IFD.VD;
1229 return nullptr;
1230 }
1231 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1232 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1233 const_iterator I = begin();
1234 const_iterator EndI = end();
1235 for (; I != EndI; ++I)
1236 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1237 break;
1238 if (I == EndI)
1239 return false;
1240 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1241 if (IFD.VD == VD)
1242 return true;
1243 return false;
1244 }
1245 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1246 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1247 iterator I = begin();
1248 const_iterator EndI = end();
1249 size_t StackLevel = getStackSize();
1250 for (; I != EndI; ++I) {
1251 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1252 I->ImplicitDefaultFirstprivateFDs.emplace_back(Args&: FD, Args&: StackLevel, Args&: VD);
1253 break;
1254 }
1255 StackLevel--;
1256 }
1257 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1258 }
1259};
1260
1261bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1262 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1263}
1264
1265bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1266 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(Kind: DKind) ||
1267 DKind == OMPD_unknown;
1268}
1269
1270} // namespace
1271
1272static const Expr *getExprAsWritten(const Expr *E) {
1273 if (const auto *FE = dyn_cast<FullExpr>(Val: E))
1274 E = FE->getSubExpr();
1275
1276 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Val: E))
1277 E = MTE->getSubExpr();
1278
1279 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(Val: E))
1280 E = Binder->getSubExpr();
1281
1282 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(Val: E))
1283 E = ICE->getSubExprAsWritten();
1284 return E->IgnoreParens();
1285}
1286
1287static Expr *getExprAsWritten(Expr *E) {
1288 return const_cast<Expr *>(getExprAsWritten(E: const_cast<const Expr *>(E)));
1289}
1290
1291static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1292 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: D))
1293 if (const auto *ME = dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit())))
1294 D = ME->getMemberDecl();
1295
1296 D = cast<ValueDecl>(Val: D->getCanonicalDecl());
1297 return D;
1298}
1299
1300static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1301 return const_cast<ValueDecl *>(
1302 getCanonicalDecl(D: const_cast<const ValueDecl *>(D)));
1303}
1304
1305static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C) {
1306 if (C == OMPC_threadprivate)
1307 return getOpenMPClauseName(C).str() + " or thread local";
1308 return getOpenMPClauseName(C).str();
1309}
1310
1311DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1312 ValueDecl *D) const {
1313 D = getCanonicalDecl(D);
1314 auto *VD = dyn_cast<VarDecl>(Val: D);
1315 const auto *FD = dyn_cast<FieldDecl>(Val: D);
1316 DSAVarData DVar;
1317 if (Iter == end()) {
1318 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1319 // in a region but not in construct]
1320 // File-scope or namespace-scope variables referenced in called routines
1321 // in the region are shared unless they appear in a threadprivate
1322 // directive.
1323 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(Val: VD))
1324 DVar.CKind = OMPC_shared;
1325
1326 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1327 // in a region but not in construct]
1328 // Variables with static storage duration that are declared in called
1329 // routines in the region are shared.
1330 if (VD && VD->hasGlobalStorage())
1331 DVar.CKind = OMPC_shared;
1332
1333 // Non-static data members are shared by default.
1334 if (FD)
1335 DVar.CKind = OMPC_shared;
1336
1337 return DVar;
1338 }
1339
1340 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1341 // in a Construct, C/C++, predetermined, p.1]
1342 // Variables with automatic storage duration that are declared in a scope
1343 // inside the construct are private.
1344 if (VD && isOpenMPLocal(D: VD, Iter) && VD->isLocalVarDecl() &&
1345 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1346 DVar.CKind = OMPC_private;
1347 return DVar;
1348 }
1349
1350 DVar.DKind = Iter->Directive;
1351 // Explicitly specified attributes and local variables with predetermined
1352 // attributes.
1353 if (Iter->SharingMap.count(Val: D)) {
1354 const DSAInfo &Data = Iter->SharingMap.lookup(Val: D);
1355 DVar.RefExpr = Data.RefExpr.getPointer();
1356 DVar.PrivateCopy = Data.PrivateCopy;
1357 DVar.CKind = Data.Attributes;
1358 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1359 DVar.Modifier = Data.Modifier;
1360 DVar.AppliedToPointee = Data.AppliedToPointee;
1361 return DVar;
1362 }
1363
1364 DefaultDataSharingAttributes IterDA = Iter->DefaultAttr;
1365 switch (Iter->DefaultVCAttr) {
1366 case DSA_VC_aggregate:
1367 if (!D->getType()->isAggregateType())
1368 IterDA = DSA_none;
1369 break;
1370 case DSA_VC_pointer:
1371 if (!D->getType()->isPointerType())
1372 IterDA = DSA_none;
1373 break;
1374 case DSA_VC_scalar:
1375 if (!D->getType()->isScalarType())
1376 IterDA = DSA_none;
1377 break;
1378 case DSA_VC_all:
1379 break;
1380 }
1381
1382 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1383 // in a Construct, C/C++, implicitly determined, p.1]
1384 // In a parallel or task construct, the data-sharing attributes of these
1385 // variables are determined by the default clause, if present.
1386 switch (IterDA) {
1387 case DSA_shared:
1388 DVar.CKind = OMPC_shared;
1389 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1390 return DVar;
1391 case DSA_none:
1392 return DVar;
1393 case DSA_firstprivate:
1394 if (VD && VD->getStorageDuration() == SD_Static &&
1395 VD->getDeclContext()->isFileContext()) {
1396 DVar.CKind = OMPC_unknown;
1397 } else {
1398 DVar.CKind = OMPC_firstprivate;
1399 }
1400 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1401 return DVar;
1402 case DSA_private:
1403 // each variable with static storage duration that is declared
1404 // in a namespace or global scope and referenced in the construct,
1405 // and that does not have a predetermined data-sharing attribute
1406 if (VD && VD->getStorageDuration() == SD_Static &&
1407 VD->getDeclContext()->isFileContext()) {
1408 DVar.CKind = OMPC_unknown;
1409 } else {
1410 DVar.CKind = OMPC_private;
1411 }
1412 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1413 return DVar;
1414 case DSA_unspecified:
1415 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1416 // in a Construct, implicitly determined, p.2]
1417 // In a parallel construct, if no default clause is present, these
1418 // variables are shared.
1419 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1420 if ((isOpenMPParallelDirective(DKind: DVar.DKind) &&
1421 !isOpenMPTaskLoopDirective(DKind: DVar.DKind)) ||
1422 isOpenMPTeamsDirective(DKind: DVar.DKind)) {
1423 DVar.CKind = OMPC_shared;
1424 return DVar;
1425 }
1426
1427 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1428 // in a Construct, implicitly determined, p.4]
1429 // In a task construct, if no default clause is present, a variable that in
1430 // the enclosing context is determined to be shared by all implicit tasks
1431 // bound to the current team is shared.
1432 if (isOpenMPTaskingDirective(Kind: DVar.DKind)) {
1433 DSAVarData DVarTemp;
1434 const_iterator I = Iter, E = end();
1435 do {
1436 ++I;
1437 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1438 // Referenced in a Construct, implicitly determined, p.6]
1439 // In a task construct, if no default clause is present, a variable
1440 // whose data-sharing attribute is not determined by the rules above is
1441 // firstprivate.
1442 DVarTemp = getDSA(Iter&: I, D);
1443 if (DVarTemp.CKind != OMPC_shared) {
1444 DVar.RefExpr = nullptr;
1445 DVar.CKind = OMPC_firstprivate;
1446 return DVar;
1447 }
1448 } while (I != E && !isImplicitTaskingRegion(DKind: I->Directive));
1449 DVar.CKind =
1450 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1451 return DVar;
1452 }
1453 }
1454 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1455 // in a Construct, implicitly determined, p.3]
1456 // For constructs other than task, if no default clause is present, these
1457 // variables inherit their data-sharing attributes from the enclosing
1458 // context.
1459 return getDSA(Iter&: ++Iter, D);
1460}
1461
1462const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1463 const Expr *NewDE) {
1464 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1465 D = getCanonicalDecl(D);
1466 SharingMapTy &StackElem = getTopOfStack();
1467 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(Key: D, Args&: NewDE);
1468 if (Inserted) {
1469 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1470 return nullptr;
1471 }
1472 assert(It->second && "Unexpected nullptr expr in the aligned map");
1473 return It->second;
1474}
1475
1476const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1477 const Expr *NewDE) {
1478 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1479 D = getCanonicalDecl(D);
1480 SharingMapTy &StackElem = getTopOfStack();
1481 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(Key: D, Args&: NewDE);
1482 if (Inserted) {
1483 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1484 return nullptr;
1485 }
1486 assert(It->second && "Unexpected nullptr expr in the aligned map");
1487 return It->second;
1488}
1489
1490void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1491 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1492 D = getCanonicalDecl(D);
1493 SharingMapTy &StackElem = getTopOfStack();
1494 StackElem.LCVMap.try_emplace(
1495 Key: D, Args: LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1496}
1497
1498const DSAStackTy::LCDeclInfo
1499DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1500 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1501 D = getCanonicalDecl(D);
1502 const SharingMapTy &StackElem = getTopOfStack();
1503 auto It = StackElem.LCVMap.find(Val: D);
1504 if (It != StackElem.LCVMap.end())
1505 return It->second;
1506 return {0, nullptr};
1507}
1508
1509const DSAStackTy::LCDeclInfo
1510DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1511 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1512 D = getCanonicalDecl(D);
1513 for (unsigned I = Level + 1; I > 0; --I) {
1514 const SharingMapTy &StackElem = getStackElemAtLevel(Level: I - 1);
1515 auto It = StackElem.LCVMap.find(Val: D);
1516 if (It != StackElem.LCVMap.end())
1517 return It->second;
1518 }
1519 return {0, nullptr};
1520}
1521
1522const DSAStackTy::LCDeclInfo
1523DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1524 const SharingMapTy *Parent = getSecondOnStackOrNull();
1525 assert(Parent && "Data-sharing attributes stack is empty");
1526 D = getCanonicalDecl(D);
1527 auto It = Parent->LCVMap.find(Val: D);
1528 if (It != Parent->LCVMap.end())
1529 return It->second;
1530 return {0, nullptr};
1531}
1532
1533const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1534 const SharingMapTy *Parent = getSecondOnStackOrNull();
1535 assert(Parent && "Data-sharing attributes stack is empty");
1536 if (Parent->LCVMap.size() < I)
1537 return nullptr;
1538 for (const auto &Pair : Parent->LCVMap)
1539 if (Pair.second.first == I)
1540 return Pair.first;
1541 return nullptr;
1542}
1543
1544void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1545 DeclRefExpr *PrivateCopy, unsigned Modifier,
1546 bool AppliedToPointee) {
1547 D = getCanonicalDecl(D);
1548 if (A == OMPC_threadprivate) {
1549 DSAInfo &Data = Threadprivates[D];
1550 Data.Attributes = A;
1551 Data.RefExpr.setPointer(E);
1552 Data.PrivateCopy = nullptr;
1553 Data.Modifier = Modifier;
1554 } else if (A == OMPC_groupprivate) {
1555 DSAInfo &Data = Groupprivates[D];
1556 Data.Attributes = A;
1557 Data.RefExpr.setPointer(E);
1558 Data.PrivateCopy = nullptr;
1559 Data.Modifier = Modifier;
1560 } else {
1561 DSAInfo &Data = getTopOfStack().SharingMap[D];
1562 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1563 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1564 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1565 (isLoopControlVariable(D).first && A == OMPC_private));
1566 Data.Modifier = Modifier;
1567 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1568 Data.RefExpr.setInt(/*IntVal=*/true);
1569 return;
1570 }
1571 const bool IsLastprivate =
1572 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1573 Data.Attributes = A;
1574 Data.RefExpr.setPointerAndInt(PtrVal: E, IntVal: IsLastprivate);
1575 Data.PrivateCopy = PrivateCopy;
1576 Data.AppliedToPointee = AppliedToPointee;
1577 if (PrivateCopy) {
1578 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1579 Data.Modifier = Modifier;
1580 Data.Attributes = A;
1581 Data.RefExpr.setPointerAndInt(PtrVal: PrivateCopy, IntVal: IsLastprivate);
1582 Data.PrivateCopy = nullptr;
1583 Data.AppliedToPointee = AppliedToPointee;
1584 }
1585 }
1586}
1587
1588/// Build a variable declaration for OpenMP loop iteration variable.
1589static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
1590 StringRef Name, const AttrVec *Attrs = nullptr,
1591 DeclRefExpr *OrigRef = nullptr) {
1592 DeclContext *DC = SemaRef.CurContext;
1593 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1594 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(T: Type, Loc);
1595 auto *Decl =
1596 VarDecl::Create(C&: SemaRef.Context, DC, StartLoc: Loc, IdLoc: Loc, Id: II, T: Type, TInfo, S: SC_None);
1597 if (Attrs) {
1598 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1599 I != E; ++I)
1600 Decl->addAttr(A: *I);
1601 }
1602 Decl->setImplicit();
1603 if (OrigRef) {
1604 Decl->addAttr(
1605 A: OMPReferencedVarAttr::CreateImplicit(Ctx&: SemaRef.Context, Ref: OrigRef));
1606 }
1607 return Decl;
1608}
1609
1610static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
1611 SourceLocation Loc,
1612 bool RefersToCapture = false) {
1613 D->setReferenced();
1614 D->markUsed(C&: S.Context);
1615 return DeclRefExpr::Create(Context: S.getASTContext(), QualifierLoc: NestedNameSpecifierLoc(),
1616 TemplateKWLoc: SourceLocation(), D, RefersToEnclosingVariableOrCapture: RefersToCapture, NameLoc: Loc, T: Ty,
1617 VK: VK_LValue);
1618}
1619
1620void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1621 BinaryOperatorKind BOK) {
1622 D = getCanonicalDecl(D);
1623 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1624 assert(
1625 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1626 "Additional reduction info may be specified only for reduction items.");
1627 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1628 assert(ReductionData.ReductionRange.isInvalid() &&
1629 (getTopOfStack().Directive == OMPD_taskgroup ||
1630 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1631 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1632 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1633 "Additional reduction info may be specified only once for reduction "
1634 "items.");
1635 ReductionData.set(BO: BOK, RR: SR);
1636 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1637 if (!TaskgroupReductionRef) {
1638 VarDecl *VD = buildVarDecl(SemaRef, Loc: SR.getBegin(),
1639 Type: SemaRef.Context.VoidPtrTy, Name: ".task_red.");
1640 TaskgroupReductionRef =
1641 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: SemaRef.Context.VoidPtrTy, Loc: SR.getBegin());
1642 }
1643}
1644
1645void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1646 const Expr *ReductionRef) {
1647 D = getCanonicalDecl(D);
1648 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1649 assert(
1650 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1651 "Additional reduction info may be specified only for reduction items.");
1652 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1653 assert(ReductionData.ReductionRange.isInvalid() &&
1654 (getTopOfStack().Directive == OMPD_taskgroup ||
1655 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1656 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1657 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1658 "Additional reduction info may be specified only once for reduction "
1659 "items.");
1660 ReductionData.set(RefExpr: ReductionRef, RR: SR);
1661 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1662 if (!TaskgroupReductionRef) {
1663 VarDecl *VD = buildVarDecl(SemaRef, Loc: SR.getBegin(),
1664 Type: SemaRef.Context.VoidPtrTy, Name: ".task_red.");
1665 TaskgroupReductionRef =
1666 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: SemaRef.Context.VoidPtrTy, Loc: SR.getBegin());
1667 }
1668}
1669
1670const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1671 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1672 Expr *&TaskgroupDescriptor) const {
1673 D = getCanonicalDecl(D);
1674 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1675 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1676 const DSAInfo &Data = I->SharingMap.lookup(Val: D);
1677 if (Data.Attributes != OMPC_reduction ||
1678 Data.Modifier != OMPC_REDUCTION_task)
1679 continue;
1680 const ReductionData &ReductionData = I->ReductionMap.lookup(Val: D);
1681 if (!ReductionData.ReductionOp ||
1682 isa<const Expr *>(Val: ReductionData.ReductionOp))
1683 return DSAVarData();
1684 SR = ReductionData.ReductionRange;
1685 BOK = cast<ReductionData::BOKPtrType>(Val: ReductionData.ReductionOp);
1686 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1687 "expression for the descriptor is not "
1688 "set.");
1689 TaskgroupDescriptor = I->TaskgroupReductionRef;
1690 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1691 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1692 /*AppliedToPointee=*/false);
1693 }
1694 return DSAVarData();
1695}
1696
1697const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1698 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1699 Expr *&TaskgroupDescriptor) const {
1700 D = getCanonicalDecl(D);
1701 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1702 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1703 const DSAInfo &Data = I->SharingMap.lookup(Val: D);
1704 if (Data.Attributes != OMPC_reduction ||
1705 Data.Modifier != OMPC_REDUCTION_task)
1706 continue;
1707 const ReductionData &ReductionData = I->ReductionMap.lookup(Val: D);
1708 if (!ReductionData.ReductionOp ||
1709 !isa<const Expr *>(Val: ReductionData.ReductionOp))
1710 return DSAVarData();
1711 SR = ReductionData.ReductionRange;
1712 ReductionRef = cast<const Expr *>(Val: ReductionData.ReductionOp);
1713 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1714 "expression for the descriptor is not "
1715 "set.");
1716 TaskgroupDescriptor = I->TaskgroupReductionRef;
1717 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1718 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1719 /*AppliedToPointee=*/false);
1720 }
1721 return DSAVarData();
1722}
1723
1724bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1725 D = D->getCanonicalDecl();
1726 for (const_iterator E = end(); I != E; ++I) {
1727 if (isImplicitOrExplicitTaskingRegion(DKind: I->Directive) ||
1728 isOpenMPTargetExecutionDirective(DKind: I->Directive)) {
1729 if (I->CurScope) {
1730 Scope *TopScope = I->CurScope->getParent();
1731 Scope *CurScope = getCurScope();
1732 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1733 CurScope = CurScope->getParent();
1734 return CurScope != TopScope;
1735 }
1736 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1737 if (I->Context == DC)
1738 return true;
1739 return false;
1740 }
1741 }
1742 return false;
1743}
1744
1745static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
1746 bool AcceptIfMutable = true,
1747 bool *IsClassType = nullptr) {
1748 ASTContext &Context = SemaRef.getASTContext();
1749 Type = Type.getNonReferenceType().getCanonicalType();
1750 bool IsConstant = Type.isConstant(Ctx: Context);
1751 Type = Context.getBaseElementType(QT: Type);
1752 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1753 ? Type->getAsCXXRecordDecl()
1754 : nullptr;
1755 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(Val: RD))
1756 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1757 RD = CTD->getTemplatedDecl();
1758 if (IsClassType)
1759 *IsClassType = RD;
1760 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1761 RD->hasDefinition() && RD->hasMutableFields());
1762}
1763
1764static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1765 QualType Type, OpenMPClauseKind CKind,
1766 SourceLocation ELoc,
1767 bool AcceptIfMutable = true,
1768 bool ListItemNotVar = false) {
1769 ASTContext &Context = SemaRef.getASTContext();
1770 bool IsClassType;
1771 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, IsClassType: &IsClassType)) {
1772 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1773 : IsClassType ? diag::err_omp_const_not_mutable_variable
1774 : diag::err_omp_const_variable;
1775 SemaRef.Diag(Loc: ELoc, DiagID: Diag) << getOpenMPClauseNameForDiag(C: CKind);
1776 if (!ListItemNotVar && D) {
1777 const VarDecl *VD = dyn_cast<VarDecl>(Val: D);
1778 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1779 VarDecl::DeclarationOnly;
1780 SemaRef.Diag(Loc: D->getLocation(),
1781 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1782 << D;
1783 }
1784 return true;
1785 }
1786 return false;
1787}
1788
1789const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1790 bool FromParent) {
1791 D = getCanonicalDecl(D);
1792 DSAVarData DVar;
1793
1794 auto *VD = dyn_cast<VarDecl>(Val: D);
1795 auto TI = Threadprivates.find(Val: D);
1796 if (TI != Threadprivates.end()) {
1797 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1798 DVar.CKind = OMPC_threadprivate;
1799 DVar.Modifier = TI->getSecond().Modifier;
1800 return DVar;
1801 }
1802 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1803 DVar.RefExpr = buildDeclRefExpr(
1804 S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1805 Loc: VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1806 DVar.CKind = OMPC_threadprivate;
1807 addDSA(D, E: DVar.RefExpr, A: OMPC_threadprivate);
1808 return DVar;
1809 }
1810 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1811 // in a Construct, C/C++, predetermined, p.1]
1812 // Variables appearing in threadprivate directives are threadprivate.
1813 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1814 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1815 SemaRef.getLangOpts().OpenMPUseTLS &&
1816 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1817 (VD && VD->getStorageClass() == SC_Register &&
1818 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1819 DVar.RefExpr = buildDeclRefExpr(
1820 S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(), Loc: D->getLocation());
1821 DVar.CKind = OMPC_threadprivate;
1822 addDSA(D, E: DVar.RefExpr, A: OMPC_threadprivate);
1823 return DVar;
1824 }
1825 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1826 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1827 !isLoopControlVariable(D).first) {
1828 const_iterator IterTarget =
1829 std::find_if(first: begin(), last: end(), pred: [](const SharingMapTy &Data) {
1830 return isOpenMPTargetExecutionDirective(DKind: Data.Directive);
1831 });
1832 if (IterTarget != end()) {
1833 const_iterator ParentIterTarget = IterTarget + 1;
1834 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1835 if (isOpenMPLocal(D: VD, I: Iter)) {
1836 DVar.RefExpr =
1837 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1838 Loc: D->getLocation());
1839 DVar.CKind = OMPC_threadprivate;
1840 return DVar;
1841 }
1842 }
1843 if (!isClauseParsingMode() || IterTarget != begin()) {
1844 auto DSAIter = IterTarget->SharingMap.find(Val: D);
1845 if (DSAIter != IterTarget->SharingMap.end() &&
1846 isOpenMPPrivate(Kind: DSAIter->getSecond().Attributes)) {
1847 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1848 DVar.CKind = OMPC_threadprivate;
1849 return DVar;
1850 }
1851 const_iterator End = end();
1852 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1853 D, Level: std::distance(first: ParentIterTarget, last: End),
1854 /*OpenMPCaptureLevel=*/0)) {
1855 DVar.RefExpr =
1856 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1857 Loc: IterTarget->ConstructLoc);
1858 DVar.CKind = OMPC_threadprivate;
1859 return DVar;
1860 }
1861 }
1862 }
1863 }
1864
1865 if (isStackEmpty())
1866 // Not in OpenMP execution region and top scope was already checked.
1867 return DVar;
1868
1869 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1870 // in a Construct, C/C++, predetermined, p.4]
1871 // Static data members are shared.
1872 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1873 // in a Construct, C/C++, predetermined, p.7]
1874 // Variables with static storage duration that are declared in a scope
1875 // inside the construct are shared.
1876 if (VD && VD->isStaticDataMember()) {
1877 // Check for explicitly specified attributes.
1878 const_iterator I = begin();
1879 const_iterator EndI = end();
1880 if (FromParent && I != EndI)
1881 ++I;
1882 if (I != EndI) {
1883 auto It = I->SharingMap.find(Val: D);
1884 if (It != I->SharingMap.end()) {
1885 const DSAInfo &Data = It->getSecond();
1886 DVar.RefExpr = Data.RefExpr.getPointer();
1887 DVar.PrivateCopy = Data.PrivateCopy;
1888 DVar.CKind = Data.Attributes;
1889 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1890 DVar.DKind = I->Directive;
1891 DVar.Modifier = Data.Modifier;
1892 DVar.AppliedToPointee = Data.AppliedToPointee;
1893 return DVar;
1894 }
1895 }
1896
1897 DVar.CKind = OMPC_shared;
1898 return DVar;
1899 }
1900
1901 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1902 // The predetermined shared attribute for const-qualified types having no
1903 // mutable members was removed after OpenMP 3.1.
1904 if (SemaRef.LangOpts.OpenMP <= 31) {
1905 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1906 // in a Construct, C/C++, predetermined, p.6]
1907 // Variables with const qualified type having no mutable member are
1908 // shared.
1909 if (isConstNotMutableType(SemaRef, Type: D->getType())) {
1910 // Variables with const-qualified type having no mutable member may be
1911 // listed in a firstprivate clause, even if they are static data members.
1912 DSAVarData DVarTemp = hasInnermostDSA(
1913 D,
1914 CPred: [](OpenMPClauseKind C, bool) {
1915 return C == OMPC_firstprivate || C == OMPC_shared;
1916 },
1917 DPred: MatchesAlways, FromParent);
1918 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1919 return DVarTemp;
1920
1921 DVar.CKind = OMPC_shared;
1922 return DVar;
1923 }
1924 }
1925
1926 // Explicitly specified attributes and local variables with predetermined
1927 // attributes.
1928 const_iterator I = begin();
1929 const_iterator EndI = end();
1930 if (FromParent && I != EndI)
1931 ++I;
1932 if (I == EndI)
1933 return DVar;
1934 auto It = I->SharingMap.find(Val: D);
1935 if (It != I->SharingMap.end()) {
1936 const DSAInfo &Data = It->getSecond();
1937 DVar.RefExpr = Data.RefExpr.getPointer();
1938 DVar.PrivateCopy = Data.PrivateCopy;
1939 DVar.CKind = Data.Attributes;
1940 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1941 DVar.DKind = I->Directive;
1942 DVar.Modifier = Data.Modifier;
1943 DVar.AppliedToPointee = Data.AppliedToPointee;
1944 }
1945
1946 return DVar;
1947}
1948
1949const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1950 bool FromParent) const {
1951 if (isStackEmpty()) {
1952 const_iterator I;
1953 return getDSA(Iter&: I, D);
1954 }
1955 D = getCanonicalDecl(D);
1956 const_iterator StartI = begin();
1957 const_iterator EndI = end();
1958 if (FromParent && StartI != EndI)
1959 ++StartI;
1960 return getDSA(Iter&: StartI, D);
1961}
1962
1963const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1964 unsigned Level) const {
1965 if (getStackSize() <= Level)
1966 return DSAVarData();
1967 D = getCanonicalDecl(D);
1968 const_iterator StartI = std::next(x: begin(), n: getStackSize() - 1 - Level);
1969 return getDSA(Iter&: StartI, D);
1970}
1971
1972const DSAStackTy::DSAVarData
1973DSAStackTy::hasDSA(ValueDecl *D,
1974 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1975 DefaultDataSharingAttributes)>
1976 CPred,
1977 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1978 bool FromParent) const {
1979 if (isStackEmpty())
1980 return {};
1981 D = getCanonicalDecl(D);
1982 const_iterator I = begin();
1983 const_iterator EndI = end();
1984 if (FromParent && I != EndI)
1985 ++I;
1986 for (; I != EndI; ++I) {
1987 if (!DPred(I->Directive) &&
1988 !isImplicitOrExplicitTaskingRegion(DKind: I->Directive))
1989 continue;
1990 const_iterator NewI = I;
1991 DSAVarData DVar = getDSA(Iter&: NewI, D);
1992 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1993 return DVar;
1994 }
1995 return {};
1996}
1997
1998const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1999 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2000 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2001 bool FromParent) const {
2002 if (isStackEmpty())
2003 return {};
2004 D = getCanonicalDecl(D);
2005 const_iterator StartI = begin();
2006 const_iterator EndI = end();
2007 if (FromParent && StartI != EndI)
2008 ++StartI;
2009 if (StartI == EndI || !DPred(StartI->Directive))
2010 return {};
2011 const_iterator NewI = StartI;
2012 DSAVarData DVar = getDSA(Iter&: NewI, D);
2013 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
2014 ? DVar
2015 : DSAVarData();
2016}
2017
2018bool DSAStackTy::hasExplicitDSA(
2019 const ValueDecl *D,
2020 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2021 unsigned Level, bool NotLastprivate) const {
2022 if (getStackSize() <= Level)
2023 return false;
2024 D = getCanonicalDecl(D);
2025 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2026 auto I = StackElem.SharingMap.find(Val: D);
2027 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
2028 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
2029 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
2030 return true;
2031 // Check predetermined rules for the loop control variables.
2032 auto LI = StackElem.LCVMap.find(Val: D);
2033 if (LI != StackElem.LCVMap.end())
2034 return CPred(OMPC_private, /*AppliedToPointee=*/false);
2035 return false;
2036}
2037
2038bool DSAStackTy::hasExplicitDirective(
2039 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2040 unsigned Level) const {
2041 if (getStackSize() <= Level)
2042 return false;
2043 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2044 return DPred(StackElem.Directive);
2045}
2046
2047bool DSAStackTy::hasDirective(
2048 const llvm::function_ref<bool(OpenMPDirectiveKind,
2049 const DeclarationNameInfo &, SourceLocation)>
2050 DPred,
2051 bool FromParent) const {
2052 // We look only in the enclosing region.
2053 size_t Skip = FromParent ? 2 : 1;
2054 for (const_iterator I = begin() + std::min(a: Skip, b: getStackSize()), E = end();
2055 I != E; ++I) {
2056 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2057 return true;
2058 }
2059 return false;
2060}
2061
2062void SemaOpenMP::InitDataSharingAttributesStack() {
2063 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2064}
2065
2066#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2067
2068void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2069
2070void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2071 DSAStack->popFunction(OldFSI);
2072}
2073
2074static bool isOpenMPDeviceDelayedContext(Sema &S) {
2075 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2076 "Expected OpenMP device compilation.");
2077 return !S.OpenMP().isInOpenMPTargetExecutionDirective();
2078}
2079
2080namespace {
2081/// Status of the function emission on the host/device.
2082enum class FunctionEmissionStatus {
2083 Emitted,
2084 Discarded,
2085 Unknown,
2086};
2087} // anonymous namespace
2088
2089SemaBase::SemaDiagnosticBuilder
2090SemaOpenMP::diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID,
2091 const FunctionDecl *FD) {
2092 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2093 "Expected OpenMP device compilation.");
2094
2095 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2096 if (FD) {
2097 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(Decl: FD);
2098 switch (FES) {
2099 case Sema::FunctionEmissionStatus::Emitted:
2100 Kind = SemaDiagnosticBuilder::K_Immediate;
2101 break;
2102 case Sema::FunctionEmissionStatus::Unknown:
2103 // TODO: We should always delay diagnostics here in case a target
2104 // region is in a function we do not emit. However, as the
2105 // current diagnostics are associated with the function containing
2106 // the target region and we do not emit that one, we would miss out
2107 // on diagnostics for the target region itself. We need to anchor
2108 // the diagnostics with the new generated function *or* ensure we
2109 // emit diagnostics associated with the surrounding function.
2110 Kind = isOpenMPDeviceDelayedContext(S&: SemaRef)
2111 ? SemaDiagnosticBuilder::K_Deferred
2112 : SemaDiagnosticBuilder::K_Immediate;
2113 break;
2114 case Sema::FunctionEmissionStatus::TemplateDiscarded:
2115 case Sema::FunctionEmissionStatus::OMPDiscarded:
2116 Kind = SemaDiagnosticBuilder::K_Nop;
2117 break;
2118 case Sema::FunctionEmissionStatus::CUDADiscarded:
2119 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2120 break;
2121 }
2122 }
2123
2124 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2125}
2126
2127SemaBase::SemaDiagnosticBuilder
2128SemaOpenMP::diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID,
2129 const FunctionDecl *FD) {
2130 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2131 "Expected OpenMP host compilation.");
2132
2133 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2134 if (FD) {
2135 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(Decl: FD);
2136 switch (FES) {
2137 case Sema::FunctionEmissionStatus::Emitted:
2138 Kind = SemaDiagnosticBuilder::K_Immediate;
2139 break;
2140 case Sema::FunctionEmissionStatus::Unknown:
2141 Kind = SemaDiagnosticBuilder::K_Deferred;
2142 break;
2143 case Sema::FunctionEmissionStatus::TemplateDiscarded:
2144 case Sema::FunctionEmissionStatus::OMPDiscarded:
2145 case Sema::FunctionEmissionStatus::CUDADiscarded:
2146 Kind = SemaDiagnosticBuilder::K_Nop;
2147 break;
2148 }
2149 }
2150
2151 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2152}
2153
2154static OpenMPDefaultmapClauseKind
2155getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) {
2156 if (LO.OpenMP <= 45) {
2157 if (VD->getType().getNonReferenceType()->isScalarType())
2158 return OMPC_DEFAULTMAP_scalar;
2159 return OMPC_DEFAULTMAP_aggregate;
2160 }
2161 if (VD->getType().getNonReferenceType()->isAnyPointerType())
2162 return OMPC_DEFAULTMAP_pointer;
2163 if (VD->getType().getNonReferenceType()->isScalarType())
2164 return OMPC_DEFAULTMAP_scalar;
2165 return OMPC_DEFAULTMAP_aggregate;
2166}
2167
2168bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2169 unsigned OpenMPCaptureLevel) const {
2170 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2171
2172 ASTContext &Ctx = getASTContext();
2173 bool IsByRef = true;
2174
2175 // Find the directive that is associated with the provided scope.
2176 D = cast<ValueDecl>(Val: D->getCanonicalDecl());
2177 QualType Ty = D->getType();
2178
2179 bool IsVariableUsedInMapClause = false;
2180 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective, Level)) {
2181 // This table summarizes how a given variable should be passed to the device
2182 // given its type and the clauses where it appears. This table is based on
2183 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2184 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2185 //
2186 // =========================================================================
2187 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2188 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2189 // =========================================================================
2190 // | scl | | | | - | | bycopy|
2191 // | scl | | - | x | - | - | bycopy|
2192 // | scl | | x | - | - | - | null |
2193 // | scl | x | | | - | | byref |
2194 // | scl | x | - | x | - | - | bycopy|
2195 // | scl | x | x | - | - | - | null |
2196 // | scl | | - | - | - | x | byref |
2197 // | scl | x | - | - | - | x | byref |
2198 //
2199 // | agg | n.a. | | | - | | byref |
2200 // | agg | n.a. | - | x | - | - | byref |
2201 // | agg | n.a. | x | - | - | - | null |
2202 // | agg | n.a. | - | - | - | x | byref |
2203 // | agg | n.a. | - | - | - | x[] | byref |
2204 //
2205 // | ptr | n.a. | | | - | | bycopy|
2206 // | ptr | n.a. | - | x | - | - | bycopy|
2207 // | ptr | n.a. | x | - | - | - | null |
2208 // | ptr | n.a. | - | - | - | x | byref |
2209 // | ptr | n.a. | - | - | - | x, x[] | bycopy|
2210 // | ptr | n.a. | - | - | - | x[] | bycopy|
2211 // | ptr | n.a. | - | - | x | | bycopy|
2212 // | ptr | n.a. | - | - | x | x | bycopy|
2213 // | ptr | n.a. | - | - | x | x[] | bycopy|
2214 // =========================================================================
2215 // Legend:
2216 // scl - scalar
2217 // ptr - pointer
2218 // agg - aggregate
2219 // x - applies
2220 // - - invalid in this combination
2221 // [] - mapped with an array section
2222 // byref - should be mapped by reference
2223 // byval - should be mapped by value
2224 // null - initialize a local variable to null on the device
2225 //
2226 // Observations:
2227 // - All scalar declarations that show up in a map clause have to be passed
2228 // by reference, because they may have been mapped in the enclosing data
2229 // environment.
2230 // - If the scalar value does not fit the size of uintptr, it has to be
2231 // passed by reference, regardless the result in the table above.
2232 // - For pointers mapped by value that have either an implicit map or an
2233 // array section, the runtime library may pass the NULL value to the
2234 // device instead of the value passed to it by the compiler.
2235 // - If both a pointer and a dereference of it are mapped, then the pointer
2236 // should be passed by reference.
2237
2238 if (Ty->isReferenceType())
2239 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2240
2241 // Locate map clauses and see if the variable being captured is mapped by
2242 // itself, or referred to, in any of those clauses. Here we only care about
2243 // variables, not fields, because fields are part of aggregates.
2244 bool IsVariableAssociatedWithSection = false;
2245 bool IsVariableItselfMapped = false;
2246
2247 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2248 VD: D, Level,
2249 Check: [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2250 &IsVariableItselfMapped,
2251 D](OMPClauseMappableExprCommon::MappableExprComponentListRef
2252 MapExprComponents,
2253 OpenMPClauseKind WhereFoundClauseKind) {
2254 // Both map and has_device_addr clauses information influences how a
2255 // variable is captured. E.g. is_device_ptr does not require changing
2256 // the default behavior.
2257 if (WhereFoundClauseKind != OMPC_map &&
2258 WhereFoundClauseKind != OMPC_has_device_addr)
2259 return false;
2260
2261 auto EI = MapExprComponents.rbegin();
2262 auto EE = MapExprComponents.rend();
2263
2264 assert(EI != EE && "Invalid map expression!");
2265
2266 if (isa<DeclRefExpr>(Val: EI->getAssociatedExpression()) &&
2267 EI->getAssociatedDeclaration() == D) {
2268 IsVariableUsedInMapClause = true;
2269
2270 // If the component list has only one element, it's for mapping the
2271 // variable itself, like map(p). This takes precedence in
2272 // determining how it's captured, so we don't need to look further
2273 // for any other maps that use the variable (like map(p[0]) etc.)
2274 if (MapExprComponents.size() == 1) {
2275 IsVariableItselfMapped = true;
2276 return true;
2277 }
2278 }
2279
2280 ++EI;
2281 if (EI == EE)
2282 return false;
2283 auto Last = std::prev(x: EE);
2284 const auto *UO =
2285 dyn_cast<UnaryOperator>(Val: Last->getAssociatedExpression());
2286 if ((UO && UO->getOpcode() == UO_Deref) ||
2287 isa<ArraySubscriptExpr>(Val: Last->getAssociatedExpression()) ||
2288 isa<ArraySectionExpr>(Val: Last->getAssociatedExpression()) ||
2289 isa<MemberExpr>(Val: EI->getAssociatedExpression()) ||
2290 isa<OMPArrayShapingExpr>(Val: Last->getAssociatedExpression())) {
2291 IsVariableAssociatedWithSection = true;
2292 // We've found a case like map(p[0]) or map(p->a) or map(*p),
2293 // so we are done with this particular map, but we need to keep
2294 // looking in case we find a map(p).
2295 return false;
2296 }
2297
2298 // Keep looking for more map info.
2299 return false;
2300 });
2301
2302 if (IsVariableUsedInMapClause) {
2303 // If variable is identified in a map clause it is always captured by
2304 // reference except if it is a pointer that is dereferenced somehow, but
2305 // not itself mapped.
2306 //
2307 // OpenMP 6.0, 7.1.1: Data sharing attribute rules, variables referenced
2308 // in a construct::
2309 // If a list item in a has_device_addr clause or in a map clause on the
2310 // target construct has a base pointer, and the base pointer is a scalar
2311 // variable *that is not a list item in a map clause on the construct*,
2312 // the base pointer is firstprivate.
2313 //
2314 // OpenMP 4.5, 2.15.1.1: Data-sharing Attribute Rules for Variables
2315 // Referenced in a Construct:
2316 // If an array section is a list item in a map clause on the target
2317 // construct and the array section is derived from a variable for which
2318 // the type is pointer then that variable is firstprivate.
2319 IsByRef = IsVariableItselfMapped ||
2320 !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2321 } else {
2322 // By default, all the data that has a scalar type is mapped by copy
2323 // (except for reduction variables).
2324 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2325 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2326 !Ty->isAnyPointerType()) ||
2327 !Ty->isScalarType() ||
2328 DSAStack->isDefaultmapCapturedByRef(
2329 Level, Kind: getVariableCategoryFromDecl(LO: getLangOpts(), VD: D)) ||
2330 DSAStack->hasExplicitDSA(
2331 D,
2332 CPred: [](OpenMPClauseKind K, bool AppliedToPointee) {
2333 return K == OMPC_reduction && !AppliedToPointee;
2334 },
2335 Level);
2336 }
2337 }
2338
2339 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2340 IsByRef =
2341 ((IsVariableUsedInMapClause &&
2342 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2343 OMPD_target) ||
2344 !(DSAStack->hasExplicitDSA(
2345 D,
2346 CPred: [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2347 return K == OMPC_firstprivate ||
2348 (K == OMPC_reduction && AppliedToPointee);
2349 },
2350 Level, /*NotLastprivate=*/true) ||
2351 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2352 // If the variable is artificial and must be captured by value - try to
2353 // capture by value.
2354 !(isa<OMPCapturedExprDecl>(Val: D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2355 !cast<OMPCapturedExprDecl>(Val: D)->getInit()->isGLValue()) &&
2356 // If the variable is implicitly firstprivate and scalar - capture by
2357 // copy
2358 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2359 DSAStack->getDefaultDSA() == DSA_private) &&
2360 !DSAStack->hasExplicitDSA(
2361 D, CPred: [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2362 Level) &&
2363 !DSAStack->isLoopControlVariable(D, Level).first);
2364 }
2365
2366 // When passing data by copy, we need to make sure it fits the uintptr size
2367 // and alignment, because the runtime library only deals with uintptr types.
2368 // If it does not fit the uintptr size, we need to pass the data by reference
2369 // instead.
2370 if (!IsByRef && (Ctx.getTypeSizeInChars(T: Ty) >
2371 Ctx.getTypeSizeInChars(T: Ctx.getUIntPtrType()) ||
2372 Ctx.getAlignOfGlobalVarInChars(T: Ty, VD: dyn_cast<VarDecl>(Val: D)) >
2373 Ctx.getTypeAlignInChars(T: Ctx.getUIntPtrType()))) {
2374 IsByRef = true;
2375 }
2376
2377 return IsByRef;
2378}
2379
2380unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2381 assert(getLangOpts().OpenMP);
2382 return DSAStack->getNestingLevel();
2383}
2384
2385bool SemaOpenMP::isInOpenMPTaskUntiedContext() const {
2386 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2387 DSAStack->isUntiedRegion();
2388}
2389
2390bool SemaOpenMP::isInOpenMPTargetExecutionDirective() const {
2391 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2392 !DSAStack->isClauseParsingMode()) ||
2393 DSAStack->hasDirective(
2394 DPred: [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2395 SourceLocation) -> bool {
2396 return isOpenMPTargetExecutionDirective(DKind: K);
2397 },
2398 FromParent: false);
2399}
2400
2401bool SemaOpenMP::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2402 // Only rebuild for Field.
2403 if (!isa<FieldDecl>(Val: D))
2404 return false;
2405 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2406 D,
2407 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2408 DefaultDataSharingAttributes DefaultAttr) {
2409 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2410 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2411 },
2412 DPred: [](OpenMPDirectiveKind) { return true; },
2413 DSAStack->isClauseParsingMode());
2414 if (DVarPrivate.CKind != OMPC_unknown)
2415 return true;
2416 return false;
2417}
2418
2419static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
2420 Expr *CaptureExpr, bool WithInit,
2421 DeclContext *CurContext,
2422 bool AsExpression);
2423
2424VarDecl *SemaOpenMP::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2425 unsigned StopAt) {
2426 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2427 D = getCanonicalDecl(D);
2428
2429 auto *VD = dyn_cast<VarDecl>(Val: D);
2430 // Do not capture constexpr variables.
2431 if (VD && VD->isConstexpr())
2432 return nullptr;
2433
2434 // If we want to determine whether the variable should be captured from the
2435 // perspective of the current capturing scope, and we've already left all the
2436 // capturing scopes of the top directive on the stack, check from the
2437 // perspective of its parent directive (if any) instead.
2438 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2439 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2440
2441 // If we are attempting to capture a global variable in a directive with
2442 // 'target' we return true so that this global is also mapped to the device.
2443 //
2444 if (VD && !VD->hasLocalStorage() &&
2445 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2446 SemaRef.getCurLambda())) {
2447 if (isInOpenMPTargetExecutionDirective()) {
2448 DSAStackTy::DSAVarData DVarTop =
2449 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2450 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2451 return VD;
2452 // If the declaration is enclosed in a 'declare target' directive,
2453 // then it should not be captured.
2454 //
2455 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2456 return nullptr;
2457 CapturedRegionScopeInfo *CSI = nullptr;
2458 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2459 RangeOrContainer: llvm::reverse(C&: SemaRef.FunctionScopes),
2460 N: CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2461 : 0)) {
2462 if (!isa<CapturingScopeInfo>(Val: FSI))
2463 return nullptr;
2464 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(Val: FSI))
2465 if (RSI->CapRegionKind == CR_OpenMP) {
2466 CSI = RSI;
2467 break;
2468 }
2469 }
2470 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2471 SmallVector<OpenMPDirectiveKind, 4> Regions;
2472 getOpenMPCaptureRegions(CaptureRegions&: Regions,
2473 DSAStack->getDirective(Level: CSI->OpenMPLevel));
2474 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2475 return VD;
2476 }
2477 if (isInOpenMPDeclareTargetContext()) {
2478 // Try to mark variable as declare target if it is used in capturing
2479 // regions.
2480 if (getLangOpts().OpenMP <= 45 &&
2481 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2482 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: VD);
2483 return nullptr;
2484 }
2485 }
2486
2487 if (CheckScopeInfo) {
2488 bool OpenMPFound = false;
2489 for (unsigned I = StopAt + 1; I > 0; --I) {
2490 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2491 if (!isa<CapturingScopeInfo>(Val: FSI))
2492 return nullptr;
2493 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(Val: FSI))
2494 if (RSI->CapRegionKind == CR_OpenMP) {
2495 OpenMPFound = true;
2496 break;
2497 }
2498 }
2499 if (!OpenMPFound)
2500 return nullptr;
2501 }
2502
2503 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2504 (!DSAStack->isClauseParsingMode() ||
2505 DSAStack->getParentDirective() != OMPD_unknown)) {
2506 auto &&Info = DSAStack->isLoopControlVariable(D);
2507 if (Info.first ||
2508 (VD && VD->hasLocalStorage() &&
2509 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2510 (VD && DSAStack->isForceVarCapturing()))
2511 return VD ? VD : Info.second;
2512 DSAStackTy::DSAVarData DVarTop =
2513 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2514 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(Kind: DVarTop.CKind) &&
2515 (!VD || VD->hasLocalStorage() ||
2516 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2517 return VD ? VD : cast<VarDecl>(Val: DVarTop.PrivateCopy->getDecl());
2518 // Threadprivate variables must not be captured.
2519 if (isOpenMPThreadPrivate(Kind: DVarTop.CKind))
2520 return nullptr;
2521 // The variable is not private or it is the variable in the directive with
2522 // default(none) clause and not used in any clause.
2523 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2524 D,
2525 CPred: [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2526 return isOpenMPPrivate(Kind: C) && !AppliedToPointee;
2527 },
2528 DPred: [](OpenMPDirectiveKind) { return true; },
2529 DSAStack->isClauseParsingMode());
2530 // Global shared must not be captured.
2531 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2532 ((DSAStack->getDefaultDSA() != DSA_none &&
2533 DSAStack->getDefaultDSA() != DSA_private &&
2534 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2535 DVarTop.CKind == OMPC_shared))
2536 return nullptr;
2537 auto *FD = dyn_cast<FieldDecl>(Val: D);
2538 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2539 !DVarPrivate.PrivateCopy) {
2540 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2541 D,
2542 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2543 DefaultDataSharingAttributes DefaultAttr) {
2544 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2545 (DefaultAttr == DSA_firstprivate ||
2546 DefaultAttr == DSA_private);
2547 },
2548 DPred: [](OpenMPDirectiveKind) { return true; },
2549 DSAStack->isClauseParsingMode());
2550 if (DVarPrivate.CKind == OMPC_unknown)
2551 return nullptr;
2552
2553 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2554 if (VD)
2555 return VD;
2556 if (SemaRef.getCurrentThisType().isNull())
2557 return nullptr;
2558 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(Loc: SourceLocation(),
2559 Type: SemaRef.getCurrentThisType(),
2560 /*IsImplicit=*/true);
2561 const CXXScopeSpec CS = CXXScopeSpec();
2562 Expr *ME = SemaRef.BuildMemberExpr(
2563 Base: ThisExpr, /*IsArrow=*/true, OpLoc: SourceLocation(),
2564 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: FD,
2565 FoundDecl: DeclAccessPair::make(D: FD, AS: FD->getAccess()),
2566 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(), Ty: FD->getType(),
2567 VK: VK_LValue, OK: OK_Ordinary);
2568 OMPCapturedExprDecl *CD = buildCaptureDecl(
2569 S&: SemaRef, Id: FD->getIdentifier(), CaptureExpr: ME, WithInit: DVarPrivate.CKind != OMPC_private,
2570 CurContext: SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2571 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2572 S&: SemaRef, D: CD, Ty: CD->getType().getNonReferenceType(), Loc: SourceLocation());
2573 VD = cast<VarDecl>(Val: VDPrivateRefExpr->getDecl());
2574 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2575 return VD;
2576 }
2577 if (DVarPrivate.CKind != OMPC_unknown ||
2578 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2579 DSAStack->getDefaultDSA() == DSA_private ||
2580 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2581 return VD ? VD : cast<VarDecl>(Val: DVarPrivate.PrivateCopy->getDecl());
2582 }
2583 return nullptr;
2584}
2585
2586void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2587 unsigned Level) const {
2588 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2589}
2590
2591void SemaOpenMP::startOpenMPLoop() {
2592 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2593 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2594 DSAStack->loopInit();
2595}
2596
2597void SemaOpenMP::startOpenMPCXXRangeFor() {
2598 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2599 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2600 DSAStack->resetPossibleLoopCounter();
2601 DSAStack->loopStart();
2602 }
2603}
2604
2605OpenMPClauseKind SemaOpenMP::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2606 unsigned CapLevel) const {
2607 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2608 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2609 (!DSAStack->isClauseParsingMode() ||
2610 DSAStack->getParentDirective() != OMPD_unknown)) {
2611 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2612 D,
2613 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2614 DefaultDataSharingAttributes DefaultAttr) {
2615 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2616 DefaultAttr == DSA_private;
2617 },
2618 DPred: [](OpenMPDirectiveKind) { return true; },
2619 DSAStack->isClauseParsingMode());
2620 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(Val: D) &&
2621 DSAStack->isImplicitDefaultFirstprivateFD(VD: cast<VarDecl>(Val: D)) &&
2622 !DSAStack->isLoopControlVariable(D).first)
2623 return OMPC_private;
2624 }
2625 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTaskingDirective, Level)) {
2626 bool IsTriviallyCopyable =
2627 D->getType().getNonReferenceType().isTriviallyCopyableType(
2628 Context: getASTContext()) &&
2629 !D->getType()
2630 .getNonReferenceType()
2631 .getCanonicalType()
2632 ->getAsCXXRecordDecl();
2633 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2634 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2635 getOpenMPCaptureRegions(CaptureRegions, DKind);
2636 if (isOpenMPTaskingDirective(Kind: CaptureRegions[CapLevel]) &&
2637 (IsTriviallyCopyable ||
2638 !isOpenMPTaskLoopDirective(DKind: CaptureRegions[CapLevel]))) {
2639 if (DSAStack->hasExplicitDSA(
2640 D,
2641 CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2642 Level, /*NotLastprivate=*/true))
2643 return OMPC_firstprivate;
2644 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2645 if (DVar.CKind != OMPC_shared &&
2646 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2647 DSAStack->addImplicitTaskFirstprivate(Level, D);
2648 return OMPC_firstprivate;
2649 }
2650 }
2651 }
2652 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2653 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2654 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2655 DSAStack->resetPossibleLoopCounter(D);
2656 DSAStack->loopStart();
2657 return OMPC_private;
2658 }
2659 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2660 DSAStack->isLoopControlVariable(D).first) &&
2661 !DSAStack->hasExplicitDSA(
2662 D, CPred: [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2663 Level) &&
2664 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2665 return OMPC_private;
2666 }
2667 if (const auto *VD = dyn_cast<VarDecl>(Val: D)) {
2668 if (DSAStack->isThreadPrivate(D: const_cast<VarDecl *>(VD)) &&
2669 DSAStack->isForceVarCapturing() &&
2670 !DSAStack->hasExplicitDSA(
2671 D, CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2672 Level))
2673 return OMPC_private;
2674 }
2675 // User-defined allocators are private since they must be defined in the
2676 // context of target region.
2677 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective, Level) &&
2678 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2679 u: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2680 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2681 return OMPC_private;
2682 return (DSAStack->hasExplicitDSA(
2683 D, CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2684 Level) ||
2685 (DSAStack->isClauseParsingMode() &&
2686 DSAStack->getClauseParsingMode() == OMPC_private) ||
2687 // Consider taskgroup reduction descriptor variable a private
2688 // to avoid possible capture in the region.
2689 (DSAStack->hasExplicitDirective(
2690 DPred: [](OpenMPDirectiveKind K) {
2691 return K == OMPD_taskgroup ||
2692 ((isOpenMPParallelDirective(DKind: K) ||
2693 isOpenMPWorksharingDirective(DKind: K)) &&
2694 !isOpenMPSimdDirective(DKind: K));
2695 },
2696 Level) &&
2697 DSAStack->isTaskgroupReductionRef(VD: D, Level)))
2698 ? OMPC_private
2699 : OMPC_unknown;
2700}
2701
2702void SemaOpenMP::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2703 unsigned Level) {
2704 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2705 D = getCanonicalDecl(D);
2706 OpenMPClauseKind OMPC = OMPC_unknown;
2707 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2708 const unsigned NewLevel = I - 1;
2709 if (DSAStack->hasExplicitDSA(
2710 D,
2711 CPred: [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2712 if (isOpenMPPrivate(Kind: K) && !AppliedToPointee) {
2713 OMPC = K;
2714 return true;
2715 }
2716 return false;
2717 },
2718 Level: NewLevel))
2719 break;
2720 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2721 VD: D, Level: NewLevel,
2722 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2723 OpenMPClauseKind) { return true; })) {
2724 OMPC = OMPC_map;
2725 break;
2726 }
2727 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective,
2728 Level: NewLevel)) {
2729 OMPC = OMPC_map;
2730 if (DSAStack->mustBeFirstprivateAtLevel(
2731 Level: NewLevel, Kind: getVariableCategoryFromDecl(LO: getLangOpts(), VD: D)))
2732 OMPC = OMPC_firstprivate;
2733 break;
2734 }
2735 }
2736 if (OMPC != OMPC_unknown)
2737 FD->addAttr(
2738 A: OMPCaptureKindAttr::CreateImplicit(Ctx&: getASTContext(), CaptureKindVal: unsigned(OMPC)));
2739}
2740
2741bool SemaOpenMP::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2742 unsigned CaptureLevel) const {
2743 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2744 // Return true if the current level is no longer enclosed in a target region.
2745
2746 SmallVector<OpenMPDirectiveKind, 4> Regions;
2747 getOpenMPCaptureRegions(CaptureRegions&: Regions, DSAStack->getDirective(Level));
2748 const auto *VD = dyn_cast<VarDecl>(Val: D);
2749 return VD && !VD->hasLocalStorage() &&
2750 DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective,
2751 Level) &&
2752 Regions[CaptureLevel] != OMPD_task;
2753}
2754
2755bool SemaOpenMP::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2756 unsigned CaptureLevel) const {
2757 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2758 // Return true if the current level is no longer enclosed in a target region.
2759
2760 if (const auto *VD = dyn_cast<VarDecl>(Val: D)) {
2761 if (!VD->hasLocalStorage()) {
2762 if (isInOpenMPTargetExecutionDirective())
2763 return true;
2764 DSAStackTy::DSAVarData TopDVar =
2765 DSAStack->getTopDSA(D, /*FromParent=*/false);
2766 unsigned NumLevels =
2767 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2768 if (Level == 0)
2769 // non-file scope static variable with default(firstprivate)
2770 // should be global captured.
2771 return (NumLevels == CaptureLevel + 1 &&
2772 (TopDVar.CKind != OMPC_shared ||
2773 DSAStack->getDefaultDSA() == DSA_firstprivate));
2774 do {
2775 --Level;
2776 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2777 if (DVar.CKind != OMPC_shared)
2778 return true;
2779 } while (Level > 0);
2780 }
2781 }
2782 return true;
2783}
2784
2785void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2786
2787void SemaOpenMP::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2788 OMPTraitInfo &TI) {
2789 OMPDeclareVariantScopes.push_back(Elt: OMPDeclareVariantScope(TI));
2790}
2791
2792void SemaOpenMP::ActOnOpenMPEndDeclareVariant() {
2793 assert(isInOpenMPDeclareVariantScope() &&
2794 "Not in OpenMP declare variant scope!");
2795
2796 OMPDeclareVariantScopes.pop_back();
2797}
2798
2799void SemaOpenMP::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2800 const FunctionDecl *Callee,
2801 SourceLocation Loc) {
2802 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2803 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2804 OMPDeclareTargetDeclAttr::getDeviceType(VD: Caller->getMostRecentDecl());
2805 // Ignore host functions during device analysis.
2806 if (getLangOpts().OpenMPIsTargetDevice &&
2807 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2808 return;
2809 // Ignore nohost functions during host analysis.
2810 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2811 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2812 return;
2813 const FunctionDecl *FD = Callee->getMostRecentDecl();
2814 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(VD: FD);
2815 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2816 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2817 // Diagnose host function called during device codegen.
2818 StringRef HostDevTy =
2819 getOpenMPSimpleClauseTypeName(Kind: OMPC_device_type, Type: OMPC_DEVICE_TYPE_host);
2820 Diag(Loc, DiagID: diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2821 Diag(Loc: *OMPDeclareTargetDeclAttr::getLocation(VD: FD),
2822 DiagID: diag::note_omp_marked_device_type_here)
2823 << HostDevTy;
2824 return;
2825 }
2826 if (!getLangOpts().OpenMPIsTargetDevice &&
2827 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2828 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2829 // In OpenMP 5.2 or later, if the function has a host variant then allow
2830 // that to be called instead
2831 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2832 for (OMPDeclareVariantAttr *A :
2833 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2834 auto *DeclRefVariant = cast<DeclRefExpr>(Val: A->getVariantFuncRef());
2835 auto *VariantFD = cast<FunctionDecl>(Val: DeclRefVariant->getDecl());
2836 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2837 OMPDeclareTargetDeclAttr::getDeviceType(
2838 VD: VariantFD->getMostRecentDecl());
2839 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2840 return true;
2841 }
2842 return false;
2843 };
2844 if (getLangOpts().OpenMP >= 52 &&
2845 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2846 return;
2847 // Diagnose nohost function called during host codegen.
2848 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2849 Kind: OMPC_device_type, Type: OMPC_DEVICE_TYPE_nohost);
2850 Diag(Loc, DiagID: diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2851 Diag(Loc: *OMPDeclareTargetDeclAttr::getLocation(VD: FD),
2852 DiagID: diag::note_omp_marked_device_type_here)
2853 << NoHostDevTy;
2854 }
2855}
2856
2857void SemaOpenMP::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2858 const DeclarationNameInfo &DirName,
2859 Scope *CurScope, SourceLocation Loc) {
2860 DSAStack->push(DKind, DirName, CurScope, Loc);
2861 SemaRef.PushExpressionEvaluationContext(
2862 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
2863}
2864
2865void SemaOpenMP::StartOpenMPClause(OpenMPClauseKind K) {
2866 DSAStack->setClauseParsingMode(K);
2867}
2868
2869void SemaOpenMP::EndOpenMPClause() {
2870 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2871 SemaRef.CleanupVarDeclMarking();
2872}
2873
2874static std::pair<ValueDecl *, bool>
2875getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2876 SourceRange &ERange, bool AllowArraySection = false,
2877 bool AllowAssumedSizeArray = false, StringRef DiagType = "");
2878
2879/// Check consistency of the reduction clauses.
2880static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2881 ArrayRef<OMPClause *> Clauses) {
2882 bool InscanFound = false;
2883 SourceLocation InscanLoc;
2884 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2885 // A reduction clause without the inscan reduction-modifier may not appear on
2886 // a construct on which a reduction clause with the inscan reduction-modifier
2887 // appears.
2888 for (OMPClause *C : Clauses) {
2889 if (C->getClauseKind() != OMPC_reduction)
2890 continue;
2891 auto *RC = cast<OMPReductionClause>(Val: C);
2892 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2893 InscanFound = true;
2894 InscanLoc = RC->getModifierLoc();
2895 continue;
2896 }
2897 if (RC->getModifier() == OMPC_REDUCTION_task) {
2898 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2899 // A reduction clause with the task reduction-modifier may only appear on
2900 // a parallel construct, a worksharing construct or a combined or
2901 // composite construct for which any of the aforementioned constructs is a
2902 // constituent construct and simd or loop are not constituent constructs.
2903 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2904 if (!(isOpenMPParallelDirective(DKind: CurDir) ||
2905 isOpenMPWorksharingDirective(DKind: CurDir)) ||
2906 isOpenMPSimdDirective(DKind: CurDir))
2907 S.Diag(Loc: RC->getModifierLoc(),
2908 DiagID: diag::err_omp_reduction_task_not_parallel_or_worksharing);
2909 continue;
2910 }
2911 }
2912 if (InscanFound) {
2913 for (OMPClause *C : Clauses) {
2914 if (C->getClauseKind() != OMPC_reduction)
2915 continue;
2916 auto *RC = cast<OMPReductionClause>(Val: C);
2917 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2918 S.Diag(Loc: RC->getModifier() == OMPC_REDUCTION_unknown
2919 ? RC->getBeginLoc()
2920 : RC->getModifierLoc(),
2921 DiagID: diag::err_omp_inscan_reduction_expected);
2922 S.Diag(Loc: InscanLoc, DiagID: diag::note_omp_previous_inscan_reduction);
2923 continue;
2924 }
2925 for (Expr *Ref : RC->varlist()) {
2926 assert(Ref && "NULL expr in OpenMP reduction clause.");
2927 SourceLocation ELoc;
2928 SourceRange ERange;
2929 Expr *SimpleRefExpr = Ref;
2930 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
2931 /*AllowArraySection=*/true);
2932 ValueDecl *D = Res.first;
2933 if (!D)
2934 continue;
2935 if (!Stack->isUsedInScanDirective(D: getCanonicalDecl(D))) {
2936 S.Diag(Loc: Ref->getExprLoc(),
2937 DiagID: diag::err_omp_reduction_not_inclusive_exclusive)
2938 << Ref->getSourceRange();
2939 }
2940 }
2941 }
2942 }
2943}
2944
2945static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2946 ArrayRef<OMPClause *> Clauses);
2947static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2948 bool WithInit);
2949
2950static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2951 const ValueDecl *D,
2952 const DSAStackTy::DSAVarData &DVar,
2953 bool IsLoopIterVar = false);
2954
2955void SemaOpenMP::EndOpenMPDSABlock(Stmt *CurDirective) {
2956 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2957 // A variable of class type (or array thereof) that appears in a lastprivate
2958 // clause requires an accessible, unambiguous default constructor for the
2959 // class type, unless the list item is also specified in a firstprivate
2960 // clause.
2961
2962 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2963 SmallVector<Expr *, 8> PrivateCopies;
2964 for (Expr *DE : Clause->varlist()) {
2965 if (DE->isValueDependent() || DE->isTypeDependent()) {
2966 PrivateCopies.push_back(Elt: nullptr);
2967 continue;
2968 }
2969 auto *DRE = cast<DeclRefExpr>(Val: DE->IgnoreParens());
2970 auto *VD = cast<VarDecl>(Val: DRE->getDecl());
2971 QualType Type = VD->getType().getNonReferenceType();
2972 const DSAStackTy::DSAVarData DVar =
2973 DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
2974 if (DVar.CKind != OMPC_lastprivate) {
2975 // The variable is also a firstprivate, so initialization sequence
2976 // for private copy is generated already.
2977 PrivateCopies.push_back(Elt: nullptr);
2978 continue;
2979 }
2980 // Generate helper private variable and initialize it with the
2981 // default value. The address of the original variable is replaced
2982 // by the address of the new private variable in CodeGen. This new
2983 // variable is not added to IdResolver, so the code in the OpenMP
2984 // region uses original variable for proper diagnostics.
2985 VarDecl *VDPrivate = buildVarDecl(
2986 SemaRef, Loc: DE->getExprLoc(), Type: Type.getUnqualifiedType(), Name: VD->getName(),
2987 Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr, OrigRef: DRE);
2988 SemaRef.ActOnUninitializedDecl(dcl: VDPrivate);
2989 if (VDPrivate->isInvalidDecl()) {
2990 PrivateCopies.push_back(Elt: nullptr);
2991 continue;
2992 }
2993 PrivateCopies.push_back(Elt: buildDeclRefExpr(
2994 S&: SemaRef, D: VDPrivate, Ty: DE->getType(), Loc: DE->getExprLoc()));
2995 }
2996 Clause->setPrivateCopies(PrivateCopies);
2997 };
2998
2999 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
3000 // Finalize nontemporal clause by handling private copies, if any.
3001 SmallVector<Expr *, 8> PrivateRefs;
3002 for (Expr *RefExpr : Clause->varlist()) {
3003 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
3004 SourceLocation ELoc;
3005 SourceRange ERange;
3006 Expr *SimpleRefExpr = RefExpr;
3007 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
3008 if (Res.second)
3009 // It will be analyzed later.
3010 PrivateRefs.push_back(Elt: RefExpr);
3011 ValueDecl *D = Res.first;
3012 if (!D)
3013 continue;
3014
3015 const DSAStackTy::DSAVarData DVar =
3016 DSAStack->getTopDSA(D, /*FromParent=*/false);
3017 PrivateRefs.push_back(Elt: DVar.PrivateCopy ? DVar.PrivateCopy
3018 : SimpleRefExpr);
3019 }
3020 Clause->setPrivateRefs(PrivateRefs);
3021 };
3022
3023 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
3024 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3025 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
3026 auto *DRE = dyn_cast<DeclRefExpr>(Val: D.Allocator->IgnoreParenImpCasts());
3027 if (!DRE)
3028 continue;
3029 ValueDecl *VD = DRE->getDecl();
3030 if (!VD || !isa<VarDecl>(Val: VD))
3031 continue;
3032 DSAStackTy::DSAVarData DVar =
3033 DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
3034 // OpenMP [2.12.5, target Construct]
3035 // Memory allocators that appear in a uses_allocators clause cannot
3036 // appear in other data-sharing attribute clauses or data-mapping
3037 // attribute clauses in the same construct.
3038 Expr *MapExpr = nullptr;
3039 if (DVar.RefExpr ||
3040 DSAStack->checkMappableExprComponentListsForDecl(
3041 VD, /*CurrentRegionOnly=*/true,
3042 Check: [VD, &MapExpr](
3043 OMPClauseMappableExprCommon::MappableExprComponentListRef
3044 MapExprComponents,
3045 OpenMPClauseKind C) {
3046 auto MI = MapExprComponents.rbegin();
3047 auto ME = MapExprComponents.rend();
3048 if (MI != ME &&
3049 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3050 VD->getCanonicalDecl()) {
3051 MapExpr = MI->getAssociatedExpression();
3052 return true;
3053 }
3054 return false;
3055 })) {
3056 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::err_omp_allocator_used_in_clauses)
3057 << D.Allocator->getSourceRange();
3058 if (DVar.RefExpr)
3059 reportOriginalDsa(SemaRef, DSAStack, D: VD, DVar);
3060 else
3061 Diag(Loc: MapExpr->getExprLoc(), DiagID: diag::note_used_here)
3062 << MapExpr->getSourceRange();
3063 }
3064 }
3065 };
3066
3067 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(Val: CurDirective)) {
3068 for (OMPClause *C : D->clauses()) {
3069 if (auto *Clause = dyn_cast<OMPLastprivateClause>(Val: C)) {
3070 FinalizeLastprivate(Clause);
3071 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(Val: C)) {
3072 FinalizeNontemporal(Clause);
3073 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(Val: C)) {
3074 FinalizeAllocators(Clause);
3075 }
3076 }
3077 // Check allocate clauses.
3078 if (!SemaRef.CurContext->isDependentContext())
3079 checkAllocateClauses(S&: SemaRef, DSAStack, Clauses: D->clauses());
3080 checkReductionClauses(S&: SemaRef, DSAStack, Clauses: D->clauses());
3081 }
3082
3083 DSAStack->pop();
3084 SemaRef.DiscardCleanupsInEvaluationContext();
3085 SemaRef.PopExpressionEvaluationContext();
3086}
3087
3088static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3089 Expr *NumIterations, Sema &SemaRef,
3090 Scope *S, DSAStackTy *Stack);
3091
3092static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
3093 OMPLoopBasedDirective::HelperExprs &B,
3094 DSAStackTy *Stack) {
3095 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3096 "loop exprs were not built");
3097
3098 if (SemaRef.CurContext->isDependentContext())
3099 return false;
3100
3101 // Finalize the clauses that need pre-built expressions for CodeGen.
3102 for (OMPClause *C : Clauses) {
3103 auto *LC = dyn_cast<OMPLinearClause>(Val: C);
3104 if (!LC)
3105 continue;
3106 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
3107 NumIterations: B.NumIterations, SemaRef,
3108 S: SemaRef.getCurScope(), Stack))
3109 return true;
3110 }
3111
3112 return false;
3113}
3114
3115namespace {
3116
3117class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3118private:
3119 Sema &SemaRef;
3120
3121public:
3122 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3123 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3124 NamedDecl *ND = Candidate.getCorrectionDecl();
3125 if (const auto *VD = dyn_cast_or_null<VarDecl>(Val: ND)) {
3126 return VD->hasGlobalStorage() &&
3127 SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(),
3128 S: SemaRef.getCurScope());
3129 }
3130 return false;
3131 }
3132
3133 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3134 return std::make_unique<VarDeclFilterCCC>(args&: *this);
3135 }
3136};
3137
3138class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3139private:
3140 Sema &SemaRef;
3141
3142public:
3143 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3144 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3145 NamedDecl *ND = Candidate.getCorrectionDecl();
3146 if (ND && ((isa<VarDecl>(Val: ND) && ND->getKind() == Decl::Var) ||
3147 isa<FunctionDecl>(Val: ND))) {
3148 return SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(),
3149 S: SemaRef.getCurScope());
3150 }
3151 return false;
3152 }
3153
3154 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3155 return std::make_unique<VarOrFuncDeclFilterCCC>(args&: *this);
3156 }
3157};
3158
3159} // namespace
3160
3161ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope,
3162 CXXScopeSpec &ScopeSpec,
3163 const DeclarationNameInfo &Id,
3164 OpenMPDirectiveKind Kind) {
3165 ASTContext &Context = getASTContext();
3166 unsigned OMPVersion = getLangOpts().OpenMP;
3167 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
3168 SemaRef.LookupParsedName(R&: Lookup, S: CurScope, SS: &ScopeSpec,
3169 /*ObjectType=*/QualType(),
3170 /*AllowBuiltinCreation=*/true);
3171
3172 if (Lookup.isAmbiguous())
3173 return ExprError();
3174
3175 VarDecl *VD;
3176 if (!Lookup.isSingleResult()) {
3177 VarDeclFilterCCC CCC(SemaRef);
3178 if (TypoCorrection Corrected =
3179 SemaRef.CorrectTypo(Typo: Id, LookupKind: Sema::LookupOrdinaryName, S: CurScope, SS: nullptr,
3180 CCC, Mode: CorrectTypoKind::ErrorRecovery)) {
3181 SemaRef.diagnoseTypo(
3182 Correction: Corrected,
3183 TypoDiag: SemaRef.PDiag(DiagID: Lookup.empty() ? diag::err_undeclared_var_use_suggest
3184 : diag::err_omp_expected_var_arg_suggest)
3185 << Id.getName());
3186 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3187 } else {
3188 Diag(Loc: Id.getLoc(), DiagID: Lookup.empty() ? diag::err_undeclared_var_use
3189 : diag::err_omp_expected_var_arg)
3190 << Id.getName();
3191 return ExprError();
3192 }
3193 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3194 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_expected_var_arg) << Id.getName();
3195 Diag(Loc: Lookup.getFoundDecl()->getLocation(), DiagID: diag::note_declared_at);
3196 return ExprError();
3197 }
3198 Lookup.suppressDiagnostics();
3199
3200 // OpenMP [2.9.2, Syntax, C/C++]
3201 // Variables must be file-scope, namespace-scope, or static block-scope.
3202 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3203 !VD->hasGlobalStorage()) {
3204 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_global_var_arg)
3205 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << !VD->isStaticLocal();
3206 bool IsDecl =
3207 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3208 Diag(Loc: VD->getLocation(),
3209 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3210 << VD;
3211 return ExprError();
3212 }
3213
3214 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3215 NamedDecl *ND = CanonicalVD;
3216 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3217 // A threadprivate or groupprivate directive for file-scope variables must
3218 // appear outside any definition or declaration.
3219 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3220 !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3221 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3222 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3223 bool IsDecl =
3224 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3225 Diag(Loc: VD->getLocation(),
3226 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3227 << VD;
3228 return ExprError();
3229 }
3230 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3231 // A threadprivate or groupprivate directive for static class member
3232 // variables must appear in the class definition, in the same scope in which
3233 // the member variables are declared.
3234 if (CanonicalVD->isStaticDataMember() &&
3235 !CanonicalVD->getDeclContext()->Equals(DC: SemaRef.getCurLexicalContext())) {
3236 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3237 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3238 bool IsDecl =
3239 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3240 Diag(Loc: VD->getLocation(),
3241 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3242 << VD;
3243 return ExprError();
3244 }
3245 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3246 // A threadprivate or groupprivate directive for namespace-scope variables
3247 // must appear outside any definition or declaration other than the
3248 // namespace definition itself.
3249 if (CanonicalVD->getDeclContext()->isNamespace() &&
3250 (!SemaRef.getCurLexicalContext()->isFileContext() ||
3251 !SemaRef.getCurLexicalContext()->Encloses(
3252 DC: CanonicalVD->getDeclContext()))) {
3253 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3254 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3255 bool IsDecl =
3256 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3257 Diag(Loc: VD->getLocation(),
3258 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3259 << VD;
3260 return ExprError();
3261 }
3262 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3263 // A threadprivate or groupprivate directive for static block-scope
3264 // variables must appear in the scope of the variable and not in a nested
3265 // scope.
3266 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3267 !SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(), S: CurScope)) {
3268 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3269 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3270 bool IsDecl =
3271 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3272 Diag(Loc: VD->getLocation(),
3273 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3274 << VD;
3275 return ExprError();
3276 }
3277
3278 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3279 // A threadprivate or groupprivate directive must lexically precede all
3280 // references to any of the variables in its list.
3281 if ((Kind == OMPD_threadprivate && VD->isUsed() &&
3282 !DSAStack->isThreadPrivate(D: VD)) ||
3283 (Kind == OMPD_groupprivate && VD->isUsed())) {
3284 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_used)
3285 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3286 return ExprError();
3287 }
3288
3289 QualType ExprType = VD->getType().getNonReferenceType();
3290 return DeclRefExpr::Create(Context, QualifierLoc: NestedNameSpecifierLoc(),
3291 TemplateKWLoc: SourceLocation(), D: VD,
3292 /*RefersToEnclosingVariableOrCapture=*/false,
3293 NameLoc: Id.getLoc(), T: ExprType, VK: VK_LValue);
3294}
3295
3296SemaOpenMP::DeclGroupPtrTy
3297SemaOpenMP::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3298 ArrayRef<Expr *> VarList) {
3299 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3300 SemaRef.CurContext->addDecl(D);
3301 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3302 }
3303 return nullptr;
3304}
3305
3306SemaOpenMP::DeclGroupPtrTy
3307SemaOpenMP::ActOnOpenMPGroupPrivateDirective(SourceLocation Loc,
3308 ArrayRef<Expr *> VarList) {
3309 if (!getLangOpts().OpenMP || getLangOpts().OpenMP < 60) {
3310 Diag(Loc, DiagID: diag::err_omp_unexpected_directive)
3311 << getOpenMPDirectiveName(D: OMPD_groupprivate, Ver: getLangOpts().OpenMP);
3312 return nullptr;
3313 }
3314 if (OMPGroupPrivateDecl *D = CheckOMPGroupPrivateDecl(Loc, VarList)) {
3315 SemaRef.CurContext->addDecl(D);
3316 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3317 }
3318 return nullptr;
3319}
3320
3321namespace {
3322class LocalVarRefChecker final
3323 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3324 Sema &SemaRef;
3325
3326public:
3327 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3328 if (const auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
3329 if (VD->hasLocalStorage()) {
3330 SemaRef.Diag(Loc: E->getBeginLoc(),
3331 DiagID: diag::err_omp_local_var_in_threadprivate_init)
3332 << E->getSourceRange();
3333 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::note_defined_here)
3334 << VD << VD->getSourceRange();
3335 return true;
3336 }
3337 }
3338 return false;
3339 }
3340 bool VisitStmt(const Stmt *S) {
3341 for (const Stmt *Child : S->children()) {
3342 if (Child && Visit(S: Child))
3343 return true;
3344 }
3345 return false;
3346 }
3347 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3348};
3349} // namespace
3350
3351OMPThreadPrivateDecl *
3352SemaOpenMP::CheckOMPThreadPrivateDecl(SourceLocation Loc,
3353 ArrayRef<Expr *> VarList) {
3354 ASTContext &Context = getASTContext();
3355 SmallVector<Expr *, 8> Vars;
3356 for (Expr *RefExpr : VarList) {
3357 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3358 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3359 SourceLocation ILoc = DE->getExprLoc();
3360
3361 // Mark variable as used.
3362 VD->setReferenced();
3363 VD->markUsed(C&: Context);
3364
3365 QualType QType = VD->getType();
3366 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3367 // It will be analyzed later.
3368 Vars.push_back(Elt: DE);
3369 continue;
3370 }
3371
3372 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3373 // A threadprivate variable must not have an incomplete type.
3374 if (SemaRef.RequireCompleteType(
3375 Loc: ILoc, T: VD->getType(), DiagID: diag::err_omp_threadprivate_incomplete_type)) {
3376 continue;
3377 }
3378
3379 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3380 // A threadprivate variable must not have a reference type.
3381 if (VD->getType()->isReferenceType()) {
3382 unsigned OMPVersion = getLangOpts().OpenMP;
3383 Diag(Loc: ILoc, DiagID: diag::err_omp_ref_type_arg)
3384 << getOpenMPDirectiveName(D: OMPD_threadprivate, Ver: OMPVersion)
3385 << VD->getType();
3386 bool IsDecl =
3387 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3388 Diag(Loc: VD->getLocation(),
3389 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3390 << VD;
3391 continue;
3392 }
3393
3394 // Check if this is a TLS variable. If TLS is not being supported, produce
3395 // the corresponding diagnostic.
3396 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3397 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3398 getLangOpts().OpenMPUseTLS &&
3399 getASTContext().getTargetInfo().isTLSSupported())) ||
3400 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3401 !VD->isLocalVarDecl())) {
3402 Diag(Loc: ILoc, DiagID: diag::err_omp_var_thread_local)
3403 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3404 bool IsDecl =
3405 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3406 Diag(Loc: VD->getLocation(),
3407 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3408 << VD;
3409 continue;
3410 }
3411
3412 // Check if initial value of threadprivate variable reference variable with
3413 // local storage (it is not supported by runtime).
3414 if (const Expr *Init = VD->getAnyInitializer()) {
3415 LocalVarRefChecker Checker(SemaRef);
3416 if (Checker.Visit(S: Init))
3417 continue;
3418 }
3419
3420 Vars.push_back(Elt: RefExpr);
3421 DSAStack->addDSA(D: VD, E: DE, A: OMPC_threadprivate);
3422 VD->addAttr(A: OMPThreadPrivateDeclAttr::CreateImplicit(
3423 Ctx&: Context, Range: SourceRange(Loc, Loc)));
3424 if (ASTMutationListener *ML = Context.getASTMutationListener())
3425 ML->DeclarationMarkedOpenMPThreadPrivate(D: VD);
3426 }
3427 OMPThreadPrivateDecl *D = nullptr;
3428 if (!Vars.empty()) {
3429 D = OMPThreadPrivateDecl::Create(C&: Context, DC: SemaRef.getCurLexicalContext(),
3430 L: Loc, VL: Vars);
3431 D->setAccess(AS_public);
3432 }
3433 return D;
3434}
3435
3436OMPGroupPrivateDecl *
3437SemaOpenMP::CheckOMPGroupPrivateDecl(SourceLocation Loc,
3438 ArrayRef<Expr *> VarList) {
3439 ASTContext &Context = getASTContext();
3440 SmallVector<Expr *, 8> Vars;
3441 for (Expr *RefExpr : VarList) {
3442 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3443 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3444 SourceLocation ILoc = DE->getExprLoc();
3445
3446 // Mark variable as used.
3447 VD->setReferenced();
3448 VD->markUsed(C&: Context);
3449
3450 QualType QType = VD->getType();
3451 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3452 // It will be analyzed later.
3453 Vars.push_back(Elt: DE);
3454 continue;
3455 }
3456
3457 // OpenMP groupprivate restrictions:
3458 // A groupprivate variable must not have an incomplete type.
3459 if (SemaRef.RequireCompleteType(
3460 Loc: ILoc, T: VD->getType(), DiagID: diag::err_omp_groupprivate_incomplete_type)) {
3461 continue;
3462 }
3463
3464 // A groupprivate variable must not have a reference type.
3465 if (VD->getType()->isReferenceType()) {
3466 Diag(Loc: ILoc, DiagID: diag::err_omp_ref_type_arg)
3467 << getOpenMPDirectiveName(D: OMPD_groupprivate) << VD->getType();
3468 bool IsDecl =
3469 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3470 Diag(Loc: VD->getLocation(),
3471 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3472 << VD;
3473 continue;
3474 }
3475
3476 // A variable that is declared with an initializer must not appear in a
3477 // groupprivate directive.
3478 if (VD->getAnyInitializer()) {
3479 Diag(Loc: ILoc, DiagID: diag::err_omp_groupprivate_with_initializer)
3480 << VD->getDeclName();
3481 bool IsDecl =
3482 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3483 Diag(Loc: VD->getLocation(),
3484 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3485 << VD;
3486 continue;
3487 }
3488
3489 Vars.push_back(Elt: RefExpr);
3490 DSAStack->addDSA(D: VD, E: DE, A: OMPC_groupprivate);
3491 VD->addAttr(A: OMPGroupPrivateDeclAttr::CreateImplicit(Ctx&: Context,
3492 Range: SourceRange(Loc, Loc)));
3493 if (ASTMutationListener *ML = Context.getASTMutationListener())
3494 ML->DeclarationMarkedOpenMPGroupPrivate(D: VD);
3495 }
3496 OMPGroupPrivateDecl *D = nullptr;
3497 if (!Vars.empty()) {
3498 D = OMPGroupPrivateDecl::Create(C&: Context, DC: SemaRef.getCurLexicalContext(),
3499 L: Loc, VL: Vars);
3500 D->setAccess(AS_public);
3501 }
3502 return D;
3503}
3504
3505static OMPAllocateDeclAttr::AllocatorTypeTy
3506getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3507 if (!Allocator)
3508 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3509 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3510 Allocator->isInstantiationDependent() ||
3511 Allocator->containsUnexpandedParameterPack())
3512 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3513 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3514 llvm::FoldingSetNodeID AEId;
3515 const Expr *AE = Allocator->IgnoreParenImpCasts();
3516 AE->IgnoreImpCasts()->Profile(ID&: AEId, Context: S.getASTContext(), /*Canonical=*/true);
3517 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3518 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3519 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3520 llvm::FoldingSetNodeID DAEId;
3521 DefAllocator->IgnoreImpCasts()->Profile(ID&: DAEId, Context: S.getASTContext(),
3522 /*Canonical=*/true);
3523 if (AEId == DAEId) {
3524 AllocatorKindRes = AllocatorKind;
3525 break;
3526 }
3527 }
3528 return AllocatorKindRes;
3529}
3530
3531static bool checkPreviousOMPAllocateAttribute(
3532 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3533 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3534 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3535 return false;
3536 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3537 Expr *PrevAllocator = A->getAllocator();
3538 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3539 getAllocatorKind(S, Stack, Allocator: PrevAllocator);
3540 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3541 if (AllocatorsMatch &&
3542 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3543 Allocator && PrevAllocator) {
3544 const Expr *AE = Allocator->IgnoreParenImpCasts();
3545 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3546 llvm::FoldingSetNodeID AEId, PAEId;
3547 AE->Profile(ID&: AEId, Context: S.Context, /*Canonical=*/true);
3548 PAE->Profile(ID&: PAEId, Context: S.Context, /*Canonical=*/true);
3549 AllocatorsMatch = AEId == PAEId;
3550 }
3551 if (!AllocatorsMatch) {
3552 SmallString<256> AllocatorBuffer;
3553 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3554 if (Allocator)
3555 Allocator->printPretty(OS&: AllocatorStream, Helper: nullptr, Policy: S.getPrintingPolicy());
3556 SmallString<256> PrevAllocatorBuffer;
3557 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3558 if (PrevAllocator)
3559 PrevAllocator->printPretty(OS&: PrevAllocatorStream, Helper: nullptr,
3560 Policy: S.getPrintingPolicy());
3561
3562 SourceLocation AllocatorLoc =
3563 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3564 SourceRange AllocatorRange =
3565 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3566 SourceLocation PrevAllocatorLoc =
3567 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3568 SourceRange PrevAllocatorRange =
3569 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3570 S.Diag(Loc: AllocatorLoc, DiagID: diag::warn_omp_used_different_allocator)
3571 << (Allocator ? 1 : 0) << AllocatorStream.str()
3572 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3573 << AllocatorRange;
3574 S.Diag(Loc: PrevAllocatorLoc, DiagID: diag::note_omp_previous_allocator)
3575 << PrevAllocatorRange;
3576 return true;
3577 }
3578 return false;
3579}
3580
3581static void
3582applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3583 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3584 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3585 if (VD->hasAttr<OMPAllocateDeclAttr>())
3586 return;
3587 if (Alignment &&
3588 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3589 Alignment->isInstantiationDependent() ||
3590 Alignment->containsUnexpandedParameterPack()))
3591 // Apply later when we have a usable value.
3592 return;
3593 if (Allocator &&
3594 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3595 Allocator->isInstantiationDependent() ||
3596 Allocator->containsUnexpandedParameterPack()))
3597 return;
3598 auto *A = OMPAllocateDeclAttr::CreateImplicit(Ctx&: S.Context, AllocatorType: AllocatorKind,
3599 Allocator, Alignment, Range: SR);
3600 VD->addAttr(A);
3601 if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3602 ML->DeclarationMarkedOpenMPAllocate(D: VD, A);
3603}
3604
3605SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPAllocateDirective(
3606 SourceLocation Loc, ArrayRef<Expr *> VarList, ArrayRef<OMPClause *> Clauses,
3607 DeclContext *Owner) {
3608 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3609 Expr *Alignment = nullptr;
3610 Expr *Allocator = nullptr;
3611 if (Clauses.empty()) {
3612 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3613 // allocate directives that appear in a target region must specify an
3614 // allocator clause unless a requires directive with the dynamic_allocators
3615 // clause is present in the same compilation unit.
3616 if (getLangOpts().OpenMPIsTargetDevice &&
3617 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3618 SemaRef.targetDiag(Loc, DiagID: diag::err_expected_allocator_clause);
3619 } else {
3620 for (const OMPClause *C : Clauses)
3621 if (const auto *AC = dyn_cast<OMPAllocatorClause>(Val: C))
3622 Allocator = AC->getAllocator();
3623 else if (const auto *AC = dyn_cast<OMPAlignClause>(Val: C))
3624 Alignment = AC->getAlignment();
3625 else
3626 llvm_unreachable("Unexpected clause on allocate directive");
3627 }
3628 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3629 getAllocatorKind(S&: SemaRef, DSAStack, Allocator);
3630 SmallVector<Expr *, 8> Vars;
3631 for (Expr *RefExpr : VarList) {
3632 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3633 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3634
3635 // Check if this is a TLS variable or global register.
3636 if (VD->getTLSKind() != VarDecl::TLS_None ||
3637 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3638 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3639 !VD->isLocalVarDecl()))
3640 continue;
3641
3642 // If the used several times in the allocate directive, the same allocator
3643 // must be used.
3644 if (checkPreviousOMPAllocateAttribute(S&: SemaRef, DSAStack, RefExpr, VD,
3645 AllocatorKind, Allocator))
3646 continue;
3647
3648 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3649 // If a list item has a static storage type, the allocator expression in the
3650 // allocator clause must be a constant expression that evaluates to one of
3651 // the predefined memory allocator values.
3652 if (Allocator && VD->hasGlobalStorage()) {
3653 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3654 Diag(Loc: Allocator->getExprLoc(),
3655 DiagID: diag::err_omp_expected_predefined_allocator)
3656 << Allocator->getSourceRange();
3657 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3658 VarDecl::DeclarationOnly;
3659 Diag(Loc: VD->getLocation(),
3660 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3661 << VD;
3662 continue;
3663 }
3664 }
3665
3666 Vars.push_back(Elt: RefExpr);
3667 applyOMPAllocateAttribute(S&: SemaRef, VD, AllocatorKind, Allocator, Alignment,
3668 SR: DE->getSourceRange());
3669 }
3670 if (Vars.empty())
3671 return nullptr;
3672 if (!Owner)
3673 Owner = SemaRef.getCurLexicalContext();
3674 auto *D = OMPAllocateDecl::Create(C&: getASTContext(), DC: Owner, L: Loc, VL: Vars, CL: Clauses);
3675 D->setAccess(AS_public);
3676 Owner->addDecl(D);
3677 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3678}
3679
3680SemaOpenMP::DeclGroupPtrTy
3681SemaOpenMP::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3682 ArrayRef<OMPClause *> ClauseList) {
3683 OMPRequiresDecl *D = nullptr;
3684 if (!SemaRef.CurContext->isFileContext()) {
3685 Diag(Loc, DiagID: diag::err_omp_invalid_scope) << "requires";
3686 } else {
3687 D = CheckOMPRequiresDecl(Loc, Clauses: ClauseList);
3688 if (D) {
3689 SemaRef.CurContext->addDecl(D);
3690 DSAStack->addRequiresDecl(RD: D);
3691 }
3692 }
3693 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3694}
3695
3696void SemaOpenMP::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3697 OpenMPDirectiveKind DKind,
3698 ArrayRef<std::string> Assumptions,
3699 bool SkippedClauses) {
3700 if (!SkippedClauses && Assumptions.empty()) {
3701 unsigned OMPVersion = getLangOpts().OpenMP;
3702 Diag(Loc, DiagID: diag::err_omp_no_clause_for_directive)
3703 << llvm::omp::getAllAssumeClauseOptions()
3704 << llvm::omp::getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
3705 }
3706
3707 auto *AA =
3708 OMPAssumeAttr::Create(Ctx&: getASTContext(), Assumption: llvm::join(R&: Assumptions, Separator: ","), Range: Loc);
3709 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3710 OMPAssumeScoped.push_back(Elt: AA);
3711 return;
3712 }
3713
3714 // Global assumes without assumption clauses are ignored.
3715 if (Assumptions.empty())
3716 return;
3717
3718 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3719 "Unexpected omp assumption directive!");
3720 OMPAssumeGlobal.push_back(Elt: AA);
3721
3722 // The OMPAssumeGlobal scope above will take care of new declarations but
3723 // we also want to apply the assumption to existing ones, e.g., to
3724 // declarations in included headers. To this end, we traverse all existing
3725 // declaration contexts and annotate function declarations here.
3726 SmallVector<DeclContext *, 8> DeclContexts;
3727 auto *Ctx = SemaRef.CurContext;
3728 while (Ctx->getLexicalParent())
3729 Ctx = Ctx->getLexicalParent();
3730 DeclContexts.push_back(Elt: Ctx);
3731 while (!DeclContexts.empty()) {
3732 DeclContext *DC = DeclContexts.pop_back_val();
3733 for (auto *SubDC : DC->decls()) {
3734 if (SubDC->isInvalidDecl())
3735 continue;
3736 if (auto *CTD = dyn_cast<ClassTemplateDecl>(Val: SubDC)) {
3737 DeclContexts.push_back(Elt: CTD->getTemplatedDecl());
3738 llvm::append_range(C&: DeclContexts, R: CTD->specializations());
3739 continue;
3740 }
3741 if (auto *DC = dyn_cast<DeclContext>(Val: SubDC))
3742 DeclContexts.push_back(Elt: DC);
3743 if (auto *F = dyn_cast<FunctionDecl>(Val: SubDC)) {
3744 F->addAttr(A: AA);
3745 continue;
3746 }
3747 }
3748 }
3749}
3750
3751void SemaOpenMP::ActOnOpenMPEndAssumesDirective() {
3752 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3753 OMPAssumeScoped.pop_back();
3754}
3755
3756StmtResult SemaOpenMP::ActOnOpenMPAssumeDirective(ArrayRef<OMPClause *> Clauses,
3757 Stmt *AStmt,
3758 SourceLocation StartLoc,
3759 SourceLocation EndLoc) {
3760 if (!AStmt)
3761 return StmtError();
3762
3763 return OMPAssumeDirective::Create(Ctx: getASTContext(), StartLoc, EndLoc, Clauses,
3764 AStmt);
3765}
3766
3767OMPRequiresDecl *
3768SemaOpenMP::CheckOMPRequiresDecl(SourceLocation Loc,
3769 ArrayRef<OMPClause *> ClauseList) {
3770 /// For target specific clauses, the requires directive cannot be
3771 /// specified after the handling of any of the target regions in the
3772 /// current compilation unit.
3773 ArrayRef<SourceLocation> TargetLocations =
3774 DSAStack->getEncounteredTargetLocs();
3775 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3776 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3777 for (const OMPClause *CNew : ClauseList) {
3778 // Check if any of the requires clauses affect target regions.
3779 if (isa<OMPUnifiedSharedMemoryClause>(Val: CNew) ||
3780 isa<OMPUnifiedAddressClause>(Val: CNew) ||
3781 isa<OMPReverseOffloadClause>(Val: CNew) ||
3782 isa<OMPDynamicAllocatorsClause>(Val: CNew)) {
3783 Diag(Loc, DiagID: diag::err_omp_directive_before_requires)
3784 << "target" << getOpenMPClauseNameForDiag(C: CNew->getClauseKind());
3785 for (SourceLocation TargetLoc : TargetLocations) {
3786 Diag(Loc: TargetLoc, DiagID: diag::note_omp_requires_encountered_directive)
3787 << "target";
3788 }
3789 } else if (!AtomicLoc.isInvalid() &&
3790 isa<OMPAtomicDefaultMemOrderClause>(Val: CNew)) {
3791 Diag(Loc, DiagID: diag::err_omp_directive_before_requires)
3792 << "atomic" << getOpenMPClauseNameForDiag(C: CNew->getClauseKind());
3793 Diag(Loc: AtomicLoc, DiagID: diag::note_omp_requires_encountered_directive)
3794 << "atomic";
3795 }
3796 }
3797 }
3798
3799 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3800 return OMPRequiresDecl::Create(
3801 C&: getASTContext(), DC: SemaRef.getCurLexicalContext(), L: Loc, CL: ClauseList);
3802 return nullptr;
3803}
3804
3805static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3806 const ValueDecl *D,
3807 const DSAStackTy::DSAVarData &DVar,
3808 bool IsLoopIterVar) {
3809 if (DVar.RefExpr) {
3810 SemaRef.Diag(Loc: DVar.RefExpr->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
3811 << getOpenMPClauseNameForDiag(C: DVar.CKind);
3812 return;
3813 }
3814 enum {
3815 PDSA_StaticMemberShared,
3816 PDSA_StaticLocalVarShared,
3817 PDSA_LoopIterVarPrivate,
3818 PDSA_LoopIterVarLinear,
3819 PDSA_LoopIterVarLastprivate,
3820 PDSA_ConstVarShared,
3821 PDSA_GlobalVarShared,
3822 PDSA_TaskVarFirstprivate,
3823 PDSA_LocalVarPrivate,
3824 PDSA_Implicit
3825 } Reason = PDSA_Implicit;
3826 bool ReportHint = false;
3827 auto ReportLoc = D->getLocation();
3828 auto *VD = dyn_cast<VarDecl>(Val: D);
3829 if (IsLoopIterVar) {
3830 if (DVar.CKind == OMPC_private)
3831 Reason = PDSA_LoopIterVarPrivate;
3832 else if (DVar.CKind == OMPC_lastprivate)
3833 Reason = PDSA_LoopIterVarLastprivate;
3834 else
3835 Reason = PDSA_LoopIterVarLinear;
3836 } else if (isOpenMPTaskingDirective(Kind: DVar.DKind) &&
3837 DVar.CKind == OMPC_firstprivate) {
3838 Reason = PDSA_TaskVarFirstprivate;
3839 ReportLoc = DVar.ImplicitDSALoc;
3840 } else if (VD && VD->isStaticLocal())
3841 Reason = PDSA_StaticLocalVarShared;
3842 else if (VD && VD->isStaticDataMember())
3843 Reason = PDSA_StaticMemberShared;
3844 else if (VD && VD->isFileVarDecl())
3845 Reason = PDSA_GlobalVarShared;
3846 else if (D->getType().isConstant(Ctx: SemaRef.getASTContext()))
3847 Reason = PDSA_ConstVarShared;
3848 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3849 ReportHint = true;
3850 Reason = PDSA_LocalVarPrivate;
3851 }
3852 if (Reason != PDSA_Implicit) {
3853 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
3854 SemaRef.Diag(Loc: ReportLoc, DiagID: diag::note_omp_predetermined_dsa)
3855 << Reason << ReportHint
3856 << getOpenMPDirectiveName(D: Stack->getCurrentDirective(), Ver: OMPVersion);
3857 } else if (DVar.ImplicitDSALoc.isValid()) {
3858 SemaRef.Diag(Loc: DVar.ImplicitDSALoc, DiagID: diag::note_omp_implicit_dsa)
3859 << getOpenMPClauseNameForDiag(C: DVar.CKind);
3860 }
3861}
3862
3863static OpenMPMapClauseKind
3864getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
3865 bool IsAggregateOrDeclareTarget,
3866 bool HasConstQualifier) {
3867 OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
3868 switch (M) {
3869 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3870 case OMPC_DEFAULTMAP_MODIFIER_storage:
3871 Kind = OMPC_MAP_alloc;
3872 break;
3873 case OMPC_DEFAULTMAP_MODIFIER_to:
3874 Kind = OMPC_MAP_to;
3875 break;
3876 case OMPC_DEFAULTMAP_MODIFIER_from:
3877 Kind = OMPC_MAP_from;
3878 break;
3879 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3880 Kind = OMPC_MAP_tofrom;
3881 break;
3882 case OMPC_DEFAULTMAP_MODIFIER_present:
3883 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3884 // If implicit-behavior is present, each variable referenced in the
3885 // construct in the category specified by variable-category is treated as if
3886 // it had been listed in a map clause with the map-type of alloc and
3887 // map-type-modifier of present.
3888 Kind = OMPC_MAP_alloc;
3889 break;
3890 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3891 case OMPC_DEFAULTMAP_MODIFIER_private:
3892 case OMPC_DEFAULTMAP_MODIFIER_last:
3893 llvm_unreachable("Unexpected defaultmap implicit behavior");
3894 case OMPC_DEFAULTMAP_MODIFIER_none:
3895 case OMPC_DEFAULTMAP_MODIFIER_default:
3896 case OMPC_DEFAULTMAP_MODIFIER_unknown:
3897 // IsAggregateOrDeclareTarget could be true if:
3898 // 1. the implicit behavior for aggregate is tofrom
3899 // 2. it's a declare target link
3900 if (IsAggregateOrDeclareTarget) {
3901 if (HasConstQualifier)
3902 Kind = OMPC_MAP_to;
3903 else
3904 Kind = OMPC_MAP_tofrom;
3905 break;
3906 }
3907 llvm_unreachable("Unexpected defaultmap implicit behavior");
3908 }
3909 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3910 return Kind;
3911}
3912
3913static bool hasNoMutableFields(const CXXRecordDecl *RD) {
3914 for (const auto *FD : RD->fields()) {
3915 if (FD->isMutable())
3916 return false;
3917 QualType FT = FD->getType();
3918 while (FT->isArrayType())
3919 FT = FT->getAsArrayTypeUnsafe()->getElementType();
3920 if (const auto *NestedRD = FT->getAsCXXRecordDecl())
3921 if (!hasNoMutableFields(RD: NestedRD))
3922 return false;
3923 }
3924 return true;
3925}
3926
3927static bool hasConstQualifiedMappingType(QualType T) {
3928 while (T->isArrayType())
3929 T = T->getAsArrayTypeUnsafe()->getElementType();
3930 if (!T.isConstQualified())
3931 return false;
3932 if (const auto *RD = T->getAsCXXRecordDecl())
3933 // TODO : Per OpenMP 6.0 p299 lines 3-4, non-mutable members of a
3934 // const-qualified struct should also be ignored for 'from'. This
3935 // requires per-member mapping granularity via compiler-generated
3936 // default mappers and a mechanism to ensure constness to the mapper.
3937 // For now we conservatively treat any struct with mutable members as
3938 // requiring full 'tofrom'.
3939 return hasNoMutableFields(RD);
3940 return true;
3941}
3942
3943namespace {
3944struct VariableImplicitInfo {
3945 static const unsigned MapKindNum = OMPC_MAP_unknown;
3946 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3947
3948 llvm::SetVector<Expr *> Privates;
3949 llvm::SetVector<Expr *> Firstprivates;
3950 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3951 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3952 MapModifiers[DefaultmapKindNum];
3953};
3954
3955class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3956 DSAStackTy *Stack;
3957 Sema &SemaRef;
3958 OpenMPDirectiveKind DKind = OMPD_unknown;
3959 bool ErrorFound = false;
3960 bool TryCaptureCXXThisMembers = false;
3961 CapturedStmt *CS = nullptr;
3962
3963 VariableImplicitInfo ImpInfo;
3964 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3965 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3966
3967 void VisitSubCaptures(OMPExecutableDirective *S) {
3968 // Check implicitly captured variables.
3969 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3970 return;
3971 if (S->getDirectiveKind() == OMPD_atomic ||
3972 S->getDirectiveKind() == OMPD_critical ||
3973 S->getDirectiveKind() == OMPD_section ||
3974 S->getDirectiveKind() == OMPD_master ||
3975 S->getDirectiveKind() == OMPD_masked ||
3976 S->getDirectiveKind() == OMPD_scope ||
3977 S->getDirectiveKind() == OMPD_assume ||
3978 isOpenMPLoopTransformationDirective(DKind: S->getDirectiveKind())) {
3979 Visit(S: S->getAssociatedStmt());
3980 return;
3981 }
3982 visitSubCaptures(S: S->getInnermostCapturedStmt());
3983 // Try to capture inner this->member references to generate correct mappings
3984 // and diagnostics.
3985 if (TryCaptureCXXThisMembers ||
3986 (isOpenMPTargetExecutionDirective(DKind) &&
3987 llvm::any_of(Range: S->getInnermostCapturedStmt()->captures(),
3988 P: [](const CapturedStmt::Capture &C) {
3989 return C.capturesThis();
3990 }))) {
3991 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3992 TryCaptureCXXThisMembers = true;
3993 Visit(S: S->getInnermostCapturedStmt()->getCapturedStmt());
3994 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3995 }
3996 // In tasks firstprivates are not captured anymore, need to analyze them
3997 // explicitly.
3998 if (isOpenMPTaskingDirective(Kind: S->getDirectiveKind()) &&
3999 !isOpenMPTaskLoopDirective(DKind: S->getDirectiveKind())) {
4000 for (OMPClause *C : S->clauses())
4001 if (auto *FC = dyn_cast<OMPFirstprivateClause>(Val: C)) {
4002 for (Expr *Ref : FC->varlist())
4003 Visit(S: Ref);
4004 }
4005 }
4006 }
4007
4008public:
4009 void VisitDeclRefExpr(DeclRefExpr *E) {
4010 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
4011 E->isValueDependent() || E->containsUnexpandedParameterPack() ||
4012 E->isInstantiationDependent() ||
4013 E->isNonOdrUse() == clang::NOUR_Unevaluated)
4014 return;
4015 if (auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
4016 // Check the datasharing rules for the expressions in the clauses.
4017 if (!CS || (isa<OMPCapturedExprDecl>(Val: VD) && !CS->capturesVariable(Var: VD) &&
4018 !Stack->getTopDSA(D: VD, /*FromParent=*/false).RefExpr &&
4019 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
4020 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: VD))
4021 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
4022 Visit(S: CED->getInit());
4023 return;
4024 }
4025 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(Val: VD))
4026 // Do not analyze internal variables and do not enclose them into
4027 // implicit clauses.
4028 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
4029 return;
4030 VD = VD->getCanonicalDecl();
4031 // Skip internally declared variables.
4032 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(Var: VD) &&
4033 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4034 !Stack->isImplicitTaskFirstprivate(D: VD))
4035 return;
4036 // Skip allocators in uses_allocators clauses.
4037 if (Stack->isUsesAllocatorsDecl(D: VD))
4038 return;
4039
4040 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D: VD, /*FromParent=*/false);
4041 // Check if the variable has explicit DSA set and stop analysis if it so.
4042 if (DVar.RefExpr || !ImplicitDeclarations.insert(V: VD).second)
4043 return;
4044
4045 // Skip internally declared static variables.
4046 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
4047 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
4048 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(Var: VD) &&
4049 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
4050 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
4051 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4052 !Stack->isImplicitTaskFirstprivate(D: VD))
4053 return;
4054
4055 SourceLocation ELoc = E->getExprLoc();
4056 // The default(none) clause requires that each variable that is referenced
4057 // in the construct, and does not have a predetermined data-sharing
4058 // attribute, must have its data-sharing attribute explicitly determined
4059 // by being listed in a data-sharing attribute clause.
4060 if (DVar.CKind == OMPC_unknown &&
4061 (Stack->getDefaultDSA() == DSA_none ||
4062 Stack->getDefaultDSA() == DSA_private ||
4063 Stack->getDefaultDSA() == DSA_firstprivate) &&
4064 isImplicitOrExplicitTaskingRegion(DKind) &&
4065 VarsWithInheritedDSA.count(Val: VD) == 0) {
4066 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4067 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4068 Stack->getDefaultDSA() == DSA_private)) {
4069 DSAStackTy::DSAVarData DVar =
4070 Stack->getImplicitDSA(D: VD, /*FromParent=*/false);
4071 InheritedDSA = DVar.CKind == OMPC_unknown;
4072 }
4073 if (InheritedDSA)
4074 VarsWithInheritedDSA[VD] = E;
4075 if (Stack->getDefaultDSA() == DSA_none)
4076 return;
4077 }
4078
4079 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
4080 // If implicit-behavior is none, each variable referenced in the
4081 // construct that does not have a predetermined data-sharing attribute
4082 // and does not appear in a to or link clause on a declare target
4083 // directive must be listed in a data-mapping attribute clause, a
4084 // data-sharing attribute clause (including a data-sharing attribute
4085 // clause on a combined construct where target. is one of the
4086 // constituent constructs), or an is_device_ptr clause.
4087 OpenMPDefaultmapClauseKind ClauseKind =
4088 getVariableCategoryFromDecl(LO: SemaRef.getLangOpts(), VD);
4089 if (SemaRef.getLangOpts().OpenMP >= 50) {
4090 bool IsModifierNone = Stack->getDefaultmapModifier(Kind: ClauseKind) ==
4091 OMPC_DEFAULTMAP_MODIFIER_none;
4092 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4093 VarsWithInheritedDSA.count(Val: VD) == 0 && !Res) {
4094 // Only check for data-mapping attribute and is_device_ptr here
4095 // since we have already make sure that the declaration does not
4096 // have a data-sharing attribute above
4097 if (!Stack->checkMappableExprComponentListsForDecl(
4098 VD, /*CurrentRegionOnly=*/true,
4099 Check: [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
4100 MapExprComponents,
4101 OpenMPClauseKind) {
4102 auto MI = MapExprComponents.rbegin();
4103 auto ME = MapExprComponents.rend();
4104 return MI != ME && MI->getAssociatedDeclaration() == VD;
4105 })) {
4106 VarsWithInheritedDSA[VD] = E;
4107 return;
4108 }
4109 }
4110 }
4111 if (SemaRef.getLangOpts().OpenMP > 50) {
4112 bool IsModifierPresent = Stack->getDefaultmapModifier(Kind: ClauseKind) ==
4113 OMPC_DEFAULTMAP_MODIFIER_present;
4114 if (IsModifierPresent) {
4115 if (!llvm::is_contained(Range&: ImpInfo.MapModifiers[ClauseKind],
4116 Element: OMPC_MAP_MODIFIER_present)) {
4117 ImpInfo.MapModifiers[ClauseKind].push_back(
4118 Elt: OMPC_MAP_MODIFIER_present);
4119 }
4120 }
4121 }
4122
4123 if (isOpenMPTargetExecutionDirective(DKind) &&
4124 !Stack->isLoopControlVariable(D: VD).first) {
4125 if (!Stack->checkMappableExprComponentListsForDecl(
4126 VD, /*CurrentRegionOnly=*/true,
4127 Check: [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
4128 StackComponents,
4129 OpenMPClauseKind) {
4130 if (SemaRef.LangOpts.OpenMP >= 50)
4131 return !StackComponents.empty();
4132 // Variable is used if it has been marked as an array, array
4133 // section, array shaping or the variable itself.
4134 return StackComponents.size() == 1 ||
4135 llvm::all_of(
4136 Range: llvm::drop_begin(RangeOrContainer: llvm::reverse(C&: StackComponents)),
4137 P: [](const OMPClauseMappableExprCommon::
4138 MappableComponent &MC) {
4139 return MC.getAssociatedDeclaration() ==
4140 nullptr &&
4141 (isa<ArraySectionExpr>(
4142 Val: MC.getAssociatedExpression()) ||
4143 isa<OMPArrayShapingExpr>(
4144 Val: MC.getAssociatedExpression()) ||
4145 isa<ArraySubscriptExpr>(
4146 Val: MC.getAssociatedExpression()));
4147 });
4148 })) {
4149 bool IsFirstprivate = false;
4150 // By default lambdas are captured as firstprivates.
4151 if (const auto *RD =
4152 VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
4153 IsFirstprivate = RD->isLambda();
4154 IsFirstprivate =
4155 IsFirstprivate || (Stack->mustBeFirstprivate(Kind: ClauseKind) && !Res);
4156 if (IsFirstprivate) {
4157 ImpInfo.Firstprivates.insert(X: E);
4158 } else {
4159 OpenMPDefaultmapClauseModifier M =
4160 Stack->getDefaultmapModifier(Kind: ClauseKind);
4161 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4162 ImpInfo.Privates.insert(X: E);
4163 } else {
4164 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
4165 M, IsAggregateOrDeclareTarget: ClauseKind == OMPC_DEFAULTMAP_aggregate || Res,
4166 HasConstQualifier: hasConstQualifiedMappingType(T: E->getType()));
4167 ImpInfo.Mappings[ClauseKind][Kind].insert(X: E);
4168 }
4169 }
4170 return;
4171 }
4172 }
4173
4174 // OpenMP [2.9.3.6, Restrictions, p.2]
4175 // A list item that appears in a reduction clause of the innermost
4176 // enclosing worksharing or parallel construct may not be accessed in an
4177 // explicit task.
4178 DVar = Stack->hasInnermostDSA(
4179 D: VD,
4180 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
4181 return C == OMPC_reduction && !AppliedToPointee;
4182 },
4183 DPred: [](OpenMPDirectiveKind K) {
4184 return isOpenMPParallelDirective(DKind: K) ||
4185 isOpenMPWorksharingDirective(DKind: K) || isOpenMPTeamsDirective(DKind: K);
4186 },
4187 /*FromParent=*/true);
4188 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind == OMPC_reduction) {
4189 ErrorFound = true;
4190 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_in_task);
4191 reportOriginalDsa(SemaRef, Stack, D: VD, DVar);
4192 return;
4193 }
4194
4195 // Define implicit data-sharing attributes for task.
4196 DVar = Stack->getImplicitDSA(D: VD, /*FromParent=*/false);
4197 if (((isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind != OMPC_shared) ||
4198 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4199 DVar.CKind == OMPC_firstprivate) ||
4200 (Stack->getDefaultDSA() == DSA_private &&
4201 DVar.CKind == OMPC_private)) &&
4202 !DVar.RefExpr)) &&
4203 !Stack->isLoopControlVariable(D: VD).first) {
4204 if (Stack->getDefaultDSA() == DSA_private)
4205 ImpInfo.Privates.insert(X: E);
4206 else
4207 ImpInfo.Firstprivates.insert(X: E);
4208 return;
4209 }
4210
4211 // Store implicitly used globals with declare target link for parent
4212 // target.
4213 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
4214 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4215 Stack->addToParentTargetRegionLinkGlobals(E);
4216 return;
4217 }
4218 }
4219 }
4220 void VisitMemberExpr(MemberExpr *E) {
4221 if (E->isTypeDependent() || E->isValueDependent() ||
4222 E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
4223 return;
4224 auto *FD = dyn_cast<FieldDecl>(Val: E->getMemberDecl());
4225 if (auto *TE = dyn_cast<CXXThisExpr>(Val: E->getBase()->IgnoreParenCasts())) {
4226 if (!FD)
4227 return;
4228 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D: FD, /*FromParent=*/false);
4229 // Check if the variable has explicit DSA set and stop analysis if it
4230 // so.
4231 if (DVar.RefExpr || !ImplicitDeclarations.insert(V: FD).second)
4232 return;
4233
4234 if (isOpenMPTargetExecutionDirective(DKind) &&
4235 !Stack->isLoopControlVariable(D: FD).first &&
4236 !Stack->checkMappableExprComponentListsForDecl(
4237 VD: FD, /*CurrentRegionOnly=*/true,
4238 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef
4239 StackComponents,
4240 OpenMPClauseKind) {
4241 return isa<CXXThisExpr>(
4242 Val: cast<MemberExpr>(
4243 Val: StackComponents.back().getAssociatedExpression())
4244 ->getBase()
4245 ->IgnoreParens());
4246 })) {
4247 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4248 // A bit-field cannot appear in a map clause.
4249 //
4250 if (FD->isBitField())
4251 return;
4252
4253 // Check to see if the member expression is referencing a class that
4254 // has already been explicitly mapped
4255 if (Stack->isClassPreviouslyMapped(QT: TE->getType()))
4256 return;
4257
4258 OpenMPDefaultmapClauseModifier Modifier =
4259 Stack->getDefaultmapModifier(Kind: OMPC_DEFAULTMAP_aggregate);
4260 OpenMPDefaultmapClauseKind ClauseKind =
4261 getVariableCategoryFromDecl(LO: SemaRef.getLangOpts(), VD: FD);
4262 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
4263 M: Modifier, /*IsAggregateOrDeclareTarget=*/true,
4264 /*HasConstQualifier=*/false);
4265 ImpInfo.Mappings[ClauseKind][Kind].insert(X: E);
4266 return;
4267 }
4268
4269 SourceLocation ELoc = E->getExprLoc();
4270 // OpenMP [2.9.3.6, Restrictions, p.2]
4271 // A list item that appears in a reduction clause of the innermost
4272 // enclosing worksharing or parallel construct may not be accessed in
4273 // an explicit task.
4274 DVar = Stack->hasInnermostDSA(
4275 D: FD,
4276 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
4277 return C == OMPC_reduction && !AppliedToPointee;
4278 },
4279 DPred: [](OpenMPDirectiveKind K) {
4280 return isOpenMPParallelDirective(DKind: K) ||
4281 isOpenMPWorksharingDirective(DKind: K) || isOpenMPTeamsDirective(DKind: K);
4282 },
4283 /*FromParent=*/true);
4284 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind == OMPC_reduction) {
4285 ErrorFound = true;
4286 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_in_task);
4287 reportOriginalDsa(SemaRef, Stack, D: FD, DVar);
4288 return;
4289 }
4290
4291 // Define implicit data-sharing attributes for task.
4292 DVar = Stack->getImplicitDSA(D: FD, /*FromParent=*/false);
4293 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind != OMPC_shared &&
4294 !Stack->isLoopControlVariable(D: FD).first) {
4295 // Check if there is a captured expression for the current field in the
4296 // region. Do not mark it as firstprivate unless there is no captured
4297 // expression.
4298 // TODO: try to make it firstprivate.
4299 if (DVar.CKind != OMPC_unknown)
4300 ImpInfo.Firstprivates.insert(X: E);
4301 }
4302 return;
4303 }
4304 if (isOpenMPTargetExecutionDirective(DKind)) {
4305 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
4306 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, CKind: OMPC_map,
4307 DKind, /*NoDiagnose=*/true))
4308 return;
4309 const auto *VD = cast<ValueDecl>(
4310 Val: CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4311 if (!Stack->checkMappableExprComponentListsForDecl(
4312 VD, /*CurrentRegionOnly=*/true,
4313 Check: [&CurComponents](
4314 OMPClauseMappableExprCommon::MappableExprComponentListRef
4315 StackComponents,
4316 OpenMPClauseKind) {
4317 auto CCI = CurComponents.rbegin();
4318 auto CCE = CurComponents.rend();
4319 for (const auto &SC : llvm::reverse(C&: StackComponents)) {
4320 // Do both expressions have the same kind?
4321 if (CCI->getAssociatedExpression()->getStmtClass() !=
4322 SC.getAssociatedExpression()->getStmtClass())
4323 if (!((isa<ArraySectionExpr>(
4324 Val: SC.getAssociatedExpression()) ||
4325 isa<OMPArrayShapingExpr>(
4326 Val: SC.getAssociatedExpression())) &&
4327 isa<ArraySubscriptExpr>(
4328 Val: CCI->getAssociatedExpression())))
4329 return false;
4330
4331 const Decl *CCD = CCI->getAssociatedDeclaration();
4332 const Decl *SCD = SC.getAssociatedDeclaration();
4333 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4334 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4335 if (SCD != CCD)
4336 return false;
4337 std::advance(i&: CCI, n: 1);
4338 if (CCI == CCE)
4339 break;
4340 }
4341 return true;
4342 })) {
4343 Visit(S: E->getBase());
4344 }
4345 } else if (!TryCaptureCXXThisMembers) {
4346 Visit(S: E->getBase());
4347 }
4348 }
4349 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4350 for (OMPClause *C : S->clauses()) {
4351 // Skip analysis of arguments of private clauses for task|target
4352 // directives.
4353 if (isa_and_nonnull<OMPPrivateClause>(Val: C))
4354 continue;
4355 // Skip analysis of arguments of implicitly defined firstprivate clause
4356 // for task|target directives.
4357 // Skip analysis of arguments of implicitly defined map clause for target
4358 // directives.
4359 if (C && !((isa<OMPFirstprivateClause>(Val: C) || isa<OMPMapClause>(Val: C)) &&
4360 C->isImplicit() && !isOpenMPTaskingDirective(Kind: DKind))) {
4361 for (Stmt *CC : C->children()) {
4362 if (CC)
4363 Visit(S: CC);
4364 }
4365 }
4366 }
4367 // Check implicitly captured variables.
4368 VisitSubCaptures(S);
4369 }
4370
4371 void VisitOMPCanonicalLoopNestTransformationDirective(
4372 OMPCanonicalLoopNestTransformationDirective *S) {
4373 // Loop transformation directives do not introduce data sharing
4374 VisitStmt(S);
4375 }
4376
4377 void VisitCallExpr(CallExpr *S) {
4378 for (Stmt *C : S->arguments()) {
4379 if (C) {
4380 // Check implicitly captured variables in the task-based directives to
4381 // check if they must be firstprivatized.
4382 Visit(S: C);
4383 }
4384 }
4385 if (Expr *Callee = S->getCallee()) {
4386 auto *CI = Callee->IgnoreParenImpCasts();
4387 if (auto *CE = dyn_cast<MemberExpr>(Val: CI))
4388 Visit(S: CE->getBase());
4389 else if (auto *CE = dyn_cast<DeclRefExpr>(Val: CI))
4390 Visit(S: CE);
4391 }
4392 }
4393 void VisitStmt(Stmt *S) {
4394 for (Stmt *C : S->children()) {
4395 if (C) {
4396 // Check implicitly captured variables in the task-based directives to
4397 // check if they must be firstprivatized.
4398 Visit(S: C);
4399 }
4400 }
4401 }
4402
4403 void visitSubCaptures(CapturedStmt *S) {
4404 for (const CapturedStmt::Capture &Cap : S->captures()) {
4405 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4406 continue;
4407 VarDecl *VD = Cap.getCapturedVar();
4408 // Do not try to map the variable if it or its sub-component was mapped
4409 // already.
4410 if (isOpenMPTargetExecutionDirective(DKind) &&
4411 Stack->checkMappableExprComponentListsForDecl(
4412 VD, /*CurrentRegionOnly=*/true,
4413 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4414 OpenMPClauseKind) { return true; }))
4415 continue;
4416 DeclRefExpr *DRE = buildDeclRefExpr(
4417 S&: SemaRef, D: VD, Ty: VD->getType().getNonLValueExprType(Context: SemaRef.Context),
4418 Loc: Cap.getLocation(), /*RefersToCapture=*/true);
4419 Visit(S: DRE);
4420 }
4421 }
4422 bool isErrorFound() const { return ErrorFound; }
4423 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4424 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4425 return VarsWithInheritedDSA;
4426 }
4427
4428 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4429 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4430 DKind = S->getCurrentDirective();
4431 // Process declare target link variables for the target directives.
4432 if (isOpenMPTargetExecutionDirective(DKind)) {
4433 for (DeclRefExpr *E : Stack->getLinkGlobals())
4434 Visit(S: E);
4435 }
4436 }
4437};
4438} // namespace
4439
4440static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4441 OpenMPDirectiveKind DKind,
4442 bool ScopeEntry) {
4443 SmallVector<llvm::omp::TraitProperty, 8> Traits;
4444 if (isOpenMPTargetExecutionDirective(DKind))
4445 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_target_target);
4446 if (isOpenMPTeamsDirective(DKind))
4447 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_teams_teams);
4448 if (isOpenMPParallelDirective(DKind))
4449 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_parallel_parallel);
4450 if (isOpenMPWorksharingDirective(DKind))
4451 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_for_for);
4452 if (isOpenMPSimdDirective(DKind))
4453 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_simd_simd);
4454 Stack->handleConstructTrait(Traits, ScopeEntry);
4455}
4456
4457static SmallVector<SemaOpenMP::CapturedParamNameType>
4458getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4459 ASTContext &Context = SemaRef.getASTContext();
4460 QualType KmpInt32Ty =
4461 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4462 QualType KmpInt32PtrTy =
4463 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4464 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4465 std::make_pair(x: ".global_tid.", y&: KmpInt32PtrTy),
4466 std::make_pair(x: ".bound_tid.", y&: KmpInt32PtrTy),
4467 };
4468 if (LoopBoundSharing) {
4469 QualType KmpSizeTy = Context.getSizeType().withConst();
4470 Params.push_back(Elt: std::make_pair(x: ".previous.lb.", y&: KmpSizeTy));
4471 Params.push_back(Elt: std::make_pair(x: ".previous.ub.", y&: KmpSizeTy));
4472 }
4473
4474 // __context with shared vars
4475 Params.push_back(Elt: std::make_pair(x: StringRef(), y: QualType()));
4476 return Params;
4477}
4478
4479static SmallVector<SemaOpenMP::CapturedParamNameType>
4480getTeamsRegionParams(Sema &SemaRef) {
4481 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4482}
4483
4484static SmallVector<SemaOpenMP::CapturedParamNameType>
4485getTaskRegionParams(Sema &SemaRef) {
4486 ASTContext &Context = SemaRef.getASTContext();
4487 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(DestWidth: 32, Signed: 1).withConst();
4488 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4489 QualType KmpInt32PtrTy =
4490 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4491 QualType Args[] = {VoidPtrTy};
4492 FunctionProtoType::ExtProtoInfo EPI;
4493 EPI.Variadic = true;
4494 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4495 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4496 std::make_pair(x: ".global_tid.", y&: KmpInt32Ty),
4497 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4498 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4499 std::make_pair(
4500 x: ".copy_fn.",
4501 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4502 std::make_pair(x: ".task_t.", y: Context.VoidPtrTy.withConst()),
4503 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4504 };
4505 return Params;
4506}
4507
4508static SmallVector<SemaOpenMP::CapturedParamNameType>
4509getTargetRegionParams(Sema &SemaRef) {
4510 ASTContext &Context = SemaRef.getASTContext();
4511 SmallVector<SemaOpenMP::CapturedParamNameType> Params;
4512 // __context with shared vars
4513 Params.push_back(Elt: std::make_pair(x: StringRef(), y: QualType()));
4514 // Implicit dyn_ptr argument, appended as the last parameter. Present on both
4515 // host and device so argument counts match without runtime manipulation.
4516 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4517 Params.push_back(Elt: std::make_pair(x: StringRef("dyn_ptr"), y&: VoidPtrTy));
4518 return Params;
4519}
4520
4521static SmallVector<SemaOpenMP::CapturedParamNameType>
4522getUnknownRegionParams(Sema &SemaRef) {
4523 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4524 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4525 };
4526 return Params;
4527}
4528
4529static SmallVector<SemaOpenMP::CapturedParamNameType>
4530getTaskloopRegionParams(Sema &SemaRef) {
4531 ASTContext &Context = SemaRef.getASTContext();
4532 QualType KmpInt32Ty =
4533 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4534 QualType KmpUInt64Ty =
4535 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4536 QualType KmpInt64Ty =
4537 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4538 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4539 QualType KmpInt32PtrTy =
4540 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4541 QualType Args[] = {VoidPtrTy};
4542 FunctionProtoType::ExtProtoInfo EPI;
4543 EPI.Variadic = true;
4544 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4545 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4546 std::make_pair(x: ".global_tid.", y&: KmpInt32Ty),
4547 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4548 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4549 std::make_pair(
4550 x: ".copy_fn.",
4551 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4552 std::make_pair(x: ".task_t.", y: Context.VoidPtrTy.withConst()),
4553 std::make_pair(x: ".lb.", y&: KmpUInt64Ty),
4554 std::make_pair(x: ".ub.", y&: KmpUInt64Ty),
4555 std::make_pair(x: ".st.", y&: KmpInt64Ty),
4556 std::make_pair(x: ".liter.", y&: KmpInt32Ty),
4557 std::make_pair(x: ".reductions.", y&: VoidPtrTy),
4558 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4559 };
4560 return Params;
4561}
4562
4563static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind,
4564 Scope *CurScope, SourceLocation Loc) {
4565 SmallVector<OpenMPDirectiveKind> Regions;
4566 getOpenMPCaptureRegions(CaptureRegions&: Regions, DKind);
4567
4568 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(Kind: DKind);
4569
4570 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4571 CSI->TheCapturedDecl->addAttr(A: AlwaysInlineAttr::CreateImplicit(
4572 Ctx&: SemaRef.getASTContext(), Range: {}, S: AlwaysInlineAttr::Keyword_forceinline));
4573 };
4574
4575 for (auto [Level, RKind] : llvm::enumerate(First&: Regions)) {
4576 switch (RKind) {
4577 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4578 // are listed here.
4579 case OMPD_parallel:
4580 SemaRef.ActOnCapturedRegionStart(
4581 Loc, CurScope, Kind: CR_OpenMP,
4582 Params: getParallelRegionParams(SemaRef, LoopBoundSharing), OpenMPCaptureLevel: Level);
4583 break;
4584 case OMPD_teams:
4585 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4586 Params: getTeamsRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4587 break;
4588 case OMPD_task:
4589 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4590 Params: getTaskRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4591 // Mark this captured region as inlined, because we don't use outlined
4592 // function directly.
4593 MarkAsInlined(SemaRef.getCurCapturedRegion());
4594 break;
4595 case OMPD_taskloop:
4596 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4597 Params: getTaskloopRegionParams(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_target:
4603 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4604 Params: getTargetRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4605 break;
4606 case OMPD_unknown:
4607 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4608 Params: getUnknownRegionParams(SemaRef));
4609 break;
4610 case OMPD_metadirective:
4611 case OMPD_nothing:
4612 default:
4613 llvm_unreachable("Unexpected capture region");
4614 }
4615 }
4616}
4617
4618void SemaOpenMP::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,
4619 Scope *CurScope) {
4620 switch (DKind) {
4621 case OMPD_atomic:
4622 case OMPD_critical:
4623 case OMPD_masked:
4624 case OMPD_master:
4625 case OMPD_section:
4626 case OMPD_tile:
4627 case OMPD_stripe:
4628 case OMPD_unroll:
4629 case OMPD_reverse:
4630 case OMPD_split:
4631 case OMPD_interchange:
4632 case OMPD_fuse:
4633 case OMPD_assume:
4634 break;
4635 default:
4636 processCapturedRegions(SemaRef, DKind, CurScope,
4637 DSAStack->getConstructLoc());
4638 break;
4639 }
4640
4641 DSAStack->setContext(SemaRef.CurContext);
4642 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4643}
4644
4645int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4646 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4647}
4648
4649int SemaOpenMP::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4650 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4651 getOpenMPCaptureRegions(CaptureRegions, DKind);
4652 return CaptureRegions.size();
4653}
4654
4655static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
4656 Expr *CaptureExpr, bool WithInit,
4657 DeclContext *CurContext,
4658 bool AsExpression) {
4659 assert(CaptureExpr);
4660 ASTContext &C = S.getASTContext();
4661 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4662 QualType Ty = Init->getType();
4663 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4664 if (S.getLangOpts().CPlusPlus) {
4665 Ty = C.getLValueReferenceType(T: Ty);
4666 } else {
4667 Ty = C.getPointerType(T: Ty);
4668 ExprResult Res =
4669 S.CreateBuiltinUnaryOp(OpLoc: CaptureExpr->getExprLoc(), Opc: UO_AddrOf, InputExpr: Init);
4670 if (!Res.isUsable())
4671 return nullptr;
4672 Init = Res.get();
4673 }
4674 WithInit = true;
4675 }
4676 auto *CED = OMPCapturedExprDecl::Create(C, DC: CurContext, Id, T: Ty,
4677 StartLoc: CaptureExpr->getBeginLoc());
4678 if (!WithInit)
4679 CED->addAttr(A: OMPCaptureNoInitAttr::CreateImplicit(Ctx&: C));
4680 CurContext->addHiddenDecl(D: CED);
4681 Sema::TentativeAnalysisScope Trap(S);
4682 S.AddInitializerToDecl(dcl: CED, init: Init, /*DirectInit=*/false);
4683 return CED;
4684}
4685
4686static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4687 bool WithInit) {
4688 OMPCapturedExprDecl *CD;
4689 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4690 CD = cast<OMPCapturedExprDecl>(Val: VD);
4691 else
4692 CD = buildCaptureDecl(S, Id: D->getIdentifier(), CaptureExpr, WithInit,
4693 CurContext: S.CurContext,
4694 /*AsExpression=*/false);
4695 return buildDeclRefExpr(S, D: CD, Ty: CD->getType().getNonReferenceType(),
4696 Loc: CaptureExpr->getExprLoc());
4697}
4698
4699static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4700 StringRef Name) {
4701 CaptureExpr = S.DefaultLvalueConversion(E: CaptureExpr).get();
4702 if (!Ref) {
4703 OMPCapturedExprDecl *CD = buildCaptureDecl(
4704 S, Id: &S.getASTContext().Idents.get(Name), CaptureExpr,
4705 /*WithInit=*/true, CurContext: S.CurContext, /*AsExpression=*/true);
4706 Ref = buildDeclRefExpr(S, D: CD, Ty: CD->getType().getNonReferenceType(),
4707 Loc: CaptureExpr->getExprLoc());
4708 }
4709 ExprResult Res = Ref;
4710 if (!S.getLangOpts().CPlusPlus &&
4711 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4712 Ref->getType()->isPointerType()) {
4713 Res = S.CreateBuiltinUnaryOp(OpLoc: CaptureExpr->getExprLoc(), Opc: UO_Deref, InputExpr: Ref);
4714 if (!Res.isUsable())
4715 return ExprError();
4716 }
4717 return S.DefaultLvalueConversion(E: Res.get());
4718}
4719
4720namespace {
4721// OpenMP directives parsed in this section are represented as a
4722// CapturedStatement with an associated statement. If a syntax error
4723// is detected during the parsing of the associated statement, the
4724// compiler must abort processing and close the CapturedStatement.
4725//
4726// Combined directives such as 'target parallel' have more than one
4727// nested CapturedStatements. This RAII ensures that we unwind out
4728// of all the nested CapturedStatements when an error is found.
4729class CaptureRegionUnwinderRAII {
4730private:
4731 Sema &S;
4732 bool &ErrorFound;
4733 OpenMPDirectiveKind DKind = OMPD_unknown;
4734
4735public:
4736 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4737 OpenMPDirectiveKind DKind)
4738 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4739 ~CaptureRegionUnwinderRAII() {
4740 if (ErrorFound) {
4741 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4742 while (--ThisCaptureLevel >= 0)
4743 S.ActOnCapturedRegionError();
4744 }
4745 }
4746};
4747} // namespace
4748
4749void SemaOpenMP::tryCaptureOpenMPLambdas(ValueDecl *V) {
4750 // Capture variables captured by reference in lambdas for target-based
4751 // directives.
4752 if (!SemaRef.CurContext->isDependentContext() &&
4753 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4754 isOpenMPTargetDataManagementDirective(
4755 DSAStack->getCurrentDirective()))) {
4756 QualType Type = V->getType();
4757 if (const auto *RD = Type.getCanonicalType()
4758 .getNonReferenceType()
4759 ->getAsCXXRecordDecl()) {
4760 bool SavedForceCaptureByReferenceInTargetExecutable =
4761 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4762 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4763 /*V=*/true);
4764 if (RD->isLambda()) {
4765 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4766 FieldDecl *ThisCapture;
4767 RD->getCaptureFields(Captures, ThisCapture);
4768 for (const LambdaCapture &LC : RD->captures()) {
4769 if (LC.getCaptureKind() == LCK_ByRef) {
4770 VarDecl *VD = cast<VarDecl>(Val: LC.getCapturedVar());
4771 DeclContext *VDC = VD->getDeclContext();
4772 if (!VDC->Encloses(DC: SemaRef.CurContext))
4773 continue;
4774 SemaRef.MarkVariableReferenced(Loc: LC.getLocation(), Var: VD);
4775 } else if (LC.getCaptureKind() == LCK_This) {
4776 QualType ThisTy = SemaRef.getCurrentThisType();
4777 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4778 T1: ThisTy, T2: ThisCapture->getType()))
4779 SemaRef.CheckCXXThisCapture(Loc: LC.getLocation());
4780 }
4781 }
4782 }
4783 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4784 SavedForceCaptureByReferenceInTargetExecutable);
4785 }
4786 }
4787}
4788
4789static bool checkOrderedOrderSpecified(Sema &S,
4790 const ArrayRef<OMPClause *> Clauses) {
4791 const OMPOrderedClause *Ordered = nullptr;
4792 const OMPOrderClause *Order = nullptr;
4793
4794 for (const OMPClause *Clause : Clauses) {
4795 if (Clause->getClauseKind() == OMPC_ordered)
4796 Ordered = cast<OMPOrderedClause>(Val: Clause);
4797 else if (Clause->getClauseKind() == OMPC_order) {
4798 Order = cast<OMPOrderClause>(Val: Clause);
4799 if (Order->getKind() != OMPC_ORDER_concurrent)
4800 Order = nullptr;
4801 }
4802 if (Ordered && Order)
4803 break;
4804 }
4805
4806 if (Ordered && Order) {
4807 S.Diag(Loc: Order->getKindKwLoc(),
4808 DiagID: diag::err_omp_simple_clause_incompatible_with_ordered)
4809 << getOpenMPClauseNameForDiag(C: OMPC_order)
4810 << getOpenMPSimpleClauseTypeName(Kind: OMPC_order, Type: OMPC_ORDER_concurrent)
4811 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4812 S.Diag(Loc: Ordered->getBeginLoc(), DiagID: diag::note_omp_ordered_param)
4813 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4814 return true;
4815 }
4816 return false;
4817}
4818
4819StmtResult SemaOpenMP::ActOnOpenMPRegionEnd(StmtResult S,
4820 ArrayRef<OMPClause *> Clauses) {
4821 handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(),
4822 /*ScopeEntry=*/false);
4823 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4824 return S;
4825
4826 bool ErrorFound = false;
4827 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4828 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4829 if (!S.isUsable()) {
4830 ErrorFound = true;
4831 return StmtError();
4832 }
4833
4834 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4835 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4836 OMPOrderedClause *OC = nullptr;
4837 OMPScheduleClause *SC = nullptr;
4838 SmallVector<const OMPLinearClause *, 4> LCs;
4839 SmallVector<const OMPClauseWithPreInit *, 4> PICs;
4840 // This is required for proper codegen.
4841 for (OMPClause *Clause : Clauses) {
4842 if (!getLangOpts().OpenMPSimd &&
4843 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4844 DSAStack->getCurrentDirective() == OMPD_target) &&
4845 Clause->getClauseKind() == OMPC_in_reduction) {
4846 // Capture taskgroup task_reduction descriptors inside the tasking regions
4847 // with the corresponding in_reduction items.
4848 auto *IRC = cast<OMPInReductionClause>(Val: Clause);
4849 for (Expr *E : IRC->taskgroup_descriptors())
4850 if (E)
4851 SemaRef.MarkDeclarationsReferencedInExpr(E);
4852 }
4853 if (isOpenMPPrivate(Kind: Clause->getClauseKind()) ||
4854 Clause->getClauseKind() == OMPC_copyprivate ||
4855 (getLangOpts().OpenMPUseTLS &&
4856 getASTContext().getTargetInfo().isTLSSupported() &&
4857 Clause->getClauseKind() == OMPC_copyin)) {
4858 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4859 // Mark all variables in private list clauses as used in inner region.
4860 for (Stmt *VarRef : Clause->children()) {
4861 if (auto *E = cast_or_null<Expr>(Val: VarRef)) {
4862 SemaRef.MarkDeclarationsReferencedInExpr(E);
4863 }
4864 }
4865 DSAStack->setForceVarCapturing(/*V=*/false);
4866 } else if (CaptureRegions.size() > 1 ||
4867 CaptureRegions.back() != OMPD_unknown) {
4868 if (auto *C = OMPClauseWithPreInit::get(C: Clause))
4869 PICs.push_back(Elt: C);
4870 if (auto *C = OMPClauseWithPostUpdate::get(C: Clause)) {
4871 if (Expr *E = C->getPostUpdateExpr())
4872 SemaRef.MarkDeclarationsReferencedInExpr(E);
4873 }
4874 }
4875 if (Clause->getClauseKind() == OMPC_schedule)
4876 SC = cast<OMPScheduleClause>(Val: Clause);
4877 else if (Clause->getClauseKind() == OMPC_ordered)
4878 OC = cast<OMPOrderedClause>(Val: Clause);
4879 else if (Clause->getClauseKind() == OMPC_linear)
4880 LCs.push_back(Elt: cast<OMPLinearClause>(Val: Clause));
4881 }
4882 // Capture allocator expressions if used.
4883 for (Expr *E : DSAStack->getInnerAllocators())
4884 SemaRef.MarkDeclarationsReferencedInExpr(E);
4885 // OpenMP, 2.7.1 Loop Construct, Restrictions
4886 // The nonmonotonic modifier cannot be specified if an ordered clause is
4887 // specified.
4888 if (SC &&
4889 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4890 SC->getSecondScheduleModifier() ==
4891 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4892 OC) {
4893 Diag(Loc: SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4894 ? SC->getFirstScheduleModifierLoc()
4895 : SC->getSecondScheduleModifierLoc(),
4896 DiagID: diag::err_omp_simple_clause_incompatible_with_ordered)
4897 << getOpenMPClauseNameForDiag(C: OMPC_schedule)
4898 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule,
4899 Type: OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4900 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4901 ErrorFound = true;
4902 }
4903 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4904 // If an order(concurrent) clause is present, an ordered clause may not appear
4905 // on the same directive.
4906 if (checkOrderedOrderSpecified(S&: SemaRef, Clauses))
4907 ErrorFound = true;
4908 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4909 for (const OMPLinearClause *C : LCs) {
4910 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_linear_ordered)
4911 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4912 }
4913 ErrorFound = true;
4914 }
4915 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4916 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4917 OC->getNumForLoops()) {
4918 unsigned OMPVersion = getLangOpts().OpenMP;
4919 Diag(Loc: OC->getBeginLoc(), DiagID: diag::err_omp_ordered_simd)
4920 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), Ver: OMPVersion);
4921 ErrorFound = true;
4922 }
4923 if (ErrorFound) {
4924 return StmtError();
4925 }
4926 StmtResult SR = S;
4927 unsigned CompletedRegions = 0;
4928 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(C&: CaptureRegions)) {
4929 // Mark all variables in private list clauses as used in inner region.
4930 // Required for proper codegen of combined directives.
4931 // TODO: add processing for other clauses.
4932 if (ThisCaptureRegion != OMPD_unknown) {
4933 for (const clang::OMPClauseWithPreInit *C : PICs) {
4934 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4935 // Find the particular capture region for the clause if the
4936 // directive is a combined one with multiple capture regions.
4937 // If the directive is not a combined one, the capture region
4938 // associated with the clause is OMPD_unknown and is generated
4939 // only once.
4940 if (CaptureRegion == ThisCaptureRegion ||
4941 CaptureRegion == OMPD_unknown) {
4942 if (auto *DS = cast_or_null<DeclStmt>(Val: C->getPreInitStmt())) {
4943 for (Decl *D : DS->decls())
4944 SemaRef.MarkVariableReferenced(Loc: D->getLocation(),
4945 Var: cast<VarDecl>(Val: D));
4946 }
4947 }
4948 }
4949 }
4950 if (ThisCaptureRegion == OMPD_target) {
4951 // Capture allocator traits in the target region. They are used implicitly
4952 // and, thus, are not captured by default.
4953 for (OMPClause *C : Clauses) {
4954 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(Val: C)) {
4955 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4956 ++I) {
4957 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4958 if (Expr *E = D.AllocatorTraits)
4959 SemaRef.MarkDeclarationsReferencedInExpr(E);
4960 }
4961 continue;
4962 }
4963 }
4964 }
4965 if (ThisCaptureRegion == OMPD_parallel) {
4966 // Capture temp arrays for inscan reductions and locals in aligned
4967 // clauses.
4968 for (OMPClause *C : Clauses) {
4969 if (auto *RC = dyn_cast<OMPReductionClause>(Val: C)) {
4970 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4971 continue;
4972 for (Expr *E : RC->copy_array_temps())
4973 if (E)
4974 SemaRef.MarkDeclarationsReferencedInExpr(E);
4975 }
4976 if (auto *AC = dyn_cast<OMPAlignedClause>(Val: C)) {
4977 for (Expr *E : AC->varlist())
4978 SemaRef.MarkDeclarationsReferencedInExpr(E);
4979 }
4980 }
4981 }
4982 if (++CompletedRegions == CaptureRegions.size())
4983 DSAStack->setBodyComplete();
4984 SR = SemaRef.ActOnCapturedRegionEnd(S: SR.get());
4985 }
4986 return SR;
4987}
4988
4989static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4990 OpenMPDirectiveKind CancelRegion,
4991 SourceLocation StartLoc) {
4992 // CancelRegion is only needed for cancel and cancellation_point.
4993 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4994 return false;
4995
4996 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4997 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4998 return false;
4999
5000 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
5001 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_wrong_cancel_region)
5002 << getOpenMPDirectiveName(D: CancelRegion, Ver: OMPVersion);
5003 return true;
5004}
5005
5006static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
5007 OpenMPDirectiveKind CurrentRegion,
5008 const DeclarationNameInfo &CurrentName,
5009 OpenMPDirectiveKind CancelRegion,
5010 OpenMPBindClauseKind BindKind,
5011 SourceLocation StartLoc) {
5012 if (!Stack->getCurScope())
5013 return false;
5014
5015 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
5016 OpenMPDirectiveKind OffendingRegion = ParentRegion;
5017 bool NestingProhibited = false;
5018 bool CloseNesting = true;
5019 bool OrphanSeen = false;
5020 enum {
5021 NoRecommend,
5022 ShouldBeInParallelRegion,
5023 ShouldBeInOrderedRegion,
5024 ShouldBeInTargetRegion,
5025 ShouldBeInTeamsRegion,
5026 ShouldBeInLoopSimdRegion,
5027 } Recommend = NoRecommend;
5028
5029 SmallVector<OpenMPDirectiveKind, 4> LeafOrComposite;
5030 ArrayRef<OpenMPDirectiveKind> ParentLOC =
5031 getLeafOrCompositeConstructs(D: ParentRegion, Output&: LeafOrComposite);
5032 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
5033 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
5034
5035 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
5036 !isOpenMPOrderConcurrentNestableDirective(DKind: CurrentRegion,
5037 LangOpts: SemaRef.LangOpts)) {
5038 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_order)
5039 << getOpenMPDirectiveName(D: CurrentRegion, Ver: OMPVersion);
5040 return true;
5041 }
5042 if (isOpenMPSimdDirective(DKind: ParentRegion) &&
5043 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
5044 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
5045 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5046 CurrentRegion != OMPD_scan))) {
5047 // OpenMP [2.16, Nesting of Regions]
5048 // OpenMP constructs may not be nested inside a simd region.
5049 // OpenMP [2.8.1,simd Construct, Restrictions]
5050 // An ordered construct with the simd clause is the only OpenMP
5051 // construct that can appear in the simd region.
5052 // Allowing a SIMD construct nested in another SIMD construct is an
5053 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5054 // message.
5055 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5056 // The only OpenMP constructs that can be encountered during execution of
5057 // a simd region are the atomic construct, the loop construct, the simd
5058 // construct and the ordered construct with the simd clause.
5059 SemaRef.Diag(Loc: StartLoc, DiagID: (CurrentRegion != OMPD_simd)
5060 ? diag::err_omp_prohibited_region_simd
5061 : diag::warn_omp_nesting_simd)
5062 << (OMPVersion >= 50 ? 1 : 0);
5063 return CurrentRegion != OMPD_simd;
5064 }
5065 if (EnclosingConstruct == OMPD_atomic) {
5066 // OpenMP [2.16, Nesting of Regions]
5067 // OpenMP constructs may not be nested inside an atomic region.
5068 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_atomic);
5069 return true;
5070 }
5071 if (CurrentRegion == OMPD_section) {
5072 // OpenMP [2.7.2, sections Construct, Restrictions]
5073 // Orphaned section directives are prohibited. That is, the section
5074 // directives must appear within the sections construct and must not be
5075 // encountered elsewhere in the sections region.
5076 if (EnclosingConstruct != OMPD_sections) {
5077 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_section_directive)
5078 << (ParentRegion != OMPD_unknown)
5079 << getOpenMPDirectiveName(D: ParentRegion, Ver: OMPVersion);
5080 return true;
5081 }
5082 return false;
5083 }
5084 // Allow some constructs (except teams and cancellation constructs) to be
5085 // orphaned (they could be used in functions, called from OpenMP regions
5086 // with the required preconditions).
5087 if (ParentRegion == OMPD_unknown &&
5088 !isOpenMPNestingTeamsDirective(DKind: CurrentRegion) &&
5089 CurrentRegion != OMPD_cancellation_point &&
5090 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5091 return false;
5092 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5093 // for a detailed explanation
5094 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5095 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5096 (isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5097 EnclosingConstruct == OMPD_loop)) {
5098 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5099 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region)
5100 << true << getOpenMPDirectiveName(D: ParentRegion, Ver: OMPVersion)
5101 << ErrorMsgNumber << getOpenMPDirectiveName(D: CurrentRegion, Ver: OMPVersion);
5102 return true;
5103 }
5104 if (CurrentRegion == OMPD_cancellation_point ||
5105 CurrentRegion == OMPD_cancel) {
5106 // OpenMP [2.16, Nesting of Regions]
5107 // A cancellation point construct for which construct-type-clause is
5108 // taskgroup must be nested inside a task construct. A cancellation
5109 // point construct for which construct-type-clause is not taskgroup must
5110 // be closely nested inside an OpenMP construct that matches the type
5111 // specified in construct-type-clause.
5112 // A cancel construct for which construct-type-clause is taskgroup must be
5113 // nested inside a task construct. A cancel construct for which
5114 // construct-type-clause is not taskgroup must be closely nested inside an
5115 // OpenMP construct that matches the type specified in
5116 // construct-type-clause.
5117 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(D: ParentRegion);
5118 if (CancelRegion == OMPD_taskgroup) {
5119 NestingProhibited =
5120 EnclosingConstruct != OMPD_task &&
5121 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5122 } else if (CancelRegion == OMPD_sections) {
5123 NestingProhibited = EnclosingConstruct != OMPD_section &&
5124 EnclosingConstruct != OMPD_sections;
5125 } else {
5126 NestingProhibited = CancelRegion != Leafs.back();
5127 }
5128 OrphanSeen = ParentRegion == OMPD_unknown;
5129 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5130 // OpenMP 5.1 [2.22, Nesting of Regions]
5131 // A masked region may not be closely nested inside a worksharing, loop,
5132 // atomic, task, or taskloop region.
5133 NestingProhibited = isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5134 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
5135 isOpenMPTaskingDirective(Kind: ParentRegion);
5136 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5137 // OpenMP [2.16, Nesting of Regions]
5138 // A critical region may not be nested (closely or otherwise) inside a
5139 // critical region with the same name. Note that this restriction is not
5140 // sufficient to prevent deadlock.
5141 SourceLocation PreviousCriticalLoc;
5142 bool DeadLock = Stack->hasDirective(
5143 DPred: [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5144 const DeclarationNameInfo &DNI,
5145 SourceLocation Loc) {
5146 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5147 PreviousCriticalLoc = Loc;
5148 return true;
5149 }
5150 return false;
5151 },
5152 FromParent: false /* skip top directive */);
5153 if (DeadLock) {
5154 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_critical_same_name)
5155 << CurrentName.getName();
5156 if (PreviousCriticalLoc.isValid())
5157 SemaRef.Diag(Loc: PreviousCriticalLoc,
5158 DiagID: diag::note_omp_previous_critical_region);
5159 return true;
5160 }
5161 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5162 // OpenMP 5.1 [2.22, Nesting of Regions]
5163 // A scope region may not be closely nested inside a worksharing, loop,
5164 // task, taskloop, critical, ordered, atomic, or masked region.
5165 // OpenMP 5.1 [2.22, Nesting of Regions]
5166 // A barrier region may not be closely nested inside a worksharing, loop,
5167 // task, taskloop, critical, ordered, atomic, or masked region.
5168 NestingProhibited = isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5169 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
5170 isOpenMPTaskingDirective(Kind: ParentRegion) ||
5171 llvm::is_contained(Set: {OMPD_masked, OMPD_master,
5172 OMPD_critical, OMPD_ordered},
5173 Element: EnclosingConstruct);
5174 } else if (isOpenMPWorksharingDirective(DKind: CurrentRegion) &&
5175 !isOpenMPParallelDirective(DKind: CurrentRegion) &&
5176 !isOpenMPTeamsDirective(DKind: CurrentRegion)) {
5177 // OpenMP 5.1 [2.22, Nesting of Regions]
5178 // A loop region that binds to a parallel region or a worksharing region
5179 // may not be closely nested inside a worksharing, loop, task, taskloop,
5180 // critical, ordered, atomic, or masked region.
5181 NestingProhibited = isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5182 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
5183 isOpenMPTaskingDirective(Kind: ParentRegion) ||
5184 llvm::is_contained(Set: {OMPD_masked, OMPD_master,
5185 OMPD_critical, OMPD_ordered},
5186 Element: EnclosingConstruct);
5187 Recommend = ShouldBeInParallelRegion;
5188 } else if (CurrentRegion == OMPD_ordered) {
5189 // OpenMP [2.16, Nesting of Regions]
5190 // An ordered region may not be closely nested inside a critical,
5191 // atomic, or explicit task region.
5192 // An ordered region must be closely nested inside a loop region (or
5193 // parallel loop region) with an ordered clause.
5194 // OpenMP [2.8.1,simd Construct, Restrictions]
5195 // An ordered construct with the simd clause is the only OpenMP construct
5196 // that can appear in the simd region.
5197 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5198 isOpenMPTaskingDirective(Kind: ParentRegion) ||
5199 !(isOpenMPSimdDirective(DKind: ParentRegion) ||
5200 Stack->isParentOrderedRegion());
5201 Recommend = ShouldBeInOrderedRegion;
5202 } else if (isOpenMPNestingTeamsDirective(DKind: CurrentRegion)) {
5203 // OpenMP [2.16, Nesting of Regions]
5204 // If specified, a teams construct must be contained within a target
5205 // construct.
5206 NestingProhibited =
5207 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5208 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5209 EnclosingConstruct != OMPD_target);
5210 OrphanSeen = ParentRegion == OMPD_unknown;
5211 Recommend = ShouldBeInTargetRegion;
5212 } else if (CurrentRegion == OMPD_scan) {
5213 if (OMPVersion >= 50) {
5214 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
5215 // simd, or for simd. This has to take into account combined directives.
5216 // In 5.2 this seems to be implied by the fact that the specified
5217 // separated constructs are do, for, and simd.
5218 NestingProhibited = !llvm::is_contained(
5219 Set: {OMPD_for, OMPD_simd, OMPD_for_simd}, Element: EnclosingConstruct);
5220 } else {
5221 NestingProhibited = true;
5222 }
5223 OrphanSeen = ParentRegion == OMPD_unknown;
5224 Recommend = ShouldBeInLoopSimdRegion;
5225 }
5226 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(DKind: CurrentRegion) &&
5227 !isOpenMPTargetDataManagementDirective(DKind: CurrentRegion) &&
5228 EnclosingConstruct == OMPD_teams) {
5229 // OpenMP [5.1, 2.22, Nesting of Regions]
5230 // distribute, distribute simd, distribute parallel worksharing-loop,
5231 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5232 // including any parallel regions arising from combined constructs,
5233 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5234 // only OpenMP regions that may be strictly nested inside the teams
5235 // region.
5236 //
5237 // As an extension, we permit atomic within teams as well.
5238 NestingProhibited = !isOpenMPParallelDirective(DKind: CurrentRegion) &&
5239 !isOpenMPDistributeDirective(DKind: CurrentRegion) &&
5240 CurrentRegion != OMPD_loop &&
5241 !(SemaRef.getLangOpts().OpenMPExtensions &&
5242 CurrentRegion == OMPD_atomic);
5243 Recommend = ShouldBeInParallelRegion;
5244 }
5245 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5246 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5247 // If the bind clause is present on the loop construct and binding is
5248 // teams then the corresponding loop region must be strictly nested inside
5249 // a teams region.
5250 NestingProhibited =
5251 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5252 Recommend = ShouldBeInTeamsRegion;
5253 }
5254 if (!NestingProhibited && isOpenMPNestingDistributeDirective(DKind: CurrentRegion)) {
5255 // OpenMP 4.5 [2.17 Nesting of Regions]
5256 // The region associated with the distribute construct must be strictly
5257 // nested inside a teams region
5258 NestingProhibited = EnclosingConstruct != OMPD_teams;
5259 Recommend = ShouldBeInTeamsRegion;
5260 }
5261 if (!NestingProhibited &&
5262 (isOpenMPTargetExecutionDirective(DKind: CurrentRegion) ||
5263 isOpenMPTargetDataManagementDirective(DKind: CurrentRegion))) {
5264 // OpenMP 4.5 [2.17 Nesting of Regions]
5265 // If a target, target update, target data, target enter data, or
5266 // target exit data construct is encountered during execution of a
5267 // target region, the behavior is unspecified.
5268 NestingProhibited = Stack->hasDirective(
5269 DPred: [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5270 SourceLocation) {
5271 if (isOpenMPTargetExecutionDirective(DKind: K)) {
5272 OffendingRegion = K;
5273 return true;
5274 }
5275 return false;
5276 },
5277 FromParent: false /* don't skip top directive */);
5278 CloseNesting = false;
5279 }
5280 if (NestingProhibited) {
5281 if (OrphanSeen) {
5282 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_device_directive)
5283 << getOpenMPDirectiveName(D: CurrentRegion, Ver: OMPVersion) << Recommend;
5284 } else {
5285 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region)
5286 << CloseNesting << getOpenMPDirectiveName(D: OffendingRegion, Ver: OMPVersion)
5287 << Recommend << getOpenMPDirectiveName(D: CurrentRegion, Ver: OMPVersion);
5288 }
5289 return true;
5290 }
5291 return false;
5292}
5293
5294struct Kind2Unsigned {
5295 using argument_type = OpenMPDirectiveKind;
5296 unsigned operator()(argument_type DK) { return unsigned(DK); }
5297};
5298static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5299 ArrayRef<OMPClause *> Clauses,
5300 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5301 bool ErrorFound = false;
5302 unsigned NamedModifiersNumber = 0;
5303 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5304 FoundNameModifiers.resize(S: llvm::omp::Directive_enumSize + 1);
5305 SmallVector<SourceLocation, 4> NameModifierLoc;
5306 unsigned OMPVersion = S.getLangOpts().OpenMP;
5307 for (const OMPClause *C : Clauses) {
5308 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(Val: C)) {
5309 // At most one if clause without a directive-name-modifier can appear on
5310 // the directive.
5311 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5312 auto &FNM = FoundNameModifiers[CurNM];
5313 if (FNM) {
5314 S.Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_more_one_clause)
5315 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion)
5316 << getOpenMPClauseNameForDiag(C: OMPC_if) << (CurNM != OMPD_unknown)
5317 << getOpenMPDirectiveName(D: CurNM, Ver: OMPVersion);
5318 ErrorFound = true;
5319 } else if (CurNM != OMPD_unknown) {
5320 NameModifierLoc.push_back(Elt: IC->getNameModifierLoc());
5321 ++NamedModifiersNumber;
5322 }
5323 FNM = IC;
5324 if (CurNM == OMPD_unknown)
5325 continue;
5326 // Check if the specified name modifier is allowed for the current
5327 // directive.
5328 // At most one if clause with the particular directive-name-modifier can
5329 // appear on the directive.
5330 if (!llvm::is_contained(Range&: AllowedNameModifiers, Element: CurNM)) {
5331 S.Diag(Loc: IC->getNameModifierLoc(),
5332 DiagID: diag::err_omp_wrong_if_directive_name_modifier)
5333 << getOpenMPDirectiveName(D: CurNM, Ver: OMPVersion)
5334 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion);
5335 ErrorFound = true;
5336 }
5337 }
5338 }
5339 // If any if clause on the directive includes a directive-name-modifier then
5340 // all if clauses on the directive must include a directive-name-modifier.
5341 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5342 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5343 S.Diag(Loc: FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5344 DiagID: diag::err_omp_no_more_if_clause);
5345 } else {
5346 std::string Values;
5347 std::string Sep(", ");
5348 unsigned AllowedCnt = 0;
5349 unsigned TotalAllowedNum =
5350 AllowedNameModifiers.size() - NamedModifiersNumber;
5351 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5352 ++Cnt) {
5353 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5354 if (!FoundNameModifiers[NM]) {
5355 Values += "'";
5356 Values += getOpenMPDirectiveName(D: NM, Ver: OMPVersion);
5357 Values += "'";
5358 if (AllowedCnt + 2 == TotalAllowedNum)
5359 Values += " or ";
5360 else if (AllowedCnt + 1 != TotalAllowedNum)
5361 Values += Sep;
5362 ++AllowedCnt;
5363 }
5364 }
5365 S.Diag(Loc: FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5366 DiagID: diag::err_omp_unnamed_if_clause)
5367 << (TotalAllowedNum > 1) << Values;
5368 }
5369 for (SourceLocation Loc : NameModifierLoc) {
5370 S.Diag(Loc, DiagID: diag::note_omp_previous_named_if_clause);
5371 }
5372 ErrorFound = true;
5373 }
5374 return ErrorFound;
5375}
5376
5377static std::pair<ValueDecl *, bool>
5378getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
5379 SourceRange &ERange, bool AllowArraySection,
5380 bool AllowAssumedSizeArray, StringRef DiagType) {
5381 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5382 RefExpr->containsUnexpandedParameterPack())
5383 return std::make_pair(x: nullptr, y: true);
5384
5385 // OpenMP [3.1, C/C++]
5386 // A list item is a variable name.
5387 // OpenMP [2.9.3.3, Restrictions, p.1]
5388 // A variable that is part of another variable (as an array or
5389 // structure element) cannot appear in a private clause.
5390 //
5391 // OpenMP [6.0]
5392 // 5.2.5 Array Sections, p. 166, L28-29
5393 // When the length is absent and the size of the dimension is not known,
5394 // the array section is an assumed-size array.
5395 // 2 Glossary, p. 23, L4-6
5396 // assumed-size array
5397 // For C/C++, an array section for which the length is absent and the
5398 // size of the dimensions is not known.
5399 // 5.2.5 Array Sections, p. 168, L11
5400 // An assumed-size array can appear only in clauses for which it is
5401 // explicitly allowed.
5402 // 7.4 List Item Privatization, Restrictions, p. 222, L15
5403 // Assumed-size arrays must not be privatized.
5404 RefExpr = RefExpr->IgnoreParens();
5405 enum {
5406 NoArrayExpr = -1,
5407 ArraySubscript = 0,
5408 OMPArraySection = 1
5409 } IsArrayExpr = NoArrayExpr;
5410 if (AllowArraySection) {
5411 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(Val: RefExpr)) {
5412 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5413 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base))
5414 Base = TempASE->getBase()->IgnoreParenImpCasts();
5415 RefExpr = Base;
5416 IsArrayExpr = ArraySubscript;
5417 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(Val: RefExpr)) {
5418 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5419 if (S.getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5420 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5421 QualType BaseType = ArraySectionExpr::getBaseOriginalType(Base);
5422 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5423 !BaseType->isVariableArrayType())) {
5424 S.Diag(Loc: OASE->getColonLocFirst(),
5425 DiagID: diag::err_omp_section_length_undefined)
5426 << (!BaseType.isNull() && BaseType->isArrayType());
5427 return std::make_pair(x: nullptr, y: false);
5428 }
5429 }
5430 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Val: Base))
5431 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5432 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base))
5433 Base = TempASE->getBase()->IgnoreParenImpCasts();
5434 RefExpr = Base;
5435 IsArrayExpr = OMPArraySection;
5436 }
5437 }
5438 ELoc = RefExpr->getExprLoc();
5439 ERange = RefExpr->getSourceRange();
5440 RefExpr = RefExpr->IgnoreParenImpCasts();
5441 auto *DE = dyn_cast_or_null<DeclRefExpr>(Val: RefExpr);
5442 auto *ME = dyn_cast_or_null<MemberExpr>(Val: RefExpr);
5443 if ((!DE || !isa<VarDecl>(Val: DE->getDecl())) &&
5444 (S.getCurrentThisType().isNull() || !ME ||
5445 !isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()) ||
5446 !isa<FieldDecl>(Val: ME->getMemberDecl()))) {
5447 if (IsArrayExpr != NoArrayExpr) {
5448 S.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
5449 << IsArrayExpr << ERange;
5450 } else if (!DiagType.empty()) {
5451 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5452 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5453 : 0;
5454 S.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_var_name_member_expr_with_type)
5455 << DiagSelect << DiagType << ERange;
5456 } else {
5457 S.Diag(Loc: ELoc,
5458 DiagID: AllowArraySection
5459 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5460 : diag::err_omp_expected_var_name_member_expr)
5461 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5462 }
5463 return std::make_pair(x: nullptr, y: false);
5464 }
5465 return std::make_pair(
5466 x: getCanonicalDecl(D: DE ? DE->getDecl() : ME->getMemberDecl()), y: false);
5467}
5468
5469namespace {
5470/// Checks if the allocator is used in uses_allocators clause to be allowed in
5471/// target regions.
5472class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5473 DSAStackTy *S = nullptr;
5474
5475public:
5476 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5477 return S->isUsesAllocatorsDecl(D: E->getDecl())
5478 .value_or(u: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5479 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5480 }
5481 bool VisitStmt(const Stmt *S) {
5482 for (const Stmt *Child : S->children()) {
5483 if (Child && Visit(S: Child))
5484 return true;
5485 }
5486 return false;
5487 }
5488 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5489};
5490} // namespace
5491
5492static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5493 ArrayRef<OMPClause *> Clauses) {
5494 assert(!S.CurContext->isDependentContext() &&
5495 "Expected non-dependent context.");
5496 auto AllocateRange =
5497 llvm::make_filter_range(Range&: Clauses, Pred: OMPAllocateClause::classof);
5498 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5499 auto PrivateRange = llvm::make_filter_range(Range&: Clauses, Pred: [](const OMPClause *C) {
5500 return isOpenMPPrivate(Kind: C->getClauseKind());
5501 });
5502 for (OMPClause *Cl : PrivateRange) {
5503 MutableArrayRef<Expr *>::iterator I, It, Et;
5504 if (Cl->getClauseKind() == OMPC_private) {
5505 auto *PC = cast<OMPPrivateClause>(Val: Cl);
5506 I = PC->private_copies().begin();
5507 It = PC->varlist_begin();
5508 Et = PC->varlist_end();
5509 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5510 auto *PC = cast<OMPFirstprivateClause>(Val: Cl);
5511 I = PC->private_copies().begin();
5512 It = PC->varlist_begin();
5513 Et = PC->varlist_end();
5514 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5515 auto *PC = cast<OMPLastprivateClause>(Val: Cl);
5516 I = PC->private_copies().begin();
5517 It = PC->varlist_begin();
5518 Et = PC->varlist_end();
5519 } else if (Cl->getClauseKind() == OMPC_linear) {
5520 auto *PC = cast<OMPLinearClause>(Val: Cl);
5521 I = PC->privates().begin();
5522 It = PC->varlist_begin();
5523 Et = PC->varlist_end();
5524 } else if (Cl->getClauseKind() == OMPC_reduction) {
5525 auto *PC = cast<OMPReductionClause>(Val: Cl);
5526 I = PC->privates().begin();
5527 It = PC->varlist_begin();
5528 Et = PC->varlist_end();
5529 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5530 auto *PC = cast<OMPTaskReductionClause>(Val: Cl);
5531 I = PC->privates().begin();
5532 It = PC->varlist_begin();
5533 Et = PC->varlist_end();
5534 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5535 auto *PC = cast<OMPInReductionClause>(Val: Cl);
5536 I = PC->privates().begin();
5537 It = PC->varlist_begin();
5538 Et = PC->varlist_end();
5539 } else {
5540 llvm_unreachable("Expected private clause.");
5541 }
5542 for (Expr *E : llvm::make_range(x: It, y: Et)) {
5543 if (!*I) {
5544 ++I;
5545 continue;
5546 }
5547 SourceLocation ELoc;
5548 SourceRange ERange;
5549 Expr *SimpleRefExpr = E;
5550 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
5551 /*AllowArraySection=*/true);
5552 DeclToCopy.try_emplace(Key: Res.first,
5553 Args: cast<VarDecl>(Val: cast<DeclRefExpr>(Val: *I)->getDecl()));
5554 ++I;
5555 }
5556 }
5557 for (OMPClause *C : AllocateRange) {
5558 auto *AC = cast<OMPAllocateClause>(Val: C);
5559 if (S.getLangOpts().OpenMP >= 50 &&
5560 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5561 isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective()) &&
5562 AC->getAllocator()) {
5563 Expr *Allocator = AC->getAllocator();
5564 // OpenMP, 2.12.5 target Construct
5565 // Memory allocators that do not appear in a uses_allocators clause cannot
5566 // appear as an allocator in an allocate clause or be used in the target
5567 // region unless a requires directive with the dynamic_allocators clause
5568 // is present in the same compilation unit.
5569 AllocatorChecker Checker(Stack);
5570 if (Checker.Visit(S: Allocator))
5571 S.Diag(Loc: Allocator->getExprLoc(),
5572 DiagID: diag::err_omp_allocator_not_in_uses_allocators)
5573 << Allocator->getSourceRange();
5574 }
5575 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5576 getAllocatorKind(S, Stack, Allocator: AC->getAllocator());
5577 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5578 // For task, taskloop or target directives, allocation requests to memory
5579 // allocators with the trait access set to thread result in unspecified
5580 // behavior.
5581 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5582 (isOpenMPTaskingDirective(Kind: Stack->getCurrentDirective()) ||
5583 isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective()))) {
5584 unsigned OMPVersion = S.getLangOpts().OpenMP;
5585 S.Diag(Loc: AC->getAllocator()->getExprLoc(),
5586 DiagID: diag::warn_omp_allocate_thread_on_task_target_directive)
5587 << getOpenMPDirectiveName(D: Stack->getCurrentDirective(), Ver: OMPVersion);
5588 }
5589 for (Expr *E : AC->varlist()) {
5590 SourceLocation ELoc;
5591 SourceRange ERange;
5592 Expr *SimpleRefExpr = E;
5593 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange);
5594 ValueDecl *VD = Res.first;
5595 if (!VD)
5596 continue;
5597 DSAStackTy::DSAVarData Data = Stack->getTopDSA(D: VD, /*FromParent=*/false);
5598 if (!isOpenMPPrivate(Kind: Data.CKind)) {
5599 S.Diag(Loc: E->getExprLoc(),
5600 DiagID: diag::err_omp_expected_private_copy_for_allocate);
5601 continue;
5602 }
5603 VarDecl *PrivateVD = DeclToCopy[VD];
5604 if (checkPreviousOMPAllocateAttribute(S, Stack, RefExpr: E, VD: PrivateVD,
5605 AllocatorKind, Allocator: AC->getAllocator()))
5606 continue;
5607 applyOMPAllocateAttribute(S, VD: PrivateVD, AllocatorKind, Allocator: AC->getAllocator(),
5608 Alignment: AC->getAlignment(), SR: E->getSourceRange());
5609 }
5610 }
5611}
5612
5613namespace {
5614/// Rewrite statements and expressions for Sema \p Actions CurContext.
5615///
5616/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5617/// context. DeclRefExpr used inside the new context are changed to refer to the
5618/// captured variable instead.
5619class CaptureVars : public TreeTransform<CaptureVars> {
5620 using BaseTransform = TreeTransform<CaptureVars>;
5621
5622public:
5623 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5624
5625 bool AlwaysRebuild() { return true; }
5626};
5627} // namespace
5628
5629static VarDecl *precomputeExpr(Sema &Actions,
5630 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5631 StringRef Name) {
5632 Expr *NewE = AssertSuccess(R: CaptureVars(Actions).TransformExpr(E));
5633 VarDecl *NewVar = buildVarDecl(SemaRef&: Actions, Loc: {}, Type: NewE->getType(), Name, Attrs: nullptr,
5634 OrigRef: dyn_cast<DeclRefExpr>(Val: E->IgnoreImplicit()));
5635 auto *NewDeclStmt = cast<DeclStmt>(Val: AssertSuccess(
5636 R: Actions.ActOnDeclStmt(Decl: Actions.ConvertDeclToDeclGroup(Ptr: NewVar), StartLoc: {}, EndLoc: {})));
5637 Actions.AddInitializerToDecl(dcl: NewDeclStmt->getSingleDecl(), init: NewE, DirectInit: false);
5638 BodyStmts.push_back(Elt: NewDeclStmt);
5639 return NewVar;
5640}
5641
5642/// Create a closure that computes the number of iterations of a loop.
5643///
5644/// \param Actions The Sema object.
5645/// \param LogicalTy Type for the logical iteration number.
5646/// \param Rel Comparison operator of the loop condition.
5647/// \param StartExpr Value of the loop counter at the first iteration.
5648/// \param StopExpr Expression the loop counter is compared against in the loop
5649/// condition. \param StepExpr Amount of increment after each iteration.
5650///
5651/// \return Closure (CapturedStmt) of the distance calculation.
5652static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5653 BinaryOperator::Opcode Rel,
5654 Expr *StartExpr, Expr *StopExpr,
5655 Expr *StepExpr) {
5656 ASTContext &Ctx = Actions.getASTContext();
5657 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(T: LogicalTy);
5658
5659 // Captured regions currently don't support return values, we use an
5660 // out-parameter instead. All inputs are implicit captures.
5661 // TODO: Instead of capturing each DeclRefExpr occurring in
5662 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5663 QualType ResultTy = Ctx.getLValueReferenceType(T: LogicalTy);
5664 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5665 {StringRef(), QualType()}};
5666 Actions.ActOnCapturedRegionStart(Loc: {}, CurScope: nullptr, Kind: CR_Default, Params);
5667
5668 Stmt *Body;
5669 {
5670 Sema::CompoundScopeRAII CompoundScope(Actions);
5671 CapturedDecl *CS = cast<CapturedDecl>(Val: Actions.CurContext);
5672
5673 // Get the LValue expression for the result.
5674 ImplicitParamDecl *DistParam = CS->getParam(i: 0);
5675 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5676 D: DistParam, Ty: LogicalTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
5677
5678 SmallVector<Stmt *, 4> BodyStmts;
5679
5680 // Capture all referenced variable references.
5681 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5682 // CapturedStmt, we could compute them before and capture the result, to be
5683 // used jointly with the LoopVar function.
5684 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, E: StartExpr, Name: ".start");
5685 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, E: StopExpr, Name: ".stop");
5686 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, E: StepExpr, Name: ".step");
5687 auto BuildVarRef = [&](VarDecl *VD) {
5688 return buildDeclRefExpr(S&: Actions, D: VD, Ty: VD->getType(), Loc: {});
5689 };
5690
5691 IntegerLiteral *Zero = IntegerLiteral::Create(
5692 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 0), type: LogicalTy, l: {});
5693 IntegerLiteral *One = IntegerLiteral::Create(
5694 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 1), type: LogicalTy, l: {});
5695 Expr *Dist;
5696 if (Rel == BO_NE) {
5697 // When using a != comparison, the increment can be +1 or -1. This can be
5698 // dynamic at runtime, so we need to check for the direction.
5699 Expr *IsNegStep = AssertSuccess(
5700 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_LT, LHSExpr: BuildVarRef(NewStep), RHSExpr: Zero));
5701
5702 // Positive increment.
5703 Expr *ForwardRange = AssertSuccess(R: Actions.BuildBinOp(
5704 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStop), RHSExpr: BuildVarRef(NewStart)));
5705 ForwardRange = AssertSuccess(
5706 R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: ForwardRange));
5707 Expr *ForwardDist = AssertSuccess(R: Actions.BuildBinOp(
5708 S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: ForwardRange, RHSExpr: BuildVarRef(NewStep)));
5709
5710 // Negative increment.
5711 Expr *BackwardRange = AssertSuccess(R: Actions.BuildBinOp(
5712 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5713 BackwardRange = AssertSuccess(
5714 R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: BackwardRange));
5715 Expr *NegIncAmount = AssertSuccess(
5716 R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: BuildVarRef(NewStep)));
5717 Expr *BackwardDist = AssertSuccess(
5718 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: BackwardRange, RHSExpr: NegIncAmount));
5719
5720 // Use the appropriate case.
5721 Dist = AssertSuccess(R: Actions.ActOnConditionalOp(
5722 QuestionLoc: {}, ColonLoc: {}, CondExpr: IsNegStep, LHSExpr: BackwardDist, RHSExpr: ForwardDist));
5723 } else {
5724 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5725 "Expected one of these relational operators");
5726
5727 // We can derive the direction from any other comparison operator. It is
5728 // non well-formed OpenMP if Step increments/decrements in the other
5729 // directions. Whether at least the first iteration passes the loop
5730 // condition.
5731 Expr *HasAnyIteration = AssertSuccess(R: Actions.BuildBinOp(
5732 S: nullptr, OpLoc: {}, Opc: Rel, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5733
5734 // Compute the range between first and last counter value.
5735 Expr *Range;
5736 if (Rel == BO_GE || Rel == BO_GT)
5737 Range = AssertSuccess(R: Actions.BuildBinOp(
5738 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5739 else
5740 Range = AssertSuccess(R: Actions.BuildBinOp(
5741 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStop), RHSExpr: BuildVarRef(NewStart)));
5742
5743 // Ensure unsigned range space.
5744 Range =
5745 AssertSuccess(R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: Range));
5746
5747 if (Rel == BO_LE || Rel == BO_GE) {
5748 // Add one to the range if the relational operator is inclusive.
5749 Range =
5750 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: Range, RHSExpr: One));
5751 }
5752
5753 // Divide by the absolute step amount. If the range is not a multiple of
5754 // the step size, rounding-up the effective upper bound ensures that the
5755 // last iteration is included.
5756 // Note that the rounding-up may cause an overflow in a temporary that
5757 // could be avoided, but would have occurred in a C-style for-loop as
5758 // well.
5759 Expr *Divisor = BuildVarRef(NewStep);
5760 if (Rel == BO_GE || Rel == BO_GT)
5761 Divisor =
5762 AssertSuccess(R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: Divisor));
5763 Expr *DivisorMinusOne =
5764 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: Divisor, RHSExpr: One));
5765 Expr *RangeRoundUp = AssertSuccess(
5766 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: Range, RHSExpr: DivisorMinusOne));
5767 Dist = AssertSuccess(
5768 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: RangeRoundUp, RHSExpr: Divisor));
5769
5770 // If there is not at least one iteration, the range contains garbage. Fix
5771 // to zero in this case.
5772 Dist = AssertSuccess(
5773 R: Actions.ActOnConditionalOp(QuestionLoc: {}, ColonLoc: {}, CondExpr: HasAnyIteration, LHSExpr: Dist, RHSExpr: Zero));
5774 }
5775
5776 // Assign the result to the out-parameter.
5777 Stmt *ResultAssign = AssertSuccess(R: Actions.BuildBinOp(
5778 S: Actions.getCurScope(), OpLoc: {}, Opc: BO_Assign, LHSExpr: DistRef, RHSExpr: Dist));
5779 BodyStmts.push_back(Elt: ResultAssign);
5780
5781 Body = AssertSuccess(R: Actions.ActOnCompoundStmt(L: {}, R: {}, Elts: BodyStmts, isStmtExpr: false));
5782 }
5783
5784 return cast<CapturedStmt>(
5785 Val: AssertSuccess(R: Actions.ActOnCapturedRegionEnd(S: Body)));
5786}
5787
5788/// Create a closure that computes the loop variable from the logical iteration
5789/// number.
5790///
5791/// \param Actions The Sema object.
5792/// \param LoopVarTy Type for the loop variable used for result value.
5793/// \param LogicalTy Type for the logical iteration number.
5794/// \param StartExpr Value of the loop counter at the first iteration.
5795/// \param Step Amount of increment after each iteration.
5796/// \param Deref Whether the loop variable is a dereference of the loop
5797/// counter variable.
5798///
5799/// \return Closure (CapturedStmt) of the loop value calculation.
5800static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5801 QualType LogicalTy,
5802 DeclRefExpr *StartExpr, Expr *Step,
5803 bool Deref) {
5804 ASTContext &Ctx = Actions.getASTContext();
5805
5806 // Pass the result as an out-parameter. Passing as return value would require
5807 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5808 // invoke a copy constructor.
5809 QualType TargetParamTy = Ctx.getLValueReferenceType(T: LoopVarTy);
5810 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5811 {"Logical", LogicalTy},
5812 {StringRef(), QualType()}};
5813 Actions.ActOnCapturedRegionStart(Loc: {}, CurScope: nullptr, Kind: CR_Default, Params);
5814
5815 // Capture the initial iterator which represents the LoopVar value at the
5816 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5817 // it in every iteration, capture it by value before it is modified.
5818 VarDecl *StartVar = cast<VarDecl>(Val: StartExpr->getDecl());
5819 bool Invalid = Actions.tryCaptureVariable(Var: StartVar, Loc: {},
5820 Kind: TryCaptureKind::ExplicitByVal, EllipsisLoc: {});
5821 (void)Invalid;
5822 assert(!Invalid && "Expecting capture-by-value to work.");
5823
5824 Expr *Body;
5825 {
5826 Sema::CompoundScopeRAII CompoundScope(Actions);
5827 auto *CS = cast<CapturedDecl>(Val: Actions.CurContext);
5828
5829 ImplicitParamDecl *TargetParam = CS->getParam(i: 0);
5830 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5831 D: TargetParam, Ty: LoopVarTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
5832 ImplicitParamDecl *IndvarParam = CS->getParam(i: 1);
5833 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5834 D: IndvarParam, Ty: LogicalTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
5835
5836 // Capture the Start expression.
5837 CaptureVars Recap(Actions);
5838 Expr *NewStart = AssertSuccess(R: Recap.TransformExpr(E: StartExpr));
5839 Expr *NewStep = AssertSuccess(R: Recap.TransformExpr(E: Step));
5840
5841 Expr *Skip = AssertSuccess(
5842 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Mul, LHSExpr: NewStep, RHSExpr: LogicalRef));
5843 // TODO: Explicitly cast to the iterator's difference_type instead of
5844 // relying on implicit conversion.
5845 Expr *Advanced =
5846 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: NewStart, RHSExpr: Skip));
5847
5848 if (Deref) {
5849 // For range-based for-loops convert the loop counter value to a concrete
5850 // loop variable value by dereferencing the iterator.
5851 Advanced =
5852 AssertSuccess(R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Deref, Input: Advanced));
5853 }
5854
5855 // Assign the result to the output parameter.
5856 Body = AssertSuccess(R: Actions.BuildBinOp(S: Actions.getCurScope(), OpLoc: {},
5857 Opc: BO_Assign, LHSExpr: TargetRef, RHSExpr: Advanced));
5858 }
5859 return cast<CapturedStmt>(
5860 Val: AssertSuccess(R: Actions.ActOnCapturedRegionEnd(S: Body)));
5861}
5862
5863StmtResult SemaOpenMP::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
5864 ASTContext &Ctx = getASTContext();
5865
5866 // Extract the common elements of ForStmt and CXXForRangeStmt:
5867 // Loop variable, repeat condition, increment
5868 Expr *Cond, *Inc;
5869 VarDecl *LIVDecl, *LUVDecl;
5870 if (auto *For = dyn_cast<ForStmt>(Val: AStmt)) {
5871 Stmt *Init = For->getInit();
5872 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Val: Init)) {
5873 // For statement declares loop variable.
5874 LIVDecl = cast<VarDecl>(Val: LCVarDeclStmt->getSingleDecl());
5875 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Val: Init)) {
5876 // For statement reuses variable.
5877 assert(LCAssign->getOpcode() == BO_Assign &&
5878 "init part must be a loop variable assignment");
5879 auto *CounterRef = cast<DeclRefExpr>(Val: LCAssign->getLHS());
5880 LIVDecl = cast<VarDecl>(Val: CounterRef->getDecl());
5881 } else
5882 llvm_unreachable("Cannot determine loop variable");
5883 LUVDecl = LIVDecl;
5884
5885 Cond = For->getCond();
5886 Inc = For->getInc();
5887 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(Val: AStmt)) {
5888 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5889 LIVDecl = cast<VarDecl>(Val: BeginStmt->getSingleDecl());
5890 LUVDecl = RangeFor->getLoopVariable();
5891
5892 Cond = RangeFor->getCond();
5893 Inc = RangeFor->getInc();
5894 } else
5895 llvm_unreachable("unhandled kind of loop");
5896
5897 QualType CounterTy = LIVDecl->getType();
5898 QualType LVTy = LUVDecl->getType();
5899
5900 // Analyze the loop condition.
5901 Expr *LHS, *RHS;
5902 BinaryOperator::Opcode CondRel;
5903 Cond = Cond->IgnoreImplicit();
5904 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Val: Cond)) {
5905 LHS = CondBinExpr->getLHS();
5906 RHS = CondBinExpr->getRHS();
5907 CondRel = CondBinExpr->getOpcode();
5908 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Val: Cond)) {
5909 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5910 LHS = CondCXXOp->getArg(Arg: 0);
5911 RHS = CondCXXOp->getArg(Arg: 1);
5912 switch (CondCXXOp->getOperator()) {
5913 case OO_ExclaimEqual:
5914 CondRel = BO_NE;
5915 break;
5916 case OO_Less:
5917 CondRel = BO_LT;
5918 break;
5919 case OO_LessEqual:
5920 CondRel = BO_LE;
5921 break;
5922 case OO_Greater:
5923 CondRel = BO_GT;
5924 break;
5925 case OO_GreaterEqual:
5926 CondRel = BO_GE;
5927 break;
5928 default:
5929 llvm_unreachable("unexpected iterator operator");
5930 }
5931 } else
5932 llvm_unreachable("unexpected loop condition");
5933
5934 // Normalize such that the loop counter is on the LHS.
5935 if (!isa<DeclRefExpr>(Val: LHS->IgnoreImplicit()) ||
5936 cast<DeclRefExpr>(Val: LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5937 std::swap(a&: LHS, b&: RHS);
5938 CondRel = BinaryOperator::reverseComparisonOp(Opc: CondRel);
5939 }
5940 auto *CounterRef = cast<DeclRefExpr>(Val: LHS->IgnoreImplicit());
5941
5942 // Decide the bit width for the logical iteration counter. By default use the
5943 // unsigned ptrdiff_t integer size (for iterators and pointers).
5944 // TODO: For iterators, use iterator::difference_type,
5945 // std::iterator_traits<>::difference_type or decltype(it - end).
5946 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5947 if (CounterTy->isIntegerType()) {
5948 unsigned BitWidth = Ctx.getIntWidth(T: CounterTy);
5949 LogicalTy = Ctx.getIntTypeForBitwidth(DestWidth: BitWidth, Signed: false);
5950 }
5951
5952 // Analyze the loop increment.
5953 Expr *Step;
5954 if (auto *IncUn = dyn_cast<UnaryOperator>(Val: Inc)) {
5955 int Direction;
5956 switch (IncUn->getOpcode()) {
5957 case UO_PreInc:
5958 case UO_PostInc:
5959 Direction = 1;
5960 break;
5961 case UO_PreDec:
5962 case UO_PostDec:
5963 Direction = -1;
5964 break;
5965 default:
5966 llvm_unreachable("unhandled unary increment operator");
5967 }
5968 Step = IntegerLiteral::Create(
5969 C: Ctx,
5970 V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), Direction, /*isSigned=*/true),
5971 type: LogicalTy, l: {});
5972 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Val: Inc)) {
5973 if (IncBin->getOpcode() == BO_AddAssign) {
5974 Step = IncBin->getRHS();
5975 } else if (IncBin->getOpcode() == BO_SubAssign) {
5976 Step = AssertSuccess(
5977 R: SemaRef.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: IncBin->getRHS()));
5978 } else
5979 llvm_unreachable("unhandled binary increment operator");
5980 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Val: Inc)) {
5981 switch (CondCXXOp->getOperator()) {
5982 case OO_PlusPlus:
5983 Step = IntegerLiteral::Create(
5984 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 1), type: LogicalTy, l: {});
5985 break;
5986 case OO_MinusMinus:
5987 Step = IntegerLiteral::Create(
5988 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), -1), type: LogicalTy, l: {});
5989 break;
5990 case OO_PlusEqual:
5991 Step = CondCXXOp->getArg(Arg: 1);
5992 break;
5993 case OO_MinusEqual:
5994 Step = AssertSuccess(
5995 R: SemaRef.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: CondCXXOp->getArg(Arg: 1)));
5996 break;
5997 default:
5998 llvm_unreachable("unhandled overloaded increment operator");
5999 }
6000 } else
6001 llvm_unreachable("unknown increment expression");
6002
6003 CapturedStmt *DistanceFunc =
6004 buildDistanceFunc(Actions&: SemaRef, LogicalTy, Rel: CondRel, StartExpr: LHS, StopExpr: RHS, StepExpr: Step);
6005 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
6006 Actions&: SemaRef, LoopVarTy: LVTy, LogicalTy, StartExpr: CounterRef, Step, Deref: isa<CXXForRangeStmt>(Val: AStmt));
6007 DeclRefExpr *LVRef =
6008 SemaRef.BuildDeclRefExpr(D: LUVDecl, Ty: LUVDecl->getType(), VK: VK_LValue, NameInfo: {},
6009 SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
6010 return OMPCanonicalLoop::create(Ctx: getASTContext(), LoopStmt: AStmt, DistanceFunc,
6011 LoopVarFunc, LoopVarRef: LVRef);
6012}
6013
6014StmtResult SemaOpenMP::ActOnOpenMPLoopnest(Stmt *AStmt) {
6015 // Handle a literal loop.
6016 if (isa<ForStmt>(Val: AStmt) || isa<CXXForRangeStmt>(Val: AStmt))
6017 return ActOnOpenMPCanonicalLoop(AStmt);
6018
6019 // If not a literal loop, it must be the result of a loop transformation.
6020 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(Val: AStmt);
6021 assert(
6022 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
6023 "Loop transformation directive expected");
6024 return LoopTransform;
6025}
6026
6027static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
6028 CXXScopeSpec &MapperIdScopeSpec,
6029 const DeclarationNameInfo &MapperId,
6030 QualType Type,
6031 Expr *UnresolvedMapper);
6032
6033/// Perform DFS through the structure/class data members trying to find
6034/// member(s) with user-defined 'default' mapper and generate implicit map
6035/// clauses for such members with the found 'default' mapper.
6036static void
6037processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
6038 SmallVectorImpl<OMPClause *> &Clauses) {
6039 // Check for the default mapper for data members.
6040 if (S.getLangOpts().OpenMP < 50)
6041 return;
6042 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6043 auto *C = dyn_cast<OMPMapClause>(Val: Clauses[Cnt]);
6044 if (!C)
6045 continue;
6046 SmallVector<Expr *, 4> SubExprs;
6047 auto *MI = C->mapperlist_begin();
6048 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
6049 ++I, ++MI) {
6050 // Expression is mapped using mapper - skip it.
6051 if (*MI)
6052 continue;
6053 Expr *E = *I;
6054 // Expression is dependent - skip it, build the mapper when it gets
6055 // instantiated.
6056 if (E->isTypeDependent() || E->isValueDependent() ||
6057 E->containsUnexpandedParameterPack())
6058 continue;
6059 // Array section - need to check for the mapping of the array section
6060 // element.
6061 QualType CanonType = E->getType().getCanonicalType();
6062 if (CanonType->isSpecificBuiltinType(K: BuiltinType::ArraySection)) {
6063 const auto *OASE = cast<ArraySectionExpr>(Val: E->IgnoreParenImpCasts());
6064 QualType BaseType =
6065 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
6066 QualType ElemType;
6067 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6068 ElemType = ATy->getElementType();
6069 else
6070 ElemType = BaseType->getPointeeType();
6071 CanonType = ElemType;
6072 }
6073
6074 // DFS over data members in structures/classes.
6075 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
6076 1, {CanonType, nullptr});
6077 llvm::DenseMap<const Type *, Expr *> Visited;
6078 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
6079 1, {nullptr, 1});
6080 while (!Types.empty()) {
6081 QualType BaseType;
6082 FieldDecl *CurFD;
6083 std::tie(args&: BaseType, args&: CurFD) = Types.pop_back_val();
6084 while (ParentChain.back().second == 0)
6085 ParentChain.pop_back();
6086 --ParentChain.back().second;
6087 if (BaseType.isNull())
6088 continue;
6089 // Only structs/classes are allowed to have mappers.
6090 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6091 if (!RD)
6092 continue;
6093 auto It = Visited.find(Val: BaseType.getTypePtr());
6094 if (It == Visited.end()) {
6095 // Try to find the associated user-defined mapper.
6096 CXXScopeSpec MapperIdScopeSpec;
6097 DeclarationNameInfo DefaultMapperId;
6098 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
6099 ID: &S.Context.Idents.get(Name: "default")));
6100 DefaultMapperId.setLoc(E->getExprLoc());
6101 ExprResult ER = buildUserDefinedMapperRef(
6102 SemaRef&: S, S: Stack->getCurScope(), MapperIdScopeSpec, MapperId: DefaultMapperId,
6103 Type: BaseType, /*UnresolvedMapper=*/nullptr);
6104 if (ER.isInvalid())
6105 continue;
6106 It = Visited.try_emplace(Key: BaseType.getTypePtr(), Args: ER.get()).first;
6107 }
6108 // Found default mapper.
6109 if (It->second) {
6110 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6111 VK_LValue, OK_Ordinary, E);
6112 OE->setIsUnique(/*V=*/true);
6113 Expr *BaseExpr = OE;
6114 for (const auto &P : ParentChain) {
6115 if (P.first) {
6116 BaseExpr = S.BuildMemberExpr(
6117 Base: BaseExpr, /*IsArrow=*/false, OpLoc: E->getExprLoc(),
6118 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: P.first,
6119 FoundDecl: DeclAccessPair::make(D: P.first, AS: P.first->getAccess()),
6120 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(),
6121 Ty: P.first->getType(), VK: VK_LValue, OK: OK_Ordinary);
6122 BaseExpr = S.DefaultLvalueConversion(E: BaseExpr).get();
6123 }
6124 }
6125 if (CurFD)
6126 BaseExpr = S.BuildMemberExpr(
6127 Base: BaseExpr, /*IsArrow=*/false, OpLoc: E->getExprLoc(),
6128 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: CurFD,
6129 FoundDecl: DeclAccessPair::make(D: CurFD, AS: CurFD->getAccess()),
6130 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(),
6131 Ty: CurFD->getType(), VK: VK_LValue, OK: OK_Ordinary);
6132 SubExprs.push_back(Elt: BaseExpr);
6133 continue;
6134 }
6135 // Check for the "default" mapper for data members.
6136 bool FirstIter = true;
6137 for (FieldDecl *FD : RD->fields()) {
6138 if (!FD)
6139 continue;
6140 QualType FieldTy = FD->getType();
6141 if (FieldTy.isNull() ||
6142 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6143 continue;
6144 if (FirstIter) {
6145 FirstIter = false;
6146 ParentChain.emplace_back(Args&: CurFD, Args: 1);
6147 } else {
6148 ++ParentChain.back().second;
6149 }
6150 Types.emplace_back(Args&: FieldTy, Args&: FD);
6151 }
6152 }
6153 }
6154 if (SubExprs.empty())
6155 continue;
6156 CXXScopeSpec MapperIdScopeSpec;
6157 DeclarationNameInfo MapperId;
6158 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
6159 IteratorModifier: nullptr, MapTypeModifiers: C->getMapTypeModifiers(), MapTypeModifiersLoc: C->getMapTypeModifiersLoc(),
6160 MapperIdScopeSpec, MapperId, MapType: C->getMapType(),
6161 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(),
6162 VarList: SubExprs, Locs: OMPVarListLocTy()))
6163 Clauses.push_back(Elt: NewClause);
6164 }
6165}
6166
6167namespace {
6168/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
6169/// call in the associated loop-nest cannot be a 'parallel for'.
6170class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
6171 Sema &SemaRef;
6172
6173public:
6174 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
6175
6176 // Is there a nested OpenMP loop bind(parallel)
6177 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
6178 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6179 if (const auto *C = D->getSingleClause<OMPBindClause>())
6180 if (C->getBindKind() == OMPC_BIND_parallel) {
6181 TeamsLoopCanBeParallelFor = false;
6182 // No need to continue visiting any more
6183 return;
6184 }
6185 }
6186 for (const Stmt *Child : D->children())
6187 if (Child)
6188 Visit(S: Child);
6189 }
6190
6191 void VisitCallExpr(const CallExpr *C) {
6192 // Function calls inhibit parallel loop translation of 'target teams loop'
6193 // unless the assume-no-nested-parallelism flag has been specified.
6194 // OpenMP API runtime library calls do not inhibit parallel loop
6195 // translation, regardless of the assume-no-nested-parallelism.
6196 bool IsOpenMPAPI = false;
6197 auto *FD = dyn_cast_or_null<FunctionDecl>(Val: C->getCalleeDecl());
6198 if (FD) {
6199 std::string Name = FD->getNameInfo().getAsString();
6200 IsOpenMPAPI = Name.find(s: "omp_") == 0;
6201 }
6202 TeamsLoopCanBeParallelFor =
6203 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6204 if (!TeamsLoopCanBeParallelFor)
6205 return;
6206
6207 for (const Stmt *Child : C->children())
6208 if (Child)
6209 Visit(S: Child);
6210 }
6211
6212 void VisitCapturedStmt(const CapturedStmt *S) {
6213 if (!S)
6214 return;
6215 Visit(S: S->getCapturedDecl()->getBody());
6216 }
6217
6218 void VisitStmt(const Stmt *S) {
6219 if (!S)
6220 return;
6221 for (const Stmt *Child : S->children())
6222 if (Child)
6223 Visit(S: Child);
6224 }
6225 explicit TeamsLoopChecker(Sema &SemaRef)
6226 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
6227
6228private:
6229 bool TeamsLoopCanBeParallelFor;
6230};
6231} // namespace
6232
6233static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
6234 TeamsLoopChecker Checker(SemaRef);
6235 Checker.Visit(S: AStmt);
6236 return Checker.teamsLoopCanBeParallelFor();
6237}
6238
6239StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective(
6240 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6241 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6242 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6243 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
6244
6245 StmtResult Res = StmtError();
6246 OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
6247 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6248
6249 if (const OMPBindClause *BC =
6250 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6251 BindKind = BC->getBindKind();
6252
6253 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6254 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6255
6256 // Setting the enclosing teams or parallel construct for the loop
6257 // directive without bind clause.
6258 // [5.0:129:25-28] If the bind clause is not present on the construct and
6259 // the loop construct is closely nested inside a teams or parallel
6260 // construct, the binding region is the corresponding teams or parallel
6261 // region. If none of those conditions hold, the binding region is not
6262 // defined.
6263 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6264 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6265 getLeafConstructsOrSelf(D: ParentDirective);
6266
6267 if (ParentDirective == OMPD_unknown) {
6268 Diag(DSAStack->getDefaultDSALocation(),
6269 DiagID: diag::err_omp_bind_required_on_loop);
6270 } else if (ParentLeafs.back() == OMPD_parallel) {
6271 BindKind = OMPC_BIND_parallel;
6272 } else if (ParentLeafs.back() == OMPD_teams) {
6273 BindKind = OMPC_BIND_teams;
6274 }
6275
6276 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6277
6278 OMPClause *C =
6279 ActOnOpenMPBindClause(Kind: BindKind, KindLoc: SourceLocation(), StartLoc: SourceLocation(),
6280 LParenLoc: SourceLocation(), EndLoc: SourceLocation());
6281 ClausesWithImplicit.push_back(Elt: C);
6282 }
6283
6284 // Diagnose "loop bind(teams)" with "reduction".
6285 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6286 for (OMPClause *C : Clauses) {
6287 if (C->getClauseKind() == OMPC_reduction)
6288 Diag(DSAStack->getDefaultDSALocation(),
6289 DiagID: diag::err_omp_loop_reduction_clause);
6290 }
6291 }
6292
6293 // First check CancelRegion which is then used in checkNestingOfRegions.
6294 if (checkCancelRegion(SemaRef, CurrentRegion: Kind, CancelRegion, StartLoc) ||
6295 checkNestingOfRegions(SemaRef, DSAStack, CurrentRegion: Kind, CurrentName: DirName, CancelRegion,
6296 BindKind, StartLoc)) {
6297 return StmtError();
6298 }
6299
6300 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6301 if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(DKind: Kind) ||
6302 isOpenMPTargetDataManagementDirective(DKind: Kind)))
6303 Diag(Loc: StartLoc, DiagID: diag::warn_hip_omp_target_directives);
6304
6305 VarsWithInheritedDSAType VarsWithInheritedDSA;
6306 bool ErrorFound = false;
6307 ClausesWithImplicit.append(in_start: Clauses.begin(), in_end: Clauses.end());
6308
6309 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6310 isOpenMPCapturingDirective(DKind: Kind)) {
6311 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6312
6313 // Check default data sharing attributes for referenced variables.
6314 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(Val: AStmt));
6315 int ThisCaptureLevel = getOpenMPCaptureLevels(DKind: Kind);
6316 Stmt *S = AStmt;
6317 while (--ThisCaptureLevel >= 0)
6318 S = cast<CapturedStmt>(Val: S)->getCapturedStmt();
6319 DSAChecker.Visit(S);
6320 if (!isOpenMPTargetDataManagementDirective(DKind: Kind) &&
6321 !isOpenMPTaskingDirective(Kind)) {
6322 // Visit subcaptures to generate implicit clauses for captured vars.
6323 auto *CS = cast<CapturedStmt>(Val: AStmt);
6324 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
6325 getOpenMPCaptureRegions(CaptureRegions, DKind: Kind);
6326 // Ignore outer tasking regions for target directives.
6327 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6328 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
6329 DSAChecker.visitSubCaptures(S: CS);
6330 }
6331 if (DSAChecker.isErrorFound())
6332 return StmtError();
6333 // Generate list of implicitly defined firstprivate variables.
6334 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6335 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6336
6337 SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
6338 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6339 // Get the original location of present modifier from Defaultmap clause.
6340 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6341 for (OMPClause *C : Clauses) {
6342 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(Val: C))
6343 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6344 PresentModifierLocs[DMC->getDefaultmapKind()] =
6345 DMC->getDefaultmapModifierLoc();
6346 }
6347
6348 for (OpenMPDefaultmapClauseKind K :
6349 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6350 Begin: OpenMPDefaultmapClauseKind(), End: OMPC_DEFAULTMAP_unknown)) {
6351 std::fill_n(first: std::back_inserter(x&: ImplicitMapModifiersLoc[K]),
6352 n: ImpInfo.MapModifiers[K].size(), value: PresentModifierLocs[K]);
6353 }
6354 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6355 for (OMPClause *C : Clauses) {
6356 if (auto *IRC = dyn_cast<OMPInReductionClause>(Val: C)) {
6357 for (Expr *E : IRC->taskgroup_descriptors())
6358 if (E)
6359 ImpInfo.Firstprivates.insert(X: E);
6360 }
6361 // OpenMP 5.0, 2.10.1 task Construct
6362 // [detach clause]... The event-handle will be considered as if it was
6363 // specified on a firstprivate clause.
6364 if (auto *DC = dyn_cast<OMPDetachClause>(Val: C))
6365 ImpInfo.Firstprivates.insert(X: DC->getEventHandler());
6366 }
6367 if (!ImpInfo.Firstprivates.empty()) {
6368 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6369 VarList: ImpInfo.Firstprivates.getArrayRef(), StartLoc: SourceLocation(),
6370 LParenLoc: SourceLocation(), EndLoc: SourceLocation())) {
6371 ClausesWithImplicit.push_back(Elt: Implicit);
6372 ErrorFound = cast<OMPFirstprivateClause>(Val: Implicit)->varlist_size() !=
6373 ImpInfo.Firstprivates.size();
6374 } else {
6375 ErrorFound = true;
6376 }
6377 }
6378 if (!ImpInfo.Privates.empty()) {
6379 if (OMPClause *Implicit = ActOnOpenMPPrivateClause(
6380 VarList: ImpInfo.Privates.getArrayRef(), StartLoc: SourceLocation(),
6381 LParenLoc: SourceLocation(), EndLoc: SourceLocation())) {
6382 ClausesWithImplicit.push_back(Elt: Implicit);
6383 ErrorFound = cast<OMPPrivateClause>(Val: Implicit)->varlist_size() !=
6384 ImpInfo.Privates.size();
6385 } else {
6386 ErrorFound = true;
6387 }
6388 }
6389 // OpenMP 5.0 [2.19.7]
6390 // If a list item appears in a reduction, lastprivate or linear
6391 // clause on a combined target construct then it is treated as
6392 // if it also appears in a map clause with a map-type of tofrom
6393 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6394 isOpenMPTargetExecutionDirective(DKind: Kind)) {
6395 SmallVector<Expr *, 4> ImplicitExprs;
6396 for (OMPClause *C : Clauses) {
6397 if (auto *RC = dyn_cast<OMPReductionClause>(Val: C))
6398 for (Expr *E : RC->varlist())
6399 if (!isa<DeclRefExpr>(Val: E->IgnoreParenImpCasts()))
6400 ImplicitExprs.emplace_back(Args&: E);
6401 }
6402 if (!ImplicitExprs.empty()) {
6403 ArrayRef<Expr *> Exprs = ImplicitExprs;
6404 CXXScopeSpec MapperIdScopeSpec;
6405 DeclarationNameInfo MapperId;
6406 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6407 IteratorModifier: nullptr, MapTypeModifiers: OMPC_MAP_MODIFIER_unknown, MapTypeModifiersLoc: SourceLocation(),
6408 MapperIdScopeSpec, MapperId, MapType: OMPC_MAP_tofrom,
6409 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(),
6410 VarList: Exprs, Locs: OMPVarListLocTy(), /*NoDiagnose=*/true))
6411 ClausesWithImplicit.emplace_back(Args&: Implicit);
6412 }
6413 }
6414 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6415 int ClauseKindCnt = -1;
6416 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6417 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6418 ++ClauseKindCnt;
6419 if (ImplicitMap.empty())
6420 continue;
6421 CXXScopeSpec MapperIdScopeSpec;
6422 DeclarationNameInfo MapperId;
6423 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6424 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6425 IteratorModifier: nullptr, MapTypeModifiers: ImpInfo.MapModifiers[I], MapTypeModifiersLoc: ImplicitMapModifiersLoc[I],
6426 MapperIdScopeSpec, MapperId, MapType: K, /*IsMapTypeImplicit=*/true,
6427 MapLoc: SourceLocation(), ColonLoc: SourceLocation(), VarList: ImplicitMap,
6428 Locs: OMPVarListLocTy())) {
6429 ClausesWithImplicit.emplace_back(Args&: Implicit);
6430 ErrorFound |= cast<OMPMapClause>(Val: Implicit)->varlist_size() !=
6431 ImplicitMap.size();
6432 } else {
6433 ErrorFound = true;
6434 }
6435 }
6436 }
6437 // Build expressions for implicit maps of data members with 'default'
6438 // mappers.
6439 if (getLangOpts().OpenMP >= 50)
6440 processImplicitMapsWithDefaultMappers(S&: SemaRef, DSAStack,
6441 Clauses&: ClausesWithImplicit);
6442 }
6443
6444 switch (Kind) {
6445 case OMPD_parallel:
6446 Res = ActOnOpenMPParallelDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6447 EndLoc);
6448 break;
6449 case OMPD_simd:
6450 Res = ActOnOpenMPSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6451 VarsWithImplicitDSA&: VarsWithInheritedDSA);
6452 break;
6453 case OMPD_tile:
6454 Res =
6455 ActOnOpenMPTileDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6456 break;
6457 case OMPD_stripe:
6458 Res = ActOnOpenMPStripeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6459 EndLoc);
6460 break;
6461 case OMPD_unroll:
6462 Res = ActOnOpenMPUnrollDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6463 EndLoc);
6464 break;
6465 case OMPD_reverse:
6466 assert(ClausesWithImplicit.empty() &&
6467 "reverse directive does not support any clauses");
6468 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6469 break;
6470 case OMPD_split:
6471 Res =
6472 ActOnOpenMPSplitDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6473 break;
6474 case OMPD_interchange:
6475 Res = ActOnOpenMPInterchangeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6476 EndLoc);
6477 break;
6478 case OMPD_fuse:
6479 Res =
6480 ActOnOpenMPFuseDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6481 break;
6482 case OMPD_for:
6483 Res = ActOnOpenMPForDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6484 VarsWithImplicitDSA&: VarsWithInheritedDSA);
6485 break;
6486 case OMPD_for_simd:
6487 Res = ActOnOpenMPForSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6488 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6489 break;
6490 case OMPD_sections:
6491 Res = ActOnOpenMPSectionsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6492 EndLoc);
6493 break;
6494 case OMPD_section:
6495 assert(ClausesWithImplicit.empty() &&
6496 "No clauses are allowed for 'omp section' directive");
6497 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6498 break;
6499 case OMPD_single:
6500 Res = ActOnOpenMPSingleDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6501 EndLoc);
6502 break;
6503 case OMPD_master:
6504 assert(ClausesWithImplicit.empty() &&
6505 "No clauses are allowed for 'omp master' directive");
6506 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6507 break;
6508 case OMPD_masked:
6509 Res = ActOnOpenMPMaskedDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6510 EndLoc);
6511 break;
6512 case OMPD_critical:
6513 Res = ActOnOpenMPCriticalDirective(DirName, Clauses: ClausesWithImplicit, AStmt,
6514 StartLoc, EndLoc);
6515 break;
6516 case OMPD_parallel_for:
6517 Res = ActOnOpenMPParallelForDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6518 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6519 break;
6520 case OMPD_parallel_for_simd:
6521 Res = ActOnOpenMPParallelForSimdDirective(
6522 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6523 break;
6524 case OMPD_scope:
6525 Res =
6526 ActOnOpenMPScopeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6527 break;
6528 case OMPD_parallel_master:
6529 Res = ActOnOpenMPParallelMasterDirective(Clauses: ClausesWithImplicit, AStmt,
6530 StartLoc, EndLoc);
6531 break;
6532 case OMPD_parallel_masked:
6533 Res = ActOnOpenMPParallelMaskedDirective(Clauses: ClausesWithImplicit, AStmt,
6534 StartLoc, EndLoc);
6535 break;
6536 case OMPD_parallel_sections:
6537 Res = ActOnOpenMPParallelSectionsDirective(Clauses: ClausesWithImplicit, AStmt,
6538 StartLoc, EndLoc);
6539 break;
6540 case OMPD_task:
6541 Res =
6542 ActOnOpenMPTaskDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6543 break;
6544 case OMPD_taskyield:
6545 assert(ClausesWithImplicit.empty() &&
6546 "No clauses are allowed for 'omp taskyield' directive");
6547 assert(AStmt == nullptr &&
6548 "No associated statement allowed for 'omp taskyield' directive");
6549 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6550 break;
6551 case OMPD_error:
6552 assert(AStmt == nullptr &&
6553 "No associated statement allowed for 'omp error' directive");
6554 Res = ActOnOpenMPErrorDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6555 break;
6556 case OMPD_barrier:
6557 assert(ClausesWithImplicit.empty() &&
6558 "No clauses are allowed for 'omp barrier' directive");
6559 assert(AStmt == nullptr &&
6560 "No associated statement allowed for 'omp barrier' directive");
6561 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6562 break;
6563 case OMPD_taskwait:
6564 assert(AStmt == nullptr &&
6565 "No associated statement allowed for 'omp taskwait' directive");
6566 Res = ActOnOpenMPTaskwaitDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6567 break;
6568 case OMPD_taskgroup:
6569 Res = ActOnOpenMPTaskgroupDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6570 EndLoc);
6571 break;
6572 case OMPD_flush:
6573 assert(AStmt == nullptr &&
6574 "No associated statement allowed for 'omp flush' directive");
6575 Res = ActOnOpenMPFlushDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6576 break;
6577 case OMPD_depobj:
6578 assert(AStmt == nullptr &&
6579 "No associated statement allowed for 'omp depobj' directive");
6580 Res = ActOnOpenMPDepobjDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6581 break;
6582 case OMPD_scan:
6583 assert(AStmt == nullptr &&
6584 "No associated statement allowed for 'omp scan' directive");
6585 Res = ActOnOpenMPScanDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6586 break;
6587 case OMPD_ordered:
6588 Res = ActOnOpenMPOrderedDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6589 EndLoc);
6590 break;
6591 case OMPD_atomic:
6592 Res = ActOnOpenMPAtomicDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6593 EndLoc);
6594 break;
6595 case OMPD_teams:
6596 Res =
6597 ActOnOpenMPTeamsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6598 break;
6599 case OMPD_target:
6600 Res = ActOnOpenMPTargetDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6601 EndLoc);
6602 break;
6603 case OMPD_target_parallel:
6604 Res = ActOnOpenMPTargetParallelDirective(Clauses: ClausesWithImplicit, AStmt,
6605 StartLoc, EndLoc);
6606 break;
6607 case OMPD_target_parallel_for:
6608 Res = ActOnOpenMPTargetParallelForDirective(
6609 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6610 break;
6611 case OMPD_cancellation_point:
6612 assert(ClausesWithImplicit.empty() &&
6613 "No clauses are allowed for 'omp cancellation point' directive");
6614 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6615 "cancellation point' directive");
6616 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6617 break;
6618 case OMPD_cancel:
6619 assert(AStmt == nullptr &&
6620 "No associated statement allowed for 'omp cancel' directive");
6621 Res = ActOnOpenMPCancelDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc,
6622 CancelRegion);
6623 break;
6624 case OMPD_target_data:
6625 Res = ActOnOpenMPTargetDataDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6626 EndLoc);
6627 break;
6628 case OMPD_target_enter_data:
6629 Res = ActOnOpenMPTargetEnterDataDirective(Clauses: ClausesWithImplicit, StartLoc,
6630 EndLoc, AStmt);
6631 break;
6632 case OMPD_target_exit_data:
6633 Res = ActOnOpenMPTargetExitDataDirective(Clauses: ClausesWithImplicit, StartLoc,
6634 EndLoc, AStmt);
6635 break;
6636 case OMPD_taskloop:
6637 Res = ActOnOpenMPTaskLoopDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6638 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6639 break;
6640 case OMPD_taskloop_simd:
6641 Res = ActOnOpenMPTaskLoopSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6642 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6643 break;
6644 case OMPD_master_taskloop:
6645 Res = ActOnOpenMPMasterTaskLoopDirective(
6646 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6647 break;
6648 case OMPD_masked_taskloop:
6649 Res = ActOnOpenMPMaskedTaskLoopDirective(
6650 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6651 break;
6652 case OMPD_master_taskloop_simd:
6653 Res = ActOnOpenMPMasterTaskLoopSimdDirective(
6654 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6655 break;
6656 case OMPD_masked_taskloop_simd:
6657 Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
6658 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6659 break;
6660 case OMPD_parallel_master_taskloop:
6661 Res = ActOnOpenMPParallelMasterTaskLoopDirective(
6662 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6663 break;
6664 case OMPD_parallel_masked_taskloop:
6665 Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
6666 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6667 break;
6668 case OMPD_parallel_master_taskloop_simd:
6669 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6670 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6671 break;
6672 case OMPD_parallel_masked_taskloop_simd:
6673 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6674 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6675 break;
6676 case OMPD_distribute:
6677 Res = ActOnOpenMPDistributeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6678 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6679 break;
6680 case OMPD_target_update:
6681 Res = ActOnOpenMPTargetUpdateDirective(Clauses: ClausesWithImplicit, StartLoc,
6682 EndLoc, AStmt);
6683 break;
6684 case OMPD_distribute_parallel_for:
6685 Res = ActOnOpenMPDistributeParallelForDirective(
6686 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6687 break;
6688 case OMPD_distribute_parallel_for_simd:
6689 Res = ActOnOpenMPDistributeParallelForSimdDirective(
6690 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6691 break;
6692 case OMPD_distribute_simd:
6693 Res = ActOnOpenMPDistributeSimdDirective(
6694 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6695 break;
6696 case OMPD_target_parallel_for_simd:
6697 Res = ActOnOpenMPTargetParallelForSimdDirective(
6698 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6699 break;
6700 case OMPD_target_simd:
6701 Res = ActOnOpenMPTargetSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6702 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6703 break;
6704 case OMPD_teams_distribute:
6705 Res = ActOnOpenMPTeamsDistributeDirective(
6706 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6707 break;
6708 case OMPD_teams_distribute_simd:
6709 Res = ActOnOpenMPTeamsDistributeSimdDirective(
6710 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6711 break;
6712 case OMPD_teams_distribute_parallel_for_simd:
6713 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6714 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6715 break;
6716 case OMPD_teams_distribute_parallel_for:
6717 Res = ActOnOpenMPTeamsDistributeParallelForDirective(
6718 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6719 break;
6720 case OMPD_target_teams:
6721 Res = ActOnOpenMPTargetTeamsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6722 EndLoc);
6723 break;
6724 case OMPD_target_teams_distribute:
6725 Res = ActOnOpenMPTargetTeamsDistributeDirective(
6726 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6727 break;
6728 case OMPD_target_teams_distribute_parallel_for:
6729 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6730 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6731 break;
6732 case OMPD_target_teams_distribute_parallel_for_simd:
6733 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6734 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6735 break;
6736 case OMPD_target_teams_distribute_simd:
6737 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
6738 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6739 break;
6740 case OMPD_interop:
6741 assert(AStmt == nullptr &&
6742 "No associated statement allowed for 'omp interop' directive");
6743 Res = ActOnOpenMPInteropDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6744 break;
6745 case OMPD_dispatch:
6746 Res = ActOnOpenMPDispatchDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6747 EndLoc);
6748 break;
6749 case OMPD_loop:
6750 Res = ActOnOpenMPGenericLoopDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6751 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6752 break;
6753 case OMPD_teams_loop:
6754 Res = ActOnOpenMPTeamsGenericLoopDirective(
6755 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6756 break;
6757 case OMPD_target_teams_loop:
6758 Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
6759 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6760 break;
6761 case OMPD_parallel_loop:
6762 Res = ActOnOpenMPParallelGenericLoopDirective(
6763 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6764 break;
6765 case OMPD_target_parallel_loop:
6766 Res = ActOnOpenMPTargetParallelGenericLoopDirective(
6767 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6768 break;
6769 case OMPD_declare_target:
6770 case OMPD_end_declare_target:
6771 case OMPD_threadprivate:
6772 case OMPD_allocate:
6773 case OMPD_declare_reduction:
6774 case OMPD_declare_mapper:
6775 case OMPD_declare_simd:
6776 case OMPD_requires:
6777 case OMPD_declare_variant:
6778 case OMPD_begin_declare_variant:
6779 case OMPD_end_declare_variant:
6780 llvm_unreachable("OpenMP Directive is not allowed");
6781 case OMPD_taskgraph:
6782 Diag(Loc: StartLoc, DiagID: diag::err_omp_unexpected_directive)
6783 << 1 << getOpenMPDirectiveName(D: OMPD_taskgraph);
6784 return StmtError();
6785 case OMPD_unknown:
6786 default:
6787 llvm_unreachable("Unknown OpenMP directive");
6788 }
6789
6790 ErrorFound = Res.isInvalid() || ErrorFound;
6791
6792 // Check variables in the clauses if default(none) or
6793 // default(firstprivate) was specified.
6794 if (DSAStack->getDefaultDSA() == DSA_none ||
6795 DSAStack->getDefaultDSA() == DSA_private ||
6796 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6797 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6798 for (OMPClause *C : Clauses) {
6799 switch (C->getClauseKind()) {
6800 case OMPC_num_threads:
6801 case OMPC_dist_schedule:
6802 // Do not analyze if no parent teams directive.
6803 if (isOpenMPTeamsDirective(DKind: Kind))
6804 break;
6805 continue;
6806 case OMPC_if:
6807 if (isOpenMPTeamsDirective(DKind: Kind) &&
6808 cast<OMPIfClause>(Val: C)->getNameModifier() != OMPD_target)
6809 break;
6810 if (isOpenMPParallelDirective(DKind: Kind) &&
6811 isOpenMPTaskLoopDirective(DKind: Kind) &&
6812 cast<OMPIfClause>(Val: C)->getNameModifier() != OMPD_parallel)
6813 break;
6814 continue;
6815 case OMPC_schedule:
6816 case OMPC_detach:
6817 break;
6818 case OMPC_grainsize:
6819 case OMPC_num_tasks:
6820 case OMPC_final:
6821 case OMPC_priority:
6822 case OMPC_novariants:
6823 case OMPC_nocontext:
6824 // Do not analyze if no parent parallel directive.
6825 if (isOpenMPParallelDirective(DKind: Kind))
6826 break;
6827 continue;
6828 case OMPC_ordered:
6829 case OMPC_device:
6830 case OMPC_num_teams:
6831 case OMPC_thread_limit:
6832 case OMPC_hint:
6833 case OMPC_collapse:
6834 case OMPC_safelen:
6835 case OMPC_simdlen:
6836 case OMPC_sizes:
6837 case OMPC_default:
6838 case OMPC_proc_bind:
6839 case OMPC_private:
6840 case OMPC_firstprivate:
6841 case OMPC_lastprivate:
6842 case OMPC_shared:
6843 case OMPC_reduction:
6844 case OMPC_task_reduction:
6845 case OMPC_in_reduction:
6846 case OMPC_linear:
6847 case OMPC_aligned:
6848 case OMPC_copyin:
6849 case OMPC_copyprivate:
6850 case OMPC_nowait:
6851 case OMPC_untied:
6852 case OMPC_mergeable:
6853 case OMPC_allocate:
6854 case OMPC_read:
6855 case OMPC_write:
6856 case OMPC_update:
6857 case OMPC_capture:
6858 case OMPC_compare:
6859 case OMPC_seq_cst:
6860 case OMPC_acq_rel:
6861 case OMPC_acquire:
6862 case OMPC_release:
6863 case OMPC_relaxed:
6864 case OMPC_depend:
6865 case OMPC_threads:
6866 case OMPC_simd:
6867 case OMPC_map:
6868 case OMPC_nogroup:
6869 case OMPC_defaultmap:
6870 case OMPC_to:
6871 case OMPC_from:
6872 case OMPC_use_device_ptr:
6873 case OMPC_use_device_addr:
6874 case OMPC_is_device_ptr:
6875 case OMPC_has_device_addr:
6876 case OMPC_nontemporal:
6877 case OMPC_order:
6878 case OMPC_destroy:
6879 case OMPC_inclusive:
6880 case OMPC_exclusive:
6881 case OMPC_uses_allocators:
6882 case OMPC_affinity:
6883 case OMPC_bind:
6884 case OMPC_filter:
6885 case OMPC_severity:
6886 case OMPC_message:
6887 continue;
6888 case OMPC_allocator:
6889 case OMPC_flush:
6890 case OMPC_depobj:
6891 case OMPC_threadprivate:
6892 case OMPC_groupprivate:
6893 case OMPC_uniform:
6894 case OMPC_unknown:
6895 case OMPC_unified_address:
6896 case OMPC_unified_shared_memory:
6897 case OMPC_reverse_offload:
6898 case OMPC_dynamic_allocators:
6899 case OMPC_atomic_default_mem_order:
6900 case OMPC_self_maps:
6901 case OMPC_device_type:
6902 case OMPC_match:
6903 case OMPC_when:
6904 case OMPC_at:
6905 default:
6906 llvm_unreachable("Unexpected clause");
6907 }
6908 for (Stmt *CC : C->children()) {
6909 if (CC)
6910 DSAChecker.Visit(S: CC);
6911 }
6912 }
6913 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6914 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6915 }
6916 for (const auto &P : VarsWithInheritedDSA) {
6917 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(Val: P.getFirst()))
6918 continue;
6919 ErrorFound = true;
6920 if (DSAStack->getDefaultDSA() == DSA_none ||
6921 DSAStack->getDefaultDSA() == DSA_private ||
6922 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6923 Diag(Loc: P.second->getExprLoc(), DiagID: diag::err_omp_no_dsa_for_variable)
6924 << P.first << P.second->getSourceRange();
6925 Diag(DSAStack->getDefaultDSALocation(), DiagID: diag::note_omp_default_dsa_none);
6926 } else if (getLangOpts().OpenMP >= 50) {
6927 Diag(Loc: P.second->getExprLoc(),
6928 DiagID: diag::err_omp_defaultmap_no_attr_for_variable)
6929 << P.first << P.second->getSourceRange();
6930 Diag(DSAStack->getDefaultDSALocation(),
6931 DiagID: diag::note_omp_defaultmap_attr_none);
6932 }
6933 }
6934
6935 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6936 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(D: Kind)) {
6937 if (isAllowedClauseForDirective(D, C: OMPC_if, Version: getLangOpts().OpenMP))
6938 AllowedNameModifiers.push_back(Elt: D);
6939 }
6940 if (!AllowedNameModifiers.empty())
6941 ErrorFound = checkIfClauses(S&: SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6942 ErrorFound;
6943
6944 if (ErrorFound)
6945 return StmtError();
6946
6947 if (!SemaRef.CurContext->isDependentContext() &&
6948 isOpenMPTargetExecutionDirective(DKind: Kind) &&
6949 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6950 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6951 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6952 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6953 // Register target to DSA Stack.
6954 DSAStack->addTargetDirLocation(LocStart: StartLoc);
6955 }
6956
6957 return Res;
6958}
6959
6960SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareSimdDirective(
6961 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6962 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6963 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6964 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6965 assert(Aligneds.size() == Alignments.size());
6966 assert(Linears.size() == LinModifiers.size());
6967 assert(Linears.size() == Steps.size());
6968 if (!DG || DG.get().isNull())
6969 return DeclGroupPtrTy();
6970
6971 const int SimdId = 0;
6972 if (!DG.get().isSingleDecl()) {
6973 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_single_decl_in_declare_simd_variant)
6974 << SimdId;
6975 return DG;
6976 }
6977 Decl *ADecl = DG.get().getSingleDecl();
6978 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: ADecl))
6979 ADecl = FTD->getTemplatedDecl();
6980
6981 auto *FD = dyn_cast<FunctionDecl>(Val: ADecl);
6982 if (!FD) {
6983 Diag(Loc: ADecl->getLocation(), DiagID: diag::err_omp_function_expected) << SimdId;
6984 return DeclGroupPtrTy();
6985 }
6986
6987 // OpenMP [2.8.2, declare simd construct, Description]
6988 // The parameter of the simdlen clause must be a constant positive integer
6989 // expression.
6990 ExprResult SL;
6991 if (Simdlen)
6992 SL = VerifyPositiveIntegerConstantInClause(Op: Simdlen, CKind: OMPC_simdlen);
6993 // OpenMP [2.8.2, declare simd construct, Description]
6994 // The special this pointer can be used as if was one of the arguments to the
6995 // function in any of the linear, aligned, or uniform clauses.
6996 // The uniform clause declares one or more arguments to have an invariant
6997 // value for all concurrent invocations of the function in the execution of a
6998 // single SIMD loop.
6999 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
7000 const Expr *UniformedLinearThis = nullptr;
7001 for (const Expr *E : Uniforms) {
7002 E = E->IgnoreParenImpCasts();
7003 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7004 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl()))
7005 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7006 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7007 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
7008 UniformedArgs.try_emplace(Key: PVD->getCanonicalDecl(), Args&: E);
7009 continue;
7010 }
7011 if (isa<CXXThisExpr>(Val: E)) {
7012 UniformedLinearThis = E;
7013 continue;
7014 }
7015 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
7016 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
7017 }
7018 // OpenMP [2.8.2, declare simd construct, Description]
7019 // The aligned clause declares that the object to which each list item points
7020 // is aligned to the number of bytes expressed in the optional parameter of
7021 // the aligned clause.
7022 // The special this pointer can be used as if was one of the arguments to the
7023 // function in any of the linear, aligned, or uniform clauses.
7024 // The type of list items appearing in the aligned clause must be array,
7025 // pointer, reference to array, or reference to pointer.
7026 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
7027 const Expr *AlignedThis = nullptr;
7028 for (const Expr *E : Aligneds) {
7029 E = E->IgnoreParenImpCasts();
7030 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7031 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7032 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7033 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7034 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7035 ->getCanonicalDecl() == CanonPVD) {
7036 // OpenMP [2.8.1, simd construct, Restrictions]
7037 // A list-item cannot appear in more than one aligned clause.
7038 auto [It, Inserted] = AlignedArgs.try_emplace(Key: CanonPVD, Args&: E);
7039 if (!Inserted) {
7040 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_used_in_clause_twice)
7041 << 1 << getOpenMPClauseNameForDiag(C: OMPC_aligned)
7042 << E->getSourceRange();
7043 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7044 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
7045 continue;
7046 }
7047 QualType QTy = PVD->getType()
7048 .getNonReferenceType()
7049 .getUnqualifiedType()
7050 .getCanonicalType();
7051 const Type *Ty = QTy.getTypePtrOrNull();
7052 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
7053 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_aligned_expected_array_or_ptr)
7054 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
7055 Diag(Loc: PVD->getLocation(), DiagID: diag::note_previous_decl) << PVD;
7056 }
7057 continue;
7058 }
7059 }
7060 if (isa<CXXThisExpr>(Val: E)) {
7061 if (AlignedThis) {
7062 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_used_in_clause_twice)
7063 << 2 << getOpenMPClauseNameForDiag(C: OMPC_aligned)
7064 << E->getSourceRange();
7065 Diag(Loc: AlignedThis->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7066 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
7067 }
7068 AlignedThis = E;
7069 continue;
7070 }
7071 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
7072 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
7073 }
7074 // The optional parameter of the aligned clause, alignment, must be a constant
7075 // positive integer expression. If no optional parameter is specified,
7076 // implementation-defined default alignments for SIMD instructions on the
7077 // target platforms are assumed.
7078 SmallVector<const Expr *, 4> NewAligns;
7079 for (Expr *E : Alignments) {
7080 ExprResult Align;
7081 if (E)
7082 Align = VerifyPositiveIntegerConstantInClause(Op: E, CKind: OMPC_aligned);
7083 NewAligns.push_back(Elt: Align.get());
7084 }
7085 // OpenMP [2.8.2, declare simd construct, Description]
7086 // The linear clause declares one or more list items to be private to a SIMD
7087 // lane and to have a linear relationship with respect to the iteration space
7088 // of a loop.
7089 // The special this pointer can be used as if was one of the arguments to the
7090 // function in any of the linear, aligned, or uniform clauses.
7091 // When a linear-step expression is specified in a linear clause it must be
7092 // either a constant integer expression or an integer-typed parameter that is
7093 // specified in a uniform clause on the directive.
7094 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7095 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7096 auto MI = LinModifiers.begin();
7097 for (const Expr *E : Linears) {
7098 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7099 ++MI;
7100 E = E->IgnoreParenImpCasts();
7101 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7102 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7103 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7104 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7105 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7106 ->getCanonicalDecl() == CanonPVD) {
7107 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7108 // A list-item cannot appear in more than one linear clause.
7109 if (auto It = LinearArgs.find(Val: CanonPVD); It != LinearArgs.end()) {
7110 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
7111 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7112 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7113 << E->getSourceRange();
7114 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7115 << getOpenMPClauseNameForDiag(C: OMPC_linear);
7116 continue;
7117 }
7118 // Each argument can appear in at most one uniform or linear clause.
7119 if (auto It = UniformedArgs.find(Val: CanonPVD);
7120 It != UniformedArgs.end()) {
7121 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
7122 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7123 << getOpenMPClauseNameForDiag(C: OMPC_uniform)
7124 << E->getSourceRange();
7125 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7126 << getOpenMPClauseNameForDiag(C: OMPC_uniform);
7127 continue;
7128 }
7129 LinearArgs[CanonPVD] = E;
7130 if (E->isValueDependent() || E->isTypeDependent() ||
7131 E->isInstantiationDependent() ||
7132 E->containsUnexpandedParameterPack())
7133 continue;
7134 (void)CheckOpenMPLinearDecl(D: CanonPVD, ELoc: E->getExprLoc(), LinKind,
7135 Type: PVD->getOriginalType(),
7136 /*IsDeclareSimd=*/true);
7137 continue;
7138 }
7139 }
7140 if (isa<CXXThisExpr>(Val: E)) {
7141 if (UniformedLinearThis) {
7142 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
7143 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7144 << getOpenMPClauseNameForDiag(C: IsUniformedThis ? OMPC_uniform
7145 : OMPC_linear)
7146 << E->getSourceRange();
7147 Diag(Loc: UniformedLinearThis->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7148 << getOpenMPClauseNameForDiag(C: IsUniformedThis ? OMPC_uniform
7149 : OMPC_linear);
7150 continue;
7151 }
7152 UniformedLinearThis = E;
7153 if (E->isValueDependent() || E->isTypeDependent() ||
7154 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
7155 continue;
7156 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, ELoc: E->getExprLoc(), LinKind,
7157 Type: E->getType(), /*IsDeclareSimd=*/true);
7158 continue;
7159 }
7160 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
7161 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
7162 }
7163 Expr *Step = nullptr;
7164 Expr *NewStep = nullptr;
7165 SmallVector<Expr *, 4> NewSteps;
7166 for (Expr *E : Steps) {
7167 // Skip the same step expression, it was checked already.
7168 if (Step == E || !E) {
7169 NewSteps.push_back(Elt: E ? NewStep : nullptr);
7170 continue;
7171 }
7172 Step = E;
7173 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: Step))
7174 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7175 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7176 if (UniformedArgs.count(Val: CanonPVD) == 0) {
7177 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_expected_uniform_param)
7178 << Step->getSourceRange();
7179 } else if (E->isValueDependent() || E->isTypeDependent() ||
7180 E->isInstantiationDependent() ||
7181 E->containsUnexpandedParameterPack() ||
7182 CanonPVD->getType()->hasIntegerRepresentation()) {
7183 NewSteps.push_back(Elt: Step);
7184 } else {
7185 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_expected_int_param)
7186 << Step->getSourceRange();
7187 }
7188 continue;
7189 }
7190 NewStep = Step;
7191 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7192 !Step->isInstantiationDependent() &&
7193 !Step->containsUnexpandedParameterPack()) {
7194 NewStep = PerformOpenMPImplicitIntegerConversion(OpLoc: Step->getExprLoc(), Op: Step)
7195 .get();
7196 if (NewStep)
7197 NewStep = SemaRef
7198 .VerifyIntegerConstantExpression(
7199 E: NewStep, /*FIXME*/ CanFold: AllowFoldKind::Allow)
7200 .get();
7201 }
7202 NewSteps.push_back(Elt: NewStep);
7203 }
7204 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7205 Ctx&: getASTContext(), BranchState: BS, Simdlen: SL.get(), Uniforms: const_cast<Expr **>(Uniforms.data()),
7206 UniformsSize: Uniforms.size(), Aligneds: const_cast<Expr **>(Aligneds.data()), AlignedsSize: Aligneds.size(),
7207 Alignments: const_cast<Expr **>(NewAligns.data()), AlignmentsSize: NewAligns.size(),
7208 Linears: const_cast<Expr **>(Linears.data()), LinearsSize: Linears.size(),
7209 Modifiers: const_cast<unsigned *>(LinModifiers.data()), ModifiersSize: LinModifiers.size(),
7210 Steps: NewSteps.data(), StepsSize: NewSteps.size(), Range: SR);
7211 ADecl->addAttr(A: NewAttr);
7212 return DG;
7213}
7214
7215StmtResult SemaOpenMP::ActOnOpenMPInformationalDirective(
7216 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
7217 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
7218 SourceLocation EndLoc) {
7219 assert(isOpenMPInformationalDirective(Kind) &&
7220 "Unexpected directive category");
7221
7222 StmtResult Res = StmtError();
7223
7224 switch (Kind) {
7225 case OMPD_assume:
7226 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
7227 break;
7228 default:
7229 llvm_unreachable("Unknown OpenMP directive");
7230 }
7231
7232 return Res;
7233}
7234
7235static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7236 QualType NewType) {
7237 assert(NewType->isFunctionProtoType() &&
7238 "Expected function type with prototype.");
7239 assert(FD->getType()->isFunctionNoProtoType() &&
7240 "Expected function with type with no prototype.");
7241 assert(FDWithProto->getType()->isFunctionProtoType() &&
7242 "Expected function with prototype.");
7243 // Synthesize parameters with the same types.
7244 FD->setType(NewType);
7245 SmallVector<ParmVarDecl *, 16> Params;
7246 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7247 auto *Param = ParmVarDecl::Create(C&: S.getASTContext(), DC: FD, StartLoc: SourceLocation(),
7248 IdLoc: SourceLocation(), Id: nullptr, T: P->getType(),
7249 /*TInfo=*/nullptr, S: SC_None, DefArg: nullptr);
7250 Param->setScopeInfo(scopeDepth: 0, parameterIndex: Params.size());
7251 Param->setImplicit();
7252 Params.push_back(Elt: Param);
7253 }
7254
7255 FD->setParams(Params);
7256}
7257
7258void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
7259 if (D->isInvalidDecl())
7260 return;
7261 FunctionDecl *FD = nullptr;
7262 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(Val: D))
7263 FD = UTemplDecl->getTemplatedDecl();
7264 else
7265 FD = cast<FunctionDecl>(Val: D);
7266 assert(FD && "Expected a function declaration!");
7267
7268 // If we are instantiating templates we do *not* apply scoped assumptions but
7269 // only global ones. We apply scoped assumption to the template definition
7270 // though.
7271 if (!SemaRef.inTemplateInstantiation()) {
7272 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7273 FD->addAttr(A: AA);
7274 }
7275 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7276 FD->addAttr(A: AA);
7277}
7278
7279SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7280 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7281
7282void SemaOpenMP::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7283 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7284 SmallVectorImpl<FunctionDecl *> &Bases) {
7285 if (!D.getIdentifier())
7286 return;
7287
7288 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7289
7290 // Template specialization is an extension, check if we do it.
7291 bool IsTemplated = !TemplateParamLists.empty();
7292 if (IsTemplated &&
7293 !DVScope.TI->isExtensionActive(
7294 TP: llvm::omp::TraitProperty::implementation_extension_allow_templates))
7295 return;
7296
7297 const IdentifierInfo *BaseII = D.getIdentifier();
7298 LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(),
7299 Sema::LookupOrdinaryName);
7300 SemaRef.LookupParsedName(R&: Lookup, S, SS: &D.getCXXScopeSpec(),
7301 /*ObjectType=*/QualType());
7302
7303 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7304 QualType FType = TInfo->getType();
7305
7306 bool IsConstexpr =
7307 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7308 bool IsConsteval =
7309 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7310
7311 for (auto *Candidate : Lookup) {
7312 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7313 FunctionDecl *UDecl = nullptr;
7314 if (IsTemplated && isa<FunctionTemplateDecl>(Val: CandidateDecl)) {
7315 auto *FTD = cast<FunctionTemplateDecl>(Val: CandidateDecl);
7316 // FIXME: Should this compare the template parameter lists on all levels?
7317 if (SemaRef.Context.isSameTemplateParameterList(
7318 X: FTD->getTemplateParameters(), Y: TemplateParamLists.back()))
7319 UDecl = FTD->getTemplatedDecl();
7320 } else if (!IsTemplated)
7321 UDecl = dyn_cast<FunctionDecl>(Val: CandidateDecl);
7322 if (!UDecl)
7323 continue;
7324
7325 // Don't specialize constexpr/consteval functions with
7326 // non-constexpr/consteval functions.
7327 if (UDecl->isConstexpr() && !IsConstexpr)
7328 continue;
7329 if (UDecl->isConsteval() && !IsConsteval)
7330 continue;
7331
7332 QualType UDeclTy = UDecl->getType();
7333 if (!UDeclTy->isDependentType()) {
7334 QualType NewType = getASTContext().mergeFunctionTypes(
7335 FType, UDeclTy, /*OfBlockPointer=*/false,
7336 /*Unqualified=*/false, /*AllowCXX=*/true);
7337 if (NewType.isNull())
7338 continue;
7339 }
7340
7341 // Found a base!
7342 Bases.push_back(Elt: UDecl);
7343 }
7344
7345 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7346 TP: llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7347 // If no base was found we create a declaration that we use as base.
7348 if (Bases.empty() && UseImplicitBase) {
7349 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7350 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParameterLists: TemplateParamLists);
7351 BaseD->setImplicit(true);
7352 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(Val: BaseD))
7353 Bases.push_back(Elt: BaseTemplD->getTemplatedDecl());
7354 else
7355 Bases.push_back(Elt: cast<FunctionDecl>(Val: BaseD));
7356 }
7357
7358 std::string MangledName;
7359 MangledName += D.getIdentifier()->getName();
7360 MangledName += getOpenMPVariantManglingSeparatorStr();
7361 MangledName += DVScope.NameSuffix;
7362 IdentifierInfo &VariantII = getASTContext().Idents.get(Name: MangledName);
7363
7364 VariantII.setMangledOpenMPVariantName(true);
7365 D.SetIdentifier(Id: &VariantII, IdLoc: D.getBeginLoc());
7366}
7367
7368void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7369 Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
7370 // Do not mark function as is used to prevent its emission if this is the
7371 // only place where it is used.
7372 EnterExpressionEvaluationContext Unevaluated(
7373 SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);
7374
7375 FunctionDecl *FD = nullptr;
7376 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(Val: D))
7377 FD = UTemplDecl->getTemplatedDecl();
7378 else
7379 FD = cast<FunctionDecl>(Val: D);
7380 auto *VariantFuncRef = DeclRefExpr::Create(
7381 Context: getASTContext(), QualifierLoc: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), D: FD,
7382 /*RefersToEnclosingVariableOrCapture=*/false,
7383 /*NameLoc=*/FD->getLocation(), T: FD->getType(), VK: ExprValueKind::VK_PRValue);
7384
7385 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7386 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7387 Ctx&: getASTContext(), VariantFuncRef, TraitInfos: DVScope.TI,
7388 /*NothingArgs=*/AdjustArgsNothing: nullptr, /*NothingArgsSize=*/AdjustArgsNothingSize: 0,
7389 /*NeedDevicePtrArgs=*/AdjustArgsNeedDevicePtr: nullptr, /*NeedDevicePtrArgsSize=*/AdjustArgsNeedDevicePtrSize: 0,
7390 /*NeedDeviceAddrArgs=*/AdjustArgsNeedDeviceAddr: nullptr, /*NeedDeviceAddrArgsSize=*/AdjustArgsNeedDeviceAddrSize: 0,
7391 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7392 for (FunctionDecl *BaseFD : Bases)
7393 BaseFD->addAttr(A: OMPDeclareVariantA);
7394}
7395
7396ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
7397 SourceLocation LParenLoc,
7398 MultiExprArg ArgExprs,
7399 SourceLocation RParenLoc,
7400 Expr *ExecConfig) {
7401 // The common case is a regular call we do not want to specialize at all. Try
7402 // to make that case fast by bailing early.
7403 CallExpr *CE = dyn_cast<CallExpr>(Val: Call.get());
7404 if (!CE)
7405 return Call;
7406
7407 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7408
7409 // Mark indirect calls inside target regions, to allow for insertion of
7410 // __llvm_omp_indirect_call_lookup calls during codegen.
7411 if (!CalleeFnDecl) {
7412 if (isInOpenMPTargetExecutionDirective()) {
7413 Expr *E = CE->getCallee()->IgnoreParenImpCasts();
7414 DeclRefExpr *DRE = nullptr;
7415 while (E) {
7416 if ((DRE = dyn_cast<DeclRefExpr>(Val: E)))
7417 break;
7418 if (auto *ME = dyn_cast<MemberExpr>(Val: E))
7419 E = ME->getBase()->IgnoreParenImpCasts();
7420 else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: E))
7421 E = ASE->getBase()->IgnoreParenImpCasts();
7422 else
7423 break;
7424 }
7425 VarDecl *VD = DRE ? dyn_cast<VarDecl>(Val: DRE->getDecl()) : nullptr;
7426 if (VD && !VD->hasAttr<OMPTargetIndirectCallAttr>()) {
7427 VD->addAttr(A: OMPTargetIndirectCallAttr::CreateImplicit(Ctx&: getASTContext()));
7428 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
7429 ML->DeclarationMarkedOpenMPIndirectCall(D: VD);
7430 }
7431 }
7432
7433 return Call;
7434 }
7435
7436 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7437 CalleeFnDecl->getIdentifier() &&
7438 CalleeFnDecl->getName().starts_with_insensitive(Prefix: "omp_")) {
7439 // checking for any calls inside an Order region
7440 if (Scope && Scope->isOpenMPOrderClauseScope())
7441 Diag(Loc: LParenLoc, DiagID: diag::err_omp_unexpected_call_to_omp_runtime_api);
7442 }
7443
7444 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7445 return Call;
7446
7447 ASTContext &Context = getASTContext();
7448 std::function<void(StringRef)> DiagUnknownTrait = [this,
7449 CE](StringRef ISATrait) {
7450 // TODO Track the selector locations in a way that is accessible here to
7451 // improve the diagnostic location.
7452 Diag(Loc: CE->getBeginLoc(), DiagID: diag::warn_unknown_declare_variant_isa_trait)
7453 << ISATrait;
7454 };
7455 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7456 SemaRef.getCurFunctionDecl(),
7457 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7458
7459 QualType CalleeFnType = CalleeFnDecl->getType();
7460
7461 SmallVector<Expr *, 4> Exprs;
7462 SmallVector<VariantMatchInfo, 4> VMIs;
7463 while (CalleeFnDecl) {
7464 for (OMPDeclareVariantAttr *A :
7465 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7466 Expr *VariantRef = A->getVariantFuncRef();
7467
7468 VariantMatchInfo VMI;
7469 OMPTraitInfo &TI = A->getTraitInfo();
7470 TI.getAsVariantMatchInfo(ASTCtx&: Context, VMI);
7471 if (!isVariantApplicableInContext(VMI, Ctx: OMPCtx,
7472 /*DeviceSetOnly=*/DeviceOrImplementationSetOnly: false))
7473 continue;
7474
7475 VMIs.push_back(Elt: VMI);
7476 Exprs.push_back(Elt: VariantRef);
7477 }
7478
7479 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7480 }
7481
7482 ExprResult NewCall;
7483 do {
7484 int BestIdx = getBestVariantMatchForContext(VMIs, Ctx: OMPCtx);
7485 if (BestIdx < 0)
7486 return Call;
7487 Expr *BestExpr = cast<DeclRefExpr>(Val: Exprs[BestIdx]);
7488 Decl *BestDecl = cast<DeclRefExpr>(Val: BestExpr)->getDecl();
7489
7490 {
7491 // Try to build a (member) call expression for the current best applicable
7492 // variant expression. We allow this to fail in which case we continue
7493 // with the next best variant expression. The fail case is part of the
7494 // implementation defined behavior in the OpenMP standard when it talks
7495 // about what differences in the function prototypes: "Any differences
7496 // that the specific OpenMP context requires in the prototype of the
7497 // variant from the base function prototype are implementation defined."
7498 // This wording is there to allow the specialized variant to have a
7499 // different type than the base function. This is intended and OK but if
7500 // we cannot create a call the difference is not in the "implementation
7501 // defined range" we allow.
7502 Sema::TentativeAnalysisScope Trap(SemaRef);
7503
7504 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(Val: BestDecl)) {
7505 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(Val: CE);
7506 BestExpr = MemberExpr::CreateImplicit(
7507 C: Context, Base: MemberCall->getImplicitObjectArgument(),
7508 /*IsArrow=*/false, MemberDecl: SpecializedMethod, T: Context.BoundMemberTy,
7509 VK: MemberCall->getValueKind(), OK: MemberCall->getObjectKind());
7510 }
7511 NewCall = SemaRef.BuildCallExpr(S: Scope, Fn: BestExpr, LParenLoc, ArgExprs,
7512 RParenLoc, ExecConfig);
7513 if (NewCall.isUsable()) {
7514 if (CallExpr *NCE = dyn_cast<CallExpr>(Val: NewCall.get())) {
7515 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7516 QualType NewType = getASTContext().mergeFunctionTypes(
7517 CalleeFnType, NewCalleeFnDecl->getType(),
7518 /*OfBlockPointer=*/false,
7519 /*Unqualified=*/false, /*AllowCXX=*/true);
7520 if (!NewType.isNull())
7521 break;
7522 // Don't use the call if the function type was not compatible.
7523 NewCall = nullptr;
7524 }
7525 }
7526 }
7527
7528 VMIs.erase(CI: VMIs.begin() + BestIdx);
7529 Exprs.erase(CI: Exprs.begin() + BestIdx);
7530 } while (!VMIs.empty());
7531
7532 if (!NewCall.isUsable())
7533 return Call;
7534 return PseudoObjectExpr::Create(Context: getASTContext(), syntactic: CE, semantic: {NewCall.get()}, resultIndex: 0);
7535}
7536
7537std::optional<std::pair<FunctionDecl *, Expr *>>
7538SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG,
7539 Expr *VariantRef,
7540 OMPTraitInfo &TI,
7541 unsigned NumAppendArgs,
7542 SourceRange SR) {
7543 ASTContext &Context = getASTContext();
7544 if (!DG || DG.get().isNull())
7545 return std::nullopt;
7546
7547 const int VariantId = 1;
7548 // Must be applied only to single decl.
7549 if (!DG.get().isSingleDecl()) {
7550 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_single_decl_in_declare_simd_variant)
7551 << VariantId << SR;
7552 return std::nullopt;
7553 }
7554 Decl *ADecl = DG.get().getSingleDecl();
7555 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: ADecl))
7556 ADecl = FTD->getTemplatedDecl();
7557
7558 // Decl must be a function.
7559 auto *FD = dyn_cast<FunctionDecl>(Val: ADecl);
7560 if (!FD) {
7561 Diag(Loc: ADecl->getLocation(), DiagID: diag::err_omp_function_expected)
7562 << VariantId << SR;
7563 return std::nullopt;
7564 }
7565
7566 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7567 // The 'target' attribute needs to be separately checked because it does
7568 // not always signify a multiversion function declaration.
7569 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7570 };
7571 // OpenMP is not compatible with multiversion function attributes.
7572 if (HasMultiVersionAttributes(FD)) {
7573 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_incompat_attributes)
7574 << SR;
7575 return std::nullopt;
7576 }
7577
7578 // Allow #pragma omp declare variant only if the function is not used.
7579 if (FD->isUsed(CheckUsedAttr: false))
7580 Diag(Loc: SR.getBegin(), DiagID: diag::warn_omp_declare_variant_after_used)
7581 << FD->getLocation();
7582
7583 // Check if the function was emitted already.
7584 const FunctionDecl *Definition;
7585 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7586 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(D: Definition)))
7587 Diag(Loc: SR.getBegin(), DiagID: diag::warn_omp_declare_variant_after_emitted)
7588 << FD->getLocation();
7589
7590 // The VariantRef must point to function.
7591 if (!VariantRef) {
7592 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_function_expected) << VariantId;
7593 return std::nullopt;
7594 }
7595
7596 auto ShouldDelayChecks = [](Expr *&E, bool) {
7597 return E && (E->isTypeDependent() || E->isValueDependent() ||
7598 E->containsUnexpandedParameterPack() ||
7599 E->isInstantiationDependent());
7600 };
7601 // Do not check templates, wait until instantiation.
7602 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7603 TI.anyScoreOrCondition(Cond: ShouldDelayChecks))
7604 return std::make_pair(x&: FD, y&: VariantRef);
7605
7606 // Deal with non-constant score and user condition expressions.
7607 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7608 bool IsScore) -> bool {
7609 if (!E || E->isIntegerConstantExpr(Ctx: getASTContext()))
7610 return false;
7611
7612 if (IsScore) {
7613 // We warn on non-constant scores and pretend they were not present.
7614 Diag(Loc: E->getExprLoc(), DiagID: diag::warn_omp_declare_variant_score_not_constant)
7615 << E;
7616 E = nullptr;
7617 } else {
7618 // We could replace a non-constant user condition with "false" but we
7619 // will soon need to handle these anyway for the dynamic version of
7620 // OpenMP context selectors.
7621 Diag(Loc: E->getExprLoc(),
7622 DiagID: diag::err_omp_declare_variant_user_condition_not_constant)
7623 << E;
7624 }
7625 return true;
7626 };
7627 if (TI.anyScoreOrCondition(Cond: HandleNonConstantScoresAndConditions))
7628 return std::nullopt;
7629
7630 QualType AdjustedFnType = FD->getType();
7631 if (NumAppendArgs) {
7632 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7633 if (!PTy) {
7634 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_prototype_required)
7635 << SR;
7636 return std::nullopt;
7637 }
7638 // Adjust the function type to account for an extra omp_interop_t for each
7639 // specified in the append_args clause.
7640 const TypeDecl *TD = nullptr;
7641 LookupResult Result(SemaRef, &Context.Idents.get(Name: "omp_interop_t"),
7642 SR.getBegin(), Sema::LookupOrdinaryName);
7643 if (SemaRef.LookupName(R&: Result, S: SemaRef.getCurScope())) {
7644 NamedDecl *ND = Result.getFoundDecl();
7645 TD = dyn_cast_or_null<TypeDecl>(Val: ND);
7646 }
7647 if (!TD) {
7648 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_interop_type_not_found) << SR;
7649 return std::nullopt;
7650 }
7651 QualType InteropType =
7652 Context.getTypeDeclType(Keyword: ElaboratedTypeKeyword::None,
7653 /*Qualifier=*/std::nullopt, Decl: TD);
7654 if (PTy->isVariadic()) {
7655 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_append_args_with_varargs) << SR;
7656 return std::nullopt;
7657 }
7658 llvm::SmallVector<QualType, 8> Params;
7659 Params.append(in_start: PTy->param_type_begin(), in_end: PTy->param_type_end());
7660 Params.insert(I: Params.end(), NumToInsert: NumAppendArgs, Elt: InteropType);
7661 AdjustedFnType = Context.getFunctionType(ResultTy: PTy->getReturnType(), Args: Params,
7662 EPI: PTy->getExtProtoInfo());
7663 }
7664
7665 // Convert VariantRef expression to the type of the original function to
7666 // resolve possible conflicts.
7667 ExprResult VariantRefCast = VariantRef;
7668 if (getLangOpts().CPlusPlus) {
7669 QualType FnPtrType;
7670 auto *Method = dyn_cast<CXXMethodDecl>(Val: FD);
7671 if (Method && !Method->isStatic()) {
7672 FnPtrType = Context.getMemberPointerType(
7673 T: AdjustedFnType, /*Qualifier=*/std::nullopt, Cls: Method->getParent());
7674 ExprResult ER;
7675 {
7676 // Build addr_of unary op to correctly handle type checks for member
7677 // functions.
7678 Sema::TentativeAnalysisScope Trap(SemaRef);
7679 ER = SemaRef.CreateBuiltinUnaryOp(OpLoc: VariantRef->getBeginLoc(), Opc: UO_AddrOf,
7680 InputExpr: VariantRef);
7681 }
7682 if (!ER.isUsable()) {
7683 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7684 << VariantId << VariantRef->getSourceRange();
7685 return std::nullopt;
7686 }
7687 VariantRef = ER.get();
7688 } else {
7689 FnPtrType = Context.getPointerType(T: AdjustedFnType);
7690 }
7691 QualType VarianPtrType = Context.getPointerType(T: VariantRef->getType());
7692 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7693 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7694 From: VariantRef, ToType: FnPtrType.getUnqualifiedType(),
7695 /*SuppressUserConversions=*/false, AllowExplicit: Sema::AllowedExplicit::None,
7696 /*InOverloadResolution=*/false,
7697 /*CStyle=*/false,
7698 /*AllowObjCWritebackConversion=*/false);
7699 if (ICS.isFailure()) {
7700 Diag(Loc: VariantRef->getExprLoc(),
7701 DiagID: diag::err_omp_declare_variant_incompat_types)
7702 << VariantRef->getType()
7703 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7704 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7705 return std::nullopt;
7706 }
7707 VariantRefCast = SemaRef.PerformImplicitConversion(
7708 From: VariantRef, ToType: FnPtrType.getUnqualifiedType(),
7709 Action: AssignmentAction::Converting);
7710 if (!VariantRefCast.isUsable())
7711 return std::nullopt;
7712 }
7713 // Drop previously built artificial addr_of unary op for member functions.
7714 if (Method && !Method->isStatic()) {
7715 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7716 if (auto *UO = dyn_cast<UnaryOperator>(
7717 Val: PossibleAddrOfVariantRef->IgnoreImplicit()))
7718 VariantRefCast = UO->getSubExpr();
7719 }
7720 }
7721
7722 ExprResult ER = SemaRef.CheckPlaceholderExpr(E: VariantRefCast.get());
7723 if (!ER.isUsable() ||
7724 !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7725 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7726 << VariantId << VariantRef->getSourceRange();
7727 return std::nullopt;
7728 }
7729
7730 // The VariantRef must point to function.
7731 auto *DRE = dyn_cast<DeclRefExpr>(Val: ER.get()->IgnoreParenImpCasts());
7732 if (!DRE) {
7733 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7734 << VariantId << VariantRef->getSourceRange();
7735 return std::nullopt;
7736 }
7737 auto *NewFD = dyn_cast_or_null<FunctionDecl>(Val: DRE->getDecl());
7738 if (!NewFD) {
7739 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7740 << VariantId << VariantRef->getSourceRange();
7741 return std::nullopt;
7742 }
7743
7744 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7745 Diag(Loc: VariantRef->getExprLoc(),
7746 DiagID: diag::err_omp_declare_variant_same_base_function)
7747 << VariantRef->getSourceRange();
7748 return std::nullopt;
7749 }
7750
7751 // Check if function types are compatible in C.
7752 if (!getLangOpts().CPlusPlus) {
7753 QualType NewType =
7754 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7755 if (NewType.isNull()) {
7756 Diag(Loc: VariantRef->getExprLoc(),
7757 DiagID: diag::err_omp_declare_variant_incompat_types)
7758 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7759 << VariantRef->getSourceRange();
7760 return std::nullopt;
7761 }
7762 if (NewType->isFunctionProtoType()) {
7763 if (FD->getType()->isFunctionNoProtoType())
7764 setPrototype(S&: SemaRef, FD, FDWithProto: NewFD, NewType);
7765 else if (NewFD->getType()->isFunctionNoProtoType())
7766 setPrototype(S&: SemaRef, FD: NewFD, FDWithProto: FD, NewType);
7767 }
7768 }
7769
7770 // Check if variant function is not marked with declare variant directive.
7771 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7772 Diag(Loc: VariantRef->getExprLoc(),
7773 DiagID: diag::warn_omp_declare_variant_marked_as_declare_variant)
7774 << VariantRef->getSourceRange();
7775 SourceRange SR =
7776 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7777 Diag(Loc: SR.getBegin(), DiagID: diag::note_omp_marked_declare_variant_here) << SR;
7778 return std::nullopt;
7779 }
7780
7781 enum DoesntSupport {
7782 VirtFuncs = 1,
7783 Constructors = 3,
7784 Destructors = 4,
7785 DeletedFuncs = 5,
7786 DefaultedFuncs = 6,
7787 ConstexprFuncs = 7,
7788 ConstevalFuncs = 8,
7789 };
7790 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(Val: FD)) {
7791 if (CXXFD->isVirtual()) {
7792 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7793 << VirtFuncs;
7794 return std::nullopt;
7795 }
7796
7797 if (isa<CXXConstructorDecl>(Val: FD)) {
7798 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7799 << Constructors;
7800 return std::nullopt;
7801 }
7802
7803 if (isa<CXXDestructorDecl>(Val: FD)) {
7804 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7805 << Destructors;
7806 return std::nullopt;
7807 }
7808 }
7809
7810 if (FD->isDeleted()) {
7811 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7812 << DeletedFuncs;
7813 return std::nullopt;
7814 }
7815
7816 if (FD->isDefaulted()) {
7817 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7818 << DefaultedFuncs;
7819 return std::nullopt;
7820 }
7821
7822 if (FD->isConstexpr()) {
7823 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7824 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7825 return std::nullopt;
7826 }
7827
7828 // Check general compatibility.
7829 if (SemaRef.areMultiversionVariantFunctionsCompatible(
7830 OldFD: FD, NewFD, NoProtoDiagID: PartialDiagnostic::NullDiagnostic(),
7831 NoteCausedDiagIDAt: PartialDiagnosticAt(SourceLocation(),
7832 PartialDiagnostic::NullDiagnostic()),
7833 NoSupportDiagIDAt: PartialDiagnosticAt(
7834 VariantRef->getExprLoc(),
7835 SemaRef.PDiag(DiagID: diag::err_omp_declare_variant_doesnt_support)),
7836 DiffDiagIDAt: PartialDiagnosticAt(VariantRef->getExprLoc(),
7837 SemaRef.PDiag(DiagID: diag::err_omp_declare_variant_diff)
7838 << FD->getLocation()),
7839 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7840 /*CLinkageMayDiffer=*/true))
7841 return std::nullopt;
7842 return std::make_pair(x&: FD, y: cast<Expr>(Val: DRE));
7843}
7844
7845void SemaOpenMP::ActOnOpenMPDeclareVariantDirective(
7846 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7847 ArrayRef<Expr *> AdjustArgsNothing,
7848 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7849 ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
7850 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7851 SourceLocation AppendArgsLoc, SourceRange SR) {
7852
7853 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7854 // An adjust_args clause or append_args clause can only be specified if the
7855 // dispatch selector of the construct selector set appears in the match
7856 // clause.
7857
7858 SmallVector<Expr *, 8> AllAdjustArgs;
7859 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNothing);
7860 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNeedDevicePtr);
7861 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNeedDeviceAddr);
7862
7863 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7864 VariantMatchInfo VMI;
7865 TI.getAsVariantMatchInfo(ASTCtx&: getASTContext(), VMI);
7866 if (!llvm::is_contained(
7867 Range&: VMI.ConstructTraits,
7868 Element: llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7869 if (!AllAdjustArgs.empty())
7870 Diag(Loc: AdjustArgsLoc, DiagID: diag::err_omp_clause_requires_dispatch_construct)
7871 << getOpenMPClauseNameForDiag(C: OMPC_adjust_args);
7872 if (!AppendArgs.empty())
7873 Diag(Loc: AppendArgsLoc, DiagID: diag::err_omp_clause_requires_dispatch_construct)
7874 << getOpenMPClauseNameForDiag(C: OMPC_append_args);
7875 return;
7876 }
7877 }
7878
7879 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7880 // Each argument can only appear in a single adjust_args clause for each
7881 // declare variant directive.
7882 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
7883
7884 for (Expr *E : AllAdjustArgs) {
7885 E = E->IgnoreParenImpCasts();
7886 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E)) {
7887 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7888 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7889 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7890 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7891 ->getCanonicalDecl() == CanonPVD) {
7892 // It's a parameter of the function, check duplicates.
7893 if (!AdjustVars.insert(Ptr: CanonPVD).second) {
7894 Diag(Loc: DRE->getLocation(), DiagID: diag::err_omp_adjust_arg_multiple_clauses)
7895 << PVD;
7896 return;
7897 }
7898 continue;
7899 }
7900 }
7901 }
7902 // Anything that is not a function parameter is an error.
7903 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause) << FD << 0;
7904 return;
7905 }
7906
7907 // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
7908 // If the `need_device_addr` adjust-op modifier is present, each list item
7909 // that appears in the clause must refer to an argument in the declaration of
7910 // the function variant that has a reference type
7911 if (getLangOpts().OpenMP >= 60) {
7912 for (Expr *E : AdjustArgsNeedDeviceAddr) {
7913 E = E->IgnoreParenImpCasts();
7914 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E)) {
7915 if (const auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl())) {
7916 if (!VD->getType()->isReferenceType())
7917 Diag(Loc: E->getExprLoc(),
7918 DiagID: diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7919 }
7920 }
7921 }
7922 }
7923
7924 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7925 Ctx&: getASTContext(), VariantFuncRef: VariantRef, TraitInfos: &TI,
7926 AdjustArgsNothing: const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothingSize: AdjustArgsNothing.size(),
7927 AdjustArgsNeedDevicePtr: const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7928 AdjustArgsNeedDevicePtrSize: AdjustArgsNeedDevicePtr.size(),
7929 AdjustArgsNeedDeviceAddr: const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
7930 AdjustArgsNeedDeviceAddrSize: AdjustArgsNeedDeviceAddr.size(),
7931 AppendArgs: const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgsSize: AppendArgs.size(), Range: SR);
7932 FD->addAttr(A: NewAttr);
7933}
7934
7935static CapturedStmt *
7936setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt) {
7937 auto *CS = dyn_cast<CapturedStmt>(Val: AStmt);
7938 assert(CS && "Captured statement expected");
7939 // 1.2.2 OpenMP Language Terminology
7940 // Structured block - An executable statement with a single entry at the
7941 // top and a single exit at the bottom.
7942 // The point of exit cannot be a branch out of the structured block.
7943 // longjmp() and throw() must not violate the entry/exit criteria.
7944 CS->getCapturedDecl()->setNothrow();
7945
7946 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7947 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7948 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
7949 // 1.2.2 OpenMP Language Terminology
7950 // Structured block - An executable statement with a single entry at the
7951 // top and a single exit at the bottom.
7952 // The point of exit cannot be a branch out of the structured block.
7953 // longjmp() and throw() must not violate the entry/exit criteria.
7954 CS->getCapturedDecl()->setNothrow();
7955 }
7956 SemaRef.setFunctionHasBranchProtectedScope();
7957 return CS;
7958}
7959
7960StmtResult
7961SemaOpenMP::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
7962 Stmt *AStmt, SourceLocation StartLoc,
7963 SourceLocation EndLoc) {
7964 if (!AStmt)
7965 return StmtError();
7966
7967 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel, AStmt);
7968
7969 return OMPParallelDirective::Create(
7970 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
7971 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7972}
7973
7974namespace {
7975/// Iteration space of a single for loop.
7976struct LoopIterationSpace final {
7977 /// True if the condition operator is the strict compare operator (<, > or
7978 /// !=).
7979 bool IsStrictCompare = false;
7980 /// Condition of the loop.
7981 Expr *PreCond = nullptr;
7982 /// This expression calculates the number of iterations in the loop.
7983 /// It is always possible to calculate it before starting the loop.
7984 Expr *NumIterations = nullptr;
7985 /// The loop counter variable.
7986 Expr *CounterVar = nullptr;
7987 /// Private loop counter variable.
7988 Expr *PrivateCounterVar = nullptr;
7989 /// This is initializer for the initial value of #CounterVar.
7990 Expr *CounterInit = nullptr;
7991 /// This is step for the #CounterVar used to generate its update:
7992 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7993 Expr *CounterStep = nullptr;
7994 /// Should step be subtracted?
7995 bool Subtract = false;
7996 /// Source range of the loop init.
7997 SourceRange InitSrcRange;
7998 /// Source range of the loop condition.
7999 SourceRange CondSrcRange;
8000 /// Source range of the loop increment.
8001 SourceRange IncSrcRange;
8002 /// Minimum value that can have the loop control variable. Used to support
8003 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
8004 /// since only such variables can be used in non-loop invariant expressions.
8005 Expr *MinValue = nullptr;
8006 /// Maximum value that can have the loop control variable. Used to support
8007 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
8008 /// since only such variables can be used in non-loop invariant expressions.
8009 Expr *MaxValue = nullptr;
8010 /// true, if the lower bound depends on the outer loop control var.
8011 bool IsNonRectangularLB = false;
8012 /// true, if the upper bound depends on the outer loop control var.
8013 bool IsNonRectangularUB = false;
8014 /// Index of the loop this loop depends on and forms non-rectangular loop
8015 /// nest.
8016 unsigned LoopDependentIdx = 0;
8017 /// Final condition for the non-rectangular loop nest support. It is used to
8018 /// check that the number of iterations for this particular counter must be
8019 /// finished.
8020 Expr *FinalCondition = nullptr;
8021};
8022
8023/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
8024/// set are referenced. Used for verifying loop nest structure before
8025/// performing a loop collapse operation.
8026class ForSubExprChecker : public DynamicRecursiveASTVisitor {
8027 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8028 VarDecl *ForbiddenVar = nullptr;
8029 SourceRange ErrLoc;
8030
8031public:
8032 explicit ForSubExprChecker(
8033 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
8034 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
8035 // We want to visit implicit code, i.e. synthetic initialisation statements
8036 // created during range-for lowering.
8037 ShouldVisitImplicitCode = true;
8038 }
8039
8040 bool VisitDeclRefExpr(DeclRefExpr *E) override {
8041 ValueDecl *VD = E->getDecl();
8042 if (!isa<VarDecl, BindingDecl>(Val: VD))
8043 return true;
8044 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
8045 if (V->getType()->isReferenceType()) {
8046 VarDecl *VD = V->getDefinition();
8047 if (VD && VD->hasInit()) {
8048 Expr *I = VD->getInit();
8049 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Val: I);
8050 if (!DRE)
8051 return true;
8052 V = DRE->getDecl()->getPotentiallyDecomposedVarDecl();
8053 }
8054 }
8055 Decl *Canon = V->getCanonicalDecl();
8056 if (CollapsedLoopVarDecls.contains(Ptr: Canon)) {
8057 ForbiddenVar = V;
8058 ErrLoc = E->getSourceRange();
8059 return false;
8060 }
8061
8062 return true;
8063 }
8064
8065 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
8066 SourceRange getErrRange() const { return ErrLoc; }
8067};
8068
8069/// Helper class for checking canonical form of the OpenMP loops and
8070/// extracting iteration space of each loop in the loop nest, that will be used
8071/// for IR generation.
8072class OpenMPIterationSpaceChecker {
8073 /// Reference to Sema.
8074 Sema &SemaRef;
8075 /// Does the loop associated directive support non-rectangular loops?
8076 bool SupportsNonRectangular;
8077 /// Data-sharing stack.
8078 DSAStackTy &Stack;
8079 /// A location for diagnostics (when there is no some better location).
8080 SourceLocation DefaultLoc;
8081 /// A location for diagnostics (when increment is not compatible).
8082 SourceLocation ConditionLoc;
8083 /// The set of variables declared within the (to be collapsed) loop nest.
8084 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8085 /// The set of induction variables from outer collapsed loops.
8086 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars;
8087 /// A source location for referring to loop init later.
8088 SourceRange InitSrcRange;
8089 /// A source location for referring to condition later.
8090 SourceRange ConditionSrcRange;
8091 /// A source location for referring to increment later.
8092 SourceRange IncrementSrcRange;
8093 /// Loop variable.
8094 ValueDecl *LCDecl = nullptr;
8095 /// Reference to loop variable.
8096 Expr *LCRef = nullptr;
8097 /// Lower bound (initializer for the var).
8098 Expr *LB = nullptr;
8099 /// Upper bound.
8100 Expr *UB = nullptr;
8101 /// Loop step (increment).
8102 Expr *Step = nullptr;
8103 /// This flag is true when condition is one of:
8104 /// Var < UB
8105 /// Var <= UB
8106 /// UB > Var
8107 /// UB >= Var
8108 /// This will have no value when the condition is !=
8109 std::optional<bool> TestIsLessOp;
8110 /// This flag is true when condition is strict ( < or > ).
8111 bool TestIsStrictOp = false;
8112 /// This flag is true when step is subtracted on each iteration.
8113 bool SubtractStep = false;
8114 /// The outer loop counter this loop depends on (if any).
8115 const ValueDecl *DepDecl = nullptr;
8116 /// Contains number of loop (starts from 1) on which loop counter init
8117 /// expression of this loop depends on.
8118 std::optional<unsigned> InitDependOnLC;
8119 /// Contains number of loop (starts from 1) on which loop counter condition
8120 /// expression of this loop depends on.
8121 std::optional<unsigned> CondDependOnLC;
8122 /// Checks if the provide statement depends on the loop counter.
8123 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8124 bool IsInitializer);
8125 /// Original condition required for checking of the exit condition for
8126 /// non-rectangular loop.
8127 Expr *Condition = nullptr;
8128
8129public:
8130 OpenMPIterationSpaceChecker(
8131 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
8132 SourceLocation DefaultLoc,
8133 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls,
8134 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars)
8135 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8136 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8137 CollapsedLoopVarDecls(CollapsedLoopDecls),
8138 CollapsedLoopInductionVars(CollapsedLoopInductionVars) {}
8139 /// Check init-expr for canonical loop form and save loop counter
8140 /// variable - #Var and its initialization value - #LB.
8141 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8142 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8143 /// for less/greater and for strict/non-strict comparison.
8144 bool checkAndSetCond(Expr *S);
8145 /// Check incr-expr for canonical loop form and return true if it
8146 /// does not conform, otherwise save loop step (#Step).
8147 bool checkAndSetInc(Expr *S);
8148 /// Return the loop counter variable.
8149 ValueDecl *getLoopDecl() const { return LCDecl; }
8150 /// Return the reference expression to loop counter variable.
8151 Expr *getLoopDeclRefExpr() const { return LCRef; }
8152 /// Source range of the loop init.
8153 SourceRange getInitSrcRange() const { return InitSrcRange; }
8154 /// Source range of the loop condition.
8155 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8156 /// Source range of the loop increment.
8157 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8158 /// True if the step should be subtracted.
8159 bool shouldSubtractStep() const { return SubtractStep; }
8160 /// True, if the compare operator is strict (<, > or !=).
8161 bool isStrictTestOp() const { return TestIsStrictOp; }
8162 /// Build the expression to calculate the number of iterations.
8163 Expr *buildNumIterations(
8164 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8165 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8166 /// Build the precondition expression for the loops.
8167 Expr *
8168 buildPreCond(Scope *S, Expr *Cond,
8169 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8170 /// Build reference expression to the counter be used for codegen.
8171 DeclRefExpr *
8172 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8173 DSAStackTy &DSA) const;
8174 /// Build reference expression to the private counter be used for
8175 /// codegen.
8176 Expr *buildPrivateCounterVar() const;
8177 /// Build initialization of the counter be used for codegen.
8178 Expr *buildCounterInit() const;
8179 /// Build step of the counter be used for codegen.
8180 Expr *buildCounterStep() const;
8181 /// Build loop data with counter value for depend clauses in ordered
8182 /// directives.
8183 Expr *
8184 buildOrderedLoopData(Scope *S, Expr *Counter,
8185 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8186 SourceLocation Loc, Expr *Inc = nullptr,
8187 OverloadedOperatorKind OOK = OO_Amp);
8188 /// Builds the minimum value for the loop counter.
8189 std::pair<Expr *, Expr *> buildMinMaxValues(
8190 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8191 /// Builds final condition for the non-rectangular loops.
8192 Expr *buildFinalCondition(Scope *S) const;
8193 /// Return true if any expression is dependent.
8194 bool dependent() const;
8195 /// Returns true if the initializer forms non-rectangular loop.
8196 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8197 /// Returns true if the condition forms non-rectangular loop.
8198 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8199 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8200 unsigned getLoopDependentIdx() const {
8201 return InitDependOnLC.value_or(u: CondDependOnLC.value_or(u: 0));
8202 }
8203
8204private:
8205 /// Check the right-hand side of an assignment in the increment
8206 /// expression.
8207 bool checkAndSetIncRHS(Expr *RHS);
8208 /// Helper to set loop counter variable and its initializer.
8209 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8210 bool EmitDiags);
8211 /// Helper to set upper bound.
8212 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8213 SourceRange SR, SourceLocation SL);
8214 /// Helper to set loop increment.
8215 bool setStep(Expr *NewStep, bool Subtract);
8216};
8217
8218bool OpenMPIterationSpaceChecker::dependent() const {
8219 if (!LCDecl) {
8220 assert(!LB && !UB && !Step);
8221 return false;
8222 }
8223 return LCDecl->getType()->isDependentType() ||
8224 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8225 (Step && Step->isValueDependent());
8226}
8227
8228bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8229 Expr *NewLCRefExpr,
8230 Expr *NewLB, bool EmitDiags) {
8231 // State consistency checking to ensure correct usage.
8232 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8233 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8234 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8235 return true;
8236 LCDecl = getCanonicalDecl(D: NewLCDecl);
8237 LCRef = NewLCRefExpr;
8238 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(Val: NewLB))
8239 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8240 if ((Ctor->isCopyOrMoveConstructor() ||
8241 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8242 CE->getNumArgs() > 0 && CE->getArg(Arg: 0) != nullptr)
8243 NewLB = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
8244 LB = NewLB;
8245 if (EmitDiags)
8246 InitDependOnLC = doesDependOnLoopCounter(S: LB, /*IsInitializer=*/true);
8247 return false;
8248}
8249
8250bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8251 bool StrictOp, SourceRange SR,
8252 SourceLocation SL) {
8253 // State consistency checking to ensure correct usage.
8254 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8255 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8256 if (!NewUB || NewUB->containsErrors())
8257 return true;
8258 UB = NewUB;
8259 if (LessOp)
8260 TestIsLessOp = LessOp;
8261 TestIsStrictOp = StrictOp;
8262 ConditionSrcRange = SR;
8263 ConditionLoc = SL;
8264 CondDependOnLC = doesDependOnLoopCounter(S: UB, /*IsInitializer=*/false);
8265 return false;
8266}
8267
8268bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8269 // State consistency checking to ensure correct usage.
8270 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8271 if (!NewStep || NewStep->containsErrors())
8272 return true;
8273 if (!NewStep->isValueDependent()) {
8274 // Check that the step is integer expression.
8275 SourceLocation StepLoc = NewStep->getBeginLoc();
8276 ExprResult Val = SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(
8277 OpLoc: StepLoc, Op: getExprAsWritten(E: NewStep));
8278 if (Val.isInvalid())
8279 return true;
8280 NewStep = Val.get();
8281
8282 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8283 // If test-expr is of form var relational-op b and relational-op is < or
8284 // <= then incr-expr must cause var to increase on each iteration of the
8285 // loop. If test-expr is of form var relational-op b and relational-op is
8286 // > or >= then incr-expr must cause var to decrease on each iteration of
8287 // the loop.
8288 // If test-expr is of form b relational-op var and relational-op is < or
8289 // <= then incr-expr must cause var to decrease on each iteration of the
8290 // loop. If test-expr is of form b relational-op var and relational-op is
8291 // > or >= then incr-expr must cause var to increase on each iteration of
8292 // the loop.
8293 std::optional<llvm::APSInt> Result =
8294 NewStep->getIntegerConstantExpr(Ctx: SemaRef.Context);
8295 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8296 bool IsConstNeg =
8297 Result && Result->isSigned() && (Subtract != Result->isNegative());
8298 bool IsConstPos =
8299 Result && Result->isSigned() && (Subtract == Result->isNegative());
8300 bool IsConstZero = Result && !Result->getBoolValue();
8301
8302 // != with increment is treated as <; != with decrement is treated as >
8303 if (!TestIsLessOp)
8304 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8305 if (UB && (IsConstZero ||
8306 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8307 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8308 SemaRef.Diag(Loc: NewStep->getExprLoc(),
8309 DiagID: diag::err_omp_loop_incr_not_compatible)
8310 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8311 SemaRef.Diag(Loc: ConditionLoc,
8312 DiagID: diag::note_omp_loop_cond_requires_compatible_incr)
8313 << *TestIsLessOp << ConditionSrcRange;
8314 return true;
8315 }
8316 if (*TestIsLessOp == Subtract) {
8317 NewStep =
8318 SemaRef.CreateBuiltinUnaryOp(OpLoc: NewStep->getExprLoc(), Opc: UO_Minus, InputExpr: NewStep)
8319 .get();
8320 Subtract = !Subtract;
8321 }
8322 }
8323
8324 Step = NewStep;
8325 SubtractStep = Subtract;
8326 return false;
8327}
8328
8329namespace {
8330/// Checker for the non-rectangular loops. Checks if the initializer or
8331/// condition expression references loop counter variable.
8332class LoopCounterRefChecker final
8333 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8334 Sema &SemaRef;
8335 DSAStackTy &Stack;
8336 const ValueDecl *CurLCDecl = nullptr;
8337 const ValueDecl *DepDecl = nullptr;
8338 const ValueDecl *PrevDepDecl = nullptr;
8339 bool IsInitializer = true;
8340 bool SupportsNonRectangular;
8341 unsigned BaseLoopId = 0;
8342 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8343 if (getCanonicalDecl(D: VD) == getCanonicalDecl(D: CurLCDecl)) {
8344 SemaRef.Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_stmt_depends_on_loop_counter)
8345 << (IsInitializer ? 0 : 1);
8346 return false;
8347 }
8348 const auto &&Data = Stack.isLoopControlVariable(D: VD);
8349 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8350 // The type of the loop iterator on which we depend may not have a random
8351 // access iterator type.
8352 if (Data.first && VD->getType()->isRecordType()) {
8353 SmallString<128> Name;
8354 llvm::raw_svector_ostream OS(Name);
8355 VD->getNameForDiagnostic(OS, Policy: SemaRef.getPrintingPolicy(),
8356 /*Qualified=*/true);
8357 SemaRef.Diag(Loc: E->getExprLoc(),
8358 DiagID: diag::err_omp_wrong_dependency_iterator_type)
8359 << OS.str();
8360 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::note_previous_decl) << VD;
8361 return false;
8362 }
8363 if (Data.first && !SupportsNonRectangular) {
8364 SemaRef.Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_invariant_dependency);
8365 return false;
8366 }
8367 if (Data.first &&
8368 (DepDecl || (PrevDepDecl &&
8369 getCanonicalDecl(D: VD) != getCanonicalDecl(D: PrevDepDecl)))) {
8370 if (!DepDecl && PrevDepDecl)
8371 DepDecl = PrevDepDecl;
8372 SmallString<128> Name;
8373 llvm::raw_svector_ostream OS(Name);
8374 DepDecl->getNameForDiagnostic(OS, Policy: SemaRef.getPrintingPolicy(),
8375 /*Qualified=*/true);
8376 SemaRef.Diag(Loc: E->getExprLoc(),
8377 DiagID: diag::err_omp_invariant_or_linear_dependency)
8378 << OS.str();
8379 return false;
8380 }
8381 if (Data.first) {
8382 DepDecl = VD;
8383 BaseLoopId = Data.first;
8384 }
8385 return Data.first;
8386 }
8387
8388public:
8389 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8390 const ValueDecl *VD = E->getDecl();
8391 if (isa<VarDecl>(Val: VD))
8392 return checkDecl(E, VD);
8393 return false;
8394 }
8395 bool VisitMemberExpr(const MemberExpr *E) {
8396 if (isa<CXXThisExpr>(Val: E->getBase()->IgnoreParens())) {
8397 const ValueDecl *VD = E->getMemberDecl();
8398 if (isa<VarDecl>(Val: VD) || isa<FieldDecl>(Val: VD))
8399 return checkDecl(E, VD);
8400 }
8401 return false;
8402 }
8403 bool VisitStmt(const Stmt *S) {
8404 bool Res = false;
8405 for (const Stmt *Child : S->children())
8406 Res = (Child && Visit(S: Child)) || Res;
8407 return Res;
8408 }
8409 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8410 const ValueDecl *CurLCDecl, bool IsInitializer,
8411 const ValueDecl *PrevDepDecl = nullptr,
8412 bool SupportsNonRectangular = true)
8413 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8414 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8415 SupportsNonRectangular(SupportsNonRectangular) {}
8416 unsigned getBaseLoopId() const {
8417 assert(CurLCDecl && "Expected loop dependency.");
8418 return BaseLoopId;
8419 }
8420 const ValueDecl *getDepDecl() const {
8421 assert(CurLCDecl && "Expected loop dependency.");
8422 return DepDecl;
8423 }
8424};
8425} // namespace
8426
8427std::optional<unsigned>
8428OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8429 bool IsInitializer) {
8430 // Check for the non-rectangular loops.
8431 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8432 DepDecl, SupportsNonRectangular);
8433 if (LoopStmtChecker.Visit(S)) {
8434 DepDecl = LoopStmtChecker.getDepDecl();
8435 return LoopStmtChecker.getBaseLoopId();
8436 }
8437 return std::nullopt;
8438}
8439
8440bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8441 // Check init-expr for canonical loop form and save loop counter
8442 // variable - #Var and its initialization value - #LB.
8443 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8444 // var = lb
8445 // integer-type var = lb
8446 // random-access-iterator-type var = lb
8447 // pointer-type var = lb
8448 //
8449 if (!S) {
8450 if (EmitDiags) {
8451 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_init);
8452 }
8453 return true;
8454 }
8455 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: S))
8456 if (!ExprTemp->cleanupsHaveSideEffects())
8457 S = ExprTemp->getSubExpr();
8458
8459 if (!CollapsedLoopVarDecls.empty()) {
8460 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8461 if (!FSEC.TraverseStmt(S)) {
8462 SourceRange Range = FSEC.getErrRange();
8463 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
8464 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8465 return true;
8466 }
8467 }
8468
8469 // Helper lambda to check if a loop variable is already used in an outer
8470 // loop.
8471 auto CheckLoopVarReuse = [&](ValueDecl *LoopVar, SourceLocation Loc) -> bool {
8472 if (EmitDiags &&
8473 CollapsedLoopInductionVars.count(Ptr: LoopVar->getCanonicalDecl())) {
8474 SemaRef.Diag(Loc, DiagID: diag::err_omp_loop_var_reused_in_collapsed_loop)
8475 << LoopVar;
8476 return true;
8477 }
8478 return false;
8479 };
8480
8481 InitSrcRange = S->getSourceRange();
8482 if (Expr *E = dyn_cast<Expr>(Val: S))
8483 S = E->IgnoreParens();
8484 if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8485 if (BO->getOpcode() == BO_Assign) {
8486 Expr *LHS = BO->getLHS()->IgnoreParens();
8487 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS)) {
8488 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: DRE->getDecl()))
8489 if (auto *ME =
8490 dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit()))) {
8491 ValueDecl *LoopVar = ME->getMemberDecl();
8492 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8493 return true;
8494 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: BO->getRHS(), EmitDiags);
8495 }
8496 ValueDecl *LoopVar = DRE->getDecl();
8497 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8498 return true;
8499 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: DRE, NewLB: BO->getRHS(), EmitDiags);
8500 }
8501 if (auto *ME = dyn_cast<MemberExpr>(Val: LHS)) {
8502 if (ME->isArrow() &&
8503 isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts())) {
8504 ValueDecl *LoopVar = ME->getMemberDecl();
8505 if (CheckLoopVarReuse(LoopVar, LHS->getBeginLoc()))
8506 return true;
8507 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: BO->getRHS(), EmitDiags);
8508 }
8509 }
8510 }
8511 } else if (auto *DS = dyn_cast<DeclStmt>(Val: S)) {
8512 if (DS->isSingleDecl()) {
8513 if (auto *Var = dyn_cast_or_null<VarDecl>(Val: DS->getSingleDecl())) {
8514 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8515 // Accept non-canonical init form here but emit ext. warning.
8516 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8517 SemaRef.Diag(Loc: S->getBeginLoc(),
8518 DiagID: diag::ext_omp_loop_not_canonical_init)
8519 << S->getSourceRange();
8520 if (CheckLoopVarReuse(Var, Var->getLocation()))
8521 return true;
8522 return setLCDeclAndLB(
8523 NewLCDecl: Var,
8524 NewLCRefExpr: buildDeclRefExpr(S&: SemaRef, D: Var,
8525 Ty: Var->getType().getNonReferenceType(),
8526 Loc: DS->getBeginLoc()),
8527 NewLB: Var->getInit(), EmitDiags);
8528 }
8529 }
8530 }
8531 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8532 if (CE->getOperator() == OO_Equal) {
8533 Expr *LHS = CE->getArg(Arg: 0);
8534 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS)) {
8535 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: DRE->getDecl()))
8536 if (auto *ME =
8537 dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit()))) {
8538 ValueDecl *LoopVar = ME->getMemberDecl();
8539 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8540 return true;
8541 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: CE->getArg(Arg: 1), EmitDiags);
8542 }
8543 ValueDecl *LoopVar = DRE->getDecl();
8544 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8545 return true;
8546 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: DRE, NewLB: CE->getArg(Arg: 1), EmitDiags);
8547 }
8548 if (auto *ME = dyn_cast<MemberExpr>(Val: LHS)) {
8549 if (ME->isArrow() &&
8550 isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts())) {
8551 ValueDecl *LoopVar = ME->getMemberDecl();
8552 if (CheckLoopVarReuse(LoopVar, LHS->getBeginLoc()))
8553 return true;
8554 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: CE->getArg(Arg: 1), EmitDiags);
8555 }
8556 }
8557 }
8558 }
8559
8560 if (dependent() || SemaRef.CurContext->isDependentContext())
8561 return false;
8562 if (EmitDiags) {
8563 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_init)
8564 << S->getSourceRange();
8565 }
8566 return true;
8567}
8568
8569/// Ignore parenthesizes, implicit casts, copy constructor and return the
8570/// variable (which may be the loop variable) if possible.
8571static const ValueDecl *getInitLCDecl(const Expr *E) {
8572 if (!E)
8573 return nullptr;
8574 E = getExprAsWritten(E);
8575 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(Val: E))
8576 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8577 if ((Ctor->isCopyOrMoveConstructor() ||
8578 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8579 CE->getNumArgs() > 0 && CE->getArg(Arg: 0) != nullptr)
8580 E = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
8581 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(Val: E)) {
8582 if (const auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
8583 return getCanonicalDecl(D: VD);
8584 }
8585 if (const auto *ME = dyn_cast_or_null<MemberExpr>(Val: E))
8586 if (ME->isArrow() && isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
8587 return getCanonicalDecl(D: ME->getMemberDecl());
8588 return nullptr;
8589}
8590
8591bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8592 // Check test-expr for canonical form, save upper-bound UB, flags for
8593 // less/greater and for strict/non-strict comparison.
8594 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8595 // var relational-op b
8596 // b relational-op var
8597 //
8598 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8599 if (!S) {
8600 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_cond)
8601 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8602 return true;
8603 }
8604 Condition = S;
8605 S = getExprAsWritten(E: S);
8606
8607 if (!CollapsedLoopVarDecls.empty()) {
8608 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8609 if (!FSEC.TraverseStmt(S)) {
8610 SourceRange Range = FSEC.getErrRange();
8611 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
8612 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8613 return true;
8614 }
8615 }
8616
8617 SourceLocation CondLoc = S->getBeginLoc();
8618 auto &&CheckAndSetCond =
8619 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8620 const Expr *RHS, SourceRange SR,
8621 SourceLocation OpLoc) -> std::optional<bool> {
8622 if (BinaryOperator::isRelationalOp(Opc: Opcode)) {
8623 if (getInitLCDecl(E: LHS) == LCDecl)
8624 return setUB(NewUB: const_cast<Expr *>(RHS),
8625 LessOp: (Opcode == BO_LT || Opcode == BO_LE),
8626 StrictOp: (Opcode == BO_LT || Opcode == BO_GT), SR, SL: OpLoc);
8627 if (getInitLCDecl(E: RHS) == LCDecl)
8628 return setUB(NewUB: const_cast<Expr *>(LHS),
8629 LessOp: (Opcode == BO_GT || Opcode == BO_GE),
8630 StrictOp: (Opcode == BO_LT || Opcode == BO_GT), SR, SL: OpLoc);
8631 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8632 return setUB(NewUB: const_cast<Expr *>(getInitLCDecl(E: LHS) == LCDecl ? RHS : LHS),
8633 /*LessOp=*/std::nullopt,
8634 /*StrictOp=*/true, SR, SL: OpLoc);
8635 }
8636 return std::nullopt;
8637 };
8638 std::optional<bool> Res;
8639 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(Val: S)) {
8640 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8641 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8642 RBO->getOperatorLoc());
8643 } else if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8644 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8645 BO->getSourceRange(), BO->getOperatorLoc());
8646 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8647 if (CE->getNumArgs() == 2) {
8648 Res = CheckAndSetCond(
8649 BinaryOperator::getOverloadedOpcode(OO: CE->getOperator()), CE->getArg(Arg: 0),
8650 CE->getArg(Arg: 1), CE->getSourceRange(), CE->getOperatorLoc());
8651 }
8652 }
8653 if (Res)
8654 return *Res;
8655 if (dependent() || SemaRef.CurContext->isDependentContext())
8656 return false;
8657 SemaRef.Diag(Loc: CondLoc, DiagID: diag::err_omp_loop_not_canonical_cond)
8658 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8659 return true;
8660}
8661
8662bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8663 // RHS of canonical loop form increment can be:
8664 // var + incr
8665 // incr + var
8666 // var - incr
8667 //
8668 RHS = RHS->IgnoreParenImpCasts();
8669 if (auto *BO = dyn_cast<BinaryOperator>(Val: RHS)) {
8670 if (BO->isAdditiveOp()) {
8671 bool IsAdd = BO->getOpcode() == BO_Add;
8672 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8673 return setStep(NewStep: BO->getRHS(), Subtract: !IsAdd);
8674 if (IsAdd && getInitLCDecl(E: BO->getRHS()) == LCDecl)
8675 return setStep(NewStep: BO->getLHS(), /*Subtract=*/false);
8676 }
8677 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: RHS)) {
8678 bool IsAdd = CE->getOperator() == OO_Plus;
8679 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8680 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8681 return setStep(NewStep: CE->getArg(Arg: 1), Subtract: !IsAdd);
8682 if (IsAdd && getInitLCDecl(E: CE->getArg(Arg: 1)) == LCDecl)
8683 return setStep(NewStep: CE->getArg(Arg: 0), /*Subtract=*/false);
8684 }
8685 }
8686 if (dependent() || SemaRef.CurContext->isDependentContext())
8687 return false;
8688 SemaRef.Diag(Loc: RHS->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_incr)
8689 << RHS->getSourceRange() << LCDecl;
8690 return true;
8691}
8692
8693bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8694 // Check incr-expr for canonical loop form and return true if it
8695 // does not conform.
8696 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8697 // ++var
8698 // var++
8699 // --var
8700 // var--
8701 // var += incr
8702 // var -= incr
8703 // var = var + incr
8704 // var = incr + var
8705 // var = var - incr
8706 //
8707 if (!S) {
8708 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_incr) << LCDecl;
8709 return true;
8710 }
8711 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: S))
8712 if (!ExprTemp->cleanupsHaveSideEffects())
8713 S = ExprTemp->getSubExpr();
8714
8715 if (!CollapsedLoopVarDecls.empty()) {
8716 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8717 if (!FSEC.TraverseStmt(S)) {
8718 SourceRange Range = FSEC.getErrRange();
8719 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
8720 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8721 return true;
8722 }
8723 }
8724
8725 IncrementSrcRange = S->getSourceRange();
8726 S = S->IgnoreParens();
8727 if (auto *UO = dyn_cast<UnaryOperator>(Val: S)) {
8728 if (UO->isIncrementDecrementOp() &&
8729 getInitLCDecl(E: UO->getSubExpr()) == LCDecl)
8730 return setStep(NewStep: SemaRef
8731 .ActOnIntegerConstant(Loc: UO->getBeginLoc(),
8732 Val: (UO->isDecrementOp() ? -1 : 1))
8733 .get(),
8734 /*Subtract=*/false);
8735 } else if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8736 switch (BO->getOpcode()) {
8737 case BO_AddAssign:
8738 case BO_SubAssign:
8739 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8740 return setStep(NewStep: BO->getRHS(), Subtract: BO->getOpcode() == BO_SubAssign);
8741 break;
8742 case BO_Assign:
8743 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8744 return checkAndSetIncRHS(RHS: BO->getRHS());
8745 break;
8746 default:
8747 break;
8748 }
8749 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8750 switch (CE->getOperator()) {
8751 case OO_PlusPlus:
8752 case OO_MinusMinus:
8753 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8754 return setStep(NewStep: SemaRef
8755 .ActOnIntegerConstant(
8756 Loc: CE->getBeginLoc(),
8757 Val: ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8758 .get(),
8759 /*Subtract=*/false);
8760 break;
8761 case OO_PlusEqual:
8762 case OO_MinusEqual:
8763 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8764 return setStep(NewStep: CE->getArg(Arg: 1), Subtract: CE->getOperator() == OO_MinusEqual);
8765 break;
8766 case OO_Equal:
8767 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8768 return checkAndSetIncRHS(RHS: CE->getArg(Arg: 1));
8769 break;
8770 default:
8771 break;
8772 }
8773 }
8774 if (dependent() || SemaRef.CurContext->isDependentContext())
8775 return false;
8776 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_incr)
8777 << S->getSourceRange() << LCDecl;
8778 return true;
8779}
8780
8781static ExprResult
8782tryBuildCapture(Sema &SemaRef, Expr *Capture,
8783 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8784 StringRef Name = ".capture_expr.") {
8785 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8786 return Capture;
8787 if (Capture->isEvaluatable(Ctx: SemaRef.Context, AllowSideEffects: Expr::SE_AllowSideEffects))
8788 return SemaRef.PerformImplicitConversion(From: Capture->IgnoreImpCasts(),
8789 ToType: Capture->getType(),
8790 Action: AssignmentAction::Converting,
8791 /*AllowExplicit=*/true);
8792 auto I = Captures.find(Key: Capture);
8793 if (I != Captures.end())
8794 return buildCapture(S&: SemaRef, CaptureExpr: Capture, Ref&: I->second, Name);
8795 DeclRefExpr *Ref = nullptr;
8796 ExprResult Res = buildCapture(S&: SemaRef, CaptureExpr: Capture, Ref, Name);
8797 Captures[Capture] = Ref;
8798 return Res;
8799}
8800
8801/// Calculate number of iterations, transforming to unsigned, if number of
8802/// iterations may be larger than the original type.
8803static Expr *
8804calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8805 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8806 bool TestIsStrictOp, bool RoundToStep,
8807 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8808 std::optional<unsigned> InitDependOnLC,
8809 std::optional<unsigned> CondDependOnLC) {
8810 ExprResult NewStep = tryBuildCapture(SemaRef, Capture: Step, Captures, Name: ".new_step");
8811 if (!NewStep.isUsable())
8812 return nullptr;
8813 llvm::APSInt LRes, SRes;
8814 bool IsLowerConst = false, IsStepConst = false;
8815 if (std::optional<llvm::APSInt> Res =
8816 Lower->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8817 LRes = *Res;
8818 IsLowerConst = true;
8819 }
8820 if (std::optional<llvm::APSInt> Res =
8821 Step->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8822 SRes = *Res;
8823 IsStepConst = true;
8824 }
8825 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8826 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8827 (TestIsStrictOp && LRes.isStrictlyPositive()));
8828 bool NeedToReorganize = false;
8829 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8830 if (!NoNeedToConvert && IsLowerConst &&
8831 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8832 NoNeedToConvert = true;
8833 if (RoundToStep) {
8834 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8835 ? LRes.getBitWidth()
8836 : SRes.getBitWidth();
8837 LRes = LRes.extend(width: BW + 1);
8838 LRes.setIsSigned(true);
8839 SRes = SRes.extend(width: BW + 1);
8840 SRes.setIsSigned(true);
8841 LRes -= SRes;
8842 NoNeedToConvert = LRes.trunc(width: BW).extend(width: BW + 1) == LRes;
8843 LRes = LRes.trunc(width: BW);
8844 }
8845 if (TestIsStrictOp) {
8846 unsigned BW = LRes.getBitWidth();
8847 LRes = LRes.extend(width: BW + 1);
8848 LRes.setIsSigned(true);
8849 ++LRes;
8850 NoNeedToConvert =
8851 NoNeedToConvert && LRes.trunc(width: BW).extend(width: BW + 1) == LRes;
8852 // truncate to the original bitwidth.
8853 LRes = LRes.trunc(width: BW);
8854 }
8855 NeedToReorganize = NoNeedToConvert;
8856 }
8857 llvm::APSInt URes;
8858 bool IsUpperConst = false;
8859 if (std::optional<llvm::APSInt> Res =
8860 Upper->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8861 URes = *Res;
8862 IsUpperConst = true;
8863 }
8864 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8865 (!RoundToStep || IsStepConst)) {
8866 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8867 : URes.getBitWidth();
8868 LRes = LRes.extend(width: BW + 1);
8869 LRes.setIsSigned(true);
8870 URes = URes.extend(width: BW + 1);
8871 URes.setIsSigned(true);
8872 URes -= LRes;
8873 NoNeedToConvert = URes.trunc(width: BW).extend(width: BW + 1) == URes;
8874 NeedToReorganize = NoNeedToConvert;
8875 }
8876 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8877 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8878 // unsigned.
8879 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8880 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8881 QualType LowerTy = Lower->getType();
8882 QualType UpperTy = Upper->getType();
8883 uint64_t LowerSize = SemaRef.Context.getTypeSize(T: LowerTy);
8884 uint64_t UpperSize = SemaRef.Context.getTypeSize(T: UpperTy);
8885 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8886 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8887 QualType CastType = SemaRef.Context.getIntTypeForBitwidth(
8888 DestWidth: LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8889 Upper =
8890 SemaRef
8891 .PerformImplicitConversion(
8892 From: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Upper).get(),
8893 ToType: CastType, Action: AssignmentAction::Converting)
8894 .get();
8895 Lower = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Lower).get();
8896 NewStep = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: NewStep.get());
8897 }
8898 }
8899 if (!Lower || !Upper || NewStep.isInvalid())
8900 return nullptr;
8901
8902 ExprResult Diff;
8903
8904 // For nested triangular loops (depth >= 2), use already computed Upper and
8905 // Lower bounds to calculate the number of iterations: Upper - Lower + 1.
8906 // Don't apply to first-level triangular loops as the standard formula handles
8907 // those correctly.
8908 if (TestIsStrictOp && InitDependOnLC.has_value() &&
8909 InitDependOnLC.value() >= 2 && !CondDependOnLC.has_value()) {
8910 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Lower);
8911 if (!Diff.isUsable())
8912 return nullptr;
8913
8914 Diff =
8915 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(),
8916 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: DefaultLoc, Val: 1).get());
8917 if (!Diff.isUsable())
8918 return nullptr;
8919
8920 return Diff.get();
8921 }
8922
8923 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8924 // 1]).
8925 if (NeedToReorganize) {
8926 Diff = Lower;
8927
8928 if (RoundToStep) {
8929 // Lower - Step
8930 Diff =
8931 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8932 if (!Diff.isUsable())
8933 return nullptr;
8934 }
8935
8936 // Lower - Step [+ 1]
8937 if (TestIsStrictOp)
8938 Diff = SemaRef.BuildBinOp(
8939 S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(),
8940 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
8941 if (!Diff.isUsable())
8942 return nullptr;
8943
8944 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
8945 if (!Diff.isUsable())
8946 return nullptr;
8947
8948 // Upper - (Lower - Step [+ 1]).
8949 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Diff.get());
8950 if (!Diff.isUsable())
8951 return nullptr;
8952 } else {
8953 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Lower);
8954
8955 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8956 // BuildBinOp already emitted error, this one is to point user to upper
8957 // and lower bound, and to tell what is passed to 'operator-'.
8958 SemaRef.Diag(Loc: Upper->getBeginLoc(), DiagID: diag::err_omp_loop_diff_cxx)
8959 << Upper->getSourceRange() << Lower->getSourceRange();
8960 return nullptr;
8961 }
8962
8963 if (!Diff.isUsable())
8964 return nullptr;
8965
8966 // Upper - Lower [- 1]
8967 if (TestIsStrictOp)
8968 Diff = SemaRef.BuildBinOp(
8969 S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Diff.get(),
8970 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
8971 if (!Diff.isUsable())
8972 return nullptr;
8973
8974 if (RoundToStep) {
8975 // Upper - Lower [- 1] + Step
8976 Diff =
8977 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8978 if (!Diff.isUsable())
8979 return nullptr;
8980 }
8981 }
8982
8983 // Parentheses (for dumping/debugging purposes only).
8984 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
8985 if (!Diff.isUsable())
8986 return nullptr;
8987
8988 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8989 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Div, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8990 if (!Diff.isUsable())
8991 return nullptr;
8992
8993 return Diff.get();
8994}
8995
8996/// Build the expression to calculate the number of iterations.
8997Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8998 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8999 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9000 QualType VarType = LCDecl->getType().getNonReferenceType();
9001 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9002 !SemaRef.getLangOpts().CPlusPlus)
9003 return nullptr;
9004 Expr *LBVal = LB;
9005 Expr *UBVal = UB;
9006 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
9007 // max(LB(MinVal), LB(MaxVal)))
9008 if (InitDependOnLC) {
9009 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
9010 if (!IS.MinValue || !IS.MaxValue)
9011 return nullptr;
9012 // OuterVar = Min
9013 ExprResult MinValue =
9014 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MinValue);
9015 if (!MinValue.isUsable())
9016 return nullptr;
9017
9018 ExprResult LBMinVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9019 LHSExpr: IS.CounterVar, RHSExpr: MinValue.get());
9020 if (!LBMinVal.isUsable())
9021 return nullptr;
9022 // OuterVar = Min, LBVal
9023 LBMinVal =
9024 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: LBMinVal.get(), RHSExpr: LBVal);
9025 if (!LBMinVal.isUsable())
9026 return nullptr;
9027 // (OuterVar = Min, LBVal)
9028 LBMinVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: LBMinVal.get());
9029 if (!LBMinVal.isUsable())
9030 return nullptr;
9031
9032 // OuterVar = Max
9033 ExprResult MaxValue =
9034 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MaxValue);
9035 if (!MaxValue.isUsable())
9036 return nullptr;
9037
9038 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9039 LHSExpr: IS.CounterVar, RHSExpr: MaxValue.get());
9040 if (!LBMaxVal.isUsable())
9041 return nullptr;
9042 // OuterVar = Max, LBVal
9043 LBMaxVal =
9044 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: LBMaxVal.get(), RHSExpr: LBVal);
9045 if (!LBMaxVal.isUsable())
9046 return nullptr;
9047 // (OuterVar = Max, LBVal)
9048 LBMaxVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: LBMaxVal.get());
9049 if (!LBMaxVal.isUsable())
9050 return nullptr;
9051
9052 Expr *LBMin =
9053 tryBuildCapture(SemaRef, Capture: LBMinVal.get(), Captures, Name: ".lb_min").get();
9054 Expr *LBMax =
9055 tryBuildCapture(SemaRef, Capture: LBMaxVal.get(), Captures, Name: ".lb_max").get();
9056 if (!LBMin || !LBMax)
9057 return nullptr;
9058 // LB(MinVal) < LB(MaxVal)
9059 ExprResult MinLessMaxRes =
9060 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_LT, LHSExpr: LBMin, RHSExpr: LBMax);
9061 if (!MinLessMaxRes.isUsable())
9062 return nullptr;
9063 Expr *MinLessMax =
9064 tryBuildCapture(SemaRef, Capture: MinLessMaxRes.get(), Captures, Name: ".min_less_max")
9065 .get();
9066 if (!MinLessMax)
9067 return nullptr;
9068 if (*TestIsLessOp) {
9069 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
9070 // LB(MaxVal))
9071 ExprResult MinLB = SemaRef.ActOnConditionalOp(QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc,
9072 CondExpr: MinLessMax, LHSExpr: LBMin, RHSExpr: LBMax);
9073 if (!MinLB.isUsable())
9074 return nullptr;
9075 LBVal = MinLB.get();
9076 } else {
9077 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
9078 // LB(MaxVal))
9079 ExprResult MaxLB = SemaRef.ActOnConditionalOp(QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc,
9080 CondExpr: MinLessMax, LHSExpr: LBMax, RHSExpr: LBMin);
9081 if (!MaxLB.isUsable())
9082 return nullptr;
9083 LBVal = MaxLB.get();
9084 }
9085 // OuterVar = LB
9086 LBMinVal =
9087 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign, LHSExpr: IS.CounterVar, RHSExpr: LBVal);
9088 if (!LBMinVal.isUsable())
9089 return nullptr;
9090 LBVal = LBMinVal.get();
9091 }
9092 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
9093 // min(UB(MinVal), UB(MaxVal))
9094 if (CondDependOnLC) {
9095 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
9096 if (!IS.MinValue || !IS.MaxValue)
9097 return nullptr;
9098 // OuterVar = Min
9099 ExprResult MinValue =
9100 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MinValue);
9101 if (!MinValue.isUsable())
9102 return nullptr;
9103
9104 ExprResult UBMinVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9105 LHSExpr: IS.CounterVar, RHSExpr: MinValue.get());
9106 if (!UBMinVal.isUsable())
9107 return nullptr;
9108 // OuterVar = Min, UBVal
9109 UBMinVal =
9110 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: UBMinVal.get(), RHSExpr: UBVal);
9111 if (!UBMinVal.isUsable())
9112 return nullptr;
9113 // (OuterVar = Min, UBVal)
9114 UBMinVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: UBMinVal.get());
9115 if (!UBMinVal.isUsable())
9116 return nullptr;
9117
9118 // OuterVar = Max
9119 ExprResult MaxValue =
9120 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MaxValue);
9121 if (!MaxValue.isUsable())
9122 return nullptr;
9123
9124 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9125 LHSExpr: IS.CounterVar, RHSExpr: MaxValue.get());
9126 if (!UBMaxVal.isUsable())
9127 return nullptr;
9128 // OuterVar = Max, UBVal
9129 UBMaxVal =
9130 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: UBMaxVal.get(), RHSExpr: UBVal);
9131 if (!UBMaxVal.isUsable())
9132 return nullptr;
9133 // (OuterVar = Max, UBVal)
9134 UBMaxVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: UBMaxVal.get());
9135 if (!UBMaxVal.isUsable())
9136 return nullptr;
9137
9138 Expr *UBMin =
9139 tryBuildCapture(SemaRef, Capture: UBMinVal.get(), Captures, Name: ".ub_min").get();
9140 Expr *UBMax =
9141 tryBuildCapture(SemaRef, Capture: UBMaxVal.get(), Captures, Name: ".ub_max").get();
9142 if (!UBMin || !UBMax)
9143 return nullptr;
9144 // UB(MinVal) > UB(MaxVal)
9145 ExprResult MinGreaterMaxRes =
9146 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_GT, LHSExpr: UBMin, RHSExpr: UBMax);
9147 if (!MinGreaterMaxRes.isUsable())
9148 return nullptr;
9149 Expr *MinGreaterMax = tryBuildCapture(SemaRef, Capture: MinGreaterMaxRes.get(),
9150 Captures, Name: ".min_greater_max")
9151 .get();
9152 if (!MinGreaterMax)
9153 return nullptr;
9154 if (*TestIsLessOp) {
9155 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
9156 // UB(MaxVal))
9157 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
9158 QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc, CondExpr: MinGreaterMax, LHSExpr: UBMin, RHSExpr: UBMax);
9159 if (!MaxUB.isUsable())
9160 return nullptr;
9161 UBVal = MaxUB.get();
9162 } else {
9163 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9164 // UB(MaxVal))
9165 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9166 QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc, CondExpr: MinGreaterMax, LHSExpr: UBMax, RHSExpr: UBMin);
9167 if (!MinUB.isUsable())
9168 return nullptr;
9169 UBVal = MinUB.get();
9170 }
9171 }
9172 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9173 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9174 Expr *Upper = tryBuildCapture(SemaRef, Capture: UBExpr, Captures, Name: ".upper").get();
9175 Expr *Lower = tryBuildCapture(SemaRef, Capture: LBExpr, Captures, Name: ".lower").get();
9176 if (!Upper || !Lower)
9177 return nullptr;
9178
9179 ExprResult Diff = calculateNumIters(
9180 SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType, TestIsStrictOp,
9181 /*RoundToStep=*/true, Captures, InitDependOnLC, CondDependOnLC);
9182 if (!Diff.isUsable())
9183 return nullptr;
9184
9185 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9186 QualType Type = Diff.get()->getType();
9187 ASTContext &C = SemaRef.Context;
9188 bool UseVarType = VarType->hasIntegerRepresentation() &&
9189 C.getTypeSize(T: Type) > C.getTypeSize(T: VarType);
9190 if (!Type->isIntegerType() || UseVarType) {
9191 unsigned NewSize =
9192 UseVarType ? C.getTypeSize(T: VarType) : C.getTypeSize(T: Type);
9193 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9194 : Type->hasSignedIntegerRepresentation();
9195 Type = C.getIntTypeForBitwidth(DestWidth: NewSize, Signed: IsSigned);
9196 if (!SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: Type)) {
9197 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: Type,
9198 Action: AssignmentAction::Converting,
9199 /*AllowExplicit=*/true);
9200 if (!Diff.isUsable())
9201 return nullptr;
9202 }
9203 }
9204 if (LimitedType) {
9205 unsigned NewSize = (C.getTypeSize(T: Type) > 32) ? 64 : 32;
9206 if (NewSize != C.getTypeSize(T: Type)) {
9207 if (NewSize < C.getTypeSize(T: Type)) {
9208 assert(NewSize == 64 && "incorrect loop var size");
9209 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::warn_omp_loop_64_bit_var)
9210 << InitSrcRange << ConditionSrcRange;
9211 }
9212 QualType NewType = C.getIntTypeForBitwidth(
9213 DestWidth: NewSize, Signed: Type->hasSignedIntegerRepresentation() ||
9214 C.getTypeSize(T: Type) < NewSize);
9215 if (!SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: NewType)) {
9216 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: NewType,
9217 Action: AssignmentAction::Converting,
9218 /*AllowExplicit=*/true);
9219 if (!Diff.isUsable())
9220 return nullptr;
9221 }
9222 }
9223 }
9224
9225 return Diff.get();
9226}
9227
9228std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9229 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9230 // Do not build for iterators, they cannot be used in non-rectangular loop
9231 // nests.
9232 if (LCDecl->getType()->isRecordType())
9233 return std::make_pair(x: nullptr, y: nullptr);
9234 // If we subtract, the min is in the condition, otherwise the min is in the
9235 // init value.
9236 Expr *MinExpr = nullptr;
9237 Expr *MaxExpr = nullptr;
9238 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9239 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9240 bool LBNonRect =
9241 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9242 bool UBNonRect =
9243 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9244 Expr *Lower =
9245 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, Capture: LBExpr, Captures).get();
9246 Expr *Upper =
9247 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, Capture: UBExpr, Captures).get();
9248 if (!Upper || !Lower)
9249 return std::make_pair(x: nullptr, y: nullptr);
9250
9251 if (*TestIsLessOp)
9252 MinExpr = Lower;
9253 else
9254 MaxExpr = Upper;
9255
9256 // Build minimum/maximum value based on number of iterations.
9257 QualType VarType = LCDecl->getType().getNonReferenceType();
9258
9259 ExprResult Diff = calculateNumIters(
9260 SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType, TestIsStrictOp,
9261 /*RoundToStep=*/false, Captures, InitDependOnLC, CondDependOnLC);
9262
9263 if (!Diff.isUsable())
9264 return std::make_pair(x: nullptr, y: nullptr);
9265
9266 // ((Upper - Lower [- 1]) / Step) * Step
9267 // Parentheses (for dumping/debugging purposes only).
9268 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9269 if (!Diff.isUsable())
9270 return std::make_pair(x: nullptr, y: nullptr);
9271
9272 ExprResult NewStep = tryBuildCapture(SemaRef, Capture: Step, Captures, Name: ".new_step");
9273 if (!NewStep.isUsable())
9274 return std::make_pair(x: nullptr, y: nullptr);
9275 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Mul, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
9276 if (!Diff.isUsable())
9277 return std::make_pair(x: nullptr, y: nullptr);
9278
9279 // Parentheses (for dumping/debugging purposes only).
9280 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9281 if (!Diff.isUsable())
9282 return std::make_pair(x: nullptr, y: nullptr);
9283
9284 // Convert to the ptrdiff_t, if original type is pointer.
9285 if (VarType->isAnyPointerType() &&
9286 !SemaRef.Context.hasSameType(
9287 T1: Diff.get()->getType(),
9288 T2: SemaRef.Context.getUnsignedPointerDiffType())) {
9289 Diff = SemaRef.PerformImplicitConversion(
9290 From: Diff.get(), ToType: SemaRef.Context.getUnsignedPointerDiffType(),
9291 Action: AssignmentAction::Converting, /*AllowExplicit=*/true);
9292 }
9293 if (!Diff.isUsable())
9294 return std::make_pair(x: nullptr, y: nullptr);
9295
9296 if (*TestIsLessOp) {
9297 // MinExpr = Lower;
9298 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9299 Diff = SemaRef.BuildBinOp(
9300 S, OpLoc: DefaultLoc, Opc: BO_Add,
9301 LHSExpr: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Lower).get(),
9302 RHSExpr: Diff.get());
9303 if (!Diff.isUsable())
9304 return std::make_pair(x: nullptr, y: nullptr);
9305 } else {
9306 // MaxExpr = Upper;
9307 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9308 Diff = SemaRef.BuildBinOp(
9309 S, OpLoc: DefaultLoc, Opc: BO_Sub,
9310 LHSExpr: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Upper).get(),
9311 RHSExpr: Diff.get());
9312 if (!Diff.isUsable())
9313 return std::make_pair(x: nullptr, y: nullptr);
9314 }
9315
9316 // Convert to the original type.
9317 if (SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: VarType))
9318 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: VarType,
9319 Action: AssignmentAction::Converting,
9320 /*AllowExplicit=*/true);
9321 if (!Diff.isUsable())
9322 return std::make_pair(x: nullptr, y: nullptr);
9323
9324 Sema::TentativeAnalysisScope Trap(SemaRef);
9325 Diff = SemaRef.ActOnFinishFullExpr(Expr: Diff.get(), /*DiscardedValue=*/false);
9326 if (!Diff.isUsable())
9327 return std::make_pair(x: nullptr, y: nullptr);
9328
9329 if (*TestIsLessOp)
9330 MaxExpr = Diff.get();
9331 else
9332 MinExpr = Diff.get();
9333
9334 return std::make_pair(x&: MinExpr, y&: MaxExpr);
9335}
9336
9337Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9338 if (InitDependOnLC || CondDependOnLC)
9339 return Condition;
9340 return nullptr;
9341}
9342
9343Expr *OpenMPIterationSpaceChecker::buildPreCond(
9344 Scope *S, Expr *Cond,
9345 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9346 // Do not build a precondition when the condition/initialization is dependent
9347 // to prevent pessimistic early loop exit.
9348 // TODO: this can be improved by calculating min/max values but not sure that
9349 // it will be very effective.
9350 if (CondDependOnLC || InitDependOnLC)
9351 return SemaRef
9352 .PerformImplicitConversion(
9353 From: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get(),
9354 ToType: SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
9355 /*AllowExplicit=*/true)
9356 .get();
9357
9358 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9359 Sema::TentativeAnalysisScope Trap(SemaRef);
9360
9361 ExprResult NewLB = tryBuildCapture(SemaRef, Capture: LB, Captures);
9362 ExprResult NewUB = tryBuildCapture(SemaRef, Capture: UB, Captures);
9363 if (!NewLB.isUsable() || !NewUB.isUsable())
9364 return nullptr;
9365
9366 ExprResult CondExpr =
9367 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc,
9368 Opc: *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9369 : (TestIsStrictOp ? BO_GT : BO_GE),
9370 LHSExpr: NewLB.get(), RHSExpr: NewUB.get());
9371 if (CondExpr.isUsable()) {
9372 if (!SemaRef.Context.hasSameUnqualifiedType(T1: CondExpr.get()->getType(),
9373 T2: SemaRef.Context.BoolTy))
9374 CondExpr = SemaRef.PerformImplicitConversion(
9375 From: CondExpr.get(), ToType: SemaRef.Context.BoolTy,
9376 /*Action=*/AssignmentAction::Casting,
9377 /*AllowExplicit=*/true);
9378 }
9379
9380 // Otherwise use original loop condition and evaluate it in runtime.
9381 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9382}
9383
9384/// Build reference expression to the counter be used for codegen.
9385DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9386 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9387 DSAStackTy &DSA) const {
9388 auto *VD = dyn_cast<VarDecl>(Val: LCDecl);
9389 if (!VD) {
9390 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(D: LCDecl);
9391 DeclRefExpr *Ref = buildDeclRefExpr(
9392 S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(), Loc: DefaultLoc);
9393 const DSAStackTy::DSAVarData Data =
9394 DSA.getTopDSA(D: LCDecl, /*FromParent=*/false);
9395 // If the loop control decl is explicitly marked as private, do not mark it
9396 // as captured again.
9397 if (!isOpenMPPrivate(Kind: Data.CKind) || !Data.RefExpr)
9398 Captures.insert(KV: std::make_pair(x: LCRef, y&: Ref));
9399 return Ref;
9400 }
9401 return cast<DeclRefExpr>(Val: LCRef);
9402}
9403
9404Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9405 if (LCDecl && !LCDecl->isInvalidDecl()) {
9406 QualType Type = LCDecl->getType().getNonReferenceType();
9407 VarDecl *PrivateVar = buildVarDecl(
9408 SemaRef, Loc: DefaultLoc, Type, Name: LCDecl->getName(),
9409 Attrs: LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9410 OrigRef: isa<VarDecl>(Val: LCDecl)
9411 ? buildDeclRefExpr(S&: SemaRef, D: cast<VarDecl>(Val: LCDecl), Ty: Type, Loc: DefaultLoc)
9412 : nullptr);
9413 if (PrivateVar->isInvalidDecl())
9414 return nullptr;
9415 return buildDeclRefExpr(S&: SemaRef, D: PrivateVar, Ty: Type, Loc: DefaultLoc);
9416 }
9417 return nullptr;
9418}
9419
9420/// Build initialization of the counter to be used for codegen.
9421Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9422
9423/// Build step of the counter be used for codegen.
9424Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9425
9426Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9427 Scope *S, Expr *Counter,
9428 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9429 Expr *Inc, OverloadedOperatorKind OOK) {
9430 Expr *Cnt = SemaRef.DefaultLvalueConversion(E: Counter).get();
9431 if (!Cnt)
9432 return nullptr;
9433 if (Inc) {
9434 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9435 "Expected only + or - operations for depend clauses.");
9436 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9437 Cnt = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BOK, LHSExpr: Cnt, RHSExpr: Inc).get();
9438 if (!Cnt)
9439 return nullptr;
9440 }
9441 QualType VarType = LCDecl->getType().getNonReferenceType();
9442 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9443 !SemaRef.getLangOpts().CPlusPlus)
9444 return nullptr;
9445 // Upper - Lower
9446 Expr *Upper =
9447 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, Capture: LB, Captures).get();
9448 Expr *Lower =
9449 *TestIsLessOp ? tryBuildCapture(SemaRef, Capture: LB, Captures).get() : Cnt;
9450 if (!Upper || !Lower)
9451 return nullptr;
9452
9453 ExprResult Diff =
9454 calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType,
9455 /*TestIsStrictOp=*/false, /*RoundToStep=*/false,
9456 Captures, InitDependOnLC, CondDependOnLC);
9457 if (!Diff.isUsable())
9458 return nullptr;
9459
9460 return Diff.get();
9461}
9462} // namespace
9463
9464void SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc,
9465 Stmt *Init) {
9466 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9467 assert(Init && "Expected loop in canonical form.");
9468 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9469 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9470 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9471 return;
9472
9473 DSAStack->loopStart();
9474 llvm::SmallPtrSet<const Decl *, 1> EmptyDeclSet;
9475 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9476 *DSAStack, ForLoc, EmptyDeclSet,
9477 EmptyDeclSet);
9478 if (!ISC.checkAndSetInit(S: Init, /*EmitDiags=*/false)) {
9479 if (ValueDecl *D = ISC.getLoopDecl()) {
9480 auto *VD = dyn_cast<VarDecl>(Val: D);
9481 DeclRefExpr *PrivateRef = nullptr;
9482 if (!VD) {
9483 if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9484 VD = Private;
9485 } else {
9486 PrivateRef = buildCapture(S&: SemaRef, D, CaptureExpr: ISC.getLoopDeclRefExpr(),
9487 /*WithInit=*/false);
9488 VD = cast<VarDecl>(Val: PrivateRef->getDecl());
9489 }
9490 }
9491 DSAStack->addLoopControlVariable(D, Capture: VD);
9492 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9493 if (LD != D->getCanonicalDecl()) {
9494 DSAStack->resetPossibleLoopCounter();
9495 if (auto *Var = dyn_cast_or_null<VarDecl>(Val: LD))
9496 SemaRef.MarkDeclarationsReferencedInExpr(E: buildDeclRefExpr(
9497 S&: SemaRef, D: const_cast<VarDecl *>(Var),
9498 Ty: Var->getType().getNonLValueExprType(Context: getASTContext()), Loc: ForLoc,
9499 /*RefersToCapture=*/true));
9500 }
9501 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9502 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9503 // associated for-loop of a simd construct with just one associated
9504 // for-loop may be listed in a linear clause with a constant-linear-step
9505 // that is the increment of the associated for-loop. The loop iteration
9506 // variable(s) in the associated for-loop(s) of a for or parallel for
9507 // construct may be listed in a private or lastprivate clause.
9508 DSAStackTy::DSAVarData DVar =
9509 DSAStack->getTopDSA(D, /*FromParent=*/false);
9510 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9511 // is declared in the loop and it is predetermined as a private.
9512 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9513 OpenMPClauseKind PredeterminedCKind =
9514 isOpenMPSimdDirective(DKind)
9515 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9516 : OMPC_private;
9517 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9518 return getLeafConstructsOrSelf(D: DK).back() == OMPD_taskloop;
9519 };
9520 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9521 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9522 (getLangOpts().OpenMP <= 45 ||
9523 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9524 ((isOpenMPWorksharingDirective(DKind) ||
9525 IsOpenMPTaskloopDirective(DKind) ||
9526 isOpenMPDistributeDirective(DKind)) &&
9527 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9528 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9529 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9530 unsigned OMPVersion = getLangOpts().OpenMP;
9531 Diag(Loc: Init->getBeginLoc(), DiagID: diag::err_omp_loop_var_dsa)
9532 << getOpenMPClauseNameForDiag(C: DVar.CKind)
9533 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion)
9534 << getOpenMPClauseNameForDiag(C: PredeterminedCKind);
9535 if (DVar.RefExpr == nullptr)
9536 DVar.CKind = PredeterminedCKind;
9537 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9538 } else if (LoopDeclRefExpr) {
9539 // Make the loop iteration variable private (for worksharing
9540 // constructs), linear (for simd directives with the only one
9541 // associated loop) or lastprivate (for simd directives with several
9542 // collapsed or ordered loops).
9543 if (DVar.CKind == OMPC_unknown)
9544 DSAStack->addDSA(D, E: LoopDeclRefExpr, A: PredeterminedCKind, PrivateCopy: PrivateRef);
9545 }
9546 }
9547 }
9548 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9549}
9550
9551namespace {
9552// Utility for OpenMP doacross clause kind
9553class OMPDoacrossKind {
9554public:
9555 bool isSource(const OMPDoacrossClause *C) {
9556 return C->getDependenceType() == OMPC_DOACROSS_source ||
9557 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9558 }
9559 bool isSink(const OMPDoacrossClause *C) {
9560 return C->getDependenceType() == OMPC_DOACROSS_sink;
9561 }
9562 bool isSinkIter(const OMPDoacrossClause *C) {
9563 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9564 }
9565};
9566} // namespace
9567/// Called on a for stmt to check and extract its iteration space
9568/// for further processing (such as collapsing).
9569static bool checkOpenMPIterationSpace(
9570 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9571 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9572 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9573 Expr *OrderedLoopCountExpr,
9574 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9575 llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
9576 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9577 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls,
9578 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars) {
9579 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9580 // OpenMP [2.9.1, Canonical Loop Form]
9581 // for (init-expr; test-expr; incr-expr) structured-block
9582 // for (range-decl: range-expr) structured-block
9583 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(Val: S))
9584 S = CanonLoop->getLoopStmt();
9585 auto *For = dyn_cast_or_null<ForStmt>(Val: S);
9586 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(Val: S);
9587 // Ranged for is supported only in OpenMP 5.0.
9588 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9589 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
9590 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_not_for)
9591 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9592 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion) << TotalNestedLoopCount
9593 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9594 if (TotalNestedLoopCount > 1) {
9595 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9596 SemaRef.Diag(Loc: DSA.getConstructLoc(),
9597 DiagID: diag::note_omp_collapse_ordered_expr)
9598 << 2 << CollapseLoopCountExpr->getSourceRange()
9599 << OrderedLoopCountExpr->getSourceRange();
9600 else if (CollapseLoopCountExpr)
9601 SemaRef.Diag(Loc: CollapseLoopCountExpr->getExprLoc(),
9602 DiagID: diag::note_omp_collapse_ordered_expr)
9603 << 0 << CollapseLoopCountExpr->getSourceRange();
9604 else if (OrderedLoopCountExpr)
9605 SemaRef.Diag(Loc: OrderedLoopCountExpr->getExprLoc(),
9606 DiagID: diag::note_omp_collapse_ordered_expr)
9607 << 1 << OrderedLoopCountExpr->getSourceRange();
9608 }
9609 return true;
9610 }
9611 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9612 "No loop body.");
9613 // Postpone analysis in dependent contexts for ranged for loops.
9614 if (CXXFor && SemaRef.CurContext->isDependentContext())
9615 return false;
9616
9617 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9618 For ? For->getForLoc() : CXXFor->getForLoc(),
9619 CollapsedLoopVarDecls,
9620 CollapsedLoopInductionVars);
9621
9622 // Check init.
9623 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9624 if (ISC.checkAndSetInit(S: Init))
9625 return true;
9626
9627 bool HasErrors = false;
9628
9629 // Check loop variable's type.
9630 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9631 // OpenMP [2.6, Canonical Loop Form]
9632 // Var is one of the following:
9633 // A variable of signed or unsigned integer type.
9634 // For C++, a variable of a random access iterator type.
9635 // For C, a variable of a pointer type.
9636 QualType VarType = LCDecl->getType().getNonReferenceType();
9637 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9638 !VarType->isPointerType() &&
9639 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9640 SemaRef.Diag(Loc: Init->getBeginLoc(), DiagID: diag::err_omp_loop_variable_type)
9641 << SemaRef.getLangOpts().CPlusPlus;
9642 HasErrors = true;
9643 }
9644
9645 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9646 // a Construct
9647 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9648 // parallel for construct is (are) private.
9649 // The loop iteration variable in the associated for-loop of a simd
9650 // construct with just one associated for-loop is linear with a
9651 // constant-linear-step that is the increment of the associated for-loop.
9652 // Exclude loop var from the list of variables with implicitly defined data
9653 // sharing attributes.
9654 VarsWithImplicitDSA.erase(Val: LCDecl);
9655
9656 assert((isOpenMPLoopDirective(DKind) ||
9657 isOpenMPCanonicalLoopSequenceTransformationDirective(DKind)) &&
9658 "DSA for non-loop vars");
9659
9660 // Check test-expr.
9661 HasErrors |= ISC.checkAndSetCond(S: For ? For->getCond() : CXXFor->getCond());
9662
9663 // Check incr-expr.
9664 HasErrors |= ISC.checkAndSetInc(S: For ? For->getInc() : CXXFor->getInc());
9665 }
9666
9667 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9668 return HasErrors;
9669
9670 // Build the loop's iteration space representation.
9671 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9672 S: DSA.getCurScope(), Cond: For ? For->getCond() : CXXFor->getCond(), Captures);
9673 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9674 ISC.buildNumIterations(S: DSA.getCurScope(), ResultIterSpaces,
9675 LimitedType: (isOpenMPWorksharingDirective(DKind) ||
9676 isOpenMPGenericLoopDirective(DKind) ||
9677 isOpenMPTaskLoopDirective(DKind) ||
9678 isOpenMPDistributeDirective(DKind) ||
9679 isOpenMPLoopTransformationDirective(DKind)),
9680 Captures);
9681 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9682 ISC.buildCounterVar(Captures, DSA);
9683 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9684 ISC.buildPrivateCounterVar();
9685 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9686 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9687 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9688 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9689 ISC.getConditionSrcRange();
9690 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9691 ISC.getIncrementSrcRange();
9692 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9693 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9694 ISC.isStrictTestOp();
9695 std::tie(args&: ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9696 args&: ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9697 ISC.buildMinMaxValues(S: DSA.getCurScope(), Captures);
9698 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9699 ISC.buildFinalCondition(S: DSA.getCurScope());
9700 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9701 ISC.doesInitDependOnLC();
9702 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9703 ISC.doesCondDependOnLC();
9704 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9705 ISC.getLoopDependentIdx();
9706
9707 HasErrors |=
9708 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9709 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9710 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9711 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9712 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9713 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9714 if (!HasErrors && DSA.isOrderedRegion()) {
9715 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9716 if (CurrentNestedLoopCount <
9717 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9718 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9719 NumLoop: CurrentNestedLoopCount,
9720 NumIterations: ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9721 DSA.getOrderedRegionParam().second->setLoopCounter(
9722 NumLoop: CurrentNestedLoopCount,
9723 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9724 }
9725 }
9726 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9727 auto *DependC = dyn_cast<OMPDependClause>(Val: Pair.first);
9728 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Val: Pair.first);
9729 unsigned NumLoops =
9730 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9731 if (CurrentNestedLoopCount >= NumLoops) {
9732 // Erroneous case - clause has some problems.
9733 continue;
9734 }
9735 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9736 Pair.second.size() <= CurrentNestedLoopCount) {
9737 // Erroneous case - clause has some problems.
9738 DependC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: nullptr);
9739 continue;
9740 }
9741 OMPDoacrossKind ODK;
9742 if (DoacrossC && ODK.isSink(C: DoacrossC) &&
9743 Pair.second.size() <= CurrentNestedLoopCount) {
9744 // Erroneous case - clause has some problems.
9745 DoacrossC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: nullptr);
9746 continue;
9747 }
9748 Expr *CntValue;
9749 SourceLocation DepLoc =
9750 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9751 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9752 (DoacrossC && ODK.isSource(C: DoacrossC)))
9753 CntValue = ISC.buildOrderedLoopData(
9754 S: DSA.getCurScope(),
9755 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9756 Loc: DepLoc);
9757 else if (DoacrossC && ODK.isSinkIter(C: DoacrossC)) {
9758 Expr *Cnt = SemaRef
9759 .DefaultLvalueConversion(
9760 E: ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9761 .get();
9762 if (!Cnt)
9763 continue;
9764 // build CounterVar - 1
9765 Expr *Inc =
9766 SemaRef.ActOnIntegerConstant(Loc: DoacrossC->getColonLoc(), /*Val=*/1)
9767 .get();
9768 CntValue = ISC.buildOrderedLoopData(
9769 S: DSA.getCurScope(),
9770 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9771 Loc: DepLoc, Inc, OOK: clang::OO_Minus);
9772 } else
9773 CntValue = ISC.buildOrderedLoopData(
9774 S: DSA.getCurScope(),
9775 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9776 Loc: DepLoc, Inc: Pair.second[CurrentNestedLoopCount].first,
9777 OOK: Pair.second[CurrentNestedLoopCount].second);
9778 if (DependC)
9779 DependC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: CntValue);
9780 else
9781 DoacrossC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: CntValue);
9782 }
9783 }
9784 // Record the loop induction variable for nested loop reuse checking.
9785 if (CurrentNestedLoopCount < NestedLoopCount && !HasErrors) {
9786 if (const ValueDecl *LCDecl = ISC.getLoopDecl())
9787 CollapsedLoopInductionVars.insert(Ptr: LCDecl->getCanonicalDecl());
9788 }
9789 return HasErrors;
9790}
9791
9792/// Build 'VarRef = Start.
9793static ExprResult
9794buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9795 ExprResult Start, bool IsNonRectangularLB,
9796 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9797 // Build 'VarRef = Start.
9798 ExprResult NewStart = IsNonRectangularLB
9799 ? Start.get()
9800 : tryBuildCapture(SemaRef, Capture: Start.get(), Captures);
9801 if (!NewStart.isUsable())
9802 return ExprError();
9803 if (!SemaRef.Context.hasSameType(T1: NewStart.get()->getType(),
9804 T2: VarRef.get()->getType())) {
9805 NewStart = SemaRef.PerformImplicitConversion(
9806 From: NewStart.get(), ToType: VarRef.get()->getType(), Action: AssignmentAction::Converting,
9807 /*AllowExplicit=*/true);
9808 if (!NewStart.isUsable())
9809 return ExprError();
9810 }
9811
9812 ExprResult Init =
9813 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: NewStart.get());
9814 return Init;
9815}
9816
9817/// Build 'VarRef = Start + Iter * Step'.
9818static ExprResult buildCounterUpdate(
9819 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9820 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9821 bool IsNonRectangularLB,
9822 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9823 // Add parentheses (for debugging purposes only).
9824 Iter = SemaRef.ActOnParenExpr(L: Loc, R: Loc, E: Iter.get());
9825 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9826 !Step.isUsable())
9827 return ExprError();
9828
9829 ExprResult NewStep = Step;
9830 if (Captures)
9831 NewStep = tryBuildCapture(SemaRef, Capture: Step.get(), Captures&: *Captures);
9832 if (NewStep.isInvalid())
9833 return ExprError();
9834 ExprResult Update =
9835 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Mul, LHSExpr: Iter.get(), RHSExpr: NewStep.get());
9836 if (!Update.isUsable())
9837 return ExprError();
9838
9839 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9840 // 'VarRef = Start (+|-) Iter * Step'.
9841 if (!Start.isUsable())
9842 return ExprError();
9843 ExprResult NewStart = SemaRef.ActOnParenExpr(L: Loc, R: Loc, E: Start.get());
9844 if (!NewStart.isUsable())
9845 return ExprError();
9846 if (Captures && !IsNonRectangularLB)
9847 NewStart = tryBuildCapture(SemaRef, Capture: Start.get(), Captures&: *Captures);
9848 if (NewStart.isInvalid())
9849 return ExprError();
9850
9851 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9852 ExprResult SavedUpdate = Update;
9853 ExprResult UpdateVal;
9854 if (VarRef.get()->getType()->isOverloadableType() ||
9855 NewStart.get()->getType()->isOverloadableType() ||
9856 Update.get()->getType()->isOverloadableType()) {
9857 Sema::TentativeAnalysisScope Trap(SemaRef);
9858
9859 Update =
9860 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: NewStart.get());
9861 if (Update.isUsable()) {
9862 UpdateVal =
9863 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: Subtract ? BO_SubAssign : BO_AddAssign,
9864 LHSExpr: VarRef.get(), RHSExpr: SavedUpdate.get());
9865 if (UpdateVal.isUsable()) {
9866 Update = SemaRef.CreateBuiltinBinOp(OpLoc: Loc, Opc: BO_Comma, LHSExpr: Update.get(),
9867 RHSExpr: UpdateVal.get());
9868 }
9869 }
9870 }
9871
9872 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9873 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9874 Update = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: Subtract ? BO_Sub : BO_Add,
9875 LHSExpr: NewStart.get(), RHSExpr: SavedUpdate.get());
9876 if (!Update.isUsable())
9877 return ExprError();
9878
9879 if (!SemaRef.Context.hasSameType(T1: Update.get()->getType(),
9880 T2: VarRef.get()->getType())) {
9881 Update = SemaRef.PerformImplicitConversion(
9882 From: Update.get(), ToType: VarRef.get()->getType(), Action: AssignmentAction::Converting,
9883 /*AllowExplicit=*/true);
9884 if (!Update.isUsable())
9885 return ExprError();
9886 }
9887
9888 Update = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: Update.get());
9889 }
9890 return Update;
9891}
9892
9893/// Convert integer expression \a E to make it have at least \a Bits
9894/// bits.
9895static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9896 if (E == nullptr)
9897 return ExprError();
9898 ASTContext &C = SemaRef.Context;
9899 QualType OldType = E->getType();
9900 unsigned HasBits = C.getTypeSize(T: OldType);
9901 if (HasBits >= Bits)
9902 return ExprResult(E);
9903 // OK to convert to signed, because new type has more bits than old.
9904 QualType NewType = C.getIntTypeForBitwidth(DestWidth: Bits, /*Signed=*/true);
9905 return SemaRef.PerformImplicitConversion(
9906 From: E, ToType: NewType, Action: AssignmentAction::Converting, /*AllowExplicit=*/true);
9907}
9908
9909/// Check if the given expression \a E is a constant integer that fits
9910/// into \a Bits bits.
9911static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9912 if (E == nullptr)
9913 return false;
9914 if (std::optional<llvm::APSInt> Result =
9915 E->getIntegerConstantExpr(Ctx: SemaRef.Context))
9916 return Signed ? Result->isSignedIntN(N: Bits) : Result->isIntN(N: Bits);
9917 return false;
9918}
9919
9920/// Build preinits statement for the given declarations.
9921static Stmt *buildPreInits(ASTContext &Context,
9922 MutableArrayRef<Decl *> PreInits) {
9923 if (!PreInits.empty()) {
9924 return new (Context) DeclStmt(
9925 DeclGroupRef::Create(C&: Context, Decls: PreInits.begin(), NumDecls: PreInits.size()),
9926 SourceLocation(), SourceLocation());
9927 }
9928 return nullptr;
9929}
9930
9931/// Append the \p Item or the content of a CompoundStmt to the list \p
9932/// TargetList.
9933///
9934/// A CompoundStmt is used as container in case multiple statements need to be
9935/// stored in lieu of using an explicit list. Flattening is necessary because
9936/// contained DeclStmts need to be visible after the execution of the list. Used
9937/// for OpenMP pre-init declarations/statements.
9938static void appendFlattenedStmtList(SmallVectorImpl<Stmt *> &TargetList,
9939 Stmt *Item) {
9940 // nullptr represents an empty list.
9941 if (!Item)
9942 return;
9943
9944 if (auto *CS = dyn_cast<CompoundStmt>(Val: Item))
9945 llvm::append_range(C&: TargetList, R: CS->body());
9946 else
9947 TargetList.push_back(Elt: Item);
9948}
9949
9950/// Build preinits statement for the given declarations.
9951static Stmt *
9952buildPreInits(ASTContext &Context,
9953 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9954 if (!Captures.empty()) {
9955 SmallVector<Decl *, 16> PreInits;
9956 for (const auto &Pair : Captures)
9957 PreInits.push_back(Elt: Pair.second->getDecl());
9958 return buildPreInits(Context, PreInits);
9959 }
9960 return nullptr;
9961}
9962
9963/// Build pre-init statement for the given statements.
9964static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9965 if (PreInits.empty())
9966 return nullptr;
9967
9968 SmallVector<Stmt *> Stmts;
9969 for (Stmt *S : PreInits)
9970 appendFlattenedStmtList(TargetList&: Stmts, Item: S);
9971 return CompoundStmt::Create(C: Context, Stmts: PreInits, FPFeatures: FPOptionsOverride(), LB: {}, RB: {});
9972}
9973
9974/// Build postupdate expression for the given list of postupdates expressions.
9975static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9976 Expr *PostUpdate = nullptr;
9977 if (!PostUpdates.empty()) {
9978 for (Expr *E : PostUpdates) {
9979 Expr *ConvE = S.BuildCStyleCastExpr(
9980 LParenLoc: E->getExprLoc(),
9981 Ty: S.Context.getTrivialTypeSourceInfo(T: S.Context.VoidTy),
9982 RParenLoc: E->getExprLoc(), Op: E)
9983 .get();
9984 PostUpdate = PostUpdate
9985 ? S.CreateBuiltinBinOp(OpLoc: ConvE->getExprLoc(), Opc: BO_Comma,
9986 LHSExpr: PostUpdate, RHSExpr: ConvE)
9987 .get()
9988 : ConvE;
9989 }
9990 }
9991 return PostUpdate;
9992}
9993
9994/// Look for variables declared in the body parts of a for-loop nest. Used
9995/// for verifying loop nest structure before performing a loop collapse
9996/// operation.
9997class ForVarDeclFinder : public DynamicRecursiveASTVisitor {
9998 int NestingDepth = 0;
9999 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
10000
10001public:
10002 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
10003 : VarDecls(VD) {}
10004
10005 bool VisitForStmt(ForStmt *F) override {
10006 ++NestingDepth;
10007 TraverseStmt(S: F->getBody());
10008 --NestingDepth;
10009 return false;
10010 }
10011
10012 bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override {
10013 ++NestingDepth;
10014 TraverseStmt(S: RF->getBody());
10015 --NestingDepth;
10016 return false;
10017 }
10018
10019 bool VisitVarDecl(VarDecl *D) override {
10020 Decl *C = D->getCanonicalDecl();
10021 if (NestingDepth > 0)
10022 VarDecls.insert(Ptr: C);
10023 return true;
10024 }
10025};
10026
10027/// Called on a for stmt to check itself and nested loops (if any).
10028/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
10029/// number of collapsed loops otherwise.
10030static unsigned
10031checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
10032 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
10033 DSAStackTy &DSA,
10034 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
10035 OMPLoopBasedDirective::HelperExprs &Built) {
10036 // If either of the loop expressions exist and contain errors, we bail out
10037 // early because diagnostics have already been emitted and we can't reliably
10038 // check more about the loop.
10039 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
10040 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
10041 return 0;
10042
10043 unsigned NestedLoopCount = 1;
10044 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
10045 !isOpenMPLoopTransformationDirective(DKind);
10046 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
10047 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopInductionVars;
10048
10049 if (CollapseLoopCountExpr) {
10050 // Found 'collapse' clause - calculate collapse number.
10051 Expr::EvalResult Result;
10052 if (!CollapseLoopCountExpr->isValueDependent() &&
10053 CollapseLoopCountExpr->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext())) {
10054 NestedLoopCount = Result.Val.getInt().getLimitedValue();
10055
10056 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
10057 FVDF.TraverseStmt(S: AStmt);
10058 } else {
10059 Built.clear(/*Size=*/1);
10060 return 1;
10061 }
10062 }
10063 unsigned OrderedLoopCount = 1;
10064 if (OrderedLoopCountExpr) {
10065 // Found 'ordered' clause - calculate collapse number.
10066 Expr::EvalResult EVResult;
10067 if (!OrderedLoopCountExpr->isValueDependent() &&
10068 OrderedLoopCountExpr->EvaluateAsInt(Result&: EVResult,
10069 Ctx: SemaRef.getASTContext())) {
10070 llvm::APSInt Result = EVResult.Val.getInt();
10071 if (Result.getLimitedValue() < NestedLoopCount) {
10072 SemaRef.Diag(Loc: OrderedLoopCountExpr->getExprLoc(),
10073 DiagID: diag::err_omp_wrong_ordered_loop_count)
10074 << OrderedLoopCountExpr->getSourceRange();
10075 SemaRef.Diag(Loc: CollapseLoopCountExpr->getExprLoc(),
10076 DiagID: diag::note_collapse_loop_count)
10077 << CollapseLoopCountExpr->getSourceRange();
10078 }
10079 OrderedLoopCount = Result.getLimitedValue();
10080 } else {
10081 Built.clear(/*Size=*/1);
10082 return 1;
10083 }
10084 }
10085 // This is helper routine for loop directives (e.g., 'for', 'simd',
10086 // 'for simd', etc.).
10087 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
10088 unsigned NumLoops = std::max(a: OrderedLoopCount, b: NestedLoopCount);
10089 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
10090 if (!OMPLoopBasedDirective::doForAllLoops(
10091 CurStmt: AStmt->IgnoreContainers(
10092 IgnoreCaptured: !isOpenMPCanonicalLoopNestTransformationDirective(DKind)),
10093 TryImperfectlyNestedLoops: SupportsNonPerfectlyNested, NumLoops,
10094 Callback: [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
10095 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
10096 &IterSpaces, &Captures, &CollapsedLoopVarDecls,
10097 &CollapsedLoopInductionVars](unsigned Cnt, Stmt *CurStmt) {
10098 if (checkOpenMPIterationSpace(
10099 DKind, S: CurStmt, SemaRef, DSA, CurrentNestedLoopCount: Cnt, NestedLoopCount,
10100 TotalNestedLoopCount: NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
10101 VarsWithImplicitDSA, ResultIterSpaces: IterSpaces, Captures,
10102 CollapsedLoopVarDecls, CollapsedLoopInductionVars))
10103 return true;
10104 if (Cnt > 0 && Cnt >= NestedLoopCount &&
10105 IterSpaces[Cnt].CounterVar) {
10106 // Handle initialization of captured loop iterator variables.
10107 auto *DRE = cast<DeclRefExpr>(Val: IterSpaces[Cnt].CounterVar);
10108 if (isa<OMPCapturedExprDecl>(Val: DRE->getDecl())) {
10109 Captures[DRE] = DRE;
10110 }
10111 }
10112 return false;
10113 },
10114 OnTransformationCallback: [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
10115 Stmt *DependentPreInits = Transform->getPreInits();
10116 if (!DependentPreInits)
10117 return;
10118
10119 // Search for pre-init declared variables that need to be captured
10120 // to be referenceable inside the directive.
10121 SmallVector<Stmt *> Constituents;
10122 appendFlattenedStmtList(TargetList&: Constituents, Item: DependentPreInits);
10123 for (Stmt *S : Constituents) {
10124 if (auto *DC = dyn_cast<DeclStmt>(Val: S)) {
10125 for (Decl *C : DC->decls()) {
10126 auto *D = cast<VarDecl>(Val: C);
10127 DeclRefExpr *Ref = buildDeclRefExpr(
10128 S&: SemaRef, D, Ty: D->getType().getNonReferenceType(),
10129 Loc: cast<OMPExecutableDirective>(Val: Transform->getDirective())
10130 ->getBeginLoc());
10131 Captures[Ref] = Ref;
10132 }
10133 }
10134 }
10135 }))
10136 return 0;
10137
10138 Built.clear(/*size=*/Size: NestedLoopCount);
10139
10140 if (SemaRef.CurContext->isDependentContext())
10141 return NestedLoopCount;
10142
10143 // An example of what is generated for the following code:
10144 //
10145 // #pragma omp simd collapse(2) ordered(2)
10146 // for (i = 0; i < NI; ++i)
10147 // for (k = 0; k < NK; ++k)
10148 // for (j = J0; j < NJ; j+=2) {
10149 // <loop body>
10150 // }
10151 //
10152 // We generate the code below.
10153 // Note: the loop body may be outlined in CodeGen.
10154 // Note: some counters may be C++ classes, operator- is used to find number of
10155 // iterations and operator+= to calculate counter value.
10156 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
10157 // or i64 is currently supported).
10158 //
10159 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
10160 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
10161 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
10162 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
10163 // // similar updates for vars in clauses (e.g. 'linear')
10164 // <loop body (using local i and j)>
10165 // }
10166 // i = NI; // assign final values of counters
10167 // j = NJ;
10168 //
10169
10170 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
10171 // the iteration counts of the collapsed for loops.
10172 // Precondition tests if there is at least one iteration (all conditions are
10173 // true).
10174 auto PreCond = ExprResult(IterSpaces[0].PreCond);
10175 Expr *N0 = IterSpaces[0].NumIterations;
10176 ExprResult LastIteration32 = widenIterationCount(
10177 /*Bits=*/32,
10178 E: SemaRef
10179 .PerformImplicitConversion(From: N0->IgnoreImpCasts(), ToType: N0->getType(),
10180 Action: AssignmentAction::Converting,
10181 /*AllowExplicit=*/true)
10182 .get(),
10183 SemaRef);
10184 ExprResult LastIteration64 = widenIterationCount(
10185 /*Bits=*/64,
10186 E: SemaRef
10187 .PerformImplicitConversion(From: N0->IgnoreImpCasts(), ToType: N0->getType(),
10188 Action: AssignmentAction::Converting,
10189 /*AllowExplicit=*/true)
10190 .get(),
10191 SemaRef);
10192
10193 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
10194 return NestedLoopCount;
10195
10196 ASTContext &C = SemaRef.Context;
10197 bool AllCountsNeedLessThan32Bits = C.getTypeSize(T: N0->getType()) < 32;
10198
10199 Scope *CurScope = DSA.getCurScope();
10200 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10201 if (PreCond.isUsable()) {
10202 PreCond =
10203 SemaRef.BuildBinOp(S: CurScope, OpLoc: PreCond.get()->getExprLoc(), Opc: BO_LAnd,
10204 LHSExpr: PreCond.get(), RHSExpr: IterSpaces[Cnt].PreCond);
10205 }
10206 Expr *N = IterSpaces[Cnt].NumIterations;
10207 SourceLocation Loc = N->getExprLoc();
10208 AllCountsNeedLessThan32Bits &= C.getTypeSize(T: N->getType()) < 32;
10209 if (LastIteration32.isUsable())
10210 LastIteration32 = SemaRef.BuildBinOp(
10211 S: CurScope, OpLoc: Loc, Opc: BO_Mul, LHSExpr: LastIteration32.get(),
10212 RHSExpr: SemaRef
10213 .PerformImplicitConversion(From: N->IgnoreImpCasts(), ToType: N->getType(),
10214 Action: AssignmentAction::Converting,
10215 /*AllowExplicit=*/true)
10216 .get());
10217 if (LastIteration64.isUsable())
10218 LastIteration64 = SemaRef.BuildBinOp(
10219 S: CurScope, OpLoc: Loc, Opc: BO_Mul, LHSExpr: LastIteration64.get(),
10220 RHSExpr: SemaRef
10221 .PerformImplicitConversion(From: N->IgnoreImpCasts(), ToType: N->getType(),
10222 Action: AssignmentAction::Converting,
10223 /*AllowExplicit=*/true)
10224 .get());
10225 }
10226
10227 // Choose either the 32-bit or 64-bit version.
10228 ExprResult LastIteration = LastIteration64;
10229 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
10230 (LastIteration32.isUsable() &&
10231 C.getTypeSize(T: LastIteration32.get()->getType()) == 32 &&
10232 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10233 fitsInto(
10234 /*Bits=*/32,
10235 Signed: LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
10236 E: LastIteration64.get(), SemaRef))))
10237 LastIteration = LastIteration32;
10238 QualType VType = LastIteration.get()->getType();
10239 QualType RealVType = VType;
10240 QualType StrideVType = VType;
10241 if (isOpenMPTaskLoopDirective(DKind)) {
10242 VType =
10243 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
10244 StrideVType =
10245 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
10246 }
10247
10248 if (!LastIteration.isUsable())
10249 return 0;
10250
10251 // Save the number of iterations.
10252 ExprResult NumIterations = LastIteration;
10253 {
10254 LastIteration = SemaRef.BuildBinOp(
10255 S: CurScope, OpLoc: LastIteration.get()->getExprLoc(), Opc: BO_Sub,
10256 LHSExpr: LastIteration.get(),
10257 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
10258 if (!LastIteration.isUsable())
10259 return 0;
10260 }
10261
10262 // Calculate the last iteration number beforehand instead of doing this on
10263 // each iteration. Do not do this if the number of iterations may be kfold-ed.
10264 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(Ctx: SemaRef.Context);
10265 ExprResult CalcLastIteration;
10266 if (!IsConstant) {
10267 ExprResult SaveRef =
10268 tryBuildCapture(SemaRef, Capture: LastIteration.get(), Captures);
10269 LastIteration = SaveRef;
10270
10271 // Prepare SaveRef + 1.
10272 NumIterations = SemaRef.BuildBinOp(
10273 S: CurScope, OpLoc: SaveRef.get()->getExprLoc(), Opc: BO_Add, LHSExpr: SaveRef.get(),
10274 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
10275 if (!NumIterations.isUsable())
10276 return 0;
10277 }
10278
10279 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
10280
10281 // Build variables passed into runtime, necessary for worksharing directives.
10282 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10283 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
10284 isOpenMPDistributeDirective(DKind) ||
10285 isOpenMPGenericLoopDirective(DKind) ||
10286 isOpenMPLoopTransformationDirective(DKind)) {
10287 // Lower bound variable, initialized with zero.
10288 VarDecl *LBDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.lb");
10289 LB = buildDeclRefExpr(S&: SemaRef, D: LBDecl, Ty: VType, Loc: InitLoc);
10290 SemaRef.AddInitializerToDecl(dcl: LBDecl,
10291 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
10292 /*DirectInit=*/false);
10293
10294 // Upper bound variable, initialized with last iteration number.
10295 VarDecl *UBDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.ub");
10296 UB = buildDeclRefExpr(S&: SemaRef, D: UBDecl, Ty: VType, Loc: InitLoc);
10297 SemaRef.AddInitializerToDecl(dcl: UBDecl, init: LastIteration.get(),
10298 /*DirectInit=*/false);
10299
10300 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
10301 // This will be used to implement clause 'lastprivate'.
10302 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(DestWidth: 32, Signed: true);
10303 VarDecl *ILDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: Int32Ty, Name: ".omp.is_last");
10304 IL = buildDeclRefExpr(S&: SemaRef, D: ILDecl, Ty: Int32Ty, Loc: InitLoc);
10305 SemaRef.AddInitializerToDecl(dcl: ILDecl,
10306 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
10307 /*DirectInit=*/false);
10308
10309 // Stride variable returned by runtime (we initialize it to 1 by default).
10310 VarDecl *STDecl =
10311 buildVarDecl(SemaRef, Loc: InitLoc, Type: StrideVType, Name: ".omp.stride");
10312 ST = buildDeclRefExpr(S&: SemaRef, D: STDecl, Ty: StrideVType, Loc: InitLoc);
10313 SemaRef.AddInitializerToDecl(dcl: STDecl,
10314 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 1).get(),
10315 /*DirectInit=*/false);
10316
10317 // Build expression: UB = min(UB, LastIteration)
10318 // It is necessary for CodeGen of directives with static scheduling.
10319 ExprResult IsUBGreater = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_GT,
10320 LHSExpr: UB.get(), RHSExpr: LastIteration.get());
10321 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10322 QuestionLoc: LastIteration.get()->getExprLoc(), ColonLoc: InitLoc, CondExpr: IsUBGreater.get(),
10323 LHSExpr: LastIteration.get(), RHSExpr: UB.get());
10324 EUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: UB.get(),
10325 RHSExpr: CondOp.get());
10326 EUB = SemaRef.ActOnFinishFullExpr(Expr: EUB.get(), /*DiscardedValue=*/false);
10327
10328 // If we have a combined directive that combines 'distribute', 'for' or
10329 // 'simd' we need to be able to access the bounds of the schedule of the
10330 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10331 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10332 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10333 // Lower bound variable, initialized with zero.
10334 VarDecl *CombLBDecl =
10335 buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.comb.lb");
10336 CombLB = buildDeclRefExpr(S&: SemaRef, D: CombLBDecl, Ty: VType, Loc: InitLoc);
10337 SemaRef.AddInitializerToDecl(
10338 dcl: CombLBDecl, init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
10339 /*DirectInit=*/false);
10340
10341 // Upper bound variable, initialized with last iteration number.
10342 VarDecl *CombUBDecl =
10343 buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.comb.ub");
10344 CombUB = buildDeclRefExpr(S&: SemaRef, D: CombUBDecl, Ty: VType, Loc: InitLoc);
10345 SemaRef.AddInitializerToDecl(dcl: CombUBDecl, init: LastIteration.get(),
10346 /*DirectInit=*/false);
10347
10348 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10349 S: CurScope, OpLoc: InitLoc, Opc: BO_GT, LHSExpr: CombUB.get(), RHSExpr: LastIteration.get());
10350 ExprResult CombCondOp =
10351 SemaRef.ActOnConditionalOp(QuestionLoc: InitLoc, ColonLoc: InitLoc, CondExpr: CombIsUBGreater.get(),
10352 LHSExpr: LastIteration.get(), RHSExpr: CombUB.get());
10353 CombEUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: CombUB.get(),
10354 RHSExpr: CombCondOp.get());
10355 CombEUB =
10356 SemaRef.ActOnFinishFullExpr(Expr: CombEUB.get(), /*DiscardedValue=*/false);
10357
10358 const CapturedDecl *CD = cast<CapturedStmt>(Val: AStmt)->getCapturedDecl();
10359 // We expect to have at least 2 more parameters than the 'parallel'
10360 // directive does - the lower and upper bounds of the previous schedule.
10361 assert(CD->getNumParams() >= 4 &&
10362 "Unexpected number of parameters in loop combined directive");
10363
10364 // Set the proper type for the bounds given what we learned from the
10365 // enclosed loops.
10366 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/i: 2);
10367 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/i: 3);
10368
10369 // Previous lower and upper bounds are obtained from the region
10370 // parameters.
10371 PrevLB =
10372 buildDeclRefExpr(S&: SemaRef, D: PrevLBDecl, Ty: PrevLBDecl->getType(), Loc: InitLoc);
10373 PrevUB =
10374 buildDeclRefExpr(S&: SemaRef, D: PrevUBDecl, Ty: PrevUBDecl->getType(), Loc: InitLoc);
10375 }
10376 }
10377
10378 // Build the iteration variable and its initialization before loop.
10379 ExprResult IV;
10380 ExprResult Init, CombInit;
10381 {
10382 VarDecl *IVDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: RealVType, Name: ".omp.iv");
10383 IV = buildDeclRefExpr(S&: SemaRef, D: IVDecl, Ty: RealVType, Loc: InitLoc);
10384 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10385 isOpenMPGenericLoopDirective(DKind) ||
10386 isOpenMPTaskLoopDirective(DKind) ||
10387 isOpenMPDistributeDirective(DKind) ||
10388 isOpenMPLoopTransformationDirective(DKind))
10389 ? LB.get()
10390 : SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 0).get();
10391 Init = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: RHS);
10392 Init = SemaRef.ActOnFinishFullExpr(Expr: Init.get(), /*DiscardedValue=*/false);
10393
10394 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10395 Expr *CombRHS =
10396 (isOpenMPWorksharingDirective(DKind) ||
10397 isOpenMPGenericLoopDirective(DKind) ||
10398 isOpenMPTaskLoopDirective(DKind) ||
10399 isOpenMPDistributeDirective(DKind))
10400 ? CombLB.get()
10401 : SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 0).get();
10402 CombInit =
10403 SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: CombRHS);
10404 CombInit =
10405 SemaRef.ActOnFinishFullExpr(Expr: CombInit.get(), /*DiscardedValue=*/false);
10406 }
10407 }
10408
10409 bool UseStrictCompare =
10410 RealVType->hasUnsignedIntegerRepresentation() &&
10411 llvm::all_of(Range&: IterSpaces, P: [](const LoopIterationSpace &LIS) {
10412 return LIS.IsStrictCompare;
10413 });
10414 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10415 // unsigned IV)) for worksharing loops.
10416 SourceLocation CondLoc = AStmt->getBeginLoc();
10417 Expr *BoundUB = UB.get();
10418 if (UseStrictCompare) {
10419 BoundUB =
10420 SemaRef
10421 .BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundUB,
10422 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10423 .get();
10424 BoundUB =
10425 SemaRef.ActOnFinishFullExpr(Expr: BoundUB, /*DiscardedValue=*/false).get();
10426 }
10427 ExprResult Cond =
10428 (isOpenMPWorksharingDirective(DKind) ||
10429 isOpenMPGenericLoopDirective(DKind) ||
10430 isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
10431 isOpenMPLoopTransformationDirective(DKind))
10432 ? SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc,
10433 Opc: UseStrictCompare ? BO_LT : BO_LE, LHSExpr: IV.get(),
10434 RHSExpr: BoundUB)
10435 : SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LT, LHSExpr: IV.get(),
10436 RHSExpr: NumIterations.get());
10437 ExprResult CombDistCond;
10438 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10439 CombDistCond = SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LT, LHSExpr: IV.get(),
10440 RHSExpr: NumIterations.get());
10441 }
10442
10443 ExprResult CombCond;
10444 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10445 Expr *BoundCombUB = CombUB.get();
10446 if (UseStrictCompare) {
10447 BoundCombUB =
10448 SemaRef
10449 .BuildBinOp(
10450 S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundCombUB,
10451 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10452 .get();
10453 BoundCombUB =
10454 SemaRef.ActOnFinishFullExpr(Expr: BoundCombUB, /*DiscardedValue=*/false)
10455 .get();
10456 }
10457 CombCond =
10458 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE,
10459 LHSExpr: IV.get(), RHSExpr: BoundCombUB);
10460 }
10461 // Loop increment (IV = IV + 1)
10462 SourceLocation IncLoc = AStmt->getBeginLoc();
10463 ExprResult Inc =
10464 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: IV.get(),
10465 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: IncLoc, Val: 1).get());
10466 if (!Inc.isUsable())
10467 return 0;
10468 Inc = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: Inc.get());
10469 Inc = SemaRef.ActOnFinishFullExpr(Expr: Inc.get(), /*DiscardedValue=*/false);
10470 if (!Inc.isUsable())
10471 return 0;
10472
10473 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10474 // Used for directives with static scheduling.
10475 // In combined construct, add combined version that use CombLB and CombUB
10476 // base variables for the update
10477 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10478 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
10479 isOpenMPGenericLoopDirective(DKind) ||
10480 isOpenMPDistributeDirective(DKind) ||
10481 isOpenMPLoopTransformationDirective(DKind)) {
10482 // LB + ST
10483 NextLB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: LB.get(), RHSExpr: ST.get());
10484 if (!NextLB.isUsable())
10485 return 0;
10486 // LB = LB + ST
10487 NextLB =
10488 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: LB.get(), RHSExpr: NextLB.get());
10489 NextLB =
10490 SemaRef.ActOnFinishFullExpr(Expr: NextLB.get(), /*DiscardedValue=*/false);
10491 if (!NextLB.isUsable())
10492 return 0;
10493 // UB + ST
10494 NextUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: UB.get(), RHSExpr: ST.get());
10495 if (!NextUB.isUsable())
10496 return 0;
10497 // UB = UB + ST
10498 NextUB =
10499 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: UB.get(), RHSExpr: NextUB.get());
10500 NextUB =
10501 SemaRef.ActOnFinishFullExpr(Expr: NextUB.get(), /*DiscardedValue=*/false);
10502 if (!NextUB.isUsable())
10503 return 0;
10504 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10505 CombNextLB =
10506 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: CombLB.get(), RHSExpr: ST.get());
10507 if (!NextLB.isUsable())
10508 return 0;
10509 // LB = LB + ST
10510 CombNextLB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: CombLB.get(),
10511 RHSExpr: CombNextLB.get());
10512 CombNextLB = SemaRef.ActOnFinishFullExpr(Expr: CombNextLB.get(),
10513 /*DiscardedValue=*/false);
10514 if (!CombNextLB.isUsable())
10515 return 0;
10516 // UB + ST
10517 CombNextUB =
10518 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: CombUB.get(), RHSExpr: ST.get());
10519 if (!CombNextUB.isUsable())
10520 return 0;
10521 // UB = UB + ST
10522 CombNextUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: CombUB.get(),
10523 RHSExpr: CombNextUB.get());
10524 CombNextUB = SemaRef.ActOnFinishFullExpr(Expr: CombNextUB.get(),
10525 /*DiscardedValue=*/false);
10526 if (!CombNextUB.isUsable())
10527 return 0;
10528 }
10529 }
10530
10531 // Create increment expression for distribute loop when combined in a same
10532 // directive with for as IV = IV + ST; ensure upper bound expression based
10533 // on PrevUB instead of NumIterations - used to implement 'for' when found
10534 // in combination with 'distribute', like in 'distribute parallel for'
10535 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10536 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10537 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10538 DistCond = SemaRef.BuildBinOp(
10539 S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE, LHSExpr: IV.get(), RHSExpr: BoundUB);
10540 assert(DistCond.isUsable() && "distribute cond expr was not built");
10541
10542 DistInc =
10543 SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Add, LHSExpr: IV.get(), RHSExpr: ST.get());
10544 assert(DistInc.isUsable() && "distribute inc expr was not built");
10545 DistInc = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Assign, LHSExpr: IV.get(),
10546 RHSExpr: DistInc.get());
10547 DistInc =
10548 SemaRef.ActOnFinishFullExpr(Expr: DistInc.get(), /*DiscardedValue=*/false);
10549 assert(DistInc.isUsable() && "distribute inc expr was not built");
10550
10551 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10552 // construct
10553 ExprResult NewPrevUB = PrevUB;
10554 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10555 if (!SemaRef.Context.hasSameType(T1: UB.get()->getType(),
10556 T2: PrevUB.get()->getType())) {
10557 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10558 LParenLoc: DistEUBLoc,
10559 Ty: SemaRef.Context.getTrivialTypeSourceInfo(T: UB.get()->getType()),
10560 RParenLoc: DistEUBLoc, Op: NewPrevUB.get());
10561 if (!NewPrevUB.isUsable())
10562 return 0;
10563 }
10564 ExprResult IsUBGreater = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistEUBLoc, Opc: BO_GT,
10565 LHSExpr: UB.get(), RHSExpr: NewPrevUB.get());
10566 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10567 QuestionLoc: DistEUBLoc, ColonLoc: DistEUBLoc, CondExpr: IsUBGreater.get(), LHSExpr: NewPrevUB.get(), RHSExpr: UB.get());
10568 PrevEUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Assign, LHSExpr: UB.get(),
10569 RHSExpr: CondOp.get());
10570 PrevEUB =
10571 SemaRef.ActOnFinishFullExpr(Expr: PrevEUB.get(), /*DiscardedValue=*/false);
10572
10573 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10574 // parallel for is in combination with a distribute directive with
10575 // schedule(static, 1)
10576 Expr *BoundPrevUB = PrevUB.get();
10577 if (UseStrictCompare) {
10578 BoundPrevUB =
10579 SemaRef
10580 .BuildBinOp(
10581 S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundPrevUB,
10582 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10583 .get();
10584 BoundPrevUB =
10585 SemaRef.ActOnFinishFullExpr(Expr: BoundPrevUB, /*DiscardedValue=*/false)
10586 .get();
10587 }
10588 ParForInDistCond =
10589 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE,
10590 LHSExpr: IV.get(), RHSExpr: BoundPrevUB);
10591 }
10592
10593 // Build updates and final values of the loop counters.
10594 bool HasErrors = false;
10595 Built.Counters.resize(N: NestedLoopCount);
10596 Built.Inits.resize(N: NestedLoopCount);
10597 Built.Updates.resize(N: NestedLoopCount);
10598 Built.Finals.resize(N: NestedLoopCount);
10599 Built.DependentCounters.resize(N: NestedLoopCount);
10600 Built.DependentInits.resize(N: NestedLoopCount);
10601 Built.FinalsConditions.resize(N: NestedLoopCount);
10602 {
10603 // We implement the following algorithm for obtaining the
10604 // original loop iteration variable values based on the
10605 // value of the collapsed loop iteration variable IV.
10606 //
10607 // Let n+1 be the number of collapsed loops in the nest.
10608 // Iteration variables (I0, I1, .... In)
10609 // Iteration counts (N0, N1, ... Nn)
10610 //
10611 // Acc = IV;
10612 //
10613 // To compute Ik for loop k, 0 <= k <= n, generate:
10614 // Prod = N(k+1) * N(k+2) * ... * Nn;
10615 // Ik = Acc / Prod;
10616 // Acc -= Ik * Prod;
10617 //
10618 ExprResult Acc = IV;
10619 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10620 LoopIterationSpace &IS = IterSpaces[Cnt];
10621 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10622 ExprResult Iter;
10623
10624 // Compute prod
10625 ExprResult Prod = SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get();
10626 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10627 Prod = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Mul, LHSExpr: Prod.get(),
10628 RHSExpr: IterSpaces[K].NumIterations);
10629
10630 // Iter = Acc / Prod
10631 // If there is at least one more inner loop to avoid
10632 // multiplication by 1.
10633 if (Cnt + 1 < NestedLoopCount)
10634 Iter =
10635 SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Div, LHSExpr: Acc.get(), RHSExpr: Prod.get());
10636 else
10637 Iter = Acc;
10638 if (!Iter.isUsable()) {
10639 HasErrors = true;
10640 break;
10641 }
10642
10643 // Update Acc:
10644 // Acc -= Iter * Prod
10645 // Check if there is at least one more inner loop to avoid
10646 // multiplication by 1.
10647 if (Cnt + 1 < NestedLoopCount)
10648 Prod = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Mul, LHSExpr: Iter.get(),
10649 RHSExpr: Prod.get());
10650 else
10651 Prod = Iter;
10652 Acc = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Sub, LHSExpr: Acc.get(), RHSExpr: Prod.get());
10653
10654 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10655 auto *VD = cast<VarDecl>(Val: cast<DeclRefExpr>(Val: IS.CounterVar)->getDecl());
10656 DeclRefExpr *CounterVar = buildDeclRefExpr(
10657 S&: SemaRef, D: VD, Ty: IS.CounterVar->getType(), Loc: IS.CounterVar->getExprLoc(),
10658 /*RefersToCapture=*/true);
10659 ExprResult Init =
10660 buildCounterInit(SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar,
10661 Start: IS.CounterInit, IsNonRectangularLB: IS.IsNonRectangularLB, Captures);
10662 if (!Init.isUsable()) {
10663 HasErrors = true;
10664 break;
10665 }
10666 ExprResult Update = buildCounterUpdate(
10667 SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar, Start: IS.CounterInit, Iter,
10668 Step: IS.CounterStep, Subtract: IS.Subtract, IsNonRectangularLB: IS.IsNonRectangularLB, Captures: &Captures);
10669 if (!Update.isUsable()) {
10670 HasErrors = true;
10671 break;
10672 }
10673
10674 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10675 ExprResult Final =
10676 buildCounterUpdate(SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar,
10677 Start: IS.CounterInit, Iter: IS.NumIterations, Step: IS.CounterStep,
10678 Subtract: IS.Subtract, IsNonRectangularLB: IS.IsNonRectangularLB, Captures: &Captures);
10679 if (!Final.isUsable()) {
10680 HasErrors = true;
10681 break;
10682 }
10683
10684 if (!Update.isUsable() || !Final.isUsable()) {
10685 HasErrors = true;
10686 break;
10687 }
10688 // Save results
10689 Built.Counters[Cnt] = IS.CounterVar;
10690 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10691 Built.Inits[Cnt] = Init.get();
10692 Built.Updates[Cnt] = Update.get();
10693 Built.Finals[Cnt] = Final.get();
10694 Built.DependentCounters[Cnt] = nullptr;
10695 Built.DependentInits[Cnt] = nullptr;
10696 Built.FinalsConditions[Cnt] = nullptr;
10697 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10698 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10699 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10700 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10701 }
10702 }
10703 }
10704
10705 if (HasErrors)
10706 return 0;
10707
10708 // Save results
10709 Built.IterationVarRef = IV.get();
10710 Built.LastIteration = LastIteration.get();
10711 Built.NumIterations = NumIterations.get();
10712 Built.CalcLastIteration = SemaRef
10713 .ActOnFinishFullExpr(Expr: CalcLastIteration.get(),
10714 /*DiscardedValue=*/false)
10715 .get();
10716 Built.PreCond = PreCond.get();
10717 Built.PreInits = buildPreInits(Context&: C, Captures);
10718 Built.Cond = Cond.get();
10719 Built.Init = Init.get();
10720 Built.Inc = Inc.get();
10721 Built.LB = LB.get();
10722 Built.UB = UB.get();
10723 Built.IL = IL.get();
10724 Built.ST = ST.get();
10725 Built.EUB = EUB.get();
10726 Built.NLB = NextLB.get();
10727 Built.NUB = NextUB.get();
10728 Built.PrevLB = PrevLB.get();
10729 Built.PrevUB = PrevUB.get();
10730 Built.DistInc = DistInc.get();
10731 Built.PrevEUB = PrevEUB.get();
10732 Built.DistCombinedFields.LB = CombLB.get();
10733 Built.DistCombinedFields.UB = CombUB.get();
10734 Built.DistCombinedFields.EUB = CombEUB.get();
10735 Built.DistCombinedFields.Init = CombInit.get();
10736 Built.DistCombinedFields.Cond = CombCond.get();
10737 Built.DistCombinedFields.NLB = CombNextLB.get();
10738 Built.DistCombinedFields.NUB = CombNextUB.get();
10739 Built.DistCombinedFields.DistCond = CombDistCond.get();
10740 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10741
10742 return NestedLoopCount;
10743}
10744
10745static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
10746 auto CollapseClauses =
10747 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10748 if (CollapseClauses.begin() != CollapseClauses.end())
10749 return (*CollapseClauses.begin())->getNumForLoops();
10750 return nullptr;
10751}
10752
10753static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
10754 auto OrderedClauses =
10755 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10756 if (OrderedClauses.begin() != OrderedClauses.end())
10757 return (*OrderedClauses.begin())->getNumForLoops();
10758 return nullptr;
10759}
10760
10761static bool checkSimdlenSafelenSpecified(Sema &S,
10762 const ArrayRef<OMPClause *> Clauses) {
10763 const OMPSafelenClause *Safelen = nullptr;
10764 const OMPSimdlenClause *Simdlen = nullptr;
10765
10766 for (const OMPClause *Clause : Clauses) {
10767 if (Clause->getClauseKind() == OMPC_safelen)
10768 Safelen = cast<OMPSafelenClause>(Val: Clause);
10769 else if (Clause->getClauseKind() == OMPC_simdlen)
10770 Simdlen = cast<OMPSimdlenClause>(Val: Clause);
10771 if (Safelen && Simdlen)
10772 break;
10773 }
10774
10775 if (Simdlen && Safelen) {
10776 const Expr *SimdlenLength = Simdlen->getSimdlen();
10777 const Expr *SafelenLength = Safelen->getSafelen();
10778 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10779 SimdlenLength->isInstantiationDependent() ||
10780 SimdlenLength->containsUnexpandedParameterPack())
10781 return false;
10782 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10783 SafelenLength->isInstantiationDependent() ||
10784 SafelenLength->containsUnexpandedParameterPack())
10785 return false;
10786 Expr::EvalResult SimdlenResult, SafelenResult;
10787 SimdlenLength->EvaluateAsInt(Result&: SimdlenResult, Ctx: S.Context);
10788 SafelenLength->EvaluateAsInt(Result&: SafelenResult, Ctx: S.Context);
10789 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10790 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10791 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10792 // If both simdlen and safelen clauses are specified, the value of the
10793 // simdlen parameter must be less than or equal to the value of the safelen
10794 // parameter.
10795 if (SimdlenRes > SafelenRes) {
10796 S.Diag(Loc: SimdlenLength->getExprLoc(),
10797 DiagID: diag::err_omp_wrong_simdlen_safelen_values)
10798 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10799 return true;
10800 }
10801 }
10802 return false;
10803}
10804
10805StmtResult SemaOpenMP::ActOnOpenMPSimdDirective(
10806 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10807 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10808 if (!AStmt)
10809 return StmtError();
10810
10811 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_simd, AStmt);
10812
10813 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10814 OMPLoopBasedDirective::HelperExprs B;
10815 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10816 // define the nested loops number.
10817 unsigned NestedLoopCount = checkOpenMPLoop(
10818 DKind: OMPD_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
10819 AStmt: CS, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
10820 if (NestedLoopCount == 0)
10821 return StmtError();
10822
10823 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10824 return StmtError();
10825
10826 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
10827 return StmtError();
10828
10829 auto *SimdDirective = OMPSimdDirective::Create(
10830 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10831 return SimdDirective;
10832}
10833
10834StmtResult SemaOpenMP::ActOnOpenMPForDirective(
10835 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10836 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10837 if (!AStmt)
10838 return StmtError();
10839
10840 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10841 OMPLoopBasedDirective::HelperExprs B;
10842 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10843 // define the nested loops number.
10844 unsigned NestedLoopCount = checkOpenMPLoop(
10845 DKind: OMPD_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
10846 AStmt, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
10847 if (NestedLoopCount == 0)
10848 return StmtError();
10849
10850 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10851 return StmtError();
10852
10853 auto *ForDirective = OMPForDirective::Create(
10854 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
10855 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10856 return ForDirective;
10857}
10858
10859StmtResult SemaOpenMP::ActOnOpenMPForSimdDirective(
10860 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10861 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10862 if (!AStmt)
10863 return StmtError();
10864
10865 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_for_simd, AStmt);
10866
10867 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10868 OMPLoopBasedDirective::HelperExprs B;
10869 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10870 // define the nested loops number.
10871 unsigned NestedLoopCount =
10872 checkOpenMPLoop(DKind: OMPD_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
10873 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
10874 VarsWithImplicitDSA, Built&: B);
10875 if (NestedLoopCount == 0)
10876 return StmtError();
10877
10878 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10879 return StmtError();
10880
10881 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
10882 return StmtError();
10883
10884 return OMPForSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
10885 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10886}
10887
10888static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind,
10889 Stmt *AStmt, DSAStackTy *Stack) {
10890 if (!AStmt)
10891 return true;
10892
10893 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10894 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
10895 auto BaseStmt = AStmt;
10896 while (auto *CS = dyn_cast_or_null<CapturedStmt>(Val: BaseStmt))
10897 BaseStmt = CS->getCapturedStmt();
10898 if (auto *C = dyn_cast_or_null<CompoundStmt>(Val: BaseStmt)) {
10899 auto S = C->children();
10900 if (S.begin() == S.end())
10901 return true;
10902 // All associated statements must be '#pragma omp section' except for
10903 // the first one.
10904 for (Stmt *SectionStmt : llvm::drop_begin(RangeOrContainer&: S)) {
10905 if (!SectionStmt || !isa<OMPSectionDirective>(Val: SectionStmt)) {
10906 if (SectionStmt)
10907 SemaRef.Diag(Loc: SectionStmt->getBeginLoc(),
10908 DiagID: diag::err_omp_sections_substmt_not_section)
10909 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
10910 return true;
10911 }
10912 cast<OMPSectionDirective>(Val: SectionStmt)
10913 ->setHasCancel(Stack->isCancelRegion());
10914 }
10915 } else {
10916 SemaRef.Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_sections_not_compound_stmt)
10917 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
10918 return true;
10919 }
10920 return false;
10921}
10922
10923StmtResult
10924SemaOpenMP::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
10925 Stmt *AStmt, SourceLocation StartLoc,
10926 SourceLocation EndLoc) {
10927 if (checkSectionsDirective(SemaRef, DKind: OMPD_sections, AStmt, DSAStack))
10928 return StmtError();
10929
10930 SemaRef.setFunctionHasBranchProtectedScope();
10931
10932 return OMPSectionsDirective::Create(
10933 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
10934 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10935}
10936
10937StmtResult SemaOpenMP::ActOnOpenMPSectionDirective(Stmt *AStmt,
10938 SourceLocation StartLoc,
10939 SourceLocation EndLoc) {
10940 if (!AStmt)
10941 return StmtError();
10942
10943 SemaRef.setFunctionHasBranchProtectedScope();
10944 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10945
10946 return OMPSectionDirective::Create(C: getASTContext(), StartLoc, EndLoc, AssociatedStmt: AStmt,
10947 DSAStack->isCancelRegion());
10948}
10949
10950static Expr *getDirectCallExpr(Expr *E) {
10951 E = E->IgnoreParenCasts()->IgnoreImplicit();
10952 if (auto *CE = dyn_cast<CallExpr>(Val: E))
10953 if (CE->getDirectCallee())
10954 return E;
10955 return nullptr;
10956}
10957
10958StmtResult
10959SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
10960 Stmt *AStmt, SourceLocation StartLoc,
10961 SourceLocation EndLoc) {
10962 if (!AStmt)
10963 return StmtError();
10964
10965 Stmt *S = cast<CapturedStmt>(Val: AStmt)->getCapturedStmt();
10966
10967 // 5.1 OpenMP
10968 // expression-stmt : an expression statement with one of the following forms:
10969 // expression = target-call ( [expression-list] );
10970 // target-call ( [expression-list] );
10971
10972 SourceLocation TargetCallLoc;
10973
10974 if (!SemaRef.CurContext->isDependentContext()) {
10975 Expr *TargetCall = nullptr;
10976
10977 auto *E = dyn_cast<Expr>(Val: S);
10978 if (!E) {
10979 Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_dispatch_statement_call);
10980 return StmtError();
10981 }
10982
10983 E = E->IgnoreParenCasts()->IgnoreImplicit();
10984
10985 if (auto *BO = dyn_cast<BinaryOperator>(Val: E)) {
10986 if (BO->getOpcode() == BO_Assign)
10987 TargetCall = getDirectCallExpr(E: BO->getRHS());
10988 } else {
10989 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(Val: E))
10990 if (COCE->getOperator() == OO_Equal)
10991 TargetCall = getDirectCallExpr(E: COCE->getArg(Arg: 1));
10992 if (!TargetCall)
10993 TargetCall = getDirectCallExpr(E);
10994 }
10995 if (!TargetCall) {
10996 Diag(Loc: E->getBeginLoc(), DiagID: diag::err_omp_dispatch_statement_call);
10997 return StmtError();
10998 }
10999 TargetCallLoc = TargetCall->getExprLoc();
11000 }
11001
11002 SemaRef.setFunctionHasBranchProtectedScope();
11003
11004 return OMPDispatchDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11005 Clauses, AssociatedStmt: AStmt, TargetCallLoc);
11006}
11007
11008static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
11009 OpenMPDirectiveKind K,
11010 DSAStackTy *Stack) {
11011 bool ErrorFound = false;
11012 for (OMPClause *C : Clauses) {
11013 if (auto *LPC = dyn_cast<OMPLastprivateClause>(Val: C)) {
11014 for (Expr *RefExpr : LPC->varlist()) {
11015 SourceLocation ELoc;
11016 SourceRange ERange;
11017 Expr *SimpleRefExpr = RefExpr;
11018 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange);
11019 if (ValueDecl *D = Res.first) {
11020 auto &&Info = Stack->isLoopControlVariable(D);
11021 if (!Info.first) {
11022 unsigned OMPVersion = S.getLangOpts().OpenMP;
11023 S.Diag(Loc: ELoc, DiagID: diag::err_omp_lastprivate_loop_var_non_loop_iteration)
11024 << getOpenMPDirectiveName(D: K, Ver: OMPVersion);
11025 ErrorFound = true;
11026 }
11027 }
11028 }
11029 }
11030 }
11031 return ErrorFound;
11032}
11033
11034StmtResult SemaOpenMP::ActOnOpenMPGenericLoopDirective(
11035 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11036 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11037 if (!AStmt)
11038 return StmtError();
11039
11040 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11041 // A list item may not appear in a lastprivate clause unless it is the
11042 // loop iteration variable of a loop that is associated with the construct.
11043 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_loop, DSAStack))
11044 return StmtError();
11045
11046 setBranchProtectedScope(SemaRef, DKind: OMPD_loop, AStmt);
11047
11048 OMPLoopDirective::HelperExprs B;
11049 // In presence of clause 'collapse', it will define the nested loops number.
11050 unsigned NestedLoopCount = checkOpenMPLoop(
11051 DKind: OMPD_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
11052 AStmt, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
11053 if (NestedLoopCount == 0)
11054 return StmtError();
11055
11056 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11057 "omp loop exprs were not built");
11058
11059 return OMPGenericLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11060 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11061}
11062
11063StmtResult SemaOpenMP::ActOnOpenMPTeamsGenericLoopDirective(
11064 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11065 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11066 if (!AStmt)
11067 return StmtError();
11068
11069 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11070 // A list item may not appear in a lastprivate clause unless it is the
11071 // loop iteration variable of a loop that is associated with the construct.
11072 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_teams_loop, DSAStack))
11073 return StmtError();
11074
11075 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_teams_loop, AStmt);
11076
11077 OMPLoopDirective::HelperExprs B;
11078 // In presence of clause 'collapse', it will define the nested loops number.
11079 unsigned NestedLoopCount =
11080 checkOpenMPLoop(DKind: OMPD_teams_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11081 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11082 VarsWithImplicitDSA, Built&: B);
11083 if (NestedLoopCount == 0)
11084 return StmtError();
11085
11086 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11087 "omp loop exprs were not built");
11088
11089 DSAStack->setParentTeamsRegionLoc(StartLoc);
11090
11091 return OMPTeamsGenericLoopDirective::Create(
11092 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11093}
11094
11095StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsGenericLoopDirective(
11096 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11097 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11098 if (!AStmt)
11099 return StmtError();
11100
11101 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11102 // A list item may not appear in a lastprivate clause unless it is the
11103 // loop iteration variable of a loop that is associated with the construct.
11104 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_target_teams_loop,
11105 DSAStack))
11106 return StmtError();
11107
11108 CapturedStmt *CS =
11109 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams_loop, AStmt);
11110
11111 OMPLoopDirective::HelperExprs B;
11112 // In presence of clause 'collapse', it will define the nested loops number.
11113 unsigned NestedLoopCount =
11114 checkOpenMPLoop(DKind: OMPD_target_teams_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11115 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11116 VarsWithImplicitDSA, Built&: B);
11117 if (NestedLoopCount == 0)
11118 return StmtError();
11119
11120 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11121 "omp loop exprs were not built");
11122
11123 return OMPTargetTeamsGenericLoopDirective::Create(
11124 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
11125 CanBeParallelFor: teamsLoopCanBeParallelFor(AStmt, SemaRef));
11126}
11127
11128StmtResult SemaOpenMP::ActOnOpenMPParallelGenericLoopDirective(
11129 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11130 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11131 if (!AStmt)
11132 return StmtError();
11133
11134 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11135 // A list item may not appear in a lastprivate clause unless it is the
11136 // loop iteration variable of a loop that is associated with the construct.
11137 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_parallel_loop,
11138 DSAStack))
11139 return StmtError();
11140
11141 CapturedStmt *CS =
11142 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_loop, AStmt);
11143
11144 OMPLoopDirective::HelperExprs B;
11145 // In presence of clause 'collapse', it will define the nested loops number.
11146 unsigned NestedLoopCount =
11147 checkOpenMPLoop(DKind: OMPD_parallel_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11148 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11149 VarsWithImplicitDSA, Built&: B);
11150 if (NestedLoopCount == 0)
11151 return StmtError();
11152
11153 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11154 "omp loop exprs were not built");
11155
11156 return OMPParallelGenericLoopDirective::Create(
11157 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11158}
11159
11160StmtResult SemaOpenMP::ActOnOpenMPTargetParallelGenericLoopDirective(
11161 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11162 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11163 if (!AStmt)
11164 return StmtError();
11165
11166 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11167 // A list item may not appear in a lastprivate clause unless it is the
11168 // loop iteration variable of a loop that is associated with the construct.
11169 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_target_parallel_loop,
11170 DSAStack))
11171 return StmtError();
11172
11173 CapturedStmt *CS =
11174 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_loop, AStmt);
11175
11176 OMPLoopDirective::HelperExprs B;
11177 // In presence of clause 'collapse', it will define the nested loops number.
11178 unsigned NestedLoopCount =
11179 checkOpenMPLoop(DKind: OMPD_target_parallel_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11180 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11181 VarsWithImplicitDSA, Built&: B);
11182 if (NestedLoopCount == 0)
11183 return StmtError();
11184
11185 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11186 "omp loop exprs were not built");
11187
11188 return OMPTargetParallelGenericLoopDirective::Create(
11189 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11190}
11191
11192StmtResult SemaOpenMP::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
11193 Stmt *AStmt,
11194 SourceLocation StartLoc,
11195 SourceLocation EndLoc) {
11196 if (!AStmt)
11197 return StmtError();
11198
11199 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11200
11201 SemaRef.setFunctionHasBranchProtectedScope();
11202
11203 // OpenMP [2.7.3, single Construct, Restrictions]
11204 // The copyprivate clause must not be used with the nowait clause.
11205 const OMPClause *Nowait = nullptr;
11206 const OMPClause *Copyprivate = nullptr;
11207 for (const OMPClause *Clause : Clauses) {
11208 if (Clause->getClauseKind() == OMPC_nowait)
11209 Nowait = Clause;
11210 else if (Clause->getClauseKind() == OMPC_copyprivate)
11211 Copyprivate = Clause;
11212 if (Copyprivate && Nowait) {
11213 Diag(Loc: Copyprivate->getBeginLoc(),
11214 DiagID: diag::err_omp_single_copyprivate_with_nowait);
11215 Diag(Loc: Nowait->getBeginLoc(), DiagID: diag::note_omp_nowait_clause_here);
11216 return StmtError();
11217 }
11218 }
11219
11220 return OMPSingleDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11221 AssociatedStmt: AStmt);
11222}
11223
11224StmtResult SemaOpenMP::ActOnOpenMPMasterDirective(Stmt *AStmt,
11225 SourceLocation StartLoc,
11226 SourceLocation EndLoc) {
11227 if (!AStmt)
11228 return StmtError();
11229
11230 SemaRef.setFunctionHasBranchProtectedScope();
11231
11232 return OMPMasterDirective::Create(C: getASTContext(), StartLoc, EndLoc, AssociatedStmt: AStmt);
11233}
11234
11235StmtResult SemaOpenMP::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
11236 Stmt *AStmt,
11237 SourceLocation StartLoc,
11238 SourceLocation EndLoc) {
11239 if (!AStmt)
11240 return StmtError();
11241
11242 SemaRef.setFunctionHasBranchProtectedScope();
11243
11244 return OMPMaskedDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11245 AssociatedStmt: AStmt);
11246}
11247
11248StmtResult SemaOpenMP::ActOnOpenMPCriticalDirective(
11249 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11250 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11251 if (!AStmt)
11252 return StmtError();
11253
11254 bool ErrorFound = false;
11255 llvm::APSInt Hint;
11256 SourceLocation HintLoc;
11257 bool DependentHint = false;
11258 for (const OMPClause *C : Clauses) {
11259 if (C->getClauseKind() == OMPC_hint) {
11260 if (!DirName.getName()) {
11261 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_hint_clause_no_name);
11262 ErrorFound = true;
11263 }
11264 Expr *E = cast<OMPHintClause>(Val: C)->getHint();
11265 if (E->isTypeDependent() || E->isValueDependent() ||
11266 E->isInstantiationDependent()) {
11267 DependentHint = true;
11268 } else {
11269 Hint = E->EvaluateKnownConstInt(Ctx: getASTContext());
11270 HintLoc = C->getBeginLoc();
11271 }
11272 }
11273 }
11274 if (ErrorFound)
11275 return StmtError();
11276 const auto Pair = DSAStack->getCriticalWithHint(Name: DirName);
11277 if (Pair.first && DirName.getName() && !DependentHint) {
11278 if (llvm::APSInt::compareValues(I1: Hint, I2: Pair.second) != 0) {
11279 Diag(Loc: StartLoc, DiagID: diag::err_omp_critical_with_hint);
11280 if (HintLoc.isValid())
11281 Diag(Loc: HintLoc, DiagID: diag::note_omp_critical_hint_here)
11282 << 0 << toString(I: Hint, /*Radix=*/10, /*Signed=*/false);
11283 else
11284 Diag(Loc: StartLoc, DiagID: diag::note_omp_critical_no_hint) << 0;
11285 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11286 Diag(Loc: C->getBeginLoc(), DiagID: diag::note_omp_critical_hint_here)
11287 << 1
11288 << toString(I: C->getHint()->EvaluateKnownConstInt(Ctx: getASTContext()),
11289 /*Radix=*/10, /*Signed=*/false);
11290 } else {
11291 Diag(Loc: Pair.first->getBeginLoc(), DiagID: diag::note_omp_critical_no_hint) << 1;
11292 }
11293 }
11294 }
11295
11296 SemaRef.setFunctionHasBranchProtectedScope();
11297
11298 auto *Dir = OMPCriticalDirective::Create(C: getASTContext(), Name: DirName, StartLoc,
11299 EndLoc, Clauses, AssociatedStmt: AStmt);
11300 if (!Pair.first && DirName.getName() && !DependentHint)
11301 DSAStack->addCriticalWithHint(D: Dir, Hint);
11302 return Dir;
11303}
11304
11305StmtResult SemaOpenMP::ActOnOpenMPParallelForDirective(
11306 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11307 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11308 if (!AStmt)
11309 return StmtError();
11310
11311 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_for, AStmt);
11312
11313 OMPLoopBasedDirective::HelperExprs B;
11314 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11315 // define the nested loops number.
11316 unsigned NestedLoopCount =
11317 checkOpenMPLoop(DKind: OMPD_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11318 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt, SemaRef, DSA&: *DSAStack,
11319 VarsWithImplicitDSA, Built&: B);
11320 if (NestedLoopCount == 0)
11321 return StmtError();
11322
11323 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11324 return StmtError();
11325
11326 return OMPParallelForDirective::Create(
11327 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
11328 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11329}
11330
11331StmtResult SemaOpenMP::ActOnOpenMPParallelForSimdDirective(
11332 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11333 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11334 if (!AStmt)
11335 return StmtError();
11336
11337 CapturedStmt *CS =
11338 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_for_simd, AStmt);
11339
11340 OMPLoopBasedDirective::HelperExprs B;
11341 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11342 // define the nested loops number.
11343 unsigned NestedLoopCount =
11344 checkOpenMPLoop(DKind: OMPD_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11345 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
11346 VarsWithImplicitDSA, Built&: B);
11347 if (NestedLoopCount == 0)
11348 return StmtError();
11349
11350 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11351 return StmtError();
11352
11353 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
11354 return StmtError();
11355
11356 return OMPParallelForSimdDirective::Create(
11357 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11358}
11359
11360StmtResult SemaOpenMP::ActOnOpenMPParallelMasterDirective(
11361 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11362 SourceLocation EndLoc) {
11363 if (!AStmt)
11364 return StmtError();
11365
11366 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_master, AStmt);
11367
11368 return OMPParallelMasterDirective::Create(
11369 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11370 DSAStack->getTaskgroupReductionRef());
11371}
11372
11373StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedDirective(
11374 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11375 SourceLocation EndLoc) {
11376 if (!AStmt)
11377 return StmtError();
11378
11379 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_masked, AStmt);
11380
11381 return OMPParallelMaskedDirective::Create(
11382 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11383 DSAStack->getTaskgroupReductionRef());
11384}
11385
11386StmtResult SemaOpenMP::ActOnOpenMPParallelSectionsDirective(
11387 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11388 SourceLocation EndLoc) {
11389 if (checkSectionsDirective(SemaRef, DKind: OMPD_parallel_sections, AStmt, DSAStack))
11390 return StmtError();
11391
11392 SemaRef.setFunctionHasBranchProtectedScope();
11393
11394 return OMPParallelSectionsDirective::Create(
11395 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11396 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11397}
11398
11399/// Find and diagnose mutually exclusive clause kinds.
11400static bool checkMutuallyExclusiveClauses(
11401 Sema &S, ArrayRef<OMPClause *> Clauses,
11402 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11403 const OMPClause *PrevClause = nullptr;
11404 bool ErrorFound = false;
11405 for (const OMPClause *C : Clauses) {
11406 if (llvm::is_contained(Range&: MutuallyExclusiveClauses, Element: C->getClauseKind())) {
11407 if (!PrevClause) {
11408 PrevClause = C;
11409 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11410 S.Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_clauses_mutually_exclusive)
11411 << getOpenMPClauseNameForDiag(C: C->getClauseKind())
11412 << getOpenMPClauseNameForDiag(C: PrevClause->getClauseKind());
11413 S.Diag(Loc: PrevClause->getBeginLoc(), DiagID: diag::note_omp_previous_clause)
11414 << getOpenMPClauseNameForDiag(C: PrevClause->getClauseKind());
11415 ErrorFound = true;
11416 }
11417 }
11418 }
11419 return ErrorFound;
11420}
11421
11422StmtResult SemaOpenMP::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
11423 Stmt *AStmt,
11424 SourceLocation StartLoc,
11425 SourceLocation EndLoc) {
11426 if (!AStmt)
11427 return StmtError();
11428
11429 // OpenMP 5.0, 2.10.1 task Construct
11430 // If a detach clause appears on the directive, then a mergeable clause cannot
11431 // appear on the same directive.
11432 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
11433 MutuallyExclusiveClauses: {OMPC_detach, OMPC_mergeable}))
11434 return StmtError();
11435
11436 setBranchProtectedScope(SemaRef, DKind: OMPD_task, AStmt);
11437
11438 return OMPTaskDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11439 AssociatedStmt: AStmt, DSAStack->isCancelRegion());
11440}
11441
11442StmtResult SemaOpenMP::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
11443 SourceLocation EndLoc) {
11444 return OMPTaskyieldDirective::Create(C: getASTContext(), StartLoc, EndLoc);
11445}
11446
11447StmtResult SemaOpenMP::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
11448 SourceLocation EndLoc) {
11449 return OMPBarrierDirective::Create(C: getASTContext(), StartLoc, EndLoc);
11450}
11451
11452StmtResult SemaOpenMP::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
11453 SourceLocation StartLoc,
11454 SourceLocation EndLoc,
11455 bool InExContext) {
11456 const OMPAtClause *AtC =
11457 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11458
11459 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11460 Diag(Loc: AtC->getAtKindKwLoc(), DiagID: diag::err_omp_unexpected_execution_modifier);
11461 return StmtError();
11462 }
11463
11464 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11465 const OMPSeverityClause *SeverityC =
11466 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11467 const OMPMessageClause *MessageC =
11468 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11469 std::optional<std::string> SL =
11470 MessageC ? MessageC->tryEvaluateString(Ctx&: getASTContext()) : std::nullopt;
11471
11472 if (MessageC && !SL)
11473 Diag(Loc: MessageC->getMessageString()->getBeginLoc(),
11474 DiagID: diag::warn_clause_expected_string)
11475 << getOpenMPClauseNameForDiag(C: OMPC_message) << 1;
11476 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11477 Diag(Loc: SeverityC->getSeverityKindKwLoc(), DiagID: diag::warn_diagnose_if_succeeded)
11478 << SL.value_or(u: "WARNING");
11479 else
11480 Diag(Loc: StartLoc, DiagID: diag::err_diagnose_if_succeeded) << SL.value_or(u: "ERROR");
11481 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11482 return StmtError();
11483 }
11484
11485 return OMPErrorDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11486}
11487
11488StmtResult
11489SemaOpenMP::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
11490 SourceLocation StartLoc,
11491 SourceLocation EndLoc) {
11492 const OMPNowaitClause *NowaitC =
11493 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11494 bool HasDependC =
11495 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11496 .empty();
11497 if (NowaitC && !HasDependC) {
11498 Diag(Loc: StartLoc, DiagID: diag::err_omp_nowait_clause_without_depend);
11499 return StmtError();
11500 }
11501
11502 return OMPTaskwaitDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11503 Clauses);
11504}
11505
11506StmtResult
11507SemaOpenMP::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
11508 Stmt *AStmt, SourceLocation StartLoc,
11509 SourceLocation EndLoc) {
11510 if (!AStmt)
11511 return StmtError();
11512
11513 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11514
11515 SemaRef.setFunctionHasBranchProtectedScope();
11516
11517 return OMPTaskgroupDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11518 Clauses, AssociatedStmt: AStmt,
11519 DSAStack->getTaskgroupReductionRef());
11520}
11521
11522StmtResult SemaOpenMP::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
11523 SourceLocation StartLoc,
11524 SourceLocation EndLoc) {
11525 OMPFlushClause *FC = nullptr;
11526 OMPClause *OrderClause = nullptr;
11527 for (OMPClause *C : Clauses) {
11528 if (C->getClauseKind() == OMPC_flush)
11529 FC = cast<OMPFlushClause>(Val: C);
11530 else
11531 OrderClause = C;
11532 }
11533 unsigned OMPVersion = getLangOpts().OpenMP;
11534 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11535 SourceLocation MemOrderLoc;
11536 for (const OMPClause *C : Clauses) {
11537 if (C->getClauseKind() == OMPC_acq_rel ||
11538 C->getClauseKind() == OMPC_acquire ||
11539 C->getClauseKind() == OMPC_release ||
11540 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11541 if (MemOrderKind != OMPC_unknown) {
11542 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_several_mem_order_clauses)
11543 << getOpenMPDirectiveName(D: OMPD_flush, Ver: OMPVersion) << 1
11544 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11545 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
11546 << getOpenMPClauseNameForDiag(C: MemOrderKind);
11547 } else {
11548 MemOrderKind = C->getClauseKind();
11549 MemOrderLoc = C->getBeginLoc();
11550 }
11551 }
11552 }
11553 if (FC && OrderClause) {
11554 Diag(Loc: FC->getLParenLoc(), DiagID: diag::err_omp_flush_order_clause_and_list)
11555 << getOpenMPClauseNameForDiag(C: OrderClause->getClauseKind());
11556 Diag(Loc: OrderClause->getBeginLoc(), DiagID: diag::note_omp_flush_order_clause_here)
11557 << getOpenMPClauseNameForDiag(C: OrderClause->getClauseKind());
11558 return StmtError();
11559 }
11560 return OMPFlushDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11561}
11562
11563StmtResult SemaOpenMP::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
11564 SourceLocation StartLoc,
11565 SourceLocation EndLoc) {
11566 if (Clauses.empty()) {
11567 Diag(Loc: StartLoc, DiagID: diag::err_omp_depobj_expected);
11568 return StmtError();
11569 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11570 Diag(Loc: Clauses[0]->getBeginLoc(), DiagID: diag::err_omp_depobj_expected);
11571 return StmtError();
11572 }
11573 // Only depobj expression and another single clause is allowed.
11574 if (Clauses.size() > 2) {
11575 Diag(Loc: Clauses[2]->getBeginLoc(),
11576 DiagID: diag::err_omp_depobj_single_clause_expected);
11577 return StmtError();
11578 } else if (Clauses.size() < 1) {
11579 Diag(Loc: Clauses[0]->getEndLoc(), DiagID: diag::err_omp_depobj_single_clause_expected);
11580 return StmtError();
11581 }
11582 return OMPDepobjDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11583}
11584
11585StmtResult SemaOpenMP::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
11586 SourceLocation StartLoc,
11587 SourceLocation EndLoc) {
11588 // Check that exactly one clause is specified.
11589 if (Clauses.size() != 1) {
11590 Diag(Loc: Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11591 DiagID: diag::err_omp_scan_single_clause_expected);
11592 return StmtError();
11593 }
11594 // Check that scan directive is used in the scope of the OpenMP loop body.
11595 if (Scope *S = DSAStack->getCurScope()) {
11596 Scope *ParentS = S->getParent();
11597 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11598 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11599 unsigned OMPVersion = getLangOpts().OpenMP;
11600 return StmtError(Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_device_directive)
11601 << getOpenMPDirectiveName(D: OMPD_scan, Ver: OMPVersion) << 5);
11602 }
11603 }
11604 // Check that only one instance of scan directives is used in the same outer
11605 // region.
11606 if (DSAStack->doesParentHasScanDirective()) {
11607 Diag(Loc: StartLoc, DiagID: diag::err_omp_several_directives_in_region) << "scan";
11608 Diag(DSAStack->getParentScanDirectiveLoc(),
11609 DiagID: diag::note_omp_previous_directive)
11610 << "scan";
11611 return StmtError();
11612 }
11613 DSAStack->setParentHasScanDirective(StartLoc);
11614 return OMPScanDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11615}
11616
11617StmtResult
11618SemaOpenMP::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
11619 Stmt *AStmt, SourceLocation StartLoc,
11620 SourceLocation EndLoc) {
11621 const OMPClause *DependFound = nullptr;
11622 const OMPClause *DependSourceClause = nullptr;
11623 const OMPClause *DependSinkClause = nullptr;
11624 const OMPClause *DoacrossFound = nullptr;
11625 const OMPClause *DoacrossSourceClause = nullptr;
11626 const OMPClause *DoacrossSinkClause = nullptr;
11627 bool ErrorFound = false;
11628 const OMPThreadsClause *TC = nullptr;
11629 const OMPSIMDClause *SC = nullptr;
11630 for (const OMPClause *C : Clauses) {
11631 auto DOC = dyn_cast<OMPDoacrossClause>(Val: C);
11632 auto DC = dyn_cast<OMPDependClause>(Val: C);
11633 if (DC || DOC) {
11634 DependFound = DC ? C : nullptr;
11635 DoacrossFound = DOC ? C : nullptr;
11636 OMPDoacrossKind ODK;
11637 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11638 (DOC && (ODK.isSource(C: DOC)))) {
11639 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11640 unsigned OMPVersion = getLangOpts().OpenMP;
11641 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_more_one_clause)
11642 << getOpenMPDirectiveName(D: OMPD_ordered, Ver: OMPVersion)
11643 << getOpenMPClauseNameForDiag(C: DC ? OMPC_depend : OMPC_doacross)
11644 << 2;
11645 ErrorFound = true;
11646 } else {
11647 if (DC)
11648 DependSourceClause = C;
11649 else
11650 DoacrossSourceClause = C;
11651 }
11652 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11653 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_sink_and_source_not_allowed)
11654 << (DC ? "depend" : "doacross") << 0;
11655 ErrorFound = true;
11656 }
11657 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11658 (DOC && (ODK.isSink(C: DOC) || ODK.isSinkIter(C: DOC)))) {
11659 if (DependSourceClause || DoacrossSourceClause) {
11660 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_sink_and_source_not_allowed)
11661 << (DC ? "depend" : "doacross") << 1;
11662 ErrorFound = true;
11663 }
11664 if (DC)
11665 DependSinkClause = C;
11666 else
11667 DoacrossSinkClause = C;
11668 }
11669 } else if (C->getClauseKind() == OMPC_threads) {
11670 TC = cast<OMPThreadsClause>(Val: C);
11671 } else if (C->getClauseKind() == OMPC_simd) {
11672 SC = cast<OMPSIMDClause>(Val: C);
11673 }
11674 }
11675 if (!ErrorFound && !SC &&
11676 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11677 // OpenMP [2.8.1,simd Construct, Restrictions]
11678 // An ordered construct with the simd clause is the only OpenMP construct
11679 // that can appear in the simd region.
11680 Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_simd)
11681 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11682 ErrorFound = true;
11683 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11684 SourceLocation Loc =
11685 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11686 Diag(Loc, DiagID: diag::err_omp_depend_clause_thread_simd)
11687 << getOpenMPClauseNameForDiag(C: DependFound ? OMPC_depend : OMPC_doacross)
11688 << getOpenMPClauseNameForDiag(C: TC ? TC->getClauseKind()
11689 : SC->getClauseKind());
11690 ErrorFound = true;
11691 } else if ((DependFound || DoacrossFound) &&
11692 !DSAStack->getParentOrderedRegionParam().first) {
11693 SourceLocation Loc =
11694 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11695 Diag(Loc, DiagID: diag::err_omp_ordered_directive_without_param)
11696 << getOpenMPClauseNameForDiag(C: DependFound ? OMPC_depend
11697 : OMPC_doacross);
11698 ErrorFound = true;
11699 } else if (TC || Clauses.empty()) {
11700 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11701 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11702 Diag(Loc: ErrLoc, DiagID: diag::err_omp_ordered_directive_with_param)
11703 << (TC != nullptr);
11704 Diag(Loc: Param->getBeginLoc(), DiagID: diag::note_omp_ordered_param) << 1;
11705 ErrorFound = true;
11706 }
11707 }
11708 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11709 return StmtError();
11710
11711 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11712 // During execution of an iteration of a worksharing-loop or a loop nest
11713 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11714 // must not execute more than one ordered region corresponding to an ordered
11715 // construct without a depend clause.
11716 if (!DependFound && !DoacrossFound) {
11717 if (DSAStack->doesParentHasOrderedDirective()) {
11718 Diag(Loc: StartLoc, DiagID: diag::err_omp_several_directives_in_region) << "ordered";
11719 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11720 DiagID: diag::note_omp_previous_directive)
11721 << "ordered";
11722 return StmtError();
11723 }
11724 DSAStack->setParentHasOrderedDirective(StartLoc);
11725 }
11726
11727 if (AStmt) {
11728 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11729
11730 SemaRef.setFunctionHasBranchProtectedScope();
11731 }
11732
11733 return OMPOrderedDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11734 AssociatedStmt: AStmt);
11735}
11736
11737namespace {
11738/// Helper class for checking expression in 'omp atomic [update]'
11739/// construct.
11740class OpenMPAtomicUpdateChecker {
11741 /// Error results for atomic update expressions.
11742 enum ExprAnalysisErrorCode {
11743 /// A statement is not an expression statement.
11744 NotAnExpression,
11745 /// Expression is not builtin binary or unary operation.
11746 NotABinaryOrUnaryExpression,
11747 /// Unary operation is not post-/pre- increment/decrement operation.
11748 NotAnUnaryIncDecExpression,
11749 /// An expression is not of scalar type.
11750 NotAScalarType,
11751 /// A binary operation is not an assignment operation.
11752 NotAnAssignmentOp,
11753 /// RHS part of the binary operation is not a binary expression.
11754 NotABinaryExpression,
11755 /// RHS part is not additive/multiplicative/shift/bitwise binary
11756 /// expression.
11757 NotABinaryOperator,
11758 /// RHS binary operation does not have reference to the updated LHS
11759 /// part.
11760 NotAnUpdateExpression,
11761 /// An expression contains semantical error not related to
11762 /// 'omp atomic [update]'
11763 NotAValidExpression,
11764 /// No errors is found.
11765 NoError
11766 };
11767 /// Reference to Sema.
11768 Sema &SemaRef;
11769 /// A location for note diagnostics (when error is found).
11770 SourceLocation NoteLoc;
11771 /// 'x' lvalue part of the source atomic expression.
11772 Expr *X;
11773 /// 'expr' rvalue part of the source atomic expression.
11774 Expr *E;
11775 /// Helper expression of the form
11776 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11777 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11778 Expr *UpdateExpr;
11779 /// Is 'x' a LHS in a RHS part of full update expression. It is
11780 /// important for non-associative operations.
11781 bool IsXLHSInRHSPart;
11782 BinaryOperatorKind Op;
11783 SourceLocation OpLoc;
11784 /// true if the source expression is a postfix unary operation, false
11785 /// if it is a prefix unary operation.
11786 bool IsPostfixUpdate;
11787
11788public:
11789 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11790 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11791 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11792 /// Check specified statement that it is suitable for 'atomic update'
11793 /// constructs and extract 'x', 'expr' and Operation from the original
11794 /// expression. If DiagId and NoteId == 0, then only check is performed
11795 /// without error notification.
11796 /// \param DiagId Diagnostic which should be emitted if error is found.
11797 /// \param NoteId Diagnostic note for the main error message.
11798 /// \return true if statement is not an update expression, false otherwise.
11799 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11800 /// Return the 'x' lvalue part of the source atomic expression.
11801 Expr *getX() const { return X; }
11802 /// Return the 'expr' rvalue part of the source atomic expression.
11803 Expr *getExpr() const { return E; }
11804 /// Return the update expression used in calculation of the updated
11805 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11806 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11807 Expr *getUpdateExpr() const { return UpdateExpr; }
11808 /// Return true if 'x' is LHS in RHS part of full update expression,
11809 /// false otherwise.
11810 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11811
11812 /// true if the source expression is a postfix unary operation, false
11813 /// if it is a prefix unary operation.
11814 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11815
11816private:
11817 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11818 unsigned NoteId = 0);
11819};
11820
11821bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11822 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11823 ExprAnalysisErrorCode ErrorFound = NoError;
11824 SourceLocation ErrorLoc, NoteLoc;
11825 SourceRange ErrorRange, NoteRange;
11826 // Allowed constructs are:
11827 // x = x binop expr;
11828 // x = expr binop x;
11829 if (AtomicBinOp->getOpcode() == BO_Assign) {
11830 X = AtomicBinOp->getLHS();
11831 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11832 Val: AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11833 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11834 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11835 AtomicInnerBinOp->isBitwiseOp()) {
11836 Op = AtomicInnerBinOp->getOpcode();
11837 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11838 Expr *LHS = AtomicInnerBinOp->getLHS();
11839 Expr *RHS = AtomicInnerBinOp->getRHS();
11840 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11841 X->IgnoreParenImpCasts()->Profile(ID&: XId, Context: SemaRef.getASTContext(),
11842 /*Canonical=*/true);
11843 LHS->IgnoreParenImpCasts()->Profile(ID&: LHSId, Context: SemaRef.getASTContext(),
11844 /*Canonical=*/true);
11845 RHS->IgnoreParenImpCasts()->Profile(ID&: RHSId, Context: SemaRef.getASTContext(),
11846 /*Canonical=*/true);
11847 if (XId == LHSId) {
11848 E = RHS;
11849 IsXLHSInRHSPart = true;
11850 } else if (XId == RHSId) {
11851 E = LHS;
11852 IsXLHSInRHSPart = false;
11853 } else {
11854 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11855 ErrorRange = AtomicInnerBinOp->getSourceRange();
11856 NoteLoc = X->getExprLoc();
11857 NoteRange = X->getSourceRange();
11858 ErrorFound = NotAnUpdateExpression;
11859 }
11860 } else {
11861 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11862 ErrorRange = AtomicInnerBinOp->getSourceRange();
11863 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11864 NoteRange = SourceRange(NoteLoc, NoteLoc);
11865 ErrorFound = NotABinaryOperator;
11866 }
11867 } else {
11868 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11869 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11870 ErrorFound = NotABinaryExpression;
11871 }
11872 } else {
11873 ErrorLoc = AtomicBinOp->getExprLoc();
11874 ErrorRange = AtomicBinOp->getSourceRange();
11875 NoteLoc = AtomicBinOp->getOperatorLoc();
11876 NoteRange = SourceRange(NoteLoc, NoteLoc);
11877 ErrorFound = NotAnAssignmentOp;
11878 }
11879 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11880 SemaRef.Diag(Loc: ErrorLoc, DiagID: DiagId) << ErrorRange;
11881 SemaRef.Diag(Loc: NoteLoc, DiagID: NoteId) << ErrorFound << NoteRange;
11882 return true;
11883 }
11884 if (SemaRef.CurContext->isDependentContext())
11885 E = X = UpdateExpr = nullptr;
11886 return ErrorFound != NoError;
11887}
11888
11889bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11890 unsigned NoteId) {
11891 ExprAnalysisErrorCode ErrorFound = NoError;
11892 SourceLocation ErrorLoc, NoteLoc;
11893 SourceRange ErrorRange, NoteRange;
11894 // Allowed constructs are:
11895 // x++;
11896 // x--;
11897 // ++x;
11898 // --x;
11899 // x binop= expr;
11900 // x = x binop expr;
11901 // x = expr binop x;
11902 if (auto *AtomicBody = dyn_cast<Expr>(Val: S)) {
11903 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11904 if (AtomicBody->getType()->isScalarType() ||
11905 AtomicBody->isInstantiationDependent()) {
11906 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11907 Val: AtomicBody->IgnoreParenImpCasts())) {
11908 // Check for Compound Assignment Operation
11909 Op = BinaryOperator::getOpForCompoundAssignment(
11910 Opc: AtomicCompAssignOp->getOpcode());
11911 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11912 E = AtomicCompAssignOp->getRHS();
11913 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11914 IsXLHSInRHSPart = true;
11915 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11916 Val: AtomicBody->IgnoreParenImpCasts())) {
11917 // Check for Binary Operation
11918 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11919 return true;
11920 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11921 Val: AtomicBody->IgnoreParenImpCasts())) {
11922 // Check for Unary Operation
11923 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11924 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11925 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11926 OpLoc = AtomicUnaryOp->getOperatorLoc();
11927 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11928 E = SemaRef.ActOnIntegerConstant(Loc: OpLoc, /*uint64_t Val=*/Val: 1).get();
11929 IsXLHSInRHSPart = true;
11930 } else {
11931 ErrorFound = NotAnUnaryIncDecExpression;
11932 ErrorLoc = AtomicUnaryOp->getExprLoc();
11933 ErrorRange = AtomicUnaryOp->getSourceRange();
11934 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11935 NoteRange = SourceRange(NoteLoc, NoteLoc);
11936 }
11937 } else if (!AtomicBody->isInstantiationDependent()) {
11938 ErrorFound = NotABinaryOrUnaryExpression;
11939 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11940 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11941 } else if (AtomicBody->containsErrors()) {
11942 ErrorFound = NotAValidExpression;
11943 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11944 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11945 }
11946 } else {
11947 ErrorFound = NotAScalarType;
11948 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11949 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11950 }
11951 } else {
11952 ErrorFound = NotAnExpression;
11953 NoteLoc = ErrorLoc = S->getBeginLoc();
11954 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11955 }
11956 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11957 SemaRef.Diag(Loc: ErrorLoc, DiagID: DiagId) << ErrorRange;
11958 SemaRef.Diag(Loc: NoteLoc, DiagID: NoteId) << ErrorFound << NoteRange;
11959 return true;
11960 }
11961 if (SemaRef.CurContext->isDependentContext())
11962 E = X = UpdateExpr = nullptr;
11963 if (ErrorFound == NoError && E && X) {
11964 // Build an update expression of form 'OpaqueValueExpr(x) binop
11965 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11966 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11967 auto *OVEX = new (SemaRef.getASTContext())
11968 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11969 auto *OVEExpr = new (SemaRef.getASTContext())
11970 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
11971 ExprResult Update =
11972 SemaRef.CreateBuiltinBinOp(OpLoc, Opc: Op, LHSExpr: IsXLHSInRHSPart ? OVEX : OVEExpr,
11973 RHSExpr: IsXLHSInRHSPart ? OVEExpr : OVEX);
11974 if (Update.isInvalid())
11975 return true;
11976 Update = SemaRef.PerformImplicitConversion(From: Update.get(), ToType: X->getType(),
11977 Action: AssignmentAction::Casting);
11978 if (Update.isInvalid())
11979 return true;
11980 UpdateExpr = Update.get();
11981 }
11982 return ErrorFound != NoError;
11983}
11984
11985/// Get the node id of the fixed point of an expression \a S.
11986llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11987 llvm::FoldingSetNodeID Id;
11988 S->IgnoreParenImpCasts()->Profile(ID&: Id, Context, Canonical: true);
11989 return Id;
11990}
11991
11992/// Check if two expressions are same.
11993bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11994 const Expr *RHS) {
11995 return getNodeId(Context, S: LHS) == getNodeId(Context, S: RHS);
11996}
11997
11998class OpenMPAtomicCompareChecker {
11999public:
12000 /// All kinds of errors that can occur in `atomic compare`
12001 enum ErrorTy {
12002 /// Empty compound statement.
12003 NoStmt = 0,
12004 /// More than one statement in a compound statement.
12005 MoreThanOneStmt,
12006 /// Not an assignment binary operator.
12007 NotAnAssignment,
12008 /// Not a conditional operator.
12009 NotCondOp,
12010 /// Wrong false expr. According to the spec, 'x' should be at the false
12011 /// expression of a conditional expression.
12012 WrongFalseExpr,
12013 /// The condition of a conditional expression is not a binary operator.
12014 NotABinaryOp,
12015 /// Invalid binary operator (not <, >, or ==).
12016 InvalidBinaryOp,
12017 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
12018 InvalidComparison,
12019 /// X is not a lvalue.
12020 XNotLValue,
12021 /// Not a scalar.
12022 NotScalar,
12023 /// Not an integer.
12024 NotInteger,
12025 /// 'else' statement is not expected.
12026 UnexpectedElse,
12027 /// Not an equality operator.
12028 NotEQ,
12029 /// Invalid assignment (not v == x).
12030 InvalidAssignment,
12031 /// Not if statement
12032 NotIfStmt,
12033 /// More than two statements in a compound statement.
12034 MoreThanTwoStmts,
12035 /// Not a compound statement.
12036 NotCompoundStmt,
12037 /// No else statement.
12038 NoElse,
12039 /// Not 'if (r)'.
12040 InvalidCondition,
12041 /// No error.
12042 NoError,
12043 };
12044
12045 struct ErrorInfoTy {
12046 ErrorTy Error;
12047 SourceLocation ErrorLoc;
12048 SourceRange ErrorRange;
12049 SourceLocation NoteLoc;
12050 SourceRange NoteRange;
12051 };
12052
12053 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
12054
12055 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
12056 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12057
12058 Expr *getX() const { return X; }
12059 Expr *getE() const { return E; }
12060 Expr *getD() const { return D; }
12061 Expr *getCond() const { return C; }
12062 bool isXBinopExpr() const { return IsXBinopExpr; }
12063
12064protected:
12065 /// Reference to ASTContext
12066 ASTContext &ContextRef;
12067 /// 'x' lvalue part of the source atomic expression.
12068 Expr *X = nullptr;
12069 /// 'expr' or 'e' rvalue part of the source atomic expression.
12070 Expr *E = nullptr;
12071 /// 'd' rvalue part of the source atomic expression.
12072 Expr *D = nullptr;
12073 /// 'cond' part of the source atomic expression. It is in one of the following
12074 /// forms:
12075 /// expr ordop x
12076 /// x ordop expr
12077 /// x == e
12078 /// e == x
12079 Expr *C = nullptr;
12080 /// True if the cond expr is in the form of 'x ordop expr'.
12081 bool IsXBinopExpr = true;
12082
12083 /// Check if it is a valid conditional update statement (cond-update-stmt).
12084 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
12085
12086 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
12087 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12088
12089 /// Check if all captured values have right type.
12090 bool checkType(ErrorInfoTy &ErrorInfo) const;
12091
12092 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
12093 bool ShouldBeLValue, bool ShouldBeInteger = false) {
12094 if (E->isInstantiationDependent())
12095 return true;
12096
12097 if (ShouldBeLValue && !E->isLValue()) {
12098 ErrorInfo.Error = ErrorTy::XNotLValue;
12099 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12100 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12101 return false;
12102 }
12103
12104 QualType QTy = E->getType();
12105 if (!QTy->isScalarType()) {
12106 ErrorInfo.Error = ErrorTy::NotScalar;
12107 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12108 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12109 return false;
12110 }
12111 if (ShouldBeInteger && !QTy->isIntegerType()) {
12112 ErrorInfo.Error = ErrorTy::NotInteger;
12113 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12114 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12115 return false;
12116 }
12117
12118 return true;
12119 }
12120};
12121
12122bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
12123 ErrorInfoTy &ErrorInfo) {
12124 auto *Then = S->getThen();
12125 if (auto *CS = dyn_cast<CompoundStmt>(Val: Then)) {
12126 if (CS->body_empty()) {
12127 ErrorInfo.Error = ErrorTy::NoStmt;
12128 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12129 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12130 return false;
12131 }
12132 if (CS->size() > 1) {
12133 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12134 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12135 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12136 return false;
12137 }
12138 Then = CS->body_front();
12139 }
12140
12141 auto *BO = dyn_cast<BinaryOperator>(Val: Then);
12142 if (!BO) {
12143 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12144 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12145 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12146 return false;
12147 }
12148 if (BO->getOpcode() != BO_Assign) {
12149 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12150 ErrorInfo.ErrorLoc = BO->getExprLoc();
12151 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12152 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12153 return false;
12154 }
12155
12156 X = BO->getLHS();
12157
12158 auto *Cond = dyn_cast<BinaryOperator>(Val: S->getCond());
12159 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: S->getCond());
12160 Expr *LHS = nullptr;
12161 Expr *RHS = nullptr;
12162 if (Cond) {
12163 LHS = Cond->getLHS();
12164 RHS = Cond->getRHS();
12165 } else if (Call) {
12166 LHS = Call->getArg(Arg: 0);
12167 RHS = Call->getArg(Arg: 1);
12168 } else {
12169 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12170 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12171 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12172 return false;
12173 }
12174
12175 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12176 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12177 C = S->getCond();
12178 D = BO->getRHS();
12179 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
12180 E = RHS;
12181 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12182 E = LHS;
12183 } else {
12184 ErrorInfo.Error = ErrorTy::InvalidComparison;
12185 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12186 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12187 S->getCond()->getSourceRange();
12188 return false;
12189 }
12190 } else if ((Cond &&
12191 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12192 (Call &&
12193 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12194 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12195 E = BO->getRHS();
12196 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS) &&
12197 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS)) {
12198 C = S->getCond();
12199 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: LHS) &&
12200 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12201 C = S->getCond();
12202 IsXBinopExpr = false;
12203 } else {
12204 ErrorInfo.Error = ErrorTy::InvalidComparison;
12205 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12206 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12207 S->getCond()->getSourceRange();
12208 return false;
12209 }
12210 } else {
12211 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12212 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12213 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12214 return false;
12215 }
12216
12217 if (S->getElse()) {
12218 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12219 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12220 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12221 return false;
12222 }
12223
12224 return true;
12225}
12226
12227bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12228 ErrorInfoTy &ErrorInfo) {
12229 auto *BO = dyn_cast<BinaryOperator>(Val: S);
12230 if (!BO) {
12231 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12232 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12233 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12234 return false;
12235 }
12236 if (BO->getOpcode() != BO_Assign) {
12237 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12238 ErrorInfo.ErrorLoc = BO->getExprLoc();
12239 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12240 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12241 return false;
12242 }
12243
12244 X = BO->getLHS();
12245
12246 auto *CO = dyn_cast<ConditionalOperator>(Val: BO->getRHS()->IgnoreParenImpCasts());
12247 if (!CO) {
12248 ErrorInfo.Error = ErrorTy::NotCondOp;
12249 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12250 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12251 return false;
12252 }
12253
12254 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: CO->getFalseExpr())) {
12255 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12256 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12257 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12258 CO->getFalseExpr()->getSourceRange();
12259 return false;
12260 }
12261
12262 auto *Cond = dyn_cast<BinaryOperator>(Val: CO->getCond());
12263 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: CO->getCond());
12264 Expr *LHS = nullptr;
12265 Expr *RHS = nullptr;
12266 if (Cond) {
12267 LHS = Cond->getLHS();
12268 RHS = Cond->getRHS();
12269 } else if (Call) {
12270 LHS = Call->getArg(Arg: 0);
12271 RHS = Call->getArg(Arg: 1);
12272 } else {
12273 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12274 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12275 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12276 CO->getCond()->getSourceRange();
12277 return false;
12278 }
12279
12280 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12281 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12282 C = CO->getCond();
12283 D = CO->getTrueExpr();
12284 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
12285 E = RHS;
12286 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12287 E = LHS;
12288 } else {
12289 ErrorInfo.Error = ErrorTy::InvalidComparison;
12290 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12291 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12292 CO->getCond()->getSourceRange();
12293 return false;
12294 }
12295 } else if ((Cond &&
12296 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12297 (Call &&
12298 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12299 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12300
12301 E = CO->getTrueExpr();
12302 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS) &&
12303 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS)) {
12304 C = CO->getCond();
12305 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: LHS) &&
12306 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12307 C = CO->getCond();
12308 IsXBinopExpr = false;
12309 } else {
12310 ErrorInfo.Error = ErrorTy::InvalidComparison;
12311 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12312 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12313 CO->getCond()->getSourceRange();
12314 return false;
12315 }
12316 } else {
12317 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12318 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12319 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12320 CO->getCond()->getSourceRange();
12321 return false;
12322 }
12323
12324 return true;
12325}
12326
12327bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12328 // 'x' and 'e' cannot be nullptr
12329 assert(X && E && "X and E cannot be nullptr");
12330
12331 if (!CheckValue(E: X, ErrorInfo, ShouldBeLValue: true))
12332 return false;
12333
12334 if (!CheckValue(E, ErrorInfo, ShouldBeLValue: false))
12335 return false;
12336
12337 if (D && !CheckValue(E: D, ErrorInfo, ShouldBeLValue: false))
12338 return false;
12339
12340 return true;
12341}
12342
12343bool OpenMPAtomicCompareChecker::checkStmt(
12344 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12345 auto *CS = dyn_cast<CompoundStmt>(Val: S);
12346 if (CS) {
12347 if (CS->body_empty()) {
12348 ErrorInfo.Error = ErrorTy::NoStmt;
12349 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12350 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12351 return false;
12352 }
12353
12354 if (CS->size() != 1) {
12355 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12356 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12357 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12358 return false;
12359 }
12360 S = CS->body_front();
12361 }
12362
12363 auto Res = false;
12364
12365 if (auto *IS = dyn_cast<IfStmt>(Val: S)) {
12366 // Check if the statement is in one of the following forms
12367 // (cond-update-stmt):
12368 // if (expr ordop x) { x = expr; }
12369 // if (x ordop expr) { x = expr; }
12370 // if (x == e) { x = d; }
12371 Res = checkCondUpdateStmt(S: IS, ErrorInfo);
12372 } else {
12373 // Check if the statement is in one of the following forms (cond-expr-stmt):
12374 // x = expr ordop x ? expr : x;
12375 // x = x ordop expr ? expr : x;
12376 // x = x == e ? d : x;
12377 Res = checkCondExprStmt(S, ErrorInfo);
12378 }
12379
12380 if (!Res)
12381 return false;
12382
12383 return checkType(ErrorInfo);
12384}
12385
12386class OpenMPAtomicCompareCaptureChecker final
12387 : public OpenMPAtomicCompareChecker {
12388public:
12389 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12390
12391 Expr *getV() const { return V; }
12392 Expr *getR() const { return R; }
12393 bool isFailOnly() const { return IsFailOnly; }
12394 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12395
12396 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12397 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12398
12399private:
12400 bool checkType(ErrorInfoTy &ErrorInfo);
12401
12402 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12403 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12404 // spec p.p. 82:
12405 // (1) { v = x; cond-update-stmt }
12406 // (2) { cond-update-stmt v = x; }
12407 // (3) if(x == e) { x = d; } else { v = x; }
12408 // (4) { r = x == e; if(r) { x = d; } }
12409 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12410
12411 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12412 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12413
12414 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12415 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12416 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12417
12418 /// 'v' lvalue part of the source atomic expression.
12419 Expr *V = nullptr;
12420 /// 'r' lvalue part of the source atomic expression.
12421 Expr *R = nullptr;
12422 /// If 'v' is only updated when the comparison fails.
12423 bool IsFailOnly = false;
12424 /// If original value of 'x' must be stored in 'v', not an updated one.
12425 bool IsPostfixUpdate = false;
12426};
12427
12428bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12429 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12430 return false;
12431
12432 if (V && !CheckValue(E: V, ErrorInfo, ShouldBeLValue: true))
12433 return false;
12434
12435 if (R && !CheckValue(E: R, ErrorInfo, ShouldBeLValue: true, ShouldBeInteger: true))
12436 return false;
12437
12438 return true;
12439}
12440
12441bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12442 ErrorInfoTy &ErrorInfo) {
12443 IsFailOnly = true;
12444
12445 auto *Then = S->getThen();
12446 if (auto *CS = dyn_cast<CompoundStmt>(Val: Then)) {
12447 if (CS->body_empty()) {
12448 ErrorInfo.Error = ErrorTy::NoStmt;
12449 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12450 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12451 return false;
12452 }
12453 if (CS->size() > 1) {
12454 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12455 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12456 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12457 return false;
12458 }
12459 Then = CS->body_front();
12460 }
12461
12462 auto *BO = dyn_cast<BinaryOperator>(Val: Then);
12463 if (!BO) {
12464 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12465 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12466 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12467 return false;
12468 }
12469 if (BO->getOpcode() != BO_Assign) {
12470 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12471 ErrorInfo.ErrorLoc = BO->getExprLoc();
12472 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12473 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12474 return false;
12475 }
12476
12477 X = BO->getLHS();
12478 D = BO->getRHS();
12479
12480 auto *Cond = dyn_cast<BinaryOperator>(Val: S->getCond());
12481 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: S->getCond());
12482 Expr *LHS = nullptr;
12483 Expr *RHS = nullptr;
12484 if (Cond) {
12485 LHS = Cond->getLHS();
12486 RHS = Cond->getRHS();
12487 } else if (Call) {
12488 LHS = Call->getArg(Arg: 0);
12489 RHS = Call->getArg(Arg: 1);
12490 } else {
12491 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12492 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12493 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12494 return false;
12495 }
12496 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12497 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12498 ErrorInfo.Error = ErrorTy::NotEQ;
12499 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12500 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12501 return false;
12502 }
12503
12504 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
12505 E = RHS;
12506 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12507 E = LHS;
12508 } else {
12509 ErrorInfo.Error = ErrorTy::InvalidComparison;
12510 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12511 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12512 return false;
12513 }
12514
12515 C = S->getCond();
12516
12517 if (!S->getElse()) {
12518 ErrorInfo.Error = ErrorTy::NoElse;
12519 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12520 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12521 return false;
12522 }
12523
12524 auto *Else = S->getElse();
12525 if (auto *CS = dyn_cast<CompoundStmt>(Val: Else)) {
12526 if (CS->body_empty()) {
12527 ErrorInfo.Error = ErrorTy::NoStmt;
12528 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12529 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12530 return false;
12531 }
12532 if (CS->size() > 1) {
12533 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12534 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12535 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12536 return false;
12537 }
12538 Else = CS->body_front();
12539 }
12540
12541 auto *ElseBO = dyn_cast<BinaryOperator>(Val: Else);
12542 if (!ElseBO) {
12543 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12544 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12545 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12546 return false;
12547 }
12548 if (ElseBO->getOpcode() != BO_Assign) {
12549 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12550 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12551 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12552 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12553 return false;
12554 }
12555
12556 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: ElseBO->getRHS())) {
12557 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12558 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12559 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12560 ElseBO->getRHS()->getSourceRange();
12561 return false;
12562 }
12563
12564 V = ElseBO->getLHS();
12565
12566 return checkType(ErrorInfo);
12567}
12568
12569bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12570 ErrorInfoTy &ErrorInfo) {
12571 // We don't check here as they should be already done before call this
12572 // function.
12573 auto *CS = cast<CompoundStmt>(Val: S);
12574 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12575 auto *S1 = cast<BinaryOperator>(Val: CS->body_front());
12576 auto *S2 = cast<IfStmt>(Val: CS->body_back());
12577 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12578
12579 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: S1->getLHS(), RHS: S2->getCond())) {
12580 ErrorInfo.Error = ErrorTy::InvalidCondition;
12581 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12582 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12583 return false;
12584 }
12585
12586 R = S1->getLHS();
12587
12588 auto *Then = S2->getThen();
12589 if (auto *ThenCS = dyn_cast<CompoundStmt>(Val: Then)) {
12590 if (ThenCS->body_empty()) {
12591 ErrorInfo.Error = ErrorTy::NoStmt;
12592 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12593 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12594 return false;
12595 }
12596 if (ThenCS->size() > 1) {
12597 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12598 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12599 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12600 return false;
12601 }
12602 Then = ThenCS->body_front();
12603 }
12604
12605 auto *ThenBO = dyn_cast<BinaryOperator>(Val: Then);
12606 if (!ThenBO) {
12607 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12608 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12609 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12610 return false;
12611 }
12612 if (ThenBO->getOpcode() != BO_Assign) {
12613 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12614 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12615 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12616 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12617 return false;
12618 }
12619
12620 X = ThenBO->getLHS();
12621 D = ThenBO->getRHS();
12622
12623 auto *BO = cast<BinaryOperator>(Val: S1->getRHS()->IgnoreImpCasts());
12624 if (BO->getOpcode() != BO_EQ) {
12625 ErrorInfo.Error = ErrorTy::NotEQ;
12626 ErrorInfo.ErrorLoc = BO->getExprLoc();
12627 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12628 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12629 return false;
12630 }
12631
12632 C = BO;
12633
12634 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: BO->getLHS())) {
12635 E = BO->getRHS();
12636 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: BO->getRHS())) {
12637 E = BO->getLHS();
12638 } else {
12639 ErrorInfo.Error = ErrorTy::InvalidComparison;
12640 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12641 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12642 return false;
12643 }
12644
12645 if (S2->getElse()) {
12646 IsFailOnly = true;
12647
12648 auto *Else = S2->getElse();
12649 if (auto *ElseCS = dyn_cast<CompoundStmt>(Val: Else)) {
12650 if (ElseCS->body_empty()) {
12651 ErrorInfo.Error = ErrorTy::NoStmt;
12652 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12653 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12654 return false;
12655 }
12656 if (ElseCS->size() > 1) {
12657 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12658 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12659 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12660 return false;
12661 }
12662 Else = ElseCS->body_front();
12663 }
12664
12665 auto *ElseBO = dyn_cast<BinaryOperator>(Val: Else);
12666 if (!ElseBO) {
12667 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12668 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12669 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12670 return false;
12671 }
12672 if (ElseBO->getOpcode() != BO_Assign) {
12673 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12674 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12675 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12676 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12677 return false;
12678 }
12679 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: ElseBO->getRHS())) {
12680 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12681 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12682 ErrorInfo.NoteLoc = X->getExprLoc();
12683 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12684 ErrorInfo.NoteRange = X->getSourceRange();
12685 return false;
12686 }
12687
12688 V = ElseBO->getLHS();
12689 }
12690
12691 return checkType(ErrorInfo);
12692}
12693
12694bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12695 ErrorInfoTy &ErrorInfo) {
12696 // if(x == e) { x = d; } else { v = x; }
12697 if (auto *IS = dyn_cast<IfStmt>(Val: S))
12698 return checkForm3(S: IS, ErrorInfo);
12699
12700 auto *CS = dyn_cast<CompoundStmt>(Val: S);
12701 if (!CS) {
12702 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12703 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12704 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12705 return false;
12706 }
12707 if (CS->body_empty()) {
12708 ErrorInfo.Error = ErrorTy::NoStmt;
12709 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12710 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12711 return false;
12712 }
12713
12714 // { if(x == e) { x = d; } else { v = x; } }
12715 if (CS->size() == 1) {
12716 auto *IS = dyn_cast<IfStmt>(Val: CS->body_front());
12717 if (!IS) {
12718 ErrorInfo.Error = ErrorTy::NotIfStmt;
12719 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12720 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12721 CS->body_front()->getSourceRange();
12722 return false;
12723 }
12724
12725 return checkForm3(S: IS, ErrorInfo);
12726 } else if (CS->size() == 2) {
12727 auto *S1 = CS->body_front();
12728 auto *S2 = CS->body_back();
12729
12730 Stmt *UpdateStmt = nullptr;
12731 Stmt *CondUpdateStmt = nullptr;
12732 Stmt *CondExprStmt = nullptr;
12733
12734 if (auto *BO = dyn_cast<BinaryOperator>(Val: S1)) {
12735 // It could be one of the following cases:
12736 // { v = x; cond-update-stmt }
12737 // { v = x; cond-expr-stmt }
12738 // { cond-expr-stmt; v = x; }
12739 // form 45
12740 if (isa<BinaryOperator>(Val: BO->getRHS()->IgnoreImpCasts()) ||
12741 isa<ConditionalOperator>(Val: BO->getRHS()->IgnoreImpCasts())) {
12742 // check if form 45
12743 if (isa<IfStmt>(Val: S2))
12744 return checkForm45(S: CS, ErrorInfo);
12745 // { cond-expr-stmt; v = x; }
12746 CondExprStmt = S1;
12747 UpdateStmt = S2;
12748 } else {
12749 IsPostfixUpdate = true;
12750 UpdateStmt = S1;
12751 if (isa<IfStmt>(Val: S2)) {
12752 // { v = x; cond-update-stmt }
12753 CondUpdateStmt = S2;
12754 } else {
12755 // { v = x; cond-expr-stmt }
12756 CondExprStmt = S2;
12757 }
12758 }
12759 } else {
12760 // { cond-update-stmt v = x; }
12761 UpdateStmt = S2;
12762 CondUpdateStmt = S1;
12763 }
12764
12765 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12766 auto *IS = dyn_cast<IfStmt>(Val: CUS);
12767 if (!IS) {
12768 ErrorInfo.Error = ErrorTy::NotIfStmt;
12769 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12770 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12771 return false;
12772 }
12773
12774 return checkCondUpdateStmt(S: IS, ErrorInfo);
12775 };
12776
12777 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12778 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12779 auto *BO = dyn_cast<BinaryOperator>(Val: US);
12780 if (!BO) {
12781 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12782 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12783 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12784 return false;
12785 }
12786 if (BO->getOpcode() != BO_Assign) {
12787 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12788 ErrorInfo.ErrorLoc = BO->getExprLoc();
12789 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12790 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12791 return false;
12792 }
12793 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: this->X, RHS: BO->getRHS())) {
12794 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12795 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12796 ErrorInfo.NoteLoc = this->X->getExprLoc();
12797 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12798 ErrorInfo.NoteRange = this->X->getSourceRange();
12799 return false;
12800 }
12801
12802 this->V = BO->getLHS();
12803
12804 return true;
12805 };
12806
12807 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12808 return false;
12809 if (CondExprStmt && !checkCondExprStmt(S: CondExprStmt, ErrorInfo))
12810 return false;
12811 if (!CheckUpdateStmt(UpdateStmt))
12812 return false;
12813 } else {
12814 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12815 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12816 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12817 return false;
12818 }
12819
12820 return checkType(ErrorInfo);
12821}
12822} // namespace
12823
12824StmtResult SemaOpenMP::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
12825 Stmt *AStmt,
12826 SourceLocation StartLoc,
12827 SourceLocation EndLoc) {
12828 ASTContext &Context = getASTContext();
12829 unsigned OMPVersion = getLangOpts().OpenMP;
12830 // Register location of the first atomic directive.
12831 DSAStack->addAtomicDirectiveLoc(Loc: StartLoc);
12832 if (!AStmt)
12833 return StmtError();
12834
12835 // 1.2.2 OpenMP Language Terminology
12836 // Structured block - An executable statement with a single entry at the
12837 // top and a single exit at the bottom.
12838 // The point of exit cannot be a branch out of the structured block.
12839 // longjmp() and throw() must not violate the entry/exit criteria.
12840 OpenMPClauseKind AtomicKind = OMPC_unknown;
12841 SourceLocation AtomicKindLoc;
12842 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12843 SourceLocation MemOrderLoc;
12844 bool MutexClauseEncountered = false;
12845 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12846 for (const OMPClause *C : Clauses) {
12847 switch (C->getClauseKind()) {
12848 case OMPC_read:
12849 case OMPC_write:
12850 case OMPC_update:
12851 MutexClauseEncountered = true;
12852 [[fallthrough]];
12853 case OMPC_capture:
12854 case OMPC_compare: {
12855 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12856 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_several_clauses)
12857 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12858 Diag(Loc: AtomicKindLoc, DiagID: diag::note_omp_previous_mem_order_clause)
12859 << getOpenMPClauseNameForDiag(C: AtomicKind);
12860 } else {
12861 AtomicKind = C->getClauseKind();
12862 AtomicKindLoc = C->getBeginLoc();
12863 if (!EncounteredAtomicKinds.insert(V: C->getClauseKind()).second) {
12864 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_several_clauses)
12865 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12866 Diag(Loc: AtomicKindLoc, DiagID: diag::note_omp_previous_mem_order_clause)
12867 << getOpenMPClauseNameForDiag(C: AtomicKind);
12868 }
12869 }
12870 break;
12871 }
12872 case OMPC_weak:
12873 case OMPC_fail: {
12874 if (!EncounteredAtomicKinds.contains(V: OMPC_compare)) {
12875 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_no_compare)
12876 << getOpenMPClauseNameForDiag(C: C->getClauseKind())
12877 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12878 return StmtError();
12879 }
12880 break;
12881 }
12882 case OMPC_seq_cst:
12883 case OMPC_acq_rel:
12884 case OMPC_acquire:
12885 case OMPC_release:
12886 case OMPC_relaxed: {
12887 if (MemOrderKind != OMPC_unknown) {
12888 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_several_mem_order_clauses)
12889 << getOpenMPDirectiveName(D: OMPD_atomic, Ver: OMPVersion) << 0
12890 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12891 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
12892 << getOpenMPClauseNameForDiag(C: MemOrderKind);
12893 } else {
12894 MemOrderKind = C->getClauseKind();
12895 MemOrderLoc = C->getBeginLoc();
12896 }
12897 break;
12898 }
12899 // The following clauses are allowed, but we don't need to do anything here.
12900 case OMPC_hint:
12901 break;
12902 default:
12903 llvm_unreachable("unknown clause is encountered");
12904 }
12905 }
12906 bool IsCompareCapture = false;
12907 if (EncounteredAtomicKinds.contains(V: OMPC_compare) &&
12908 EncounteredAtomicKinds.contains(V: OMPC_capture)) {
12909 IsCompareCapture = true;
12910 AtomicKind = OMPC_compare;
12911 }
12912 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12913 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12914 // release.
12915 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12916 // acquire.
12917 // If atomic-clause is update or not present then memory-order-clause must not
12918 // be acq_rel or acquire.
12919 if ((AtomicKind == OMPC_read &&
12920 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12921 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12922 AtomicKind == OMPC_unknown) &&
12923 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12924 SourceLocation Loc = AtomicKindLoc;
12925 if (AtomicKind == OMPC_unknown)
12926 Loc = StartLoc;
12927 Diag(Loc, DiagID: diag::err_omp_atomic_incompatible_mem_order_clause)
12928 << getOpenMPClauseNameForDiag(C: AtomicKind)
12929 << (AtomicKind == OMPC_unknown ? 1 : 0)
12930 << getOpenMPClauseNameForDiag(C: MemOrderKind);
12931 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
12932 << getOpenMPClauseNameForDiag(C: MemOrderKind);
12933 }
12934
12935 Stmt *Body = AStmt;
12936 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: Body))
12937 Body = EWC->getSubExpr();
12938
12939 Expr *X = nullptr;
12940 Expr *V = nullptr;
12941 Expr *E = nullptr;
12942 Expr *UE = nullptr;
12943 Expr *D = nullptr;
12944 Expr *CE = nullptr;
12945 Expr *R = nullptr;
12946 bool IsXLHSInRHSPart = false;
12947 bool IsPostfixUpdate = false;
12948 bool IsFailOnly = false;
12949 // OpenMP [2.12.6, atomic Construct]
12950 // In the next expressions:
12951 // * x and v (as applicable) are both l-value expressions with scalar type.
12952 // * During the execution of an atomic region, multiple syntactic
12953 // occurrences of x must designate the same storage location.
12954 // * Neither of v and expr (as applicable) may access the storage location
12955 // designated by x.
12956 // * Neither of x and expr (as applicable) may access the storage location
12957 // designated by v.
12958 // * expr is an expression with scalar type.
12959 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12960 // * binop, binop=, ++, and -- are not overloaded operators.
12961 // * The expression x binop expr must be numerically equivalent to x binop
12962 // (expr). This requirement is satisfied if the operators in expr have
12963 // precedence greater than binop, or by using parentheses around expr or
12964 // subexpressions of expr.
12965 // * The expression expr binop x must be numerically equivalent to (expr)
12966 // binop x. This requirement is satisfied if the operators in expr have
12967 // precedence equal to or greater than binop, or by using parentheses around
12968 // expr or subexpressions of expr.
12969 // * For forms that allow multiple occurrences of x, the number of times
12970 // that x is evaluated is unspecified.
12971 if (AtomicKind == OMPC_read) {
12972 enum {
12973 NotAnExpression,
12974 NotAnAssignmentOp,
12975 NotAScalarType,
12976 NotAnLValue,
12977 NoError
12978 } ErrorFound = NoError;
12979 SourceLocation ErrorLoc, NoteLoc;
12980 SourceRange ErrorRange, NoteRange;
12981 // If clause is read:
12982 // v = x;
12983 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
12984 const auto *AtomicBinOp =
12985 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
12986 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12987 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12988 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12989 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12990 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12991 if (!X->isLValue() || !V->isLValue()) {
12992 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12993 ErrorFound = NotAnLValue;
12994 ErrorLoc = AtomicBinOp->getExprLoc();
12995 ErrorRange = AtomicBinOp->getSourceRange();
12996 NoteLoc = NotLValueExpr->getExprLoc();
12997 NoteRange = NotLValueExpr->getSourceRange();
12998 }
12999 } else if (!X->isInstantiationDependent() ||
13000 !V->isInstantiationDependent()) {
13001 const Expr *NotScalarExpr =
13002 (X->isInstantiationDependent() || X->getType()->isScalarType())
13003 ? V
13004 : X;
13005 ErrorFound = NotAScalarType;
13006 ErrorLoc = AtomicBinOp->getExprLoc();
13007 ErrorRange = AtomicBinOp->getSourceRange();
13008 NoteLoc = NotScalarExpr->getExprLoc();
13009 NoteRange = NotScalarExpr->getSourceRange();
13010 }
13011 } else if (!AtomicBody->isInstantiationDependent()) {
13012 ErrorFound = NotAnAssignmentOp;
13013 ErrorLoc = AtomicBody->getExprLoc();
13014 ErrorRange = AtomicBody->getSourceRange();
13015 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13016 : AtomicBody->getExprLoc();
13017 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13018 : AtomicBody->getSourceRange();
13019 }
13020 } else {
13021 ErrorFound = NotAnExpression;
13022 NoteLoc = ErrorLoc = Body->getBeginLoc();
13023 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
13024 }
13025 if (ErrorFound != NoError) {
13026 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_read_not_expression_statement)
13027 << ErrorRange;
13028 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_read_write)
13029 << ErrorFound << NoteRange;
13030 return StmtError();
13031 }
13032 if (SemaRef.CurContext->isDependentContext())
13033 V = X = nullptr;
13034 } else if (AtomicKind == OMPC_write) {
13035 enum {
13036 NotAnExpression,
13037 NotAnAssignmentOp,
13038 NotAScalarType,
13039 NotAnLValue,
13040 NoError
13041 } ErrorFound = NoError;
13042 SourceLocation ErrorLoc, NoteLoc;
13043 SourceRange ErrorRange, NoteRange;
13044 // If clause is write:
13045 // x = expr;
13046 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
13047 const auto *AtomicBinOp =
13048 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
13049 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13050 X = AtomicBinOp->getLHS();
13051 E = AtomicBinOp->getRHS();
13052 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
13053 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
13054 if (!X->isLValue()) {
13055 ErrorFound = NotAnLValue;
13056 ErrorLoc = AtomicBinOp->getExprLoc();
13057 ErrorRange = AtomicBinOp->getSourceRange();
13058 NoteLoc = X->getExprLoc();
13059 NoteRange = X->getSourceRange();
13060 }
13061 } else if (!X->isInstantiationDependent() ||
13062 !E->isInstantiationDependent()) {
13063 const Expr *NotScalarExpr =
13064 (X->isInstantiationDependent() || X->getType()->isScalarType())
13065 ? E
13066 : X;
13067 ErrorFound = NotAScalarType;
13068 ErrorLoc = AtomicBinOp->getExprLoc();
13069 ErrorRange = AtomicBinOp->getSourceRange();
13070 NoteLoc = NotScalarExpr->getExprLoc();
13071 NoteRange = NotScalarExpr->getSourceRange();
13072 }
13073 } else if (!AtomicBody->isInstantiationDependent()) {
13074 ErrorFound = NotAnAssignmentOp;
13075 ErrorLoc = AtomicBody->getExprLoc();
13076 ErrorRange = AtomicBody->getSourceRange();
13077 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13078 : AtomicBody->getExprLoc();
13079 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13080 : AtomicBody->getSourceRange();
13081 }
13082 } else {
13083 ErrorFound = NotAnExpression;
13084 NoteLoc = ErrorLoc = Body->getBeginLoc();
13085 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
13086 }
13087 if (ErrorFound != NoError) {
13088 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_write_not_expression_statement)
13089 << ErrorRange;
13090 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_read_write)
13091 << ErrorFound << NoteRange;
13092 return StmtError();
13093 }
13094 if (SemaRef.CurContext->isDependentContext())
13095 E = X = nullptr;
13096 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
13097 // If clause is update:
13098 // x++;
13099 // x--;
13100 // ++x;
13101 // --x;
13102 // x binop= expr;
13103 // x = x binop expr;
13104 // x = expr binop x;
13105 OpenMPAtomicUpdateChecker Checker(SemaRef);
13106 if (Checker.checkStatement(
13107 S: Body,
13108 DiagId: (AtomicKind == OMPC_update)
13109 ? diag::err_omp_atomic_update_not_expression_statement
13110 : diag::err_omp_atomic_not_expression_statement,
13111 NoteId: diag::note_omp_atomic_update))
13112 return StmtError();
13113 if (!SemaRef.CurContext->isDependentContext()) {
13114 E = Checker.getExpr();
13115 X = Checker.getX();
13116 UE = Checker.getUpdateExpr();
13117 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13118 }
13119 } else if (AtomicKind == OMPC_capture) {
13120 enum {
13121 NotAnAssignmentOp,
13122 NotACompoundStatement,
13123 NotTwoSubstatements,
13124 NotASpecificExpression,
13125 NoError
13126 } ErrorFound = NoError;
13127 SourceLocation ErrorLoc, NoteLoc;
13128 SourceRange ErrorRange, NoteRange;
13129 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
13130 // If clause is a capture:
13131 // v = x++;
13132 // v = x--;
13133 // v = ++x;
13134 // v = --x;
13135 // v = x binop= expr;
13136 // v = x = x binop expr;
13137 // v = x = expr binop x;
13138 const auto *AtomicBinOp =
13139 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
13140 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13141 V = AtomicBinOp->getLHS();
13142 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
13143 OpenMPAtomicUpdateChecker Checker(SemaRef);
13144 if (Checker.checkStatement(
13145 S: Body, DiagId: diag::err_omp_atomic_capture_not_expression_statement,
13146 NoteId: diag::note_omp_atomic_update))
13147 return StmtError();
13148 E = Checker.getExpr();
13149 X = Checker.getX();
13150 UE = Checker.getUpdateExpr();
13151 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13152 IsPostfixUpdate = Checker.isPostfixUpdate();
13153 } else if (!AtomicBody->isInstantiationDependent()) {
13154 ErrorLoc = AtomicBody->getExprLoc();
13155 ErrorRange = AtomicBody->getSourceRange();
13156 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13157 : AtomicBody->getExprLoc();
13158 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13159 : AtomicBody->getSourceRange();
13160 ErrorFound = NotAnAssignmentOp;
13161 }
13162 if (ErrorFound != NoError) {
13163 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_capture_not_expression_statement)
13164 << ErrorRange;
13165 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13166 return StmtError();
13167 }
13168 if (SemaRef.CurContext->isDependentContext())
13169 UE = V = E = X = nullptr;
13170 } else {
13171 // If clause is a capture:
13172 // { v = x; x = expr; }
13173 // { v = x; x++; }
13174 // { v = x; x--; }
13175 // { v = x; ++x; }
13176 // { v = x; --x; }
13177 // { v = x; x binop= expr; }
13178 // { v = x; x = x binop expr; }
13179 // { v = x; x = expr binop x; }
13180 // { x++; v = x; }
13181 // { x--; v = x; }
13182 // { ++x; v = x; }
13183 // { --x; v = x; }
13184 // { x binop= expr; v = x; }
13185 // { x = x binop expr; v = x; }
13186 // { x = expr binop x; v = x; }
13187 if (auto *CS = dyn_cast<CompoundStmt>(Val: Body)) {
13188 // Check that this is { expr1; expr2; }
13189 if (CS->size() == 2) {
13190 Stmt *First = CS->body_front();
13191 Stmt *Second = CS->body_back();
13192 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: First))
13193 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13194 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: Second))
13195 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13196 // Need to find what subexpression is 'v' and what is 'x'.
13197 OpenMPAtomicUpdateChecker Checker(SemaRef);
13198 bool IsUpdateExprFound = !Checker.checkStatement(S: Second);
13199 BinaryOperator *BinOp = nullptr;
13200 if (IsUpdateExprFound) {
13201 BinOp = dyn_cast<BinaryOperator>(Val: First);
13202 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13203 }
13204 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
13205 // { v = x; x++; }
13206 // { v = x; x--; }
13207 // { v = x; ++x; }
13208 // { v = x; --x; }
13209 // { v = x; x binop= expr; }
13210 // { v = x; x = x binop expr; }
13211 // { v = x; x = expr binop x; }
13212 // Check that the first expression has form v = x.
13213 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13214 llvm::FoldingSetNodeID XId, PossibleXId;
13215 Checker.getX()->Profile(ID&: XId, Context, /*Canonical=*/true);
13216 PossibleX->Profile(ID&: PossibleXId, Context, /*Canonical=*/true);
13217 IsUpdateExprFound = XId == PossibleXId;
13218 if (IsUpdateExprFound) {
13219 V = BinOp->getLHS();
13220 X = Checker.getX();
13221 E = Checker.getExpr();
13222 UE = Checker.getUpdateExpr();
13223 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13224 IsPostfixUpdate = true;
13225 }
13226 }
13227 if (!IsUpdateExprFound) {
13228 IsUpdateExprFound = !Checker.checkStatement(S: First);
13229 BinOp = nullptr;
13230 if (IsUpdateExprFound) {
13231 BinOp = dyn_cast<BinaryOperator>(Val: Second);
13232 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13233 }
13234 if (IsUpdateExprFound &&
13235 !SemaRef.CurContext->isDependentContext()) {
13236 // { x++; v = x; }
13237 // { x--; v = x; }
13238 // { ++x; v = x; }
13239 // { --x; v = x; }
13240 // { x binop= expr; v = x; }
13241 // { x = x binop expr; v = x; }
13242 // { x = expr binop x; v = x; }
13243 // Check that the second expression has form v = x.
13244 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13245 llvm::FoldingSetNodeID XId, PossibleXId;
13246 Checker.getX()->Profile(ID&: XId, Context, /*Canonical=*/true);
13247 PossibleX->Profile(ID&: PossibleXId, Context, /*Canonical=*/true);
13248 IsUpdateExprFound = XId == PossibleXId;
13249 if (IsUpdateExprFound) {
13250 V = BinOp->getLHS();
13251 X = Checker.getX();
13252 E = Checker.getExpr();
13253 UE = Checker.getUpdateExpr();
13254 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13255 IsPostfixUpdate = false;
13256 }
13257 }
13258 }
13259 if (!IsUpdateExprFound) {
13260 // { v = x; x = expr; }
13261 auto *FirstExpr = dyn_cast<Expr>(Val: First);
13262 auto *SecondExpr = dyn_cast<Expr>(Val: Second);
13263 if (!FirstExpr || !SecondExpr ||
13264 !(FirstExpr->isInstantiationDependent() ||
13265 SecondExpr->isInstantiationDependent())) {
13266 auto *FirstBinOp = dyn_cast<BinaryOperator>(Val: First);
13267 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13268 ErrorFound = NotAnAssignmentOp;
13269 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13270 : First->getBeginLoc();
13271 NoteRange = ErrorRange = FirstBinOp
13272 ? FirstBinOp->getSourceRange()
13273 : SourceRange(ErrorLoc, ErrorLoc);
13274 } else {
13275 auto *SecondBinOp = dyn_cast<BinaryOperator>(Val: Second);
13276 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13277 ErrorFound = NotAnAssignmentOp;
13278 NoteLoc = ErrorLoc = SecondBinOp
13279 ? SecondBinOp->getOperatorLoc()
13280 : Second->getBeginLoc();
13281 NoteRange = ErrorRange =
13282 SecondBinOp ? SecondBinOp->getSourceRange()
13283 : SourceRange(ErrorLoc, ErrorLoc);
13284 } else {
13285 Expr *PossibleXRHSInFirst =
13286 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13287 Expr *PossibleXLHSInSecond =
13288 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13289 llvm::FoldingSetNodeID X1Id, X2Id;
13290 PossibleXRHSInFirst->Profile(ID&: X1Id, Context,
13291 /*Canonical=*/true);
13292 PossibleXLHSInSecond->Profile(ID&: X2Id, Context,
13293 /*Canonical=*/true);
13294 IsUpdateExprFound = X1Id == X2Id;
13295 if (IsUpdateExprFound) {
13296 V = FirstBinOp->getLHS();
13297 X = SecondBinOp->getLHS();
13298 E = SecondBinOp->getRHS();
13299 UE = nullptr;
13300 IsXLHSInRHSPart = false;
13301 IsPostfixUpdate = true;
13302 } else {
13303 ErrorFound = NotASpecificExpression;
13304 ErrorLoc = FirstBinOp->getExprLoc();
13305 ErrorRange = FirstBinOp->getSourceRange();
13306 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13307 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13308 }
13309 }
13310 }
13311 }
13312 }
13313 } else {
13314 NoteLoc = ErrorLoc = Body->getBeginLoc();
13315 NoteRange = ErrorRange =
13316 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13317 ErrorFound = NotTwoSubstatements;
13318 }
13319 } else {
13320 NoteLoc = ErrorLoc = Body->getBeginLoc();
13321 NoteRange = ErrorRange =
13322 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13323 ErrorFound = NotACompoundStatement;
13324 }
13325 }
13326 if (ErrorFound != NoError) {
13327 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_capture_not_compound_statement)
13328 << ErrorRange;
13329 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13330 return StmtError();
13331 }
13332 if (SemaRef.CurContext->isDependentContext())
13333 UE = V = E = X = nullptr;
13334 } else if (AtomicKind == OMPC_compare) {
13335 if (IsCompareCapture) {
13336 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13337 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
13338 if (!Checker.checkStmt(S: Body, ErrorInfo)) {
13339 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_compare_capture)
13340 << ErrorInfo.ErrorRange;
13341 Diag(Loc: ErrorInfo.NoteLoc, DiagID: diag::note_omp_atomic_compare)
13342 << ErrorInfo.Error << ErrorInfo.NoteRange;
13343 return StmtError();
13344 }
13345 X = Checker.getX();
13346 E = Checker.getE();
13347 D = Checker.getD();
13348 CE = Checker.getCond();
13349 V = Checker.getV();
13350 R = Checker.getR();
13351 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13352 IsXLHSInRHSPart = Checker.isXBinopExpr();
13353 IsFailOnly = Checker.isFailOnly();
13354 IsPostfixUpdate = Checker.isPostfixUpdate();
13355 } else {
13356 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13357 OpenMPAtomicCompareChecker Checker(SemaRef);
13358 if (!Checker.checkStmt(S: Body, ErrorInfo)) {
13359 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_compare)
13360 << ErrorInfo.ErrorRange;
13361 Diag(Loc: ErrorInfo.NoteLoc, DiagID: diag::note_omp_atomic_compare)
13362 << ErrorInfo.Error << ErrorInfo.NoteRange;
13363 return StmtError();
13364 }
13365 X = Checker.getX();
13366 E = Checker.getE();
13367 D = Checker.getD();
13368 CE = Checker.getCond();
13369 // The weak clause may only appear if the resulting atomic operation is
13370 // an atomic conditional update for which the comparison tests for
13371 // equality. It was not possible to do this check in
13372 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13373 // could not be performed (Clauses are not available).
13374 auto *It = find_if(Range&: Clauses, P: [](OMPClause *C) {
13375 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13376 });
13377 if (It != Clauses.end()) {
13378 auto *Cond = dyn_cast<BinaryOperator>(Val: CE);
13379 if (Cond->getOpcode() != BO_EQ) {
13380 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13381 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13382 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13383 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13384
13385 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_weak_no_equality)
13386 << ErrorInfo.ErrorRange;
13387 return StmtError();
13388 }
13389 }
13390 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13391 IsXLHSInRHSPart = Checker.isXBinopExpr();
13392 }
13393 }
13394
13395 SemaRef.setFunctionHasBranchProtectedScope();
13396
13397 return OMPAtomicDirective::Create(
13398 C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
13399 Exprs: {.X: X, .V: V, .R: R, .E: E, .UE: UE, .D: D, .Cond: CE, .IsXLHSInRHSPart: IsXLHSInRHSPart, .IsPostfixUpdate: IsPostfixUpdate, .IsFailOnly: IsFailOnly});
13400}
13401
13402StmtResult SemaOpenMP::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
13403 Stmt *AStmt,
13404 SourceLocation StartLoc,
13405 SourceLocation EndLoc) {
13406 if (!AStmt)
13407 return StmtError();
13408
13409 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_target, AStmt);
13410
13411 // OpenMP [2.16, Nesting of Regions]
13412 // If specified, a teams construct must be contained within a target
13413 // construct. That target construct must contain no statements or directives
13414 // outside of the teams construct.
13415 if (DSAStack->hasInnerTeamsRegion()) {
13416 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13417 bool OMPTeamsFound = true;
13418 if (const auto *CS = dyn_cast<CompoundStmt>(Val: S)) {
13419 auto I = CS->body_begin();
13420 while (I != CS->body_end()) {
13421 const auto *OED = dyn_cast<OMPExecutableDirective>(Val: *I);
13422 bool IsTeams = OED && isOpenMPTeamsDirective(DKind: OED->getDirectiveKind());
13423 if (!IsTeams || I != CS->body_begin()) {
13424 OMPTeamsFound = false;
13425 if (IsTeams && I != CS->body_begin()) {
13426 // This is the two teams case. Since the InnerTeamsRegionLoc will
13427 // point to this second one reset the iterator to the other teams.
13428 --I;
13429 }
13430 break;
13431 }
13432 ++I;
13433 }
13434 assert(I != CS->body_end() && "Not found statement");
13435 S = *I;
13436 } else {
13437 const auto *OED = dyn_cast<OMPExecutableDirective>(Val: S);
13438 OMPTeamsFound = OED && isOpenMPTeamsDirective(DKind: OED->getDirectiveKind());
13439 }
13440 if (!OMPTeamsFound) {
13441 Diag(Loc: StartLoc, DiagID: diag::err_omp_target_contains_not_only_teams);
13442 Diag(DSAStack->getInnerTeamsRegionLoc(),
13443 DiagID: diag::note_omp_nested_teams_construct_here);
13444 Diag(Loc: S->getBeginLoc(), DiagID: diag::note_omp_nested_statement_here)
13445 << isa<OMPExecutableDirective>(Val: S);
13446 return StmtError();
13447 }
13448 }
13449
13450 return OMPTargetDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
13451 AssociatedStmt: AStmt);
13452}
13453
13454StmtResult SemaOpenMP::ActOnOpenMPTargetParallelDirective(
13455 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13456 SourceLocation EndLoc) {
13457 if (!AStmt)
13458 return StmtError();
13459
13460 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel, AStmt);
13461
13462 return OMPTargetParallelDirective::Create(
13463 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
13464 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13465}
13466
13467StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForDirective(
13468 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13469 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13470 if (!AStmt)
13471 return StmtError();
13472
13473 CapturedStmt *CS =
13474 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_for, AStmt);
13475
13476 OMPLoopBasedDirective::HelperExprs B;
13477 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13478 // define the nested loops number.
13479 unsigned NestedLoopCount =
13480 checkOpenMPLoop(DKind: OMPD_target_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13481 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
13482 VarsWithImplicitDSA, Built&: B);
13483 if (NestedLoopCount == 0)
13484 return StmtError();
13485
13486 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13487 return StmtError();
13488
13489 return OMPTargetParallelForDirective::Create(
13490 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13491 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13492}
13493
13494/// Check for existence of a map clause in the list of clauses.
13495static bool hasClauses(ArrayRef<OMPClause *> Clauses,
13496 const OpenMPClauseKind K) {
13497 return llvm::any_of(
13498 Range&: Clauses, P: [K](const OMPClause *C) { return C->getClauseKind() == K; });
13499}
13500
13501template <typename... Params>
13502static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
13503 const Params... ClauseTypes) {
13504 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13505}
13506
13507/// Check if the variables in the mapping clause are externally visible.
13508static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
13509 for (const OMPClause *C : Clauses) {
13510 if (auto *TC = dyn_cast<OMPToClause>(Val: C))
13511 return llvm::all_of(Range: TC->all_decls(), P: [](ValueDecl *VD) {
13512 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13513 (VD->isExternallyVisible() &&
13514 VD->getVisibility() != HiddenVisibility);
13515 });
13516 else if (auto *FC = dyn_cast<OMPFromClause>(Val: C))
13517 return llvm::all_of(Range: FC->all_decls(), P: [](ValueDecl *VD) {
13518 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13519 (VD->isExternallyVisible() &&
13520 VD->getVisibility() != HiddenVisibility);
13521 });
13522 }
13523
13524 return true;
13525}
13526
13527StmtResult
13528SemaOpenMP::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
13529 Stmt *AStmt, SourceLocation StartLoc,
13530 SourceLocation EndLoc) {
13531 if (!AStmt)
13532 return StmtError();
13533
13534 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13535
13536 // OpenMP [2.12.2, target data Construct, Restrictions]
13537 // At least one map, use_device_addr or use_device_ptr clause must appear on
13538 // the directive.
13539 if (!hasClauses(Clauses, K: OMPC_map, ClauseTypes: OMPC_use_device_ptr) &&
13540 (getLangOpts().OpenMP < 50 ||
13541 !hasClauses(Clauses, K: OMPC_use_device_addr))) {
13542 StringRef Expected;
13543 if (getLangOpts().OpenMP < 50)
13544 Expected = "'map' or 'use_device_ptr'";
13545 else
13546 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13547 unsigned OMPVersion = getLangOpts().OpenMP;
13548 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
13549 << Expected << getOpenMPDirectiveName(D: OMPD_target_data, Ver: OMPVersion);
13550 return StmtError();
13551 }
13552
13553 SemaRef.setFunctionHasBranchProtectedScope();
13554
13555 return OMPTargetDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13556 Clauses, AssociatedStmt: AStmt);
13557}
13558
13559StmtResult SemaOpenMP::ActOnOpenMPTargetEnterDataDirective(
13560 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13561 SourceLocation EndLoc, Stmt *AStmt) {
13562 if (!AStmt)
13563 return StmtError();
13564
13565 setBranchProtectedScope(SemaRef, DKind: OMPD_target_enter_data, AStmt);
13566
13567 // OpenMP [2.10.2, Restrictions, p. 99]
13568 // At least one map clause must appear on the directive.
13569 if (!hasClauses(Clauses, K: OMPC_map)) {
13570 unsigned OMPVersion = getLangOpts().OpenMP;
13571 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
13572 << "'map'"
13573 << getOpenMPDirectiveName(D: OMPD_target_enter_data, Ver: OMPVersion);
13574 return StmtError();
13575 }
13576
13577 return OMPTargetEnterDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13578 Clauses, AssociatedStmt: AStmt);
13579}
13580
13581StmtResult SemaOpenMP::ActOnOpenMPTargetExitDataDirective(
13582 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13583 SourceLocation EndLoc, Stmt *AStmt) {
13584 if (!AStmt)
13585 return StmtError();
13586
13587 setBranchProtectedScope(SemaRef, DKind: OMPD_target_exit_data, AStmt);
13588
13589 // OpenMP [2.10.3, Restrictions, p. 102]
13590 // At least one map clause must appear on the directive.
13591 if (!hasClauses(Clauses, K: OMPC_map)) {
13592 unsigned OMPVersion = getLangOpts().OpenMP;
13593 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
13594 << "'map'" << getOpenMPDirectiveName(D: OMPD_target_exit_data, Ver: OMPVersion);
13595 return StmtError();
13596 }
13597
13598 return OMPTargetExitDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13599 Clauses, AssociatedStmt: AStmt);
13600}
13601
13602StmtResult SemaOpenMP::ActOnOpenMPTargetUpdateDirective(
13603 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13604 SourceLocation EndLoc, Stmt *AStmt) {
13605 if (!AStmt)
13606 return StmtError();
13607
13608 setBranchProtectedScope(SemaRef, DKind: OMPD_target_update, AStmt);
13609
13610 if (!hasClauses(Clauses, K: OMPC_to, ClauseTypes: OMPC_from)) {
13611 Diag(Loc: StartLoc, DiagID: diag::err_omp_at_least_one_motion_clause_required);
13612 return StmtError();
13613 }
13614
13615 if (!isClauseMappable(Clauses)) {
13616 Diag(Loc: StartLoc, DiagID: diag::err_omp_cannot_update_with_internal_linkage);
13617 return StmtError();
13618 }
13619
13620 return OMPTargetUpdateDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13621 Clauses, AssociatedStmt: AStmt);
13622}
13623
13624/// This checks whether a \p ClauseType clause \p C has at most \p Max
13625/// expression. If not, a diag of number \p Diag will be emitted.
13626template <typename ClauseType>
13627static bool checkNumExprsInClause(SemaBase &SemaRef,
13628 ArrayRef<OMPClause *> Clauses,
13629 unsigned MaxNum, unsigned Diag) {
13630 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13631 if (ClauseItr == Clauses.end())
13632 return true;
13633 const auto *C = cast<ClauseType>(*ClauseItr);
13634 auto VarList = C->getVarRefs();
13635 if (VarList.size() > MaxNum) {
13636 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13637 << getOpenMPClauseNameForDiag(C->getClauseKind());
13638 return false;
13639 }
13640 return true;
13641}
13642
13643StmtResult SemaOpenMP::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
13644 Stmt *AStmt,
13645 SourceLocation StartLoc,
13646 SourceLocation EndLoc) {
13647 if (!AStmt)
13648 return StmtError();
13649
13650 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13651 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed) ||
13652 !checkNumExprsInClause<OMPThreadLimitClause>(
13653 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed))
13654 return StmtError();
13655
13656 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13657 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13658 Diag(Loc: StartLoc, DiagID: diag::warn_hip_omp_target_directives);
13659
13660 setBranchProtectedScope(SemaRef, DKind: OMPD_teams, AStmt);
13661
13662 DSAStack->setParentTeamsRegionLoc(StartLoc);
13663
13664 return OMPTeamsDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
13665 AssociatedStmt: AStmt);
13666}
13667
13668StmtResult SemaOpenMP::ActOnOpenMPCancellationPointDirective(
13669 SourceLocation StartLoc, SourceLocation EndLoc,
13670 OpenMPDirectiveKind CancelRegion) {
13671 if (DSAStack->isParentNowaitRegion()) {
13672 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_nowait) << 0;
13673 return StmtError();
13674 }
13675 if (DSAStack->isParentOrderedRegion()) {
13676 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_ordered) << 0;
13677 return StmtError();
13678 }
13679 return OMPCancellationPointDirective::Create(C: getASTContext(), StartLoc,
13680 EndLoc, CancelRegion);
13681}
13682
13683StmtResult SemaOpenMP::ActOnOpenMPCancelDirective(
13684 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13685 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13686 if (DSAStack->isParentNowaitRegion()) {
13687 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_nowait) << 1;
13688 return StmtError();
13689 }
13690 if (DSAStack->isParentOrderedRegion()) {
13691 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_ordered) << 1;
13692 return StmtError();
13693 }
13694 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13695 return OMPCancelDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
13696 CancelRegion);
13697}
13698
13699static bool checkReductionClauseWithNogroup(Sema &S,
13700 ArrayRef<OMPClause *> Clauses) {
13701 const OMPClause *ReductionClause = nullptr;
13702 const OMPClause *NogroupClause = nullptr;
13703 for (const OMPClause *C : Clauses) {
13704 if (C->getClauseKind() == OMPC_reduction) {
13705 ReductionClause = C;
13706 if (NogroupClause)
13707 break;
13708 continue;
13709 }
13710 if (C->getClauseKind() == OMPC_nogroup) {
13711 NogroupClause = C;
13712 if (ReductionClause)
13713 break;
13714 continue;
13715 }
13716 }
13717 if (ReductionClause && NogroupClause) {
13718 S.Diag(Loc: ReductionClause->getBeginLoc(), DiagID: diag::err_omp_reduction_with_nogroup)
13719 << SourceRange(NogroupClause->getBeginLoc(),
13720 NogroupClause->getEndLoc());
13721 return true;
13722 }
13723 return false;
13724}
13725
13726StmtResult SemaOpenMP::ActOnOpenMPTaskLoopDirective(
13727 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13728 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13729 if (!AStmt)
13730 return StmtError();
13731
13732 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13733 OMPLoopBasedDirective::HelperExprs B;
13734 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13735 // define the nested loops number.
13736 unsigned NestedLoopCount =
13737 checkOpenMPLoop(DKind: OMPD_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13738 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13739 DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
13740 if (NestedLoopCount == 0)
13741 return StmtError();
13742
13743 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13744 "omp for loop exprs were not built");
13745
13746 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13747 // The grainsize clause and num_tasks clause are mutually exclusive and may
13748 // not appear on the same taskloop directive.
13749 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13750 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13751 return StmtError();
13752 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13753 // If a reduction clause is present on the taskloop directive, the nogroup
13754 // clause must not be specified.
13755 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13756 return StmtError();
13757
13758 SemaRef.setFunctionHasBranchProtectedScope();
13759 return OMPTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13760 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13761 DSAStack->isCancelRegion());
13762}
13763
13764StmtResult SemaOpenMP::ActOnOpenMPTaskLoopSimdDirective(
13765 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13766 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13767 if (!AStmt)
13768 return StmtError();
13769
13770 CapturedStmt *CS =
13771 setBranchProtectedScope(SemaRef, DKind: OMPD_taskloop_simd, AStmt);
13772
13773 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13774 OMPLoopBasedDirective::HelperExprs B;
13775 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13776 // define the nested loops number.
13777 unsigned NestedLoopCount =
13778 checkOpenMPLoop(DKind: OMPD_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13779 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
13780 VarsWithImplicitDSA, Built&: B);
13781 if (NestedLoopCount == 0)
13782 return StmtError();
13783
13784 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13785 return StmtError();
13786
13787 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13788 // The grainsize clause and num_tasks clause are mutually exclusive and may
13789 // not appear on the same taskloop directive.
13790 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13791 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13792 return StmtError();
13793 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13794 // If a reduction clause is present on the taskloop directive, the nogroup
13795 // clause must not be specified.
13796 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13797 return StmtError();
13798 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13799 return StmtError();
13800
13801 return OMPTaskLoopSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13802 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13803}
13804
13805StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopDirective(
13806 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13807 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13808 if (!AStmt)
13809 return StmtError();
13810
13811 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13812 OMPLoopBasedDirective::HelperExprs B;
13813 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13814 // define the nested loops number.
13815 unsigned NestedLoopCount =
13816 checkOpenMPLoop(DKind: OMPD_master_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13817 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13818 DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
13819 if (NestedLoopCount == 0)
13820 return StmtError();
13821
13822 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13823 "omp for loop exprs were not built");
13824
13825 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13826 // The grainsize clause and num_tasks clause are mutually exclusive and may
13827 // not appear on the same taskloop directive.
13828 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13829 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13830 return StmtError();
13831 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13832 // If a reduction clause is present on the taskloop directive, the nogroup
13833 // clause must not be specified.
13834 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13835 return StmtError();
13836
13837 SemaRef.setFunctionHasBranchProtectedScope();
13838 return OMPMasterTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13839 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13840 DSAStack->isCancelRegion());
13841}
13842
13843StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopDirective(
13844 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13845 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13846 if (!AStmt)
13847 return StmtError();
13848
13849 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13850 OMPLoopBasedDirective::HelperExprs B;
13851 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13852 // define the nested loops number.
13853 unsigned NestedLoopCount =
13854 checkOpenMPLoop(DKind: OMPD_masked_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13855 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13856 DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
13857 if (NestedLoopCount == 0)
13858 return StmtError();
13859
13860 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13861 "omp for loop exprs were not built");
13862
13863 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13864 // The grainsize clause and num_tasks clause are mutually exclusive and may
13865 // not appear on the same taskloop directive.
13866 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13867 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13868 return StmtError();
13869 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13870 // If a reduction clause is present on the taskloop directive, the nogroup
13871 // clause must not be specified.
13872 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13873 return StmtError();
13874
13875 SemaRef.setFunctionHasBranchProtectedScope();
13876 return OMPMaskedTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13877 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13878 DSAStack->isCancelRegion());
13879}
13880
13881StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopSimdDirective(
13882 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13883 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13884 if (!AStmt)
13885 return StmtError();
13886
13887 CapturedStmt *CS =
13888 setBranchProtectedScope(SemaRef, DKind: OMPD_master_taskloop_simd, AStmt);
13889
13890 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13891 OMPLoopBasedDirective::HelperExprs B;
13892 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13893 // define the nested loops number.
13894 unsigned NestedLoopCount =
13895 checkOpenMPLoop(DKind: OMPD_master_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13896 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
13897 VarsWithImplicitDSA, Built&: B);
13898 if (NestedLoopCount == 0)
13899 return StmtError();
13900
13901 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13902 return StmtError();
13903
13904 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13905 // The grainsize clause and num_tasks clause are mutually exclusive and may
13906 // not appear on the same taskloop directive.
13907 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13908 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13909 return StmtError();
13910 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13911 // If a reduction clause is present on the taskloop directive, the nogroup
13912 // clause must not be specified.
13913 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13914 return StmtError();
13915 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13916 return StmtError();
13917
13918 return OMPMasterTaskLoopSimdDirective::Create(
13919 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13920}
13921
13922StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopSimdDirective(
13923 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13924 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13925 if (!AStmt)
13926 return StmtError();
13927
13928 CapturedStmt *CS =
13929 setBranchProtectedScope(SemaRef, DKind: OMPD_masked_taskloop_simd, AStmt);
13930
13931 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13932 OMPLoopBasedDirective::HelperExprs B;
13933 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13934 // define the nested loops number.
13935 unsigned NestedLoopCount =
13936 checkOpenMPLoop(DKind: OMPD_masked_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13937 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
13938 VarsWithImplicitDSA, Built&: B);
13939 if (NestedLoopCount == 0)
13940 return StmtError();
13941
13942 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13943 return StmtError();
13944
13945 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13946 // The grainsize clause and num_tasks clause are mutually exclusive and may
13947 // not appear on the same taskloop directive.
13948 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13949 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13950 return StmtError();
13951 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13952 // If a reduction clause is present on the taskloop directive, the nogroup
13953 // clause must not be specified.
13954 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13955 return StmtError();
13956 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13957 return StmtError();
13958
13959 return OMPMaskedTaskLoopSimdDirective::Create(
13960 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13961}
13962
13963StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopDirective(
13964 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13965 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13966 if (!AStmt)
13967 return StmtError();
13968
13969 CapturedStmt *CS =
13970 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_master_taskloop, AStmt);
13971
13972 OMPLoopBasedDirective::HelperExprs B;
13973 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13974 // define the nested loops number.
13975 unsigned NestedLoopCount = checkOpenMPLoop(
13976 DKind: OMPD_parallel_master_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13977 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
13978 VarsWithImplicitDSA, Built&: B);
13979 if (NestedLoopCount == 0)
13980 return StmtError();
13981
13982 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13983 "omp for loop exprs were not built");
13984
13985 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13986 // The grainsize clause and num_tasks clause are mutually exclusive and may
13987 // not appear on the same taskloop directive.
13988 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13989 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13990 return StmtError();
13991 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13992 // If a reduction clause is present on the taskloop directive, the nogroup
13993 // clause must not be specified.
13994 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13995 return StmtError();
13996
13997 return OMPParallelMasterTaskLoopDirective::Create(
13998 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13999 DSAStack->isCancelRegion());
14000}
14001
14002StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopDirective(
14003 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14004 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14005 if (!AStmt)
14006 return StmtError();
14007
14008 CapturedStmt *CS =
14009 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_masked_taskloop, AStmt);
14010
14011 OMPLoopBasedDirective::HelperExprs B;
14012 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14013 // define the nested loops number.
14014 unsigned NestedLoopCount = checkOpenMPLoop(
14015 DKind: OMPD_parallel_masked_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14016 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14017 VarsWithImplicitDSA, Built&: B);
14018 if (NestedLoopCount == 0)
14019 return StmtError();
14020
14021 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14022 "omp for loop exprs were not built");
14023
14024 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14025 // The grainsize clause and num_tasks clause are mutually exclusive and may
14026 // not appear on the same taskloop directive.
14027 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14028 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14029 return StmtError();
14030 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14031 // If a reduction clause is present on the taskloop directive, the nogroup
14032 // clause must not be specified.
14033 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14034 return StmtError();
14035
14036 return OMPParallelMaskedTaskLoopDirective::Create(
14037 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14038 DSAStack->isCancelRegion());
14039}
14040
14041StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
14042 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14043 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14044 if (!AStmt)
14045 return StmtError();
14046
14047 CapturedStmt *CS = setBranchProtectedScope(
14048 SemaRef, DKind: OMPD_parallel_master_taskloop_simd, AStmt);
14049
14050 OMPLoopBasedDirective::HelperExprs B;
14051 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14052 // define the nested loops number.
14053 unsigned NestedLoopCount = checkOpenMPLoop(
14054 DKind: OMPD_parallel_master_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14055 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14056 VarsWithImplicitDSA, Built&: B);
14057 if (NestedLoopCount == 0)
14058 return StmtError();
14059
14060 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14061 return StmtError();
14062
14063 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14064 // The grainsize clause and num_tasks clause are mutually exclusive and may
14065 // not appear on the same taskloop directive.
14066 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14067 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14068 return StmtError();
14069 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14070 // If a reduction clause is present on the taskloop directive, the nogroup
14071 // clause must not be specified.
14072 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14073 return StmtError();
14074 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14075 return StmtError();
14076
14077 return OMPParallelMasterTaskLoopSimdDirective::Create(
14078 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14079}
14080
14081StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
14082 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14083 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14084 if (!AStmt)
14085 return StmtError();
14086
14087 CapturedStmt *CS = setBranchProtectedScope(
14088 SemaRef, DKind: OMPD_parallel_masked_taskloop_simd, AStmt);
14089
14090 OMPLoopBasedDirective::HelperExprs B;
14091 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14092 // define the nested loops number.
14093 unsigned NestedLoopCount = checkOpenMPLoop(
14094 DKind: OMPD_parallel_masked_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14095 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14096 VarsWithImplicitDSA, Built&: B);
14097 if (NestedLoopCount == 0)
14098 return StmtError();
14099
14100 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14101 return StmtError();
14102
14103 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14104 // The grainsize clause and num_tasks clause are mutually exclusive and may
14105 // not appear on the same taskloop directive.
14106 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14107 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14108 return StmtError();
14109 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14110 // If a reduction clause is present on the taskloop directive, the nogroup
14111 // clause must not be specified.
14112 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14113 return StmtError();
14114 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14115 return StmtError();
14116
14117 return OMPParallelMaskedTaskLoopSimdDirective::Create(
14118 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14119}
14120
14121StmtResult SemaOpenMP::ActOnOpenMPDistributeDirective(
14122 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14123 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14124 if (!AStmt)
14125 return StmtError();
14126
14127 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14128 OMPLoopBasedDirective::HelperExprs B;
14129 // In presence of clause 'collapse' with number of loops, it will
14130 // define the nested loops number.
14131 unsigned NestedLoopCount =
14132 checkOpenMPLoop(DKind: OMPD_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14133 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt,
14134 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14135 if (NestedLoopCount == 0)
14136 return StmtError();
14137
14138 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14139 "omp for loop exprs were not built");
14140
14141 SemaRef.setFunctionHasBranchProtectedScope();
14142 auto *DistributeDirective = OMPDistributeDirective::Create(
14143 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14144 return DistributeDirective;
14145}
14146
14147StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForDirective(
14148 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14149 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14150 if (!AStmt)
14151 return StmtError();
14152
14153 CapturedStmt *CS =
14154 setBranchProtectedScope(SemaRef, DKind: OMPD_distribute_parallel_for, AStmt);
14155
14156 OMPLoopBasedDirective::HelperExprs B;
14157 // In presence of clause 'collapse' with number of loops, it will
14158 // define the nested loops number.
14159 unsigned NestedLoopCount = checkOpenMPLoop(
14160 DKind: OMPD_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14161 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14162 VarsWithImplicitDSA, Built&: B);
14163 if (NestedLoopCount == 0)
14164 return StmtError();
14165
14166 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14167 "omp for loop exprs were not built");
14168
14169 return OMPDistributeParallelForDirective::Create(
14170 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14171 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14172}
14173
14174StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForSimdDirective(
14175 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14176 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14177 if (!AStmt)
14178 return StmtError();
14179
14180 CapturedStmt *CS = setBranchProtectedScope(
14181 SemaRef, DKind: OMPD_distribute_parallel_for_simd, AStmt);
14182
14183 OMPLoopBasedDirective::HelperExprs B;
14184 // In presence of clause 'collapse' with number of loops, it will
14185 // define the nested loops number.
14186 unsigned NestedLoopCount = checkOpenMPLoop(
14187 DKind: OMPD_distribute_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14188 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, 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 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14197 return StmtError();
14198
14199 return OMPDistributeParallelForSimdDirective::Create(
14200 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14201}
14202
14203StmtResult SemaOpenMP::ActOnOpenMPDistributeSimdDirective(
14204 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14205 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14206 if (!AStmt)
14207 return StmtError();
14208
14209 CapturedStmt *CS =
14210 setBranchProtectedScope(SemaRef, DKind: OMPD_distribute_simd, AStmt);
14211
14212 OMPLoopBasedDirective::HelperExprs B;
14213 // In presence of clause 'collapse' with number of loops, it will
14214 // define the nested loops number.
14215 unsigned NestedLoopCount =
14216 checkOpenMPLoop(DKind: OMPD_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14217 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
14218 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14219 if (NestedLoopCount == 0)
14220 return StmtError();
14221
14222 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14223 return StmtError();
14224
14225 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14226 return StmtError();
14227
14228 return OMPDistributeSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14229 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14230}
14231
14232StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForSimdDirective(
14233 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14234 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14235 if (!AStmt)
14236 return StmtError();
14237
14238 CapturedStmt *CS =
14239 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_for_simd, AStmt);
14240
14241 OMPLoopBasedDirective::HelperExprs B;
14242 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14243 // define the nested loops number.
14244 unsigned NestedLoopCount = checkOpenMPLoop(
14245 DKind: OMPD_target_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14246 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
14247 VarsWithImplicitDSA, Built&: B);
14248 if (NestedLoopCount == 0)
14249 return StmtError();
14250
14251 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14252 return StmtError();
14253
14254 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14255 return StmtError();
14256
14257 return OMPTargetParallelForSimdDirective::Create(
14258 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14259}
14260
14261StmtResult SemaOpenMP::ActOnOpenMPTargetSimdDirective(
14262 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14263 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14264 if (!AStmt)
14265 return StmtError();
14266
14267 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_target_simd, AStmt);
14268
14269 OMPLoopBasedDirective::HelperExprs B;
14270 // In presence of clause 'collapse' with number of loops, it will define the
14271 // nested loops number.
14272 unsigned NestedLoopCount =
14273 checkOpenMPLoop(DKind: OMPD_target_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14274 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
14275 VarsWithImplicitDSA, Built&: B);
14276 if (NestedLoopCount == 0)
14277 return StmtError();
14278
14279 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14280 return StmtError();
14281
14282 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14283 return StmtError();
14284
14285 return OMPTargetSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14286 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14287}
14288
14289StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeDirective(
14290 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14291 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14292 if (!AStmt)
14293 return StmtError();
14294
14295 CapturedStmt *CS =
14296 setBranchProtectedScope(SemaRef, DKind: OMPD_teams_distribute, AStmt);
14297
14298 OMPLoopBasedDirective::HelperExprs B;
14299 // In presence of clause 'collapse' with number of loops, it will
14300 // define the nested loops number.
14301 unsigned NestedLoopCount =
14302 checkOpenMPLoop(DKind: OMPD_teams_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14303 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
14304 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14305 if (NestedLoopCount == 0)
14306 return StmtError();
14307
14308 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14309 "omp teams distribute loop exprs were not built");
14310
14311 DSAStack->setParentTeamsRegionLoc(StartLoc);
14312
14313 return OMPTeamsDistributeDirective::Create(
14314 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14315}
14316
14317StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeSimdDirective(
14318 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14319 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14320 if (!AStmt)
14321 return StmtError();
14322
14323 CapturedStmt *CS =
14324 setBranchProtectedScope(SemaRef, DKind: OMPD_teams_distribute_simd, AStmt);
14325
14326 OMPLoopBasedDirective::HelperExprs B;
14327 // In presence of clause 'collapse' with number of loops, it will
14328 // define the nested loops number.
14329 unsigned NestedLoopCount = checkOpenMPLoop(
14330 DKind: OMPD_teams_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14331 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14332 VarsWithImplicitDSA, Built&: B);
14333 if (NestedLoopCount == 0)
14334 return StmtError();
14335
14336 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14337 return StmtError();
14338
14339 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14340 return StmtError();
14341
14342 DSAStack->setParentTeamsRegionLoc(StartLoc);
14343
14344 return OMPTeamsDistributeSimdDirective::Create(
14345 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14346}
14347
14348StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
14349 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14350 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14351 if (!AStmt)
14352 return StmtError();
14353
14354 CapturedStmt *CS = setBranchProtectedScope(
14355 SemaRef, DKind: OMPD_teams_distribute_parallel_for_simd, AStmt);
14356
14357 OMPLoopBasedDirective::HelperExprs B;
14358 // In presence of clause 'collapse' with number of loops, it will
14359 // define the nested loops number.
14360 unsigned NestedLoopCount = checkOpenMPLoop(
14361 DKind: OMPD_teams_distribute_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14362 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14363 VarsWithImplicitDSA, Built&: B);
14364 if (NestedLoopCount == 0)
14365 return StmtError();
14366
14367 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14368 return StmtError();
14369
14370 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14371 return StmtError();
14372
14373 DSAStack->setParentTeamsRegionLoc(StartLoc);
14374
14375 return OMPTeamsDistributeParallelForSimdDirective::Create(
14376 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14377}
14378
14379StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForDirective(
14380 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14381 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14382 if (!AStmt)
14383 return StmtError();
14384
14385 CapturedStmt *CS = setBranchProtectedScope(
14386 SemaRef, DKind: OMPD_teams_distribute_parallel_for, AStmt);
14387
14388 OMPLoopBasedDirective::HelperExprs B;
14389 // In presence of clause 'collapse' with number of loops, it will
14390 // define the nested loops number.
14391 unsigned NestedLoopCount = checkOpenMPLoop(
14392 DKind: OMPD_teams_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14393 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14394 VarsWithImplicitDSA, Built&: B);
14395
14396 if (NestedLoopCount == 0)
14397 return StmtError();
14398
14399 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14400 "omp for loop exprs were not built");
14401
14402 DSAStack->setParentTeamsRegionLoc(StartLoc);
14403
14404 return OMPTeamsDistributeParallelForDirective::Create(
14405 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14406 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14407}
14408
14409StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDirective(
14410 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14411 SourceLocation EndLoc) {
14412 if (!AStmt)
14413 return StmtError();
14414
14415 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams, AStmt);
14416
14417 const OMPClause *BareClause = nullptr;
14418 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, K: OMPC_num_teams) &&
14419 hasClauses(Clauses, K: OMPC_thread_limit);
14420 bool HasBareClause = llvm::any_of(Range&: Clauses, P: [&](const OMPClause *C) {
14421 BareClause = C;
14422 return C->getClauseKind() == OMPC_ompx_bare;
14423 });
14424
14425 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14426 Diag(Loc: BareClause->getBeginLoc(), DiagID: diag::err_ompx_bare_no_grid);
14427 return StmtError();
14428 }
14429
14430 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14431 unsigned DiagNo = HasBareClause
14432 ? diag::err_ompx_more_than_three_expr_not_allowed
14433 : diag::err_omp_multi_expr_not_allowed;
14434
14435 if (!checkNumExprsInClause<OMPNumTeamsClause>(SemaRef&: *this, Clauses,
14436 MaxNum: ClauseMaxNumExprs, Diag: DiagNo) ||
14437 !checkNumExprsInClause<OMPThreadLimitClause>(SemaRef&: *this, Clauses,
14438 MaxNum: ClauseMaxNumExprs, Diag: DiagNo)) {
14439 return StmtError();
14440 }
14441 return OMPTargetTeamsDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14442 Clauses, AssociatedStmt: AStmt);
14443}
14444
14445StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeDirective(
14446 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14447 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14448 if (!AStmt)
14449 return StmtError();
14450
14451 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14452 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed) ||
14453 !checkNumExprsInClause<OMPThreadLimitClause>(
14454 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed))
14455 return StmtError();
14456
14457 CapturedStmt *CS =
14458 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams_distribute, AStmt);
14459
14460 OMPLoopBasedDirective::HelperExprs B;
14461 // In presence of clause 'collapse' with number of loops, it will
14462 // define the nested loops number.
14463 unsigned NestedLoopCount = checkOpenMPLoop(
14464 DKind: OMPD_target_teams_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14465 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14466 VarsWithImplicitDSA, Built&: B);
14467 if (NestedLoopCount == 0)
14468 return StmtError();
14469
14470 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14471 "omp target teams distribute loop exprs were not built");
14472
14473 return OMPTargetTeamsDistributeDirective::Create(
14474 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14475}
14476
14477StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14478 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14479 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14480 if (!AStmt)
14481 return StmtError();
14482
14483 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14484 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed) ||
14485 !checkNumExprsInClause<OMPThreadLimitClause>(
14486 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed))
14487 return StmtError();
14488
14489 CapturedStmt *CS = setBranchProtectedScope(
14490 SemaRef, DKind: OMPD_target_teams_distribute_parallel_for, AStmt);
14491
14492 OMPLoopBasedDirective::HelperExprs B;
14493 // In presence of clause 'collapse' with number of loops, it will
14494 // define the nested loops number.
14495 unsigned NestedLoopCount = checkOpenMPLoop(
14496 DKind: OMPD_target_teams_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14497 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14498 VarsWithImplicitDSA, Built&: B);
14499 if (NestedLoopCount == 0)
14500 return StmtError();
14501
14502 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14503 return StmtError();
14504
14505 return OMPTargetTeamsDistributeParallelForDirective::Create(
14506 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14507 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14508}
14509
14510StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14511 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14512 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14513 if (!AStmt)
14514 return StmtError();
14515
14516 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14517 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed) ||
14518 !checkNumExprsInClause<OMPThreadLimitClause>(
14519 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed))
14520 return StmtError();
14521
14522 CapturedStmt *CS = setBranchProtectedScope(
14523 SemaRef, DKind: OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14524
14525 OMPLoopBasedDirective::HelperExprs B;
14526 // In presence of clause 'collapse' with number of loops, it will
14527 // define the nested loops number.
14528 unsigned NestedLoopCount =
14529 checkOpenMPLoop(DKind: OMPD_target_teams_distribute_parallel_for_simd,
14530 CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14531 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
14532 SemaRef, DSA&: *DSAStack, 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 OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14543 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14544}
14545
14546StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14547 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14548 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14549 if (!AStmt)
14550 return StmtError();
14551
14552 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14553 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed) ||
14554 !checkNumExprsInClause<OMPThreadLimitClause>(
14555 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed))
14556 return StmtError();
14557
14558 CapturedStmt *CS = setBranchProtectedScope(
14559 SemaRef, DKind: OMPD_target_teams_distribute_simd, AStmt);
14560
14561 OMPLoopBasedDirective::HelperExprs B;
14562 // In presence of clause 'collapse' with number of loops, it will
14563 // define the nested loops number.
14564 unsigned NestedLoopCount = checkOpenMPLoop(
14565 DKind: OMPD_target_teams_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14566 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14567 VarsWithImplicitDSA, Built&: B);
14568 if (NestedLoopCount == 0)
14569 return StmtError();
14570
14571 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14572 return StmtError();
14573
14574 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14575 return StmtError();
14576
14577 return OMPTargetTeamsDistributeSimdDirective::Create(
14578 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14579}
14580
14581/// Updates OriginalInits by checking Transform against loop transformation
14582/// directives and appending their pre-inits if a match is found.
14583static void updatePreInits(OMPLoopTransformationDirective *Transform,
14584 SmallVectorImpl<Stmt *> &PreInits) {
14585 Stmt *Dir = Transform->getDirective();
14586 switch (Dir->getStmtClass()) {
14587#define STMT(CLASS, PARENT)
14588#define ABSTRACT_STMT(CLASS)
14589#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14590 case Stmt::CLASS##Class: \
14591 appendFlattenedStmtList(PreInits, \
14592 static_cast<const CLASS *>(Dir)->getPreInits()); \
14593 break;
14594#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14595 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14596#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14597 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14598#include "clang/AST/StmtNodes.inc"
14599#undef COMMON_OMP_LOOP_TRANSFORMATION
14600 default:
14601 llvm_unreachable("Not a loop transformation");
14602 }
14603}
14604
14605bool SemaOpenMP::checkTransformableLoopNest(
14606 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14607 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14608 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *>> &OriginalInits) {
14609 OriginalInits.emplace_back();
14610 bool Result = OMPLoopBasedDirective::doForAllLoops(
14611 CurStmt: AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14612 Callback: [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14613 Stmt *CurStmt) {
14614 VarsWithInheritedDSAType TmpDSA;
14615 unsigned SingleNumLoops =
14616 checkOpenMPLoop(DKind: Kind, CollapseLoopCountExpr: nullptr, OrderedLoopCountExpr: nullptr, AStmt: CurStmt, SemaRef, DSA&: *DSAStack,
14617 VarsWithImplicitDSA&: TmpDSA, Built&: LoopHelpers[Cnt]);
14618 if (SingleNumLoops == 0)
14619 return true;
14620 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14621 if (auto *For = dyn_cast<ForStmt>(Val: CurStmt)) {
14622 OriginalInits.back().push_back(Elt: For->getInit());
14623 Body = For->getBody();
14624 } else {
14625 assert(isa<CXXForRangeStmt>(CurStmt) &&
14626 "Expected canonical for or range-based for loops.");
14627 auto *CXXFor = cast<CXXForRangeStmt>(Val: CurStmt);
14628 OriginalInits.back().push_back(Elt: CXXFor->getBeginStmt());
14629 Body = CXXFor->getBody();
14630 }
14631 OriginalInits.emplace_back();
14632 return false;
14633 },
14634 OnTransformationCallback: [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14635 updatePreInits(Transform, PreInits&: OriginalInits.back());
14636 });
14637 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14638 OriginalInits.pop_back();
14639 return Result;
14640}
14641
14642/// Counts the total number of OpenMP canonical nested loops, including the
14643/// outermost loop (the original loop). PRECONDITION of this visitor is that it
14644/// must be invoked from the original loop to be analyzed. The traversal stops
14645/// for Decl's and Expr's given that they may contain inner loops that must not
14646/// be counted.
14647///
14648/// Example AST structure for the code:
14649///
14650/// int main() {
14651/// #pragma omp fuse
14652/// {
14653/// for (int i = 0; i < 100; i++) { <-- Outer loop
14654/// []() {
14655/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (1)
14656/// };
14657/// for(int j = 0; j < 5; ++j) {} <-- Inner loop
14658/// }
14659/// for (int r = 0; i < 100; i++) { <-- Outer loop
14660/// struct LocalClass {
14661/// void bar() {
14662/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (2)
14663/// }
14664/// };
14665/// for(int k = 0; k < 10; ++k) {} <-- Inner loop
14666/// {x = 5; for(k = 0; k < 10; ++k) x += k; x}; <-- NOT A LOOP (3)
14667/// }
14668/// }
14669/// }
14670/// (1) because in a different function (here: a lambda)
14671/// (2) because in a different function (here: class method)
14672/// (3) because considered to be intervening-code of non-perfectly nested loop
14673/// Result: Loop 'i' contains 2 loops, Loop 'r' also contains 2 loops.
14674class NestedLoopCounterVisitor final : public DynamicRecursiveASTVisitor {
14675private:
14676 unsigned NestedLoopCount = 0;
14677
14678public:
14679 explicit NestedLoopCounterVisitor() = default;
14680
14681 unsigned getNestedLoopCount() const { return NestedLoopCount; }
14682
14683 bool VisitForStmt(ForStmt *FS) override {
14684 ++NestedLoopCount;
14685 return true;
14686 }
14687
14688 bool VisitCXXForRangeStmt(CXXForRangeStmt *FRS) override {
14689 ++NestedLoopCount;
14690 return true;
14691 }
14692
14693 bool TraverseStmt(Stmt *S) override {
14694 if (!S)
14695 return true;
14696
14697 // Skip traversal of all expressions, including special cases like
14698 // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
14699 // may contain inner statements (and even loops), but they are not part
14700 // of the syntactic body of the surrounding loop structure.
14701 // Therefore must not be counted.
14702 if (isa<Expr>(Val: S))
14703 return true;
14704
14705 // Only recurse into CompoundStmt (block {}) and loop bodies.
14706 if (isa<CompoundStmt, ForStmt, CXXForRangeStmt>(Val: S)) {
14707 return DynamicRecursiveASTVisitor::TraverseStmt(S);
14708 }
14709
14710 // Stop traversal of the rest of statements, that break perfect
14711 // loop nesting, such as control flow (IfStmt, SwitchStmt...).
14712 return true;
14713 }
14714
14715 bool TraverseDecl(Decl *D) override {
14716 // Stop in the case of finding a declaration, it is not important
14717 // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
14718 // FunctionDecl...).
14719 return true;
14720 }
14721};
14722
14723bool SemaOpenMP::analyzeLoopSequence(Stmt *LoopSeqStmt,
14724 LoopSequenceAnalysis &SeqAnalysis,
14725 ASTContext &Context,
14726 OpenMPDirectiveKind Kind) {
14727 VarsWithInheritedDSAType TmpDSA;
14728 // Helper Lambda to handle storing initialization and body statements for
14729 // both ForStmt and CXXForRangeStmt.
14730 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14731 if (auto *For = dyn_cast<ForStmt>(Val: LoopStmt)) {
14732 Analysis.OriginalInits.push_back(Elt: For->getInit());
14733 Analysis.TheForStmt = For;
14734 } else {
14735 auto *CXXFor = cast<CXXForRangeStmt>(Val: LoopStmt);
14736 Analysis.OriginalInits.push_back(Elt: CXXFor->getBeginStmt());
14737 Analysis.TheForStmt = CXXFor;
14738 }
14739 };
14740
14741 // Helper lambda functions to encapsulate the processing of different
14742 // derivations of the canonical loop sequence grammar
14743 // Modularized code for handling loop generation and transformations.
14744 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14745 auto *LoopTransform = cast<OMPLoopTransformationDirective>(Val: Child);
14746 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14747 unsigned NumGeneratedTopLevelLoops =
14748 LoopTransform->getNumGeneratedTopLevelLoops();
14749 // Handle the case where transformed statement is not available due to
14750 // dependent contexts
14751 if (!TransformedStmt) {
14752 if (NumGeneratedTopLevelLoops > 0) {
14753 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14754 return true;
14755 }
14756 // Unroll full (0 loops produced)
14757 Diag(Loc: Child->getBeginLoc(), DiagID: diag::err_omp_not_for)
14758 << 0 << getOpenMPDirectiveName(D: Kind);
14759 return false;
14760 }
14761 // Handle loop transformations with multiple loop nests
14762 // Unroll full
14763 if (!NumGeneratedTopLevelLoops) {
14764 Diag(Loc: Child->getBeginLoc(), DiagID: diag::err_omp_not_for)
14765 << 0 << getOpenMPDirectiveName(D: Kind);
14766 return false;
14767 }
14768 // Loop transformatons such as split or loopranged fuse
14769 if (NumGeneratedTopLevelLoops > 1) {
14770 // Get the preinits related to this loop sequence generating
14771 // loop transformation (i.e loopranged fuse, split...)
14772 // These preinits differ slightly from regular inits/pre-inits related
14773 // to single loop generating loop transformations (interchange, unroll)
14774 // given that they are not bounded to a particular loop nest
14775 // so they need to be treated independently
14776 updatePreInits(Transform: LoopTransform, PreInits&: SeqAnalysis.LoopSequencePreInits);
14777 return analyzeLoopSequence(LoopSeqStmt: TransformedStmt, SeqAnalysis, Context, Kind);
14778 }
14779 // Vast majority: (Tile, Unroll, Stripe, Reverse, Interchange, Fuse all)
14780 // Process the transformed loop statement
14781 LoopAnalysis &NewTransformedSingleLoop =
14782 SeqAnalysis.Loops.emplace_back(Args&: Child);
14783 unsigned IsCanonical = checkOpenMPLoop(
14784 DKind: Kind, CollapseLoopCountExpr: nullptr, OrderedLoopCountExpr: nullptr, AStmt: TransformedStmt, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA&: TmpDSA,
14785 Built&: NewTransformedSingleLoop.HelperExprs);
14786
14787 if (!IsCanonical)
14788 return false;
14789
14790 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
14791 updatePreInits(Transform: LoopTransform, PreInits&: NewTransformedSingleLoop.TransformsPreInits);
14792
14793 SeqAnalysis.LoopSeqSize++;
14794 return true;
14795 };
14796
14797 // Modularized code for handling regular canonical loops.
14798 auto AnalyzeRegularLoop = [&](Stmt *Child) {
14799 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Args&: Child);
14800 unsigned IsCanonical =
14801 checkOpenMPLoop(DKind: Kind, CollapseLoopCountExpr: nullptr, OrderedLoopCountExpr: nullptr, AStmt: Child, SemaRef, DSA&: *DSAStack,
14802 VarsWithImplicitDSA&: TmpDSA, Built&: NewRegularLoop.HelperExprs);
14803
14804 if (!IsCanonical)
14805 return false;
14806
14807 StoreLoopStatements(NewRegularLoop, Child);
14808 NestedLoopCounterVisitor NLCV;
14809 NLCV.TraverseStmt(S: Child);
14810 return true;
14811 };
14812
14813 // High level grammar validation.
14814 for (Stmt *Child : LoopSeqStmt->children()) {
14815 if (!Child)
14816 continue;
14817 // Skip over non-loop-sequence statements.
14818 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(S: Child)) {
14819 Child = Child->IgnoreContainers();
14820 // Ignore empty compound statement.
14821 if (!Child)
14822 continue;
14823 // In the case of a nested loop sequence ignoring containers would not
14824 // be enough, a recurisve transversal of the loop sequence is required.
14825 if (isa<CompoundStmt>(Val: Child)) {
14826 if (!analyzeLoopSequence(LoopSeqStmt: Child, SeqAnalysis, Context, Kind))
14827 return false;
14828 // Already been treated, skip this children
14829 continue;
14830 }
14831 }
14832 // Regular loop sequence handling.
14833 if (LoopSequenceAnalysis::isLoopSequenceDerivation(S: Child)) {
14834 if (LoopAnalysis::isLoopTransformation(S: Child)) {
14835 if (!AnalyzeLoopGeneration(Child))
14836 return false;
14837 // AnalyzeLoopGeneration updates SeqAnalysis.LoopSeqSize accordingly.
14838 } else {
14839 if (!AnalyzeRegularLoop(Child))
14840 return false;
14841 SeqAnalysis.LoopSeqSize++;
14842 }
14843 } else {
14844 // Report error for invalid statement inside canonical loop sequence.
14845 Diag(Loc: Child->getBeginLoc(), DiagID: diag::err_omp_not_for)
14846 << 0 << getOpenMPDirectiveName(D: Kind);
14847 return false;
14848 }
14849 }
14850 return true;
14851}
14852
14853bool SemaOpenMP::checkTransformableLoopSequence(
14854 OpenMPDirectiveKind Kind, Stmt *AStmt, LoopSequenceAnalysis &SeqAnalysis,
14855 ASTContext &Context) {
14856 // Following OpenMP 6.0 API Specification, a Canonical Loop Sequence follows
14857 // the grammar:
14858 //
14859 // canonical-loop-sequence:
14860 // {
14861 // loop-sequence+
14862 // }
14863 // where loop-sequence can be any of the following:
14864 // 1. canonical-loop-sequence
14865 // 2. loop-nest
14866 // 3. loop-sequence-generating-construct (i.e OMPLoopTransformationDirective)
14867 //
14868 // To recognise and traverse this structure the helper function
14869 // analyzeLoopSequence serves as the recurisve entry point
14870 // and tries to match the input AST to the canonical loop sequence grammar
14871 // structure. This function will perform both a semantic and syntactical
14872 // analysis of the given statement according to OpenMP 6.0 definition of
14873 // the aforementioned canonical loop sequence.
14874
14875 // We expect an outer compound statement.
14876 if (!isa<CompoundStmt>(Val: AStmt)) {
14877 Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_not_a_loop_sequence)
14878 << getOpenMPDirectiveName(D: Kind);
14879 return false;
14880 }
14881
14882 // Recursive entry point to process the main loop sequence
14883 if (!analyzeLoopSequence(LoopSeqStmt: AStmt, SeqAnalysis, Context, Kind))
14884 return false;
14885
14886 // Diagnose an empty loop sequence.
14887 if (!SeqAnalysis.LoopSeqSize) {
14888 Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_empty_loop_sequence)
14889 << getOpenMPDirectiveName(D: Kind);
14890 return false;
14891 }
14892 return true;
14893}
14894
14895/// Add preinit statements that need to be propagated from the selected loop.
14896static void addLoopPreInits(ASTContext &Context,
14897 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14898 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14899 SmallVectorImpl<Stmt *> &PreInits) {
14900
14901 // For range-based for-statements, ensure that their syntactic sugar is
14902 // executed by adding them as pre-init statements.
14903 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt)) {
14904 Stmt *RangeInit = CXXRangeFor->getInit();
14905 if (RangeInit)
14906 PreInits.push_back(Elt: RangeInit);
14907
14908 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14909 PreInits.push_back(Elt: new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14910 RangeStmt->getBeginLoc(),
14911 RangeStmt->getEndLoc()));
14912
14913 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14914 PreInits.push_back(Elt: new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14915 RangeEnd->getBeginLoc(),
14916 RangeEnd->getEndLoc()));
14917 }
14918
14919 llvm::append_range(C&: PreInits, R&: OriginalInit);
14920
14921 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14922 if (auto *PI = cast_or_null<DeclStmt>(Val: LoopHelper.PreInits)) {
14923 PreInits.push_back(Elt: new (Context) DeclStmt(
14924 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14925 }
14926
14927 // Gather declarations for the data members used as counters.
14928 for (Expr *CounterRef : LoopHelper.Counters) {
14929 auto *CounterDecl = cast<DeclRefExpr>(Val: CounterRef)->getDecl();
14930 if (isa<OMPCapturedExprDecl>(Val: CounterDecl))
14931 PreInits.push_back(Elt: new (Context) DeclStmt(
14932 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14933 }
14934}
14935
14936/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14937/// loop of a construct.
14938static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14939 size_t NumLoops = LoopStmts.size();
14940 OMPLoopBasedDirective::doForAllLoops(
14941 CurStmt: AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14942 Callback: [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14943 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14944 LoopStmts[Cnt] = CurStmt;
14945 return false;
14946 });
14947 assert(!is_contained(LoopStmts, nullptr) &&
14948 "Expecting a loop statement for each affected loop");
14949}
14950
14951/// Build and return a DeclRefExpr for the floor induction variable using the
14952/// SemaRef and the provided parameters.
14953static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
14954 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
14955 return buildDeclRefExpr(S&: SemaRef, D: FloorIndVars[I], Ty: IVTy,
14956 Loc: OrigCntVar->getExprLoc());
14957}
14958
14959StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
14960 Stmt *AStmt,
14961 SourceLocation StartLoc,
14962 SourceLocation EndLoc) {
14963 ASTContext &Context = getASTContext();
14964 Scope *CurScope = SemaRef.getCurScope();
14965
14966 const auto *SizesClause =
14967 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14968 if (!SizesClause ||
14969 llvm::any_of(Range: SizesClause->getSizesRefs(), P: [](Expr *E) { return !E; }))
14970 return StmtError();
14971 unsigned NumLoops = SizesClause->getNumSizes();
14972
14973 // Empty statement should only be possible if there already was an error.
14974 if (!AStmt)
14975 return StmtError();
14976
14977 // Verify and diagnose loop nest.
14978 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14979 Stmt *Body = nullptr;
14980 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
14981 if (!checkTransformableLoopNest(Kind: OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14982 OriginalInits))
14983 return StmtError();
14984
14985 // Delay tiling to when template is completely instantiated.
14986 if (SemaRef.CurContext->isDependentContext())
14987 return OMPTileDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
14988 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
14989
14990 assert(LoopHelpers.size() == NumLoops &&
14991 "Expecting loop iteration space dimensionality to match number of "
14992 "affected loops");
14993 assert(OriginalInits.size() == NumLoops &&
14994 "Expecting loop iteration space dimensionality to match number of "
14995 "affected loops");
14996
14997 // Collect all affected loop statements.
14998 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14999 collectLoopStmts(AStmt, LoopStmts);
15000
15001 SmallVector<Stmt *, 4> PreInits;
15002 CaptureVars CopyTransformer(SemaRef);
15003
15004 // Create iteration variables for the generated loops.
15005 SmallVector<VarDecl *, 4> FloorIndVars;
15006 SmallVector<VarDecl *, 4> TileIndVars;
15007 FloorIndVars.resize(N: NumLoops);
15008 TileIndVars.resize(N: NumLoops);
15009 for (unsigned I = 0; I < NumLoops; ++I) {
15010 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15011
15012 assert(LoopHelper.Counters.size() == 1 &&
15013 "Expect single-dimensional loop iteration space");
15014 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15015 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15016 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15017 QualType CntTy = IterVarRef->getType();
15018
15019 // Iteration variable for the floor (i.e. outer) loop.
15020 {
15021 std::string FloorCntName =
15022 (Twine(".floor_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15023 VarDecl *FloorCntDecl =
15024 buildVarDecl(SemaRef, Loc: {}, Type: CntTy, Name: FloorCntName, Attrs: nullptr, OrigRef: OrigCntVar);
15025 FloorIndVars[I] = FloorCntDecl;
15026 }
15027
15028 // Iteration variable for the tile (i.e. inner) loop.
15029 {
15030 std::string TileCntName =
15031 (Twine(".tile_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15032
15033 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15034 // used by the expressions to derive the original iteration variable's
15035 // value from the logical iteration number.
15036 auto *TileCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
15037 TileCntDecl->setDeclName(
15038 &SemaRef.PP.getIdentifierTable().get(Name: TileCntName));
15039 TileIndVars[I] = TileCntDecl;
15040 }
15041
15042 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
15043 PreInits);
15044 }
15045
15046 // Once the original iteration values are set, append the innermost body.
15047 Stmt *Inner = Body;
15048
15049 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
15050 SizesClause, CurScope](int I) -> Expr * {
15051 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
15052
15053 if (DimTileSizeExpr->containsErrors())
15054 return nullptr;
15055
15056 if (isa<ConstantExpr>(Val: DimTileSizeExpr))
15057 return AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr));
15058
15059 // When the tile size is not a constant but a variable, it is possible to
15060 // pass non-positive numbers. For instance:
15061 // \code{c}
15062 // int a = 0;
15063 // #pragma omp tile sizes(a)
15064 // for (int i = 0; i < 42; ++i)
15065 // body(i);
15066 // \endcode
15067 // Although there is no meaningful interpretation of the tile size, the body
15068 // should still be executed 42 times to avoid surprises. To preserve the
15069 // invariant that every loop iteration is executed exactly once and not
15070 // cause an infinite loop, apply a minimum tile size of one.
15071 // Build expr:
15072 // \code{c}
15073 // (TS <= 0) ? 1 : TS
15074 // \endcode
15075 QualType DimTy = DimTileSizeExpr->getType();
15076 uint64_t DimWidth = Context.getTypeSize(T: DimTy);
15077 IntegerLiteral *Zero = IntegerLiteral::Create(
15078 C: Context, V: llvm::APInt::getZero(numBits: DimWidth), type: DimTy, l: {});
15079 IntegerLiteral *One =
15080 IntegerLiteral::Create(C: Context, V: llvm::APInt(DimWidth, 1), type: DimTy, l: {});
15081 Expr *Cond = AssertSuccess(R: SemaRef.BuildBinOp(
15082 S: CurScope, OpLoc: {}, Opc: BO_LE,
15083 LHSExpr: AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr)), RHSExpr: Zero));
15084 Expr *MinOne = new (Context) ConditionalOperator(
15085 Cond, {}, One, {},
15086 AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr)), DimTy,
15087 VK_PRValue, OK_Ordinary);
15088 return MinOne;
15089 };
15090
15091 // Create tile loops from the inside to the outside.
15092 for (int I = NumLoops - 1; I >= 0; --I) {
15093 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15094 Expr *NumIterations = LoopHelper.NumIterations;
15095 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15096 QualType IVTy = NumIterations->getType();
15097 Stmt *LoopStmt = LoopStmts[I];
15098
15099 // Commonly used variables. One of the constraints of an AST is that every
15100 // node object must appear at most once, hence we define a lambda that
15101 // creates a new AST node at every use.
15102 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
15103 OrigCntVar]() {
15104 return buildDeclRefExpr(S&: SemaRef, D: TileIndVars[I], Ty: IVTy,
15105 Loc: OrigCntVar->getExprLoc());
15106 };
15107
15108 // For init-statement: auto .tile.iv = .floor.iv
15109 SemaRef.AddInitializerToDecl(
15110 dcl: TileIndVars[I],
15111 init: SemaRef
15112 .DefaultLvalueConversion(
15113 E: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15114 .get(),
15115 /*DirectInit=*/false);
15116 Decl *CounterDecl = TileIndVars[I];
15117 StmtResult InitStmt = new (Context)
15118 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15119 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15120 if (!InitStmt.isUsable())
15121 return StmtError();
15122
15123 // For cond-expression:
15124 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
15125 Expr *DimTileSize = MakeDimTileSize(I);
15126 if (!DimTileSize)
15127 return StmtError();
15128 ExprResult EndOfTile = SemaRef.BuildBinOp(
15129 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
15130 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15131 RHSExpr: DimTileSize);
15132 if (!EndOfTile.isUsable())
15133 return StmtError();
15134 ExprResult IsPartialTile =
15135 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15136 LHSExpr: NumIterations, RHSExpr: EndOfTile.get());
15137 if (!IsPartialTile.isUsable())
15138 return StmtError();
15139 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
15140 QuestionLoc: LoopHelper.Cond->getBeginLoc(), ColonLoc: LoopHelper.Cond->getEndLoc(),
15141 CondExpr: IsPartialTile.get(), LHSExpr: NumIterations, RHSExpr: EndOfTile.get());
15142 if (!MinTileAndIterSpace.isUsable())
15143 return StmtError();
15144 ExprResult CondExpr =
15145 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15146 LHSExpr: MakeTileIVRef(), RHSExpr: MinTileAndIterSpace.get());
15147 if (!CondExpr.isUsable())
15148 return StmtError();
15149
15150 // For incr-statement: ++.tile.iv
15151 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15152 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeTileIVRef());
15153 if (!IncrStmt.isUsable())
15154 return StmtError();
15155
15156 // Statements to set the original iteration variable's value from the
15157 // logical iteration number.
15158 // Generated for loop is:
15159 // \code
15160 // Original_for_init;
15161 // for (auto .tile.iv = .floor.iv;
15162 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
15163 // ++.tile.iv) {
15164 // Original_Body;
15165 // Original_counter_update;
15166 // }
15167 // \endcode
15168 // FIXME: If the innermost body is an loop itself, inserting these
15169 // statements stops it being recognized as a perfectly nested loop (e.g.
15170 // for applying tiling again). If this is the case, sink the expressions
15171 // further into the inner loop.
15172 SmallVector<Stmt *, 4> BodyParts;
15173 BodyParts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
15174 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
15175 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
15176 BodyParts.push_back(Elt: Inner);
15177 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
15178 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
15179 Inner = new (Context)
15180 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15181 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15182 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15183 }
15184
15185 // Create floor loops from the inside to the outside.
15186 for (int I = NumLoops - 1; I >= 0; --I) {
15187 auto &LoopHelper = LoopHelpers[I];
15188 Expr *NumIterations = LoopHelper.NumIterations;
15189 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15190 QualType IVTy = NumIterations->getType();
15191
15192 // For init-statement: auto .floor.iv = 0
15193 SemaRef.AddInitializerToDecl(
15194 dcl: FloorIndVars[I],
15195 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
15196 /*DirectInit=*/false);
15197 Decl *CounterDecl = FloorIndVars[I];
15198 StmtResult InitStmt = new (Context)
15199 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15200 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15201 if (!InitStmt.isUsable())
15202 return StmtError();
15203
15204 // For cond-expression: .floor.iv < NumIterations
15205 ExprResult CondExpr = SemaRef.BuildBinOp(
15206 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15207 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15208 RHSExpr: NumIterations);
15209 if (!CondExpr.isUsable())
15210 return StmtError();
15211
15212 // For incr-statement: .floor.iv += DimTileSize
15213 Expr *DimTileSize = MakeDimTileSize(I);
15214 if (!DimTileSize)
15215 return StmtError();
15216 ExprResult IncrStmt = SemaRef.BuildBinOp(
15217 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
15218 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15219 RHSExpr: DimTileSize);
15220 if (!IncrStmt.isUsable())
15221 return StmtError();
15222
15223 Inner = new (Context)
15224 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15225 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15226 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15227 }
15228
15229 return OMPTileDirective::Create(C: Context, StartLoc, EndLoc, Clauses, NumLoops,
15230 AssociatedStmt: AStmt, TransformedStmt: Inner,
15231 PreInits: buildPreInits(Context, PreInits));
15232}
15233
15234StmtResult SemaOpenMP::ActOnOpenMPStripeDirective(ArrayRef<OMPClause *> Clauses,
15235 Stmt *AStmt,
15236 SourceLocation StartLoc,
15237 SourceLocation EndLoc) {
15238 ASTContext &Context = getASTContext();
15239 Scope *CurScope = SemaRef.getCurScope();
15240
15241 const auto *SizesClause =
15242 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15243 if (!SizesClause ||
15244 llvm::any_of(Range: SizesClause->getSizesRefs(), P: [](const Expr *SizeExpr) {
15245 return !SizeExpr || SizeExpr->containsErrors();
15246 }))
15247 return StmtError();
15248 unsigned NumLoops = SizesClause->getNumSizes();
15249
15250 // Empty statement should only be possible if there already was an error.
15251 if (!AStmt)
15252 return StmtError();
15253
15254 // Verify and diagnose loop nest.
15255 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
15256 Stmt *Body = nullptr;
15257 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
15258 if (!checkTransformableLoopNest(Kind: OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15259 Body, OriginalInits))
15260 return StmtError();
15261
15262 // Delay striping to when template is completely instantiated.
15263 if (SemaRef.CurContext->isDependentContext())
15264 return OMPStripeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15265 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
15266
15267 assert(LoopHelpers.size() == NumLoops &&
15268 "Expecting loop iteration space dimensionality to match number of "
15269 "affected loops");
15270 assert(OriginalInits.size() == NumLoops &&
15271 "Expecting loop iteration space dimensionality to match number of "
15272 "affected loops");
15273
15274 // Collect all affected loop statements.
15275 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15276 collectLoopStmts(AStmt, LoopStmts);
15277
15278 SmallVector<Stmt *, 4> PreInits;
15279 CaptureVars CopyTransformer(SemaRef);
15280
15281 // Create iteration variables for the generated loops.
15282 SmallVector<VarDecl *, 4> FloorIndVars;
15283 SmallVector<VarDecl *, 4> StripeIndVars;
15284 FloorIndVars.resize(N: NumLoops);
15285 StripeIndVars.resize(N: NumLoops);
15286 for (unsigned I : llvm::seq<unsigned>(Size: NumLoops)) {
15287 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15288
15289 assert(LoopHelper.Counters.size() == 1 &&
15290 "Expect single-dimensional loop iteration space");
15291 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15292 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15293 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15294 QualType CntTy = IterVarRef->getType();
15295
15296 // Iteration variable for the stripe (i.e. outer) loop.
15297 {
15298 std::string FloorCntName =
15299 (Twine(".floor_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15300 VarDecl *FloorCntDecl =
15301 buildVarDecl(SemaRef, Loc: {}, Type: CntTy, Name: FloorCntName, Attrs: nullptr, OrigRef: OrigCntVar);
15302 FloorIndVars[I] = FloorCntDecl;
15303 }
15304
15305 // Iteration variable for the stripe (i.e. inner) loop.
15306 {
15307 std::string StripeCntName =
15308 (Twine(".stripe_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15309
15310 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15311 // used by the expressions to derive the original iteration variable's
15312 // value from the logical iteration number.
15313 auto *StripeCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
15314 StripeCntDecl->setDeclName(
15315 &SemaRef.PP.getIdentifierTable().get(Name: StripeCntName));
15316 StripeIndVars[I] = StripeCntDecl;
15317 }
15318
15319 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
15320 PreInits);
15321 }
15322
15323 // Once the original iteration values are set, append the innermost body.
15324 Stmt *Inner = Body;
15325
15326 auto MakeDimStripeSize = [&](int I) -> Expr * {
15327 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15328 if (isa<ConstantExpr>(Val: DimStripeSizeExpr))
15329 return AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr));
15330
15331 // When the stripe size is not a constant but a variable, it is possible to
15332 // pass non-positive numbers. For instance:
15333 // \code{c}
15334 // int a = 0;
15335 // #pragma omp stripe sizes(a)
15336 // for (int i = 0; i < 42; ++i)
15337 // body(i);
15338 // \endcode
15339 // Although there is no meaningful interpretation of the stripe size, the
15340 // body should still be executed 42 times to avoid surprises. To preserve
15341 // the invariant that every loop iteration is executed exactly once and not
15342 // cause an infinite loop, apply a minimum stripe size of one.
15343 // Build expr:
15344 // \code{c}
15345 // (TS <= 0) ? 1 : TS
15346 // \endcode
15347 QualType DimTy = DimStripeSizeExpr->getType();
15348 uint64_t DimWidth = Context.getTypeSize(T: DimTy);
15349 IntegerLiteral *Zero = IntegerLiteral::Create(
15350 C: Context, V: llvm::APInt::getZero(numBits: DimWidth), type: DimTy, l: {});
15351 IntegerLiteral *One =
15352 IntegerLiteral::Create(C: Context, V: llvm::APInt(DimWidth, 1), type: DimTy, l: {});
15353 Expr *Cond = AssertSuccess(R: SemaRef.BuildBinOp(
15354 S: CurScope, OpLoc: {}, Opc: BO_LE,
15355 LHSExpr: AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr)), RHSExpr: Zero));
15356 Expr *MinOne = new (Context) ConditionalOperator(
15357 Cond, {}, One, {},
15358 AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr)), DimTy,
15359 VK_PRValue, OK_Ordinary);
15360 return MinOne;
15361 };
15362
15363 // Create stripe loops from the inside to the outside.
15364 for (int I = NumLoops - 1; I >= 0; --I) {
15365 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15366 Expr *NumIterations = LoopHelper.NumIterations;
15367 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15368 QualType IVTy = NumIterations->getType();
15369 Stmt *LoopStmt = LoopStmts[I];
15370
15371 // For init-statement: auto .stripe.iv = .floor.iv
15372 SemaRef.AddInitializerToDecl(
15373 dcl: StripeIndVars[I],
15374 init: SemaRef
15375 .DefaultLvalueConversion(
15376 E: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15377 .get(),
15378 /*DirectInit=*/false);
15379 Decl *CounterDecl = StripeIndVars[I];
15380 StmtResult InitStmt = new (Context)
15381 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15382 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15383 if (!InitStmt.isUsable())
15384 return StmtError();
15385
15386 // For cond-expression:
15387 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
15388 ExprResult EndOfStripe = SemaRef.BuildBinOp(
15389 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
15390 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15391 RHSExpr: MakeDimStripeSize(I));
15392 if (!EndOfStripe.isUsable())
15393 return StmtError();
15394 ExprResult IsPartialStripe =
15395 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15396 LHSExpr: NumIterations, RHSExpr: EndOfStripe.get());
15397 if (!IsPartialStripe.isUsable())
15398 return StmtError();
15399 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
15400 QuestionLoc: LoopHelper.Cond->getBeginLoc(), ColonLoc: LoopHelper.Cond->getEndLoc(),
15401 CondExpr: IsPartialStripe.get(), LHSExpr: NumIterations, RHSExpr: EndOfStripe.get());
15402 if (!MinStripeAndIterSpace.isUsable())
15403 return StmtError();
15404 ExprResult CondExpr = SemaRef.BuildBinOp(
15405 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15406 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars: StripeIndVars, I, IVTy, OrigCntVar),
15407 RHSExpr: MinStripeAndIterSpace.get());
15408 if (!CondExpr.isUsable())
15409 return StmtError();
15410
15411 // For incr-statement: ++.stripe.iv
15412 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15413 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc,
15414 Input: makeFloorIVRef(SemaRef, FloorIndVars: StripeIndVars, I, IVTy, OrigCntVar));
15415 if (!IncrStmt.isUsable())
15416 return StmtError();
15417
15418 // Statements to set the original iteration variable's value from the
15419 // logical iteration number.
15420 // Generated for loop is:
15421 // \code
15422 // Original_for_init;
15423 // for (auto .stripe.iv = .floor.iv;
15424 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
15425 // ++.stripe.iv) {
15426 // Original_Body;
15427 // Original_counter_update;
15428 // }
15429 // \endcode
15430 // FIXME: If the innermost body is a loop itself, inserting these
15431 // statements stops it being recognized as a perfectly nested loop (e.g.
15432 // for applying another loop transformation). If this is the case, sink the
15433 // expressions further into the inner loop.
15434 SmallVector<Stmt *, 4> BodyParts;
15435 BodyParts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
15436 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
15437 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
15438 BodyParts.push_back(Elt: Inner);
15439 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
15440 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
15441 Inner = new (Context)
15442 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15443 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15444 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15445 }
15446
15447 // Create grid loops from the inside to the outside.
15448 for (int I = NumLoops - 1; I >= 0; --I) {
15449 auto &LoopHelper = LoopHelpers[I];
15450 Expr *NumIterations = LoopHelper.NumIterations;
15451 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15452 QualType IVTy = NumIterations->getType();
15453
15454 // For init-statement: auto .grid.iv = 0
15455 SemaRef.AddInitializerToDecl(
15456 dcl: FloorIndVars[I],
15457 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
15458 /*DirectInit=*/false);
15459 Decl *CounterDecl = FloorIndVars[I];
15460 StmtResult InitStmt = new (Context)
15461 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15462 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15463 if (!InitStmt.isUsable())
15464 return StmtError();
15465
15466 // For cond-expression: .floor.iv < NumIterations
15467 ExprResult CondExpr = SemaRef.BuildBinOp(
15468 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15469 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15470 RHSExpr: NumIterations);
15471 if (!CondExpr.isUsable())
15472 return StmtError();
15473
15474 // For incr-statement: .floor.iv += DimStripeSize
15475 ExprResult IncrStmt = SemaRef.BuildBinOp(
15476 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
15477 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15478 RHSExpr: MakeDimStripeSize(I));
15479 if (!IncrStmt.isUsable())
15480 return StmtError();
15481
15482 Inner = new (Context)
15483 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15484 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15485 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15486 }
15487
15488 return OMPStripeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15489 NumLoops, AssociatedStmt: AStmt, TransformedStmt: Inner,
15490 PreInits: buildPreInits(Context, PreInits));
15491}
15492
15493StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
15494 Stmt *AStmt,
15495 SourceLocation StartLoc,
15496 SourceLocation EndLoc) {
15497 ASTContext &Context = getASTContext();
15498 Scope *CurScope = SemaRef.getCurScope();
15499 // Empty statement should only be possible if there already was an error.
15500 if (!AStmt)
15501 return StmtError();
15502
15503 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
15504 MutuallyExclusiveClauses: {OMPC_partial, OMPC_full}))
15505 return StmtError();
15506
15507 const OMPFullClause *FullClause =
15508 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15509 const OMPPartialClause *PartialClause =
15510 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15511 assert(!(FullClause && PartialClause) &&
15512 "mutual exclusivity must have been checked before");
15513
15514 constexpr unsigned NumLoops = 1;
15515 Stmt *Body = nullptr;
15516 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
15517 NumLoops);
15518 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15519 if (!checkTransformableLoopNest(Kind: OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15520 Body, OriginalInits))
15521 return StmtError();
15522
15523 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15524
15525 // Delay unrolling to when template is completely instantiated.
15526 if (SemaRef.CurContext->isDependentContext())
15527 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
15528 NumGeneratedTopLevelLoops, TransformedStmt: nullptr,
15529 PreInits: nullptr);
15530
15531 assert(LoopHelpers.size() == NumLoops &&
15532 "Expecting a single-dimensional loop iteration space");
15533 assert(OriginalInits.size() == NumLoops &&
15534 "Expecting a single-dimensional loop iteration space");
15535 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15536
15537 if (FullClause) {
15538 if (!VerifyPositiveIntegerConstantInClause(
15539 Op: LoopHelper.NumIterations, CKind: OMPC_full, /*StrictlyPositive=*/false,
15540 /*SuppressExprDiags=*/true)
15541 .isUsable()) {
15542 Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_unroll_full_variable_trip_count);
15543 Diag(Loc: FullClause->getBeginLoc(), DiagID: diag::note_omp_directive_here)
15544 << "#pragma omp unroll full";
15545 return StmtError();
15546 }
15547 }
15548
15549 // The generated loop may only be passed to other loop-associated directive
15550 // when a partial clause is specified. Without the requirement it is
15551 // sufficient to generate loop unroll metadata at code-generation.
15552 if (NumGeneratedTopLevelLoops == 0)
15553 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
15554 NumGeneratedTopLevelLoops, TransformedStmt: nullptr,
15555 PreInits: nullptr);
15556
15557 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15558 // associated with another loop directive.
15559 //
15560 // The canonical loop analysis return by checkTransformableLoopNest assumes
15561 // the following structure to be the same loop without transformations or
15562 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15563 // LoopHelper.Counters;
15564 // for (; IV < LoopHelper.NumIterations; ++IV) {
15565 // LoopHelper.Updates;
15566 // Body;
15567 // }
15568 // \endcode
15569 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15570 // and referenced by LoopHelper.IterationVarRef.
15571 //
15572 // The unrolling directive transforms this into the following loop:
15573 // \code
15574 // OriginalInits; \
15575 // LoopHelper.PreInits; > NewPreInits
15576 // LoopHelper.Counters; /
15577 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15578 // #pragma clang loop unroll_count(Factor)
15579 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15580 // {
15581 // LoopHelper.Updates;
15582 // Body;
15583 // }
15584 // }
15585 // \endcode
15586 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15587 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15588 // references it. If the partially unrolled loop is associated with another
15589 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15590 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15591 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15592 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15593 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15594 // property of the OMPLoopBasedDirective instead of statements in
15595 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15596 // of a canonical loop nest where these PreInits are emitted before the
15597 // outermost directive.
15598
15599 // Find the loop statement.
15600 Stmt *LoopStmt = nullptr;
15601 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
15602
15603 // Determine the PreInit declarations.
15604 SmallVector<Stmt *, 4> PreInits;
15605 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
15606
15607 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15608 QualType IVTy = IterationVarRef->getType();
15609 assert(LoopHelper.Counters.size() == 1 &&
15610 "Expecting a single-dimensional loop iteration space");
15611 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15612
15613 // Determine the unroll factor.
15614 uint64_t Factor;
15615 SourceLocation FactorLoc;
15616 if (Expr *FactorVal = PartialClause->getFactor();
15617 FactorVal && !FactorVal->containsErrors()) {
15618 Factor = FactorVal->getIntegerConstantExpr(Ctx: Context)->getZExtValue();
15619 FactorLoc = FactorVal->getExprLoc();
15620 } else {
15621 // TODO: Use a better profitability model.
15622 Factor = 2;
15623 }
15624 assert(Factor > 0 && "Expected positive unroll factor");
15625 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15626 return IntegerLiteral::Create(
15627 C: getASTContext(), V: llvm::APInt(getASTContext().getIntWidth(T: IVTy), Factor),
15628 type: IVTy, l: FactorLoc);
15629 };
15630
15631 // Iteration variable SourceLocations.
15632 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15633 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15634 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15635
15636 // Internal variable names.
15637 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15638 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15639 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15640
15641 // Create the iteration variable for the unrolled loop.
15642 VarDecl *OuterIVDecl =
15643 buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: OuterIVName, Attrs: nullptr, OrigRef: OrigVar);
15644 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15645 return buildDeclRefExpr(S&: SemaRef, D: OuterIVDecl, Ty: IVTy, Loc: OrigVarLoc);
15646 };
15647
15648 // Iteration variable for the inner loop: Reuse the iteration variable created
15649 // by checkOpenMPLoop.
15650 auto *InnerIVDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
15651 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name: InnerIVName));
15652 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15653 return buildDeclRefExpr(S&: SemaRef, D: InnerIVDecl, Ty: IVTy, Loc: OrigVarLoc);
15654 };
15655
15656 // Make a copy of the NumIterations expression for each use: By the AST
15657 // constraints, every expression object in a DeclContext must be unique.
15658 CaptureVars CopyTransformer(SemaRef);
15659 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15660 return AssertSuccess(
15661 R: CopyTransformer.TransformExpr(E: LoopHelper.NumIterations));
15662 };
15663
15664 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15665 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(E: MakeOuterRef());
15666 SemaRef.AddInitializerToDecl(dcl: InnerIVDecl, init: LValueConv.get(),
15667 /*DirectInit=*/false);
15668 StmtResult InnerInit = new (Context)
15669 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15670 if (!InnerInit.isUsable())
15671 return StmtError();
15672
15673 // Inner For cond-expression:
15674 // \code
15675 // .unroll_inner.iv < .unrolled.iv + Factor &&
15676 // .unroll_inner.iv < NumIterations
15677 // \endcode
15678 // This conjunction of two conditions allows ScalarEvolution to derive the
15679 // maximum trip count of the inner loop.
15680 ExprResult EndOfTile =
15681 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
15682 LHSExpr: MakeOuterRef(), RHSExpr: MakeFactorExpr());
15683 if (!EndOfTile.isUsable())
15684 return StmtError();
15685 ExprResult InnerCond1 =
15686 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15687 LHSExpr: MakeInnerRef(), RHSExpr: EndOfTile.get());
15688 if (!InnerCond1.isUsable())
15689 return StmtError();
15690 ExprResult InnerCond2 =
15691 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15692 LHSExpr: MakeInnerRef(), RHSExpr: MakeNumIterations());
15693 if (!InnerCond2.isUsable())
15694 return StmtError();
15695 ExprResult InnerCond =
15696 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LAnd,
15697 LHSExpr: InnerCond1.get(), RHSExpr: InnerCond2.get());
15698 if (!InnerCond.isUsable())
15699 return StmtError();
15700
15701 // Inner For incr-statement: ++.unroll_inner.iv
15702 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15703 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeInnerRef());
15704 if (!InnerIncr.isUsable())
15705 return StmtError();
15706
15707 // Inner For statement.
15708 SmallVector<Stmt *> InnerBodyStmts;
15709 InnerBodyStmts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
15710 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
15711 InnerBodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
15712 InnerBodyStmts.push_back(Elt: Body);
15713 CompoundStmt *InnerBody =
15714 CompoundStmt::Create(C: getASTContext(), Stmts: InnerBodyStmts, FPFeatures: FPOptionsOverride(),
15715 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
15716 ForStmt *InnerFor = new (Context)
15717 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15718 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15719 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15720
15721 // Unroll metadata for the inner loop.
15722 // This needs to take into account the remainder portion of the unrolled loop,
15723 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15724 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15725 // the maximum trip count, which will also generate a remainder loop. Just
15726 // `unroll(enable)` (which could have been useful if the user has not
15727 // specified a concrete factor; even though the outer loop cannot be
15728 // influenced anymore, would avoid more code bloat than necessary) will refuse
15729 // the loop because "Won't unroll; remainder loop could not be generated when
15730 // assuming runtime trip count". Even if it did work, it must not choose a
15731 // larger unroll factor than the maximum loop length, or it would always just
15732 // execute the remainder loop.
15733 LoopHintAttr *UnrollHintAttr =
15734 LoopHintAttr::CreateImplicit(Ctx&: Context, Option: LoopHintAttr::UnrollCount,
15735 State: LoopHintAttr::Numeric, Value: MakeFactorExpr());
15736 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15737 C: getASTContext(), Loc: StartLoc, Attrs: {UnrollHintAttr}, SubStmt: InnerFor);
15738
15739 // Outer For init-statement: auto .unrolled.iv = 0
15740 SemaRef.AddInitializerToDecl(
15741 dcl: OuterIVDecl,
15742 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
15743 /*DirectInit=*/false);
15744 StmtResult OuterInit = new (Context)
15745 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15746 if (!OuterInit.isUsable())
15747 return StmtError();
15748
15749 // Outer For cond-expression: .unrolled.iv < NumIterations
15750 ExprResult OuterConde =
15751 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15752 LHSExpr: MakeOuterRef(), RHSExpr: MakeNumIterations());
15753 if (!OuterConde.isUsable())
15754 return StmtError();
15755
15756 // Outer For incr-statement: .unrolled.iv += Factor
15757 ExprResult OuterIncr =
15758 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
15759 LHSExpr: MakeOuterRef(), RHSExpr: MakeFactorExpr());
15760 if (!OuterIncr.isUsable())
15761 return StmtError();
15762
15763 // Outer For statement.
15764 ForStmt *OuterFor = new (Context)
15765 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15766 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15767 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15768
15769 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
15770 NumGeneratedTopLevelLoops, TransformedStmt: OuterFor,
15771 PreInits: buildPreInits(Context, PreInits));
15772}
15773
15774StmtResult SemaOpenMP::ActOnOpenMPReverseDirective(Stmt *AStmt,
15775 SourceLocation StartLoc,
15776 SourceLocation EndLoc) {
15777 ASTContext &Context = getASTContext();
15778 Scope *CurScope = SemaRef.getCurScope();
15779
15780 // Empty statement should only be possible if there already was an error.
15781 if (!AStmt)
15782 return StmtError();
15783
15784 constexpr unsigned NumLoops = 1;
15785 Stmt *Body = nullptr;
15786 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
15787 NumLoops);
15788 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15789 if (!checkTransformableLoopNest(Kind: OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15790 Body, OriginalInits))
15791 return StmtError();
15792
15793 // Delay applying the transformation to when template is completely
15794 // instantiated.
15795 if (SemaRef.CurContext->isDependentContext())
15796 return OMPReverseDirective::Create(C: Context, StartLoc, EndLoc, AssociatedStmt: AStmt,
15797 NumLoops, TransformedStmt: nullptr, PreInits: nullptr);
15798
15799 assert(LoopHelpers.size() == NumLoops &&
15800 "Expecting a single-dimensional loop iteration space");
15801 assert(OriginalInits.size() == NumLoops &&
15802 "Expecting a single-dimensional loop iteration space");
15803 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15804
15805 // Find the loop statement.
15806 Stmt *LoopStmt = nullptr;
15807 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
15808
15809 // Determine the PreInit declarations.
15810 SmallVector<Stmt *> PreInits;
15811 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
15812
15813 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15814 QualType IVTy = IterationVarRef->getType();
15815 uint64_t IVWidth = Context.getTypeSize(T: IVTy);
15816 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15817
15818 // Iteration variable SourceLocations.
15819 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15820 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15821 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15822
15823 // Locations pointing to the transformation.
15824 SourceLocation TransformLoc = StartLoc;
15825 SourceLocation TransformLocBegin = StartLoc;
15826 SourceLocation TransformLocEnd = EndLoc;
15827
15828 // Internal variable names.
15829 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15830 SmallString<64> ForwardIVName(".forward.iv.");
15831 ForwardIVName += OrigVarName;
15832 SmallString<64> ReversedIVName(".reversed.iv.");
15833 ReversedIVName += OrigVarName;
15834
15835 // LoopHelper.Updates will read the logical iteration number from
15836 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
15837 // that logical iteration from it, then assign it to the user loop counter
15838 // variable. We cannot directly use LoopHelper.IterationVarRef as the
15839 // induction variable of the generated loop because it may cause an underflow:
15840 // \code{.c}
15841 // for (unsigned i = 0; i < n; ++i)
15842 // body(i);
15843 // \endcode
15844 //
15845 // Naive reversal:
15846 // \code{.c}
15847 // for (unsigned i = n-1; i >= 0; --i)
15848 // body(i);
15849 // \endcode
15850 //
15851 // Instead, we introduce a new iteration variable representing the logical
15852 // iteration counter of the original loop, convert it to the logical iteration
15853 // number of the reversed loop, then let LoopHelper.Updates compute the user's
15854 // loop iteration variable from it.
15855 // \code{.cpp}
15856 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
15857 // auto .reversed.iv = n - .forward.iv - 1;
15858 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
15859 // body(i); // Body
15860 // }
15861 // \endcode
15862
15863 // Subexpressions with more than one use. One of the constraints of an AST is
15864 // that every node object must appear at most once, hence we define a lambda
15865 // that creates a new AST node at every use.
15866 CaptureVars CopyTransformer(SemaRef);
15867 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15868 return AssertSuccess(
15869 R: CopyTransformer.TransformExpr(E: LoopHelper.NumIterations));
15870 };
15871
15872 // Create the iteration variable for the forward loop (from 0 to n-1).
15873 VarDecl *ForwardIVDecl =
15874 buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: ForwardIVName, Attrs: nullptr, OrigRef: OrigVar);
15875 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15876 OrigVarLoc]() {
15877 return buildDeclRefExpr(S&: SemaRef, D: ForwardIVDecl, Ty: IVTy, Loc: OrigVarLoc);
15878 };
15879
15880 // Iteration variable for the reversed induction variable (from n-1 downto 0):
15881 // Reuse the iteration variable created by checkOpenMPLoop.
15882 auto *ReversedIVDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
15883 ReversedIVDecl->setDeclName(
15884 &SemaRef.PP.getIdentifierTable().get(Name: ReversedIVName));
15885
15886 // For init-statement:
15887 // \code{.cpp}
15888 // auto .forward.iv = 0;
15889 // \endcode
15890 auto *Zero = IntegerLiteral::Create(C: Context, V: llvm::APInt::getZero(numBits: IVWidth),
15891 type: ForwardIVDecl->getType(), l: OrigVarLoc);
15892 SemaRef.AddInitializerToDecl(dcl: ForwardIVDecl, init: Zero, /*DirectInit=*/false);
15893 StmtResult Init = new (Context)
15894 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15895 if (!Init.isUsable())
15896 return StmtError();
15897
15898 // Forward iv cond-expression:
15899 // \code{.cpp}
15900 // .forward.iv < MakeNumIterations()
15901 // \endcode
15902 ExprResult Cond =
15903 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15904 LHSExpr: MakeForwardRef(), RHSExpr: MakeNumIterations());
15905 if (!Cond.isUsable())
15906 return StmtError();
15907
15908 // Forward incr-statement:
15909 // \code{.c}
15910 // ++.forward.iv
15911 // \endcode
15912 ExprResult Incr = SemaRef.BuildUnaryOp(S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(),
15913 Opc: UO_PreInc, Input: MakeForwardRef());
15914 if (!Incr.isUsable())
15915 return StmtError();
15916
15917 // Reverse the forward-iv:
15918 // \code{.cpp}
15919 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
15920 // \endcode
15921 auto *One = IntegerLiteral::Create(C: Context, V: llvm::APInt(IVWidth, 1), type: IVTy,
15922 l: TransformLoc);
15923 ExprResult Minus = SemaRef.BuildBinOp(S: CurScope, OpLoc: TransformLoc, Opc: BO_Sub,
15924 LHSExpr: MakeNumIterations(), RHSExpr: One);
15925 if (!Minus.isUsable())
15926 return StmtError();
15927 Minus = SemaRef.BuildBinOp(S: CurScope, OpLoc: TransformLoc, Opc: BO_Sub, LHSExpr: Minus.get(),
15928 RHSExpr: MakeForwardRef());
15929 if (!Minus.isUsable())
15930 return StmtError();
15931 StmtResult InitReversed = new (Context) DeclStmt(
15932 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15933 if (!InitReversed.isUsable())
15934 return StmtError();
15935 SemaRef.AddInitializerToDecl(dcl: ReversedIVDecl, init: Minus.get(),
15936 /*DirectInit=*/false);
15937
15938 // The new loop body.
15939 SmallVector<Stmt *, 4> BodyStmts;
15940 BodyStmts.reserve(N: LoopHelper.Updates.size() + 2 +
15941 (isa<CXXForRangeStmt>(Val: LoopStmt) ? 1 : 0));
15942 BodyStmts.push_back(Elt: InitReversed.get());
15943 llvm::append_range(C&: BodyStmts, R&: LoopHelper.Updates);
15944 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
15945 BodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
15946 BodyStmts.push_back(Elt: Body);
15947 auto *ReversedBody =
15948 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
15949 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
15950
15951 // Finally create the reversed For-statement.
15952 auto *ReversedFor = new (Context)
15953 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
15954 ReversedBody, LoopHelper.Init->getBeginLoc(),
15955 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15956 return OMPReverseDirective::Create(C: Context, StartLoc, EndLoc, AssociatedStmt: AStmt, NumLoops,
15957 TransformedStmt: ReversedFor,
15958 PreInits: buildPreInits(Context, PreInits));
15959}
15960
15961/// Build the AST for \#pragma omp split counts(c1, c2, ...).
15962///
15963/// Splits the single associated loop into N consecutive loops, where N is the
15964/// number of count expressions.
15965StmtResult SemaOpenMP::ActOnOpenMPSplitDirective(ArrayRef<OMPClause *> Clauses,
15966 Stmt *AStmt,
15967 SourceLocation StartLoc,
15968 SourceLocation EndLoc) {
15969 ASTContext &Context = getASTContext();
15970 Scope *CurScope = SemaRef.getCurScope();
15971
15972 // Empty statement should only be possible if there already was an error.
15973 if (!AStmt)
15974 return StmtError();
15975
15976 const auto *CountsClause =
15977 OMPExecutableDirective::getSingleClause<OMPCountsClause>(Clauses);
15978 if (!CountsClause)
15979 return StmtError();
15980
15981 // Split applies to a single loop; check it is transformable and get helpers.
15982 constexpr unsigned NumLoops = 1;
15983 Stmt *Body = nullptr;
15984 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
15985 NumLoops);
15986 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15987 if (!checkTransformableLoopNest(Kind: OMPD_split, AStmt, NumLoops, LoopHelpers,
15988 Body, OriginalInits))
15989 return StmtError();
15990
15991 // Delay applying the transformation to when template is completely
15992 // instantiated.
15993 if (SemaRef.CurContext->isDependentContext())
15994 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15995 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
15996
15997 assert(LoopHelpers.size() == NumLoops &&
15998 "Expecting a single-dimensional loop iteration space");
15999 assert(OriginalInits.size() == NumLoops &&
16000 "Expecting a single-dimensional loop iteration space");
16001 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
16002
16003 // Find the loop statement.
16004 Stmt *LoopStmt = nullptr;
16005 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
16006
16007 // Determine the PreInit declarations.
16008 SmallVector<Stmt *> PreInits;
16009 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
16010
16011 // Type and name of the original loop variable; we create one IV per segment
16012 // and assign it to the original var so the body sees the same name.
16013 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
16014 QualType IVTy = IterationVarRef->getType();
16015 uint64_t IVWidth = Context.getTypeSize(T: IVTy);
16016 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
16017
16018 // Iteration variable SourceLocations.
16019 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
16020 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
16021 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
16022 // Internal variable names.
16023 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
16024
16025 if (!CountsClause->hasOmpFill())
16026 return StmtError();
16027 unsigned FillIdx = *CountsClause->getOmpFillIndex();
16028
16029 unsigned NumItems = CountsClause->getNumCounts();
16030 SmallVector<uint64_t, 4> CountValues(NumItems, 0);
16031 ArrayRef<Expr *> Refs = CountsClause->getCountsRefs();
16032 for (unsigned I = 0; I < NumItems; ++I) {
16033 if (I == FillIdx)
16034 continue;
16035 Expr *CountExpr = Refs[I];
16036 if (!CountExpr)
16037 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16038 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16039 std::optional<llvm::APSInt> OptVal =
16040 CountExpr->getIntegerConstantExpr(Ctx: Context);
16041 if (!OptVal || OptVal->isNegative())
16042 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16043 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16044 CountValues[I] = OptVal->getZExtValue();
16045 }
16046
16047 Expr *NumIterExpr = LoopHelper.NumIterations;
16048
16049 uint64_t RightSum = 0;
16050 for (unsigned I = FillIdx + 1; I < NumItems; ++I)
16051 RightSum += CountValues[I];
16052
16053 auto MakeIntLit = [&](uint64_t Val) {
16054 return IntegerLiteral::Create(C: Context, V: llvm::APInt(IVWidth, Val), type: IVTy,
16055 l: OrigVarLoc);
16056 };
16057
16058 size_t NumSegments = NumItems;
16059 SmallVector<Stmt *, 4> SplitLoops;
16060
16061 auto *IterVarDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
16062 SplitLoops.push_back(Elt: new (Context) DeclStmt(DeclGroupRef(IterVarDecl),
16063 IterationVarRef->getBeginLoc(),
16064 IterationVarRef->getEndLoc()));
16065
16066 uint64_t LeftAccum = 0;
16067 uint64_t RightRemaining = RightSum;
16068
16069 for (size_t Seg = 0; Seg < NumSegments; ++Seg) {
16070 Expr *StartExpr = nullptr;
16071 Expr *EndExpr = nullptr;
16072
16073 if (Seg < FillIdx) {
16074 StartExpr = MakeIntLit(LeftAccum);
16075 LeftAccum += CountValues[Seg];
16076 EndExpr = MakeIntLit(LeftAccum);
16077 } else if (Seg == FillIdx) {
16078 StartExpr = MakeIntLit(LeftAccum);
16079 if (RightRemaining == 0) {
16080 EndExpr = NumIterExpr;
16081 } else {
16082 ExprResult Sub =
16083 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16084 RHSExpr: MakeIntLit(RightRemaining));
16085 if (!Sub.isUsable())
16086 return StmtError();
16087 EndExpr = Sub.get();
16088 }
16089 } else {
16090 if (RightRemaining == RightSum) {
16091 if (RightSum == 0)
16092 StartExpr = NumIterExpr;
16093 else {
16094 ExprResult Sub =
16095 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16096 RHSExpr: MakeIntLit(RightRemaining));
16097 if (!Sub.isUsable())
16098 return StmtError();
16099 StartExpr = Sub.get();
16100 }
16101 } else {
16102 ExprResult Sub =
16103 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16104 RHSExpr: MakeIntLit(RightRemaining));
16105 if (!Sub.isUsable())
16106 return StmtError();
16107 StartExpr = Sub.get();
16108 }
16109 RightRemaining -= CountValues[Seg];
16110 if (RightRemaining == 0)
16111 EndExpr = NumIterExpr;
16112 else {
16113 ExprResult Sub =
16114 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16115 RHSExpr: MakeIntLit(RightRemaining));
16116 if (!Sub.isUsable())
16117 return StmtError();
16118 EndExpr = Sub.get();
16119 }
16120 }
16121
16122 SmallString<64> IVName(".split.iv.");
16123 IVName += (Twine(Seg) + "." + OrigVarName).str();
16124 VarDecl *IVDecl = buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: IVName, Attrs: nullptr, OrigRef: OrigVar);
16125 auto MakeIVRef = [&SemaRef = this->SemaRef, IVDecl, IVTy, OrigVarLoc]() {
16126 return buildDeclRefExpr(S&: SemaRef, D: IVDecl, Ty: IVTy, Loc: OrigVarLoc);
16127 };
16128
16129 SemaRef.AddInitializerToDecl(dcl: IVDecl, init: StartExpr, /*DirectInit=*/false);
16130 StmtResult InitStmt = new (Context)
16131 DeclStmt(DeclGroupRef(IVDecl), OrigVarLocBegin, OrigVarLocEnd);
16132 if (!InitStmt.isUsable())
16133 return StmtError();
16134
16135 ExprResult CondExpr = SemaRef.BuildBinOp(
16136 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT, LHSExpr: MakeIVRef(), RHSExpr: EndExpr);
16137 if (!CondExpr.isUsable())
16138 return StmtError();
16139
16140 ExprResult IncrExpr = SemaRef.BuildUnaryOp(
16141 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeIVRef());
16142 if (!IncrExpr.isUsable())
16143 return StmtError();
16144
16145 ExprResult IVAssign = SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Assign,
16146 LHSExpr: IterationVarRef, RHSExpr: MakeIVRef());
16147 if (!IVAssign.isUsable())
16148 return StmtError();
16149
16150 SmallVector<Stmt *, 4> BodyStmts;
16151 BodyStmts.push_back(Elt: IVAssign.get());
16152 BodyStmts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
16153 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt)) {
16154 if (Seg == 0) {
16155 BodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
16156 } else {
16157 VarDecl *LoopVar = CXXRangeFor->getLoopVariable();
16158 DeclRefExpr *LVRef = buildDeclRefExpr(
16159 S&: SemaRef, D: LoopVar, Ty: LoopVar->getType().getNonReferenceType(),
16160 Loc: OrigVarLoc);
16161 ExprResult LVAssign = SemaRef.BuildBinOp(
16162 S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Assign, LHSExpr: LVRef, RHSExpr: LoopVar->getInit());
16163 if (!LVAssign.isUsable())
16164 return StmtError();
16165 BodyStmts.push_back(Elt: LVAssign.get());
16166 }
16167 }
16168 BodyStmts.push_back(Elt: Body);
16169
16170 auto *LoopBody =
16171 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
16172 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
16173
16174 auto *For = new (Context)
16175 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
16176 IncrExpr.get(), LoopBody, LoopHelper.Init->getBeginLoc(),
16177 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16178 SplitLoops.push_back(Elt: For);
16179 }
16180
16181 auto *SplitStmt = CompoundStmt::Create(
16182 C: Context, Stmts: SplitLoops, FPFeatures: FPOptionsOverride(),
16183 LB: SplitLoops.front()->getBeginLoc(), RB: SplitLoops.back()->getEndLoc());
16184
16185 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses, NumLoops,
16186 AssociatedStmt: AStmt, TransformedStmt: SplitStmt,
16187 PreInits: buildPreInits(Context, PreInits));
16188}
16189
16190StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
16191 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
16192 SourceLocation EndLoc) {
16193 ASTContext &Context = getASTContext();
16194 DeclContext *CurContext = SemaRef.CurContext;
16195 Scope *CurScope = SemaRef.getCurScope();
16196
16197 // Empty statement should only be possible if there already was an error.
16198 if (!AStmt)
16199 return StmtError();
16200
16201 // interchange without permutation clause swaps two loops.
16202 const OMPPermutationClause *PermutationClause =
16203 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
16204 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
16205
16206 // Verify and diagnose loop nest.
16207 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
16208 Stmt *Body = nullptr;
16209 SmallVector<SmallVector<Stmt *>, 2> OriginalInits;
16210 if (!checkTransformableLoopNest(Kind: OMPD_interchange, AStmt, NumLoops,
16211 LoopHelpers, Body, OriginalInits))
16212 return StmtError();
16213
16214 // Delay interchange to when template is completely instantiated.
16215 if (CurContext->isDependentContext())
16216 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16217 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16218
16219 // An invalid expression in the permutation clause is set to nullptr in
16220 // ActOnOpenMPPermutationClause.
16221 if (PermutationClause &&
16222 llvm::is_contained(Range: PermutationClause->getArgsRefs(), Element: nullptr))
16223 return StmtError();
16224
16225 assert(LoopHelpers.size() == NumLoops &&
16226 "Expecting loop iteration space dimensionaly to match number of "
16227 "affected loops");
16228 assert(OriginalInits.size() == NumLoops &&
16229 "Expecting loop iteration space dimensionaly to match number of "
16230 "affected loops");
16231
16232 // Decode the permutation clause.
16233 SmallVector<uint64_t, 2> Permutation;
16234 if (!PermutationClause) {
16235 Permutation = {1, 0};
16236 } else {
16237 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
16238 llvm::BitVector Flags(PermArgs.size());
16239 for (Expr *PermArg : PermArgs) {
16240 std::optional<llvm::APSInt> PermCstExpr =
16241 PermArg->getIntegerConstantExpr(Ctx: Context);
16242 if (!PermCstExpr)
16243 continue;
16244 uint64_t PermInt = PermCstExpr->getZExtValue();
16245 assert(1 <= PermInt && PermInt <= NumLoops &&
16246 "Must be a permutation; diagnostic emitted in "
16247 "ActOnOpenMPPermutationClause");
16248 if (Flags[PermInt - 1]) {
16249 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
16250 Diag(Loc: PermArg->getExprLoc(),
16251 DiagID: diag::err_omp_interchange_permutation_value_repeated)
16252 << PermInt << ExprRange;
16253 continue;
16254 }
16255 Flags[PermInt - 1] = true;
16256
16257 Permutation.push_back(Elt: PermInt - 1);
16258 }
16259
16260 if (Permutation.size() != NumLoops)
16261 return StmtError();
16262 }
16263
16264 // Nothing to transform with trivial permutation.
16265 if (NumLoops <= 1 || llvm::all_of(Range: llvm::enumerate(First&: Permutation), P: [](auto P) {
16266 auto [Idx, Arg] = P;
16267 return Idx == Arg;
16268 }))
16269 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16270 NumLoops, AssociatedStmt: AStmt, TransformedStmt: AStmt, PreInits: nullptr);
16271
16272 // Find the affected loops.
16273 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
16274 collectLoopStmts(AStmt, LoopStmts);
16275
16276 // Collect pre-init statements on the order before the permuation.
16277 SmallVector<Stmt *> PreInits;
16278 for (auto I : llvm::seq<int>(Size: NumLoops)) {
16279 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16280
16281 assert(LoopHelper.Counters.size() == 1 &&
16282 "Single-dimensional loop iteration space expected");
16283
16284 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
16285 PreInits);
16286 }
16287
16288 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
16289 CaptureVars CopyTransformer(SemaRef);
16290
16291 // Create the permuted loops from the inside to the outside of the
16292 // interchanged loop nest. Body of the innermost new loop is the original
16293 // innermost body.
16294 Stmt *Inner = Body;
16295 for (auto TargetIdx : llvm::reverse(C: llvm::seq<int>(Size: NumLoops))) {
16296 // Get the original loop that belongs to this new position.
16297 uint64_t SourceIdx = Permutation[TargetIdx];
16298 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
16299 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
16300 assert(SourceHelper.Counters.size() == 1 &&
16301 "Single-dimensional loop iteration space expected");
16302 auto *OrigCntVar = cast<DeclRefExpr>(Val: SourceHelper.Counters.front());
16303
16304 // Normalized loop counter variable: From 0 to n-1, always an integer type.
16305 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: SourceHelper.IterationVarRef);
16306 QualType IVTy = IterVarRef->getType();
16307 assert(IVTy->isIntegerType() &&
16308 "Expected the logical iteration counter to be an integer");
16309
16310 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
16311 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
16312
16313 // Make a copy of the NumIterations expression for each use: By the AST
16314 // constraints, every expression object in a DeclContext must be unique.
16315 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
16316 return AssertSuccess(
16317 R: CopyTransformer.TransformExpr(E: SourceHelper.NumIterations));
16318 };
16319
16320 // Iteration variable for the permuted loop. Reuse the one from
16321 // checkOpenMPLoop which will also be used to update the original loop
16322 // variable.
16323 SmallString<64> PermutedCntName(".permuted_");
16324 PermutedCntName.append(Refs: {llvm::utostr(X: TargetIdx), ".iv.", OrigVarName});
16325 auto *PermutedCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
16326 PermutedCntDecl->setDeclName(
16327 &SemaRef.PP.getIdentifierTable().get(Name: PermutedCntName));
16328 PermutedIndVars[TargetIdx] = PermutedCntDecl;
16329 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
16330 return buildDeclRefExpr(S&: SemaRef, D: PermutedCntDecl, Ty: IVTy, Loc: OrigVarLoc);
16331 };
16332
16333 // For init-statement:
16334 // \code
16335 // auto .permuted_{target}.iv = 0
16336 // \endcode
16337 ExprResult Zero = SemaRef.ActOnIntegerConstant(Loc: OrigVarLoc, Val: 0);
16338 if (!Zero.isUsable())
16339 return StmtError();
16340 SemaRef.AddInitializerToDecl(dcl: PermutedCntDecl, init: Zero.get(),
16341 /*DirectInit=*/false);
16342 StmtResult InitStmt = new (Context)
16343 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
16344 OrigCntVar->getEndLoc());
16345 if (!InitStmt.isUsable())
16346 return StmtError();
16347
16348 // For cond-expression:
16349 // \code
16350 // .permuted_{target}.iv < MakeNumIterations()
16351 // \endcode
16352 ExprResult CondExpr =
16353 SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceHelper.Cond->getExprLoc(), Opc: BO_LT,
16354 LHSExpr: MakePermutedRef(), RHSExpr: MakeNumIterations());
16355 if (!CondExpr.isUsable())
16356 return StmtError();
16357
16358 // For incr-statement:
16359 // \code
16360 // ++.tile.iv
16361 // \endcode
16362 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
16363 S: CurScope, OpLoc: SourceHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakePermutedRef());
16364 if (!IncrStmt.isUsable())
16365 return StmtError();
16366
16367 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
16368 SourceHelper.Updates.end());
16369 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: SourceLoopStmt))
16370 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
16371 BodyParts.push_back(Elt: Inner);
16372 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
16373 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
16374 Inner = new (Context) ForStmt(
16375 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
16376 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
16377 SourceHelper.Inc->getEndLoc());
16378 }
16379
16380 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16381 NumLoops, AssociatedStmt: AStmt, TransformedStmt: Inner,
16382 PreInits: buildPreInits(Context, PreInits));
16383}
16384
16385StmtResult SemaOpenMP::ActOnOpenMPFuseDirective(ArrayRef<OMPClause *> Clauses,
16386 Stmt *AStmt,
16387 SourceLocation StartLoc,
16388 SourceLocation EndLoc) {
16389
16390 ASTContext &Context = getASTContext();
16391 DeclContext *CurrContext = SemaRef.CurContext;
16392 Scope *CurScope = SemaRef.getCurScope();
16393 CaptureVars CopyTransformer(SemaRef);
16394
16395 // Ensure the structured block is not empty
16396 if (!AStmt)
16397 return StmtError();
16398
16399 // Defer transformation in dependent contexts
16400 // The NumLoopNests argument is set to a placeholder 1 (even though
16401 // using looprange fuse could yield up to 3 top level loop nests)
16402 // because a dependent context could prevent determining its true value
16403 if (CurrContext->isDependentContext())
16404 return OMPFuseDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16405 /* NumLoops */ NumGeneratedTopLevelLoops: 1, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16406
16407 // Validate that the potential loop sequence is transformable for fusion
16408 // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops
16409 LoopSequenceAnalysis SeqAnalysis;
16410 if (!checkTransformableLoopSequence(Kind: OMPD_fuse, AStmt, SeqAnalysis, Context))
16411 return StmtError();
16412
16413 // SeqAnalysis.LoopSeqSize exists mostly to handle dependent contexts,
16414 // otherwise it must be the same as SeqAnalysis.Loops.size().
16415 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16416 "Inconsistent size of the loop sequence and the number of loops "
16417 "found in the sequence");
16418
16419 // Handle clauses, which can be any of the following: [looprange, apply]
16420 const auto *LRC =
16421 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16422
16423 // The clause arguments are invalidated if any error arises
16424 // such as non-constant or non-positive arguments
16425 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16426 return StmtError();
16427
16428 // Delayed semantic check of LoopRange constraint
16429 // Evaluates the loop range arguments and returns the first and count values
16430 auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count,
16431 uint64_t &FirstVal,
16432 uint64_t &CountVal) {
16433 llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Ctx: Context);
16434 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Ctx: Context);
16435 FirstVal = FirstInt.getZExtValue();
16436 CountVal = CountInt.getZExtValue();
16437 };
16438
16439 // OpenMP [6.0, Restrictions]
16440 // first + count - 1 must not evaluate to a value greater than the
16441 // loop sequence length of the associated canonical loop sequence.
16442 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16443 unsigned NumLoops) -> bool {
16444 return FirstVal + CountVal - 1 <= NumLoops;
16445 };
16446 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16447
16448 // Validates the loop range after evaluating the semantic information
16449 // and ensures that the range is valid for the given loop sequence size.
16450 // Expressions are evaluated at compile time to obtain constant values.
16451 if (LRC) {
16452 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16453 CountVal);
16454 if (CountVal == 1)
16455 SemaRef.Diag(Loc: LRC->getCountLoc(), DiagID: diag::warn_omp_redundant_fusion)
16456 << getOpenMPDirectiveName(D: OMPD_fuse);
16457
16458 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16459 SemaRef.Diag(Loc: LRC->getFirstLoc(), DiagID: diag::err_omp_invalid_looprange)
16460 << getOpenMPDirectiveName(D: OMPD_fuse) << FirstVal
16461 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16462 return StmtError();
16463 }
16464
16465 LastVal = FirstVal + CountVal - 1;
16466 }
16467
16468 // Complete fusion generates a single canonical loop nest
16469 // However looprange clause may generate several loop nests
16470 unsigned NumGeneratedTopLevelLoops =
16471 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16472
16473 // Emit a warning for redundant loop fusion when the sequence contains only
16474 // one loop.
16475 if (SeqAnalysis.LoopSeqSize == 1)
16476 SemaRef.Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::warn_omp_redundant_fusion)
16477 << getOpenMPDirectiveName(D: OMPD_fuse);
16478
16479 // Select the type with the largest bit width among all induction variables
16480 QualType IVType =
16481 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16482 for (unsigned I : llvm::seq<unsigned>(Begin: FirstVal, End: LastVal)) {
16483 QualType CurrentIVType =
16484 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16485 if (Context.getTypeSize(T: CurrentIVType) > Context.getTypeSize(T: IVType)) {
16486 IVType = CurrentIVType;
16487 }
16488 }
16489 uint64_t IVBitWidth = Context.getIntWidth(T: IVType);
16490
16491 // Create pre-init declarations for all loops lower bounds, upper bounds,
16492 // strides and num-iterations for every top level loop in the fusion
16493 SmallVector<VarDecl *, 4> LBVarDecls;
16494 SmallVector<VarDecl *, 4> STVarDecls;
16495 SmallVector<VarDecl *, 4> NIVarDecls;
16496 SmallVector<VarDecl *, 4> UBVarDecls;
16497 SmallVector<VarDecl *, 4> IVVarDecls;
16498
16499 // Helper lambda to create variables for bounds, strides, and other
16500 // expressions. Generates both the variable declaration and the corresponding
16501 // initialization statement.
16502 auto CreateHelperVarAndStmt =
16503 [&, &SemaRef = SemaRef](Expr *ExprToCopy, const std::string &BaseName,
16504 unsigned I, bool NeedsNewVD = false) {
16505 Expr *TransformedExpr =
16506 AssertSuccess(R: CopyTransformer.TransformExpr(E: ExprToCopy));
16507 if (!TransformedExpr)
16508 return std::pair<VarDecl *, StmtResult>(nullptr, StmtError());
16509
16510 auto Name = (Twine(".omp.") + BaseName + std::to_string(val: I)).str();
16511
16512 VarDecl *VD;
16513 if (NeedsNewVD) {
16514 VD = buildVarDecl(SemaRef, Loc: SourceLocation(), Type: IVType, Name);
16515 SemaRef.AddInitializerToDecl(dcl: VD, init: TransformedExpr, DirectInit: false);
16516 } else {
16517 // Create a unique variable name
16518 DeclRefExpr *DRE = cast<DeclRefExpr>(Val: TransformedExpr);
16519 VD = cast<VarDecl>(Val: DRE->getDecl());
16520 VD->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name));
16521 }
16522 // Create the corresponding declaration statement
16523 StmtResult DeclStmt = new (Context) class DeclStmt(
16524 DeclGroupRef(VD), SourceLocation(), SourceLocation());
16525 return std::make_pair(x&: VD, y&: DeclStmt);
16526 };
16527
16528 // PreInits hold a sequence of variable declarations that must be executed
16529 // before the fused loop begins. These include bounds, strides, and other
16530 // helper variables required for the transformation. Other loop transforms
16531 // also contain their own preinits
16532 SmallVector<Stmt *> PreInits;
16533
16534 // Update the general preinits using the preinits generated by loop sequence
16535 // generating loop transformations. These preinits differ slightly from
16536 // single-loop transformation preinits, as they can be detached from a
16537 // specific loop inside multiple generated loop nests. This happens
16538 // because certain helper variables, like '.omp.fuse.max', are introduced to
16539 // handle fused iteration spaces and may not be directly tied to a single
16540 // original loop. The preinit structure must ensure that hidden variables
16541 // like '.omp.fuse.max' are still properly handled.
16542 // Transformations that apply this concept: Loopranged Fuse, Split
16543 llvm::append_range(C&: PreInits, R&: SeqAnalysis.LoopSequencePreInits);
16544
16545 // Process each single loop to generate and collect declarations
16546 // and statements for all helper expressions related to
16547 // particular single loop nests
16548
16549 // Also In the case of the fused loops, we keep track of their original
16550 // inits by appending them to their preinits statement, and in the case of
16551 // transformations, also append their preinits (which contain the original
16552 // loop initialization statement or other statements)
16553
16554 // Firstly we need to set TransformIndex to match the begining of the
16555 // looprange section
16556 unsigned int TransformIndex = 0;
16557 for (unsigned I : llvm::seq<unsigned>(Size: FirstVal - 1)) {
16558 if (SeqAnalysis.Loops[I].isLoopTransformation())
16559 ++TransformIndex;
16560 }
16561
16562 for (unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16563 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16564 addLoopPreInits(Context, LoopHelper&: SeqAnalysis.Loops[I].HelperExprs,
16565 LoopStmt: SeqAnalysis.Loops[I].TheForStmt,
16566 OriginalInit: SeqAnalysis.Loops[I].OriginalInits, PreInits);
16567 } else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16568 // For transformed loops, insert both pre-inits and original inits.
16569 // Order matters: pre-inits may define variables used in the original
16570 // inits such as upper bounds...
16571 SmallVector<Stmt *> &TransformPreInit =
16572 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16573 llvm::append_range(C&: PreInits, R&: TransformPreInit);
16574
16575 addLoopPreInits(Context, LoopHelper&: SeqAnalysis.Loops[I].HelperExprs,
16576 LoopStmt: SeqAnalysis.Loops[I].TheForStmt,
16577 OriginalInit: SeqAnalysis.Loops[I].OriginalInits, PreInits);
16578 }
16579 auto [UBVD, UBDStmt] =
16580 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB, "ub", J);
16581 auto [LBVD, LBDStmt] =
16582 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB, "lb", J);
16583 auto [STVD, STDStmt] =
16584 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST, "st", J);
16585 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16586 SeqAnalysis.Loops[I].HelperExprs.NumIterations, "ni", J, true);
16587 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16588 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef, "iv", J);
16589
16590 assert(LBVD && STVD && NIVD && IVVD &&
16591 "OpenMP Fuse Helper variables creation failed");
16592
16593 UBVarDecls.push_back(Elt: UBVD);
16594 LBVarDecls.push_back(Elt: LBVD);
16595 STVarDecls.push_back(Elt: STVD);
16596 NIVarDecls.push_back(Elt: NIVD);
16597 IVVarDecls.push_back(Elt: IVVD);
16598
16599 PreInits.push_back(Elt: LBDStmt.get());
16600 PreInits.push_back(Elt: STDStmt.get());
16601 PreInits.push_back(Elt: NIDStmt.get());
16602 PreInits.push_back(Elt: IVDStmt.get());
16603 }
16604
16605 auto MakeVarDeclRef = [&SemaRef = this->SemaRef](VarDecl *VD) {
16606 return buildDeclRefExpr(S&: SemaRef, D: VD, Ty: VD->getType(), Loc: VD->getLocation(),
16607 RefersToCapture: false);
16608 };
16609
16610 // Following up the creation of the final fused loop will be performed
16611 // which has the following shape (considering the selected loops):
16612 //
16613 // for (fuse.index = 0; fuse.index < max(ni0, ni1..., nik); ++fuse.index) {
16614 // if (fuse.index < ni0){
16615 // iv0 = lb0 + st0 * fuse.index;
16616 // original.index0 = iv0
16617 // body(0);
16618 // }
16619 // if (fuse.index < ni1){
16620 // iv1 = lb1 + st1 * fuse.index;
16621 // original.index1 = iv1
16622 // body(1);
16623 // }
16624 //
16625 // ...
16626 //
16627 // if (fuse.index < nik){
16628 // ivk = lbk + stk * fuse.index;
16629 // original.indexk = ivk
16630 // body(k); Expr *InitVal = IntegerLiteral::Create(Context,
16631 // llvm::APInt(IVWidth, 0),
16632 // }
16633
16634 // 1. Create the initialized fuse index
16635 StringRef IndexName = ".omp.fuse.index";
16636 Expr *InitVal = IntegerLiteral::Create(C: Context, V: llvm::APInt(IVBitWidth, 0),
16637 type: IVType, l: SourceLocation());
16638 VarDecl *IndexDecl =
16639 buildVarDecl(SemaRef, Loc: {}, Type: IVType, Name: IndexName, Attrs: nullptr, OrigRef: nullptr);
16640 SemaRef.AddInitializerToDecl(dcl: IndexDecl, init: InitVal, DirectInit: false);
16641 StmtResult InitStmt = new (Context)
16642 DeclStmt(DeclGroupRef(IndexDecl), SourceLocation(), SourceLocation());
16643
16644 if (!InitStmt.isUsable())
16645 return StmtError();
16646
16647 auto MakeIVRef = [&SemaRef = this->SemaRef, IndexDecl, IVType,
16648 Loc = InitVal->getExprLoc()]() {
16649 return buildDeclRefExpr(S&: SemaRef, D: IndexDecl, Ty: IVType, Loc, RefersToCapture: false);
16650 };
16651
16652 // 2. Iteratively compute the max number of logical iterations Max(NI_1, NI_2,
16653 // ..., NI_k)
16654 //
16655 // This loop accumulates the maximum value across multiple expressions,
16656 // ensuring each step constructs a unique AST node for correctness. By using
16657 // intermediate temporary variables and conditional operators, we maintain
16658 // distinct nodes and avoid duplicating subtrees, For instance, max(a,b,c):
16659 // omp.temp0 = max(a, b)
16660 // omp.temp1 = max(omp.temp0, c)
16661 // omp.fuse.max = max(omp.temp1, omp.temp0)
16662
16663 ExprResult MaxExpr;
16664 // I is the range of loops in the sequence that we fuse.
16665 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16666 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16667 QualType NITy = NIRef->getType();
16668
16669 if (MaxExpr.isUnset()) {
16670 // Initialize MaxExpr with the first NI expression
16671 MaxExpr = NIRef;
16672 } else {
16673 // Create a new acummulator variable t_i = MaxExpr
16674 std::string TempName = (Twine(".omp.temp.") + Twine(J)).str();
16675 VarDecl *TempDecl =
16676 buildVarDecl(SemaRef, Loc: {}, Type: NITy, Name: TempName, Attrs: nullptr, OrigRef: nullptr);
16677 TempDecl->setInit(MaxExpr.get());
16678 DeclRefExpr *TempRef =
16679 buildDeclRefExpr(S&: SemaRef, D: TempDecl, Ty: NITy, Loc: SourceLocation(), RefersToCapture: false);
16680 DeclRefExpr *TempRef2 =
16681 buildDeclRefExpr(S&: SemaRef, D: TempDecl, Ty: NITy, Loc: SourceLocation(), RefersToCapture: false);
16682 // Add a DeclStmt to PreInits to ensure the variable is declared.
16683 StmtResult TempStmt = new (Context)
16684 DeclStmt(DeclGroupRef(TempDecl), SourceLocation(), SourceLocation());
16685
16686 if (!TempStmt.isUsable())
16687 return StmtError();
16688 PreInits.push_back(Elt: TempStmt.get());
16689
16690 // Build MaxExpr <-(MaxExpr > NIRef ? MaxExpr : NIRef)
16691 ExprResult Comparison =
16692 SemaRef.BuildBinOp(S: nullptr, OpLoc: SourceLocation(), Opc: BO_GT, LHSExpr: TempRef, RHSExpr: NIRef);
16693 // Handle any errors in Comparison creation
16694 if (!Comparison.isUsable())
16695 return StmtError();
16696
16697 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
16698 // Update MaxExpr using a conditional expression to hold the max value
16699 MaxExpr = new (Context) ConditionalOperator(
16700 Comparison.get(), SourceLocation(), TempRef2, SourceLocation(),
16701 NIRef2->getExprStmt(), NITy, VK_LValue, OK_Ordinary);
16702
16703 if (!MaxExpr.isUsable())
16704 return StmtError();
16705 }
16706 }
16707 if (!MaxExpr.isUsable())
16708 return StmtError();
16709
16710 // 3. Declare the max variable
16711 const std::string MaxName = Twine(".omp.fuse.max").str();
16712 VarDecl *MaxDecl =
16713 buildVarDecl(SemaRef, Loc: {}, Type: IVType, Name: MaxName, Attrs: nullptr, OrigRef: nullptr);
16714 MaxDecl->setInit(MaxExpr.get());
16715 DeclRefExpr *MaxRef = buildDeclRefExpr(S&: SemaRef, D: MaxDecl, Ty: IVType, Loc: {}, RefersToCapture: false);
16716 StmtResult MaxStmt = new (Context)
16717 DeclStmt(DeclGroupRef(MaxDecl), SourceLocation(), SourceLocation());
16718
16719 if (MaxStmt.isInvalid())
16720 return StmtError();
16721 PreInits.push_back(Elt: MaxStmt.get());
16722
16723 // 4. Create condition Expr: index < n_max
16724 ExprResult CondExpr = SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_LT,
16725 LHSExpr: MakeIVRef(), RHSExpr: MaxRef);
16726 if (!CondExpr.isUsable())
16727 return StmtError();
16728
16729 // 5. Increment Expr: ++index
16730 ExprResult IncrExpr =
16731 SemaRef.BuildUnaryOp(S: CurScope, OpLoc: SourceLocation(), Opc: UO_PreInc, Input: MakeIVRef());
16732 if (!IncrExpr.isUsable())
16733 return StmtError();
16734
16735 // 6. Build the Fused Loop Body
16736 // The final fused loop iterates over the maximum logical range. Inside the
16737 // loop, each original loop's index is calculated dynamically, and its body
16738 // is executed conditionally.
16739 //
16740 // Each sub-loop's body is guarded by a conditional statement to ensure
16741 // it executes only within its logical iteration range:
16742 //
16743 // if (fuse.index < ni_k){
16744 // iv_k = lb_k + st_k * fuse.index;
16745 // original.index = iv_k
16746 // body(k);
16747 // }
16748
16749 CompoundStmt *FusedBody = nullptr;
16750 SmallVector<Stmt *, 4> FusedBodyStmts;
16751 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16752 // Assingment of the original sub-loop index to compute the logical index
16753 // IV_k = LB_k + omp.fuse.index * ST_k
16754 ExprResult IdxExpr =
16755 SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_Mul,
16756 LHSExpr: MakeVarDeclRef(STVarDecls[J]), RHSExpr: MakeIVRef());
16757 if (!IdxExpr.isUsable())
16758 return StmtError();
16759 IdxExpr = SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_Add,
16760 LHSExpr: MakeVarDeclRef(LBVarDecls[J]), RHSExpr: IdxExpr.get());
16761
16762 if (!IdxExpr.isUsable())
16763 return StmtError();
16764 IdxExpr = SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_Assign,
16765 LHSExpr: MakeVarDeclRef(IVVarDecls[J]), RHSExpr: IdxExpr.get());
16766 if (!IdxExpr.isUsable())
16767 return StmtError();
16768
16769 // Update the original i_k = IV_k
16770 SmallVector<Stmt *, 4> BodyStmts;
16771 BodyStmts.push_back(Elt: IdxExpr.get());
16772 llvm::append_range(C&: BodyStmts, R&: SeqAnalysis.Loops[I].HelperExprs.Updates);
16773
16774 // If the loop is a CXXForRangeStmt then the iterator variable is needed
16775 if (auto *SourceCXXFor =
16776 dyn_cast<CXXForRangeStmt>(Val: SeqAnalysis.Loops[I].TheForStmt))
16777 BodyStmts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
16778
16779 Stmt *Body =
16780 (isa<ForStmt>(Val: SeqAnalysis.Loops[I].TheForStmt))
16781 ? cast<ForStmt>(Val: SeqAnalysis.Loops[I].TheForStmt)->getBody()
16782 : cast<CXXForRangeStmt>(Val: SeqAnalysis.Loops[I].TheForStmt)->getBody();
16783 BodyStmts.push_back(Elt: Body);
16784
16785 CompoundStmt *CombinedBody =
16786 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
16787 LB: SourceLocation(), RB: SourceLocation());
16788 ExprResult Condition =
16789 SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_LT, LHSExpr: MakeIVRef(),
16790 RHSExpr: MakeVarDeclRef(NIVarDecls[J]));
16791
16792 if (!Condition.isUsable())
16793 return StmtError();
16794
16795 IfStmt *IfStatement = IfStmt::Create(
16796 Ctx: Context, IL: SourceLocation(), Kind: IfStatementKind::Ordinary, Init: nullptr, Var: nullptr,
16797 Cond: Condition.get(), LPL: SourceLocation(), RPL: SourceLocation(), Then: CombinedBody,
16798 EL: SourceLocation(), Else: nullptr);
16799
16800 FusedBodyStmts.push_back(Elt: IfStatement);
16801 }
16802 FusedBody = CompoundStmt::Create(C: Context, Stmts: FusedBodyStmts, FPFeatures: FPOptionsOverride(),
16803 LB: SourceLocation(), RB: SourceLocation());
16804
16805 // 7. Construct the final fused loop
16806 ForStmt *FusedForStmt = new (Context)
16807 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, IncrExpr.get(),
16808 FusedBody, InitStmt.get()->getBeginLoc(), SourceLocation(),
16809 IncrExpr.get()->getEndLoc());
16810
16811 // In the case of looprange, the result of fuse won't simply
16812 // be a single loop (ForStmt), but rather a loop sequence
16813 // (CompoundStmt) of 3 parts: the pre-fusion loops, the fused loop
16814 // and the post-fusion loops, preserving its original order.
16815 //
16816 // Note: If looprange clause produces a single fused loop nest then
16817 // this compound statement wrapper is unnecessary (Therefore this
16818 // treatment is skipped)
16819
16820 Stmt *FusionStmt = FusedForStmt;
16821 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
16822 SmallVector<Stmt *, 4> FinalLoops;
16823
16824 // Reset the transform index
16825 TransformIndex = 0;
16826
16827 // Collect all non-fused loops before and after the fused region.
16828 // Pre-fusion and post-fusion loops are inserted in order exploiting their
16829 // symmetry, along with their corresponding transformation pre-inits if
16830 // needed. The fused loop is added between the two regions.
16831 for (unsigned I : llvm::seq<unsigned>(Size: SeqAnalysis.LoopSeqSize)) {
16832 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
16833 // Update the Transformation counter to skip already treated
16834 // loop transformations
16835 if (!SeqAnalysis.Loops[I].isLoopTransformation())
16836 ++TransformIndex;
16837 continue;
16838 }
16839
16840 // No need to handle:
16841 // Regular loops: they are kept intact as-is.
16842 // Loop-sequence-generating transformations: already handled earlier.
16843 // Only TransformSingleLoop requires inserting pre-inits here
16844 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16845 const auto &TransformPreInit =
16846 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16847 if (!TransformPreInit.empty())
16848 llvm::append_range(C&: PreInits, R: TransformPreInit);
16849 }
16850
16851 FinalLoops.push_back(Elt: SeqAnalysis.Loops[I].TheForStmt);
16852 }
16853
16854 FinalLoops.insert(I: FinalLoops.begin() + (FirstVal - 1), Elt: FusedForStmt);
16855 FusionStmt = CompoundStmt::Create(C: Context, Stmts: FinalLoops, FPFeatures: FPOptionsOverride(),
16856 LB: SourceLocation(), RB: SourceLocation());
16857 }
16858 return OMPFuseDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16859 NumGeneratedTopLevelLoops, AssociatedStmt: AStmt, TransformedStmt: FusionStmt,
16860 PreInits: buildPreInits(Context, PreInits));
16861}
16862
16863OMPClause *SemaOpenMP::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
16864 Expr *Expr,
16865 SourceLocation StartLoc,
16866 SourceLocation LParenLoc,
16867 SourceLocation EndLoc) {
16868 OMPClause *Res = nullptr;
16869 switch (Kind) {
16870 case OMPC_final:
16871 Res = ActOnOpenMPFinalClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
16872 break;
16873 case OMPC_safelen:
16874 Res = ActOnOpenMPSafelenClause(Length: Expr, StartLoc, LParenLoc, EndLoc);
16875 break;
16876 case OMPC_simdlen:
16877 Res = ActOnOpenMPSimdlenClause(Length: Expr, StartLoc, LParenLoc, EndLoc);
16878 break;
16879 case OMPC_allocator:
16880 Res = ActOnOpenMPAllocatorClause(Allocator: Expr, StartLoc, LParenLoc, EndLoc);
16881 break;
16882 case OMPC_collapse:
16883 Res = ActOnOpenMPCollapseClause(NumForLoops: Expr, StartLoc, LParenLoc, EndLoc);
16884 break;
16885 case OMPC_ordered:
16886 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, NumForLoops: Expr);
16887 break;
16888 case OMPC_nowait:
16889 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc, LParenLoc, Condition: Expr);
16890 break;
16891 case OMPC_priority:
16892 Res = ActOnOpenMPPriorityClause(Priority: Expr, StartLoc, LParenLoc, EndLoc);
16893 break;
16894 case OMPC_hint:
16895 Res = ActOnOpenMPHintClause(Hint: Expr, StartLoc, LParenLoc, EndLoc);
16896 break;
16897 case OMPC_depobj:
16898 Res = ActOnOpenMPDepobjClause(Depobj: Expr, StartLoc, LParenLoc, EndLoc);
16899 break;
16900 case OMPC_detach:
16901 Res = ActOnOpenMPDetachClause(Evt: Expr, StartLoc, LParenLoc, EndLoc);
16902 break;
16903 case OMPC_novariants:
16904 Res = ActOnOpenMPNovariantsClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
16905 break;
16906 case OMPC_nocontext:
16907 Res = ActOnOpenMPNocontextClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
16908 break;
16909 case OMPC_filter:
16910 Res = ActOnOpenMPFilterClause(ThreadID: Expr, StartLoc, LParenLoc, EndLoc);
16911 break;
16912 case OMPC_partial:
16913 Res = ActOnOpenMPPartialClause(FactorExpr: Expr, StartLoc, LParenLoc, EndLoc);
16914 break;
16915 case OMPC_message:
16916 Res = ActOnOpenMPMessageClause(MS: Expr, StartLoc, LParenLoc, EndLoc);
16917 break;
16918 case OMPC_align:
16919 Res = ActOnOpenMPAlignClause(Alignment: Expr, StartLoc, LParenLoc, EndLoc);
16920 break;
16921 case OMPC_ompx_dyn_cgroup_mem:
16922 Res = ActOnOpenMPXDynCGroupMemClause(Size: Expr, StartLoc, LParenLoc, EndLoc);
16923 break;
16924 case OMPC_holds:
16925 Res = ActOnOpenMPHoldsClause(E: Expr, StartLoc, LParenLoc, EndLoc);
16926 break;
16927 case OMPC_transparent:
16928 Res = ActOnOpenMPTransparentClause(Transparent: Expr, StartLoc, LParenLoc, EndLoc);
16929 break;
16930 case OMPC_dyn_groupprivate:
16931 case OMPC_grainsize:
16932 case OMPC_num_tasks:
16933 case OMPC_num_threads:
16934 case OMPC_device:
16935 case OMPC_if:
16936 case OMPC_default:
16937 case OMPC_proc_bind:
16938 case OMPC_schedule:
16939 case OMPC_private:
16940 case OMPC_firstprivate:
16941 case OMPC_lastprivate:
16942 case OMPC_shared:
16943 case OMPC_reduction:
16944 case OMPC_task_reduction:
16945 case OMPC_in_reduction:
16946 case OMPC_linear:
16947 case OMPC_aligned:
16948 case OMPC_copyin:
16949 case OMPC_copyprivate:
16950 case OMPC_untied:
16951 case OMPC_mergeable:
16952 case OMPC_threadprivate:
16953 case OMPC_groupprivate:
16954 case OMPC_sizes:
16955 case OMPC_allocate:
16956 case OMPC_flush:
16957 case OMPC_read:
16958 case OMPC_write:
16959 case OMPC_update:
16960 case OMPC_capture:
16961 case OMPC_compare:
16962 case OMPC_seq_cst:
16963 case OMPC_acq_rel:
16964 case OMPC_acquire:
16965 case OMPC_release:
16966 case OMPC_relaxed:
16967 case OMPC_depend:
16968 case OMPC_threads:
16969 case OMPC_simd:
16970 case OMPC_map:
16971 case OMPC_nogroup:
16972 case OMPC_dist_schedule:
16973 case OMPC_defaultmap:
16974 case OMPC_unknown:
16975 case OMPC_uniform:
16976 case OMPC_to:
16977 case OMPC_from:
16978 case OMPC_use_device_ptr:
16979 case OMPC_use_device_addr:
16980 case OMPC_is_device_ptr:
16981 case OMPC_unified_address:
16982 case OMPC_unified_shared_memory:
16983 case OMPC_reverse_offload:
16984 case OMPC_dynamic_allocators:
16985 case OMPC_atomic_default_mem_order:
16986 case OMPC_self_maps:
16987 case OMPC_device_type:
16988 case OMPC_match:
16989 case OMPC_nontemporal:
16990 case OMPC_order:
16991 case OMPC_at:
16992 case OMPC_severity:
16993 case OMPC_destroy:
16994 case OMPC_inclusive:
16995 case OMPC_exclusive:
16996 case OMPC_uses_allocators:
16997 case OMPC_affinity:
16998 case OMPC_when:
16999 case OMPC_bind:
17000 case OMPC_num_teams:
17001 case OMPC_thread_limit:
17002 default:
17003 llvm_unreachable("Clause is not allowed.");
17004 }
17005 return Res;
17006}
17007
17008// An OpenMP directive such as 'target parallel' has two captured regions:
17009// for the 'target' and 'parallel' respectively. This function returns
17010// the region in which to capture expressions associated with a clause.
17011// A return value of OMPD_unknown signifies that the expression should not
17012// be captured.
17013static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
17014 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
17015 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
17016 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
17017 "Invalid directive with CKind-clause");
17018
17019 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
17020 if (NameModifier != OMPD_unknown &&
17021 !isAllowedClauseForDirective(D: NameModifier, C: CKind, Version: OpenMPVersion))
17022 return OMPD_unknown;
17023
17024 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(D: DKind);
17025
17026 // [5.2:341:24-30]
17027 // If the clauses have expressions on them, such as for various clauses where
17028 // the argument of the clause is an expression, or lower-bound, length, or
17029 // stride expressions inside array sections (or subscript and stride
17030 // expressions in subscript-triplet for Fortran), or linear-step or alignment
17031 // expressions, the expressions are evaluated immediately before the construct
17032 // to which the clause has been split or duplicated per the above rules
17033 // (therefore inside of the outer leaf constructs). However, the expressions
17034 // inside the num_teams and thread_limit clauses are always evaluated before
17035 // the outermost leaf construct.
17036
17037 // Process special cases first.
17038 switch (CKind) {
17039 case OMPC_if:
17040 switch (DKind) {
17041 case OMPD_teams_loop:
17042 case OMPD_target_teams_loop:
17043 // For [target] teams loop, assume capture region is 'teams' so it's
17044 // available for codegen later to use if/when necessary.
17045 return OMPD_teams;
17046 case OMPD_target_update:
17047 case OMPD_target_enter_data:
17048 case OMPD_target_exit_data:
17049 return OMPD_task;
17050 default:
17051 break;
17052 }
17053 break;
17054 case OMPC_num_teams:
17055 case OMPC_thread_limit:
17056 case OMPC_ompx_dyn_cgroup_mem:
17057 case OMPC_dyn_groupprivate:
17058 // TODO: This may need to consider teams too.
17059 if (Leafs[0] == OMPD_target)
17060 return OMPD_target;
17061 break;
17062 case OMPC_device:
17063 if (Leafs[0] == OMPD_target ||
17064 llvm::is_contained(Set: {OMPD_dispatch, OMPD_target_update,
17065 OMPD_target_enter_data, OMPD_target_exit_data},
17066 Element: DKind))
17067 return OMPD_task;
17068 break;
17069 case OMPC_novariants:
17070 case OMPC_nocontext:
17071 if (DKind == OMPD_dispatch)
17072 return OMPD_task;
17073 break;
17074 case OMPC_when:
17075 if (DKind == OMPD_metadirective)
17076 return OMPD_metadirective;
17077 break;
17078 case OMPC_filter:
17079 return OMPD_unknown;
17080 default:
17081 break;
17082 }
17083
17084 // If none of the special cases above applied, and DKind is a capturing
17085 // directive, find the innermost enclosing leaf construct that allows the
17086 // clause, and returns the corresponding capture region.
17087
17088 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
17089 // Find the index in "Leafs" of the last leaf that allows the given
17090 // clause. The search will only include indexes [0, EndIdx).
17091 // EndIdx may be set to the index of the NameModifier, if present.
17092 int InnermostIdx = [&]() {
17093 for (int I = EndIdx - 1; I >= 0; --I) {
17094 if (isAllowedClauseForDirective(D: Leafs[I], C: Clause, Version: OpenMPVersion))
17095 return I;
17096 }
17097 return -1;
17098 }();
17099
17100 // Find the nearest enclosing capture region.
17101 SmallVector<OpenMPDirectiveKind, 2> Regions;
17102 for (int I = InnermostIdx - 1; I >= 0; --I) {
17103 if (!isOpenMPCapturingDirective(DKind: Leafs[I]))
17104 continue;
17105 Regions.clear();
17106 getOpenMPCaptureRegions(CaptureRegions&: Regions, DKind: Leafs[I]);
17107 if (Regions[0] != OMPD_unknown)
17108 return Regions.back();
17109 }
17110 return OMPD_unknown;
17111 };
17112
17113 if (isOpenMPCapturingDirective(DKind)) {
17114 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
17115 for (int I = 0, E = Leafs.size(); I != E; ++I) {
17116 if (Leafs[I] == Dir)
17117 return I + 1;
17118 }
17119 return 0;
17120 };
17121
17122 int End = NameModifier == OMPD_unknown ? Leafs.size()
17123 : GetLeafIndex(NameModifier);
17124 return GetEnclosingRegion(End, CKind);
17125 }
17126
17127 return OMPD_unknown;
17128}
17129
17130OMPClause *SemaOpenMP::ActOnOpenMPIfClause(
17131 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
17132 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
17133 SourceLocation ColonLoc, SourceLocation EndLoc) {
17134 Expr *ValExpr = Condition;
17135 Stmt *HelperValStmt = nullptr;
17136 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17137 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17138 !Condition->isInstantiationDependent() &&
17139 !Condition->containsUnexpandedParameterPack()) {
17140 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
17141 if (Val.isInvalid())
17142 return nullptr;
17143
17144 ValExpr = Val.get();
17145
17146 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17147 CaptureRegion = getOpenMPCaptureRegionForClause(
17148 DKind, CKind: OMPC_if, OpenMPVersion: getLangOpts().OpenMP, NameModifier);
17149 if (CaptureRegion != OMPD_unknown &&
17150 !SemaRef.CurContext->isDependentContext()) {
17151 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17152 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17153 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17154 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
17155 }
17156 }
17157
17158 return new (getASTContext())
17159 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
17160 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
17161}
17162
17163OMPClause *SemaOpenMP::ActOnOpenMPFinalClause(Expr *Condition,
17164 SourceLocation StartLoc,
17165 SourceLocation LParenLoc,
17166 SourceLocation EndLoc) {
17167 Expr *ValExpr = Condition;
17168 Stmt *HelperValStmt = nullptr;
17169 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17170 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17171 !Condition->isInstantiationDependent() &&
17172 !Condition->containsUnexpandedParameterPack()) {
17173 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
17174 if (Val.isInvalid())
17175 return nullptr;
17176
17177 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
17178
17179 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17180 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_final,
17181 OpenMPVersion: getLangOpts().OpenMP);
17182 if (CaptureRegion != OMPD_unknown &&
17183 !SemaRef.CurContext->isDependentContext()) {
17184 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17185 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17186 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17187 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
17188 }
17189 }
17190
17191 return new (getASTContext()) OMPFinalClause(
17192 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17193}
17194
17195ExprResult
17196SemaOpenMP::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
17197 Expr *Op) {
17198 if (!Op)
17199 return ExprError();
17200
17201 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
17202 public:
17203 IntConvertDiagnoser()
17204 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
17205 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
17206 QualType T) override {
17207 return S.Diag(Loc, DiagID: diag::err_omp_not_integral) << T;
17208 }
17209 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
17210 QualType T) override {
17211 return S.Diag(Loc, DiagID: diag::err_omp_incomplete_type) << T;
17212 }
17213 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
17214 QualType T,
17215 QualType ConvTy) override {
17216 return S.Diag(Loc, DiagID: diag::err_omp_explicit_conversion) << T << ConvTy;
17217 }
17218 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
17219 QualType ConvTy) override {
17220 return S.Diag(Loc: Conv->getLocation(), DiagID: diag::note_omp_conversion_here)
17221 << ConvTy->isEnumeralType() << ConvTy;
17222 }
17223 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
17224 QualType T) override {
17225 return S.Diag(Loc, DiagID: diag::err_omp_ambiguous_conversion) << T;
17226 }
17227 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
17228 QualType ConvTy) override {
17229 return S.Diag(Loc: Conv->getLocation(), DiagID: diag::note_omp_conversion_here)
17230 << ConvTy->isEnumeralType() << ConvTy;
17231 }
17232 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
17233 QualType) override {
17234 llvm_unreachable("conversion functions are permitted");
17235 }
17236 } ConvertDiagnoser;
17237 return SemaRef.PerformContextualImplicitConversion(Loc, FromE: Op, Converter&: ConvertDiagnoser);
17238}
17239
17240static bool
17241isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
17242 bool StrictlyPositive, bool BuildCapture = false,
17243 OpenMPDirectiveKind DKind = OMPD_unknown,
17244 OpenMPDirectiveKind *CaptureRegion = nullptr,
17245 Stmt **HelperValStmt = nullptr) {
17246 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
17247 !ValExpr->isInstantiationDependent()) {
17248 SourceLocation Loc = ValExpr->getExprLoc();
17249 ExprResult Value =
17250 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, Op: ValExpr);
17251 if (Value.isInvalid())
17252 return false;
17253
17254 ValExpr = Value.get();
17255 // The expression must evaluate to a non-negative integer value.
17256 if (std::optional<llvm::APSInt> Result =
17257 ValExpr->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
17258 if (Result->isSigned() &&
17259 !((!StrictlyPositive && Result->isNonNegative()) ||
17260 (StrictlyPositive && Result->isStrictlyPositive()))) {
17261 SemaRef.Diag(Loc, DiagID: diag::err_omp_negative_expression_in_clause)
17262 << getOpenMPClauseNameForDiag(C: CKind) << (StrictlyPositive ? 1 : 0)
17263 << ValExpr->getSourceRange();
17264 return false;
17265 }
17266 }
17267 if (!BuildCapture)
17268 return true;
17269 *CaptureRegion =
17270 getOpenMPCaptureRegionForClause(DKind, CKind, OpenMPVersion: SemaRef.LangOpts.OpenMP);
17271 if (*CaptureRegion != OMPD_unknown &&
17272 !SemaRef.CurContext->isDependentContext()) {
17273 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17274 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17275 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17276 *HelperValStmt = buildPreInits(Context&: SemaRef.Context, Captures);
17277 }
17278 }
17279 return true;
17280}
17281
17282static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
17283 unsigned Last,
17284 ArrayRef<unsigned> Exclude = {}) {
17285 SmallString<256> Buffer;
17286 llvm::raw_svector_ostream Out(Buffer);
17287 unsigned Skipped = Exclude.size();
17288 for (unsigned I = First; I < Last; ++I) {
17289 if (llvm::is_contained(Range&: Exclude, Element: I)) {
17290 --Skipped;
17291 continue;
17292 }
17293 Out << "'" << getOpenMPSimpleClauseTypeName(Kind: K, Type: I) << "'";
17294 if (I + Skipped + 2 == Last)
17295 Out << " or ";
17296 else if (I + Skipped + 1 != Last)
17297 Out << ", ";
17298 }
17299 return std::string(Out.str());
17300}
17301
17302OMPClause *SemaOpenMP::ActOnOpenMPNumThreadsClause(
17303 OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads,
17304 SourceLocation StartLoc, SourceLocation LParenLoc,
17305 SourceLocation ModifierLoc, SourceLocation EndLoc) {
17306 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 60) &&
17307 "Unexpected num_threads modifier in OpenMP < 60.");
17308
17309 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTHREADS_unknown) {
17310 std::string Values = getListOfPossibleValues(K: OMPC_num_threads, /*First=*/0,
17311 Last: OMPC_NUMTHREADS_unknown);
17312 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
17313 << Values << getOpenMPClauseNameForDiag(C: OMPC_num_threads);
17314 return nullptr;
17315 }
17316
17317 Expr *ValExpr = NumThreads;
17318 Stmt *HelperValStmt = nullptr;
17319
17320 // OpenMP [2.5, Restrictions]
17321 // The num_threads expression must evaluate to a positive integer value.
17322 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_num_threads,
17323 /*StrictlyPositive=*/true))
17324 return nullptr;
17325
17326 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17327 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
17328 DKind, CKind: OMPC_num_threads, OpenMPVersion: getLangOpts().OpenMP);
17329 if (CaptureRegion != OMPD_unknown &&
17330 !SemaRef.CurContext->isDependentContext()) {
17331 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17332 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17333 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17334 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
17335 }
17336
17337 return new (getASTContext())
17338 OMPNumThreadsClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
17339 StartLoc, LParenLoc, ModifierLoc, EndLoc);
17340}
17341
17342ExprResult SemaOpenMP::VerifyPositiveIntegerConstantInClause(
17343 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
17344 bool SuppressExprDiags) {
17345 if (!E)
17346 return ExprError();
17347 if (E->isValueDependent() || E->isTypeDependent() ||
17348 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
17349 return E;
17350
17351 llvm::APSInt Result;
17352 ExprResult ICE;
17353 if (SuppressExprDiags) {
17354 // Use a custom diagnoser that suppresses 'note' diagnostics about the
17355 // expression.
17356 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
17357 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
17358 SemaBase::SemaDiagnosticBuilder
17359 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
17360 llvm_unreachable("Diagnostic suppressed");
17361 }
17362 } Diagnoser;
17363 ICE = SemaRef.VerifyIntegerConstantExpression(E, Result: &Result, Diagnoser,
17364 CanFold: AllowFoldKind::Allow);
17365 } else {
17366 ICE =
17367 SemaRef.VerifyIntegerConstantExpression(E, Result: &Result,
17368 /*FIXME*/ CanFold: AllowFoldKind::Allow);
17369 }
17370 if (ICE.isInvalid())
17371 return ExprError();
17372
17373 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
17374 (!StrictlyPositive && !Result.isNonNegative())) {
17375 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_negative_expression_in_clause)
17376 << getOpenMPClauseNameForDiag(C: CKind) << (StrictlyPositive ? 1 : 0)
17377 << E->getSourceRange();
17378 return ExprError();
17379 }
17380 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
17381 CKind == OMPC_allocate) &&
17382 !Result.isPowerOf2()) {
17383 Diag(Loc: E->getExprLoc(), DiagID: diag::warn_omp_alignment_not_power_of_two)
17384 << E->getSourceRange();
17385 return ExprError();
17386 }
17387
17388 if (!Result.isRepresentableByInt64()) {
17389 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_large_expression_in_clause)
17390 << getOpenMPClauseNameForDiag(C: CKind) << E->getSourceRange();
17391 return ExprError();
17392 }
17393
17394 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
17395 DSAStack->setAssociatedLoops(Result.getExtValue());
17396 else if (CKind == OMPC_ordered)
17397 DSAStack->setAssociatedLoops(Result.getExtValue());
17398 return ICE;
17399}
17400
17401void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
17402
17403void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
17404
17405int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
17406
17407void SemaOpenMP::ActOnOpenMPDeviceNum(Expr *DeviceNumExpr) {
17408 llvm::APSInt Result;
17409 Expr::EvalResult EvalResult;
17410 // Evaluate the expression to an integer value
17411 if (!DeviceNumExpr->isValueDependent() &&
17412 DeviceNumExpr->EvaluateAsInt(Result&: EvalResult, Ctx: SemaRef.Context)) {
17413 // The device expression must evaluate to a non-negative integer value.
17414 Result = EvalResult.Val.getInt();
17415 if (Result.isNonNegative()) {
17416 setOpenMPDeviceNum(Result.getZExtValue());
17417 } else {
17418 Diag(Loc: DeviceNumExpr->getExprLoc(),
17419 DiagID: diag::err_omp_negative_expression_in_clause)
17420 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
17421 }
17422 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(Val: DeviceNumExpr)) {
17423 // Check if the expression is an identifier
17424 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
17425 if (IdInfo) {
17426 setOpenMPDeviceNumID(IdInfo->getName());
17427 }
17428 } else {
17429 Diag(Loc: DeviceNumExpr->getExprLoc(), DiagID: diag::err_expected_expression);
17430 }
17431}
17432
17433OMPClause *SemaOpenMP::ActOnOpenMPSafelenClause(Expr *Len,
17434 SourceLocation StartLoc,
17435 SourceLocation LParenLoc,
17436 SourceLocation EndLoc) {
17437 // OpenMP [2.8.1, simd construct, Description]
17438 // The parameter of the safelen clause must be a constant
17439 // positive integer expression.
17440 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(E: Len, CKind: OMPC_safelen);
17441 if (Safelen.isInvalid())
17442 return nullptr;
17443 return new (getASTContext())
17444 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
17445}
17446
17447OMPClause *SemaOpenMP::ActOnOpenMPSimdlenClause(Expr *Len,
17448 SourceLocation StartLoc,
17449 SourceLocation LParenLoc,
17450 SourceLocation EndLoc) {
17451 // OpenMP [2.8.1, simd construct, Description]
17452 // The parameter of the simdlen clause must be a constant
17453 // positive integer expression.
17454 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(E: Len, CKind: OMPC_simdlen);
17455 if (Simdlen.isInvalid())
17456 return nullptr;
17457 return new (getASTContext())
17458 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
17459}
17460
17461/// Tries to find omp_allocator_handle_t type.
17462static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
17463 DSAStackTy *Stack) {
17464 if (!Stack->getOMPAllocatorHandleT().isNull())
17465 return true;
17466
17467 // Set the allocator handle type.
17468 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_allocator_handle_t");
17469 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
17470 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
17471 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found)
17472 << "omp_allocator_handle_t";
17473 return false;
17474 }
17475 QualType AllocatorHandleEnumTy = PT.get();
17476 AllocatorHandleEnumTy.addConst();
17477 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17478
17479 // Fill the predefined allocator map.
17480 bool ErrorFound = false;
17481 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17482 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
17483 StringRef Allocator =
17484 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(Val: AllocatorKind);
17485 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Name: Allocator);
17486 auto *VD = dyn_cast_or_null<ValueDecl>(
17487 Val: S.LookupSingleName(S: S.TUScope, Name: AllocatorName, Loc, NameKind: Sema::LookupAnyName));
17488 if (!VD) {
17489 ErrorFound = true;
17490 break;
17491 }
17492 QualType AllocatorType =
17493 VD->getType().getNonLValueExprType(Context: S.getASTContext());
17494 ExprResult Res = S.BuildDeclRefExpr(D: VD, Ty: AllocatorType, VK: VK_LValue, Loc);
17495 if (!Res.isUsable()) {
17496 ErrorFound = true;
17497 break;
17498 }
17499 Res = S.PerformImplicitConversion(From: Res.get(), ToType: AllocatorHandleEnumTy,
17500 Action: AssignmentAction::Initializing,
17501 /*AllowExplicit=*/true);
17502 if (!Res.isUsable()) {
17503 ErrorFound = true;
17504 break;
17505 }
17506 Stack->setAllocator(AllocatorKind, Allocator: Res.get());
17507 }
17508 if (ErrorFound) {
17509 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found)
17510 << "omp_allocator_handle_t";
17511 return false;
17512 }
17513
17514 return true;
17515}
17516
17517OMPClause *SemaOpenMP::ActOnOpenMPAllocatorClause(Expr *A,
17518 SourceLocation StartLoc,
17519 SourceLocation LParenLoc,
17520 SourceLocation EndLoc) {
17521 // OpenMP [2.11.3, allocate Directive, Description]
17522 // allocator is an expression of omp_allocator_handle_t type.
17523 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: A->getExprLoc(), DSAStack))
17524 return nullptr;
17525
17526 ExprResult Allocator = SemaRef.DefaultLvalueConversion(E: A);
17527 if (Allocator.isInvalid())
17528 return nullptr;
17529 Allocator = SemaRef.PerformImplicitConversion(
17530 From: Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
17531 Action: AssignmentAction::Initializing,
17532 /*AllowExplicit=*/true);
17533 if (Allocator.isInvalid())
17534 return nullptr;
17535 return new (getASTContext())
17536 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
17537}
17538
17539OMPClause *SemaOpenMP::ActOnOpenMPCollapseClause(Expr *NumForLoops,
17540 SourceLocation StartLoc,
17541 SourceLocation LParenLoc,
17542 SourceLocation EndLoc) {
17543 // OpenMP [2.7.1, loop construct, Description]
17544 // OpenMP [2.8.1, simd construct, Description]
17545 // OpenMP [2.9.6, distribute construct, Description]
17546 // The parameter of the collapse clause must be a constant
17547 // positive integer expression.
17548 ExprResult NumForLoopsResult =
17549 VerifyPositiveIntegerConstantInClause(E: NumForLoops, CKind: OMPC_collapse);
17550 if (NumForLoopsResult.isInvalid())
17551 return nullptr;
17552 return new (getASTContext())
17553 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
17554}
17555
17556OMPClause *SemaOpenMP::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
17557 SourceLocation EndLoc,
17558 SourceLocation LParenLoc,
17559 Expr *NumForLoops) {
17560 // OpenMP [2.7.1, loop construct, Description]
17561 // OpenMP [2.8.1, simd construct, Description]
17562 // OpenMP [2.9.6, distribute construct, Description]
17563 // The parameter of the ordered clause must be a constant
17564 // positive integer expression if any.
17565 if (NumForLoops && LParenLoc.isValid()) {
17566 ExprResult NumForLoopsResult =
17567 VerifyPositiveIntegerConstantInClause(E: NumForLoops, CKind: OMPC_ordered);
17568 if (NumForLoopsResult.isInvalid())
17569 return nullptr;
17570 NumForLoops = NumForLoopsResult.get();
17571 } else {
17572 NumForLoops = nullptr;
17573 }
17574 auto *Clause =
17575 OMPOrderedClause::Create(C: getASTContext(), Num: NumForLoops,
17576 NumLoops: NumForLoops ? DSAStack->getAssociatedLoops() : 0,
17577 StartLoc, LParenLoc, EndLoc);
17578 DSAStack->setOrderedRegion(/*IsOrdered=*/true, Param: NumForLoops, Clause);
17579 return Clause;
17580}
17581
17582OMPClause *SemaOpenMP::ActOnOpenMPSimpleClause(
17583 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
17584 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17585 OMPClause *Res = nullptr;
17586 switch (Kind) {
17587 case OMPC_proc_bind:
17588 Res = ActOnOpenMPProcBindClause(Kind: static_cast<ProcBindKind>(Argument),
17589 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17590 break;
17591 case OMPC_atomic_default_mem_order:
17592 Res = ActOnOpenMPAtomicDefaultMemOrderClause(
17593 Kind: static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
17594 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17595 break;
17596 case OMPC_fail:
17597 Res = ActOnOpenMPFailClause(Kind: static_cast<OpenMPClauseKind>(Argument),
17598 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17599 break;
17600 case OMPC_update:
17601 Res = ActOnOpenMPUpdateClause(Kind: static_cast<OpenMPDependClauseKind>(Argument),
17602 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17603 break;
17604 case OMPC_bind:
17605 Res = ActOnOpenMPBindClause(Kind: static_cast<OpenMPBindClauseKind>(Argument),
17606 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17607 break;
17608 case OMPC_at:
17609 Res = ActOnOpenMPAtClause(Kind: static_cast<OpenMPAtClauseKind>(Argument),
17610 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17611 break;
17612 case OMPC_severity:
17613 Res = ActOnOpenMPSeverityClause(
17614 Kind: static_cast<OpenMPSeverityClauseKind>(Argument), KindLoc: ArgumentLoc, StartLoc,
17615 LParenLoc, EndLoc);
17616 break;
17617 case OMPC_threadset:
17618 Res = ActOnOpenMPThreadsetClause(Kind: static_cast<OpenMPThreadsetKind>(Argument),
17619 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17620 break;
17621 case OMPC_if:
17622 case OMPC_final:
17623 case OMPC_num_threads:
17624 case OMPC_safelen:
17625 case OMPC_simdlen:
17626 case OMPC_sizes:
17627 case OMPC_allocator:
17628 case OMPC_collapse:
17629 case OMPC_schedule:
17630 case OMPC_private:
17631 case OMPC_firstprivate:
17632 case OMPC_lastprivate:
17633 case OMPC_shared:
17634 case OMPC_reduction:
17635 case OMPC_task_reduction:
17636 case OMPC_in_reduction:
17637 case OMPC_linear:
17638 case OMPC_aligned:
17639 case OMPC_copyin:
17640 case OMPC_copyprivate:
17641 case OMPC_ordered:
17642 case OMPC_nowait:
17643 case OMPC_untied:
17644 case OMPC_mergeable:
17645 case OMPC_threadprivate:
17646 case OMPC_groupprivate:
17647 case OMPC_allocate:
17648 case OMPC_flush:
17649 case OMPC_depobj:
17650 case OMPC_read:
17651 case OMPC_write:
17652 case OMPC_capture:
17653 case OMPC_compare:
17654 case OMPC_seq_cst:
17655 case OMPC_acq_rel:
17656 case OMPC_acquire:
17657 case OMPC_release:
17658 case OMPC_relaxed:
17659 case OMPC_depend:
17660 case OMPC_device:
17661 case OMPC_threads:
17662 case OMPC_simd:
17663 case OMPC_map:
17664 case OMPC_num_teams:
17665 case OMPC_thread_limit:
17666 case OMPC_priority:
17667 case OMPC_grainsize:
17668 case OMPC_nogroup:
17669 case OMPC_num_tasks:
17670 case OMPC_hint:
17671 case OMPC_dist_schedule:
17672 case OMPC_default:
17673 case OMPC_defaultmap:
17674 case OMPC_unknown:
17675 case OMPC_uniform:
17676 case OMPC_to:
17677 case OMPC_from:
17678 case OMPC_use_device_ptr:
17679 case OMPC_use_device_addr:
17680 case OMPC_is_device_ptr:
17681 case OMPC_has_device_addr:
17682 case OMPC_unified_address:
17683 case OMPC_unified_shared_memory:
17684 case OMPC_reverse_offload:
17685 case OMPC_dynamic_allocators:
17686 case OMPC_self_maps:
17687 case OMPC_device_type:
17688 case OMPC_match:
17689 case OMPC_nontemporal:
17690 case OMPC_destroy:
17691 case OMPC_novariants:
17692 case OMPC_nocontext:
17693 case OMPC_detach:
17694 case OMPC_inclusive:
17695 case OMPC_exclusive:
17696 case OMPC_uses_allocators:
17697 case OMPC_affinity:
17698 case OMPC_when:
17699 case OMPC_message:
17700 default:
17701 llvm_unreachable("Clause is not allowed.");
17702 }
17703 return Res;
17704}
17705
17706OMPClause *SemaOpenMP::ActOnOpenMPDefaultClause(
17707 llvm::omp::DefaultKind M, SourceLocation MLoc,
17708 OpenMPDefaultClauseVariableCategory VCKind, SourceLocation VCKindLoc,
17709 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17710 if (M == OMP_DEFAULT_unknown) {
17711 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
17712 << getListOfPossibleValues(K: OMPC_default, /*First=*/0,
17713 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17714 << getOpenMPClauseNameForDiag(C: OMPC_default);
17715 return nullptr;
17716 }
17717 if (VCKind == OMPC_DEFAULT_VC_unknown) {
17718 Diag(Loc: VCKindLoc, DiagID: diag::err_omp_default_vc)
17719 << getOpenMPSimpleClauseTypeName(Kind: OMPC_default, Type: unsigned(M));
17720 return nullptr;
17721 }
17722
17723 bool IsTargetDefault =
17724 getLangOpts().OpenMP >= 60 &&
17725 isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective());
17726
17727 // OpenMP 6.0, page 224, lines 3-4 default Clause, Semantics
17728 // If data-sharing-attribute is shared then the clause has no effect
17729 // on a target construct;
17730 if (IsTargetDefault && M == OMP_DEFAULT_shared)
17731 return nullptr;
17732
17733 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
17734 OpenMPDefaultClauseVariableCategory VCKind) {
17735 OpenMPDefaultmapClauseModifier DefMapMod;
17736 OpenMPDefaultmapClauseKind DefMapKind;
17737 // default data-sharing-attribute
17738 switch (M) {
17739 case OMP_DEFAULT_none:
17740 if (IsTargetDefault)
17741 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
17742 else
17743 DSAStack->setDefaultDSANone(MLoc);
17744 break;
17745 case OMP_DEFAULT_firstprivate:
17746 if (IsTargetDefault)
17747 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
17748 else
17749 DSAStack->setDefaultDSAFirstPrivate(MLoc);
17750 break;
17751 case OMP_DEFAULT_private:
17752 if (IsTargetDefault)
17753 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
17754 else
17755 DSAStack->setDefaultDSAPrivate(MLoc);
17756 break;
17757 case OMP_DEFAULT_shared:
17758 assert(!IsTargetDefault && "DSA shared invalid with target directive");
17759 DSAStack->setDefaultDSAShared(MLoc);
17760 break;
17761 default:
17762 llvm_unreachable("unexpected DSA in OpenMP default clause");
17763 }
17764 // default variable-category
17765 switch (VCKind) {
17766 case OMPC_DEFAULT_VC_aggregate:
17767 if (IsTargetDefault)
17768 DefMapKind = OMPC_DEFAULTMAP_aggregate;
17769 else
17770 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
17771 break;
17772 case OMPC_DEFAULT_VC_pointer:
17773 if (IsTargetDefault)
17774 DefMapKind = OMPC_DEFAULTMAP_pointer;
17775 else
17776 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
17777 break;
17778 case OMPC_DEFAULT_VC_scalar:
17779 if (IsTargetDefault)
17780 DefMapKind = OMPC_DEFAULTMAP_scalar;
17781 else
17782 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
17783 break;
17784 case OMPC_DEFAULT_VC_all:
17785 if (IsTargetDefault)
17786 DefMapKind = OMPC_DEFAULTMAP_all;
17787 else
17788 DSAStack->setDefaultDSAVCAll(VCKindLoc);
17789 break;
17790 default:
17791 llvm_unreachable("unexpected variable category in OpenMP default clause");
17792 }
17793 // OpenMP 6.0, page 224, lines 4-5 default Clause, Semantics
17794 // otherwise, its effect on a target construct is equivalent to
17795 // specifying the defaultmap clause with the same data-sharing-attribute
17796 // and variable-category.
17797 //
17798 // If earlier than OpenMP 6.0, or not a target directive, the default DSA
17799 // is/was set as before.
17800 if (IsTargetDefault) {
17801 if (DefMapKind == OMPC_DEFAULTMAP_all) {
17802 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: OMPC_DEFAULTMAP_aggregate, Loc: MLoc);
17803 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: OMPC_DEFAULTMAP_scalar, Loc: MLoc);
17804 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: OMPC_DEFAULTMAP_pointer, Loc: MLoc);
17805 } else {
17806 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: DefMapKind, Loc: MLoc);
17807 }
17808 }
17809 };
17810
17811 SetDefaultClauseAttrs(M, VCKind);
17812 return new (getASTContext())
17813 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
17814}
17815
17816OMPClause *SemaOpenMP::ActOnOpenMPThreadsetClause(OpenMPThreadsetKind Kind,
17817 SourceLocation KindLoc,
17818 SourceLocation StartLoc,
17819 SourceLocation LParenLoc,
17820 SourceLocation EndLoc) {
17821 if (Kind == OMPC_THREADSET_unknown) {
17822 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
17823 << getListOfPossibleValues(K: OMPC_threadset, /*First=*/0,
17824 /*Last=*/unsigned(OMPC_THREADSET_unknown))
17825 << getOpenMPClauseName(C: OMPC_threadset);
17826 return nullptr;
17827 }
17828
17829 return new (getASTContext())
17830 OMPThreadsetClause(Kind, KindLoc, StartLoc, LParenLoc, EndLoc);
17831}
17832
17833static OMPClause *
17834createTransparentClause(Sema &SemaRef, ASTContext &Ctx, Expr *ImpexTypeArg,
17835 Stmt *HelperValStmt, OpenMPDirectiveKind CaptureRegion,
17836 SourceLocation StartLoc, SourceLocation LParenLoc,
17837 SourceLocation EndLoc) {
17838 ExprResult ER = SemaRef.DefaultLvalueConversion(E: ImpexTypeArg);
17839 if (ER.isInvalid())
17840 return nullptr;
17841
17842 return new (Ctx) OMPTransparentClause(ER.get(), HelperValStmt, CaptureRegion,
17843 StartLoc, LParenLoc, EndLoc);
17844}
17845
17846OMPClause *SemaOpenMP::ActOnOpenMPTransparentClause(Expr *ImpexTypeArg,
17847 SourceLocation StartLoc,
17848 SourceLocation LParenLoc,
17849 SourceLocation EndLoc) {
17850 Stmt *HelperValStmt = nullptr;
17851 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17852 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
17853 DKind, CKind: OMPC_transparent, OpenMPVersion: getLangOpts().OpenMP);
17854 if (CaptureRegion != OMPD_unknown &&
17855 !SemaRef.CurContext->isDependentContext()) {
17856 Expr *ValExpr = SemaRef.MakeFullExpr(Arg: ImpexTypeArg).get();
17857 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17858 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17859 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
17860 }
17861 if (!ImpexTypeArg) {
17862 return new (getASTContext())
17863 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
17864 StartLoc, LParenLoc, EndLoc);
17865 }
17866 QualType Ty = ImpexTypeArg->getType();
17867
17868 if (const auto *TT = Ty->getAs<TypedefType>()) {
17869 const TypedefNameDecl *TypedefDecl = TT->getDecl();
17870 llvm::StringRef TypedefName = TypedefDecl->getName();
17871 IdentifierInfo &II = SemaRef.PP.getIdentifierTable().get(Name: TypedefName);
17872 ParsedType ImpexTy =
17873 SemaRef.getTypeName(II, NameLoc: StartLoc, S: SemaRef.getCurScope());
17874 if (!ImpexTy.getAsOpaquePtr() || ImpexTy.get().isNull()) {
17875 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_implied_type_not_found)
17876 << TypedefName;
17877 return nullptr;
17878 }
17879 return new (getASTContext())
17880 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
17881 StartLoc, LParenLoc, EndLoc);
17882 }
17883
17884 if (Ty->isEnumeralType())
17885 return createTransparentClause(SemaRef, Ctx&: getASTContext(), ImpexTypeArg,
17886 HelperValStmt, CaptureRegion, StartLoc,
17887 LParenLoc, EndLoc);
17888 if (Ty->isIntegerType()) {
17889 if (isNonNegativeIntegerValue(ValExpr&: ImpexTypeArg, SemaRef, CKind: OMPC_transparent,
17890 /*StrictlyPositive=*/false)) {
17891 ExprResult Value =
17892 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc: StartLoc,
17893 Op: ImpexTypeArg);
17894 if (std::optional<llvm::APSInt> Result =
17895 Value.get()->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
17896 if (Result->isNegative() ||
17897 Result >
17898 static_cast<int64_t>(SemaOpenMP::OpenMPImpexType::OMP_Export))
17899 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_transparent_invalid_value);
17900 }
17901 return new (getASTContext())
17902 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
17903 StartLoc, LParenLoc, EndLoc);
17904 }
17905 }
17906 if (!isNonNegativeIntegerValue(ValExpr&: ImpexTypeArg, SemaRef, CKind: OMPC_transparent,
17907 /*StrictlyPositive=*/true))
17908 return nullptr;
17909 return new (getASTContext()) OMPTransparentClause(
17910 ImpexTypeArg, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17911}
17912
17913OMPClause *SemaOpenMP::ActOnOpenMPProcBindClause(ProcBindKind Kind,
17914 SourceLocation KindKwLoc,
17915 SourceLocation StartLoc,
17916 SourceLocation LParenLoc,
17917 SourceLocation EndLoc) {
17918 if (Kind == OMP_PROC_BIND_unknown) {
17919 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
17920 << getListOfPossibleValues(K: OMPC_proc_bind,
17921 /*First=*/unsigned(OMP_PROC_BIND_master),
17922 /*Last=*/
17923 unsigned(getLangOpts().OpenMP > 50
17924 ? OMP_PROC_BIND_primary
17925 : OMP_PROC_BIND_spread) +
17926 1)
17927 << getOpenMPClauseNameForDiag(C: OMPC_proc_bind);
17928 return nullptr;
17929 }
17930 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
17931 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
17932 << getListOfPossibleValues(K: OMPC_proc_bind,
17933 /*First=*/unsigned(OMP_PROC_BIND_master),
17934 /*Last=*/
17935 unsigned(OMP_PROC_BIND_spread) + 1)
17936 << getOpenMPClauseNameForDiag(C: OMPC_proc_bind);
17937 return new (getASTContext())
17938 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17939}
17940
17941OMPClause *SemaOpenMP::ActOnOpenMPAtomicDefaultMemOrderClause(
17942 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
17943 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17944 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
17945 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
17946 << getListOfPossibleValues(
17947 K: OMPC_atomic_default_mem_order, /*First=*/0,
17948 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
17949 << getOpenMPClauseNameForDiag(C: OMPC_atomic_default_mem_order);
17950 return nullptr;
17951 }
17952 return new (getASTContext()) OMPAtomicDefaultMemOrderClause(
17953 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17954}
17955
17956OMPClause *SemaOpenMP::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
17957 SourceLocation KindKwLoc,
17958 SourceLocation StartLoc,
17959 SourceLocation LParenLoc,
17960 SourceLocation EndLoc) {
17961 if (Kind == OMPC_AT_unknown) {
17962 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
17963 << getListOfPossibleValues(K: OMPC_at, /*First=*/0,
17964 /*Last=*/OMPC_AT_unknown)
17965 << getOpenMPClauseNameForDiag(C: OMPC_at);
17966 return nullptr;
17967 }
17968 return new (getASTContext())
17969 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17970}
17971
17972OMPClause *SemaOpenMP::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
17973 SourceLocation KindKwLoc,
17974 SourceLocation StartLoc,
17975 SourceLocation LParenLoc,
17976 SourceLocation EndLoc) {
17977 if (Kind == OMPC_SEVERITY_unknown) {
17978 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
17979 << getListOfPossibleValues(K: OMPC_severity, /*First=*/0,
17980 /*Last=*/OMPC_SEVERITY_unknown)
17981 << getOpenMPClauseNameForDiag(C: OMPC_severity);
17982 return nullptr;
17983 }
17984 return new (getASTContext())
17985 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17986}
17987
17988OMPClause *SemaOpenMP::ActOnOpenMPMessageClause(Expr *ME,
17989 SourceLocation StartLoc,
17990 SourceLocation LParenLoc,
17991 SourceLocation EndLoc) {
17992 assert(ME && "NULL expr in Message clause");
17993 QualType Type = ME->getType();
17994 if ((!Type->isPointerType() && !Type->isArrayType()) ||
17995 !Type->getPointeeOrArrayElementType()->isAnyCharacterType()) {
17996 Diag(Loc: ME->getBeginLoc(), DiagID: diag::warn_clause_expected_string)
17997 << getOpenMPClauseNameForDiag(C: OMPC_message) << 0;
17998 return nullptr;
17999 }
18000
18001 Stmt *HelperValStmt = nullptr;
18002
18003 // Depending on whether this clause appears in an executable context or not,
18004 // we may or may not build a capture.
18005 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18006 OpenMPDirectiveKind CaptureRegion =
18007 DKind == OMPD_unknown ? OMPD_unknown
18008 : getOpenMPCaptureRegionForClause(
18009 DKind, CKind: OMPC_message, OpenMPVersion: getLangOpts().OpenMP);
18010 if (CaptureRegion != OMPD_unknown &&
18011 !SemaRef.CurContext->isDependentContext()) {
18012 ME = SemaRef.MakeFullExpr(Arg: ME).get();
18013 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18014 ME = tryBuildCapture(SemaRef, Capture: ME, Captures).get();
18015 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
18016 }
18017
18018 // Convert array type to pointer type if needed.
18019 ME = SemaRef.DefaultFunctionArrayLvalueConversion(E: ME).get();
18020
18021 return new (getASTContext()) OMPMessageClause(
18022 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18023}
18024
18025OMPClause *SemaOpenMP::ActOnOpenMPOrderClause(
18026 OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind,
18027 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
18028 SourceLocation KindLoc, SourceLocation EndLoc) {
18029 if (Kind != OMPC_ORDER_concurrent ||
18030 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
18031 // Kind should be concurrent,
18032 // Modifiers introduced in OpenMP 5.1
18033 static_assert(OMPC_ORDER_unknown > 0,
18034 "OMPC_ORDER_unknown not greater than 0");
18035
18036 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
18037 << getListOfPossibleValues(K: OMPC_order,
18038 /*First=*/0,
18039 /*Last=*/OMPC_ORDER_unknown)
18040 << getOpenMPClauseNameForDiag(C: OMPC_order);
18041 return nullptr;
18042 }
18043 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
18044 MLoc.isValid()) {
18045 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
18046 << getListOfPossibleValues(K: OMPC_order,
18047 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
18048 /*Last=*/OMPC_ORDER_MODIFIER_last)
18049 << getOpenMPClauseNameForDiag(C: OMPC_order);
18050 } else if (getLangOpts().OpenMP >= 50) {
18051 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
18052 if (DSAStack->getCurScope()) {
18053 // mark the current scope with 'order' flag
18054 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
18055 DSAStack->getCurScope()->setFlags(existingFlags |
18056 Scope::OpenMPOrderClauseScope);
18057 }
18058 }
18059 return new (getASTContext()) OMPOrderClause(
18060 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
18061}
18062
18063OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,
18064 SourceLocation KindKwLoc,
18065 SourceLocation StartLoc,
18066 SourceLocation LParenLoc,
18067 SourceLocation EndLoc) {
18068 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
18069 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
18070 SmallVector<unsigned> Except = {
18071 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
18072 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
18073 if (getLangOpts().OpenMP < 51)
18074 Except.push_back(Elt: OMPC_DEPEND_inoutset);
18075 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
18076 << getListOfPossibleValues(K: OMPC_depend, /*First=*/0,
18077 /*Last=*/OMPC_DEPEND_unknown, Exclude: Except)
18078 << getOpenMPClauseNameForDiag(C: OMPC_update);
18079 return nullptr;
18080 }
18081 return OMPUpdateClause::Create(C: getASTContext(), StartLoc, LParenLoc,
18082 ArgumentLoc: KindKwLoc, DK: Kind, EndLoc);
18083}
18084
18085OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
18086 SourceLocation StartLoc,
18087 SourceLocation LParenLoc,
18088 SourceLocation EndLoc) {
18089 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
18090
18091 for (Expr *&SizeExpr : SanitizedSizeExprs) {
18092 // Skip if already sanitized, e.g. during a partial template instantiation.
18093 if (!SizeExpr)
18094 continue;
18095
18096 bool IsValid = isNonNegativeIntegerValue(ValExpr&: SizeExpr, SemaRef, CKind: OMPC_sizes,
18097 /*StrictlyPositive=*/true);
18098
18099 // isNonNegativeIntegerValue returns true for non-integral types (but still
18100 // emits error diagnostic), so check for the expected type explicitly.
18101 QualType SizeTy = SizeExpr->getType();
18102 if (!SizeTy->isIntegerType())
18103 IsValid = false;
18104
18105 // Handling in templates is tricky. There are four possibilities to
18106 // consider:
18107 //
18108 // 1a. The expression is valid and we are in a instantiated template or not
18109 // in a template:
18110 // Pass valid expression to be further analysed later in Sema.
18111 // 1b. The expression is valid and we are in a template (including partial
18112 // instantiation):
18113 // isNonNegativeIntegerValue skipped any checks so there is no
18114 // guarantee it will be correct after instantiation.
18115 // ActOnOpenMPSizesClause will be called again at instantiation when
18116 // it is not in a dependent context anymore. This may cause warnings
18117 // to be emitted multiple times.
18118 // 2a. The expression is invalid and we are in an instantiated template or
18119 // not in a template:
18120 // Invalidate the expression with a clearly wrong value (nullptr) so
18121 // later in Sema we do not have to do the same validity analysis again
18122 // or crash from unexpected data. Error diagnostics have already been
18123 // emitted.
18124 // 2b. The expression is invalid and we are in a template (including partial
18125 // instantiation):
18126 // Pass the invalid expression as-is, template instantiation may
18127 // replace unexpected types/values with valid ones. The directives
18128 // with this clause must not try to use these expressions in dependent
18129 // contexts, but delay analysis until full instantiation.
18130 if (!SizeExpr->isInstantiationDependent() && !IsValid)
18131 SizeExpr = nullptr;
18132 }
18133
18134 return OMPSizesClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
18135 Sizes: SanitizedSizeExprs);
18136}
18137
18138OMPClause *SemaOpenMP::ActOnOpenMPCountsClause(ArrayRef<Expr *> CountExprs,
18139 SourceLocation StartLoc,
18140 SourceLocation LParenLoc,
18141 SourceLocation EndLoc,
18142 std::optional<unsigned> FillIdx,
18143 SourceLocation FillLoc,
18144 unsigned FillCount) {
18145 SmallVector<Expr *> SanitizedCountExprs(CountExprs);
18146
18147 // OpenMP 6.0: each list item in counts(...) is either the omp_fill keyword
18148 // or an integral constant expression (non-negative). Runtime variables are
18149 // not permitted; this matches split codegen, which needs segment sizes at
18150 // compile time.
18151 for (unsigned I = 0; I < SanitizedCountExprs.size(); ++I) {
18152 Expr *&CountExpr = SanitizedCountExprs[I];
18153 if (FillIdx && I == *FillIdx)
18154 continue;
18155 if (!CountExpr)
18156 continue;
18157
18158 ExprResult Verified = VerifyPositiveIntegerConstantInClause(
18159 E: CountExpr, CKind: OMPC_counts, /*StrictlyPositive=*/false);
18160 if (Verified.isInvalid())
18161 CountExpr = nullptr;
18162 else
18163 CountExpr = Verified.get();
18164 }
18165
18166 if (FillCount != 1) {
18167 Diag(Loc: FillCount == 0 ? StartLoc : FillLoc,
18168 DiagID: diag::err_omp_split_counts_not_one_omp_fill);
18169 }
18170
18171 return OMPCountsClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
18172 Counts: SanitizedCountExprs, FillIdx, FillLoc);
18173}
18174
18175OMPClause *SemaOpenMP::ActOnOpenMPPermutationClause(ArrayRef<Expr *> PermExprs,
18176 SourceLocation StartLoc,
18177 SourceLocation LParenLoc,
18178 SourceLocation EndLoc) {
18179 size_t NumLoops = PermExprs.size();
18180 SmallVector<Expr *> SanitizedPermExprs;
18181 llvm::append_range(C&: SanitizedPermExprs, R&: PermExprs);
18182
18183 for (Expr *&PermExpr : SanitizedPermExprs) {
18184 // Skip if template-dependent or already sanitized, e.g. during a partial
18185 // template instantiation.
18186 if (!PermExpr || PermExpr->isInstantiationDependent())
18187 continue;
18188
18189 llvm::APSInt PermVal;
18190 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
18191 E: PermExpr, Result: &PermVal, CanFold: AllowFoldKind::Allow);
18192 bool IsValid = PermEvalExpr.isUsable();
18193 if (IsValid)
18194 PermExpr = PermEvalExpr.get();
18195
18196 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
18197 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
18198 PermEvalExpr.get()->getEndLoc());
18199 Diag(Loc: PermEvalExpr.get()->getExprLoc(),
18200 DiagID: diag::err_omp_interchange_permutation_value_range)
18201 << NumLoops << ExprRange;
18202 IsValid = false;
18203 }
18204
18205 if (!PermExpr->isInstantiationDependent() && !IsValid)
18206 PermExpr = nullptr;
18207 }
18208
18209 return OMPPermutationClause::Create(C: getASTContext(), StartLoc, LParenLoc,
18210 EndLoc, Args: SanitizedPermExprs);
18211}
18212
18213OMPClause *SemaOpenMP::ActOnOpenMPFullClause(SourceLocation StartLoc,
18214 SourceLocation EndLoc) {
18215 return OMPFullClause::Create(C: getASTContext(), StartLoc, EndLoc);
18216}
18217
18218OMPClause *SemaOpenMP::ActOnOpenMPPartialClause(Expr *FactorExpr,
18219 SourceLocation StartLoc,
18220 SourceLocation LParenLoc,
18221 SourceLocation EndLoc) {
18222 if (FactorExpr) {
18223 // If an argument is specified, it must be a constant (or an unevaluated
18224 // template expression).
18225 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
18226 E: FactorExpr, CKind: OMPC_partial, /*StrictlyPositive=*/true);
18227 if (FactorResult.isInvalid())
18228 return nullptr;
18229 FactorExpr = FactorResult.get();
18230 }
18231
18232 return OMPPartialClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
18233 Factor: FactorExpr);
18234}
18235
18236OMPClause *SemaOpenMP::ActOnOpenMPLoopRangeClause(
18237 Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc,
18238 SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc) {
18239
18240 // OpenMP [6.0, Restrictions]
18241 // First and Count must be integer expressions with positive value
18242 ExprResult FirstVal =
18243 VerifyPositiveIntegerConstantInClause(E: First, CKind: OMPC_looprange);
18244 if (FirstVal.isInvalid())
18245 First = nullptr;
18246
18247 ExprResult CountVal =
18248 VerifyPositiveIntegerConstantInClause(E: Count, CKind: OMPC_looprange);
18249 if (CountVal.isInvalid())
18250 Count = nullptr;
18251
18252 // OpenMP [6.0, Restrictions]
18253 // first + count - 1 must not evaluate to a value greater than the
18254 // loop sequence length of the associated canonical loop sequence.
18255 // This check must be performed afterwards due to the delayed
18256 // parsing and computation of the associated loop sequence
18257 return OMPLoopRangeClause::Create(C: getASTContext(), StartLoc, LParenLoc,
18258 FirstLoc, CountLoc, EndLoc, First, Count);
18259}
18260
18261OMPClause *SemaOpenMP::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
18262 SourceLocation LParenLoc,
18263 SourceLocation EndLoc) {
18264 ExprResult AlignVal;
18265 AlignVal = VerifyPositiveIntegerConstantInClause(E: A, CKind: OMPC_align);
18266 if (AlignVal.isInvalid())
18267 return nullptr;
18268 return OMPAlignClause::Create(C: getASTContext(), A: AlignVal.get(), StartLoc,
18269 LParenLoc, EndLoc);
18270}
18271
18272OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause(
18273 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
18274 SourceLocation StartLoc, SourceLocation LParenLoc,
18275 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
18276 SourceLocation EndLoc) {
18277 OMPClause *Res = nullptr;
18278 switch (Kind) {
18279 case OMPC_schedule: {
18280 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
18281 assert(Argument.size() == NumberOfElements &&
18282 ArgumentLoc.size() == NumberOfElements);
18283 Res = ActOnOpenMPScheduleClause(
18284 M1: static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
18285 M2: static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
18286 Kind: static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), ChunkSize: Expr,
18287 StartLoc, LParenLoc, M1Loc: ArgumentLoc[Modifier1], M2Loc: ArgumentLoc[Modifier2],
18288 KindLoc: ArgumentLoc[ScheduleKind], CommaLoc: DelimLoc, EndLoc);
18289 break;
18290 }
18291 case OMPC_if:
18292 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
18293 Res = ActOnOpenMPIfClause(NameModifier: static_cast<OpenMPDirectiveKind>(Argument.back()),
18294 Condition: Expr, StartLoc, LParenLoc, NameModifierLoc: ArgumentLoc.back(),
18295 ColonLoc: DelimLoc, EndLoc);
18296 break;
18297 case OMPC_dist_schedule:
18298 Res = ActOnOpenMPDistScheduleClause(
18299 Kind: static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), ChunkSize: Expr,
18300 StartLoc, LParenLoc, KindLoc: ArgumentLoc.back(), CommaLoc: DelimLoc, EndLoc);
18301 break;
18302 case OMPC_default:
18303 enum { DefaultModifier, DefaultVarCategory };
18304 Res = ActOnOpenMPDefaultClause(
18305 M: static_cast<llvm::omp::DefaultKind>(Argument[DefaultModifier]),
18306 MLoc: ArgumentLoc[DefaultModifier],
18307 VCKind: static_cast<OpenMPDefaultClauseVariableCategory>(
18308 Argument[DefaultVarCategory]),
18309 VCKindLoc: ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
18310 break;
18311 case OMPC_defaultmap:
18312 enum { Modifier, DefaultmapKind };
18313 Res = ActOnOpenMPDefaultmapClause(
18314 M: static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
18315 Kind: static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
18316 StartLoc, LParenLoc, MLoc: ArgumentLoc[Modifier], KindLoc: ArgumentLoc[DefaultmapKind],
18317 EndLoc);
18318 break;
18319 case OMPC_order:
18320 enum { OrderModifier, OrderKind };
18321 Res = ActOnOpenMPOrderClause(
18322 Modifier: static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
18323 Kind: static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
18324 LParenLoc, MLoc: ArgumentLoc[OrderModifier], KindLoc: ArgumentLoc[OrderKind], EndLoc);
18325 break;
18326 case OMPC_device:
18327 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
18328 Res = ActOnOpenMPDeviceClause(
18329 Modifier: static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Device: Expr,
18330 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
18331 break;
18332 case OMPC_grainsize:
18333 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
18334 "Modifier for grainsize clause and its location are expected.");
18335 Res = ActOnOpenMPGrainsizeClause(
18336 Modifier: static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Size: Expr,
18337 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
18338 break;
18339 case OMPC_num_tasks:
18340 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
18341 "Modifier for num_tasks clause and its location are expected.");
18342 Res = ActOnOpenMPNumTasksClause(
18343 Modifier: static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), NumTasks: Expr,
18344 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
18345 break;
18346 case OMPC_dyn_groupprivate: {
18347 enum { Modifier1, Modifier2, NumberOfElements };
18348 assert(Argument.size() == NumberOfElements &&
18349 ArgumentLoc.size() == NumberOfElements &&
18350 "Modifiers for dyn_groupprivate clause and their locations are "
18351 "expected.");
18352 Res = ActOnOpenMPDynGroupprivateClause(
18353 M1: static_cast<OpenMPDynGroupprivateClauseModifier>(Argument[Modifier1]),
18354 M2: static_cast<OpenMPDynGroupprivateClauseFallbackModifier>(
18355 Argument[Modifier2]),
18356 Size: Expr, StartLoc, LParenLoc, M1Loc: ArgumentLoc[Modifier1],
18357 M2Loc: ArgumentLoc[Modifier2], EndLoc);
18358 break;
18359 }
18360 case OMPC_num_threads:
18361 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
18362 "Modifier for num_threads clause and its location are expected.");
18363 Res = ActOnOpenMPNumThreadsClause(
18364 Modifier: static_cast<OpenMPNumThreadsClauseModifier>(Argument.back()), NumThreads: Expr,
18365 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
18366 break;
18367 case OMPC_final:
18368 case OMPC_safelen:
18369 case OMPC_simdlen:
18370 case OMPC_sizes:
18371 case OMPC_allocator:
18372 case OMPC_collapse:
18373 case OMPC_proc_bind:
18374 case OMPC_private:
18375 case OMPC_firstprivate:
18376 case OMPC_lastprivate:
18377 case OMPC_shared:
18378 case OMPC_reduction:
18379 case OMPC_task_reduction:
18380 case OMPC_in_reduction:
18381 case OMPC_linear:
18382 case OMPC_aligned:
18383 case OMPC_copyin:
18384 case OMPC_copyprivate:
18385 case OMPC_ordered:
18386 case OMPC_nowait:
18387 case OMPC_untied:
18388 case OMPC_mergeable:
18389 case OMPC_threadprivate:
18390 case OMPC_groupprivate:
18391 case OMPC_allocate:
18392 case OMPC_flush:
18393 case OMPC_depobj:
18394 case OMPC_read:
18395 case OMPC_write:
18396 case OMPC_update:
18397 case OMPC_capture:
18398 case OMPC_compare:
18399 case OMPC_seq_cst:
18400 case OMPC_acq_rel:
18401 case OMPC_acquire:
18402 case OMPC_release:
18403 case OMPC_relaxed:
18404 case OMPC_depend:
18405 case OMPC_threads:
18406 case OMPC_simd:
18407 case OMPC_map:
18408 case OMPC_num_teams:
18409 case OMPC_thread_limit:
18410 case OMPC_priority:
18411 case OMPC_nogroup:
18412 case OMPC_hint:
18413 case OMPC_unknown:
18414 case OMPC_uniform:
18415 case OMPC_to:
18416 case OMPC_from:
18417 case OMPC_use_device_ptr:
18418 case OMPC_use_device_addr:
18419 case OMPC_is_device_ptr:
18420 case OMPC_has_device_addr:
18421 case OMPC_unified_address:
18422 case OMPC_unified_shared_memory:
18423 case OMPC_reverse_offload:
18424 case OMPC_dynamic_allocators:
18425 case OMPC_atomic_default_mem_order:
18426 case OMPC_self_maps:
18427 case OMPC_device_type:
18428 case OMPC_match:
18429 case OMPC_nontemporal:
18430 case OMPC_at:
18431 case OMPC_severity:
18432 case OMPC_message:
18433 case OMPC_destroy:
18434 case OMPC_novariants:
18435 case OMPC_nocontext:
18436 case OMPC_detach:
18437 case OMPC_inclusive:
18438 case OMPC_exclusive:
18439 case OMPC_uses_allocators:
18440 case OMPC_affinity:
18441 case OMPC_when:
18442 case OMPC_bind:
18443 default:
18444 llvm_unreachable("Clause is not allowed.");
18445 }
18446 return Res;
18447}
18448
18449static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
18450 OpenMPScheduleClauseModifier M2,
18451 SourceLocation M1Loc, SourceLocation M2Loc) {
18452 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
18453 SmallVector<unsigned, 2> Excluded;
18454 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
18455 Excluded.push_back(Elt: M2);
18456 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
18457 Excluded.push_back(Elt: OMPC_SCHEDULE_MODIFIER_monotonic);
18458 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
18459 Excluded.push_back(Elt: OMPC_SCHEDULE_MODIFIER_nonmonotonic);
18460 S.Diag(Loc: M1Loc, DiagID: diag::err_omp_unexpected_clause_value)
18461 << getListOfPossibleValues(K: OMPC_schedule,
18462 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
18463 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
18464 Exclude: Excluded)
18465 << getOpenMPClauseNameForDiag(C: OMPC_schedule);
18466 return true;
18467 }
18468 return false;
18469}
18470
18471OMPClause *SemaOpenMP::ActOnOpenMPScheduleClause(
18472 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
18473 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
18474 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
18475 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
18476 if (checkScheduleModifiers(S&: SemaRef, M1, M2, M1Loc, M2Loc) ||
18477 checkScheduleModifiers(S&: SemaRef, M1: M2, M2: M1, M1Loc: M2Loc, M2Loc: M1Loc))
18478 return nullptr;
18479 // OpenMP, 2.7.1, Loop Construct, Restrictions
18480 // Either the monotonic modifier or the nonmonotonic modifier can be specified
18481 // but not both.
18482 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
18483 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
18484 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
18485 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
18486 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
18487 Diag(Loc: M2Loc, DiagID: diag::err_omp_unexpected_schedule_modifier)
18488 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule, Type: M2)
18489 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule, Type: M1);
18490 return nullptr;
18491 }
18492 if (Kind == OMPC_SCHEDULE_unknown) {
18493 std::string Values;
18494 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
18495 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
18496 Values = getListOfPossibleValues(K: OMPC_schedule, /*First=*/0,
18497 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
18498 Exclude);
18499 } else {
18500 Values = getListOfPossibleValues(K: OMPC_schedule, /*First=*/0,
18501 /*Last=*/OMPC_SCHEDULE_unknown);
18502 }
18503 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
18504 << Values << getOpenMPClauseNameForDiag(C: OMPC_schedule);
18505 return nullptr;
18506 }
18507 // OpenMP, 2.7.1, Loop Construct, Restrictions
18508 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
18509 // schedule(guided).
18510 // OpenMP 5.0 does not have this restriction.
18511 if (getLangOpts().OpenMP < 50 &&
18512 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
18513 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
18514 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
18515 Diag(Loc: M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
18516 DiagID: diag::err_omp_schedule_nonmonotonic_static);
18517 return nullptr;
18518 }
18519 Expr *ValExpr = ChunkSize;
18520 Stmt *HelperValStmt = nullptr;
18521 if (ChunkSize) {
18522 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
18523 !ChunkSize->isInstantiationDependent() &&
18524 !ChunkSize->containsUnexpandedParameterPack()) {
18525 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
18526 ExprResult Val =
18527 PerformOpenMPImplicitIntegerConversion(Loc: ChunkSizeLoc, Op: ChunkSize);
18528 if (Val.isInvalid())
18529 return nullptr;
18530
18531 ValExpr = Val.get();
18532
18533 // OpenMP [2.7.1, Restrictions]
18534 // chunk_size must be a loop invariant integer expression with a positive
18535 // value.
18536 if (std::optional<llvm::APSInt> Result =
18537 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
18538 if (Result->isSigned() && !Result->isStrictlyPositive()) {
18539 Diag(Loc: ChunkSizeLoc, DiagID: diag::err_omp_negative_expression_in_clause)
18540 << "schedule" << 1 << ChunkSize->getSourceRange();
18541 return nullptr;
18542 }
18543 } else if (getOpenMPCaptureRegionForClause(
18544 DSAStack->getCurrentDirective(), CKind: OMPC_schedule,
18545 OpenMPVersion: getLangOpts().OpenMP) != OMPD_unknown &&
18546 !SemaRef.CurContext->isDependentContext()) {
18547 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
18548 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18549 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
18550 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
18551 }
18552 }
18553 }
18554
18555 return new (getASTContext())
18556 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
18557 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
18558}
18559
18560OMPClause *SemaOpenMP::ActOnOpenMPClause(OpenMPClauseKind Kind,
18561 SourceLocation StartLoc,
18562 SourceLocation EndLoc) {
18563 OMPClause *Res = nullptr;
18564 switch (Kind) {
18565 case OMPC_ordered:
18566 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
18567 break;
18568 case OMPC_nowait:
18569 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc,
18570 /*LParenLoc=*/SourceLocation(),
18571 /*Condition=*/nullptr);
18572 break;
18573 case OMPC_untied:
18574 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
18575 break;
18576 case OMPC_mergeable:
18577 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
18578 break;
18579 case OMPC_read:
18580 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
18581 break;
18582 case OMPC_write:
18583 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
18584 break;
18585 case OMPC_update:
18586 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
18587 break;
18588 case OMPC_capture:
18589 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
18590 break;
18591 case OMPC_compare:
18592 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
18593 break;
18594 case OMPC_fail:
18595 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
18596 break;
18597 case OMPC_seq_cst:
18598 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
18599 break;
18600 case OMPC_acq_rel:
18601 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
18602 break;
18603 case OMPC_acquire:
18604 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
18605 break;
18606 case OMPC_release:
18607 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
18608 break;
18609 case OMPC_relaxed:
18610 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
18611 break;
18612 case OMPC_weak:
18613 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
18614 break;
18615 case OMPC_threads:
18616 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
18617 break;
18618 case OMPC_simd:
18619 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
18620 break;
18621 case OMPC_nogroup:
18622 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
18623 break;
18624 case OMPC_unified_address:
18625 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
18626 break;
18627 case OMPC_unified_shared_memory:
18628 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18629 break;
18630 case OMPC_reverse_offload:
18631 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
18632 break;
18633 case OMPC_dynamic_allocators:
18634 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
18635 break;
18636 case OMPC_self_maps:
18637 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
18638 break;
18639 case OMPC_destroy:
18640 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
18641 /*LParenLoc=*/SourceLocation(),
18642 /*VarLoc=*/SourceLocation(), EndLoc);
18643 break;
18644 case OMPC_full:
18645 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
18646 break;
18647 case OMPC_partial:
18648 Res = ActOnOpenMPPartialClause(FactorExpr: nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
18649 break;
18650 case OMPC_ompx_bare:
18651 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
18652 break;
18653 case OMPC_if:
18654 case OMPC_final:
18655 case OMPC_num_threads:
18656 case OMPC_safelen:
18657 case OMPC_simdlen:
18658 case OMPC_sizes:
18659 case OMPC_allocator:
18660 case OMPC_collapse:
18661 case OMPC_schedule:
18662 case OMPC_private:
18663 case OMPC_firstprivate:
18664 case OMPC_lastprivate:
18665 case OMPC_shared:
18666 case OMPC_reduction:
18667 case OMPC_task_reduction:
18668 case OMPC_in_reduction:
18669 case OMPC_linear:
18670 case OMPC_aligned:
18671 case OMPC_copyin:
18672 case OMPC_copyprivate:
18673 case OMPC_default:
18674 case OMPC_proc_bind:
18675 case OMPC_threadprivate:
18676 case OMPC_groupprivate:
18677 case OMPC_allocate:
18678 case OMPC_flush:
18679 case OMPC_depobj:
18680 case OMPC_depend:
18681 case OMPC_device:
18682 case OMPC_map:
18683 case OMPC_num_teams:
18684 case OMPC_thread_limit:
18685 case OMPC_priority:
18686 case OMPC_grainsize:
18687 case OMPC_num_tasks:
18688 case OMPC_hint:
18689 case OMPC_dist_schedule:
18690 case OMPC_defaultmap:
18691 case OMPC_unknown:
18692 case OMPC_uniform:
18693 case OMPC_to:
18694 case OMPC_from:
18695 case OMPC_use_device_ptr:
18696 case OMPC_use_device_addr:
18697 case OMPC_is_device_ptr:
18698 case OMPC_has_device_addr:
18699 case OMPC_atomic_default_mem_order:
18700 case OMPC_device_type:
18701 case OMPC_match:
18702 case OMPC_nontemporal:
18703 case OMPC_order:
18704 case OMPC_at:
18705 case OMPC_severity:
18706 case OMPC_message:
18707 case OMPC_novariants:
18708 case OMPC_nocontext:
18709 case OMPC_detach:
18710 case OMPC_inclusive:
18711 case OMPC_exclusive:
18712 case OMPC_uses_allocators:
18713 case OMPC_affinity:
18714 case OMPC_when:
18715 case OMPC_ompx_dyn_cgroup_mem:
18716 case OMPC_dyn_groupprivate:
18717 default:
18718 llvm_unreachable("Clause is not allowed.");
18719 }
18720 return Res;
18721}
18722
18723OMPClause *SemaOpenMP::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
18724 SourceLocation EndLoc,
18725 SourceLocation LParenLoc,
18726 Expr *Condition) {
18727 Expr *ValExpr = Condition;
18728 if (Condition && LParenLoc.isValid()) {
18729 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18730 !Condition->isInstantiationDependent() &&
18731 !Condition->containsUnexpandedParameterPack()) {
18732 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
18733 if (Val.isInvalid())
18734 return nullptr;
18735
18736 ValExpr = Val.get();
18737 }
18738 }
18739 DSAStack->setNowaitRegion();
18740 return new (getASTContext())
18741 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
18742}
18743
18744OMPClause *SemaOpenMP::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
18745 SourceLocation EndLoc) {
18746 DSAStack->setUntiedRegion();
18747 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
18748}
18749
18750OMPClause *SemaOpenMP::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
18751 SourceLocation EndLoc) {
18752 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
18753}
18754
18755OMPClause *SemaOpenMP::ActOnOpenMPReadClause(SourceLocation StartLoc,
18756 SourceLocation EndLoc) {
18757 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
18758}
18759
18760OMPClause *SemaOpenMP::ActOnOpenMPWriteClause(SourceLocation StartLoc,
18761 SourceLocation EndLoc) {
18762 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
18763}
18764
18765OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
18766 SourceLocation EndLoc) {
18767 return OMPUpdateClause::Create(C: getASTContext(), StartLoc, EndLoc);
18768}
18769
18770OMPClause *SemaOpenMP::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
18771 SourceLocation EndLoc) {
18772 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
18773}
18774
18775OMPClause *SemaOpenMP::ActOnOpenMPCompareClause(SourceLocation StartLoc,
18776 SourceLocation EndLoc) {
18777 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
18778}
18779
18780OMPClause *SemaOpenMP::ActOnOpenMPFailClause(SourceLocation StartLoc,
18781 SourceLocation EndLoc) {
18782 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
18783}
18784
18785OMPClause *SemaOpenMP::ActOnOpenMPFailClause(OpenMPClauseKind Parameter,
18786 SourceLocation KindLoc,
18787 SourceLocation StartLoc,
18788 SourceLocation LParenLoc,
18789 SourceLocation EndLoc) {
18790
18791 if (!checkFailClauseParameter(FailClauseParameter: Parameter)) {
18792 Diag(Loc: KindLoc, DiagID: diag::err_omp_atomic_fail_wrong_or_no_clauses);
18793 return nullptr;
18794 }
18795 return new (getASTContext())
18796 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
18797}
18798
18799OMPClause *SemaOpenMP::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
18800 SourceLocation EndLoc) {
18801 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
18802}
18803
18804OMPClause *SemaOpenMP::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
18805 SourceLocation EndLoc) {
18806 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
18807}
18808
18809OMPClause *SemaOpenMP::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
18810 SourceLocation EndLoc) {
18811 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
18812}
18813
18814OMPClause *SemaOpenMP::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
18815 SourceLocation EndLoc) {
18816 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
18817}
18818
18819OMPClause *SemaOpenMP::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
18820 SourceLocation EndLoc) {
18821 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
18822}
18823
18824OMPClause *SemaOpenMP::ActOnOpenMPWeakClause(SourceLocation StartLoc,
18825 SourceLocation EndLoc) {
18826 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
18827}
18828
18829OMPClause *SemaOpenMP::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
18830 SourceLocation EndLoc) {
18831 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
18832}
18833
18834OMPClause *SemaOpenMP::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
18835 SourceLocation EndLoc) {
18836 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
18837}
18838
18839OMPClause *SemaOpenMP::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
18840 SourceLocation EndLoc) {
18841 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
18842}
18843
18844OMPClause *SemaOpenMP::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
18845 SourceLocation EndLoc) {
18846 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
18847}
18848
18849OMPClause *
18850SemaOpenMP::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
18851 SourceLocation EndLoc) {
18852 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18853}
18854
18855OMPClause *SemaOpenMP::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
18856 SourceLocation EndLoc) {
18857 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
18858}
18859
18860OMPClause *
18861SemaOpenMP::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
18862 SourceLocation EndLoc) {
18863 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
18864}
18865
18866OMPClause *SemaOpenMP::ActOnOpenMPSelfMapsClause(SourceLocation StartLoc,
18867 SourceLocation EndLoc) {
18868 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
18869}
18870
18871StmtResult
18872SemaOpenMP::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
18873 SourceLocation StartLoc,
18874 SourceLocation EndLoc) {
18875
18876 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18877 // At least one action-clause must appear on a directive.
18878 if (!hasClauses(Clauses, K: OMPC_init, ClauseTypes: OMPC_use, ClauseTypes: OMPC_destroy, ClauseTypes: OMPC_nowait)) {
18879 unsigned OMPVersion = getLangOpts().OpenMP;
18880 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
18881 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
18882 << Expected << getOpenMPDirectiveName(D: OMPD_interop, Ver: OMPVersion);
18883 return StmtError();
18884 }
18885
18886 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18887 // A depend clause can only appear on the directive if a targetsync
18888 // interop-type is present or the interop-var was initialized with
18889 // the targetsync interop-type.
18890
18891 // If there is any 'init' clause diagnose if there is no 'init' clause with
18892 // interop-type of 'targetsync'. Cases involving other directives cannot be
18893 // diagnosed.
18894 const OMPDependClause *DependClause = nullptr;
18895 bool HasInitClause = false;
18896 bool IsTargetSync = false;
18897 for (const OMPClause *C : Clauses) {
18898 if (IsTargetSync)
18899 break;
18900 if (const auto *InitClause = dyn_cast<OMPInitClause>(Val: C)) {
18901 HasInitClause = true;
18902 if (InitClause->getIsTargetSync())
18903 IsTargetSync = true;
18904 } else if (const auto *DC = dyn_cast<OMPDependClause>(Val: C)) {
18905 DependClause = DC;
18906 }
18907 }
18908 if (DependClause && HasInitClause && !IsTargetSync) {
18909 Diag(Loc: DependClause->getBeginLoc(), DiagID: diag::err_omp_interop_bad_depend_clause);
18910 return StmtError();
18911 }
18912
18913 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18914 // Each interop-var may be specified for at most one action-clause of each
18915 // interop construct.
18916 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
18917 for (OMPClause *C : Clauses) {
18918 OpenMPClauseKind ClauseKind = C->getClauseKind();
18919 std::pair<ValueDecl *, bool> DeclResult;
18920 SourceLocation ELoc;
18921 SourceRange ERange;
18922
18923 if (ClauseKind == OMPC_init) {
18924 auto *E = cast<OMPInitClause>(Val: C)->getInteropVar();
18925 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
18926 } else if (ClauseKind == OMPC_use) {
18927 auto *E = cast<OMPUseClause>(Val: C)->getInteropVar();
18928 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
18929 } else if (ClauseKind == OMPC_destroy) {
18930 auto *E = cast<OMPDestroyClause>(Val: C)->getInteropVar();
18931 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
18932 }
18933
18934 if (DeclResult.first) {
18935 if (!InteropVars.insert(Ptr: DeclResult.first).second) {
18936 Diag(Loc: ELoc, DiagID: diag::err_omp_interop_var_multiple_actions)
18937 << DeclResult.first;
18938 return StmtError();
18939 }
18940 }
18941 }
18942
18943 return OMPInteropDirective::Create(C: getASTContext(), StartLoc, EndLoc,
18944 Clauses);
18945}
18946
18947static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
18948 SourceLocation VarLoc,
18949 OpenMPClauseKind Kind) {
18950 SourceLocation ELoc;
18951 SourceRange ERange;
18952 Expr *RefExpr = InteropVarExpr;
18953 auto Res = getPrivateItem(S&: SemaRef, RefExpr, ELoc, ERange,
18954 /*AllowArraySection=*/false,
18955 /*AllowAssumedSizeArray=*/false,
18956 /*DiagType=*/"omp_interop_t");
18957
18958 if (Res.second) {
18959 // It will be analyzed later.
18960 return true;
18961 }
18962
18963 if (!Res.first)
18964 return false;
18965
18966 // Interop variable should be of type omp_interop_t.
18967 bool HasError = false;
18968 QualType InteropType;
18969 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get(Name: "omp_interop_t"),
18970 VarLoc, Sema::LookupOrdinaryName);
18971 if (SemaRef.LookupName(R&: Result, S: SemaRef.getCurScope())) {
18972 NamedDecl *ND = Result.getFoundDecl();
18973 if (const auto *TD = dyn_cast<TypeDecl>(Val: ND)) {
18974 InteropType = QualType(TD->getTypeForDecl(), 0);
18975 } else {
18976 HasError = true;
18977 }
18978 } else {
18979 HasError = true;
18980 }
18981
18982 if (HasError) {
18983 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_implied_type_not_found)
18984 << "omp_interop_t";
18985 return false;
18986 }
18987
18988 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
18989 if (!SemaRef.Context.hasSameType(T1: InteropType, T2: VarType)) {
18990 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_interop_variable_wrong_type);
18991 return false;
18992 }
18993
18994 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18995 // The interop-var passed to init or destroy must be non-const.
18996 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
18997 isConstNotMutableType(SemaRef, Type: InteropVarExpr->getType())) {
18998 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_interop_variable_expected)
18999 << /*non-const*/ 1;
19000 return false;
19001 }
19002 return true;
19003}
19004
19005OMPClause *SemaOpenMP::ActOnOpenMPInitClause(
19006 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
19007 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
19008
19009 if (!isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_init))
19010 return nullptr;
19011
19012 // Check prefer_type values. fr() arguments are either string literals or
19013 // constant integral expressions; null Fr is only valid in OMP 6.0.
19014 // attr() arguments must be ext-string-literals with the 'ompx_' prefix
19015 // (OpenMP 6.0 spec, section 16.1.3).
19016 for (const OMPInteropPref &P : InteropInfo.Prefs) {
19017 const Expr *E = P.Fr;
19018 if (!E) {
19019 assert(InteropInfo.HasPreferAttrs && "null Fr requires OMP 6.0 syntax");
19020 } else if (!E->isValueDependent() && !E->isTypeDependent() &&
19021 !E->isInstantiationDependent() &&
19022 !E->containsUnexpandedParameterPack()) {
19023 if (!E->isIntegerConstantExpr(Ctx: getASTContext()) &&
19024 !isa<StringLiteral>(Val: E)) {
19025 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_interop_prefer_type);
19026 return nullptr;
19027 }
19028 }
19029 for (const Expr *A : P.Attrs) {
19030 if (A->isValueDependent() || A->isTypeDependent() ||
19031 A->isInstantiationDependent() || A->containsUnexpandedParameterPack())
19032 continue;
19033 const auto *SL = dyn_cast<StringLiteral>(Val: A);
19034 if (!SL) {
19035 Diag(Loc: A->getExprLoc(), DiagID: diag::err_omp_interop_attr_not_string);
19036 return nullptr;
19037 }
19038 if (!SL->getString().starts_with(Prefix: "ompx_")) {
19039 Diag(Loc: A->getExprLoc(), DiagID: diag::err_omp_interop_attr_missing_ompx_prefix)
19040 << SL->getString();
19041 return nullptr;
19042 }
19043 if (SL->getString().contains(C: ',')) {
19044 Diag(Loc: A->getExprLoc(), DiagID: diag::err_omp_interop_attr_contains_comma)
19045 << SL->getString();
19046 return nullptr;
19047 }
19048 }
19049 }
19050
19051 return OMPInitClause::Create(C: getASTContext(), InteropVar, InteropInfo,
19052 StartLoc, LParenLoc, VarLoc, EndLoc);
19053}
19054
19055OMPClause *SemaOpenMP::ActOnOpenMPUseClause(Expr *InteropVar,
19056 SourceLocation StartLoc,
19057 SourceLocation LParenLoc,
19058 SourceLocation VarLoc,
19059 SourceLocation EndLoc) {
19060
19061 if (!isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_use))
19062 return nullptr;
19063
19064 return new (getASTContext())
19065 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
19066}
19067
19068OMPClause *SemaOpenMP::ActOnOpenMPDestroyClause(Expr *InteropVar,
19069 SourceLocation StartLoc,
19070 SourceLocation LParenLoc,
19071 SourceLocation VarLoc,
19072 SourceLocation EndLoc) {
19073 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
19074 DSAStack->getCurrentDirective() == OMPD_depobj) {
19075 unsigned OMPVersion = getLangOpts().OpenMP;
19076 Diag(Loc: StartLoc, DiagID: diag::err_omp_expected_clause_argument)
19077 << getOpenMPClauseNameForDiag(C: OMPC_destroy)
19078 << getOpenMPDirectiveName(D: OMPD_depobj, Ver: OMPVersion);
19079 return nullptr;
19080 }
19081 if (InteropVar &&
19082 !isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_destroy))
19083 return nullptr;
19084
19085 return new (getASTContext())
19086 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
19087}
19088
19089OMPClause *SemaOpenMP::ActOnOpenMPNovariantsClause(Expr *Condition,
19090 SourceLocation StartLoc,
19091 SourceLocation LParenLoc,
19092 SourceLocation EndLoc) {
19093 Expr *ValExpr = Condition;
19094 Stmt *HelperValStmt = nullptr;
19095 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
19096 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
19097 !Condition->isInstantiationDependent() &&
19098 !Condition->containsUnexpandedParameterPack()) {
19099 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
19100 if (Val.isInvalid())
19101 return nullptr;
19102
19103 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
19104
19105 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19106 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_novariants,
19107 OpenMPVersion: getLangOpts().OpenMP);
19108 if (CaptureRegion != OMPD_unknown &&
19109 !SemaRef.CurContext->isDependentContext()) {
19110 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
19111 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19112 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
19113 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
19114 }
19115 }
19116
19117 return new (getASTContext()) OMPNovariantsClause(
19118 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19119}
19120
19121OMPClause *SemaOpenMP::ActOnOpenMPNocontextClause(Expr *Condition,
19122 SourceLocation StartLoc,
19123 SourceLocation LParenLoc,
19124 SourceLocation EndLoc) {
19125 Expr *ValExpr = Condition;
19126 Stmt *HelperValStmt = nullptr;
19127 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
19128 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
19129 !Condition->isInstantiationDependent() &&
19130 !Condition->containsUnexpandedParameterPack()) {
19131 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
19132 if (Val.isInvalid())
19133 return nullptr;
19134
19135 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
19136
19137 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19138 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_nocontext,
19139 OpenMPVersion: getLangOpts().OpenMP);
19140 if (CaptureRegion != OMPD_unknown &&
19141 !SemaRef.CurContext->isDependentContext()) {
19142 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
19143 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19144 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
19145 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
19146 }
19147 }
19148
19149 return new (getASTContext()) OMPNocontextClause(
19150 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19151}
19152
19153OMPClause *SemaOpenMP::ActOnOpenMPFilterClause(Expr *ThreadID,
19154 SourceLocation StartLoc,
19155 SourceLocation LParenLoc,
19156 SourceLocation EndLoc) {
19157 Expr *ValExpr = ThreadID;
19158 Stmt *HelperValStmt = nullptr;
19159
19160 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19161 OpenMPDirectiveKind CaptureRegion =
19162 getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_filter, OpenMPVersion: getLangOpts().OpenMP);
19163 if (CaptureRegion != OMPD_unknown &&
19164 !SemaRef.CurContext->isDependentContext()) {
19165 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
19166 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19167 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
19168 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
19169 }
19170
19171 return new (getASTContext()) OMPFilterClause(
19172 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19173}
19174
19175OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
19176 ArrayRef<Expr *> VarList,
19177 const OMPVarListLocTy &Locs,
19178 OpenMPVarListDataTy &Data) {
19179 SourceLocation StartLoc = Locs.StartLoc;
19180 SourceLocation LParenLoc = Locs.LParenLoc;
19181 SourceLocation EndLoc = Locs.EndLoc;
19182 OMPClause *Res = nullptr;
19183 int ExtraModifier = Data.ExtraModifier;
19184 int OriginalSharingModifier = Data.OriginalSharingModifier;
19185 Expr *ExtraModifierExpr = Data.ExtraModifierExpr;
19186 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
19187 SourceLocation ColonLoc = Data.ColonLoc;
19188 switch (Kind) {
19189 case OMPC_private:
19190 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
19191 break;
19192 case OMPC_firstprivate:
19193 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
19194 break;
19195 case OMPC_lastprivate:
19196 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
19197 "Unexpected lastprivate modifier.");
19198 Res = ActOnOpenMPLastprivateClause(
19199 VarList, LPKind: static_cast<OpenMPLastprivateModifier>(ExtraModifier),
19200 LPKindLoc: ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
19201 break;
19202 case OMPC_shared:
19203 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
19204 break;
19205 case OMPC_reduction:
19206 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
19207 "Unexpected lastprivate modifier.");
19208 Res = ActOnOpenMPReductionClause(
19209 VarList,
19210 Modifiers: OpenMPVarListDataTy::OpenMPReductionClauseModifiers(
19211 ExtraModifier, OriginalSharingModifier),
19212 StartLoc, LParenLoc, ModifierLoc: ExtraModifierLoc, ColonLoc, EndLoc,
19213 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
19214 break;
19215 case OMPC_task_reduction:
19216 Res = ActOnOpenMPTaskReductionClause(
19217 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
19218 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
19219 break;
19220 case OMPC_in_reduction:
19221 Res = ActOnOpenMPInReductionClause(
19222 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
19223 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
19224 break;
19225 case OMPC_linear:
19226 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
19227 "Unexpected linear modifier.");
19228 Res = ActOnOpenMPLinearClause(
19229 VarList, Step: Data.DepModOrTailExpr, StartLoc, LParenLoc,
19230 LinKind: static_cast<OpenMPLinearClauseKind>(ExtraModifier), LinLoc: ExtraModifierLoc,
19231 ColonLoc, StepModifierLoc: Data.StepModifierLoc, EndLoc);
19232 break;
19233 case OMPC_aligned:
19234 Res = ActOnOpenMPAlignedClause(VarList, Alignment: Data.DepModOrTailExpr, StartLoc,
19235 LParenLoc, ColonLoc, EndLoc);
19236 break;
19237 case OMPC_copyin:
19238 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
19239 break;
19240 case OMPC_copyprivate:
19241 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
19242 break;
19243 case OMPC_flush:
19244 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
19245 break;
19246 case OMPC_depend:
19247 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
19248 "Unexpected depend modifier.");
19249 Res = ActOnOpenMPDependClause(
19250 Data: {.DepKind: static_cast<OpenMPDependClauseKind>(ExtraModifier), .DepLoc: ExtraModifierLoc,
19251 .ColonLoc: ColonLoc, .OmpAllMemoryLoc: Data.OmpAllMemoryLoc},
19252 DepModifier: Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
19253 break;
19254 case OMPC_map:
19255 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
19256 "Unexpected map modifier.");
19257 Res = ActOnOpenMPMapClause(
19258 IteratorModifier: Data.IteratorExpr, MapTypeModifiers: Data.MapTypeModifiers, MapTypeModifiersLoc: Data.MapTypeModifiersLoc,
19259 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId,
19260 MapType: static_cast<OpenMPMapClauseKind>(ExtraModifier), IsMapTypeImplicit: Data.IsMapTypeImplicit,
19261 MapLoc: ExtraModifierLoc, ColonLoc, VarList, Locs);
19262 break;
19263 case OMPC_to:
19264 Res = ActOnOpenMPToClause(
19265 MotionModifiers: Data.MotionModifiers, MotionModifiersLoc: Data.MotionModifiersLoc, IteratorModifier: Data.IteratorExpr,
19266 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId, ColonLoc,
19267 VarList, Locs);
19268 break;
19269 case OMPC_from:
19270 Res = ActOnOpenMPFromClause(
19271 MotionModifiers: Data.MotionModifiers, MotionModifiersLoc: Data.MotionModifiersLoc, IteratorModifier: Data.IteratorExpr,
19272 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId, ColonLoc,
19273 VarList, Locs);
19274 break;
19275 case OMPC_use_device_ptr:
19276 assert(0 <= Data.ExtraModifier &&
19277 Data.ExtraModifier <= OMPC_USE_DEVICE_PTR_FALLBACK_unknown &&
19278 "Unexpected use_device_ptr fallback modifier.");
19279 Res = ActOnOpenMPUseDevicePtrClause(
19280 VarList, Locs,
19281 FallbackModifier: static_cast<OpenMPUseDevicePtrFallbackModifier>(Data.ExtraModifier),
19282 FallbackModifierLoc: Data.ExtraModifierLoc);
19283 break;
19284 case OMPC_use_device_addr:
19285 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
19286 break;
19287 case OMPC_is_device_ptr:
19288 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
19289 break;
19290 case OMPC_has_device_addr:
19291 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
19292 break;
19293 case OMPC_allocate: {
19294 OpenMPAllocateClauseModifier Modifier1 = OMPC_ALLOCATE_unknown;
19295 OpenMPAllocateClauseModifier Modifier2 = OMPC_ALLOCATE_unknown;
19296 SourceLocation Modifier1Loc, Modifier2Loc;
19297 if (!Data.AllocClauseModifiers.empty()) {
19298 assert(Data.AllocClauseModifiers.size() <= 2 &&
19299 "More allocate modifiers than expected");
19300 Modifier1 = Data.AllocClauseModifiers[0];
19301 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
19302 if (Data.AllocClauseModifiers.size() == 2) {
19303 Modifier2 = Data.AllocClauseModifiers[1];
19304 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
19305 }
19306 }
19307 Res = ActOnOpenMPAllocateClause(
19308 Allocator: Data.DepModOrTailExpr, Alignment: Data.AllocateAlignment, FirstModifier: Modifier1, FirstModifierLoc: Modifier1Loc,
19309 SecondModifier: Modifier2, SecondModifierLoc: Modifier2Loc, VarList, StartLoc, ColonLoc: LParenLoc, LParenLoc: ColonLoc,
19310 EndLoc);
19311 break;
19312 }
19313 case OMPC_nontemporal:
19314 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
19315 break;
19316 case OMPC_inclusive:
19317 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
19318 break;
19319 case OMPC_exclusive:
19320 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
19321 break;
19322 case OMPC_affinity:
19323 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
19324 Modifier: Data.DepModOrTailExpr, Locators: VarList);
19325 break;
19326 case OMPC_doacross:
19327 Res = ActOnOpenMPDoacrossClause(
19328 DepType: static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
19329 DepLoc: ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
19330 break;
19331 case OMPC_num_teams:
19332 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_NUMTEAMS_unknown &&
19333 "Unexpected num_teams modifier.");
19334 Res = ActOnOpenMPNumTeamsClause(
19335 VarList, Modifier: static_cast<OpenMPNumTeamsClauseModifier>(ExtraModifier),
19336 ModifierExpr: ExtraModifierExpr, ModifierLoc: ExtraModifierLoc, StartLoc, LParenLoc, EndLoc);
19337 break;
19338 case OMPC_thread_limit:
19339 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
19340 break;
19341 case OMPC_if:
19342 case OMPC_depobj:
19343 case OMPC_final:
19344 case OMPC_num_threads:
19345 case OMPC_safelen:
19346 case OMPC_simdlen:
19347 case OMPC_sizes:
19348 case OMPC_allocator:
19349 case OMPC_collapse:
19350 case OMPC_default:
19351 case OMPC_proc_bind:
19352 case OMPC_schedule:
19353 case OMPC_ordered:
19354 case OMPC_nowait:
19355 case OMPC_untied:
19356 case OMPC_mergeable:
19357 case OMPC_threadprivate:
19358 case OMPC_groupprivate:
19359 case OMPC_read:
19360 case OMPC_write:
19361 case OMPC_update:
19362 case OMPC_capture:
19363 case OMPC_compare:
19364 case OMPC_seq_cst:
19365 case OMPC_acq_rel:
19366 case OMPC_acquire:
19367 case OMPC_release:
19368 case OMPC_relaxed:
19369 case OMPC_device:
19370 case OMPC_threads:
19371 case OMPC_simd:
19372 case OMPC_priority:
19373 case OMPC_grainsize:
19374 case OMPC_nogroup:
19375 case OMPC_num_tasks:
19376 case OMPC_hint:
19377 case OMPC_dist_schedule:
19378 case OMPC_defaultmap:
19379 case OMPC_unknown:
19380 case OMPC_uniform:
19381 case OMPC_unified_address:
19382 case OMPC_unified_shared_memory:
19383 case OMPC_reverse_offload:
19384 case OMPC_dynamic_allocators:
19385 case OMPC_atomic_default_mem_order:
19386 case OMPC_self_maps:
19387 case OMPC_device_type:
19388 case OMPC_match:
19389 case OMPC_order:
19390 case OMPC_at:
19391 case OMPC_severity:
19392 case OMPC_message:
19393 case OMPC_destroy:
19394 case OMPC_novariants:
19395 case OMPC_nocontext:
19396 case OMPC_detach:
19397 case OMPC_uses_allocators:
19398 case OMPC_when:
19399 case OMPC_bind:
19400 default:
19401 llvm_unreachable("Clause is not allowed.");
19402 }
19403 return Res;
19404}
19405
19406ExprResult SemaOpenMP::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
19407 ExprObjectKind OK,
19408 SourceLocation Loc) {
19409 ExprResult Res = SemaRef.BuildDeclRefExpr(
19410 D: Capture, Ty: Capture->getType().getNonReferenceType(), VK: VK_LValue, Loc);
19411 if (!Res.isUsable())
19412 return ExprError();
19413 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
19414 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: Loc, Opc: UO_Deref, InputExpr: Res.get());
19415 if (!Res.isUsable())
19416 return ExprError();
19417 }
19418 if (VK != VK_LValue && Res.get()->isGLValue()) {
19419 Res = SemaRef.DefaultLvalueConversion(E: Res.get());
19420 if (!Res.isUsable())
19421 return ExprError();
19422 }
19423 return Res;
19424}
19425
19426OMPClause *SemaOpenMP::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
19427 SourceLocation StartLoc,
19428 SourceLocation LParenLoc,
19429 SourceLocation EndLoc) {
19430 SmallVector<Expr *, 8> Vars;
19431 SmallVector<Expr *, 8> PrivateCopies;
19432 unsigned OMPVersion = getLangOpts().OpenMP;
19433 bool IsImplicitClause =
19434 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
19435 for (Expr *RefExpr : VarList) {
19436 assert(RefExpr && "NULL expr in OpenMP private clause.");
19437 SourceLocation ELoc;
19438 SourceRange ERange;
19439 Expr *SimpleRefExpr = RefExpr;
19440 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
19441 if (Res.second) {
19442 // It will be analyzed later.
19443 Vars.push_back(Elt: RefExpr);
19444 PrivateCopies.push_back(Elt: nullptr);
19445 }
19446 ValueDecl *D = Res.first;
19447 if (!D)
19448 continue;
19449
19450 QualType Type = D->getType();
19451 auto *VD = dyn_cast<VarDecl>(Val: D);
19452
19453 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19454 // A variable that appears in a private clause must not have an incomplete
19455 // type or a reference type.
19456 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
19457 DiagID: diag::err_omp_private_incomplete_type))
19458 continue;
19459 Type = Type.getNonReferenceType();
19460
19461 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19462 // A variable that is privatized must not have a const-qualified type
19463 // unless it is of class type with a mutable member. This restriction does
19464 // not apply to the firstprivate clause.
19465 //
19466 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
19467 // A variable that appears in a private clause must not have a
19468 // const-qualified type unless it is of class type with a mutable member.
19469 if (rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_private, ELoc))
19470 continue;
19471
19472 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19473 // in a Construct]
19474 // Variables with the predetermined data-sharing attributes may not be
19475 // listed in data-sharing attributes clauses, except for the cases
19476 // listed below. For these exceptions only, listing a predetermined
19477 // variable in a data-sharing attribute clause is allowed and overrides
19478 // the variable's predetermined data-sharing attributes.
19479 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19480 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
19481 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
19482 << getOpenMPClauseNameForDiag(C: DVar.CKind)
19483 << getOpenMPClauseNameForDiag(C: OMPC_private);
19484 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19485 continue;
19486 }
19487
19488 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19489 // Variably modified types are not supported for tasks.
19490 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
19491 isOpenMPTaskingDirective(Kind: CurrDir)) {
19492 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
19493 << getOpenMPClauseNameForDiag(C: OMPC_private) << Type
19494 << getOpenMPDirectiveName(D: CurrDir, Ver: OMPVersion);
19495 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19496 VarDecl::DeclarationOnly;
19497 Diag(Loc: D->getLocation(),
19498 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19499 << D;
19500 continue;
19501 }
19502
19503 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19504 // A list item cannot appear in both a map clause and a data-sharing
19505 // attribute clause on the same construct
19506 //
19507 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19508 // A list item cannot appear in both a map clause and a data-sharing
19509 // attribute clause on the same construct unless the construct is a
19510 // combined construct.
19511 if ((getLangOpts().OpenMP <= 45 &&
19512 isOpenMPTargetExecutionDirective(DKind: CurrDir)) ||
19513 CurrDir == OMPD_target) {
19514 OpenMPClauseKind ConflictKind;
19515 if (DSAStack->checkMappableExprComponentListsForDecl(
19516 VD, /*CurrentRegionOnly=*/true,
19517 Check: [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
19518 OpenMPClauseKind WhereFoundClauseKind) -> bool {
19519 ConflictKind = WhereFoundClauseKind;
19520 return true;
19521 })) {
19522 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
19523 << getOpenMPClauseNameForDiag(C: OMPC_private)
19524 << getOpenMPClauseNameForDiag(C: ConflictKind)
19525 << getOpenMPDirectiveName(D: CurrDir, Ver: OMPVersion);
19526 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19527 continue;
19528 }
19529 }
19530
19531 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
19532 // A variable of class type (or array thereof) that appears in a private
19533 // clause requires an accessible, unambiguous default constructor for the
19534 // class type.
19535 // Generate helper private variable and initialize it with the default
19536 // value. The address of the original variable is replaced by the address of
19537 // the new private variable in CodeGen. This new variable is not added to
19538 // IdResolver, so the code in the OpenMP region uses original variable for
19539 // proper diagnostics.
19540 Type = Type.getUnqualifiedType();
19541 VarDecl *VDPrivate =
19542 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
19543 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
19544 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
19545 SemaRef.ActOnUninitializedDecl(dcl: VDPrivate);
19546 if (VDPrivate->isInvalidDecl())
19547 continue;
19548 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19549 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(), Loc: ELoc);
19550
19551 DeclRefExpr *Ref = nullptr;
19552 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19553 auto *FD = dyn_cast<FieldDecl>(Val: D);
19554 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19555 if (VD)
19556 Ref = buildDeclRefExpr(S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(),
19557 Loc: RefExpr->getExprLoc());
19558 else
19559 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
19560 }
19561 if (!IsImplicitClause)
19562 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_private, PrivateCopy: Ref);
19563 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
19564 ? RefExpr->IgnoreParens()
19565 : Ref);
19566 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
19567 }
19568
19569 if (Vars.empty())
19570 return nullptr;
19571
19572 return OMPPrivateClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
19573 VL: Vars, PrivateVL: PrivateCopies);
19574}
19575
19576OMPClause *SemaOpenMP::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
19577 SourceLocation StartLoc,
19578 SourceLocation LParenLoc,
19579 SourceLocation EndLoc) {
19580 SmallVector<Expr *, 8> Vars;
19581 SmallVector<Expr *, 8> PrivateCopies;
19582 SmallVector<Expr *, 8> Inits;
19583 SmallVector<Decl *, 4> ExprCaptures;
19584 bool IsImplicitClause =
19585 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
19586 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
19587 unsigned OMPVersion = getLangOpts().OpenMP;
19588
19589 for (Expr *RefExpr : VarList) {
19590 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
19591 SourceLocation ELoc;
19592 SourceRange ERange;
19593 Expr *SimpleRefExpr = RefExpr;
19594 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
19595 if (Res.second) {
19596 // It will be analyzed later.
19597 Vars.push_back(Elt: RefExpr);
19598 PrivateCopies.push_back(Elt: nullptr);
19599 Inits.push_back(Elt: nullptr);
19600 }
19601 ValueDecl *D = Res.first;
19602 if (!D)
19603 continue;
19604
19605 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
19606 QualType Type = D->getType();
19607 auto *VD = dyn_cast<VarDecl>(Val: D);
19608
19609 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19610 // A variable that appears in a private clause must not have an incomplete
19611 // type or a reference type.
19612 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
19613 DiagID: diag::err_omp_firstprivate_incomplete_type))
19614 continue;
19615 Type = Type.getNonReferenceType();
19616
19617 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
19618 // A variable of class type (or array thereof) that appears in a private
19619 // clause requires an accessible, unambiguous copy constructor for the
19620 // class type.
19621 QualType ElemType =
19622 getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
19623
19624 // If an implicit firstprivate variable found it was checked already.
19625 DSAStackTy::DSAVarData TopDVar;
19626 if (!IsImplicitClause) {
19627 DSAStackTy::DSAVarData DVar =
19628 DSAStack->getTopDSA(D, /*FromParent=*/false);
19629 TopDVar = DVar;
19630 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19631 bool IsConstant = ElemType.isConstant(Ctx: getASTContext());
19632 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
19633 // A list item that specifies a given variable may not appear in more
19634 // than one clause on the same directive, except that a variable may be
19635 // specified in both firstprivate and lastprivate clauses.
19636 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19637 // A list item may appear in a firstprivate or lastprivate clause but not
19638 // both.
19639 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
19640 (isOpenMPDistributeDirective(DKind: CurrDir) ||
19641 DVar.CKind != OMPC_lastprivate) &&
19642 DVar.RefExpr) {
19643 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
19644 << getOpenMPClauseNameForDiag(C: DVar.CKind)
19645 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
19646 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19647 continue;
19648 }
19649
19650 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19651 // in a Construct]
19652 // Variables with the predetermined data-sharing attributes may not be
19653 // listed in data-sharing attributes clauses, except for the cases
19654 // listed below. For these exceptions only, listing a predetermined
19655 // variable in a data-sharing attribute clause is allowed and overrides
19656 // the variable's predetermined data-sharing attributes.
19657 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19658 // in a Construct, C/C++, p.2]
19659 // Variables with const-qualified type having no mutable member may be
19660 // listed in a firstprivate clause, even if they are static data members.
19661 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
19662 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
19663 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
19664 << getOpenMPClauseNameForDiag(C: DVar.CKind)
19665 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
19666 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19667 continue;
19668 }
19669
19670 // OpenMP [2.9.3.4, Restrictions, p.2]
19671 // A list item that is private within a parallel region must not appear
19672 // in a firstprivate clause on a worksharing construct if any of the
19673 // worksharing regions arising from the worksharing construct ever bind
19674 // to any of the parallel regions arising from the parallel construct.
19675 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19676 // A list item that is private within a teams region must not appear in a
19677 // firstprivate clause on a distribute construct if any of the distribute
19678 // regions arising from the distribute construct ever bind to any of the
19679 // teams regions arising from the teams construct.
19680 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19681 // A list item that appears in a reduction clause of a teams construct
19682 // must not appear in a firstprivate clause on a distribute construct if
19683 // any of the distribute regions arising from the distribute construct
19684 // ever bind to any of the teams regions arising from the teams construct.
19685 if ((isOpenMPWorksharingDirective(DKind: CurrDir) ||
19686 isOpenMPDistributeDirective(DKind: CurrDir)) &&
19687 !isOpenMPParallelDirective(DKind: CurrDir) &&
19688 !isOpenMPTeamsDirective(DKind: CurrDir)) {
19689 DVar = DSAStack->getImplicitDSA(D, FromParent: true);
19690 if (DVar.CKind != OMPC_shared &&
19691 (isOpenMPParallelDirective(DKind: DVar.DKind) ||
19692 isOpenMPTeamsDirective(DKind: DVar.DKind) ||
19693 DVar.DKind == OMPD_unknown)) {
19694 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
19695 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate)
19696 << getOpenMPClauseNameForDiag(C: OMPC_shared);
19697 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19698 continue;
19699 }
19700 }
19701 // OpenMP [2.9.3.4, Restrictions, p.3]
19702 // A list item that appears in a reduction clause of a parallel construct
19703 // must not appear in a firstprivate clause on a worksharing or task
19704 // construct if any of the worksharing or task regions arising from the
19705 // worksharing or task construct ever bind to any of the parallel regions
19706 // arising from the parallel construct.
19707 // OpenMP [2.9.3.4, Restrictions, p.4]
19708 // A list item that appears in a reduction clause in worksharing
19709 // construct must not appear in a firstprivate clause in a task construct
19710 // encountered during execution of any of the worksharing regions arising
19711 // from the worksharing construct.
19712 if (isOpenMPTaskingDirective(Kind: CurrDir)) {
19713 DVar = DSAStack->hasInnermostDSA(
19714 D,
19715 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
19716 return C == OMPC_reduction && !AppliedToPointee;
19717 },
19718 DPred: [](OpenMPDirectiveKind K) {
19719 return isOpenMPParallelDirective(DKind: K) ||
19720 isOpenMPWorksharingDirective(DKind: K) ||
19721 isOpenMPTeamsDirective(DKind: K);
19722 },
19723 /*FromParent=*/true);
19724 if (DVar.CKind == OMPC_reduction &&
19725 (isOpenMPParallelDirective(DKind: DVar.DKind) ||
19726 isOpenMPWorksharingDirective(DKind: DVar.DKind) ||
19727 isOpenMPTeamsDirective(DKind: DVar.DKind))) {
19728 Diag(Loc: ELoc, DiagID: diag::err_omp_parallel_reduction_in_task_firstprivate)
19729 << getOpenMPDirectiveName(D: DVar.DKind, Ver: OMPVersion);
19730 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19731 continue;
19732 }
19733 }
19734
19735 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19736 // A list item cannot appear in both a map clause and a data-sharing
19737 // attribute clause on the same construct
19738 //
19739 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19740 // A list item cannot appear in both a map clause and a data-sharing
19741 // attribute clause on the same construct unless the construct is a
19742 // combined construct.
19743 if ((getLangOpts().OpenMP <= 45 &&
19744 isOpenMPTargetExecutionDirective(DKind: CurrDir)) ||
19745 CurrDir == OMPD_target) {
19746 OpenMPClauseKind ConflictKind;
19747 if (DSAStack->checkMappableExprComponentListsForDecl(
19748 VD, /*CurrentRegionOnly=*/true,
19749 Check: [&ConflictKind](
19750 OMPClauseMappableExprCommon::MappableExprComponentListRef,
19751 OpenMPClauseKind WhereFoundClauseKind) {
19752 ConflictKind = WhereFoundClauseKind;
19753 return true;
19754 })) {
19755 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
19756 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate)
19757 << getOpenMPClauseNameForDiag(C: ConflictKind)
19758 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19759 Ver: OMPVersion);
19760 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19761 continue;
19762 }
19763 }
19764 }
19765
19766 // Variably modified types are not supported for tasks.
19767 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
19768 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
19769 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
19770 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate) << Type
19771 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19772 Ver: OMPVersion);
19773 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19774 VarDecl::DeclarationOnly;
19775 Diag(Loc: D->getLocation(),
19776 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19777 << D;
19778 continue;
19779 }
19780
19781 Type = Type.getUnqualifiedType();
19782 VarDecl *VDPrivate =
19783 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
19784 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
19785 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
19786 // Generate helper private variable and initialize it with the value of the
19787 // original variable. The address of the original variable is replaced by
19788 // the address of the new private variable in the CodeGen. This new variable
19789 // is not added to IdResolver, so the code in the OpenMP region uses
19790 // original variable for proper diagnostics and variable capturing.
19791 Expr *VDInitRefExpr = nullptr;
19792 // For arrays generate initializer for single element and replace it by the
19793 // original array element in CodeGen.
19794 if (Type->isArrayType()) {
19795 VarDecl *VDInit =
19796 buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type: ElemType, Name: D->getName());
19797 VDInitRefExpr = buildDeclRefExpr(S&: SemaRef, D: VDInit, Ty: ElemType, Loc: ELoc);
19798 Expr *Init = SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get();
19799 ElemType = ElemType.getUnqualifiedType();
19800 VarDecl *VDInitTemp = buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(),
19801 Type: ElemType, Name: ".firstprivate.temp");
19802 InitializedEntity Entity =
19803 InitializedEntity::InitializeVariable(Var: VDInitTemp);
19804 InitializationKind Kind = InitializationKind::CreateCopy(InitLoc: ELoc, EqualLoc: ELoc);
19805
19806 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
19807 ExprResult Result = InitSeq.Perform(S&: SemaRef, Entity, Kind, Args: Init);
19808 if (Result.isInvalid())
19809 VDPrivate->setInvalidDecl();
19810 else
19811 VDPrivate->setInit(Result.getAs<Expr>());
19812 // Remove temp variable declaration.
19813 getASTContext().Deallocate(Ptr: VDInitTemp);
19814 } else {
19815 VarDecl *VDInit = buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type,
19816 Name: ".firstprivate.temp");
19817 VDInitRefExpr = buildDeclRefExpr(S&: SemaRef, D: VDInit, Ty: RefExpr->getType(),
19818 Loc: RefExpr->getExprLoc());
19819 SemaRef.AddInitializerToDecl(
19820 dcl: VDPrivate, init: SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get(),
19821 /*DirectInit=*/false);
19822 }
19823 if (VDPrivate->isInvalidDecl()) {
19824 if (IsImplicitClause) {
19825 Diag(Loc: RefExpr->getExprLoc(),
19826 DiagID: diag::note_omp_task_predetermined_firstprivate_here);
19827 }
19828 continue;
19829 }
19830 SemaRef.CurContext->addDecl(D: VDPrivate);
19831 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19832 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(),
19833 Loc: RefExpr->getExprLoc());
19834 DeclRefExpr *Ref = nullptr;
19835 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19836 if (TopDVar.CKind == OMPC_lastprivate) {
19837 Ref = TopDVar.PrivateCopy;
19838 } else {
19839 auto *FD = dyn_cast<FieldDecl>(Val: D);
19840 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19841 if (VD)
19842 Ref =
19843 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(),
19844 Loc: RefExpr->getExprLoc());
19845 else
19846 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
19847 if (VD || !isOpenMPCapturedDecl(D))
19848 ExprCaptures.push_back(Elt: Ref->getDecl());
19849 }
19850 }
19851 if (!IsImplicitClause)
19852 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
19853 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
19854 ? RefExpr->IgnoreParens()
19855 : Ref);
19856 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
19857 Inits.push_back(Elt: VDInitRefExpr);
19858 }
19859
19860 if (Vars.empty())
19861 return nullptr;
19862
19863 return OMPFirstprivateClause::Create(
19864 C: getASTContext(), StartLoc, LParenLoc, EndLoc, VL: Vars, PrivateVL: PrivateCopies, InitVL: Inits,
19865 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures));
19866}
19867
19868OMPClause *SemaOpenMP::ActOnOpenMPLastprivateClause(
19869 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
19870 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
19871 SourceLocation LParenLoc, SourceLocation EndLoc) {
19872 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
19873 assert(ColonLoc.isValid() && "Colon location must be valid.");
19874 Diag(Loc: LPKindLoc, DiagID: diag::err_omp_unexpected_clause_value)
19875 << getListOfPossibleValues(K: OMPC_lastprivate, /*First=*/0,
19876 /*Last=*/OMPC_LASTPRIVATE_unknown)
19877 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate);
19878 return nullptr;
19879 }
19880
19881 SmallVector<Expr *, 8> Vars;
19882 SmallVector<Expr *, 8> SrcExprs;
19883 SmallVector<Expr *, 8> DstExprs;
19884 SmallVector<Expr *, 8> AssignmentOps;
19885 SmallVector<Decl *, 4> ExprCaptures;
19886 SmallVector<Expr *, 4> ExprPostUpdates;
19887 for (Expr *RefExpr : VarList) {
19888 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
19889 SourceLocation ELoc;
19890 SourceRange ERange;
19891 Expr *SimpleRefExpr = RefExpr;
19892 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
19893 if (Res.second) {
19894 // It will be analyzed later.
19895 Vars.push_back(Elt: RefExpr);
19896 SrcExprs.push_back(Elt: nullptr);
19897 DstExprs.push_back(Elt: nullptr);
19898 AssignmentOps.push_back(Elt: nullptr);
19899 }
19900 ValueDecl *D = Res.first;
19901 if (!D)
19902 continue;
19903
19904 QualType Type = D->getType();
19905 auto *VD = dyn_cast<VarDecl>(Val: D);
19906
19907 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
19908 // A variable that appears in a lastprivate clause must not have an
19909 // incomplete type or a reference type.
19910 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
19911 DiagID: diag::err_omp_lastprivate_incomplete_type))
19912 continue;
19913 Type = Type.getNonReferenceType();
19914
19915 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19916 // A variable that is privatized must not have a const-qualified type
19917 // unless it is of class type with a mutable member. This restriction does
19918 // not apply to the firstprivate clause.
19919 //
19920 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
19921 // A variable that appears in a lastprivate clause must not have a
19922 // const-qualified type unless it is of class type with a mutable member.
19923 if (rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_lastprivate, ELoc))
19924 continue;
19925
19926 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
19927 // A list item that appears in a lastprivate clause with the conditional
19928 // modifier must be a scalar variable.
19929 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
19930 Diag(Loc: ELoc, DiagID: diag::err_omp_lastprivate_conditional_non_scalar);
19931 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19932 VarDecl::DeclarationOnly;
19933 Diag(Loc: D->getLocation(),
19934 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19935 << D;
19936 continue;
19937 }
19938
19939 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19940 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19941 // in a Construct]
19942 // Variables with the predetermined data-sharing attributes may not be
19943 // listed in data-sharing attributes clauses, except for the cases
19944 // listed below.
19945 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19946 // A list item may appear in a firstprivate or lastprivate clause but not
19947 // both.
19948 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19949 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19950 (isOpenMPDistributeDirective(DKind: CurrDir) ||
19951 DVar.CKind != OMPC_firstprivate) &&
19952 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
19953 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
19954 << getOpenMPClauseNameForDiag(C: DVar.CKind)
19955 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate);
19956 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19957 continue;
19958 }
19959
19960 // OpenMP [2.14.3.5, Restrictions, p.2]
19961 // A list item that is private within a parallel region, or that appears in
19962 // the reduction clause of a parallel construct, must not appear in a
19963 // lastprivate clause on a worksharing construct if any of the corresponding
19964 // worksharing regions ever binds to any of the corresponding parallel
19965 // regions.
19966 DSAStackTy::DSAVarData TopDVar = DVar;
19967 if (isOpenMPWorksharingDirective(DKind: CurrDir) &&
19968 !isOpenMPParallelDirective(DKind: CurrDir) &&
19969 !isOpenMPTeamsDirective(DKind: CurrDir)) {
19970 DVar = DSAStack->getImplicitDSA(D, FromParent: true);
19971 if (DVar.CKind != OMPC_shared) {
19972 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
19973 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate)
19974 << getOpenMPClauseNameForDiag(C: OMPC_shared);
19975 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19976 continue;
19977 }
19978 }
19979
19980 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
19981 // A variable of class type (or array thereof) that appears in a
19982 // lastprivate clause requires an accessible, unambiguous default
19983 // constructor for the class type, unless the list item is also specified
19984 // in a firstprivate clause.
19985 // A variable of class type (or array thereof) that appears in a
19986 // lastprivate clause requires an accessible, unambiguous copy assignment
19987 // operator for the class type.
19988 Type = getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
19989 VarDecl *SrcVD = buildVarDecl(SemaRef, Loc: ERange.getBegin(),
19990 Type: Type.getUnqualifiedType(), Name: ".lastprivate.src",
19991 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
19992 DeclRefExpr *PseudoSrcExpr =
19993 buildDeclRefExpr(S&: SemaRef, D: SrcVD, Ty: Type.getUnqualifiedType(), Loc: ELoc);
19994 VarDecl *DstVD =
19995 buildVarDecl(SemaRef, Loc: ERange.getBegin(), Type, Name: ".lastprivate.dst",
19996 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
19997 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: Type, Loc: ELoc);
19998 // For arrays generate assignment operation for single element and replace
19999 // it by the original array element in CodeGen.
20000 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, OpLoc: ELoc, Opc: BO_Assign,
20001 LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
20002 if (AssignmentOp.isInvalid())
20003 continue;
20004 AssignmentOp = SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: ELoc,
20005 /*DiscardedValue=*/false);
20006 if (AssignmentOp.isInvalid())
20007 continue;
20008
20009 DeclRefExpr *Ref = nullptr;
20010 if (!VD && !SemaRef.CurContext->isDependentContext()) {
20011 if (TopDVar.CKind == OMPC_firstprivate) {
20012 Ref = TopDVar.PrivateCopy;
20013 } else {
20014 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
20015 if (!isOpenMPCapturedDecl(D))
20016 ExprCaptures.push_back(Elt: Ref->getDecl());
20017 }
20018 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
20019 (!isOpenMPCapturedDecl(D) &&
20020 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
20021 ExprResult RefRes = SemaRef.DefaultLvalueConversion(E: Ref);
20022 if (!RefRes.isUsable())
20023 continue;
20024 ExprResult PostUpdateRes =
20025 SemaRef.BuildBinOp(DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign,
20026 LHSExpr: SimpleRefExpr, RHSExpr: RefRes.get());
20027 if (!PostUpdateRes.isUsable())
20028 continue;
20029 ExprPostUpdates.push_back(
20030 Elt: SemaRef.IgnoredValueConversions(E: PostUpdateRes.get()).get());
20031 }
20032 }
20033 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_lastprivate, PrivateCopy: Ref);
20034 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
20035 ? RefExpr->IgnoreParens()
20036 : Ref);
20037 SrcExprs.push_back(Elt: PseudoSrcExpr);
20038 DstExprs.push_back(Elt: PseudoDstExpr);
20039 AssignmentOps.push_back(Elt: AssignmentOp.get());
20040 }
20041
20042 if (Vars.empty())
20043 return nullptr;
20044
20045 return OMPLastprivateClause::Create(
20046 C: getASTContext(), StartLoc, LParenLoc, EndLoc, VL: Vars, SrcExprs, DstExprs,
20047 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
20048 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures),
20049 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: ExprPostUpdates));
20050}
20051
20052OMPClause *SemaOpenMP::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
20053 SourceLocation StartLoc,
20054 SourceLocation LParenLoc,
20055 SourceLocation EndLoc) {
20056 SmallVector<Expr *, 8> Vars;
20057 for (Expr *RefExpr : VarList) {
20058 assert(RefExpr && "NULL expr in OpenMP shared clause.");
20059 SourceLocation ELoc;
20060 SourceRange ERange;
20061 Expr *SimpleRefExpr = RefExpr;
20062 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
20063 if (Res.second) {
20064 // It will be analyzed later.
20065 Vars.push_back(Elt: RefExpr);
20066 }
20067 ValueDecl *D = Res.first;
20068 if (!D)
20069 continue;
20070
20071 auto *VD = dyn_cast<VarDecl>(Val: D);
20072 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
20073 // in a Construct]
20074 // Variables with the predetermined data-sharing attributes may not be
20075 // listed in data-sharing attributes clauses, except for the cases
20076 // listed below. For these exceptions only, listing a predetermined
20077 // variable in a data-sharing attribute clause is allowed and overrides
20078 // the variable's predetermined data-sharing attributes.
20079 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20080 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
20081 DVar.RefExpr) {
20082 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
20083 << getOpenMPClauseNameForDiag(C: DVar.CKind)
20084 << getOpenMPClauseNameForDiag(C: OMPC_shared);
20085 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20086 continue;
20087 }
20088
20089 DeclRefExpr *Ref = nullptr;
20090 if (!VD && isOpenMPCapturedDecl(D) &&
20091 !SemaRef.CurContext->isDependentContext())
20092 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
20093 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_shared, PrivateCopy: Ref);
20094 Vars.push_back(Elt: (VD || !Ref || SemaRef.CurContext->isDependentContext())
20095 ? RefExpr->IgnoreParens()
20096 : Ref);
20097 }
20098
20099 if (Vars.empty())
20100 return nullptr;
20101
20102 return OMPSharedClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
20103 VL: Vars);
20104}
20105
20106namespace {
20107class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
20108 DSAStackTy *Stack;
20109
20110public:
20111 bool VisitDeclRefExpr(DeclRefExpr *E) {
20112 if (auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
20113 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D: VD, /*FromParent=*/false);
20114 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
20115 return false;
20116 if (DVar.CKind != OMPC_unknown)
20117 return true;
20118 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
20119 D: VD,
20120 CPred: [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
20121 return isOpenMPPrivate(Kind: C) && !AppliedToPointee;
20122 },
20123 DPred: [](OpenMPDirectiveKind) { return true; },
20124 /*FromParent=*/true);
20125 return DVarPrivate.CKind != OMPC_unknown;
20126 }
20127 return false;
20128 }
20129 bool VisitStmt(Stmt *S) {
20130 for (Stmt *Child : S->children()) {
20131 if (Child && Visit(S: Child))
20132 return true;
20133 }
20134 return false;
20135 }
20136 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
20137};
20138} // namespace
20139
20140namespace {
20141// Transform MemberExpression for specified FieldDecl of current class to
20142// DeclRefExpr to specified OMPCapturedExprDecl.
20143class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
20144 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
20145 ValueDecl *Field = nullptr;
20146 DeclRefExpr *CapturedExpr = nullptr;
20147
20148public:
20149 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
20150 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
20151
20152 ExprResult TransformMemberExpr(MemberExpr *E) {
20153 if (isa<CXXThisExpr>(Val: E->getBase()->IgnoreParenImpCasts()) &&
20154 E->getMemberDecl() == Field) {
20155 CapturedExpr = buildCapture(S&: SemaRef, D: Field, CaptureExpr: E, /*WithInit=*/false);
20156 return CapturedExpr;
20157 }
20158 return BaseTransform::TransformMemberExpr(E);
20159 }
20160 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
20161};
20162} // namespace
20163
20164template <typename T, typename U>
20165static T filterLookupForUDReductionAndMapper(
20166 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
20167 for (U &Set : Lookups) {
20168 for (auto *D : Set) {
20169 if (T Res = Gen(cast<ValueDecl>(D)))
20170 return Res;
20171 }
20172 }
20173 return T();
20174}
20175
20176static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
20177 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
20178
20179 for (auto *RD : D->redecls()) {
20180 // Don't bother with extra checks if we already know this one isn't visible.
20181 if (RD == D)
20182 continue;
20183
20184 auto ND = cast<NamedDecl>(Val: RD);
20185 if (LookupResult::isVisible(SemaRef, D: ND))
20186 return ND;
20187 }
20188
20189 return nullptr;
20190}
20191
20192static void
20193argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
20194 SourceLocation Loc, QualType Ty,
20195 SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
20196 // Find all of the associated namespaces and classes based on the
20197 // arguments we have.
20198 Sema::AssociatedNamespaceSet AssociatedNamespaces;
20199 Sema::AssociatedClassSet AssociatedClasses;
20200 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
20201 SemaRef.FindAssociatedClassesAndNamespaces(InstantiationLoc: Loc, Args: &OVE, AssociatedNamespaces,
20202 AssociatedClasses);
20203
20204 // C++ [basic.lookup.argdep]p3:
20205 // Let X be the lookup set produced by unqualified lookup (3.4.1)
20206 // and let Y be the lookup set produced by argument dependent
20207 // lookup (defined as follows). If X contains [...] then Y is
20208 // empty. Otherwise Y is the set of declarations found in the
20209 // namespaces associated with the argument types as described
20210 // below. The set of declarations found by the lookup of the name
20211 // is the union of X and Y.
20212 //
20213 // Here, we compute Y and add its members to the overloaded
20214 // candidate set.
20215 for (auto *NS : AssociatedNamespaces) {
20216 // When considering an associated namespace, the lookup is the
20217 // same as the lookup performed when the associated namespace is
20218 // used as a qualifier (3.4.3.2) except that:
20219 //
20220 // -- Any using-directives in the associated namespace are
20221 // ignored.
20222 //
20223 // -- Any namespace-scope friend functions declared in
20224 // associated classes are visible within their respective
20225 // namespaces even if they are not visible during an ordinary
20226 // lookup (11.4).
20227 DeclContext::lookup_result R = NS->lookup(Name: Id.getName());
20228 for (auto *D : R) {
20229 auto *Underlying = D;
20230 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
20231 Underlying = USD->getTargetDecl();
20232
20233 if (!isa<OMPDeclareReductionDecl>(Val: Underlying) &&
20234 !isa<OMPDeclareMapperDecl>(Val: Underlying))
20235 continue;
20236
20237 if (!SemaRef.isVisible(D)) {
20238 D = findAcceptableDecl(SemaRef, D);
20239 if (!D)
20240 continue;
20241 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
20242 Underlying = USD->getTargetDecl();
20243 }
20244 Lookups.emplace_back();
20245 Lookups.back().addDecl(D: Underlying);
20246 }
20247 }
20248}
20249
20250static ExprResult
20251buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
20252 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
20253 const DeclarationNameInfo &ReductionId, QualType Ty,
20254 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
20255 if (ReductionIdScopeSpec.isInvalid())
20256 return ExprError();
20257 SmallVector<UnresolvedSet<8>, 4> Lookups;
20258 if (S) {
20259 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
20260 Lookup.suppressDiagnostics();
20261 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &ReductionIdScopeSpec,
20262 /*ObjectType=*/QualType())) {
20263 NamedDecl *D = Lookup.getRepresentativeDecl();
20264 do {
20265 S = S->getParent();
20266 } while (S && !S->isDeclScope(D));
20267 if (S)
20268 S = S->getParent();
20269 Lookups.emplace_back();
20270 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
20271 Lookup.clear();
20272 }
20273 } else if (auto *ULE =
20274 cast_or_null<UnresolvedLookupExpr>(Val: UnresolvedReduction)) {
20275 Lookups.push_back(Elt: UnresolvedSet<8>());
20276 Decl *PrevD = nullptr;
20277 for (NamedDecl *D : ULE->decls()) {
20278 if (D == PrevD)
20279 Lookups.push_back(Elt: UnresolvedSet<8>());
20280 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Val: D))
20281 Lookups.back().addDecl(D: DRD);
20282 PrevD = D;
20283 }
20284 }
20285 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
20286 Ty->isInstantiationDependentType() ||
20287 Ty->containsUnexpandedParameterPack() ||
20288 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
20289 return !D->isInvalidDecl() &&
20290 (D->getType()->isDependentType() ||
20291 D->getType()->isInstantiationDependentType() ||
20292 D->getType()->containsUnexpandedParameterPack());
20293 })) {
20294 UnresolvedSet<8> ResSet;
20295 for (const UnresolvedSet<8> &Set : Lookups) {
20296 if (Set.empty())
20297 continue;
20298 ResSet.append(I: Set.begin(), E: Set.end());
20299 // The last item marks the end of all declarations at the specified scope.
20300 ResSet.addDecl(D: Set[Set.size() - 1]);
20301 }
20302 return UnresolvedLookupExpr::Create(
20303 Context: SemaRef.Context, /*NamingClass=*/nullptr,
20304 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: SemaRef.Context), NameInfo: ReductionId,
20305 /*ADL=*/RequiresADL: true, Begin: ResSet.begin(), End: ResSet.end(), /*KnownDependent=*/false,
20306 /*KnownInstantiationDependent=*/false);
20307 }
20308 // Lookup inside the classes.
20309 // C++ [over.match.oper]p3:
20310 // For a unary operator @ with an operand of a type whose
20311 // cv-unqualified version is T1, and for a binary operator @ with
20312 // a left operand of a type whose cv-unqualified version is T1 and
20313 // a right operand of a type whose cv-unqualified version is T2,
20314 // three sets of candidate functions, designated member
20315 // candidates, non-member candidates and built-in candidates, are
20316 // constructed as follows:
20317 // -- If T1 is a complete class type or a class currently being
20318 // defined, the set of member candidates is the result of the
20319 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
20320 // the set of member candidates is empty.
20321 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
20322 Lookup.suppressDiagnostics();
20323 if (Ty->isRecordType()) {
20324 // Complete the type if it can be completed.
20325 // If the type is neither complete nor being defined, bail out now.
20326 bool IsComplete = SemaRef.isCompleteType(Loc, T: Ty);
20327 auto *RD = Ty->castAsRecordDecl();
20328 if (IsComplete || RD->isBeingDefined()) {
20329 Lookup.clear();
20330 SemaRef.LookupQualifiedName(R&: Lookup, LookupCtx: RD);
20331 if (Lookup.empty()) {
20332 Lookups.emplace_back();
20333 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
20334 }
20335 }
20336 }
20337 // Perform ADL.
20338 if (SemaRef.getLangOpts().CPlusPlus)
20339 argumentDependentLookup(SemaRef, Id: ReductionId, Loc, Ty, Lookups);
20340 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20341 Lookups, Gen: [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
20342 if (!D->isInvalidDecl() &&
20343 SemaRef.Context.hasSameType(T1: D->getType(), T2: Ty))
20344 return D;
20345 return nullptr;
20346 }))
20347 return SemaRef.BuildDeclRefExpr(D: VD, Ty: VD->getType().getNonReferenceType(),
20348 VK: VK_LValue, Loc);
20349 if (SemaRef.getLangOpts().CPlusPlus) {
20350 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20351 Lookups, Gen: [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
20352 if (!D->isInvalidDecl() &&
20353 SemaRef.IsDerivedFrom(Loc, Derived: Ty, Base: D->getType()) &&
20354 !Ty.isMoreQualifiedThan(other: D->getType(),
20355 Ctx: SemaRef.getASTContext()))
20356 return D;
20357 return nullptr;
20358 })) {
20359 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
20360 /*DetectVirtual=*/false);
20361 if (SemaRef.IsDerivedFrom(Loc, Derived: Ty, Base: VD->getType(), Paths)) {
20362 if (!Paths.isAmbiguous(BaseType: SemaRef.Context.getCanonicalType(
20363 T: VD->getType().getUnqualifiedType()))) {
20364 if (SemaRef.CheckBaseClassAccess(
20365 AccessLoc: Loc, Base: VD->getType(), Derived: Ty, Path: Paths.front(),
20366 /*DiagID=*/0) != Sema::AR_inaccessible) {
20367 SemaRef.BuildBasePathArray(Paths, BasePath);
20368 return SemaRef.BuildDeclRefExpr(
20369 D: VD, Ty: VD->getType().getNonReferenceType(), VK: VK_LValue, Loc);
20370 }
20371 }
20372 }
20373 }
20374 }
20375 if (ReductionIdScopeSpec.isSet()) {
20376 SemaRef.Diag(Loc, DiagID: diag::err_omp_not_resolved_reduction_identifier)
20377 << Ty << Range;
20378 return ExprError();
20379 }
20380 return ExprEmpty();
20381}
20382
20383namespace {
20384/// Data for the reduction-based clauses.
20385struct ReductionData {
20386 /// List of original reduction items.
20387 SmallVector<Expr *, 8> Vars;
20388 /// List of private copies of the reduction items.
20389 SmallVector<Expr *, 8> Privates;
20390 /// LHS expressions for the reduction_op expressions.
20391 SmallVector<Expr *, 8> LHSs;
20392 /// RHS expressions for the reduction_op expressions.
20393 SmallVector<Expr *, 8> RHSs;
20394 /// Reduction operation expression.
20395 SmallVector<Expr *, 8> ReductionOps;
20396 /// inscan copy operation expressions.
20397 SmallVector<Expr *, 8> InscanCopyOps;
20398 /// inscan copy temp array expressions for prefix sums.
20399 SmallVector<Expr *, 8> InscanCopyArrayTemps;
20400 /// inscan copy temp array element expressions for prefix sums.
20401 SmallVector<Expr *, 8> InscanCopyArrayElems;
20402 /// Taskgroup descriptors for the corresponding reduction items in
20403 /// in_reduction clauses.
20404 SmallVector<Expr *, 8> TaskgroupDescriptors;
20405 /// List of captures for clause.
20406 SmallVector<Decl *, 4> ExprCaptures;
20407 /// List of postupdate expressions.
20408 SmallVector<Expr *, 4> ExprPostUpdates;
20409 /// Reduction modifier.
20410 unsigned RedModifier = 0;
20411 /// Original modifier.
20412 unsigned OrigSharingModifier = 0;
20413 /// Private Variable Reduction
20414 SmallVector<bool, 8> IsPrivateVarReduction;
20415 ReductionData() = delete;
20416 /// Reserves required memory for the reduction data.
20417 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
20418 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
20419 Vars.reserve(N: Size);
20420 Privates.reserve(N: Size);
20421 LHSs.reserve(N: Size);
20422 RHSs.reserve(N: Size);
20423 ReductionOps.reserve(N: Size);
20424 IsPrivateVarReduction.reserve(N: Size);
20425 if (RedModifier == OMPC_REDUCTION_inscan) {
20426 InscanCopyOps.reserve(N: Size);
20427 InscanCopyArrayTemps.reserve(N: Size);
20428 InscanCopyArrayElems.reserve(N: Size);
20429 }
20430 TaskgroupDescriptors.reserve(N: Size);
20431 ExprCaptures.reserve(N: Size);
20432 ExprPostUpdates.reserve(N: Size);
20433 }
20434 /// Stores reduction item and reduction operation only (required for dependent
20435 /// reduction item).
20436 void push(Expr *Item, Expr *ReductionOp) {
20437 Vars.emplace_back(Args&: Item);
20438 Privates.emplace_back(Args: nullptr);
20439 LHSs.emplace_back(Args: nullptr);
20440 RHSs.emplace_back(Args: nullptr);
20441 ReductionOps.emplace_back(Args&: ReductionOp);
20442 IsPrivateVarReduction.emplace_back(Args: false);
20443 TaskgroupDescriptors.emplace_back(Args: nullptr);
20444 if (RedModifier == OMPC_REDUCTION_inscan) {
20445 InscanCopyOps.push_back(Elt: nullptr);
20446 InscanCopyArrayTemps.push_back(Elt: nullptr);
20447 InscanCopyArrayElems.push_back(Elt: nullptr);
20448 }
20449 }
20450 /// Stores reduction data.
20451 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
20452 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
20453 Expr *CopyArrayElem, bool IsPrivate) {
20454 Vars.emplace_back(Args&: Item);
20455 Privates.emplace_back(Args&: Private);
20456 LHSs.emplace_back(Args&: LHS);
20457 RHSs.emplace_back(Args&: RHS);
20458 ReductionOps.emplace_back(Args&: ReductionOp);
20459 TaskgroupDescriptors.emplace_back(Args&: TaskgroupDescriptor);
20460 if (RedModifier == OMPC_REDUCTION_inscan) {
20461 InscanCopyOps.push_back(Elt: CopyOp);
20462 InscanCopyArrayTemps.push_back(Elt: CopyArrayTemp);
20463 InscanCopyArrayElems.push_back(Elt: CopyArrayElem);
20464 } else {
20465 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
20466 CopyArrayElem == nullptr &&
20467 "Copy operation must be used for inscan reductions only.");
20468 }
20469 IsPrivateVarReduction.emplace_back(Args&: IsPrivate);
20470 }
20471};
20472} // namespace
20473
20474static bool checkOMPArraySectionConstantForReduction(
20475 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
20476 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
20477 const Expr *Length = OASE->getLength();
20478 if (Length == nullptr) {
20479 // For array sections of the form [1:] or [:], we would need to analyze
20480 // the lower bound...
20481 if (OASE->getColonLocFirst().isValid())
20482 return false;
20483
20484 // This is an array subscript which has implicit length 1!
20485 SingleElement = true;
20486 ArraySizes.push_back(Elt: llvm::APSInt::get(X: 1));
20487 } else {
20488 Expr::EvalResult Result;
20489 if (!Length->EvaluateAsInt(Result, Ctx: Context))
20490 return false;
20491
20492 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
20493 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
20494 ArraySizes.push_back(Elt: ConstantLengthValue);
20495 }
20496
20497 // Get the base of this array section and walk up from there.
20498 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
20499
20500 // We require length = 1 for all array sections except the right-most to
20501 // guarantee that the memory region is contiguous and has no holes in it.
20502 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Val: Base)) {
20503 Length = TempOASE->getLength();
20504 if (Length == nullptr) {
20505 // For array sections of the form [1:] or [:], we would need to analyze
20506 // the lower bound...
20507 if (OASE->getColonLocFirst().isValid())
20508 return false;
20509
20510 // This is an array subscript which has implicit length 1!
20511 llvm::APSInt ConstantOne = llvm::APSInt::get(X: 1);
20512 ArraySizes.push_back(Elt: ConstantOne);
20513 } else {
20514 Expr::EvalResult Result;
20515 if (!Length->EvaluateAsInt(Result, Ctx: Context))
20516 return false;
20517
20518 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
20519 if (ConstantLengthValue.getSExtValue() != 1)
20520 return false;
20521
20522 ArraySizes.push_back(Elt: ConstantLengthValue);
20523 }
20524 Base = TempOASE->getBase()->IgnoreParenImpCasts();
20525 }
20526
20527 // If we have a single element, we don't need to add the implicit lengths.
20528 if (!SingleElement) {
20529 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base)) {
20530 // Has implicit length 1!
20531 llvm::APSInt ConstantOne = llvm::APSInt::get(X: 1);
20532 ArraySizes.push_back(Elt: ConstantOne);
20533 Base = TempASE->getBase()->IgnoreParenImpCasts();
20534 }
20535 }
20536
20537 // This array section can be privatized as a single value or as a constant
20538 // sized array.
20539 return true;
20540}
20541
20542static BinaryOperatorKind
20543getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
20544 if (BOK == BO_Add)
20545 return BO_AddAssign;
20546 if (BOK == BO_Mul)
20547 return BO_MulAssign;
20548 if (BOK == BO_And)
20549 return BO_AndAssign;
20550 if (BOK == BO_Or)
20551 return BO_OrAssign;
20552 if (BOK == BO_Xor)
20553 return BO_XorAssign;
20554 return BOK;
20555}
20556
20557static bool actOnOMPReductionKindClause(
20558 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
20559 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20560 SourceLocation ColonLoc, SourceLocation EndLoc,
20561 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20562 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
20563 DeclarationName DN = ReductionId.getName();
20564 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
20565 BinaryOperatorKind BOK = BO_Comma;
20566
20567 ASTContext &Context = S.Context;
20568 // OpenMP [2.14.3.6, reduction clause]
20569 // C
20570 // reduction-identifier is either an identifier or one of the following
20571 // operators: +, -, *, &, |, ^, && and ||
20572 // C++
20573 // reduction-identifier is either an id-expression or one of the following
20574 // operators: +, -, *, &, |, ^, && and ||
20575 switch (OOK) {
20576 case OO_Plus:
20577 BOK = BO_Add;
20578 break;
20579 case OO_Minus:
20580 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
20581 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
20582 // reduction identifier.
20583 if (S.LangOpts.OpenMP > 52)
20584 BOK = BO_Comma;
20585 else
20586 BOK = BO_Add;
20587 break;
20588 case OO_Star:
20589 BOK = BO_Mul;
20590 break;
20591 case OO_Amp:
20592 BOK = BO_And;
20593 break;
20594 case OO_Pipe:
20595 BOK = BO_Or;
20596 break;
20597 case OO_Caret:
20598 BOK = BO_Xor;
20599 break;
20600 case OO_AmpAmp:
20601 BOK = BO_LAnd;
20602 break;
20603 case OO_PipePipe:
20604 BOK = BO_LOr;
20605 break;
20606 case OO_New:
20607 case OO_Delete:
20608 case OO_Array_New:
20609 case OO_Array_Delete:
20610 case OO_Slash:
20611 case OO_Percent:
20612 case OO_Tilde:
20613 case OO_Exclaim:
20614 case OO_Equal:
20615 case OO_Less:
20616 case OO_Greater:
20617 case OO_LessEqual:
20618 case OO_GreaterEqual:
20619 case OO_PlusEqual:
20620 case OO_MinusEqual:
20621 case OO_StarEqual:
20622 case OO_SlashEqual:
20623 case OO_PercentEqual:
20624 case OO_CaretEqual:
20625 case OO_AmpEqual:
20626 case OO_PipeEqual:
20627 case OO_LessLess:
20628 case OO_GreaterGreater:
20629 case OO_LessLessEqual:
20630 case OO_GreaterGreaterEqual:
20631 case OO_EqualEqual:
20632 case OO_ExclaimEqual:
20633 case OO_Spaceship:
20634 case OO_PlusPlus:
20635 case OO_MinusMinus:
20636 case OO_Comma:
20637 case OO_ArrowStar:
20638 case OO_Arrow:
20639 case OO_Call:
20640 case OO_Subscript:
20641 case OO_Conditional:
20642 case OO_Coawait:
20643 case NUM_OVERLOADED_OPERATORS:
20644 llvm_unreachable("Unexpected reduction identifier");
20645 case OO_None:
20646 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
20647 if (II->isStr(Str: "max"))
20648 BOK = BO_GT;
20649 else if (II->isStr(Str: "min"))
20650 BOK = BO_LT;
20651 }
20652 break;
20653 }
20654
20655 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
20656 // A reduction clause with the minus (-) operator was deprecated
20657 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
20658 S.Diag(Loc: ReductionId.getLoc(), DiagID: diag::warn_omp_minus_in_reduction_deprecated);
20659
20660 SourceRange ReductionIdRange;
20661 if (ReductionIdScopeSpec.isValid())
20662 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
20663 else
20664 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
20665 ReductionIdRange.setEnd(ReductionId.getEndLoc());
20666
20667 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
20668 bool FirstIter = true;
20669 for (Expr *RefExpr : VarList) {
20670 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
20671 // OpenMP [2.1, C/C++]
20672 // A list item is a variable or array section, subject to the restrictions
20673 // specified in Section 2.4 on page 42 and in each of the sections
20674 // describing clauses and directives for which a list appears.
20675 // OpenMP [2.14.3.3, Restrictions, p.1]
20676 // A variable that is part of another variable (as an array or
20677 // structure element) cannot appear in a private clause.
20678 if (!FirstIter && IR != ER)
20679 ++IR;
20680 FirstIter = false;
20681 SourceLocation ELoc;
20682 SourceRange ERange;
20683 bool IsPrivate = false;
20684 Expr *SimpleRefExpr = RefExpr;
20685 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
20686 /*AllowArraySection=*/true);
20687 if (Res.second) {
20688 // Try to find 'declare reduction' corresponding construct before using
20689 // builtin/overloaded operators.
20690 QualType Type = Context.DependentTy;
20691 CXXCastPath BasePath;
20692 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20693 SemaRef&: S, Loc: ELoc, Range: ERange, S: Stack->getCurScope(), ReductionIdScopeSpec,
20694 ReductionId, Ty: Type, BasePath, UnresolvedReduction: IR == ER ? nullptr : *IR);
20695 Expr *ReductionOp = nullptr;
20696 if (S.CurContext->isDependentContext() &&
20697 (DeclareReductionRef.isUnset() ||
20698 isa<UnresolvedLookupExpr>(Val: DeclareReductionRef.get())))
20699 ReductionOp = DeclareReductionRef.get();
20700 // It will be analyzed later.
20701 RD.push(Item: RefExpr, ReductionOp);
20702 }
20703 ValueDecl *D = Res.first;
20704 if (!D)
20705 continue;
20706
20707 Expr *TaskgroupDescriptor = nullptr;
20708 QualType Type;
20709 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: RefExpr->IgnoreParens());
20710 auto *OASE = dyn_cast<ArraySectionExpr>(Val: RefExpr->IgnoreParens());
20711 if (ASE) {
20712 Type = ASE->getType().getNonReferenceType();
20713 } else if (OASE) {
20714 QualType BaseType =
20715 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
20716 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20717 Type = ATy->getElementType();
20718 else
20719 Type = BaseType->getPointeeType();
20720 Type = Type.getNonReferenceType();
20721 } else {
20722 Type = Context.getBaseElementType(QT: D->getType().getNonReferenceType());
20723 }
20724 auto *VD = dyn_cast<VarDecl>(Val: D);
20725
20726 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
20727 // A variable that appears in a private clause must not have an incomplete
20728 // type or a reference type.
20729 if (S.RequireCompleteType(Loc: ELoc, T: D->getType(),
20730 DiagID: diag::err_omp_reduction_incomplete_type))
20731 continue;
20732 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20733 // A list item that appears in a reduction clause must not be
20734 // const-qualified.
20735 if (rejectConstNotMutableType(SemaRef&: S, D, Type, CKind: ClauseKind, ELoc,
20736 /*AcceptIfMutable=*/false, ListItemNotVar: ASE || OASE))
20737 continue;
20738
20739 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
20740 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
20741 // If a list-item is a reference type then it must bind to the same object
20742 // for all threads of the team.
20743 if (!ASE && !OASE) {
20744 if (VD) {
20745 VarDecl *VDDef = VD->getDefinition();
20746 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
20747 DSARefChecker Check(Stack);
20748 if (Check.Visit(S: VDDef->getInit())) {
20749 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_ref_type_arg)
20750 << getOpenMPClauseNameForDiag(C: ClauseKind) << ERange;
20751 S.Diag(Loc: VDDef->getLocation(), DiagID: diag::note_defined_here) << VDDef;
20752 continue;
20753 }
20754 }
20755 }
20756
20757 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
20758 // in a Construct]
20759 // Variables with the predetermined data-sharing attributes may not be
20760 // listed in data-sharing attributes clauses, except for the cases
20761 // listed below. For these exceptions only, listing a predetermined
20762 // variable in a data-sharing attribute clause is allowed and overrides
20763 // the variable's predetermined data-sharing attributes.
20764 // OpenMP [2.14.3.6, Restrictions, p.3]
20765 // Any number of reduction clauses can be specified on the directive,
20766 // but a list item can appear only once in the reduction clauses for that
20767 // directive.
20768 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20769 if (DVar.CKind == OMPC_reduction) {
20770 S.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced)
20771 << getOpenMPClauseNameForDiag(C: ClauseKind);
20772 if (DVar.RefExpr)
20773 S.Diag(Loc: DVar.RefExpr->getExprLoc(), DiagID: diag::note_omp_referenced);
20774 continue;
20775 }
20776 if (DVar.CKind != OMPC_unknown) {
20777 S.Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
20778 << getOpenMPClauseNameForDiag(C: DVar.CKind)
20779 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
20780 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
20781 continue;
20782 }
20783
20784 // OpenMP [2.14.3.6, Restrictions, p.1]
20785 // A list item that appears in a reduction clause of a worksharing
20786 // construct must be shared in the parallel regions to which any of the
20787 // worksharing regions arising from the worksharing construct bind.
20788
20789 if (S.getLangOpts().OpenMP <= 52 &&
20790 isOpenMPWorksharingDirective(DKind: CurrDir) &&
20791 !isOpenMPParallelDirective(DKind: CurrDir) &&
20792 !isOpenMPTeamsDirective(DKind: CurrDir)) {
20793 DVar = Stack->getImplicitDSA(D, FromParent: true);
20794 if (DVar.CKind != OMPC_shared) {
20795 S.Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
20796 << getOpenMPClauseNameForDiag(C: OMPC_reduction)
20797 << getOpenMPClauseNameForDiag(C: OMPC_shared);
20798 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
20799 continue;
20800 }
20801 } else if (isOpenMPWorksharingDirective(DKind: CurrDir) &&
20802 !isOpenMPParallelDirective(DKind: CurrDir) &&
20803 !isOpenMPTeamsDirective(DKind: CurrDir)) {
20804 // OpenMP 6.0 [ 7.6.10 ]
20805 // Support Reduction over private variables with reduction clause.
20806 // A list item in a reduction clause can now be private in the enclosing
20807 // context. For orphaned constructs it is assumed to be shared unless
20808 // the original(private) modifier appears in the clause.
20809 DVar = Stack->getImplicitDSA(D, FromParent: true);
20810 // Determine if the variable should be considered private
20811 IsPrivate = DVar.CKind != OMPC_shared;
20812 bool IsOrphaned = false;
20813 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
20814 IsOrphaned = ParentDir == OMPD_unknown;
20815 if ((IsOrphaned &&
20816 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
20817 IsPrivate = true;
20818 }
20819 } else {
20820 // Threadprivates cannot be shared between threads, so dignose if the base
20821 // is a threadprivate variable.
20822 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20823 if (DVar.CKind == OMPC_threadprivate) {
20824 S.Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
20825 << getOpenMPClauseNameForDiag(C: DVar.CKind)
20826 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
20827 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
20828 continue;
20829 }
20830 }
20831
20832 // Try to find 'declare reduction' corresponding construct before using
20833 // builtin/overloaded operators.
20834 CXXCastPath BasePath;
20835 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20836 SemaRef&: S, Loc: ELoc, Range: ERange, S: Stack->getCurScope(), ReductionIdScopeSpec,
20837 ReductionId, Ty: Type, BasePath, UnresolvedReduction: IR == ER ? nullptr : *IR);
20838 if (DeclareReductionRef.isInvalid())
20839 continue;
20840 if (S.CurContext->isDependentContext() &&
20841 (DeclareReductionRef.isUnset() ||
20842 isa<UnresolvedLookupExpr>(Val: DeclareReductionRef.get()))) {
20843 RD.push(Item: RefExpr, ReductionOp: DeclareReductionRef.get());
20844 // Handle non-dependent inscan reduction variables in dependent contexts.
20845 if (RD.RedModifier == OMPC_REDUCTION_inscan)
20846 Stack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_reduction, PrivateCopy: nullptr,
20847 Modifier: RD.RedModifier, AppliedToPointee: ASE || OASE);
20848 continue;
20849 }
20850 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
20851 // Not allowed reduction identifier is found.
20852 if (S.LangOpts.OpenMP > 52)
20853 S.Diag(Loc: ReductionId.getBeginLoc(),
20854 DiagID: diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
20855 << Type << ReductionIdRange;
20856 else
20857 S.Diag(Loc: ReductionId.getBeginLoc(),
20858 DiagID: diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
20859 << Type << ReductionIdRange;
20860 continue;
20861 }
20862
20863 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20864 // The type of a list item that appears in a reduction clause must be valid
20865 // for the reduction-identifier. For a max or min reduction in C, the type
20866 // of the list item must be an allowed arithmetic data type: char, int,
20867 // float, double, or _Bool, possibly modified with long, short, signed, or
20868 // unsigned. For a max or min reduction in C++, the type of the list item
20869 // must be an allowed arithmetic data type: char, wchar_t, int, float,
20870 // double, or bool, possibly modified with long, short, signed, or unsigned.
20871 if (DeclareReductionRef.isUnset()) {
20872 if ((BOK == BO_GT || BOK == BO_LT) &&
20873 !(Type->isScalarType() ||
20874 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
20875 S.Diag(Loc: ELoc, DiagID: diag::err_omp_clause_not_arithmetic_type_arg)
20876 << getOpenMPClauseNameForDiag(C: ClauseKind)
20877 << S.getLangOpts().CPlusPlus;
20878 if (!ASE && !OASE) {
20879 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20880 VarDecl::DeclarationOnly;
20881 S.Diag(Loc: D->getLocation(),
20882 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20883 << D;
20884 }
20885 continue;
20886 }
20887 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
20888 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
20889 S.Diag(Loc: ELoc, DiagID: diag::err_omp_clause_floating_type_arg)
20890 << getOpenMPClauseNameForDiag(C: ClauseKind);
20891 if (!ASE && !OASE) {
20892 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20893 VarDecl::DeclarationOnly;
20894 S.Diag(Loc: D->getLocation(),
20895 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20896 << D;
20897 }
20898 continue;
20899 }
20900 }
20901
20902 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
20903 VarDecl *LHSVD = buildVarDecl(SemaRef&: S, Loc: ELoc, Type, Name: ".reduction.lhs",
20904 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
20905 VarDecl *RHSVD = buildVarDecl(SemaRef&: S, Loc: ELoc, Type, Name: D->getName(),
20906 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
20907 QualType PrivateTy = Type;
20908
20909 // Try if we can determine constant lengths for all array sections and avoid
20910 // the VLA.
20911 bool ConstantLengthOASE = false;
20912 if (OASE) {
20913 bool SingleElement;
20914 llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
20915 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
20916 Context, OASE, SingleElement, ArraySizes);
20917
20918 // If we don't have a single element, we must emit a constant array type.
20919 if (ConstantLengthOASE && !SingleElement) {
20920 for (llvm::APSInt &Size : ArraySizes)
20921 PrivateTy = Context.getConstantArrayType(EltTy: PrivateTy, ArySize: Size, SizeExpr: nullptr,
20922 ASM: ArraySizeModifier::Normal,
20923 /*IndexTypeQuals=*/0);
20924 }
20925 }
20926
20927 if ((OASE && !ConstantLengthOASE) ||
20928 (!OASE && !ASE &&
20929 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
20930 if (!Context.getTargetInfo().isVLASupported()) {
20931 if (isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective())) {
20932 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_vla_unsupported) << !!OASE;
20933 S.Diag(Loc: ELoc, DiagID: diag::note_vla_unsupported);
20934 continue;
20935 } else {
20936 S.targetDiag(Loc: ELoc, DiagID: diag::err_omp_reduction_vla_unsupported) << !!OASE;
20937 S.targetDiag(Loc: ELoc, DiagID: diag::note_vla_unsupported);
20938 }
20939 }
20940 // For arrays/array sections only:
20941 // Create pseudo array type for private copy. The size for this array will
20942 // be generated during codegen.
20943 // For array subscripts or single variables Private Ty is the same as Type
20944 // (type of the variable or single array element).
20945 PrivateTy = Context.getVariableArrayType(
20946 EltTy: Type,
20947 NumElts: new (Context)
20948 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
20949 ASM: ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
20950 } else if (!ASE && !OASE &&
20951 Context.getAsArrayType(T: D->getType().getNonReferenceType())) {
20952 PrivateTy = D->getType().getNonReferenceType();
20953 }
20954 // Private copy.
20955 VarDecl *PrivateVD =
20956 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: PrivateTy, Name: D->getName(),
20957 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
20958 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
20959 // Add initializer for private variable.
20960 Expr *Init = nullptr;
20961 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, D: LHSVD, Ty: Type, Loc: ELoc);
20962 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, D: RHSVD, Ty: Type, Loc: ELoc);
20963 if (DeclareReductionRef.isUsable()) {
20964 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
20965 auto *DRD = cast<OMPDeclareReductionDecl>(Val: DRDRef->getDecl());
20966 if (DRD->getInitializer()) {
20967 Init = DRDRef;
20968 RHSVD->setInit(DRDRef);
20969 RHSVD->setInitStyle(VarDecl::CallInit);
20970 }
20971 } else {
20972 switch (BOK) {
20973 case BO_Add:
20974 case BO_Xor:
20975 case BO_Or:
20976 case BO_LOr:
20977 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
20978 if (Type->isScalarType() || Type->isAnyComplexType())
20979 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/0).get();
20980 break;
20981 case BO_Mul:
20982 // '*' reduction op - initializer is '1'.
20983 // For C++ class types (e.g. std::complex) the OpenMP built-in
20984 // reduction identifiers are an extension: the standard only defines
20985 // identities for arithmetic (and, in Clang, _Complex) types. Without
20986 // an explicit initializer the private copy would be value-initialized,
20987 // which yields the *additive* identity (e.g. std::complex(0,0)) and is
20988 // wrong for multiplication. Initialize from the integer literal '1'
20989 // instead and let the converting constructor build the multiplicative
20990 // identity (e.g. std::complex(1) == (1,0)).
20991 if (Type->isScalarType() || Type->isAnyComplexType()) {
20992 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
20993 } else if (S.getLangOpts().CPlusPlus && Type->isRecordType()) {
20994 // Only use '1' when the type is actually copy-initializable from it.
20995 // Otherwise fall back to value-initialization (the previous behavior)
20996 // rather than rejecting the reduction, so a class that used to
20997 // compile keeps compiling. Such a class keeps its (possibly
20998 // incorrect) value-initialized identity, matching the pre-existing
20999 // behavior; BO_Add likewise relies on value-initialization for class
21000 // types.
21001 Expr *One = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
21002 InitializedEntity Entity =
21003 InitializedEntity::InitializeTemporary(Type);
21004 InitializationKind Kind = InitializationKind::CreateCopy(InitLoc: ELoc, EqualLoc: ELoc);
21005 InitializationSequence Seq(S, Entity, Kind, One);
21006 if (Seq)
21007 Init = One;
21008 }
21009 break;
21010 case BO_LAnd:
21011 if (Type->isScalarType() || Type->isAnyComplexType()) {
21012 // '&&' reduction ops - initializer is '1'.
21013 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
21014 }
21015 break;
21016 case BO_And: {
21017 // '&' reduction op - initializer is '~0'.
21018 QualType OrigType = Type;
21019 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
21020 Type = ComplexTy->getElementType();
21021 if (Type->isRealFloatingType()) {
21022 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
21023 Semantics: Context.getFloatTypeSemantics(T: Type));
21024 Init = FloatingLiteral::Create(C: Context, V: InitValue, /*isexact=*/true,
21025 Type, L: ELoc);
21026 } else if (Type->isScalarType()) {
21027 uint64_t Size = Context.getTypeSize(T: Type);
21028 QualType IntTy = Context.getIntTypeForBitwidth(DestWidth: Size, /*Signed=*/0);
21029 llvm::APInt InitValue = llvm::APInt::getAllOnes(numBits: Size);
21030 Init = IntegerLiteral::Create(C: Context, V: InitValue, type: IntTy, l: ELoc);
21031 }
21032 if (Init && OrigType->isAnyComplexType()) {
21033 // Init = 0xFFFF + 0xFFFFi;
21034 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
21035 Init = S.CreateBuiltinBinOp(OpLoc: ELoc, Opc: BO_Add, LHSExpr: Init, RHSExpr: Im).get();
21036 }
21037 Type = OrigType;
21038 break;
21039 }
21040 case BO_LT:
21041 case BO_GT: {
21042 // 'min' reduction op - initializer is 'Largest representable number in
21043 // the reduction list item type'.
21044 // 'max' reduction op - initializer is 'Least representable number in
21045 // the reduction list item type'.
21046 if (Type->isIntegerType() || Type->isPointerType()) {
21047 bool IsSigned = Type->hasSignedIntegerRepresentation();
21048 uint64_t Size = Context.getTypeSize(T: Type);
21049 QualType IntTy =
21050 Context.getIntTypeForBitwidth(DestWidth: Size, /*Signed=*/IsSigned);
21051 llvm::APInt InitValue =
21052 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(numBits: Size)
21053 : llvm::APInt::getMinValue(numBits: Size)
21054 : IsSigned ? llvm::APInt::getSignedMaxValue(numBits: Size)
21055 : llvm::APInt::getMaxValue(numBits: Size);
21056 Init = IntegerLiteral::Create(C: Context, V: InitValue, type: IntTy, l: ELoc);
21057 if (Type->isPointerType()) {
21058 // Cast to pointer type.
21059 ExprResult CastExpr = S.BuildCStyleCastExpr(
21060 LParenLoc: ELoc, Ty: Context.getTrivialTypeSourceInfo(T: Type, Loc: ELoc), RParenLoc: ELoc, Op: Init);
21061 if (CastExpr.isInvalid())
21062 continue;
21063 Init = CastExpr.get();
21064 }
21065 } else if (Type->isRealFloatingType()) {
21066 llvm::APFloat InitValue = llvm::APFloat::getLargest(
21067 Sem: Context.getFloatTypeSemantics(T: Type), Negative: BOK != BO_LT);
21068 Init = FloatingLiteral::Create(C: Context, V: InitValue, /*isexact=*/true,
21069 Type, L: ELoc);
21070 }
21071 break;
21072 }
21073 case BO_PtrMemD:
21074 case BO_PtrMemI:
21075 case BO_MulAssign:
21076 case BO_Div:
21077 case BO_Rem:
21078 case BO_Sub:
21079 case BO_Shl:
21080 case BO_Shr:
21081 case BO_LE:
21082 case BO_GE:
21083 case BO_EQ:
21084 case BO_NE:
21085 case BO_Cmp:
21086 case BO_AndAssign:
21087 case BO_XorAssign:
21088 case BO_OrAssign:
21089 case BO_Assign:
21090 case BO_AddAssign:
21091 case BO_SubAssign:
21092 case BO_DivAssign:
21093 case BO_RemAssign:
21094 case BO_ShlAssign:
21095 case BO_ShrAssign:
21096 case BO_Comma:
21097 llvm_unreachable("Unexpected reduction operation");
21098 }
21099 }
21100 if (Init && DeclareReductionRef.isUnset()) {
21101 S.AddInitializerToDecl(dcl: RHSVD, init: Init, /*DirectInit=*/false);
21102 // Store initializer for single element in private copy. Will be used
21103 // during codegen.
21104 PrivateVD->setInit(RHSVD->getInit());
21105 PrivateVD->setInitStyle(RHSVD->getInitStyle());
21106 } else if (!Init) {
21107 S.ActOnUninitializedDecl(dcl: RHSVD);
21108 // Store initializer for single element in private copy. Will be used
21109 // during codegen.
21110 PrivateVD->setInit(RHSVD->getInit());
21111 PrivateVD->setInitStyle(RHSVD->getInitStyle());
21112 }
21113 if (RHSVD->isInvalidDecl())
21114 continue;
21115 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
21116 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_id_not_compatible)
21117 << Type << ReductionIdRange;
21118 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
21119 VarDecl::DeclarationOnly;
21120 S.Diag(Loc: D->getLocation(),
21121 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21122 << D;
21123 continue;
21124 }
21125 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, D: PrivateVD, Ty: PrivateTy, Loc: ELoc);
21126 ExprResult ReductionOp;
21127 if (DeclareReductionRef.isUsable()) {
21128 QualType RedTy = DeclareReductionRef.get()->getType();
21129 QualType PtrRedTy = Context.getPointerType(T: RedTy);
21130 ExprResult LHS = S.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: LHSDRE);
21131 ExprResult RHS = S.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: RHSDRE);
21132 if (!BasePath.empty()) {
21133 LHS = S.DefaultLvalueConversion(E: LHS.get());
21134 RHS = S.DefaultLvalueConversion(E: RHS.get());
21135 LHS = ImplicitCastExpr::Create(
21136 Context, T: PtrRedTy, Kind: CK_UncheckedDerivedToBase, Operand: LHS.get(), BasePath: &BasePath,
21137 Cat: LHS.get()->getValueKind(), FPO: FPOptionsOverride());
21138 RHS = ImplicitCastExpr::Create(
21139 Context, T: PtrRedTy, Kind: CK_UncheckedDerivedToBase, Operand: RHS.get(), BasePath: &BasePath,
21140 Cat: RHS.get()->getValueKind(), FPO: FPOptionsOverride());
21141 }
21142 FunctionProtoType::ExtProtoInfo EPI;
21143 QualType Params[] = {PtrRedTy, PtrRedTy};
21144 QualType FnTy = Context.getFunctionType(ResultTy: Context.VoidTy, Args: Params, EPI);
21145 auto *OVE = new (Context) OpaqueValueExpr(
21146 ELoc, Context.getPointerType(T: FnTy), VK_PRValue, OK_Ordinary,
21147 S.DefaultLvalueConversion(E: DeclareReductionRef.get()).get());
21148 Expr *Args[] = {LHS.get(), RHS.get()};
21149 ReductionOp =
21150 CallExpr::Create(Ctx: Context, Fn: OVE, Args, Ty: Context.VoidTy, VK: VK_PRValue, RParenLoc: ELoc,
21151 FPFeatures: S.CurFPFeatureOverrides());
21152 } else {
21153 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
21154 if (Type->isRecordType() && CombBOK != BOK) {
21155 Sema::TentativeAnalysisScope Trap(S);
21156 ReductionOp =
21157 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
21158 Opc: CombBOK, LHSExpr: LHSDRE, RHSExpr: RHSDRE);
21159 }
21160 if (!ReductionOp.isUsable()) {
21161 ReductionOp =
21162 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(), Opc: BOK,
21163 LHSExpr: LHSDRE, RHSExpr: RHSDRE);
21164 if (ReductionOp.isUsable()) {
21165 if (BOK != BO_LT && BOK != BO_GT) {
21166 ReductionOp =
21167 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
21168 Opc: BO_Assign, LHSExpr: LHSDRE, RHSExpr: ReductionOp.get());
21169 } else {
21170 auto *ConditionalOp = new (Context)
21171 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
21172 RHSDRE, Type, VK_LValue, OK_Ordinary);
21173 ReductionOp =
21174 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
21175 Opc: BO_Assign, LHSExpr: LHSDRE, RHSExpr: ConditionalOp);
21176 }
21177 }
21178 }
21179 if (ReductionOp.isUsable())
21180 ReductionOp = S.ActOnFinishFullExpr(Expr: ReductionOp.get(),
21181 /*DiscardedValue=*/false);
21182 if (!ReductionOp.isUsable())
21183 continue;
21184 }
21185
21186 // Add copy operations for inscan reductions.
21187 // LHS = RHS;
21188 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
21189 if (ClauseKind == OMPC_reduction &&
21190 RD.RedModifier == OMPC_REDUCTION_inscan) {
21191 ExprResult RHS = S.DefaultLvalueConversion(E: RHSDRE);
21192 CopyOpRes = S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: LHSDRE,
21193 RHSExpr: RHS.get());
21194 if (!CopyOpRes.isUsable())
21195 continue;
21196 CopyOpRes =
21197 S.ActOnFinishFullExpr(Expr: CopyOpRes.get(), /*DiscardedValue=*/true);
21198 if (!CopyOpRes.isUsable())
21199 continue;
21200 // For simd directive and simd-based directives in simd mode no need to
21201 // construct temp array, need just a single temp element.
21202 if (Stack->getCurrentDirective() == OMPD_simd ||
21203 (S.getLangOpts().OpenMPSimd &&
21204 isOpenMPSimdDirective(DKind: Stack->getCurrentDirective()))) {
21205 VarDecl *TempArrayVD =
21206 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: PrivateTy, Name: D->getName(),
21207 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
21208 // Add a constructor to the temp decl.
21209 S.ActOnUninitializedDecl(dcl: TempArrayVD);
21210 TempArrayRes = buildDeclRefExpr(S, D: TempArrayVD, Ty: PrivateTy, Loc: ELoc);
21211 } else {
21212 // Build temp array for prefix sum.
21213 auto *Dim = new (S.Context)
21214 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
21215 QualType ArrayTy = S.Context.getVariableArrayType(
21216 EltTy: PrivateTy, NumElts: Dim, ASM: ArraySizeModifier::Normal,
21217 /*IndexTypeQuals=*/0);
21218 VarDecl *TempArrayVD =
21219 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: ArrayTy, Name: D->getName(),
21220 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
21221 // Add a constructor to the temp decl.
21222 S.ActOnUninitializedDecl(dcl: TempArrayVD);
21223 TempArrayRes = buildDeclRefExpr(S, D: TempArrayVD, Ty: ArrayTy, Loc: ELoc);
21224 TempArrayElem =
21225 S.DefaultFunctionArrayLvalueConversion(E: TempArrayRes.get());
21226 auto *Idx = new (S.Context)
21227 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
21228 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(Base: TempArrayElem.get(),
21229 LLoc: ELoc, Idx, RLoc: ELoc);
21230 }
21231 }
21232
21233 // OpenMP [2.15.4.6, Restrictions, p.2]
21234 // A list item that appears in an in_reduction clause of a task construct
21235 // must appear in a task_reduction clause of a construct associated with a
21236 // taskgroup region that includes the participating task in its taskgroup
21237 // set. The construct associated with the innermost region that meets this
21238 // condition must specify the same reduction-identifier as the in_reduction
21239 // clause.
21240 if (ClauseKind == OMPC_in_reduction) {
21241 SourceRange ParentSR;
21242 BinaryOperatorKind ParentBOK;
21243 const Expr *ParentReductionOp = nullptr;
21244 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
21245 DSAStackTy::DSAVarData ParentBOKDSA =
21246 Stack->getTopMostTaskgroupReductionData(D, SR&: ParentSR, BOK&: ParentBOK,
21247 TaskgroupDescriptor&: ParentBOKTD);
21248 DSAStackTy::DSAVarData ParentReductionOpDSA =
21249 Stack->getTopMostTaskgroupReductionData(
21250 D, SR&: ParentSR, ReductionRef&: ParentReductionOp, TaskgroupDescriptor&: ParentReductionOpTD);
21251 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
21252 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
21253 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
21254 (DeclareReductionRef.isUsable() && IsParentBOK) ||
21255 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
21256 bool EmitError = true;
21257 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
21258 llvm::FoldingSetNodeID RedId, ParentRedId;
21259 ParentReductionOp->Profile(ID&: ParentRedId, Context, /*Canonical=*/true);
21260 DeclareReductionRef.get()->Profile(ID&: RedId, Context,
21261 /*Canonical=*/true);
21262 EmitError = RedId != ParentRedId;
21263 }
21264 if (EmitError) {
21265 S.Diag(Loc: ReductionId.getBeginLoc(),
21266 DiagID: diag::err_omp_reduction_identifier_mismatch)
21267 << ReductionIdRange << RefExpr->getSourceRange();
21268 S.Diag(Loc: ParentSR.getBegin(),
21269 DiagID: diag::note_omp_previous_reduction_identifier)
21270 << ParentSR
21271 << (IsParentBOK ? ParentBOKDSA.RefExpr
21272 : ParentReductionOpDSA.RefExpr)
21273 ->getSourceRange();
21274 continue;
21275 }
21276 }
21277 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
21278 }
21279
21280 DeclRefExpr *Ref = nullptr;
21281 Expr *VarsExpr = RefExpr->IgnoreParens();
21282 if (!VD && !S.CurContext->isDependentContext()) {
21283 if (ASE || OASE) {
21284 TransformExprToCaptures RebuildToCapture(S, D);
21285 VarsExpr =
21286 RebuildToCapture.TransformExpr(E: RefExpr->IgnoreParens()).get();
21287 Ref = RebuildToCapture.getCapturedExpr();
21288 } else {
21289 VarsExpr = Ref = buildCapture(S, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
21290 }
21291 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
21292 RD.ExprCaptures.emplace_back(Args: Ref->getDecl());
21293 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
21294 ExprResult RefRes = S.DefaultLvalueConversion(E: Ref);
21295 if (!RefRes.isUsable())
21296 continue;
21297 ExprResult PostUpdateRes =
21298 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: SimpleRefExpr,
21299 RHSExpr: RefRes.get());
21300 if (!PostUpdateRes.isUsable())
21301 continue;
21302 if (isOpenMPTaskingDirective(Kind: Stack->getCurrentDirective()) ||
21303 Stack->getCurrentDirective() == OMPD_taskgroup) {
21304 S.Diag(Loc: RefExpr->getExprLoc(),
21305 DiagID: diag::err_omp_reduction_non_addressable_expression)
21306 << RefExpr->getSourceRange();
21307 continue;
21308 }
21309 RD.ExprPostUpdates.emplace_back(
21310 Args: S.IgnoredValueConversions(E: PostUpdateRes.get()).get());
21311 }
21312 }
21313 }
21314 // All reduction items are still marked as reduction (to do not increase
21315 // code base size).
21316 unsigned Modifier = RD.RedModifier;
21317 // Consider task_reductions as reductions with task modifier. Required for
21318 // correct analysis of in_reduction clauses.
21319 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
21320 Modifier = OMPC_REDUCTION_task;
21321 Stack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_reduction, PrivateCopy: Ref, Modifier,
21322 AppliedToPointee: ASE || OASE);
21323 if (Modifier == OMPC_REDUCTION_task &&
21324 (CurrDir == OMPD_taskgroup ||
21325 ((isOpenMPParallelDirective(DKind: CurrDir) ||
21326 isOpenMPWorksharingDirective(DKind: CurrDir)) &&
21327 !isOpenMPSimdDirective(DKind: CurrDir)))) {
21328 if (DeclareReductionRef.isUsable())
21329 Stack->addTaskgroupReductionData(D, SR: ReductionIdRange,
21330 ReductionRef: DeclareReductionRef.get());
21331 else
21332 Stack->addTaskgroupReductionData(D, SR: ReductionIdRange, BOK);
21333 }
21334 RD.push(Item: VarsExpr, Private: PrivateDRE, LHS: LHSDRE, RHS: RHSDRE, ReductionOp: ReductionOp.get(),
21335 TaskgroupDescriptor, CopyOp: CopyOpRes.get(), CopyArrayTemp: TempArrayRes.get(),
21336 CopyArrayElem: TempArrayElem.get(), IsPrivate);
21337 }
21338 return RD.Vars.empty();
21339}
21340
21341OMPClause *SemaOpenMP::ActOnOpenMPReductionClause(
21342 ArrayRef<Expr *> VarList,
21343 OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers,
21344 SourceLocation StartLoc, SourceLocation LParenLoc,
21345 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
21346 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
21347 ArrayRef<Expr *> UnresolvedReductions) {
21348 OpenMPReductionClauseModifier Modifier =
21349 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
21350 OpenMPOriginalSharingModifier OriginalSharingModifier =
21351 static_cast<OpenMPOriginalSharingModifier>(
21352 Modifiers.OriginalSharingModifier);
21353 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
21354 Diag(Loc: LParenLoc, DiagID: diag::err_omp_unexpected_clause_value)
21355 << getListOfPossibleValues(K: OMPC_reduction, /*First=*/0,
21356 /*Last=*/OMPC_REDUCTION_unknown)
21357 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
21358 return nullptr;
21359 }
21360 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
21361 // A reduction clause with the inscan reduction-modifier may only appear on a
21362 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
21363 // construct, a parallel worksharing-loop construct or a parallel
21364 // worksharing-loop SIMD construct.
21365 if (Modifier == OMPC_REDUCTION_inscan &&
21366 (DSAStack->getCurrentDirective() != OMPD_for &&
21367 DSAStack->getCurrentDirective() != OMPD_for_simd &&
21368 DSAStack->getCurrentDirective() != OMPD_simd &&
21369 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
21370 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
21371 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_wrong_inscan_reduction);
21372 return nullptr;
21373 }
21374 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
21375 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_reduction, VarList,
21376 StartLoc, LParenLoc, ColonLoc, EndLoc,
21377 ReductionIdScopeSpec, ReductionId,
21378 UnresolvedReductions, RD))
21379 return nullptr;
21380
21381 return OMPReductionClause::Create(
21382 C: getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
21383 Modifier, VL: RD.Vars,
21384 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
21385 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps, CopyOps: RD.InscanCopyOps,
21386 CopyArrayTemps: RD.InscanCopyArrayTemps, CopyArrayElems: RD.InscanCopyArrayElems,
21387 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
21388 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates), IsPrivateVarReduction: RD.IsPrivateVarReduction,
21389 OriginalSharingModifier);
21390}
21391
21392OMPClause *SemaOpenMP::ActOnOpenMPTaskReductionClause(
21393 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21394 SourceLocation ColonLoc, SourceLocation EndLoc,
21395 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
21396 ArrayRef<Expr *> UnresolvedReductions) {
21397 ReductionData RD(VarList.size());
21398 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_task_reduction,
21399 VarList, StartLoc, LParenLoc, ColonLoc,
21400 EndLoc, ReductionIdScopeSpec, ReductionId,
21401 UnresolvedReductions, RD))
21402 return nullptr;
21403
21404 return OMPTaskReductionClause::Create(
21405 C: getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, VL: RD.Vars,
21406 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
21407 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps,
21408 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
21409 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates));
21410}
21411
21412OMPClause *SemaOpenMP::ActOnOpenMPInReductionClause(
21413 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21414 SourceLocation ColonLoc, SourceLocation EndLoc,
21415 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
21416 ArrayRef<Expr *> UnresolvedReductions) {
21417 ReductionData RD(VarList.size());
21418 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_in_reduction, VarList,
21419 StartLoc, LParenLoc, ColonLoc, EndLoc,
21420 ReductionIdScopeSpec, ReductionId,
21421 UnresolvedReductions, RD))
21422 return nullptr;
21423
21424 return OMPInReductionClause::Create(
21425 C: getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, VL: RD.Vars,
21426 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
21427 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps, TaskgroupDescriptors: RD.TaskgroupDescriptors,
21428 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
21429 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates));
21430}
21431
21432bool SemaOpenMP::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
21433 SourceLocation LinLoc) {
21434 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
21435 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
21436 Diag(Loc: LinLoc, DiagID: diag::err_omp_wrong_linear_modifier)
21437 << getLangOpts().CPlusPlus;
21438 return true;
21439 }
21440 return false;
21441}
21442
21443bool SemaOpenMP::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
21444 OpenMPLinearClauseKind LinKind,
21445 QualType Type, bool IsDeclareSimd) {
21446 const auto *VD = dyn_cast_or_null<VarDecl>(Val: D);
21447 // A variable must not have an incomplete type or a reference type.
21448 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
21449 DiagID: diag::err_omp_linear_incomplete_type))
21450 return true;
21451 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
21452 !Type->isReferenceType()) {
21453 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_linear_modifier_non_reference)
21454 << Type << getOpenMPSimpleClauseTypeName(Kind: OMPC_linear, Type: LinKind);
21455 return true;
21456 }
21457 Type = Type.getNonReferenceType();
21458
21459 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
21460 // A variable that is privatized must not have a const-qualified type
21461 // unless it is of class type with a mutable member. This restriction does
21462 // not apply to the firstprivate clause, nor to the linear clause on
21463 // declarative directives (like declare simd).
21464 if (!IsDeclareSimd &&
21465 rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_linear, ELoc))
21466 return true;
21467
21468 // A list item must be of integral or pointer type.
21469 Type = Type.getUnqualifiedType().getCanonicalType();
21470 const auto *Ty = Type.getTypePtrOrNull();
21471 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
21472 !Ty->isIntegralType(Ctx: getASTContext()) && !Ty->isPointerType())) {
21473 Diag(Loc: ELoc, DiagID: diag::err_omp_linear_expected_int_or_ptr) << Type;
21474 if (D) {
21475 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21476 VarDecl::DeclarationOnly;
21477 Diag(Loc: D->getLocation(),
21478 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21479 << D;
21480 }
21481 return true;
21482 }
21483 return false;
21484}
21485
21486OMPClause *SemaOpenMP::ActOnOpenMPLinearClause(
21487 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
21488 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
21489 SourceLocation LinLoc, SourceLocation ColonLoc,
21490 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
21491 SmallVector<Expr *, 8> Vars;
21492 SmallVector<Expr *, 8> Privates;
21493 SmallVector<Expr *, 8> Inits;
21494 SmallVector<Decl *, 4> ExprCaptures;
21495 SmallVector<Expr *, 4> ExprPostUpdates;
21496 // OpenMP 5.2 [Section 5.4.6, linear clause]
21497 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
21498 // 'ref'
21499 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
21500 getLangOpts().OpenMP >= 52)
21501 Diag(Loc: Step->getBeginLoc(), DiagID: diag::err_omp_step_simple_modifier_exclusive);
21502 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
21503 LinKind = OMPC_LINEAR_val;
21504 for (Expr *RefExpr : VarList) {
21505 assert(RefExpr && "NULL expr in OpenMP linear clause.");
21506 SourceLocation ELoc;
21507 SourceRange ERange;
21508 Expr *SimpleRefExpr = RefExpr;
21509 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
21510 if (Res.second) {
21511 // It will be analyzed later.
21512 Vars.push_back(Elt: RefExpr);
21513 Privates.push_back(Elt: nullptr);
21514 Inits.push_back(Elt: nullptr);
21515 }
21516 ValueDecl *D = Res.first;
21517 if (!D)
21518 continue;
21519
21520 QualType Type = D->getType();
21521 auto *VD = dyn_cast<VarDecl>(Val: D);
21522
21523 // OpenMP [2.14.3.7, linear clause]
21524 // A list-item cannot appear in more than one linear clause.
21525 // A list-item that appears in a linear clause cannot appear in any
21526 // other data-sharing attribute clause.
21527 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
21528 if (DVar.RefExpr) {
21529 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
21530 << getOpenMPClauseNameForDiag(C: DVar.CKind)
21531 << getOpenMPClauseNameForDiag(C: OMPC_linear);
21532 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
21533 continue;
21534 }
21535
21536 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
21537 continue;
21538 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
21539
21540 // Build private copy of original var.
21541 VarDecl *Private =
21542 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
21543 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
21544 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
21545 DeclRefExpr *PrivateRef = buildDeclRefExpr(S&: SemaRef, D: Private, Ty: Type, Loc: ELoc);
21546 // Build var to save initial value.
21547 VarDecl *Init = buildVarDecl(SemaRef, Loc: ELoc, Type, Name: ".linear.start");
21548 Expr *InitExpr;
21549 DeclRefExpr *Ref = nullptr;
21550 if (!VD && !SemaRef.CurContext->isDependentContext()) {
21551 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
21552 if (!isOpenMPCapturedDecl(D)) {
21553 ExprCaptures.push_back(Elt: Ref->getDecl());
21554 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
21555 ExprResult RefRes = SemaRef.DefaultLvalueConversion(E: Ref);
21556 if (!RefRes.isUsable())
21557 continue;
21558 ExprResult PostUpdateRes =
21559 SemaRef.BuildBinOp(DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign,
21560 LHSExpr: SimpleRefExpr, RHSExpr: RefRes.get());
21561 if (!PostUpdateRes.isUsable())
21562 continue;
21563 ExprPostUpdates.push_back(
21564 Elt: SemaRef.IgnoredValueConversions(E: PostUpdateRes.get()).get());
21565 }
21566 }
21567 }
21568 if (LinKind == OMPC_LINEAR_uval)
21569 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
21570 else
21571 InitExpr = VD ? SimpleRefExpr : Ref;
21572 SemaRef.AddInitializerToDecl(
21573 dcl: Init, init: SemaRef.DefaultLvalueConversion(E: InitExpr).get(),
21574 /*DirectInit=*/false);
21575 DeclRefExpr *InitRef = buildDeclRefExpr(S&: SemaRef, D: Init, Ty: Type, Loc: ELoc);
21576
21577 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_linear, PrivateCopy: Ref);
21578 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
21579 ? RefExpr->IgnoreParens()
21580 : Ref);
21581 Privates.push_back(Elt: PrivateRef);
21582 Inits.push_back(Elt: InitRef);
21583 }
21584
21585 if (Vars.empty())
21586 return nullptr;
21587
21588 Expr *StepExpr = Step;
21589 Expr *CalcStepExpr = nullptr;
21590 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
21591 !Step->isInstantiationDependent() &&
21592 !Step->containsUnexpandedParameterPack()) {
21593 SourceLocation StepLoc = Step->getBeginLoc();
21594 ExprResult Val = PerformOpenMPImplicitIntegerConversion(Loc: StepLoc, Op: Step);
21595 if (Val.isInvalid())
21596 return nullptr;
21597 StepExpr = Val.get();
21598
21599 // Build var to save the step value.
21600 VarDecl *SaveVar =
21601 buildVarDecl(SemaRef, Loc: StepLoc, Type: StepExpr->getType(), Name: ".linear.step");
21602 ExprResult SaveRef =
21603 buildDeclRefExpr(S&: SemaRef, D: SaveVar, Ty: StepExpr->getType(), Loc: StepLoc);
21604 ExprResult CalcStep = SemaRef.BuildBinOp(
21605 S: SemaRef.getCurScope(), OpLoc: StepLoc, Opc: BO_Assign, LHSExpr: SaveRef.get(), RHSExpr: StepExpr);
21606 CalcStep =
21607 SemaRef.ActOnFinishFullExpr(Expr: CalcStep.get(), /*DiscardedValue=*/false);
21608
21609 // Warn about zero linear step (it would be probably better specified as
21610 // making corresponding variables 'const').
21611 if (std::optional<llvm::APSInt> Result =
21612 StepExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
21613 if (!Result->isNegative() && !Result->isStrictlyPositive())
21614 Diag(Loc: StepLoc, DiagID: diag::warn_omp_linear_step_zero)
21615 << Vars[0] << (Vars.size() > 1);
21616 } else if (CalcStep.isUsable()) {
21617 // Calculate the step beforehand instead of doing this on each iteration.
21618 // (This is not used if the number of iterations may be kfold-ed).
21619 CalcStepExpr = CalcStep.get();
21620 }
21621 }
21622
21623 return OMPLinearClause::Create(C: getASTContext(), StartLoc, LParenLoc, Modifier: LinKind,
21624 ModifierLoc: LinLoc, ColonLoc, StepModifierLoc, EndLoc,
21625 VL: Vars, PL: Privates, IL: Inits, Step: StepExpr, CalcStep: CalcStepExpr,
21626 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures),
21627 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: ExprPostUpdates));
21628}
21629
21630static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
21631 Expr *NumIterations, Sema &SemaRef,
21632 Scope *S, DSAStackTy *Stack) {
21633 // Walk the vars and build update/final expressions for the CodeGen.
21634 SmallVector<Expr *, 8> Updates;
21635 SmallVector<Expr *, 8> Finals;
21636 SmallVector<Expr *, 8> UsedExprs;
21637 Expr *Step = Clause.getStep();
21638 Expr *CalcStep = Clause.getCalcStep();
21639 // OpenMP [2.14.3.7, linear clause]
21640 // If linear-step is not specified it is assumed to be 1.
21641 if (!Step)
21642 Step = SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get();
21643 else if (CalcStep)
21644 Step = cast<BinaryOperator>(Val: CalcStep)->getLHS();
21645 bool HasErrors = false;
21646 auto CurInit = Clause.inits().begin();
21647 auto CurPrivate = Clause.privates().begin();
21648 OpenMPLinearClauseKind LinKind = Clause.getModifier();
21649 for (Expr *RefExpr : Clause.varlist()) {
21650 SourceLocation ELoc;
21651 SourceRange ERange;
21652 Expr *SimpleRefExpr = RefExpr;
21653 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
21654 ValueDecl *D = Res.first;
21655 if (Res.second || !D) {
21656 Updates.push_back(Elt: nullptr);
21657 Finals.push_back(Elt: nullptr);
21658 HasErrors = true;
21659 continue;
21660 }
21661 auto &&Info = Stack->isLoopControlVariable(D);
21662 // OpenMP [2.15.11, distribute simd Construct]
21663 // A list item may not appear in a linear clause, unless it is the loop
21664 // iteration variable.
21665 if (isOpenMPDistributeDirective(DKind: Stack->getCurrentDirective()) &&
21666 isOpenMPSimdDirective(DKind: Stack->getCurrentDirective()) && !Info.first) {
21667 SemaRef.Diag(Loc: ELoc,
21668 DiagID: diag::err_omp_linear_distribute_var_non_loop_iteration);
21669 Updates.push_back(Elt: nullptr);
21670 Finals.push_back(Elt: nullptr);
21671 HasErrors = true;
21672 continue;
21673 }
21674 Expr *InitExpr = *CurInit;
21675
21676 // Build privatized reference to the current linear var.
21677 auto *DE = cast<DeclRefExpr>(Val: SimpleRefExpr);
21678 Expr *CapturedRef;
21679 if (LinKind == OMPC_LINEAR_uval)
21680 CapturedRef = cast<VarDecl>(Val: DE->getDecl())->getInit();
21681 else
21682 CapturedRef =
21683 buildDeclRefExpr(S&: SemaRef, D: cast<VarDecl>(Val: DE->getDecl()),
21684 Ty: DE->getType().getUnqualifiedType(), Loc: DE->getExprLoc(),
21685 /*RefersToCapture=*/true);
21686
21687 // Build update: Var = InitExpr + IV * Step
21688 ExprResult Update;
21689 if (!Info.first)
21690 Update = buildCounterUpdate(
21691 SemaRef, S, Loc: RefExpr->getExprLoc(), VarRef: *CurPrivate, Start: InitExpr, Iter: IV, Step,
21692 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
21693 else
21694 Update = *CurPrivate;
21695 Update = SemaRef.ActOnFinishFullExpr(Expr: Update.get(), CC: DE->getBeginLoc(),
21696 /*DiscardedValue=*/false);
21697
21698 // Build final: Var = PrivCopy;
21699 ExprResult Final;
21700 if (!Info.first)
21701 Final = SemaRef.BuildBinOp(
21702 S, OpLoc: RefExpr->getExprLoc(), Opc: BO_Assign, LHSExpr: CapturedRef,
21703 RHSExpr: SemaRef.DefaultLvalueConversion(E: *CurPrivate).get());
21704 else
21705 Final = *CurPrivate;
21706 Final = SemaRef.ActOnFinishFullExpr(Expr: Final.get(), CC: DE->getBeginLoc(),
21707 /*DiscardedValue=*/false);
21708
21709 if (!Update.isUsable() || !Final.isUsable()) {
21710 Updates.push_back(Elt: nullptr);
21711 Finals.push_back(Elt: nullptr);
21712 UsedExprs.push_back(Elt: nullptr);
21713 HasErrors = true;
21714 } else {
21715 Updates.push_back(Elt: Update.get());
21716 Finals.push_back(Elt: Final.get());
21717 if (!Info.first)
21718 UsedExprs.push_back(Elt: SimpleRefExpr);
21719 }
21720 ++CurInit;
21721 ++CurPrivate;
21722 }
21723 if (Expr *S = Clause.getStep())
21724 UsedExprs.push_back(Elt: S);
21725 // Fill the remaining part with the nullptr.
21726 UsedExprs.append(NumInputs: Clause.varlist_size() + 1 - UsedExprs.size(), Elt: nullptr);
21727 Clause.setUpdates(Updates);
21728 Clause.setFinals(Finals);
21729 Clause.setUsedExprs(UsedExprs);
21730 return HasErrors;
21731}
21732
21733OMPClause *SemaOpenMP::ActOnOpenMPAlignedClause(
21734 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
21735 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
21736 SmallVector<Expr *, 8> Vars;
21737 for (Expr *RefExpr : VarList) {
21738 assert(RefExpr && "NULL expr in OpenMP aligned clause.");
21739 SourceLocation ELoc;
21740 SourceRange ERange;
21741 Expr *SimpleRefExpr = RefExpr;
21742 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
21743 if (Res.second) {
21744 // It will be analyzed later.
21745 Vars.push_back(Elt: RefExpr);
21746 }
21747 ValueDecl *D = Res.first;
21748 if (!D)
21749 continue;
21750
21751 QualType QType = D->getType();
21752 auto *VD = dyn_cast<VarDecl>(Val: D);
21753
21754 // OpenMP [2.8.1, simd construct, Restrictions]
21755 // The type of list items appearing in the aligned clause must be
21756 // array, pointer, reference to array, or reference to pointer.
21757 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
21758 const Type *Ty = QType.getTypePtrOrNull();
21759 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
21760 Diag(Loc: ELoc, DiagID: diag::err_omp_aligned_expected_array_or_ptr)
21761 << QType << getLangOpts().CPlusPlus << ERange;
21762 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21763 VarDecl::DeclarationOnly;
21764 Diag(Loc: D->getLocation(),
21765 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21766 << D;
21767 continue;
21768 }
21769
21770 // OpenMP [2.8.1, simd construct, Restrictions]
21771 // A list-item cannot appear in more than one aligned clause.
21772 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, NewDE: SimpleRefExpr)) {
21773 Diag(Loc: ELoc, DiagID: diag::err_omp_used_in_clause_twice)
21774 << 0 << getOpenMPClauseNameForDiag(C: OMPC_aligned) << ERange;
21775 Diag(Loc: PrevRef->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
21776 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
21777 continue;
21778 }
21779
21780 DeclRefExpr *Ref = nullptr;
21781 if (!VD && isOpenMPCapturedDecl(D))
21782 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
21783 Vars.push_back(Elt: SemaRef
21784 .DefaultFunctionArrayConversion(
21785 E: (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
21786 .get());
21787 }
21788
21789 // OpenMP [2.8.1, simd construct, Description]
21790 // The parameter of the aligned clause, alignment, must be a constant
21791 // positive integer expression.
21792 // If no optional parameter is specified, implementation-defined default
21793 // alignments for SIMD instructions on the target platforms are assumed.
21794 if (Alignment != nullptr) {
21795 ExprResult AlignResult =
21796 VerifyPositiveIntegerConstantInClause(E: Alignment, CKind: OMPC_aligned);
21797 if (AlignResult.isInvalid())
21798 return nullptr;
21799 Alignment = AlignResult.get();
21800 }
21801 if (Vars.empty())
21802 return nullptr;
21803
21804 return OMPAlignedClause::Create(C: getASTContext(), StartLoc, LParenLoc,
21805 ColonLoc, EndLoc, VL: Vars, A: Alignment);
21806}
21807
21808OMPClause *SemaOpenMP::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
21809 SourceLocation StartLoc,
21810 SourceLocation LParenLoc,
21811 SourceLocation EndLoc) {
21812 SmallVector<Expr *, 8> Vars;
21813 SmallVector<Expr *, 8> SrcExprs;
21814 SmallVector<Expr *, 8> DstExprs;
21815 SmallVector<Expr *, 8> AssignmentOps;
21816 for (Expr *RefExpr : VarList) {
21817 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
21818 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
21819 // It will be analyzed later.
21820 Vars.push_back(Elt: RefExpr);
21821 SrcExprs.push_back(Elt: nullptr);
21822 DstExprs.push_back(Elt: nullptr);
21823 AssignmentOps.push_back(Elt: nullptr);
21824 continue;
21825 }
21826
21827 SourceLocation ELoc = RefExpr->getExprLoc();
21828 // OpenMP [2.1, C/C++]
21829 // A list item is a variable name.
21830 // OpenMP [2.14.4.1, Restrictions, p.1]
21831 // A list item that appears in a copyin clause must be threadprivate.
21832 auto *DE = dyn_cast<DeclRefExpr>(Val: RefExpr);
21833 if (!DE || !isa<VarDecl>(Val: DE->getDecl())) {
21834 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_var_name_member_expr)
21835 << 0 << RefExpr->getSourceRange();
21836 continue;
21837 }
21838
21839 Decl *D = DE->getDecl();
21840 auto *VD = cast<VarDecl>(Val: D);
21841
21842 QualType Type = VD->getType();
21843 if (Type->isDependentType() || Type->isInstantiationDependentType()) {
21844 // It will be analyzed later.
21845 Vars.push_back(Elt: DE);
21846 SrcExprs.push_back(Elt: nullptr);
21847 DstExprs.push_back(Elt: nullptr);
21848 AssignmentOps.push_back(Elt: nullptr);
21849 continue;
21850 }
21851
21852 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
21853 // A list item that appears in a copyin clause must be threadprivate.
21854 if (!DSAStack->isThreadPrivate(D: VD)) {
21855 unsigned OMPVersion = getLangOpts().OpenMP;
21856 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
21857 << getOpenMPClauseNameForDiag(C: OMPC_copyin)
21858 << getOpenMPDirectiveName(D: OMPD_threadprivate, Ver: OMPVersion);
21859 continue;
21860 }
21861
21862 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21863 // A variable of class type (or array thereof) that appears in a
21864 // copyin clause requires an accessible, unambiguous copy assignment
21865 // operator for the class type.
21866 QualType ElemType =
21867 getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
21868 VarDecl *SrcVD =
21869 buildVarDecl(SemaRef, Loc: DE->getBeginLoc(), Type: ElemType.getUnqualifiedType(),
21870 Name: ".copyin.src", Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21871 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
21872 S&: SemaRef, D: SrcVD, Ty: ElemType.getUnqualifiedType(), Loc: DE->getExprLoc());
21873 VarDecl *DstVD =
21874 buildVarDecl(SemaRef, Loc: DE->getBeginLoc(), Type: ElemType, Name: ".copyin.dst",
21875 Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21876 DeclRefExpr *PseudoDstExpr =
21877 buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: ElemType, Loc: DE->getExprLoc());
21878 // For arrays generate assignment operation for single element and replace
21879 // it by the original array element in CodeGen.
21880 ExprResult AssignmentOp =
21881 SemaRef.BuildBinOp(/*S=*/nullptr, OpLoc: DE->getExprLoc(), Opc: BO_Assign,
21882 LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
21883 if (AssignmentOp.isInvalid())
21884 continue;
21885 AssignmentOp =
21886 SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: DE->getExprLoc(),
21887 /*DiscardedValue=*/false);
21888 if (AssignmentOp.isInvalid())
21889 continue;
21890
21891 DSAStack->addDSA(D: VD, E: DE, A: OMPC_copyin);
21892 Vars.push_back(Elt: DE);
21893 SrcExprs.push_back(Elt: PseudoSrcExpr);
21894 DstExprs.push_back(Elt: PseudoDstExpr);
21895 AssignmentOps.push_back(Elt: AssignmentOp.get());
21896 }
21897
21898 if (Vars.empty())
21899 return nullptr;
21900
21901 return OMPCopyinClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
21902 VL: Vars, SrcExprs, DstExprs, AssignmentOps);
21903}
21904
21905OMPClause *SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
21906 SourceLocation StartLoc,
21907 SourceLocation LParenLoc,
21908 SourceLocation EndLoc) {
21909 SmallVector<Expr *, 8> Vars;
21910 SmallVector<Expr *, 8> SrcExprs;
21911 SmallVector<Expr *, 8> DstExprs;
21912 SmallVector<Expr *, 8> AssignmentOps;
21913 for (Expr *RefExpr : VarList) {
21914 assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
21915 SourceLocation ELoc;
21916 SourceRange ERange;
21917 Expr *SimpleRefExpr = RefExpr;
21918 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
21919 if (Res.second) {
21920 // It will be analyzed later.
21921 Vars.push_back(Elt: RefExpr);
21922 SrcExprs.push_back(Elt: nullptr);
21923 DstExprs.push_back(Elt: nullptr);
21924 AssignmentOps.push_back(Elt: nullptr);
21925 }
21926 ValueDecl *D = Res.first;
21927 if (!D)
21928 continue;
21929
21930 QualType Type = D->getType();
21931 auto *VD = dyn_cast<VarDecl>(Val: D);
21932
21933 // OpenMP [2.14.4.2, Restrictions, p.2]
21934 // A list item that appears in a copyprivate clause may not appear in a
21935 // private or firstprivate clause on the single construct.
21936 if (!VD || !DSAStack->isThreadPrivate(D: VD)) {
21937 DSAStackTy::DSAVarData DVar =
21938 DSAStack->getTopDSA(D, /*FromParent=*/false);
21939 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
21940 DVar.RefExpr) {
21941 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
21942 << getOpenMPClauseNameForDiag(C: DVar.CKind)
21943 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate);
21944 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
21945 continue;
21946 }
21947
21948 // OpenMP [2.11.4.2, Restrictions, p.1]
21949 // All list items that appear in a copyprivate clause must be either
21950 // threadprivate or private in the enclosing context.
21951 if (DVar.CKind == OMPC_unknown) {
21952 DVar = DSAStack->getImplicitDSA(D, FromParent: false);
21953 if (DVar.CKind == OMPC_shared) {
21954 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
21955 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate)
21956 << "threadprivate or private in the enclosing context";
21957 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
21958 continue;
21959 }
21960 }
21961 }
21962
21963 // Variably modified types are not supported.
21964 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
21965 unsigned OMPVersion = getLangOpts().OpenMP;
21966 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
21967 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate) << Type
21968 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
21969 Ver: OMPVersion);
21970 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21971 VarDecl::DeclarationOnly;
21972 Diag(Loc: D->getLocation(),
21973 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21974 << D;
21975 continue;
21976 }
21977
21978 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21979 // A variable of class type (or array thereof) that appears in a
21980 // copyin clause requires an accessible, unambiguous copy assignment
21981 // operator for the class type.
21982 Type = getASTContext()
21983 .getBaseElementType(QT: Type.getNonReferenceType())
21984 .getUnqualifiedType();
21985 VarDecl *SrcVD =
21986 buildVarDecl(SemaRef, Loc: RefExpr->getBeginLoc(), Type, Name: ".copyprivate.src",
21987 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
21988 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(S&: SemaRef, D: SrcVD, Ty: Type, Loc: ELoc);
21989 VarDecl *DstVD =
21990 buildVarDecl(SemaRef, Loc: RefExpr->getBeginLoc(), Type, Name: ".copyprivate.dst",
21991 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
21992 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: Type, Loc: ELoc);
21993 ExprResult AssignmentOp = SemaRef.BuildBinOp(
21994 DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
21995 if (AssignmentOp.isInvalid())
21996 continue;
21997 AssignmentOp = SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: ELoc,
21998 /*DiscardedValue=*/false);
21999 if (AssignmentOp.isInvalid())
22000 continue;
22001
22002 // No need to mark vars as copyprivate, they are already threadprivate or
22003 // implicitly private.
22004 assert(VD || isOpenMPCapturedDecl(D));
22005 Vars.push_back(
22006 Elt: VD ? RefExpr->IgnoreParens()
22007 : buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false));
22008 SrcExprs.push_back(Elt: PseudoSrcExpr);
22009 DstExprs.push_back(Elt: PseudoDstExpr);
22010 AssignmentOps.push_back(Elt: AssignmentOp.get());
22011 }
22012
22013 if (Vars.empty())
22014 return nullptr;
22015
22016 return OMPCopyprivateClause::Create(C: getASTContext(), StartLoc, LParenLoc,
22017 EndLoc, VL: Vars, SrcExprs, DstExprs,
22018 AssignmentOps);
22019}
22020
22021OMPClause *SemaOpenMP::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
22022 SourceLocation StartLoc,
22023 SourceLocation LParenLoc,
22024 SourceLocation EndLoc) {
22025 if (VarList.empty())
22026 return nullptr;
22027
22028 return OMPFlushClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
22029 VL: VarList);
22030}
22031
22032/// Tries to find omp_depend_t. type.
22033static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
22034 bool Diagnose = true) {
22035 QualType OMPDependT = Stack->getOMPDependT();
22036 if (!OMPDependT.isNull())
22037 return true;
22038 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_depend_t");
22039 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
22040 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22041 if (Diagnose)
22042 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_depend_t";
22043 return false;
22044 }
22045 Stack->setOMPDependT(PT.get());
22046 return true;
22047}
22048
22049OMPClause *SemaOpenMP::ActOnOpenMPDepobjClause(Expr *Depobj,
22050 SourceLocation StartLoc,
22051 SourceLocation LParenLoc,
22052 SourceLocation EndLoc) {
22053 if (!Depobj)
22054 return nullptr;
22055
22056 bool OMPDependTFound = findOMPDependT(S&: SemaRef, Loc: StartLoc, DSAStack);
22057
22058 // OpenMP 5.0, 2.17.10.1 depobj Construct
22059 // depobj is an lvalue expression of type omp_depend_t.
22060 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
22061 !Depobj->isInstantiationDependent() &&
22062 !Depobj->containsUnexpandedParameterPack() &&
22063 (OMPDependTFound && !getASTContext().typesAreCompatible(
22064 DSAStack->getOMPDependT(), T2: Depobj->getType(),
22065 /*CompareUnqualified=*/true))) {
22066 Diag(Loc: Depobj->getExprLoc(), DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
22067 << 0 << Depobj->getType() << Depobj->getSourceRange();
22068 }
22069
22070 if (!Depobj->isLValue()) {
22071 Diag(Loc: Depobj->getExprLoc(), DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
22072 << 1 << Depobj->getSourceRange();
22073 }
22074
22075 return OMPDepobjClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
22076 Depobj);
22077}
22078
22079namespace {
22080// Utility struct that gathers the related info for doacross clause.
22081struct DoacrossDataInfoTy {
22082 // The list of expressions.
22083 SmallVector<Expr *, 8> Vars;
22084 // The OperatorOffset for doacross loop.
22085 DSAStackTy::OperatorOffsetTy OpsOffs;
22086 // The depended loop count.
22087 llvm::APSInt TotalDepCount;
22088};
22089} // namespace
22090static DoacrossDataInfoTy
22091ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource,
22092 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
22093 SourceLocation EndLoc) {
22094
22095 SmallVector<Expr *, 8> Vars;
22096 DSAStackTy::OperatorOffsetTy OpsOffs;
22097 llvm::APSInt DepCounter(/*BitWidth=*/32);
22098 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
22099
22100 if (const Expr *OrderedCountExpr =
22101 Stack->getParentOrderedRegionParam().first) {
22102 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Ctx: SemaRef.Context);
22103 TotalDepCount.setIsUnsigned(/*Val=*/true);
22104 }
22105
22106 for (Expr *RefExpr : VarList) {
22107 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
22108 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
22109 // It will be analyzed later.
22110 Vars.push_back(Elt: RefExpr);
22111 continue;
22112 }
22113
22114 SourceLocation ELoc = RefExpr->getExprLoc();
22115 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
22116 if (!IsSource) {
22117 if (Stack->getParentOrderedRegionParam().first &&
22118 DepCounter >= TotalDepCount) {
22119 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_unexpected_expr);
22120 continue;
22121 }
22122 ++DepCounter;
22123 // OpenMP [2.13.9, Summary]
22124 // depend(dependence-type : vec), where dependence-type is:
22125 // 'sink' and where vec is the iteration vector, which has the form:
22126 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
22127 // where n is the value specified by the ordered clause in the loop
22128 // directive, xi denotes the loop iteration variable of the i-th nested
22129 // loop associated with the loop directive, and di is a constant
22130 // non-negative integer.
22131 if (SemaRef.CurContext->isDependentContext()) {
22132 // It will be analyzed later.
22133 Vars.push_back(Elt: RefExpr);
22134 continue;
22135 }
22136 SimpleExpr = SimpleExpr->IgnoreImplicit();
22137 OverloadedOperatorKind OOK = OO_None;
22138 SourceLocation OOLoc;
22139 Expr *LHS = SimpleExpr;
22140 Expr *RHS = nullptr;
22141 if (auto *BO = dyn_cast<BinaryOperator>(Val: SimpleExpr)) {
22142 OOK = BinaryOperator::getOverloadedOperator(Opc: BO->getOpcode());
22143 OOLoc = BO->getOperatorLoc();
22144 LHS = BO->getLHS()->IgnoreParenImpCasts();
22145 RHS = BO->getRHS()->IgnoreParenImpCasts();
22146 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Val: SimpleExpr)) {
22147 OOK = OCE->getOperator();
22148 OOLoc = OCE->getOperatorLoc();
22149 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
22150 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
22151 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Val: SimpleExpr)) {
22152 OOK = MCE->getMethodDecl()
22153 ->getNameInfo()
22154 .getName()
22155 .getCXXOverloadedOperator();
22156 OOLoc = MCE->getCallee()->getExprLoc();
22157 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
22158 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
22159 }
22160 SourceLocation ELoc;
22161 SourceRange ERange;
22162 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: LHS, ELoc, ERange);
22163 if (Res.second) {
22164 // It will be analyzed later.
22165 Vars.push_back(Elt: RefExpr);
22166 }
22167 ValueDecl *D = Res.first;
22168 if (!D)
22169 continue;
22170
22171 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
22172 SemaRef.Diag(Loc: OOLoc, DiagID: diag::err_omp_depend_sink_expected_plus_minus);
22173 continue;
22174 }
22175 if (RHS) {
22176 ExprResult RHSRes =
22177 SemaRef.OpenMP().VerifyPositiveIntegerConstantInClause(
22178 E: RHS, CKind: OMPC_depend, /*StrictlyPositive=*/false);
22179 if (RHSRes.isInvalid())
22180 continue;
22181 }
22182 if (!SemaRef.CurContext->isDependentContext() &&
22183 Stack->getParentOrderedRegionParam().first &&
22184 DepCounter != Stack->isParentLoopControlVariable(D).first) {
22185 const ValueDecl *VD =
22186 Stack->getParentLoopControlVariable(I: DepCounter.getZExtValue());
22187 if (VD)
22188 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
22189 << 1 << VD;
22190 else
22191 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
22192 << 0;
22193 continue;
22194 }
22195 OpsOffs.emplace_back(Args&: RHS, Args&: OOK);
22196 }
22197 Vars.push_back(Elt: RefExpr->IgnoreParenImpCasts());
22198 }
22199 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
22200 TotalDepCount > VarList.size() &&
22201 Stack->getParentOrderedRegionParam().first &&
22202 Stack->getParentLoopControlVariable(I: VarList.size() + 1)) {
22203 SemaRef.Diag(Loc: EndLoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
22204 << 1 << Stack->getParentLoopControlVariable(I: VarList.size() + 1);
22205 }
22206 return {.Vars: Vars, .OpsOffs: OpsOffs, .TotalDepCount: TotalDepCount};
22207}
22208
22209OMPClause *SemaOpenMP::ActOnOpenMPDependClause(
22210 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
22211 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
22212 SourceLocation EndLoc) {
22213 OpenMPDependClauseKind DepKind = Data.DepKind;
22214 SourceLocation DepLoc = Data.DepLoc;
22215 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
22216 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
22217 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
22218 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(C: OMPC_depend);
22219 return nullptr;
22220 }
22221 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
22222 DepKind == OMPC_DEPEND_mutexinoutset) {
22223 Diag(Loc: DepLoc, DiagID: diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
22224 return nullptr;
22225 }
22226 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
22227 DSAStack->getCurrentDirective() == OMPD_depobj) &&
22228 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
22229 DepKind == OMPC_DEPEND_sink ||
22230 ((getLangOpts().OpenMP < 50 ||
22231 DSAStack->getCurrentDirective() == OMPD_depobj) &&
22232 DepKind == OMPC_DEPEND_depobj))) {
22233 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
22234 OMPC_DEPEND_outallmemory,
22235 OMPC_DEPEND_inoutallmemory};
22236 if (getLangOpts().OpenMP < 50 ||
22237 DSAStack->getCurrentDirective() == OMPD_depobj)
22238 Except.push_back(Elt: OMPC_DEPEND_depobj);
22239 if (getLangOpts().OpenMP < 51)
22240 Except.push_back(Elt: OMPC_DEPEND_inoutset);
22241 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
22242 ? "depend modifier(iterator) or "
22243 : "";
22244 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
22245 << Expected + getListOfPossibleValues(K: OMPC_depend, /*First=*/0,
22246 /*Last=*/OMPC_DEPEND_unknown,
22247 Exclude: Except)
22248 << getOpenMPClauseNameForDiag(C: OMPC_depend);
22249 return nullptr;
22250 }
22251 if (DepModifier &&
22252 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
22253 Diag(Loc: DepModifier->getExprLoc(),
22254 DiagID: diag::err_omp_depend_sink_source_with_modifier);
22255 return nullptr;
22256 }
22257 if (DepModifier &&
22258 !DepModifier->getType()->isSpecificBuiltinType(K: BuiltinType::OMPIterator))
22259 Diag(Loc: DepModifier->getExprLoc(), DiagID: diag::err_omp_depend_modifier_not_iterator);
22260
22261 SmallVector<Expr *, 8> Vars;
22262 DSAStackTy::OperatorOffsetTy OpsOffs;
22263 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
22264
22265 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
22266 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
22267 SemaRef, IsSource: DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
22268 Vars = VarOffset.Vars;
22269 OpsOffs = VarOffset.OpsOffs;
22270 TotalDepCount = VarOffset.TotalDepCount;
22271 } else {
22272 for (Expr *RefExpr : VarList) {
22273 assert(RefExpr && "NULL expr in OpenMP depend clause.");
22274 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
22275 // It will be analyzed later.
22276 Vars.push_back(Elt: RefExpr);
22277 continue;
22278 }
22279
22280 SourceLocation ELoc = RefExpr->getExprLoc();
22281 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
22282 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
22283 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
22284 if (OMPDependTFound)
22285 OMPDependTFound = findOMPDependT(S&: SemaRef, Loc: StartLoc, DSAStack,
22286 Diagnose: DepKind == OMPC_DEPEND_depobj);
22287 if (DepKind == OMPC_DEPEND_depobj) {
22288 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
22289 // List items used in depend clauses with the depobj dependence type
22290 // must be expressions of the omp_depend_t type.
22291 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
22292 !RefExpr->isInstantiationDependent() &&
22293 !RefExpr->containsUnexpandedParameterPack() &&
22294 (OMPDependTFound &&
22295 !getASTContext().hasSameUnqualifiedType(
22296 DSAStack->getOMPDependT(), T2: RefExpr->getType()))) {
22297 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
22298 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
22299 continue;
22300 }
22301 if (!RefExpr->isLValue()) {
22302 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
22303 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
22304 continue;
22305 }
22306 } else {
22307 // OpenMP 5.0 [2.17.11, Restrictions]
22308 // List items used in depend clauses cannot be zero-length array
22309 // sections.
22310 QualType ExprTy = RefExpr->getType().getNonReferenceType();
22311 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: SimpleExpr);
22312 if (OASE) {
22313 QualType BaseType =
22314 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
22315 if (BaseType.isNull())
22316 return nullptr;
22317 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22318 ExprTy = ATy->getElementType();
22319 else
22320 ExprTy = BaseType->getPointeeType();
22321 if (BaseType.isNull() || ExprTy.isNull())
22322 return nullptr;
22323 ExprTy = ExprTy.getNonReferenceType();
22324 const Expr *Length = OASE->getLength();
22325 Expr::EvalResult Result;
22326 if (Length && !Length->isValueDependent() &&
22327 Length->EvaluateAsInt(Result, Ctx: getASTContext()) &&
22328 Result.Val.getInt().isZero()) {
22329 Diag(Loc: ELoc,
22330 DiagID: diag::err_omp_depend_zero_length_array_section_not_allowed)
22331 << SimpleExpr->getSourceRange();
22332 continue;
22333 }
22334 }
22335
22336 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
22337 // List items used in depend clauses with the in, out, inout,
22338 // inoutset, or mutexinoutset dependence types cannot be
22339 // expressions of the omp_depend_t type.
22340 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
22341 !RefExpr->isInstantiationDependent() &&
22342 !RefExpr->containsUnexpandedParameterPack() &&
22343 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
22344 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
22345 ExprTy.getTypePtr()))) {
22346 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
22347 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22348 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22349 << RefExpr->getSourceRange();
22350 continue;
22351 }
22352
22353 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: SimpleExpr);
22354 if (ASE && !ASE->getBase()->isTypeDependent() &&
22355 !ASE->getBase()
22356 ->getType()
22357 .getNonReferenceType()
22358 ->isPointerType() &&
22359 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
22360 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
22361 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22362 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22363 << RefExpr->getSourceRange();
22364 continue;
22365 }
22366
22367 ExprResult Res;
22368 {
22369 Sema::TentativeAnalysisScope Trap(SemaRef);
22370 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf,
22371 InputExpr: RefExpr->IgnoreParenImpCasts());
22372 }
22373 if (!Res.isUsable() && !isa<ArraySectionExpr>(Val: SimpleExpr) &&
22374 !isa<OMPArrayShapingExpr>(Val: SimpleExpr)) {
22375 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
22376 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22377 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22378 << RefExpr->getSourceRange();
22379 continue;
22380 }
22381 }
22382 }
22383 Vars.push_back(Elt: RefExpr->IgnoreParenImpCasts());
22384 }
22385 }
22386
22387 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
22388 DepKind != OMPC_DEPEND_outallmemory &&
22389 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
22390 return nullptr;
22391
22392 auto *C = OMPDependClause::Create(
22393 C: getASTContext(), StartLoc, LParenLoc, EndLoc,
22394 Data: {.DepKind: DepKind, .DepLoc: DepLoc, .ColonLoc: Data.ColonLoc, .OmpAllMemoryLoc: Data.OmpAllMemoryLoc}, DepModifier, VL: Vars,
22395 NumLoops: TotalDepCount.getZExtValue());
22396 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
22397 DSAStack->isParentOrderedRegion())
22398 DSAStack->addDoacrossDependClause(C, OpsOffs);
22399 return C;
22400}
22401
22402OMPClause *SemaOpenMP::ActOnOpenMPDeviceClause(
22403 OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc,
22404 SourceLocation LParenLoc, SourceLocation ModifierLoc,
22405 SourceLocation EndLoc) {
22406 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
22407 "Unexpected device modifier in OpenMP < 50.");
22408
22409 bool ErrorFound = false;
22410 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
22411 std::string Values =
22412 getListOfPossibleValues(K: OMPC_device, /*First=*/0, Last: OMPC_DEVICE_unknown);
22413 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
22414 << Values << getOpenMPClauseNameForDiag(C: OMPC_device);
22415 ErrorFound = true;
22416 }
22417
22418 Expr *ValExpr = Device;
22419 Stmt *HelperValStmt = nullptr;
22420
22421 // OpenMP 5.2 [1.3, Execution Model]: a conforming device number is either
22422 // a non-negative integer that is less than or equal to omp_get_num_devices()
22423 // or equal to omp_initial_device or omp_invalid_device. The predefined
22424 // identifiers were introduced in OpenMP 5.2; earlier versions require a
22425 // non-negative integer.
22426 if (getLangOpts().OpenMP >= 52) {
22427 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
22428 !ValExpr->isInstantiationDependent()) {
22429 SourceLocation Loc = ValExpr->getExprLoc();
22430 ExprResult Value = PerformOpenMPImplicitIntegerConversion(Loc, Op: ValExpr);
22431 if (Value.isInvalid()) {
22432 ErrorFound = true;
22433 } else {
22434 ValExpr = Value.get();
22435 if (std::optional<llvm::APSInt> Result =
22436 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
22437 if (Result->isSigned() && Result->slt(RHS: -2)) {
22438 Diag(Loc, DiagID: diag::err_omp_device_expression_invalid)
22439 << ValExpr->getSourceRange();
22440 ErrorFound = true;
22441 }
22442 }
22443 }
22444 }
22445 } else {
22446 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_device,
22447 /*StrictlyPositive=*/false) ||
22448 ErrorFound;
22449 }
22450 if (ErrorFound)
22451 return nullptr;
22452
22453 // OpenMP 5.0 [2.12.5, Restrictions]
22454 // In case of ancestor device-modifier, a requires directive with
22455 // the reverse_offload clause must be specified.
22456 if (Modifier == OMPC_DEVICE_ancestor) {
22457 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
22458 SemaRef.targetDiag(
22459 Loc: StartLoc,
22460 DiagID: diag::err_omp_device_ancestor_without_requires_reverse_offload);
22461 ErrorFound = true;
22462 }
22463 }
22464
22465 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22466 OpenMPDirectiveKind CaptureRegion =
22467 getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_device, OpenMPVersion: getLangOpts().OpenMP);
22468 if (CaptureRegion != OMPD_unknown &&
22469 !SemaRef.CurContext->isDependentContext()) {
22470 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
22471 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22472 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
22473 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
22474 }
22475
22476 return new (getASTContext())
22477 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
22478 LParenLoc, ModifierLoc, EndLoc);
22479}
22480
22481static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
22482 DSAStackTy *Stack, QualType QTy,
22483 bool FullCheck = true) {
22484 if (SemaRef.RequireCompleteType(Loc: SL, T: QTy, DiagID: diag::err_incomplete_type))
22485 return false;
22486 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
22487 !QTy.isTriviallyCopyableType(Context: SemaRef.Context))
22488 SemaRef.Diag(Loc: SL, DiagID: diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
22489 return true;
22490}
22491
22492/// Return true if it can be proven that the provided array expression
22493/// (array section or array subscript) does NOT specify the whole size of the
22494/// array whose base type is \a BaseQTy.
22495static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
22496 const Expr *E,
22497 QualType BaseQTy) {
22498 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: E);
22499
22500 // If this is an array subscript, it refers to the whole size if the size of
22501 // the dimension is constant and equals 1. Also, an array section assumes the
22502 // format of an array subscript if no colon is used.
22503 if (isa<ArraySubscriptExpr>(Val: E) ||
22504 (OASE && OASE->getColonLocFirst().isInvalid())) {
22505 if (const auto *ATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr()))
22506 return ATy->getSExtSize() != 1;
22507 // Size can't be evaluated statically.
22508 return false;
22509 }
22510
22511 assert(OASE && "Expecting array section if not an array subscript.");
22512 const Expr *LowerBound = OASE->getLowerBound();
22513 const Expr *Length = OASE->getLength();
22514
22515 // If there is a lower bound that does not evaluates to zero, we are not
22516 // covering the whole dimension.
22517 if (LowerBound) {
22518 Expr::EvalResult Result;
22519 if (!LowerBound->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
22520 return false; // Can't get the integer value as a constant.
22521
22522 llvm::APSInt ConstLowerBound = Result.Val.getInt();
22523 if (ConstLowerBound.getSExtValue())
22524 return true;
22525 }
22526
22527 // If we don't have a length we covering the whole dimension.
22528 if (!Length)
22529 return false;
22530
22531 // If the base is a pointer, we don't have a way to get the size of the
22532 // pointee.
22533 if (BaseQTy->isPointerType())
22534 return false;
22535
22536 // We can only check if the length is the same as the size of the dimension
22537 // if we have a constant array.
22538 const auto *CATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr());
22539 if (!CATy)
22540 return false;
22541
22542 Expr::EvalResult Result;
22543 if (!Length->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
22544 return false; // Can't get the integer value as a constant.
22545
22546 llvm::APSInt ConstLength = Result.Val.getInt();
22547 return CATy->getSExtSize() != ConstLength.getSExtValue();
22548}
22549
22550// Return true if it can be proven that the provided array expression (array
22551// section or array subscript) does NOT specify a single element of the array
22552// whose base type is \a BaseQTy.
22553static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
22554 const Expr *E,
22555 QualType BaseQTy) {
22556 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: E);
22557
22558 // An array subscript always refer to a single element. Also, an array section
22559 // assumes the format of an array subscript if no colon is used.
22560 if (isa<ArraySubscriptExpr>(Val: E) ||
22561 (OASE && OASE->getColonLocFirst().isInvalid()))
22562 return false;
22563
22564 assert(OASE && "Expecting array section if not an array subscript.");
22565 const Expr *Length = OASE->getLength();
22566
22567 // If we don't have a length we have to check if the array has unitary size
22568 // for this dimension. Also, we should always expect a length if the base type
22569 // is pointer.
22570 if (!Length) {
22571 if (const auto *ATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr()))
22572 return ATy->getSExtSize() != 1;
22573 // We cannot assume anything.
22574 return false;
22575 }
22576
22577 // Check if the length evaluates to 1.
22578 Expr::EvalResult Result;
22579 if (!Length->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
22580 return false; // Can't get the integer value as a constant.
22581
22582 llvm::APSInt ConstLength = Result.Val.getInt();
22583 return ConstLength.getSExtValue() != 1;
22584}
22585
22586// The base of elements of list in a map clause have to be either:
22587// - a reference to variable or field.
22588// - a member expression.
22589// - an array expression.
22590//
22591// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
22592// reference to 'r'.
22593//
22594// If we have:
22595//
22596// struct SS {
22597// Bla S;
22598// foo() {
22599// #pragma omp target map (S.Arr[:12]);
22600// }
22601// }
22602//
22603// We want to retrieve the member expression 'this->S';
22604
22605// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
22606// If a list item is an array section, it must specify contiguous storage.
22607//
22608// For this restriction it is sufficient that we make sure only references
22609// to variables or fields and array expressions, and that no array sections
22610// exist except in the rightmost expression (unless they cover the whole
22611// dimension of the array). E.g. these would be invalid:
22612//
22613// r.ArrS[3:5].Arr[6:7]
22614//
22615// r.ArrS[3:5].x
22616//
22617// but these would be valid:
22618// r.ArrS[3].Arr[6:7]
22619//
22620// r.ArrS[3].x
22621namespace {
22622class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
22623 Sema &SemaRef;
22624 OpenMPClauseKind CKind = OMPC_unknown;
22625 OpenMPDirectiveKind DKind = OMPD_unknown;
22626 OMPClauseMappableExprCommon::MappableExprComponentList &Components;
22627 bool IsNonContiguous = false;
22628 bool NoDiagnose = false;
22629 const Expr *RelevantExpr = nullptr;
22630 bool AllowUnitySizeArraySection = true;
22631 bool AllowWholeSizeArraySection = true;
22632 bool AllowAnotherPtr = true;
22633 SourceLocation ELoc;
22634 SourceRange ERange;
22635
22636 void emitErrorMsg() {
22637 // If nothing else worked, this is not a valid map clause expression.
22638 if (SemaRef.getLangOpts().OpenMP < 50) {
22639 SemaRef.Diag(Loc: ELoc,
22640 DiagID: diag::err_omp_expected_named_var_member_or_array_expression)
22641 << ERange;
22642 } else {
22643 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22644 << getOpenMPClauseNameForDiag(C: CKind) << ERange;
22645 }
22646 }
22647
22648public:
22649 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
22650 if (!isa<VarDecl>(Val: DRE->getDecl())) {
22651 emitErrorMsg();
22652 return false;
22653 }
22654 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22655 RelevantExpr = DRE;
22656 // Record the component.
22657 Components.emplace_back(Args&: DRE, Args: DRE->getDecl(), Args&: IsNonContiguous);
22658 return true;
22659 }
22660
22661 bool VisitMemberExpr(MemberExpr *ME) {
22662 Expr *E = ME;
22663 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
22664
22665 if (isa<CXXThisExpr>(Val: BaseE)) {
22666 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22667 // We found a base expression: this->Val.
22668 RelevantExpr = ME;
22669 } else {
22670 E = BaseE;
22671 }
22672
22673 if (!isa<FieldDecl>(Val: ME->getMemberDecl())) {
22674 if (!NoDiagnose) {
22675 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_access_to_data_field)
22676 << ME->getSourceRange();
22677 return false;
22678 }
22679 if (RelevantExpr)
22680 return false;
22681 return Visit(S: E);
22682 }
22683
22684 auto *FD = cast<FieldDecl>(Val: ME->getMemberDecl());
22685
22686 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
22687 // A bit-field cannot appear in a map clause.
22688 //
22689 if (FD->isBitField()) {
22690 if (!NoDiagnose) {
22691 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_bit_fields_forbidden_in_clause)
22692 << ME->getSourceRange() << getOpenMPClauseNameForDiag(C: CKind);
22693 return false;
22694 }
22695 if (RelevantExpr)
22696 return false;
22697 return Visit(S: E);
22698 }
22699
22700 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22701 // If the type of a list item is a reference to a type T then the type
22702 // will be considered to be T for all purposes of this clause.
22703 QualType CurType = BaseE->getType().getNonReferenceType();
22704
22705 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
22706 // A list item cannot be a variable that is a member of a structure with
22707 // a union type.
22708 //
22709 if (CurType->isUnionType()) {
22710 if (!NoDiagnose) {
22711 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_union_type_not_allowed)
22712 << ME->getSourceRange();
22713 return false;
22714 }
22715 return RelevantExpr || Visit(S: E);
22716 }
22717
22718 // If we got a member expression, we should not expect any array section
22719 // before that:
22720 //
22721 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
22722 // If a list item is an element of a structure, only the rightmost symbol
22723 // of the variable reference can be an array section.
22724 //
22725 AllowUnitySizeArraySection = false;
22726 AllowWholeSizeArraySection = false;
22727
22728 // Record the component.
22729 Components.emplace_back(Args&: ME, Args&: FD, Args&: IsNonContiguous);
22730 return RelevantExpr || Visit(S: E);
22731 }
22732
22733 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
22734 Expr *E = AE->getBase()->IgnoreParenImpCasts();
22735
22736 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
22737 if (!NoDiagnose) {
22738 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
22739 << 0 << AE->getSourceRange();
22740 return false;
22741 }
22742 return RelevantExpr || Visit(S: E);
22743 }
22744
22745 // If we got an array subscript that express the whole dimension we
22746 // can have any array expressions before. If it only expressing part of
22747 // the dimension, we can only have unitary-size array expressions.
22748 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, E: AE, BaseQTy: E->getType()))
22749 AllowWholeSizeArraySection = false;
22750
22751 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E->IgnoreParenCasts())) {
22752 Expr::EvalResult Result;
22753 if (!AE->getIdx()->isValueDependent() &&
22754 AE->getIdx()->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()) &&
22755 !Result.Val.getInt().isZero()) {
22756 SemaRef.Diag(Loc: AE->getIdx()->getExprLoc(),
22757 DiagID: diag::err_omp_invalid_map_this_expr);
22758 SemaRef.Diag(Loc: AE->getIdx()->getExprLoc(),
22759 DiagID: diag::note_omp_invalid_subscript_on_this_ptr_map);
22760 }
22761 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22762 RelevantExpr = TE;
22763 }
22764
22765 // Record the component - we don't have any declaration associated.
22766 Components.emplace_back(Args&: AE, Args: nullptr, Args&: IsNonContiguous);
22767
22768 return RelevantExpr || Visit(S: E);
22769 }
22770
22771 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
22772 // After OMP 5.0 Array section in reduction clause will be implicitly
22773 // mapped
22774 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
22775 "Array sections cannot be implicitly mapped.");
22776 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22777 QualType CurType =
22778 ArraySectionExpr::getBaseOriginalType(Base: E).getCanonicalType();
22779
22780 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22781 // If the type of a list item is a reference to a type T then the type
22782 // will be considered to be T for all purposes of this clause.
22783 if (CurType->isReferenceType())
22784 CurType = CurType->getPointeeType();
22785
22786 bool IsPointer = CurType->isAnyPointerType();
22787
22788 if (!IsPointer && !CurType->isArrayType()) {
22789 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
22790 << 0 << OASE->getSourceRange();
22791 return false;
22792 }
22793
22794 bool NotWhole =
22795 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, E: OASE, BaseQTy: CurType);
22796 bool NotUnity =
22797 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, E: OASE, BaseQTy: CurType);
22798
22799 if (AllowWholeSizeArraySection) {
22800 // Any array section is currently allowed. Allowing a whole size array
22801 // section implies allowing a unity array section as well.
22802 //
22803 // If this array section refers to the whole dimension we can still
22804 // accept other array sections before this one, except if the base is a
22805 // pointer. Otherwise, only unitary sections are accepted.
22806 if (NotWhole || IsPointer)
22807 AllowWholeSizeArraySection = false;
22808 } else if (DKind == OMPD_target_update &&
22809 SemaRef.getLangOpts().OpenMP >= 50) {
22810 if (IsPointer && !AllowAnotherPtr)
22811 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_section_length_undefined)
22812 << /*array of unknown bound */ 1;
22813 else
22814 IsNonContiguous = true;
22815 } else if (AllowUnitySizeArraySection && NotUnity) {
22816 // A unity or whole array section is not allowed and that is not
22817 // compatible with the properties of the current array section.
22818 if (NoDiagnose)
22819 return false;
22820 SemaRef.Diag(Loc: ELoc,
22821 DiagID: diag::err_array_section_does_not_specify_contiguous_storage)
22822 << OASE->getSourceRange();
22823 return false;
22824 }
22825
22826 if (IsPointer)
22827 AllowAnotherPtr = false;
22828
22829 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E)) {
22830 Expr::EvalResult ResultR;
22831 Expr::EvalResult ResultL;
22832 if (!OASE->getLength()->isValueDependent() &&
22833 OASE->getLength()->EvaluateAsInt(Result&: ResultR, Ctx: SemaRef.getASTContext()) &&
22834 !ResultR.Val.getInt().isOne()) {
22835 SemaRef.Diag(Loc: OASE->getLength()->getExprLoc(),
22836 DiagID: diag::err_omp_invalid_map_this_expr);
22837 SemaRef.Diag(Loc: OASE->getLength()->getExprLoc(),
22838 DiagID: diag::note_omp_invalid_length_on_this_ptr_mapping);
22839 }
22840 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
22841 OASE->getLowerBound()->EvaluateAsInt(Result&: ResultL,
22842 Ctx: SemaRef.getASTContext()) &&
22843 !ResultL.Val.getInt().isZero()) {
22844 SemaRef.Diag(Loc: OASE->getLowerBound()->getExprLoc(),
22845 DiagID: diag::err_omp_invalid_map_this_expr);
22846 SemaRef.Diag(Loc: OASE->getLowerBound()->getExprLoc(),
22847 DiagID: diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
22848 }
22849 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22850 RelevantExpr = TE;
22851 }
22852
22853 // Record the component - we don't have any declaration associated.
22854 Components.emplace_back(Args&: OASE, Args: nullptr, /*IsNonContiguous=*/Args: false);
22855 return RelevantExpr || Visit(S: E);
22856 }
22857 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
22858 Expr *Base = E->getBase();
22859
22860 // Record the component - we don't have any declaration associated.
22861 Components.emplace_back(Args&: E, Args: nullptr, Args&: IsNonContiguous);
22862
22863 return Visit(S: Base->IgnoreParenImpCasts());
22864 }
22865
22866 bool VisitUnaryOperator(UnaryOperator *UO) {
22867 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
22868 UO->getOpcode() != UO_Deref) {
22869 emitErrorMsg();
22870 return false;
22871 }
22872 if (!RelevantExpr) {
22873 // Record the component if haven't found base decl.
22874 Components.emplace_back(Args&: UO, Args: nullptr, /*IsNonContiguous=*/Args: false);
22875 }
22876 return RelevantExpr || Visit(S: UO->getSubExpr()->IgnoreParenImpCasts());
22877 }
22878 bool VisitBinaryOperator(BinaryOperator *BO) {
22879 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
22880 emitErrorMsg();
22881 return false;
22882 }
22883
22884 // Pointer arithmetic is the only thing we expect to happen here so after we
22885 // make sure the binary operator is a pointer type, the only thing we need
22886 // to do is to visit the subtree that has the same type as root (so that we
22887 // know the other subtree is just an offset)
22888 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
22889 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
22890 Components.emplace_back(Args&: BO, Args: nullptr, Args: false);
22891 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
22892 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
22893 "Either LHS or RHS have base decl inside");
22894 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
22895 return RelevantExpr || Visit(S: LE);
22896 return RelevantExpr || Visit(S: RE);
22897 }
22898 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
22899 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22900 RelevantExpr = CTE;
22901 Components.emplace_back(Args&: CTE, Args: nullptr, Args&: IsNonContiguous);
22902 return true;
22903 }
22904 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
22905 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22906 Components.emplace_back(Args&: COCE, Args: nullptr, Args&: IsNonContiguous);
22907 return true;
22908 }
22909 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
22910 Expr *Source = E->getSourceExpr();
22911 if (!Source) {
22912 emitErrorMsg();
22913 return false;
22914 }
22915 return Visit(S: Source);
22916 }
22917 bool VisitStmt(Stmt *) {
22918 emitErrorMsg();
22919 return false;
22920 }
22921 const Expr *getFoundBase() const { return RelevantExpr; }
22922 explicit MapBaseChecker(
22923 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
22924 OMPClauseMappableExprCommon::MappableExprComponentList &Components,
22925 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
22926 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
22927 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
22928};
22929} // namespace
22930
22931/// Return the expression of the base of the mappable expression or null if it
22932/// cannot be determined and do all the necessary checks to see if the
22933/// expression is valid as a standalone mappable expression. In the process,
22934/// record all the components of the expression.
22935static const Expr *checkMapClauseExpressionBase(
22936 Sema &SemaRef, Expr *E,
22937 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
22938 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
22939 SourceLocation ELoc = E->getExprLoc();
22940 SourceRange ERange = E->getSourceRange();
22941 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
22942 ERange);
22943 if (Checker.Visit(S: E->IgnoreParens())) {
22944 // Check if the highest dimension array section has length specified
22945 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
22946 (CKind == OMPC_to || CKind == OMPC_from)) {
22947 auto CI = CurComponents.rbegin();
22948 auto CE = CurComponents.rend();
22949 for (; CI != CE; ++CI) {
22950 const auto *OASE =
22951 dyn_cast<ArraySectionExpr>(Val: CI->getAssociatedExpression());
22952 if (!OASE)
22953 continue;
22954 if (OASE && OASE->getLength())
22955 break;
22956 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_array_section_does_not_specify_length)
22957 << ERange;
22958 }
22959 }
22960 return Checker.getFoundBase();
22961 }
22962 return nullptr;
22963}
22964
22965// Return true if expression E associated with value VD has conflicts with other
22966// map information.
22967static bool checkMapConflicts(
22968 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
22969 bool CurrentRegionOnly,
22970 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
22971 OpenMPClauseKind CKind) {
22972 assert(VD && E);
22973 SourceLocation ELoc = E->getExprLoc();
22974 SourceRange ERange = E->getSourceRange();
22975
22976 // In order to easily check the conflicts we need to match each component of
22977 // the expression under test with the components of the expressions that are
22978 // already in the stack.
22979
22980 assert(!CurComponents.empty() && "Map clause expression with no components!");
22981 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
22982 "Map clause expression with unexpected base!");
22983
22984 // Variables to help detecting enclosing problems in data environment nests.
22985 bool IsEnclosedByDataEnvironmentExpr = false;
22986 const Expr *EnclosingExpr = nullptr;
22987
22988 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
22989 VD, CurrentRegionOnly,
22990 Check: [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
22991 ERange, CKind, &EnclosingExpr,
22992 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
22993 StackComponents,
22994 OpenMPClauseKind Kind) {
22995 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
22996 return false;
22997 assert(!StackComponents.empty() &&
22998 "Map clause expression with no components!");
22999 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
23000 "Map clause expression with unexpected base!");
23001 (void)VD;
23002
23003 // The whole expression in the stack.
23004 const Expr *RE = StackComponents.front().getAssociatedExpression();
23005
23006 // Expressions must start from the same base. Here we detect at which
23007 // point both expressions diverge from each other and see if we can
23008 // detect if the memory referred to both expressions is contiguous and
23009 // do not overlap.
23010 auto CI = CurComponents.rbegin();
23011 auto CE = CurComponents.rend();
23012 auto SI = StackComponents.rbegin();
23013 auto SE = StackComponents.rend();
23014 for (; CI != CE && SI != SE; ++CI, ++SI) {
23015
23016 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
23017 // At most one list item can be an array item derived from a given
23018 // variable in map clauses of the same construct.
23019 if (CurrentRegionOnly &&
23020 (isa<ArraySubscriptExpr>(Val: CI->getAssociatedExpression()) ||
23021 isa<ArraySectionExpr>(Val: CI->getAssociatedExpression()) ||
23022 isa<OMPArrayShapingExpr>(Val: CI->getAssociatedExpression())) &&
23023 (isa<ArraySubscriptExpr>(Val: SI->getAssociatedExpression()) ||
23024 isa<ArraySectionExpr>(Val: SI->getAssociatedExpression()) ||
23025 isa<OMPArrayShapingExpr>(Val: SI->getAssociatedExpression()))) {
23026 SemaRef.Diag(Loc: CI->getAssociatedExpression()->getExprLoc(),
23027 DiagID: diag::err_omp_multiple_array_items_in_map_clause)
23028 << CI->getAssociatedExpression()->getSourceRange();
23029 SemaRef.Diag(Loc: SI->getAssociatedExpression()->getExprLoc(),
23030 DiagID: diag::note_used_here)
23031 << SI->getAssociatedExpression()->getSourceRange();
23032 return true;
23033 }
23034
23035 // Do both expressions have the same kind?
23036 if (CI->getAssociatedExpression()->getStmtClass() !=
23037 SI->getAssociatedExpression()->getStmtClass())
23038 break;
23039
23040 // Are we dealing with different variables/fields?
23041 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
23042 break;
23043 }
23044 // Check if the extra components of the expressions in the enclosing
23045 // data environment are redundant for the current base declaration.
23046 // If they are, the maps completely overlap, which is legal.
23047 for (; SI != SE; ++SI) {
23048 QualType Type;
23049 if (const auto *ASE =
23050 dyn_cast<ArraySubscriptExpr>(Val: SI->getAssociatedExpression())) {
23051 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
23052 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
23053 Val: SI->getAssociatedExpression())) {
23054 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
23055 Type = ArraySectionExpr::getBaseOriginalType(Base: E).getCanonicalType();
23056 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
23057 Val: SI->getAssociatedExpression())) {
23058 Type = OASE->getBase()->getType()->getPointeeType();
23059 }
23060 if (Type.isNull() || Type->isAnyPointerType() ||
23061 checkArrayExpressionDoesNotReferToWholeSize(
23062 SemaRef, E: SI->getAssociatedExpression(), BaseQTy: Type))
23063 break;
23064 }
23065
23066 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
23067 // List items of map clauses in the same construct must not share
23068 // original storage.
23069 //
23070 // If the expressions are exactly the same or one is a subset of the
23071 // other, it means they are sharing storage.
23072 if (CI == CE && SI == SE) {
23073 if (CurrentRegionOnly) {
23074 if (CKind == OMPC_map) {
23075 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << ERange;
23076 } else {
23077 assert(CKind == OMPC_to || CKind == OMPC_from);
23078 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced_in_target_update)
23079 << ERange;
23080 }
23081 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
23082 << RE->getSourceRange();
23083 return true;
23084 }
23085 // If we find the same expression in the enclosing data environment,
23086 // that is legal.
23087 IsEnclosedByDataEnvironmentExpr = true;
23088 return false;
23089 }
23090
23091 QualType DerivedType =
23092 std::prev(x: CI)->getAssociatedDeclaration()->getType();
23093 SourceLocation DerivedLoc =
23094 std::prev(x: CI)->getAssociatedExpression()->getExprLoc();
23095
23096 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
23097 // If the type of a list item is a reference to a type T then the type
23098 // will be considered to be T for all purposes of this clause.
23099 DerivedType = DerivedType.getNonReferenceType();
23100
23101 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
23102 // A variable for which the type is pointer and an array section
23103 // derived from that variable must not appear as list items of map
23104 // clauses of the same construct.
23105 //
23106 // Also, cover one of the cases in:
23107 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
23108 // If any part of the original storage of a list item has corresponding
23109 // storage in the device data environment, all of the original storage
23110 // must have corresponding storage in the device data environment.
23111 //
23112 if (DerivedType->isAnyPointerType()) {
23113 if (CI == CE || SI == SE) {
23114 SemaRef.Diag(
23115 Loc: DerivedLoc,
23116 DiagID: diag::err_omp_pointer_mapped_along_with_derived_section)
23117 << DerivedLoc;
23118 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
23119 << RE->getSourceRange();
23120 return true;
23121 }
23122 if (CI->getAssociatedExpression()->getStmtClass() !=
23123 SI->getAssociatedExpression()->getStmtClass() ||
23124 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
23125 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
23126 assert(CI != CE && SI != SE);
23127 SemaRef.Diag(Loc: DerivedLoc, DiagID: diag::err_omp_same_pointer_dereferenced)
23128 << DerivedLoc;
23129 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
23130 << RE->getSourceRange();
23131 return true;
23132 }
23133 }
23134
23135 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
23136 // List items of map clauses in the same construct must not share
23137 // original storage.
23138 //
23139 // An expression is a subset of the other.
23140 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
23141 if (CKind == OMPC_map) {
23142 if (CI != CE || SI != SE) {
23143 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
23144 // a pointer.
23145 auto Begin =
23146 CI != CE ? CurComponents.begin() : StackComponents.begin();
23147 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
23148 auto It = Begin;
23149 while (It != End && !It->getAssociatedDeclaration())
23150 std::advance(i&: It, n: 1);
23151 assert(It != End &&
23152 "Expected at least one component with the declaration.");
23153 if (It != Begin && It->getAssociatedDeclaration()
23154 ->getType()
23155 .getCanonicalType()
23156 ->isAnyPointerType()) {
23157 IsEnclosedByDataEnvironmentExpr = false;
23158 EnclosingExpr = nullptr;
23159 return false;
23160 }
23161 }
23162 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << ERange;
23163 } else {
23164 assert(CKind == OMPC_to || CKind == OMPC_from);
23165 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced_in_target_update)
23166 << ERange;
23167 }
23168 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
23169 << RE->getSourceRange();
23170 return true;
23171 }
23172
23173 // The current expression uses the same base as other expression in the
23174 // data environment but does not contain it completely.
23175 if (!CurrentRegionOnly && SI != SE)
23176 EnclosingExpr = RE;
23177
23178 // The current expression is a subset of the expression in the data
23179 // environment.
23180 IsEnclosedByDataEnvironmentExpr |=
23181 (!CurrentRegionOnly && CI != CE && SI == SE);
23182
23183 return false;
23184 });
23185
23186 if (CurrentRegionOnly)
23187 return FoundError;
23188
23189 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
23190 // If any part of the original storage of a list item has corresponding
23191 // storage in the device data environment, all of the original storage must
23192 // have corresponding storage in the device data environment.
23193 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
23194 // If a list item is an element of a structure, and a different element of
23195 // the structure has a corresponding list item in the device data environment
23196 // prior to a task encountering the construct associated with the map clause,
23197 // then the list item must also have a corresponding list item in the device
23198 // data environment prior to the task encountering the construct.
23199 //
23200 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
23201 SemaRef.Diag(Loc: ELoc,
23202 DiagID: diag::err_omp_original_storage_is_shared_and_does_not_contain)
23203 << ERange;
23204 SemaRef.Diag(Loc: EnclosingExpr->getExprLoc(), DiagID: diag::note_used_here)
23205 << EnclosingExpr->getSourceRange();
23206 return true;
23207 }
23208
23209 return FoundError;
23210}
23211
23212// Look up the user-defined mapper given the mapper name and mapped type, and
23213// build a reference to it.
23214static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
23215 CXXScopeSpec &MapperIdScopeSpec,
23216 const DeclarationNameInfo &MapperId,
23217 QualType Type,
23218 Expr *UnresolvedMapper) {
23219 if (MapperIdScopeSpec.isInvalid())
23220 return ExprError();
23221 // Get the actual type for the array type.
23222 if (Type->isArrayType()) {
23223 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
23224 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
23225 }
23226 // Find all user-defined mappers with the given MapperId.
23227 SmallVector<UnresolvedSet<8>, 4> Lookups;
23228 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
23229 Lookup.suppressDiagnostics();
23230 if (S) {
23231 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &MapperIdScopeSpec,
23232 /*ObjectType=*/QualType())) {
23233 NamedDecl *D = Lookup.getRepresentativeDecl();
23234 while (S && !S->isDeclScope(D))
23235 S = S->getParent();
23236 if (S)
23237 S = S->getParent();
23238 Lookups.emplace_back();
23239 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
23240 Lookup.clear();
23241 }
23242 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(Val: UnresolvedMapper)) {
23243 // Extract the user-defined mappers with the given MapperId.
23244 Lookups.push_back(Elt: UnresolvedSet<8>());
23245 for (NamedDecl *D : ULE->decls()) {
23246 auto *DMD = cast<OMPDeclareMapperDecl>(Val: D);
23247 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
23248 Lookups.back().addDecl(D: DMD);
23249 }
23250 }
23251 // Defer the lookup for dependent types. The results will be passed through
23252 // UnresolvedMapper on instantiation.
23253 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
23254 Type->isInstantiationDependentType() ||
23255 Type->containsUnexpandedParameterPack() ||
23256 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
23257 return !D->isInvalidDecl() &&
23258 (D->getType()->isDependentType() ||
23259 D->getType()->isInstantiationDependentType() ||
23260 D->getType()->containsUnexpandedParameterPack());
23261 })) {
23262 UnresolvedSet<8> URS;
23263 for (const UnresolvedSet<8> &Set : Lookups) {
23264 if (Set.empty())
23265 continue;
23266 URS.append(I: Set.begin(), E: Set.end());
23267 }
23268 return UnresolvedLookupExpr::Create(
23269 Context: SemaRef.Context, /*NamingClass=*/nullptr,
23270 QualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: SemaRef.Context), NameInfo: MapperId,
23271 /*ADL=*/RequiresADL: false, Begin: URS.begin(), End: URS.end(), /*KnownDependent=*/false,
23272 /*KnownInstantiationDependent=*/false);
23273 }
23274 SourceLocation Loc = MapperId.getLoc();
23275 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23276 // The type must be of struct, union or class type in C and C++
23277 if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
23278 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
23279 SemaRef.Diag(Loc, DiagID: diag::err_omp_mapper_wrong_type);
23280 return ExprError();
23281 }
23282 // Perform argument dependent lookup.
23283 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
23284 argumentDependentLookup(SemaRef, Id: MapperId, Loc, Ty: Type, Lookups);
23285 // Return the first user-defined mapper with the desired type.
23286 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
23287 Lookups, Gen: [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
23288 if (!D->isInvalidDecl() &&
23289 SemaRef.Context.hasSameType(T1: D->getType(), T2: Type))
23290 return D;
23291 return nullptr;
23292 }))
23293 return SemaRef.BuildDeclRefExpr(D: VD, Ty: Type, VK: VK_LValue, Loc);
23294 // Find the first user-defined mapper with a type derived from the desired
23295 // type.
23296 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
23297 Lookups, Gen: [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
23298 if (!D->isInvalidDecl() &&
23299 SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: D->getType()) &&
23300 !Type.isMoreQualifiedThan(other: D->getType(),
23301 Ctx: SemaRef.getASTContext()))
23302 return D;
23303 return nullptr;
23304 })) {
23305 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
23306 /*DetectVirtual=*/false);
23307 if (SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: VD->getType(), Paths)) {
23308 if (!Paths.isAmbiguous(BaseType: SemaRef.Context.getCanonicalType(
23309 T: VD->getType().getUnqualifiedType()))) {
23310 if (SemaRef.CheckBaseClassAccess(
23311 AccessLoc: Loc, Base: VD->getType(), Derived: Type, Path: Paths.front(),
23312 /*DiagID=*/0) != Sema::AR_inaccessible) {
23313 return SemaRef.BuildDeclRefExpr(D: VD, Ty: Type, VK: VK_LValue, Loc);
23314 }
23315 }
23316 }
23317 }
23318 // Report error if a mapper is specified, but cannot be found.
23319 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
23320 SemaRef.Diag(Loc, DiagID: diag::err_omp_invalid_mapper)
23321 << Type << MapperId.getName();
23322 return ExprError();
23323 }
23324 return ExprEmpty();
23325}
23326
23327namespace {
23328// Utility struct that gathers all the related lists associated with a mappable
23329// expression.
23330struct MappableVarListInfo {
23331 // The list of expressions.
23332 ArrayRef<Expr *> VarList;
23333 // The list of processed expressions.
23334 SmallVector<Expr *, 16> ProcessedVarList;
23335 // The mappble components for each expression.
23336 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
23337 // The base declaration of the variable.
23338 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
23339 // The reference to the user-defined mapper associated with every expression.
23340 SmallVector<Expr *, 16> UDMapperList;
23341
23342 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
23343 // We have a list of components and base declarations for each entry in the
23344 // variable list.
23345 VarComponents.reserve(N: VarList.size());
23346 VarBaseDeclarations.reserve(N: VarList.size());
23347 }
23348};
23349} // namespace
23350
23351static DeclRefExpr *buildImplicitMap(Sema &S, QualType BaseType,
23352 DSAStackTy *Stack,
23353 SmallVectorImpl<OMPClause *> &Maps) {
23354
23355 const RecordDecl *RD = BaseType->getAsRecordDecl();
23356 SourceRange Range = RD->getSourceRange();
23357 DeclarationNameInfo ImplicitName;
23358 // Dummy variable _s for Mapper.
23359 VarDecl *VD = buildVarDecl(SemaRef&: S, Loc: Range.getEnd(), Type: BaseType, Name: "_s");
23360 DeclRefExpr *MapperVarRef =
23361 buildDeclRefExpr(S, D: VD, Ty: BaseType, Loc: SourceLocation());
23362
23363 // Create implicit map clause for mapper.
23364 SmallVector<Expr *, 4> SExprs;
23365 for (auto *FD : RD->fields()) {
23366 Expr *BE = S.BuildMemberExpr(
23367 Base: MapperVarRef, /*IsArrow=*/false, OpLoc: Range.getBegin(),
23368 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: Range.getBegin(), Member: FD,
23369 FoundDecl: DeclAccessPair::make(D: FD, AS: FD->getAccess()),
23370 /*HadMultipleCandidates=*/false,
23371 MemberNameInfo: DeclarationNameInfo(FD->getDeclName(), FD->getSourceRange().getBegin()),
23372 Ty: FD->getType(), VK: VK_LValue, OK: OK_Ordinary);
23373 SExprs.push_back(Elt: BE);
23374 }
23375 CXXScopeSpec MapperIdScopeSpec;
23376 DeclarationNameInfo MapperId;
23377 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
23378
23379 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
23380 IteratorModifier: nullptr, MapTypeModifiers: OMPC_MAP_MODIFIER_unknown, MapTypeModifiersLoc: SourceLocation(), MapperIdScopeSpec,
23381 MapperId, MapType: DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
23382 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(), VarList: SExprs,
23383 Locs: OMPVarListLocTy());
23384 Maps.push_back(Elt: MapClause);
23385 return MapperVarRef;
23386}
23387
23388static ExprResult buildImplicitMapper(Sema &S, QualType BaseType,
23389 DSAStackTy *Stack) {
23390
23391 // Build impilicit map for mapper
23392 SmallVector<OMPClause *, 4> Maps;
23393 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
23394
23395 const RecordDecl *RD = BaseType->getAsRecordDecl();
23396 // AST context is RD's ParentASTContext().
23397 ASTContext &Ctx = RD->getParentASTContext();
23398 // DeclContext is RD's DeclContext.
23399 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
23400
23401 // Create implicit default mapper for "RD".
23402 DeclarationName MapperId;
23403 auto &DeclNames = Ctx.DeclarationNames;
23404 MapperId = DeclNames.getIdentifier(ID: &Ctx.Idents.get(Name: "default"));
23405 auto *DMD = OMPDeclareMapperDecl::Create(C&: Ctx, DC: DCT, L: SourceLocation(), Name: MapperId,
23406 T: BaseType, VarName: MapperId, Clauses: Maps, PrevDeclInScope: nullptr);
23407 Scope *Scope = S.getScopeForContext(Ctx: DCT);
23408 if (Scope)
23409 S.PushOnScopeChains(D: DMD, S: Scope, /*AddToContext=*/false);
23410 DCT->addDecl(D: DMD);
23411 DMD->setAccess(clang::AS_none);
23412 auto *VD = cast<DeclRefExpr>(Val: MapperVarRef)->getDecl();
23413 VD->setDeclContext(DMD);
23414 VD->setLexicalDeclContext(DMD);
23415 DMD->addDecl(D: VD);
23416 DMD->setMapperVarRef(MapperVarRef);
23417 FieldDecl *FD = *RD->field_begin();
23418 // create mapper refence.
23419 return DeclRefExpr::Create(Context: Ctx, QualifierLoc: NestedNameSpecifierLoc{}, TemplateKWLoc: FD->getLocation(),
23420 D: DMD, RefersToEnclosingVariableOrCapture: false, NameLoc: SourceLocation(), T: BaseType, VK: VK_LValue);
23421}
23422
23423// Look up the user-defined mapper given the mapper name and mapper type,
23424// return true if found one.
23425static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
23426 CXXScopeSpec &MapperIdScopeSpec,
23427 const DeclarationNameInfo &MapperId,
23428 QualType Type) {
23429 // Find all user-defined mappers with the given MapperId.
23430 SmallVector<UnresolvedSet<8>, 4> Lookups;
23431 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
23432 Lookup.suppressDiagnostics();
23433 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &MapperIdScopeSpec,
23434 /*ObjectType=*/QualType())) {
23435 NamedDecl *D = Lookup.getRepresentativeDecl();
23436 while (S && !S->isDeclScope(D))
23437 S = S->getParent();
23438 if (S)
23439 S = S->getParent();
23440 Lookups.emplace_back();
23441 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
23442 Lookup.clear();
23443 }
23444 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
23445 Type->isInstantiationDependentType() ||
23446 Type->containsUnexpandedParameterPack() ||
23447 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
23448 return !D->isInvalidDecl() &&
23449 (D->getType()->isDependentType() ||
23450 D->getType()->isInstantiationDependentType() ||
23451 D->getType()->containsUnexpandedParameterPack());
23452 }))
23453 return false;
23454 // Perform argument dependent lookup.
23455 SourceLocation Loc = MapperId.getLoc();
23456 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
23457 argumentDependentLookup(SemaRef, Id: MapperId, Loc, Ty: Type, Lookups);
23458 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
23459 Lookups, Gen: [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
23460 if (!D->isInvalidDecl() &&
23461 SemaRef.Context.hasSameType(T1: D->getType(), T2: Type))
23462 return D;
23463 return nullptr;
23464 }))
23465 return true;
23466 // Find the first user-defined mapper with a type derived from the desired
23467 // type.
23468 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
23469 Lookups, Gen: [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
23470 if (!D->isInvalidDecl() &&
23471 SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: D->getType()) &&
23472 !Type.isMoreQualifiedThan(other: D->getType(), Ctx: SemaRef.getASTContext()))
23473 return D;
23474 return nullptr;
23475 });
23476 if (!VD)
23477 return false;
23478 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
23479 /*DetectVirtual=*/false);
23480 if (SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: VD->getType(), Paths)) {
23481 bool IsAmbiguous = !Paths.isAmbiguous(
23482 BaseType: SemaRef.Context.getCanonicalType(T: VD->getType().getUnqualifiedType()));
23483 if (IsAmbiguous)
23484 return false;
23485 if (SemaRef.CheckBaseClassAccess(AccessLoc: Loc, Base: VD->getType(), Derived: Type, Path: Paths.front(),
23486 /*DiagID=*/0) != Sema::AR_inaccessible)
23487 return true;
23488 }
23489 return false;
23490}
23491
23492static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
23493 QualType CanonType, const Expr *E) {
23494
23495 // DFS over data members in structures/classes.
23496 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(1,
23497 {CanonType, nullptr});
23498 llvm::DenseMap<const Type *, bool> Visited;
23499 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
23500 while (!Types.empty()) {
23501 auto [BaseType, CurFD] = Types.pop_back_val();
23502 while (ParentChain.back().second == 0)
23503 ParentChain.pop_back();
23504 --ParentChain.back().second;
23505 if (BaseType.isNull())
23506 continue;
23507 // Only structs/classes are allowed to have mappers.
23508 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
23509 if (!RD)
23510 continue;
23511 auto It = Visited.find(Val: BaseType.getTypePtr());
23512 if (It == Visited.end()) {
23513 // Try to find the associated user-defined mapper.
23514 CXXScopeSpec MapperIdScopeSpec;
23515 DeclarationNameInfo DefaultMapperId;
23516 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
23517 ID: &S.Context.Idents.get(Name: "default")));
23518 DefaultMapperId.setLoc(E->getExprLoc());
23519 bool HasUDMapper =
23520 hasUserDefinedMapper(SemaRef&: S, S: Stack->getCurScope(), MapperIdScopeSpec,
23521 MapperId: DefaultMapperId, Type: BaseType);
23522 It = Visited.try_emplace(Key: BaseType.getTypePtr(), Args&: HasUDMapper).first;
23523 }
23524 // Found default mapper.
23525 if (It->second)
23526 return true;
23527 // Check for the "default" mapper for data members.
23528 bool FirstIter = true;
23529 for (FieldDecl *FD : RD->fields()) {
23530 if (!FD)
23531 continue;
23532 QualType FieldTy = FD->getType();
23533 if (FieldTy.isNull() ||
23534 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
23535 continue;
23536 if (FirstIter) {
23537 FirstIter = false;
23538 ParentChain.emplace_back(Args&: CurFD, Args: 1);
23539 } else {
23540 ++ParentChain.back().second;
23541 }
23542 Types.emplace_back(Args&: FieldTy, Args&: FD);
23543 }
23544 }
23545 return false;
23546}
23547
23548// Check the validity of the provided variable list for the provided clause kind
23549// \a CKind. In the check process the valid expressions, mappable expression
23550// components, variables, and user-defined mappers are extracted and used to
23551// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
23552// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
23553// and \a MapperId are expected to be valid if the clause kind is 'map'.
23554static void checkMappableExpressionList(
23555 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
23556 MappableVarListInfo &MVLI, SourceLocation StartLoc,
23557 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
23558 ArrayRef<Expr *> UnresolvedMappers,
23559 OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
23560 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
23561 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
23562 // We only expect mappable expressions in 'to', 'from', 'map', and
23563 // 'use_device_addr' clauses.
23564 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from ||
23565 CKind == OMPC_use_device_addr) &&
23566 "Unexpected clause kind with mappable expressions!");
23567 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
23568
23569 // If the identifier of user-defined mapper is not specified, it is "default".
23570 // We do not change the actual name in this clause to distinguish whether a
23571 // mapper is specified explicitly, i.e., it is not explicitly specified when
23572 // MapperId.getName() is empty.
23573 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
23574 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
23575 MapperId.setName(DeclNames.getIdentifier(
23576 ID: &SemaRef.getASTContext().Idents.get(Name: "default")));
23577 MapperId.setLoc(StartLoc);
23578 }
23579
23580 // Iterators to find the current unresolved mapper expression.
23581 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
23582 bool UpdateUMIt = false;
23583 Expr *UnresolvedMapper = nullptr;
23584
23585 bool HasHoldModifier =
23586 llvm::is_contained(Range&: Modifiers, Element: OMPC_MAP_MODIFIER_ompx_hold);
23587
23588 // Keep track of the mappable components and base declarations in this clause.
23589 // Each entry in the list is going to have a list of components associated. We
23590 // record each set of the components so that we can build the clause later on.
23591 // In the end we should have the same amount of declarations and component
23592 // lists.
23593
23594 for (Expr *RE : MVLI.VarList) {
23595 assert(RE && "Null expr in omp to/from/map clause");
23596 SourceLocation ELoc = RE->getExprLoc();
23597
23598 // Find the current unresolved mapper expression.
23599 if (UpdateUMIt && UMIt != UMEnd) {
23600 UMIt++;
23601 assert(
23602 UMIt != UMEnd &&
23603 "Expect the size of UnresolvedMappers to match with that of VarList");
23604 }
23605 UpdateUMIt = true;
23606 if (UMIt != UMEnd)
23607 UnresolvedMapper = *UMIt;
23608
23609 const Expr *VE = RE->IgnoreParenLValueCasts();
23610
23611 if (VE->isValueDependent() || VE->isTypeDependent() ||
23612 VE->isInstantiationDependent() ||
23613 VE->containsUnexpandedParameterPack()) {
23614 // Try to find the associated user-defined mapper.
23615 ExprResult ER = buildUserDefinedMapperRef(
23616 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23617 Type: VE->getType().getCanonicalType(), UnresolvedMapper);
23618 if (ER.isInvalid())
23619 continue;
23620 MVLI.UDMapperList.push_back(Elt: ER.get());
23621 // We can only analyze this information once the missing information is
23622 // resolved.
23623 MVLI.ProcessedVarList.push_back(Elt: RE);
23624 continue;
23625 }
23626
23627 Expr *SimpleExpr = RE->IgnoreParenCasts();
23628
23629 if (!RE->isLValue()) {
23630 if (SemaRef.getLangOpts().OpenMP < 50) {
23631 SemaRef.Diag(
23632 Loc: ELoc, DiagID: diag::err_omp_expected_named_var_member_or_array_expression)
23633 << RE->getSourceRange();
23634 } else {
23635 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_non_lvalue_in_map_or_motion_clauses)
23636 << getOpenMPClauseNameForDiag(C: CKind) << RE->getSourceRange();
23637 }
23638 continue;
23639 }
23640
23641 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
23642 ValueDecl *CurDeclaration = nullptr;
23643
23644 // Obtain the array or member expression bases if required. Also, fill the
23645 // components array with all the components identified in the process.
23646 const Expr *BE =
23647 checkMapClauseExpressionBase(SemaRef, E: SimpleExpr, CurComponents, CKind,
23648 DKind: DSAS->getCurrentDirective(), NoDiagnose);
23649 if (!BE)
23650 continue;
23651
23652 assert(!CurComponents.empty() &&
23653 "Invalid mappable expression information.");
23654
23655 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: BE)) {
23656 // Add store "this" pointer to class in DSAStackTy for future checking
23657 DSAS->addMappedClassesQualTypes(QT: TE->getType());
23658 // Try to find the associated user-defined mapper.
23659 ExprResult ER = buildUserDefinedMapperRef(
23660 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23661 Type: VE->getType().getCanonicalType(), UnresolvedMapper);
23662 if (ER.isInvalid())
23663 continue;
23664 MVLI.UDMapperList.push_back(Elt: ER.get());
23665 // Skip restriction checking for variable or field declarations
23666 MVLI.ProcessedVarList.push_back(Elt: RE);
23667 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
23668 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
23669 in_end: CurComponents.end());
23670 MVLI.VarBaseDeclarations.push_back(Elt: nullptr);
23671 continue;
23672 }
23673
23674 // For the following checks, we rely on the base declaration which is
23675 // expected to be associated with the last component. The declaration is
23676 // expected to be a variable or a field (if 'this' is being mapped).
23677 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
23678 assert(CurDeclaration && "Null decl on map clause.");
23679 assert(
23680 CurDeclaration->isCanonicalDecl() &&
23681 "Expecting components to have associated only canonical declarations.");
23682
23683 auto *VD = dyn_cast<VarDecl>(Val: CurDeclaration);
23684 const auto *FD = dyn_cast<FieldDecl>(Val: CurDeclaration);
23685
23686 assert((VD || FD) && "Only variables or fields are expected here!");
23687 (void)FD;
23688
23689 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
23690 // threadprivate variables cannot appear in a map clause.
23691 // OpenMP 4.5 [2.10.5, target update Construct]
23692 // threadprivate variables cannot appear in a from clause.
23693 if (VD && DSAS->isThreadPrivate(D: VD)) {
23694 if (NoDiagnose)
23695 continue;
23696 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(D: VD, /*FromParent=*/false);
23697 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_threadprivate_in_clause)
23698 << getOpenMPClauseNameForDiag(C: CKind);
23699 reportOriginalDsa(SemaRef, Stack: DSAS, D: VD, DVar);
23700 continue;
23701 }
23702
23703 // OpenMP 6.0 [7.9.6, map Clause, Restrictions, p. 386]
23704 // A device-local variable must not appear as a list item in a map clause.
23705 if (VD && CKind == OMPC_map) {
23706 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23707 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
23708 if (*Res == OMPDeclareTargetDeclAttr::MT_Local) {
23709 if (NoDiagnose)
23710 continue;
23711 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_device_local_in_clause)
23712 << VD << getOpenMPClauseNameForDiag(C: CKind);
23713 continue;
23714 }
23715 }
23716 }
23717
23718 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23719 // A list item cannot appear in both a map clause and a data-sharing
23720 // attribute clause on the same construct.
23721
23722 // Check conflicts with other map clause expressions. We check the conflicts
23723 // with the current construct separately from the enclosing data
23724 // environment, because the restrictions are different. We only have to
23725 // check conflicts across regions for the map clauses.
23726 if (checkMapConflicts(SemaRef, DSAS, VD: CurDeclaration, E: SimpleExpr,
23727 /*CurrentRegionOnly=*/true, CurComponents, CKind))
23728 break;
23729 if (CKind == OMPC_map &&
23730 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
23731 checkMapConflicts(SemaRef, DSAS, VD: CurDeclaration, E: SimpleExpr,
23732 /*CurrentRegionOnly=*/false, CurComponents, CKind))
23733 break;
23734
23735 // OpenMP 4.5 [2.10.5, target update Construct]
23736 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
23737 // If the type of a list item is a reference to a type T then the type will
23738 // be considered to be T for all purposes of this clause.
23739 auto I = llvm::find_if(
23740 Range&: CurComponents,
23741 P: [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
23742 return MC.getAssociatedDeclaration();
23743 });
23744 assert(I != CurComponents.end() && "Null decl on map clause.");
23745 (void)I;
23746 QualType Type;
23747 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: VE->IgnoreParens());
23748 auto *OASE = dyn_cast<ArraySectionExpr>(Val: VE->IgnoreParens());
23749 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(Val: VE->IgnoreParens());
23750 if (ASE) {
23751 Type = ASE->getType().getNonReferenceType();
23752 } else if (OASE) {
23753 QualType BaseType =
23754 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
23755 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
23756 Type = ATy->getElementType();
23757 else
23758 Type = BaseType->getPointeeType();
23759 Type = Type.getNonReferenceType();
23760 } else if (OAShE) {
23761 Type = OAShE->getBase()->getType()->getPointeeType();
23762 } else {
23763 Type = VE->getType();
23764 }
23765
23766 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
23767 // A list item in a to or from clause must have a mappable type.
23768 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23769 // A list item must have a mappable type.
23770 if (!checkTypeMappable(SL: VE->getExprLoc(), SR: VE->getSourceRange(), SemaRef,
23771 Stack: DSAS, QTy: Type, /*FullCheck=*/true))
23772 continue;
23773
23774 if (CKind == OMPC_map) {
23775 // target enter data
23776 // OpenMP [2.10.2, Restrictions, p. 99]
23777 // A map-type must be specified in all map clauses and must be either
23778 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
23779 // no map type is present.
23780 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
23781 if (DKind == OMPD_target_enter_data &&
23782 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
23783 SemaRef.getLangOpts().OpenMP >= 52)) {
23784 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
23785 << (IsMapTypeImplicit ? 1 : 0)
23786 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
23787 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
23788 continue;
23789 }
23790
23791 // target exit_data
23792 // OpenMP [2.10.3, Restrictions, p. 102]
23793 // A map-type must be specified in all map clauses and must be either
23794 // from, release, or delete. Starting with OpenMP 5.2 the default map
23795 // type is `from` if no map type is present.
23796 if (DKind == OMPD_target_exit_data &&
23797 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
23798 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
23799 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
23800 << (IsMapTypeImplicit ? 1 : 0)
23801 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
23802 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
23803 continue;
23804 }
23805
23806 // The 'ompx_hold' modifier is specifically intended to be used on a
23807 // 'target' or 'target data' directive to prevent data from being unmapped
23808 // during the associated statement. It is not permitted on a 'target
23809 // enter data' or 'target exit data' directive, which have no associated
23810 // statement.
23811 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
23812 HasHoldModifier) {
23813 SemaRef.Diag(Loc: StartLoc,
23814 DiagID: diag::err_omp_invalid_map_type_modifier_for_directive)
23815 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map,
23816 Type: OMPC_MAP_MODIFIER_ompx_hold)
23817 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
23818 continue;
23819 }
23820
23821 // target, target data
23822 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
23823 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
23824 // A map-type in a map clause must be to, from, tofrom or alloc
23825 if ((DKind == OMPD_target_data ||
23826 isOpenMPTargetExecutionDirective(DKind)) &&
23827 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
23828 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
23829 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
23830 << (IsMapTypeImplicit ? 1 : 0)
23831 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
23832 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
23833 continue;
23834 }
23835
23836 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
23837 // A list item cannot appear in both a map clause and a data-sharing
23838 // attribute clause on the same construct
23839 //
23840 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
23841 // A list item cannot appear in both a map clause and a data-sharing
23842 // attribute clause on the same construct unless the construct is a
23843 // combined construct.
23844 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
23845 isOpenMPTargetExecutionDirective(DKind)) ||
23846 DKind == OMPD_target)) {
23847 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(D: VD, /*FromParent=*/false);
23848 if (isOpenMPPrivate(Kind: DVar.CKind)) {
23849 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
23850 << getOpenMPClauseNameForDiag(C: DVar.CKind)
23851 << getOpenMPClauseNameForDiag(C: OMPC_map)
23852 << getOpenMPDirectiveName(D: DSAS->getCurrentDirective(),
23853 Ver: OMPVersion);
23854 reportOriginalDsa(SemaRef, Stack: DSAS, D: CurDeclaration, DVar);
23855 continue;
23856 }
23857 }
23858 }
23859
23860 // Try to find the associated user-defined mapper.
23861 ExprResult ER = buildUserDefinedMapperRef(
23862 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23863 Type: Type.getCanonicalType(), UnresolvedMapper);
23864 if (ER.isInvalid())
23865 continue;
23866
23867 // If no user-defined mapper is found, we need to create an implicit one for
23868 // arrays/array-sections on structs that have members that have
23869 // user-defined mappers. This is needed to ensure that the mapper for the
23870 // member is invoked when mapping each element of the array/array-section.
23871 if (!ER.get()) {
23872 QualType BaseType;
23873
23874 if (isa<ArraySectionExpr>(Val: VE)) {
23875 BaseType = VE->getType().getCanonicalType();
23876 if (BaseType->isSpecificBuiltinType(K: BuiltinType::ArraySection)) {
23877 const auto *OASE = cast<ArraySectionExpr>(Val: VE->IgnoreParenImpCasts());
23878 QualType BType =
23879 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
23880 QualType ElemType;
23881 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
23882 ElemType = ATy->getElementType();
23883 else
23884 ElemType = BType->getPointeeType();
23885 BaseType = ElemType.getCanonicalType();
23886 }
23887 } else if (VE->getType()->isArrayType()) {
23888 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
23889 const QualType ElemType = AT->getElementType();
23890 BaseType = ElemType.getCanonicalType();
23891 }
23892
23893 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
23894 isImplicitMapperNeeded(S&: SemaRef, Stack: DSAS, CanonType: BaseType, E: VE)) {
23895 ER = buildImplicitMapper(S&: SemaRef, BaseType, Stack: DSAS);
23896 }
23897 }
23898 MVLI.UDMapperList.push_back(Elt: ER.get());
23899
23900 // Save the current expression.
23901 MVLI.ProcessedVarList.push_back(Elt: RE);
23902
23903 // Store the components in the stack so that they can be used to check
23904 // against other clauses later on.
23905 DSAS->addMappableExpressionComponents(VD: CurDeclaration, Components: CurComponents,
23906 /*WhereFoundClauseKind=*/OMPC_map);
23907
23908 // Save the components and declaration to create the clause. For purposes of
23909 // the clause creation, any component list that has base 'this' uses
23910 // null as base declaration.
23911 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
23912 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
23913 in_end: CurComponents.end());
23914 MVLI.VarBaseDeclarations.push_back(Elt: isa<MemberExpr>(Val: BE) ? nullptr
23915 : CurDeclaration);
23916 }
23917}
23918
23919OMPClause *SemaOpenMP::ActOnOpenMPMapClause(
23920 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
23921 ArrayRef<SourceLocation> MapTypeModifiersLoc,
23922 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23923 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
23924 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23925 const OMPVarListLocTy &Locs, bool NoDiagnose,
23926 ArrayRef<Expr *> UnresolvedMappers) {
23927 OpenMPMapModifierKind Modifiers[] = {
23928 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
23929 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
23930 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
23931 OMPC_MAP_MODIFIER_unknown};
23932 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
23933
23934 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
23935 K: BuiltinType::OMPIterator))
23936 Diag(Loc: IteratorModifier->getExprLoc(),
23937 DiagID: diag::err_omp_map_modifier_not_iterator);
23938
23939 // Process map-type-modifiers, flag errors for duplicate modifiers.
23940 unsigned Count = 0;
23941 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
23942 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
23943 llvm::is_contained(Range&: Modifiers, Element: MapTypeModifiers[I])) {
23944 Diag(Loc: MapTypeModifiersLoc[I], DiagID: diag::err_omp_duplicate_map_type_modifier);
23945 continue;
23946 }
23947 assert(Count < NumberOfOMPMapClauseModifiers &&
23948 "Modifiers exceed the allowed number of map type modifiers");
23949 Modifiers[Count] = MapTypeModifiers[I];
23950 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
23951 ++Count;
23952 }
23953
23954 MappableVarListInfo MVLI(VarList);
23955 // Per OpenMP 6.0 p299 lines 3-4, a list item with the const specifier and
23956 // no mutable members is ignored for 'from' clauses. A const-qualified
23957 // variable cannot be modified on the device, so copying back to the host
23958 // is unnecessary and potentially unsafe. Strip the FROM component:
23959 // map(tofrom:) -> map(to:), map(from:) -> map(alloc:).
23960 for (auto *E : VarList) {
23961 if ((MapType == OMPC_MAP_from || MapType == OMPC_MAP_tofrom) &&
23962 hasConstQualifiedMappingType(T: E->getType()))
23963 MapType = (MapType == OMPC_MAP_tofrom) ? OMPC_MAP_to : OMPC_MAP_alloc;
23964 }
23965 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_map, MVLI, StartLoc: Locs.StartLoc,
23966 MapperIdScopeSpec, MapperId, UnresolvedMappers,
23967 MapType, Modifiers, IsMapTypeImplicit,
23968 NoDiagnose);
23969
23970 // We need to produce a map clause even if we don't have variables so that
23971 // other diagnostics related with non-existing map clauses are accurate.
23972 return OMPMapClause::Create(
23973 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
23974 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, IteratorModifier, MapModifiers: Modifiers,
23975 MapModifiersLoc: ModifiersLoc, UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()),
23976 MapperId, Type: MapType, TypeIsImplicit: IsMapTypeImplicit, TypeLoc: MapLoc);
23977}
23978
23979QualType SemaOpenMP::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
23980 TypeResult ParsedType) {
23981 assert(ParsedType.isUsable());
23982
23983 QualType ReductionType = SemaRef.GetTypeFromParser(Ty: ParsedType.get());
23984 if (ReductionType.isNull())
23985 return QualType();
23986
23987 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
23988 // A type name in a declare reduction directive cannot be a function type, an
23989 // array type, a reference type, or a type qualified with const, volatile or
23990 // restrict.
23991 if (ReductionType.hasQualifiers()) {
23992 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 0;
23993 return QualType();
23994 }
23995
23996 if (ReductionType->isFunctionType()) {
23997 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 1;
23998 return QualType();
23999 }
24000 if (ReductionType->isReferenceType()) {
24001 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 2;
24002 return QualType();
24003 }
24004 if (ReductionType->isArrayType()) {
24005 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 3;
24006 return QualType();
24007 }
24008 return ReductionType;
24009}
24010
24011SemaOpenMP::DeclGroupPtrTy
24012SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveStart(
24013 Scope *S, DeclContext *DC, DeclarationName Name,
24014 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
24015 AccessSpecifier AS, Decl *PrevDeclInScope) {
24016 SmallVector<Decl *, 8> Decls;
24017 Decls.reserve(N: ReductionTypes.size());
24018
24019 LookupResult Lookup(SemaRef, Name, SourceLocation(),
24020 Sema::LookupOMPReductionName,
24021 SemaRef.forRedeclarationInCurContext());
24022 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
24023 // A reduction-identifier may not be re-declared in the current scope for the
24024 // same type or for a type that is compatible according to the base language
24025 // rules.
24026 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
24027 OMPDeclareReductionDecl *PrevDRD = nullptr;
24028 bool InCompoundScope = true;
24029 if (S != nullptr) {
24030 // Find previous declaration with the same name not referenced in other
24031 // declarations.
24032 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
24033 InCompoundScope =
24034 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
24035 SemaRef.LookupName(R&: Lookup, S);
24036 SemaRef.FilterLookupForScope(R&: Lookup, Ctx: DC, S, /*ConsiderLinkage=*/false,
24037 /*AllowInlineNamespace=*/false);
24038 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
24039 LookupResult::Filter Filter = Lookup.makeFilter();
24040 while (Filter.hasNext()) {
24041 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Val: Filter.next());
24042 if (InCompoundScope) {
24043 UsedAsPrevious.try_emplace(Key: PrevDecl, Args: false);
24044 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
24045 UsedAsPrevious[D] = true;
24046 }
24047 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
24048 PrevDecl->getLocation();
24049 }
24050 Filter.done();
24051 if (InCompoundScope) {
24052 for (const auto &PrevData : UsedAsPrevious) {
24053 if (!PrevData.second) {
24054 PrevDRD = PrevData.first;
24055 break;
24056 }
24057 }
24058 }
24059 } else if (PrevDeclInScope != nullptr) {
24060 auto *PrevDRDInScope = PrevDRD =
24061 cast<OMPDeclareReductionDecl>(Val: PrevDeclInScope);
24062 do {
24063 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
24064 PrevDRDInScope->getLocation();
24065 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
24066 } while (PrevDRDInScope != nullptr);
24067 }
24068 for (const auto &TyData : ReductionTypes) {
24069 const auto I = PreviousRedeclTypes.find(Val: TyData.first.getCanonicalType());
24070 bool Invalid = false;
24071 if (I != PreviousRedeclTypes.end()) {
24072 Diag(Loc: TyData.second, DiagID: diag::err_omp_declare_reduction_redefinition)
24073 << TyData.first;
24074 Diag(Loc: I->second, DiagID: diag::note_previous_definition);
24075 Invalid = true;
24076 }
24077 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
24078 auto *DRD = OMPDeclareReductionDecl::Create(
24079 C&: getASTContext(), DC, L: TyData.second, Name, T: TyData.first, PrevDeclInScope: PrevDRD);
24080 DC->addDecl(D: DRD);
24081 DRD->setAccess(AS);
24082 Decls.push_back(Elt: DRD);
24083 if (Invalid)
24084 DRD->setInvalidDecl();
24085 else
24086 PrevDRD = DRD;
24087 }
24088
24089 return DeclGroupPtrTy::make(
24090 P: DeclGroupRef::Create(C&: getASTContext(), Decls: Decls.begin(), NumDecls: Decls.size()));
24091}
24092
24093void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
24094 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
24095
24096 // Enter new function scope.
24097 SemaRef.PushFunctionScope();
24098 SemaRef.setFunctionHasBranchProtectedScope();
24099 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
24100
24101 if (S != nullptr)
24102 SemaRef.PushDeclContext(S, DC: DRD);
24103 else
24104 SemaRef.CurContext = DRD;
24105
24106 SemaRef.PushExpressionEvaluationContext(
24107 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
24108
24109 QualType ReductionType = DRD->getType();
24110 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
24111 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
24112 // uses semantics of argument handles by value, but it should be passed by
24113 // reference. C lang does not support references, so pass all parameters as
24114 // pointers.
24115 // Create 'T omp_in;' variable.
24116 VarDecl *OmpInParm =
24117 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_in");
24118 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
24119 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
24120 // uses semantics of argument handles by value, but it should be passed by
24121 // reference. C lang does not support references, so pass all parameters as
24122 // pointers.
24123 // Create 'T omp_out;' variable.
24124 VarDecl *OmpOutParm =
24125 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_out");
24126 if (S != nullptr) {
24127 SemaRef.PushOnScopeChains(D: OmpInParm, S);
24128 SemaRef.PushOnScopeChains(D: OmpOutParm, S);
24129 } else {
24130 DRD->addDecl(D: OmpInParm);
24131 DRD->addDecl(D: OmpOutParm);
24132 }
24133 Expr *InE =
24134 ::buildDeclRefExpr(S&: SemaRef, D: OmpInParm, Ty: ReductionType, Loc: D->getLocation());
24135 Expr *OutE =
24136 ::buildDeclRefExpr(S&: SemaRef, D: OmpOutParm, Ty: ReductionType, Loc: D->getLocation());
24137 DRD->setCombinerData(InE, OutE);
24138}
24139
24140void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D,
24141 Expr *Combiner) {
24142 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
24143 SemaRef.DiscardCleanupsInEvaluationContext();
24144 SemaRef.PopExpressionEvaluationContext();
24145
24146 SemaRef.PopDeclContext();
24147 SemaRef.PopFunctionScopeInfo();
24148
24149 if (Combiner != nullptr)
24150 DRD->setCombiner(Combiner);
24151 else
24152 DRD->setInvalidDecl();
24153}
24154
24155VarDecl *SemaOpenMP::ActOnOpenMPDeclareReductionInitializerStart(Scope *S,
24156 Decl *D) {
24157 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
24158
24159 // Enter new function scope.
24160 SemaRef.PushFunctionScope();
24161 SemaRef.setFunctionHasBranchProtectedScope();
24162
24163 if (S != nullptr)
24164 SemaRef.PushDeclContext(S, DC: DRD);
24165 else
24166 SemaRef.CurContext = DRD;
24167
24168 SemaRef.PushExpressionEvaluationContext(
24169 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
24170
24171 QualType ReductionType = DRD->getType();
24172 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
24173 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
24174 // uses semantics of argument handles by value, but it should be passed by
24175 // reference. C lang does not support references, so pass all parameters as
24176 // pointers.
24177 // Create 'T omp_priv;' variable.
24178 VarDecl *OmpPrivParm =
24179 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_priv");
24180 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
24181 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
24182 // uses semantics of argument handles by value, but it should be passed by
24183 // reference. C lang does not support references, so pass all parameters as
24184 // pointers.
24185 // Create 'T omp_orig;' variable.
24186 VarDecl *OmpOrigParm =
24187 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_orig");
24188 if (S != nullptr) {
24189 SemaRef.PushOnScopeChains(D: OmpPrivParm, S);
24190 SemaRef.PushOnScopeChains(D: OmpOrigParm, S);
24191 } else {
24192 DRD->addDecl(D: OmpPrivParm);
24193 DRD->addDecl(D: OmpOrigParm);
24194 }
24195 Expr *OrigE =
24196 ::buildDeclRefExpr(S&: SemaRef, D: OmpOrigParm, Ty: ReductionType, Loc: D->getLocation());
24197 Expr *PrivE =
24198 ::buildDeclRefExpr(S&: SemaRef, D: OmpPrivParm, Ty: ReductionType, Loc: D->getLocation());
24199 DRD->setInitializerData(OrigE, PrivE);
24200 return OmpPrivParm;
24201}
24202
24203void SemaOpenMP::ActOnOpenMPDeclareReductionInitializerEnd(
24204 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
24205 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
24206 SemaRef.DiscardCleanupsInEvaluationContext();
24207 SemaRef.PopExpressionEvaluationContext();
24208
24209 SemaRef.PopDeclContext();
24210 SemaRef.PopFunctionScopeInfo();
24211
24212 if (Initializer != nullptr) {
24213 DRD->setInitializer(E: Initializer, IK: OMPDeclareReductionInitKind::Call);
24214 } else if (OmpPrivParm->hasInit()) {
24215 DRD->setInitializer(E: OmpPrivParm->getInit(),
24216 IK: OmpPrivParm->isDirectInit()
24217 ? OMPDeclareReductionInitKind::Direct
24218 : OMPDeclareReductionInitKind::Copy);
24219 } else {
24220 DRD->setInvalidDecl();
24221 }
24222}
24223
24224SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveEnd(
24225 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
24226 for (Decl *D : DeclReductions.get()) {
24227 if (IsValid) {
24228 if (S)
24229 SemaRef.PushOnScopeChains(D: cast<OMPDeclareReductionDecl>(Val: D), S,
24230 /*AddToContext=*/false);
24231 } else {
24232 D->setInvalidDecl();
24233 }
24234 }
24235 return DeclReductions;
24236}
24237
24238TypeResult SemaOpenMP::ActOnOpenMPDeclareMapperVarDecl(Scope *S,
24239 Declarator &D) {
24240 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
24241 QualType T = TInfo->getType();
24242 if (D.isInvalidType())
24243 return true;
24244
24245 if (getLangOpts().CPlusPlus) {
24246 // Check that there are no default arguments (C++ only).
24247 SemaRef.CheckExtraCXXDefaultArguments(D);
24248 }
24249
24250 return SemaRef.CreateParsedType(T, TInfo);
24251}
24252
24253QualType SemaOpenMP::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
24254 TypeResult ParsedType) {
24255 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
24256
24257 QualType MapperType = SemaRef.GetTypeFromParser(Ty: ParsedType.get());
24258 assert(!MapperType.isNull() && "Expect valid mapper type");
24259
24260 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
24261 // The type must be of struct, union or class type in C and C++
24262 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
24263 Diag(Loc: TyLoc, DiagID: diag::err_omp_mapper_wrong_type);
24264 return QualType();
24265 }
24266 return MapperType;
24267}
24268
24269SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareMapperDirective(
24270 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
24271 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
24272 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
24273 LookupResult Lookup(SemaRef, Name, SourceLocation(),
24274 Sema::LookupOMPMapperName,
24275 SemaRef.forRedeclarationInCurContext());
24276 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
24277 // A mapper-identifier may not be redeclared in the current scope for the
24278 // same type or for a type that is compatible according to the base language
24279 // rules.
24280 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
24281 OMPDeclareMapperDecl *PrevDMD = nullptr;
24282 bool InCompoundScope = true;
24283 if (S != nullptr) {
24284 // Find previous declaration with the same name not referenced in other
24285 // declarations.
24286 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
24287 InCompoundScope =
24288 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
24289 SemaRef.LookupName(R&: Lookup, S);
24290 SemaRef.FilterLookupForScope(R&: Lookup, Ctx: DC, S, /*ConsiderLinkage=*/false,
24291 /*AllowInlineNamespace=*/false);
24292 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
24293 LookupResult::Filter Filter = Lookup.makeFilter();
24294 while (Filter.hasNext()) {
24295 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Val: Filter.next());
24296 if (InCompoundScope) {
24297 UsedAsPrevious.try_emplace(Key: PrevDecl, Args: false);
24298 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
24299 UsedAsPrevious[D] = true;
24300 }
24301 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
24302 PrevDecl->getLocation();
24303 }
24304 Filter.done();
24305 if (InCompoundScope) {
24306 for (const auto &PrevData : UsedAsPrevious) {
24307 if (!PrevData.second) {
24308 PrevDMD = PrevData.first;
24309 break;
24310 }
24311 }
24312 }
24313 } else if (PrevDeclInScope) {
24314 auto *PrevDMDInScope = PrevDMD =
24315 cast<OMPDeclareMapperDecl>(Val: PrevDeclInScope);
24316 do {
24317 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
24318 PrevDMDInScope->getLocation();
24319 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
24320 } while (PrevDMDInScope != nullptr);
24321 }
24322 const auto I = PreviousRedeclTypes.find(Val: MapperType.getCanonicalType());
24323 bool Invalid = false;
24324 if (I != PreviousRedeclTypes.end()) {
24325 Diag(Loc: StartLoc, DiagID: diag::err_omp_declare_mapper_redefinition)
24326 << MapperType << Name;
24327 Diag(Loc: I->second, DiagID: diag::note_previous_definition);
24328 Invalid = true;
24329 }
24330 // Build expressions for implicit maps of data members with 'default'
24331 // mappers.
24332 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
24333 if (getLangOpts().OpenMP >= 50)
24334 processImplicitMapsWithDefaultMappers(S&: SemaRef, DSAStack,
24335 Clauses&: ClausesWithImplicit);
24336 auto *DMD = OMPDeclareMapperDecl::Create(C&: getASTContext(), DC, L: StartLoc, Name,
24337 T: MapperType, VarName: VN, Clauses: ClausesWithImplicit,
24338 PrevDeclInScope: PrevDMD);
24339 if (S)
24340 SemaRef.PushOnScopeChains(D: DMD, S);
24341 else
24342 DC->addDecl(D: DMD);
24343 DMD->setAccess(AS);
24344 if (Invalid)
24345 DMD->setInvalidDecl();
24346
24347 auto *VD = cast<DeclRefExpr>(Val: MapperVarRef)->getDecl();
24348 VD->setDeclContext(DMD);
24349 VD->setLexicalDeclContext(DMD);
24350 DMD->addDecl(D: VD);
24351 DMD->setMapperVarRef(MapperVarRef);
24352
24353 return DeclGroupPtrTy::make(P: DeclGroupRef(DMD));
24354}
24355
24356ExprResult SemaOpenMP::ActOnOpenMPDeclareMapperDirectiveVarDecl(
24357 Scope *S, QualType MapperType, SourceLocation StartLoc,
24358 DeclarationName VN) {
24359 TypeSourceInfo *TInfo =
24360 getASTContext().getTrivialTypeSourceInfo(T: MapperType, Loc: StartLoc);
24361 auto *VD = VarDecl::Create(
24362 C&: getASTContext(), DC: getASTContext().getTranslationUnitDecl(), StartLoc,
24363 IdLoc: StartLoc, Id: VN.getAsIdentifierInfo(), T: MapperType, TInfo, S: SC_None);
24364 if (S)
24365 SemaRef.PushOnScopeChains(D: VD, S, /*AddToContext=*/false);
24366 Expr *E = buildDeclRefExpr(S&: SemaRef, D: VD, Ty: MapperType, Loc: StartLoc);
24367 DSAStack->addDeclareMapperVarRef(Ref: E);
24368 return E;
24369}
24370
24371void SemaOpenMP::ActOnOpenMPIteratorVarDecl(VarDecl *VD) {
24372 bool IsGlobalVar =
24373 !VD->isLocalVarDecl() && VD->getDeclContext()->isTranslationUnit();
24374 if (DSAStack->getDeclareMapperVarRef()) {
24375 if (IsGlobalVar)
24376 SemaRef.Consumer.HandleTopLevelDecl(D: DeclGroupRef(VD));
24377 DSAStack->addIteratorVarDecl(VD);
24378 } else {
24379 // Currently, only declare mapper handles global-scope iterator vars.
24380 assert(!IsGlobalVar && "Only declare mapper handles TU-scope iterators.");
24381 }
24382}
24383
24384bool SemaOpenMP::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
24385 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
24386 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
24387 if (const auto *DRE = cast_or_null<DeclRefExpr>(Val: Ref)) {
24388 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
24389 return true;
24390 if (VD->isUsableInConstantExpressions(C: getASTContext()))
24391 return true;
24392 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
24393 return true;
24394 return false;
24395 }
24396 return true;
24397}
24398
24399const ValueDecl *SemaOpenMP::getOpenMPDeclareMapperVarName() const {
24400 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
24401 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
24402}
24403
24404OMPClause *SemaOpenMP::ActOnOpenMPNumTeamsClause(
24405 ArrayRef<Expr *> VarList, OpenMPNumTeamsClauseModifier Modifier,
24406 Expr *ModifierExpr, SourceLocation ModifierLoc, SourceLocation StartLoc,
24407 SourceLocation LParenLoc, SourceLocation EndLoc) {
24408 if (VarList.empty())
24409 return nullptr;
24410
24411 for (Expr *ValExpr : VarList) {
24412 // OpenMP [teams Construct, Restrictions]
24413 // The num_teams expression must evaluate to a positive integer value.
24414 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_num_teams,
24415 /*StrictlyPositive=*/true))
24416 return nullptr;
24417 }
24418
24419 // OpenMP [teams Construct, Restrictions]
24420 // The lower-bound expression in num_teams must evaluate to a positive integer
24421 // value.
24422 if (ModifierExpr) {
24423 assert(Modifier == OMPC_NUMTEAMS_lower_bound && "Unexpected modifier.");
24424
24425 if (getLangOpts().OpenMP < 51) {
24426 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_modifier_requires_version)
24427 << getOpenMPSimpleClauseTypeName(Kind: llvm::omp::OMPC_num_teams, Type: Modifier)
24428 << getOpenMPClauseName(C: llvm::omp::OMPC_num_teams) << "5.1";
24429 return nullptr;
24430 }
24431
24432 if (!isNonNegativeIntegerValue(ValExpr&: ModifierExpr, SemaRef, CKind: OMPC_num_teams,
24433 /*StrictlyPositive=*/true))
24434 return nullptr;
24435
24436 // OpenMP 5.2: Validate lower-bound is less than or equal to upper-bound.
24437 Expr *LowerBound = ModifierExpr;
24438 Expr *UpperBound = VarList[0];
24439
24440 // Check if both are compile-time constants for validation.
24441 if (!LowerBound->isValueDependent() && !UpperBound->isValueDependent() &&
24442 LowerBound->isIntegerConstantExpr(Ctx: getASTContext()) &&
24443 UpperBound->isIntegerConstantExpr(Ctx: getASTContext())) {
24444
24445 // Get the actual constant values.
24446 llvm::APSInt LowerVal =
24447 LowerBound->EvaluateKnownConstInt(Ctx: getASTContext());
24448 llvm::APSInt UpperVal =
24449 UpperBound->EvaluateKnownConstInt(Ctx: getASTContext());
24450
24451 if (LowerVal > UpperVal) {
24452 Diag(Loc: LowerBound->getExprLoc(),
24453 DiagID: diag::err_omp_num_teams_lower_bound_larger)
24454 << LowerBound->getSourceRange() << UpperBound->getSourceRange();
24455 return nullptr;
24456 }
24457 }
24458 }
24459
24460 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24461 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
24462 DKind, CKind: OMPC_num_teams, OpenMPVersion: getLangOpts().OpenMP);
24463 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
24464 return OMPNumTeamsClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
24465 LParenLoc, EndLoc, VL: VarList, Modifier,
24466 ModifierExpr, ModifierLoc,
24467 /*PreInit=*/nullptr);
24468
24469 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24470 SmallVector<Expr *, 3> Vars;
24471 for (Expr *ValExpr : VarList) {
24472 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
24473 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
24474 Vars.push_back(Elt: ValExpr);
24475 }
24476
24477 if (ModifierExpr) {
24478 ModifierExpr = SemaRef.MakeFullExpr(Arg: ModifierExpr).get();
24479 ModifierExpr = tryBuildCapture(SemaRef, Capture: ModifierExpr, Captures).get();
24480 }
24481
24482 Stmt *PreInit = buildPreInits(Context&: getASTContext(), Captures);
24483 return OMPNumTeamsClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
24484 LParenLoc, EndLoc, VL: Vars, Modifier,
24485 ModifierExpr, ModifierLoc, PreInit);
24486}
24487
24488OMPClause *SemaOpenMP::ActOnOpenMPThreadLimitClause(ArrayRef<Expr *> VarList,
24489 SourceLocation StartLoc,
24490 SourceLocation LParenLoc,
24491 SourceLocation EndLoc) {
24492 if (VarList.empty())
24493 return nullptr;
24494
24495 for (Expr *ValExpr : VarList) {
24496 // OpenMP [teams Constrcut, Restrictions]
24497 // The thread_limit expression must evaluate to a positive integer value.
24498 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_thread_limit,
24499 /*StrictlyPositive=*/true))
24500 return nullptr;
24501 }
24502
24503 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24504 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
24505 DKind, CKind: OMPC_thread_limit, OpenMPVersion: getLangOpts().OpenMP);
24506 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
24507 return OMPThreadLimitClause::Create(C: getASTContext(), CaptureRegion,
24508 StartLoc, LParenLoc, EndLoc, VL: VarList,
24509 /*PreInit=*/nullptr);
24510
24511 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24512 SmallVector<Expr *, 3> Vars;
24513 for (Expr *ValExpr : VarList) {
24514 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
24515 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
24516 Vars.push_back(Elt: ValExpr);
24517 }
24518
24519 Stmt *PreInit = buildPreInits(Context&: getASTContext(), Captures);
24520 return OMPThreadLimitClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
24521 LParenLoc, EndLoc, VL: Vars, PreInit);
24522}
24523
24524OMPClause *SemaOpenMP::ActOnOpenMPPriorityClause(Expr *Priority,
24525 SourceLocation StartLoc,
24526 SourceLocation LParenLoc,
24527 SourceLocation EndLoc) {
24528 Expr *ValExpr = Priority;
24529 Stmt *HelperValStmt = nullptr;
24530 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24531
24532 // OpenMP [2.9.1, task Constrcut]
24533 // The priority-value is a non-negative numerical scalar expression.
24534 if (!isNonNegativeIntegerValue(
24535 ValExpr, SemaRef, CKind: OMPC_priority,
24536 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
24537 DSAStack->getCurrentDirective(), CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
24538 return nullptr;
24539
24540 return new (getASTContext()) OMPPriorityClause(
24541 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24542}
24543
24544OMPClause *SemaOpenMP::ActOnOpenMPGrainsizeClause(
24545 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
24546 SourceLocation StartLoc, SourceLocation LParenLoc,
24547 SourceLocation ModifierLoc, SourceLocation EndLoc) {
24548 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
24549 "Unexpected grainsize modifier in OpenMP < 51.");
24550
24551 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
24552 std::string Values = getListOfPossibleValues(K: OMPC_grainsize, /*First=*/0,
24553 Last: OMPC_GRAINSIZE_unknown);
24554 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
24555 << Values << getOpenMPClauseNameForDiag(C: OMPC_grainsize);
24556 return nullptr;
24557 }
24558
24559 Expr *ValExpr = Grainsize;
24560 Stmt *HelperValStmt = nullptr;
24561 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24562
24563 // OpenMP [2.9.2, taskloop Constrcut]
24564 // The parameter of the grainsize clause must be a positive integer
24565 // expression.
24566 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_grainsize,
24567 /*StrictlyPositive=*/true,
24568 /*BuildCapture=*/true,
24569 DSAStack->getCurrentDirective(),
24570 CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
24571 return nullptr;
24572
24573 return new (getASTContext())
24574 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
24575 StartLoc, LParenLoc, ModifierLoc, EndLoc);
24576}
24577
24578OMPClause *SemaOpenMP::ActOnOpenMPNumTasksClause(
24579 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
24580 SourceLocation StartLoc, SourceLocation LParenLoc,
24581 SourceLocation ModifierLoc, SourceLocation EndLoc) {
24582 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
24583 "Unexpected num_tasks modifier in OpenMP < 51.");
24584
24585 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
24586 std::string Values = getListOfPossibleValues(K: OMPC_num_tasks, /*First=*/0,
24587 Last: OMPC_NUMTASKS_unknown);
24588 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
24589 << Values << getOpenMPClauseNameForDiag(C: OMPC_num_tasks);
24590 return nullptr;
24591 }
24592
24593 Expr *ValExpr = NumTasks;
24594 Stmt *HelperValStmt = nullptr;
24595 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24596
24597 // OpenMP [2.9.2, taskloop Constrcut]
24598 // The parameter of the num_tasks clause must be a positive integer
24599 // expression.
24600 if (!isNonNegativeIntegerValue(
24601 ValExpr, SemaRef, CKind: OMPC_num_tasks,
24602 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
24603 DSAStack->getCurrentDirective(), CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
24604 return nullptr;
24605
24606 return new (getASTContext())
24607 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
24608 StartLoc, LParenLoc, ModifierLoc, EndLoc);
24609}
24610
24611OMPClause *SemaOpenMP::ActOnOpenMPHintClause(Expr *Hint,
24612 SourceLocation StartLoc,
24613 SourceLocation LParenLoc,
24614 SourceLocation EndLoc) {
24615 // OpenMP [2.13.2, critical construct, Description]
24616 // ... where hint-expression is an integer constant expression that evaluates
24617 // to a valid lock hint.
24618 ExprResult HintExpr =
24619 VerifyPositiveIntegerConstantInClause(E: Hint, CKind: OMPC_hint, StrictlyPositive: false);
24620 if (HintExpr.isInvalid())
24621 return nullptr;
24622 return new (getASTContext())
24623 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
24624}
24625
24626/// Tries to find omp_event_handle_t type.
24627static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
24628 DSAStackTy *Stack) {
24629 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
24630 if (!OMPEventHandleT.isNull())
24631 return true;
24632 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_event_handle_t");
24633 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
24634 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
24635 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
24636 return false;
24637 }
24638 Stack->setOMPEventHandleT(PT.get());
24639 return true;
24640}
24641
24642OMPClause *SemaOpenMP::ActOnOpenMPDetachClause(Expr *Evt,
24643 SourceLocation StartLoc,
24644 SourceLocation LParenLoc,
24645 SourceLocation EndLoc) {
24646 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
24647 !Evt->isInstantiationDependent() &&
24648 !Evt->containsUnexpandedParameterPack()) {
24649 if (!findOMPEventHandleT(S&: SemaRef, Loc: Evt->getExprLoc(), DSAStack))
24650 return nullptr;
24651 // OpenMP 5.0, 2.10.1 task Construct.
24652 // event-handle is a variable of the omp_event_handle_t type.
24653 auto *Ref = dyn_cast<DeclRefExpr>(Val: Evt->IgnoreParenImpCasts());
24654 if (!Ref) {
24655 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
24656 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
24657 return nullptr;
24658 }
24659 auto *VD = dyn_cast_or_null<VarDecl>(Val: Ref->getDecl());
24660 if (!VD) {
24661 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
24662 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
24663 return nullptr;
24664 }
24665 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
24666 T2: VD->getType()) ||
24667 VD->getType().isConstant(Ctx: getASTContext())) {
24668 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
24669 << "omp_event_handle_t" << 1 << VD->getType()
24670 << Evt->getSourceRange();
24671 return nullptr;
24672 }
24673 // OpenMP 5.0, 2.10.1 task Construct
24674 // [detach clause]... The event-handle will be considered as if it was
24675 // specified on a firstprivate clause.
24676 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
24677 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
24678 DVar.RefExpr) {
24679 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
24680 << getOpenMPClauseNameForDiag(C: DVar.CKind)
24681 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
24682 reportOriginalDsa(SemaRef, DSAStack, D: VD, DVar);
24683 return nullptr;
24684 }
24685 }
24686
24687 return new (getASTContext())
24688 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
24689}
24690
24691OMPClause *SemaOpenMP::ActOnOpenMPDistScheduleClause(
24692 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
24693 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
24694 SourceLocation EndLoc) {
24695 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
24696 std::string Values;
24697 Values += "'";
24698 Values += getOpenMPSimpleClauseTypeName(Kind: OMPC_dist_schedule, Type: 0);
24699 Values += "'";
24700 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
24701 << Values << getOpenMPClauseNameForDiag(C: OMPC_dist_schedule);
24702 return nullptr;
24703 }
24704 Expr *ValExpr = ChunkSize;
24705 Stmt *HelperValStmt = nullptr;
24706 if (ChunkSize) {
24707 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
24708 !ChunkSize->isInstantiationDependent() &&
24709 !ChunkSize->containsUnexpandedParameterPack()) {
24710 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
24711 ExprResult Val =
24712 PerformOpenMPImplicitIntegerConversion(Loc: ChunkSizeLoc, Op: ChunkSize);
24713 if (Val.isInvalid())
24714 return nullptr;
24715
24716 ValExpr = Val.get();
24717
24718 // OpenMP [2.7.1, Restrictions]
24719 // chunk_size must be a loop invariant integer expression with a positive
24720 // value.
24721 if (std::optional<llvm::APSInt> Result =
24722 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
24723 if (Result->isSigned() && !Result->isStrictlyPositive()) {
24724 Diag(Loc: ChunkSizeLoc, DiagID: diag::err_omp_negative_expression_in_clause)
24725 << "dist_schedule" << /*strictly positive*/ 1
24726 << ChunkSize->getSourceRange();
24727 return nullptr;
24728 }
24729 } else if (getOpenMPCaptureRegionForClause(
24730 DSAStack->getCurrentDirective(), CKind: OMPC_dist_schedule,
24731 OpenMPVersion: getLangOpts().OpenMP) != OMPD_unknown &&
24732 !SemaRef.CurContext->isDependentContext()) {
24733 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
24734 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24735 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
24736 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
24737 }
24738 }
24739 }
24740
24741 return new (getASTContext())
24742 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
24743 Kind, ValExpr, HelperValStmt);
24744}
24745
24746OMPClause *SemaOpenMP::ActOnOpenMPDefaultmapClause(
24747 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
24748 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
24749 SourceLocation KindLoc, SourceLocation EndLoc) {
24750 if (getLangOpts().OpenMP < 50) {
24751 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
24752 Kind != OMPC_DEFAULTMAP_scalar) {
24753 std::string Value;
24754 SourceLocation Loc;
24755 Value += "'";
24756 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
24757 Value += getOpenMPSimpleClauseTypeName(Kind: OMPC_defaultmap,
24758 Type: OMPC_DEFAULTMAP_MODIFIER_tofrom);
24759 Loc = MLoc;
24760 } else {
24761 Value += getOpenMPSimpleClauseTypeName(Kind: OMPC_defaultmap,
24762 Type: OMPC_DEFAULTMAP_scalar);
24763 Loc = KindLoc;
24764 }
24765 Value += "'";
24766 Diag(Loc, DiagID: diag::err_omp_unexpected_clause_value)
24767 << Value << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
24768 return nullptr;
24769 }
24770 } else {
24771 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
24772 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
24773 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
24774 if (!isDefaultmapKind || !isDefaultmapModifier) {
24775 StringRef KindValue = getLangOpts().OpenMP < 52
24776 ? "'scalar', 'aggregate', 'pointer'"
24777 : "'scalar', 'aggregate', 'pointer', 'all'";
24778 if (getLangOpts().OpenMP == 50) {
24779 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
24780 "'firstprivate', 'none', 'default'";
24781 if (!isDefaultmapKind && isDefaultmapModifier) {
24782 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
24783 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
24784 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24785 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
24786 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
24787 } else {
24788 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
24789 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
24790 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
24791 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
24792 }
24793 } else {
24794 StringRef ModifierValue =
24795 getLangOpts().OpenMP < 60
24796 ? "'alloc', 'from', 'to', 'tofrom', "
24797 "'firstprivate', 'none', 'default', 'present'"
24798 : "'storage', 'from', 'to', 'tofrom', "
24799 "'firstprivate', 'private', 'none', 'default', 'present'";
24800 if (!isDefaultmapKind && isDefaultmapModifier) {
24801 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
24802 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
24803 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24804 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
24805 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
24806 } else {
24807 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
24808 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
24809 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
24810 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
24811 }
24812 }
24813 return nullptr;
24814 }
24815
24816 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
24817 // At most one defaultmap clause for each category can appear on the
24818 // directive.
24819 if (DSAStack->checkDefaultmapCategory(VariableCategory: Kind)) {
24820 Diag(Loc: StartLoc, DiagID: diag::err_omp_one_defaultmap_each_category);
24821 return nullptr;
24822 }
24823 }
24824 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
24825 // Variable category is not specified - mark all categories.
24826 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_aggregate, Loc: StartLoc);
24827 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_scalar, Loc: StartLoc);
24828 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_pointer, Loc: StartLoc);
24829 } else {
24830 DSAStack->setDefaultDMAAttr(M, Kind, Loc: StartLoc);
24831 }
24832
24833 return new (getASTContext())
24834 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
24835}
24836
24837bool SemaOpenMP::ActOnStartOpenMPDeclareTargetContext(
24838 DeclareTargetContextInfo &DTCI) {
24839 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
24840 if (!CurLexicalContext->isFileContext() &&
24841 !CurLexicalContext->isExternCContext() &&
24842 !CurLexicalContext->isExternCXXContext() &&
24843 !isa<CXXRecordDecl>(Val: CurLexicalContext) &&
24844 !isa<ClassTemplateDecl>(Val: CurLexicalContext) &&
24845 !isa<ClassTemplatePartialSpecializationDecl>(Val: CurLexicalContext) &&
24846 !isa<ClassTemplateSpecializationDecl>(Val: CurLexicalContext)) {
24847 Diag(Loc: DTCI.Loc, DiagID: diag::err_omp_region_not_file_context);
24848 return false;
24849 }
24850
24851 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24852 if (getLangOpts().HIP)
24853 Diag(Loc: DTCI.Loc, DiagID: diag::warn_hip_omp_target_directives);
24854
24855 DeclareTargetNesting.push_back(Elt: DTCI);
24856 return true;
24857}
24858
24859const SemaOpenMP::DeclareTargetContextInfo
24860SemaOpenMP::ActOnOpenMPEndDeclareTargetDirective() {
24861 assert(!DeclareTargetNesting.empty() &&
24862 "check isInOpenMPDeclareTargetContext() first!");
24863 return DeclareTargetNesting.pop_back_val();
24864}
24865
24866void SemaOpenMP::ActOnFinishedOpenMPDeclareTargetContext(
24867 DeclareTargetContextInfo &DTCI) {
24868 for (auto &It : DTCI.ExplicitlyMapped)
24869 ActOnOpenMPDeclareTargetName(ND: It.first, Loc: It.second.Loc, MT: It.second.MT, DTCI);
24870}
24871
24872void SemaOpenMP::DiagnoseUnterminatedOpenMPDeclareTarget() {
24873 if (DeclareTargetNesting.empty())
24874 return;
24875 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
24876 unsigned OMPVersion = getLangOpts().OpenMP;
24877 Diag(Loc: DTCI.Loc, DiagID: diag::warn_omp_unterminated_declare_target)
24878 << getOpenMPDirectiveName(D: DTCI.Kind, Ver: OMPVersion);
24879}
24880
24881NamedDecl *SemaOpenMP::lookupOpenMPDeclareTargetName(
24882 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
24883 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
24884 SemaRef.LookupParsedName(R&: Lookup, S: CurScope, SS: &ScopeSpec,
24885 /*ObjectType=*/QualType(),
24886 /*AllowBuiltinCreation=*/true);
24887
24888 if (Lookup.isAmbiguous())
24889 return nullptr;
24890 Lookup.suppressDiagnostics();
24891
24892 if (!Lookup.isSingleResult()) {
24893 VarOrFuncDeclFilterCCC CCC(SemaRef);
24894 if (TypoCorrection Corrected =
24895 SemaRef.CorrectTypo(Typo: Id, LookupKind: Sema::LookupOrdinaryName, S: CurScope, SS: nullptr,
24896 CCC, Mode: CorrectTypoKind::ErrorRecovery)) {
24897 SemaRef.diagnoseTypo(Correction: Corrected,
24898 TypoDiag: SemaRef.PDiag(DiagID: diag::err_undeclared_var_use_suggest)
24899 << Id.getName());
24900 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: Corrected.getCorrectionDecl());
24901 return nullptr;
24902 }
24903
24904 Diag(Loc: Id.getLoc(), DiagID: diag::err_undeclared_var_use) << Id.getName();
24905 return nullptr;
24906 }
24907
24908 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
24909 if (!isa<VarDecl>(Val: ND) && !isa<FunctionDecl>(Val: ND) &&
24910 !isa<FunctionTemplateDecl>(Val: ND)) {
24911 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_invalid_target_decl) << Id.getName();
24912 return nullptr;
24913 }
24914 return ND;
24915}
24916
24917void SemaOpenMP::ActOnOpenMPDeclareTargetName(
24918 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
24919 DeclareTargetContextInfo &DTCI) {
24920 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
24921 isa<FunctionTemplateDecl>(ND)) &&
24922 "Expected variable, function or function template.");
24923
24924 if (auto *VD = dyn_cast<VarDecl>(Val: ND)) {
24925 // Only global variables can be marked as declare target.
24926 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24927 !VD->isStaticDataMember()) {
24928 Diag(Loc, DiagID: diag::err_omp_declare_target_has_local_vars)
24929 << VD->getNameAsString();
24930 return;
24931 }
24932 }
24933 // Diagnose marking after use as it may lead to incorrect diagnosis and
24934 // codegen.
24935 if (getLangOpts().OpenMP >= 50 &&
24936 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
24937 Diag(Loc, DiagID: diag::warn_omp_declare_target_after_first_use);
24938
24939 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24940 if (getLangOpts().HIP)
24941 Diag(Loc, DiagID: diag::warn_hip_omp_target_directives);
24942
24943 // 'local' is incompatible with 'device_type(host)' because 'local'
24944 // variables exist only on the device.
24945 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
24946 DTCI.DT == OMPDeclareTargetDeclAttr::DT_Host) {
24947 Diag(Loc, DiagID: diag::err_omp_declare_target_local_host_only);
24948 return;
24949 }
24950
24951 // Explicit declare target lists have precedence.
24952 const unsigned Level = -1;
24953
24954 auto *VD = cast<ValueDecl>(Val: ND);
24955 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24956 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24957 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
24958 (*ActiveAttr)->getLevel() == Level) {
24959 Diag(Loc, DiagID: diag::err_omp_device_type_mismatch)
24960 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(Val: DTCI.DT)
24961 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
24962 Val: (*ActiveAttr)->getDevType());
24963 return;
24964 }
24965 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
24966 (*ActiveAttr)->getLevel() == Level) {
24967 Diag(Loc, DiagID: diag::err_omp_declare_target_var_in_both_clauses)
24968 << ND
24969 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(
24970 Val: (*ActiveAttr)->getMapType())
24971 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(Val: MT);
24972 return;
24973 }
24974
24975 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
24976 return;
24977
24978 Expr *IndirectE = nullptr;
24979 bool IsIndirect = false;
24980 if (DTCI.Indirect) {
24981 IndirectE = *DTCI.Indirect;
24982 if (!IndirectE)
24983 IsIndirect = true;
24984 }
24985 // FIXME: 'local' with 'device_type(nohost)' is not yet fully supported
24986 // in codegen. Treat as 'device_type(any)' for now. The variable will
24987 // exist on both host and device, but the host copy is unused.
24988 auto DT = DTCI.DT;
24989 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
24990 DT == OMPDeclareTargetDeclAttr::DT_NoHost) {
24991 Diag(Loc, DiagID: diag::warn_omp_declare_target_local_nohost);
24992 DT = OMPDeclareTargetDeclAttr::DT_Any;
24993 }
24994
24995 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24996 Ctx&: getASTContext(), MapType: MT, DevType: DT, IndirectExpr: IndirectE, Indirect: IsIndirect, Level,
24997 Range: SourceRange(Loc, Loc));
24998 ND->addAttr(A);
24999 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
25000 ML->DeclarationMarkedOpenMPDeclareTarget(D: ND, Attr: A);
25001 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: ND, IdLoc: Loc);
25002 if (auto *VD = dyn_cast<VarDecl>(Val: ND);
25003 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
25004 VD->hasGlobalStorage())
25005 ActOnOpenMPDeclareTargetInitializer(D: ND);
25006}
25007
25008static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
25009 Sema &SemaRef, Decl *D) {
25010 if (!D || !isa<VarDecl>(Val: D))
25011 return;
25012 auto *VD = cast<VarDecl>(Val: D);
25013 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
25014 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
25015 if (SemaRef.LangOpts.OpenMP >= 50 &&
25016 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
25017 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
25018 VD->hasGlobalStorage()) {
25019 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
25020 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter &&
25021 *MapTy != OMPDeclareTargetDeclAttr::MT_Local)) {
25022 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
25023 // If a lambda declaration and definition appears between a
25024 // declare target directive and the matching end declare target
25025 // directive, all variables that are captured by the lambda
25026 // expression must also appear in a to clause.
25027 SemaRef.Diag(Loc: VD->getLocation(),
25028 DiagID: diag::err_omp_lambda_capture_in_declare_target_not_to);
25029 SemaRef.Diag(Loc: SL, DiagID: diag::note_var_explicitly_captured_here)
25030 << VD << 0 << SR;
25031 return;
25032 }
25033 }
25034 if (MapTy)
25035 return;
25036 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::warn_omp_not_in_target_context);
25037 SemaRef.Diag(Loc: SL, DiagID: diag::note_used_here) << SR;
25038}
25039
25040static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
25041 Sema &SemaRef, DSAStackTy *Stack,
25042 ValueDecl *VD) {
25043 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
25044 checkTypeMappable(SL, SR, SemaRef, Stack, QTy: VD->getType(),
25045 /*FullCheck=*/false);
25046}
25047
25048void SemaOpenMP::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
25049 SourceLocation IdLoc) {
25050 if (!D || D->isInvalidDecl())
25051 return;
25052 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
25053 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
25054 if (auto *VD = dyn_cast<VarDecl>(Val: D)) {
25055 // Only global variables can be marked as declare target.
25056 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
25057 !VD->isStaticDataMember())
25058 return;
25059 // 2.10.6: threadprivate variable cannot appear in a declare target
25060 // directive.
25061 if (DSAStack->isThreadPrivate(D: VD)) {
25062 Diag(Loc: SL, DiagID: diag::err_omp_threadprivate_in_target);
25063 reportOriginalDsa(SemaRef, DSAStack, D: VD, DSAStack->getTopDSA(D: VD, FromParent: false));
25064 return;
25065 }
25066 }
25067 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: D))
25068 D = FTD->getTemplatedDecl();
25069 if (auto *FD = dyn_cast<FunctionDecl>(Val: D)) {
25070 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
25071 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD: FD);
25072 if (IdLoc.isValid() && Res &&
25073 (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
25074 *Res == OMPDeclareTargetDeclAttr::MT_Local)) {
25075 Diag(Loc: IdLoc, DiagID: diag::err_omp_function_in_target_clause_list)
25076 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(Val: *Res);
25077 Diag(Loc: FD->getLocation(), DiagID: diag::note_defined_here) << FD;
25078 return;
25079 }
25080 }
25081 if (auto *VD = dyn_cast<ValueDecl>(Val: D)) {
25082 // Problem if any with var declared with incomplete type will be reported
25083 // as normal, so no need to check it here.
25084 if ((E || !VD->getType()->isIncompleteType()) &&
25085 !checkValueDeclInTarget(SL, SR, SemaRef, DSAStack, VD))
25086 return;
25087 if (!E && isInOpenMPDeclareTargetContext()) {
25088 // Checking declaration inside declare target region.
25089 if (isa<VarDecl>(Val: D) || isa<FunctionDecl>(Val: D) ||
25090 isa<FunctionTemplateDecl>(Val: D)) {
25091 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
25092 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
25093 unsigned Level = DeclareTargetNesting.size();
25094 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
25095 return;
25096 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
25097 Expr *IndirectE = nullptr;
25098 bool IsIndirect = false;
25099 if (DTCI.Indirect) {
25100 IndirectE = *DTCI.Indirect;
25101 if (!IndirectE)
25102 IsIndirect = true;
25103 }
25104 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
25105 Ctx&: getASTContext(),
25106 MapType: getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
25107 : OMPDeclareTargetDeclAttr::MT_To,
25108 DevType: DTCI.DT, IndirectExpr: IndirectE, Indirect: IsIndirect, Level,
25109 Range: SourceRange(DTCI.Loc, DTCI.Loc));
25110 D->addAttr(A);
25111 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
25112 ML->DeclarationMarkedOpenMPDeclareTarget(D, Attr: A);
25113 }
25114 return;
25115 }
25116 }
25117 if (!E)
25118 return;
25119 checkDeclInTargetContext(SL: E->getExprLoc(), SR: E->getSourceRange(), SemaRef, D);
25120}
25121
25122/// This class visits every VarDecl that the initializer references and adds
25123/// OMPDeclareTargetDeclAttr to each of them.
25124class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
25125 SmallVector<VarDecl *> DeclVector;
25126 Attr *A;
25127
25128public:
25129 /// A StmtVisitor class function that visits all DeclRefExpr and adds
25130 /// OMPDeclareTargetDeclAttr to them.
25131 void VisitDeclRefExpr(DeclRefExpr *Node) {
25132 if (auto *VD = dyn_cast<VarDecl>(Val: Node->getDecl())) {
25133 VD->addAttr(A);
25134 DeclVector.push_back(Elt: VD);
25135 }
25136 }
25137 /// A function that iterates across each of the Expr's children.
25138 void VisitExpr(Expr *Ex) {
25139 for (auto *Child : Ex->children()) {
25140 Visit(S: Child);
25141 }
25142 }
25143 /// A function that keeps a record of all the Decls that are variables, has
25144 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
25145 /// each Decl one at a time and use the inherited 'visit' functions to look
25146 /// for DeclRefExpr.
25147 void declareTargetInitializer(Decl *TD) {
25148 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
25149 DeclVector.push_back(Elt: cast<VarDecl>(Val: TD));
25150 llvm::SmallDenseSet<Decl *> Visited;
25151 while (!DeclVector.empty()) {
25152 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
25153 if (!Visited.insert(V: TargetVarDecl).second)
25154 continue;
25155
25156 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
25157 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
25158 if (Expr *Ex = TargetVarDecl->getInit())
25159 Visit(S: Ex);
25160 }
25161 }
25162 }
25163};
25164
25165/// Adding OMPDeclareTargetDeclAttr to variables with static storage
25166/// duration that are referenced in the initializer expression list of
25167/// variables with static storage duration in declare target directive.
25168void SemaOpenMP::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) {
25169 GlobalDeclRefChecker Checker;
25170 if (isa<VarDecl>(Val: TargetDecl))
25171 Checker.declareTargetInitializer(TD: TargetDecl);
25172}
25173
25174OMPClause *SemaOpenMP::ActOnOpenMPToClause(
25175 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
25176 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
25177 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
25178 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
25179 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
25180 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
25181 OMPC_MOTION_MODIFIER_unknown,
25182 OMPC_MOTION_MODIFIER_unknown};
25183 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
25184
25185 // Process motion-modifiers, flag errors for duplicate modifiers.
25186 unsigned Count = 0;
25187 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
25188 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
25189 llvm::is_contained(Range&: Modifiers, Element: MotionModifiers[I])) {
25190 Diag(Loc: MotionModifiersLoc[I], DiagID: diag::err_omp_duplicate_motion_modifier);
25191 continue;
25192 }
25193 assert(Count < NumberOfOMPMotionModifiers &&
25194 "Modifiers exceed the allowed number of motion modifiers");
25195 Modifiers[Count] = MotionModifiers[I];
25196 ModifiersLoc[Count] = MotionModifiersLoc[I];
25197 ++Count;
25198 }
25199
25200 MappableVarListInfo MVLI(VarList);
25201 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_to, MVLI, StartLoc: Locs.StartLoc,
25202 MapperIdScopeSpec, MapperId, UnresolvedMappers);
25203 if (MVLI.ProcessedVarList.empty())
25204 return nullptr;
25205 if (IteratorExpr)
25206 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: IteratorExpr))
25207 if (auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
25208 DSAStack->addIteratorVarDecl(VD);
25209 return OMPToClause::Create(
25210 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25211 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, IteratorModifier: IteratorExpr, MotionModifiers: Modifiers,
25212 MotionModifiersLoc: ModifiersLoc, UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()),
25213 MapperId);
25214}
25215
25216OMPClause *SemaOpenMP::ActOnOpenMPFromClause(
25217 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
25218 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
25219 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
25220 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
25221 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
25222 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
25223 OMPC_MOTION_MODIFIER_unknown,
25224 OMPC_MOTION_MODIFIER_unknown};
25225 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
25226
25227 // Process motion-modifiers, flag errors for duplicate modifiers.
25228 unsigned Count = 0;
25229 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
25230 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
25231 llvm::is_contained(Range&: Modifiers, Element: MotionModifiers[I])) {
25232 Diag(Loc: MotionModifiersLoc[I], DiagID: diag::err_omp_duplicate_motion_modifier);
25233 continue;
25234 }
25235 assert(Count < NumberOfOMPMotionModifiers &&
25236 "Modifiers exceed the allowed number of motion modifiers");
25237 Modifiers[Count] = MotionModifiers[I];
25238 ModifiersLoc[Count] = MotionModifiersLoc[I];
25239 ++Count;
25240 }
25241
25242 MappableVarListInfo MVLI(VarList);
25243 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_from, MVLI, StartLoc: Locs.StartLoc,
25244 MapperIdScopeSpec, MapperId, UnresolvedMappers);
25245 if (MVLI.ProcessedVarList.empty())
25246 return nullptr;
25247 if (IteratorExpr)
25248 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: IteratorExpr))
25249 if (auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
25250 DSAStack->addIteratorVarDecl(VD);
25251 return OMPFromClause::Create(
25252 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25253 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, IteratorExpr, MotionModifiers: Modifiers,
25254 MotionModifiersLoc: ModifiersLoc, UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()),
25255 MapperId);
25256}
25257
25258OMPClause *SemaOpenMP::ActOnOpenMPUseDevicePtrClause(
25259 ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs,
25260 OpenMPUseDevicePtrFallbackModifier FallbackModifier,
25261 SourceLocation FallbackModifierLoc) {
25262 MappableVarListInfo MVLI(VarList);
25263 SmallVector<Expr *, 8> PrivateCopies;
25264 SmallVector<Expr *, 8> Inits;
25265
25266 for (Expr *RefExpr : VarList) {
25267 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
25268 SourceLocation ELoc;
25269 SourceRange ERange;
25270 Expr *SimpleRefExpr = RefExpr;
25271 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
25272 if (Res.second) {
25273 // It will be analyzed later.
25274 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
25275 PrivateCopies.push_back(Elt: nullptr);
25276 Inits.push_back(Elt: nullptr);
25277 }
25278 ValueDecl *D = Res.first;
25279 if (!D)
25280 continue;
25281
25282 QualType Type = D->getType();
25283 Type = Type.getNonReferenceType().getUnqualifiedType();
25284
25285 auto *VD = dyn_cast<VarDecl>(Val: D);
25286
25287 // Item should be a pointer or reference to pointer.
25288 if (!Type->isPointerType()) {
25289 Diag(Loc: ELoc, DiagID: diag::err_omp_usedeviceptr_not_a_pointer)
25290 << 0 << RefExpr->getSourceRange();
25291 continue;
25292 }
25293
25294 // Build the private variable and the expression that refers to it.
25295 auto VDPrivate =
25296 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
25297 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
25298 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
25299 if (VDPrivate->isInvalidDecl())
25300 continue;
25301
25302 SemaRef.CurContext->addDecl(D: VDPrivate);
25303 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
25304 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(), Loc: ELoc);
25305
25306 // Add temporary variable to initialize the private copy of the pointer.
25307 VarDecl *VDInit =
25308 buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type, Name: ".devptr.temp");
25309 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
25310 S&: SemaRef, D: VDInit, Ty: RefExpr->getType(), Loc: RefExpr->getExprLoc());
25311 SemaRef.AddInitializerToDecl(
25312 dcl: VDPrivate, init: SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get(),
25313 /*DirectInit=*/false);
25314
25315 // If required, build a capture to implement the privatization initialized
25316 // with the current list item value.
25317 DeclRefExpr *Ref = nullptr;
25318 if (!VD)
25319 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
25320 MVLI.ProcessedVarList.push_back(Elt: VD ? RefExpr->IgnoreParens() : Ref);
25321 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
25322 Inits.push_back(Elt: VDInitRefExpr);
25323
25324 // We need to add a data sharing attribute for this variable to make sure it
25325 // is correctly captured. A variable that shows up in a use_device_ptr has
25326 // similar properties of a first private variable.
25327 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
25328
25329 // Create a mappable component for the list item. List items in this clause
25330 // only need a component.
25331 MVLI.VarBaseDeclarations.push_back(Elt: D);
25332 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
25333 MVLI.VarComponents.back().emplace_back(Args&: SimpleRefExpr, Args&: D,
25334 /*IsNonContiguous=*/Args: false);
25335 }
25336
25337 if (MVLI.ProcessedVarList.empty())
25338 return nullptr;
25339
25340 return OMPUseDevicePtrClause::Create(
25341 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, PrivateVars: PrivateCopies, Inits,
25342 Declarations: MVLI.VarBaseDeclarations, ComponentLists: MVLI.VarComponents, FallbackModifier,
25343 FallbackModifierLoc);
25344}
25345
25346OMPClause *
25347SemaOpenMP::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
25348 const OMPVarListLocTy &Locs) {
25349 MappableVarListInfo MVLI(VarList);
25350
25351 for (Expr *RefExpr : VarList) {
25352 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
25353 SourceLocation ELoc;
25354 SourceRange ERange;
25355 Expr *SimpleRefExpr = RefExpr;
25356 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
25357 /*AllowArraySection=*/true,
25358 /*AllowAssumedSizeArray=*/true);
25359 if (Res.second) {
25360 // It will be analyzed later.
25361 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
25362 }
25363 ValueDecl *D = Res.first;
25364 if (!D)
25365 continue;
25366 auto *VD = dyn_cast<VarDecl>(Val: D);
25367
25368 // If required, build a capture to implement the privatization initialized
25369 // with the current list item value.
25370 DeclRefExpr *Ref = nullptr;
25371 if (!VD)
25372 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
25373 MVLI.ProcessedVarList.push_back(Elt: VD ? RefExpr->IgnoreParens() : Ref);
25374
25375 // We need to add a data sharing attribute for this variable to make sure it
25376 // is correctly captured. A variable that shows up in a use_device_addr has
25377 // similar properties of a first private variable.
25378 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
25379
25380 // Use the map-like approach to fully populate VarComponents
25381 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
25382
25383 const Expr *BE = checkMapClauseExpressionBase(
25384 SemaRef, E: RefExpr, CurComponents, CKind: OMPC_use_device_addr,
25385 DSAStack->getCurrentDirective(),
25386 /*NoDiagnose=*/false);
25387
25388 if (!BE)
25389 continue;
25390
25391 assert(!CurComponents.empty() &&
25392 "use_device_addr clause expression with no components!");
25393
25394 // OpenMP use_device_addr: If a list item is an array section, the array
25395 // base must be a base language identifier. We caught the cases where
25396 // the array-section has a base-variable in getPrivateItem. e.g.
25397 // struct S {
25398 // int a[10];
25399 // }; S s1;
25400 // ... use_device_addr(s1.a[0]) // not ok, caught already
25401 //
25402 // But we still neeed to verify that the base-pointer is also a
25403 // base-language identifier, and catch cases like:
25404 // int *pa[10]; *p;
25405 // ... use_device_addr(pa[1][2]) // not ok, base-pointer is pa[1]
25406 // ... use_device_addr(p[1]) // ok
25407 // ... use_device_addr(this->p[1]) // ok
25408 auto AttachPtrResult = OMPClauseMappableExprCommon::findAttachPtrExpr(
25409 Components: CurComponents, DSAStack->getCurrentDirective());
25410 const Expr *AttachPtrExpr = AttachPtrResult.first;
25411
25412 if (AttachPtrExpr) {
25413 const Expr *BaseExpr = AttachPtrExpr->IgnoreParenImpCasts();
25414 bool IsValidBase = false;
25415
25416 if (isa<DeclRefExpr>(Val: BaseExpr))
25417 IsValidBase = true;
25418 else if (const auto *ME = dyn_cast<MemberExpr>(Val: BaseExpr);
25419 ME && isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
25420 IsValidBase = true;
25421
25422 if (!IsValidBase) {
25423 SemaRef.Diag(Loc: ELoc,
25424 DiagID: diag::err_omp_expected_base_pointer_var_name_member_expr)
25425 << (SemaRef.getCurrentThisType().isNull() ? 0 : 1)
25426 << AttachPtrExpr->getSourceRange();
25427 continue;
25428 }
25429 }
25430
25431 // Get the declaration from the components
25432 ValueDecl *CurDeclaration = CurComponents.back().getAssociatedDeclaration();
25433 assert((isa<CXXThisExpr>(BE) || CurDeclaration) &&
25434 "Unexpected null decl for use_device_addr clause.");
25435
25436 MVLI.VarBaseDeclarations.push_back(Elt: CurDeclaration);
25437 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
25438 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
25439 in_end: CurComponents.end());
25440 }
25441
25442 if (MVLI.ProcessedVarList.empty())
25443 return nullptr;
25444
25445 return OMPUseDeviceAddrClause::Create(
25446 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25447 ComponentLists: MVLI.VarComponents);
25448}
25449
25450OMPClause *
25451SemaOpenMP::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
25452 const OMPVarListLocTy &Locs) {
25453 MappableVarListInfo MVLI(VarList);
25454 for (Expr *RefExpr : VarList) {
25455 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
25456 SourceLocation ELoc;
25457 SourceRange ERange;
25458 Expr *SimpleRefExpr = RefExpr;
25459 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
25460 if (Res.second) {
25461 // It will be analyzed later.
25462 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
25463 }
25464 ValueDecl *D = Res.first;
25465 if (!D)
25466 continue;
25467
25468 QualType Type = D->getType();
25469 // item should be a pointer or array or reference to pointer or array
25470 if (!Type.getNonReferenceType()->isPointerType() &&
25471 !Type.getNonReferenceType()->isArrayType()) {
25472 Diag(Loc: ELoc, DiagID: diag::err_omp_argument_type_isdeviceptr)
25473 << 0 << RefExpr->getSourceRange();
25474 continue;
25475 }
25476
25477 // Check if the declaration in the clause does not show up in any data
25478 // sharing attribute.
25479 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
25480 if (isOpenMPPrivate(Kind: DVar.CKind)) {
25481 unsigned OMPVersion = getLangOpts().OpenMP;
25482 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
25483 << getOpenMPClauseNameForDiag(C: DVar.CKind)
25484 << getOpenMPClauseNameForDiag(C: OMPC_is_device_ptr)
25485 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
25486 Ver: OMPVersion);
25487 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
25488 continue;
25489 }
25490
25491 const Expr *ConflictExpr;
25492 if (DSAStack->checkMappableExprComponentListsForDecl(
25493 VD: D, /*CurrentRegionOnly=*/true,
25494 Check: [&ConflictExpr](
25495 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
25496 OpenMPClauseKind) -> bool {
25497 ConflictExpr = R.front().getAssociatedExpression();
25498 return true;
25499 })) {
25500 Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
25501 Diag(Loc: ConflictExpr->getExprLoc(), DiagID: diag::note_used_here)
25502 << ConflictExpr->getSourceRange();
25503 continue;
25504 }
25505
25506 // Store the components in the stack so that they can be used to check
25507 // against other clauses later on.
25508 OMPClauseMappableExprCommon::MappableComponent MC(
25509 SimpleRefExpr, D, /*IsNonContiguous=*/false);
25510 DSAStack->addMappableExpressionComponents(
25511 VD: D, Components: MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
25512
25513 // Record the expression we've just processed.
25514 MVLI.ProcessedVarList.push_back(Elt: SimpleRefExpr);
25515
25516 // Create a mappable component for the list item. List items in this clause
25517 // only need a component. We use a null declaration to signal fields in
25518 // 'this'.
25519 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
25520 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
25521 "Unexpected device pointer expression!");
25522 MVLI.VarBaseDeclarations.push_back(
25523 Elt: isa<DeclRefExpr>(Val: SimpleRefExpr) ? D : nullptr);
25524 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
25525 MVLI.VarComponents.back().push_back(Elt: MC);
25526 }
25527
25528 if (MVLI.ProcessedVarList.empty())
25529 return nullptr;
25530
25531 return OMPIsDevicePtrClause::Create(
25532 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25533 ComponentLists: MVLI.VarComponents);
25534}
25535
25536OMPClause *
25537SemaOpenMP::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
25538 const OMPVarListLocTy &Locs) {
25539 MappableVarListInfo MVLI(VarList);
25540 for (Expr *RefExpr : VarList) {
25541 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
25542 SourceLocation ELoc;
25543 SourceRange ERange;
25544 Expr *SimpleRefExpr = RefExpr;
25545 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
25546 /*AllowArraySection=*/true);
25547 if (Res.second) {
25548 // It will be analyzed later.
25549 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
25550 }
25551 ValueDecl *D = Res.first;
25552 if (!D)
25553 continue;
25554
25555 // Check if the declaration in the clause does not show up in any data
25556 // sharing attribute.
25557 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
25558 if (isOpenMPPrivate(Kind: DVar.CKind)) {
25559 unsigned OMPVersion = getLangOpts().OpenMP;
25560 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
25561 << getOpenMPClauseNameForDiag(C: DVar.CKind)
25562 << getOpenMPClauseNameForDiag(C: OMPC_has_device_addr)
25563 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
25564 Ver: OMPVersion);
25565 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
25566 continue;
25567 }
25568
25569 const Expr *ConflictExpr;
25570 if (DSAStack->checkMappableExprComponentListsForDecl(
25571 VD: D, /*CurrentRegionOnly=*/true,
25572 Check: [&ConflictExpr](
25573 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
25574 OpenMPClauseKind) -> bool {
25575 ConflictExpr = R.front().getAssociatedExpression();
25576 return true;
25577 })) {
25578 Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
25579 Diag(Loc: ConflictExpr->getExprLoc(), DiagID: diag::note_used_here)
25580 << ConflictExpr->getSourceRange();
25581 continue;
25582 }
25583
25584 // Store the components in the stack so that they can be used to check
25585 // against other clauses later on.
25586 Expr *Component = SimpleRefExpr;
25587 auto *VD = dyn_cast<VarDecl>(Val: D);
25588 if (VD && (isa<ArraySectionExpr>(Val: RefExpr->IgnoreParenImpCasts()) ||
25589 isa<ArraySubscriptExpr>(Val: RefExpr->IgnoreParenImpCasts())))
25590 Component =
25591 SemaRef.DefaultFunctionArrayLvalueConversion(E: SimpleRefExpr).get();
25592 OMPClauseMappableExprCommon::MappableComponent MC(
25593 Component, D, /*IsNonContiguous=*/false);
25594 DSAStack->addMappableExpressionComponents(
25595 VD: D, Components: MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
25596
25597 // Record the expression we've just processed.
25598 if (!VD && !SemaRef.CurContext->isDependentContext()) {
25599 DeclRefExpr *Ref =
25600 buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
25601 assert(Ref && "has_device_addr capture failed");
25602 MVLI.ProcessedVarList.push_back(Elt: Ref);
25603 } else
25604 MVLI.ProcessedVarList.push_back(Elt: RefExpr->IgnoreParens());
25605
25606 // Create a mappable component for the list item. List items in this clause
25607 // only need a component. We use a null declaration to signal fields in
25608 // 'this'.
25609 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
25610 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
25611 "Unexpected device pointer expression!");
25612 MVLI.VarBaseDeclarations.push_back(
25613 Elt: isa<DeclRefExpr>(Val: SimpleRefExpr) ? D : nullptr);
25614 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
25615 MVLI.VarComponents.back().push_back(Elt: MC);
25616 }
25617
25618 if (MVLI.ProcessedVarList.empty())
25619 return nullptr;
25620
25621 return OMPHasDeviceAddrClause::Create(
25622 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25623 ComponentLists: MVLI.VarComponents);
25624}
25625
25626OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause(
25627 Expr *Allocator, Expr *Alignment,
25628 OpenMPAllocateClauseModifier FirstAllocateModifier,
25629 SourceLocation FirstAllocateModifierLoc,
25630 OpenMPAllocateClauseModifier SecondAllocateModifier,
25631 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
25632 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
25633 SourceLocation EndLoc) {
25634 if (Allocator) {
25635 // Allocator expression is dependent - skip it for now and build the
25636 // allocator when instantiated.
25637 bool AllocDependent =
25638 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
25639 Allocator->isInstantiationDependent() ||
25640 Allocator->containsUnexpandedParameterPack());
25641 if (!AllocDependent) {
25642 // OpenMP [2.11.4 allocate Clause, Description]
25643 // allocator is an expression of omp_allocator_handle_t type.
25644 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: Allocator->getExprLoc(), DSAStack))
25645 return nullptr;
25646
25647 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(E: Allocator);
25648 if (AllocatorRes.isInvalid())
25649 return nullptr;
25650 AllocatorRes = SemaRef.PerformImplicitConversion(
25651 From: AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
25652 Action: AssignmentAction::Initializing,
25653 /*AllowExplicit=*/true);
25654 if (AllocatorRes.isInvalid())
25655 return nullptr;
25656 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
25657 }
25658 } else {
25659 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
25660 // allocate clauses that appear on a target construct or on constructs in a
25661 // target region must specify an allocator expression unless a requires
25662 // directive with the dynamic_allocators clause is present in the same
25663 // compilation unit.
25664 if (getLangOpts().OpenMPIsTargetDevice &&
25665 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
25666 SemaRef.targetDiag(Loc: StartLoc, DiagID: diag::err_expected_allocator_expression);
25667 }
25668 if (Alignment) {
25669 bool AlignmentDependent = Alignment->isTypeDependent() ||
25670 Alignment->isValueDependent() ||
25671 Alignment->isInstantiationDependent() ||
25672 Alignment->containsUnexpandedParameterPack();
25673 if (!AlignmentDependent) {
25674 ExprResult AlignResult =
25675 VerifyPositiveIntegerConstantInClause(E: Alignment, CKind: OMPC_allocate);
25676 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
25677 }
25678 }
25679 // Analyze and build list of variables.
25680 SmallVector<Expr *, 8> Vars;
25681 for (Expr *RefExpr : VarList) {
25682 assert(RefExpr && "NULL expr in OpenMP allocate clause.");
25683 SourceLocation ELoc;
25684 SourceRange ERange;
25685 Expr *SimpleRefExpr = RefExpr;
25686 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
25687 if (Res.second) {
25688 // It will be analyzed later.
25689 Vars.push_back(Elt: RefExpr);
25690 }
25691 ValueDecl *D = Res.first;
25692 if (!D)
25693 continue;
25694
25695 auto *VD = dyn_cast<VarDecl>(Val: D);
25696 DeclRefExpr *Ref = nullptr;
25697 if (!VD && !SemaRef.CurContext->isDependentContext())
25698 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
25699 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
25700 ? RefExpr->IgnoreParens()
25701 : Ref);
25702 }
25703
25704 if (Vars.empty())
25705 return nullptr;
25706
25707 if (Allocator)
25708 DSAStack->addInnerAllocatorExpr(E: Allocator);
25709
25710 return OMPAllocateClause::Create(
25711 C: getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
25712 Modifier1: FirstAllocateModifier, Modifier1Loc: FirstAllocateModifierLoc, Modifier2: SecondAllocateModifier,
25713 Modifier2Loc: SecondAllocateModifierLoc, EndLoc, VL: Vars);
25714}
25715
25716OMPClause *SemaOpenMP::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
25717 SourceLocation StartLoc,
25718 SourceLocation LParenLoc,
25719 SourceLocation EndLoc) {
25720 SmallVector<Expr *, 8> Vars;
25721 for (Expr *RefExpr : VarList) {
25722 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
25723 SourceLocation ELoc;
25724 SourceRange ERange;
25725 Expr *SimpleRefExpr = RefExpr;
25726 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
25727 if (Res.second)
25728 // It will be analyzed later.
25729 Vars.push_back(Elt: RefExpr);
25730 ValueDecl *D = Res.first;
25731 if (!D)
25732 continue;
25733
25734 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
25735 // A list-item cannot appear in more than one nontemporal clause.
25736 if (const Expr *PrevRef =
25737 DSAStack->addUniqueNontemporal(D, NewDE: SimpleRefExpr)) {
25738 Diag(Loc: ELoc, DiagID: diag::err_omp_used_in_clause_twice)
25739 << 0 << getOpenMPClauseNameForDiag(C: OMPC_nontemporal) << ERange;
25740 Diag(Loc: PrevRef->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
25741 << getOpenMPClauseNameForDiag(C: OMPC_nontemporal);
25742 continue;
25743 }
25744
25745 Vars.push_back(Elt: RefExpr);
25746 }
25747
25748 if (Vars.empty())
25749 return nullptr;
25750
25751 return OMPNontemporalClause::Create(C: getASTContext(), StartLoc, LParenLoc,
25752 EndLoc, VL: Vars);
25753}
25754
25755StmtResult SemaOpenMP::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
25756 Stmt *AStmt,
25757 SourceLocation StartLoc,
25758 SourceLocation EndLoc) {
25759 if (!AStmt)
25760 return StmtError();
25761
25762 SemaRef.setFunctionHasBranchProtectedScope();
25763
25764 return OMPScopeDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
25765 AssociatedStmt: AStmt);
25766}
25767
25768OMPClause *SemaOpenMP::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
25769 SourceLocation StartLoc,
25770 SourceLocation LParenLoc,
25771 SourceLocation EndLoc) {
25772 SmallVector<Expr *, 8> Vars;
25773 for (Expr *RefExpr : VarList) {
25774 assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
25775 SourceLocation ELoc;
25776 SourceRange ERange;
25777 Expr *SimpleRefExpr = RefExpr;
25778 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
25779 /*AllowArraySection=*/true);
25780 if (Res.second)
25781 // It will be analyzed later.
25782 Vars.push_back(Elt: RefExpr);
25783 ValueDecl *D = Res.first;
25784 if (!D)
25785 continue;
25786
25787 const DSAStackTy::DSAVarData DVar =
25788 DSAStack->getTopDSA(D, /*FromParent=*/true);
25789 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
25790 // A list item that appears in the inclusive or exclusive clause must appear
25791 // in a reduction clause with the inscan modifier on the enclosing
25792 // worksharing-loop, worksharing-loop SIMD, or simd construct.
25793 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
25794 Diag(Loc: ELoc, DiagID: diag::err_omp_inclusive_exclusive_not_reduction)
25795 << RefExpr->getSourceRange();
25796
25797 if (DSAStack->getParentDirective() != OMPD_unknown)
25798 DSAStack->markDeclAsUsedInScanDirective(D);
25799 Vars.push_back(Elt: RefExpr);
25800 }
25801
25802 if (Vars.empty())
25803 return nullptr;
25804
25805 return OMPInclusiveClause::Create(C: getASTContext(), StartLoc, LParenLoc,
25806 EndLoc, VL: Vars);
25807}
25808
25809OMPClause *SemaOpenMP::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
25810 SourceLocation StartLoc,
25811 SourceLocation LParenLoc,
25812 SourceLocation EndLoc) {
25813 SmallVector<Expr *, 8> Vars;
25814 for (Expr *RefExpr : VarList) {
25815 assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
25816 SourceLocation ELoc;
25817 SourceRange ERange;
25818 Expr *SimpleRefExpr = RefExpr;
25819 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
25820 /*AllowArraySection=*/true);
25821 if (Res.second)
25822 // It will be analyzed later.
25823 Vars.push_back(Elt: RefExpr);
25824 ValueDecl *D = Res.first;
25825 if (!D)
25826 continue;
25827
25828 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
25829 DSAStackTy::DSAVarData DVar;
25830 if (ParentDirective != OMPD_unknown)
25831 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
25832 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
25833 // A list item that appears in the inclusive or exclusive clause must appear
25834 // in a reduction clause with the inscan modifier on the enclosing
25835 // worksharing-loop, worksharing-loop SIMD, or simd construct.
25836 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
25837 DVar.Modifier != OMPC_REDUCTION_inscan) {
25838 Diag(Loc: ELoc, DiagID: diag::err_omp_inclusive_exclusive_not_reduction)
25839 << RefExpr->getSourceRange();
25840 } else {
25841 DSAStack->markDeclAsUsedInScanDirective(D);
25842 }
25843 Vars.push_back(Elt: RefExpr);
25844 }
25845
25846 if (Vars.empty())
25847 return nullptr;
25848
25849 return OMPExclusiveClause::Create(C: getASTContext(), StartLoc, LParenLoc,
25850 EndLoc, VL: Vars);
25851}
25852
25853/// Tries to find omp_alloctrait_t type.
25854static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
25855 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
25856 if (!OMPAlloctraitT.isNull())
25857 return true;
25858 IdentifierInfo &II = S.PP.getIdentifierTable().get(Name: "omp_alloctrait_t");
25859 ParsedType PT = S.getTypeName(II, NameLoc: Loc, S: S.getCurScope());
25860 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
25861 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
25862 return false;
25863 }
25864 Stack->setOMPAlloctraitT(PT.get());
25865 return true;
25866}
25867
25868OMPClause *SemaOpenMP::ActOnOpenMPUsesAllocatorClause(
25869 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
25870 ArrayRef<UsesAllocatorsData> Data) {
25871 ASTContext &Context = getASTContext();
25872 // OpenMP [2.12.5, target Construct]
25873 // allocator is an identifier of omp_allocator_handle_t type.
25874 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: StartLoc, DSAStack))
25875 return nullptr;
25876 // OpenMP [2.12.5, target Construct]
25877 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
25878 if (llvm::any_of(
25879 Range&: Data,
25880 P: [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
25881 !findOMPAlloctraitT(S&: SemaRef, Loc: StartLoc, DSAStack))
25882 return nullptr;
25883 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
25884 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
25885 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
25886 StringRef Allocator =
25887 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(Val: AllocatorKind);
25888 DeclarationName AllocatorName = &Context.Idents.get(Name: Allocator);
25889 PredefinedAllocators.insert(Ptr: SemaRef.LookupSingleName(
25890 S: SemaRef.TUScope, Name: AllocatorName, Loc: StartLoc, NameKind: Sema::LookupAnyName));
25891 }
25892
25893 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
25894 for (const UsesAllocatorsData &D : Data) {
25895 Expr *AllocatorExpr = nullptr;
25896 // Check allocator expression.
25897 if (D.Allocator->isTypeDependent()) {
25898 AllocatorExpr = D.Allocator;
25899 } else {
25900 // Traits were specified - need to assign new allocator to the specified
25901 // allocator, so it must be an lvalue.
25902 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
25903 auto *DRE = dyn_cast<DeclRefExpr>(Val: AllocatorExpr);
25904 bool IsPredefinedAllocator = false;
25905 if (DRE) {
25906 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
25907 getAllocatorKind(S&: SemaRef, DSAStack, Allocator: AllocatorExpr);
25908 IsPredefinedAllocator =
25909 AllocatorTy !=
25910 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
25911 }
25912 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
25913 QualType AllocatorExprType = AllocatorExpr->getType();
25914 bool IsTypeCompatible = IsPredefinedAllocator;
25915 IsTypeCompatible = IsTypeCompatible ||
25916 Context.hasSameUnqualifiedType(T1: AllocatorExprType,
25917 T2: OMPAllocatorHandleT);
25918 IsTypeCompatible =
25919 IsTypeCompatible ||
25920 Context.typesAreCompatible(T1: AllocatorExprType, T2: OMPAllocatorHandleT);
25921 bool IsNonConstantLValue =
25922 !AllocatorExprType.isConstant(Ctx: Context) && AllocatorExpr->isLValue();
25923 if (!DRE || !IsTypeCompatible ||
25924 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
25925 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::err_omp_var_expected)
25926 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
25927 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
25928 continue;
25929 }
25930 // OpenMP [2.12.5, target Construct]
25931 // Predefined allocators appearing in a uses_allocators clause cannot have
25932 // traits specified.
25933 if (IsPredefinedAllocator && D.AllocatorTraits) {
25934 Diag(Loc: D.AllocatorTraits->getExprLoc(),
25935 DiagID: diag::err_omp_predefined_allocator_with_traits)
25936 << D.AllocatorTraits->getSourceRange();
25937 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::note_omp_predefined_allocator)
25938 << cast<NamedDecl>(Val: DRE->getDecl())->getName()
25939 << D.Allocator->getSourceRange();
25940 continue;
25941 }
25942 // OpenMP [2.12.5, target Construct]
25943 // Non-predefined allocators appearing in a uses_allocators clause must
25944 // have traits specified.
25945 if (getLangOpts().OpenMP < 52) {
25946 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
25947 Diag(Loc: D.Allocator->getExprLoc(),
25948 DiagID: diag::err_omp_nonpredefined_allocator_without_traits);
25949 continue;
25950 }
25951 }
25952 // No allocator traits - just convert it to rvalue.
25953 if (!D.AllocatorTraits)
25954 AllocatorExpr = SemaRef.DefaultLvalueConversion(E: AllocatorExpr).get();
25955 DSAStack->addUsesAllocatorsDecl(
25956 D: DRE->getDecl(),
25957 Kind: IsPredefinedAllocator
25958 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
25959 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
25960 }
25961 Expr *AllocatorTraitsExpr = nullptr;
25962 if (D.AllocatorTraits) {
25963 if (D.AllocatorTraits->isTypeDependent()) {
25964 AllocatorTraitsExpr = D.AllocatorTraits;
25965 } else {
25966 // OpenMP [2.12.5, target Construct]
25967 // Arrays that contain allocator traits that appear in a uses_allocators
25968 // clause must be constant arrays, have constant values and be defined
25969 // in the same scope as the construct in which the clause appears.
25970 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
25971 // Check that traits expr is a constant array.
25972 QualType TraitTy;
25973 if (const ArrayType *Ty =
25974 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
25975 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Val: Ty))
25976 TraitTy = ConstArrayTy->getElementType();
25977 if (TraitTy.isNull() ||
25978 !(Context.hasSameUnqualifiedType(T1: TraitTy,
25979 DSAStack->getOMPAlloctraitT()) ||
25980 Context.typesAreCompatible(T1: TraitTy, DSAStack->getOMPAlloctraitT(),
25981 /*CompareUnqualified=*/true))) {
25982 Diag(Loc: D.AllocatorTraits->getExprLoc(),
25983 DiagID: diag::err_omp_expected_array_alloctraits)
25984 << AllocatorTraitsExpr->getType();
25985 continue;
25986 }
25987 // Do not map by default allocator traits if it is a standalone
25988 // variable.
25989 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: AllocatorTraitsExpr))
25990 DSAStack->addUsesAllocatorsDecl(
25991 D: DRE->getDecl(),
25992 Kind: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
25993 }
25994 }
25995 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
25996 NewD.Allocator = AllocatorExpr;
25997 NewD.AllocatorTraits = AllocatorTraitsExpr;
25998 NewD.LParenLoc = D.LParenLoc;
25999 NewD.RParenLoc = D.RParenLoc;
26000 }
26001 return OMPUsesAllocatorsClause::Create(C: getASTContext(), StartLoc, LParenLoc,
26002 EndLoc, Data: NewData);
26003}
26004
26005OMPClause *SemaOpenMP::ActOnOpenMPAffinityClause(
26006 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
26007 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
26008 SmallVector<Expr *, 8> Vars;
26009 for (Expr *RefExpr : Locators) {
26010 assert(RefExpr && "NULL expr in OpenMP affinity clause.");
26011 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr) || RefExpr->isTypeDependent()) {
26012 // It will be analyzed later.
26013 Vars.push_back(Elt: RefExpr);
26014 continue;
26015 }
26016
26017 SourceLocation ELoc = RefExpr->getExprLoc();
26018 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
26019
26020 if (!SimpleExpr->isLValue()) {
26021 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
26022 << 1 << 0 << RefExpr->getSourceRange();
26023 continue;
26024 }
26025
26026 ExprResult Res;
26027 {
26028 Sema::TentativeAnalysisScope Trap(SemaRef);
26029 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: SimpleExpr);
26030 }
26031 if (!Res.isUsable() && !isa<ArraySectionExpr>(Val: SimpleExpr) &&
26032 !isa<OMPArrayShapingExpr>(Val: SimpleExpr)) {
26033 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
26034 << 1 << 0 << RefExpr->getSourceRange();
26035 continue;
26036 }
26037 Vars.push_back(Elt: SimpleExpr);
26038 }
26039
26040 return OMPAffinityClause::Create(C: getASTContext(), StartLoc, LParenLoc,
26041 ColonLoc, EndLoc, Modifier, Locators: Vars);
26042}
26043
26044OMPClause *SemaOpenMP::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
26045 SourceLocation KindLoc,
26046 SourceLocation StartLoc,
26047 SourceLocation LParenLoc,
26048 SourceLocation EndLoc) {
26049 if (Kind == OMPC_BIND_unknown) {
26050 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
26051 << getListOfPossibleValues(K: OMPC_bind, /*First=*/0,
26052 /*Last=*/unsigned(OMPC_BIND_unknown))
26053 << getOpenMPClauseNameForDiag(C: OMPC_bind);
26054 return nullptr;
26055 }
26056
26057 return OMPBindClause::Create(C: getASTContext(), K: Kind, KLoc: KindLoc, StartLoc,
26058 LParenLoc, EndLoc);
26059}
26060
26061OMPClause *SemaOpenMP::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
26062 SourceLocation StartLoc,
26063 SourceLocation LParenLoc,
26064 SourceLocation EndLoc) {
26065 Expr *ValExpr = Size;
26066 Stmt *HelperValStmt = nullptr;
26067
26068 // OpenMP [2.5, Restrictions]
26069 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
26070 // value.
26071 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_ompx_dyn_cgroup_mem,
26072 /*StrictlyPositive=*/false))
26073 return nullptr;
26074
26075 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
26076 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
26077 DKind, CKind: OMPC_ompx_dyn_cgroup_mem, OpenMPVersion: getLangOpts().OpenMP);
26078 if (CaptureRegion != OMPD_unknown &&
26079 !SemaRef.CurContext->isDependentContext()) {
26080 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
26081 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26082 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
26083 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
26084 }
26085
26086 return new (getASTContext()) OMPXDynCGroupMemClause(
26087 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
26088}
26089
26090OMPClause *SemaOpenMP::ActOnOpenMPDynGroupprivateClause(
26091 OpenMPDynGroupprivateClauseModifier M1,
26092 OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size,
26093 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
26094 SourceLocation M2Loc, SourceLocation EndLoc) {
26095
26096 if ((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ||
26097 (M2Loc.isValid() && M2 == OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown)) {
26098 std::string Values = getListOfPossibleValues(
26099 K: OMPC_dyn_groupprivate, /*First=*/0, Last: OMPC_DYN_GROUPPRIVATE_unknown);
26100 Diag(Loc: (M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ? M1Loc
26101 : M2Loc,
26102 DiagID: diag::err_omp_unexpected_clause_value)
26103 << Values << getOpenMPClauseName(C: OMPC_dyn_groupprivate);
26104 return nullptr;
26105 }
26106
26107 Expr *ValExpr = Size;
26108 Stmt *HelperValStmt = nullptr;
26109
26110 // OpenMP [2.5, Restrictions]
26111 // The dyn_groupprivate expression must evaluate to a positive integer
26112 // value.
26113 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_dyn_groupprivate,
26114 /*StrictlyPositive=*/false))
26115 return nullptr;
26116
26117 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
26118 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
26119 DKind, CKind: OMPC_dyn_groupprivate, OpenMPVersion: getLangOpts().OpenMP);
26120 if (CaptureRegion != OMPD_unknown &&
26121 !SemaRef.CurContext->isDependentContext()) {
26122 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
26123 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26124 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
26125 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
26126 }
26127
26128 return new (getASTContext()) OMPDynGroupprivateClause(
26129 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
26130 M1Loc, M2, M2Loc);
26131}
26132
26133OMPClause *SemaOpenMP::ActOnOpenMPDoacrossClause(
26134 OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
26135 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
26136 SourceLocation LParenLoc, SourceLocation EndLoc) {
26137
26138 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
26139 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
26140 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
26141 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
26142 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
26143 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(C: OMPC_doacross);
26144 return nullptr;
26145 }
26146
26147 SmallVector<Expr *, 8> Vars;
26148 DSAStackTy::OperatorOffsetTy OpsOffs;
26149 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
26150 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
26151 SemaRef,
26152 IsSource: DepType == OMPC_DOACROSS_source ||
26153 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
26154 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
26155 VarList, DSAStack, EndLoc);
26156 Vars = VarOffset.Vars;
26157 OpsOffs = VarOffset.OpsOffs;
26158 TotalDepCount = VarOffset.TotalDepCount;
26159 auto *C = OMPDoacrossClause::Create(C: getASTContext(), StartLoc, LParenLoc,
26160 EndLoc, DepType, DepLoc, ColonLoc, VL: Vars,
26161 NumLoops: TotalDepCount.getZExtValue());
26162 if (DSAStack->isParentOrderedRegion())
26163 DSAStack->addDoacrossDependClause(C, OpsOffs);
26164 return C;
26165}
26166
26167OMPClause *SemaOpenMP::ActOnOpenMPXAttributeClause(ArrayRef<const Attr *> Attrs,
26168 SourceLocation StartLoc,
26169 SourceLocation LParenLoc,
26170 SourceLocation EndLoc) {
26171 return new (getASTContext())
26172 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
26173}
26174
26175OMPClause *SemaOpenMP::ActOnOpenMPXBareClause(SourceLocation StartLoc,
26176 SourceLocation EndLoc) {
26177 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
26178}
26179
26180OMPClause *SemaOpenMP::ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc,
26181 SourceLocation LParenLoc,
26182 SourceLocation EndLoc) {
26183 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
26184}
26185
26186OMPClause *SemaOpenMP::ActOnOpenMPDirectivePresenceClause(
26187 OpenMPClauseKind CK, llvm::ArrayRef<OpenMPDirectiveKind> DKVec,
26188 SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc) {
26189 switch (CK) {
26190 case OMPC_absent:
26191 return OMPAbsentClause::Create(C: getASTContext(), DKVec, Loc, LLoc, RLoc);
26192 case OMPC_contains:
26193 return OMPContainsClause::Create(C: getASTContext(), DKVec, Loc, LLoc, RLoc);
26194 default:
26195 llvm_unreachable("Unexpected OpenMP clause");
26196 }
26197}
26198
26199OMPClause *SemaOpenMP::ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK,
26200 SourceLocation Loc,
26201 SourceLocation RLoc) {
26202 switch (CK) {
26203 case OMPC_no_openmp:
26204 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
26205 case OMPC_no_openmp_routines:
26206 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
26207 case OMPC_no_parallelism:
26208 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
26209 case OMPC_no_openmp_constructs:
26210 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
26211 default:
26212 llvm_unreachable("Unexpected OpenMP clause");
26213 }
26214}
26215
26216ExprResult SemaOpenMP::ActOnOMPArraySectionExpr(
26217 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
26218 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
26219 Expr *Stride, SourceLocation RBLoc) {
26220 ASTContext &Context = getASTContext();
26221 if (Base->hasPlaceholderType() &&
26222 !Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
26223 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base);
26224 if (Result.isInvalid())
26225 return ExprError();
26226 Base = Result.get();
26227 }
26228 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
26229 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: LowerBound);
26230 if (Result.isInvalid())
26231 return ExprError();
26232 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26233 if (Result.isInvalid())
26234 return ExprError();
26235 LowerBound = Result.get();
26236 }
26237 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
26238 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Length);
26239 if (Result.isInvalid())
26240 return ExprError();
26241 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26242 if (Result.isInvalid())
26243 return ExprError();
26244 Length = Result.get();
26245 }
26246 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
26247 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Stride);
26248 if (Result.isInvalid())
26249 return ExprError();
26250 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26251 if (Result.isInvalid())
26252 return ExprError();
26253 Stride = Result.get();
26254 }
26255
26256 // Build an unanalyzed expression if either operand is type-dependent.
26257 if (Base->isTypeDependent() ||
26258 (LowerBound &&
26259 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
26260 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
26261 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
26262 return new (Context) ArraySectionExpr(
26263 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
26264 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
26265 }
26266
26267 // Perform default conversions.
26268 QualType OriginalTy = ArraySectionExpr::getBaseOriginalType(Base);
26269 QualType ResultTy;
26270 if (OriginalTy->isAnyPointerType()) {
26271 ResultTy = OriginalTy->getPointeeType();
26272 } else if (OriginalTy->isArrayType()) {
26273 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
26274 } else {
26275 return ExprError(
26276 Diag(Loc: Base->getExprLoc(), DiagID: diag::err_omp_typecheck_section_value)
26277 << Base->getSourceRange());
26278 }
26279 // C99 6.5.2.1p1
26280 if (LowerBound) {
26281 auto Res = PerformOpenMPImplicitIntegerConversion(Loc: LowerBound->getExprLoc(),
26282 Op: LowerBound);
26283 if (Res.isInvalid())
26284 return ExprError(Diag(Loc: LowerBound->getExprLoc(),
26285 DiagID: diag::err_omp_typecheck_section_not_integer)
26286 << 0 << LowerBound->getSourceRange());
26287 LowerBound = Res.get();
26288
26289 if (LowerBound->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
26290 LowerBound->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
26291 Diag(Loc: LowerBound->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
26292 << 0 << LowerBound->getSourceRange();
26293 }
26294 if (Length) {
26295 auto Res =
26296 PerformOpenMPImplicitIntegerConversion(Loc: Length->getExprLoc(), Op: Length);
26297 if (Res.isInvalid())
26298 return ExprError(Diag(Loc: Length->getExprLoc(),
26299 DiagID: diag::err_omp_typecheck_section_not_integer)
26300 << 1 << Length->getSourceRange());
26301 Length = Res.get();
26302
26303 if (Length->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
26304 Length->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
26305 Diag(Loc: Length->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
26306 << 1 << Length->getSourceRange();
26307 }
26308 if (Stride) {
26309 ExprResult Res =
26310 PerformOpenMPImplicitIntegerConversion(Loc: Stride->getExprLoc(), Op: Stride);
26311 if (Res.isInvalid())
26312 return ExprError(Diag(Loc: Stride->getExprLoc(),
26313 DiagID: diag::err_omp_typecheck_section_not_integer)
26314 << 1 << Stride->getSourceRange());
26315 Stride = Res.get();
26316
26317 if (Stride->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
26318 Stride->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
26319 Diag(Loc: Stride->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
26320 << 1 << Stride->getSourceRange();
26321 }
26322
26323 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
26324 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
26325 // type. Note that functions are not objects, and that (in C99 parlance)
26326 // incomplete types are not object types.
26327 if (ResultTy->isFunctionType()) {
26328 Diag(Loc: Base->getExprLoc(), DiagID: diag::err_omp_section_function_type)
26329 << ResultTy << Base->getSourceRange();
26330 return ExprError();
26331 }
26332
26333 if (SemaRef.RequireCompleteType(Loc: Base->getExprLoc(), T: ResultTy,
26334 DiagID: diag::err_omp_section_incomplete_type, Args: Base))
26335 return ExprError();
26336
26337 if (LowerBound && !OriginalTy->isAnyPointerType()) {
26338 Expr::EvalResult Result;
26339 if (LowerBound->EvaluateAsInt(Result, Ctx: Context)) {
26340 // OpenMP 5.0, [2.1.5 Array Sections]
26341 // The array section must be a subset of the original array.
26342 llvm::APSInt LowerBoundValue = Result.Val.getInt();
26343 if (LowerBoundValue.isNegative()) {
26344 Diag(Loc: LowerBound->getExprLoc(),
26345 DiagID: diag::err_omp_section_not_subset_of_array)
26346 << LowerBound->getSourceRange();
26347 return ExprError();
26348 }
26349 }
26350 }
26351
26352 if (Length) {
26353 Expr::EvalResult Result;
26354 if (Length->EvaluateAsInt(Result, Ctx: Context)) {
26355 // OpenMP 5.0, [2.1.5 Array Sections]
26356 // The length must evaluate to non-negative integers.
26357 llvm::APSInt LengthValue = Result.Val.getInt();
26358 if (LengthValue.isNegative()) {
26359 Diag(Loc: Length->getExprLoc(), DiagID: diag::err_omp_section_length_negative)
26360 << toString(I: LengthValue, /*Radix=*/10, /*Signed=*/true)
26361 << Length->getSourceRange();
26362 return ExprError();
26363 }
26364 }
26365 } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
26366 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
26367 !OriginalTy->isVariableArrayType()))) {
26368 // OpenMP 5.0, [2.1.5 Array Sections]
26369 // When the size of the array dimension is not known, the length must be
26370 // specified explicitly.
26371 Diag(Loc: ColonLocFirst, DiagID: diag::err_omp_section_length_undefined)
26372 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
26373 return ExprError();
26374 }
26375
26376 if (Stride) {
26377 Expr::EvalResult Result;
26378 if (Stride->EvaluateAsInt(Result, Ctx: Context)) {
26379 // OpenMP 5.0, [2.1.5 Array Sections]
26380 // The stride must evaluate to a positive integer.
26381 llvm::APSInt StrideValue = Result.Val.getInt();
26382 if (!StrideValue.isStrictlyPositive()) {
26383 Diag(Loc: Stride->getExprLoc(), DiagID: diag::err_omp_section_stride_non_positive)
26384 << toString(I: StrideValue, /*Radix=*/10, /*Signed=*/true)
26385 << Stride->getSourceRange();
26386 return ExprError();
26387 }
26388 }
26389 }
26390
26391 if (!Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
26392 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(E: Base);
26393 if (Result.isInvalid())
26394 return ExprError();
26395 Base = Result.get();
26396 }
26397 return new (Context) ArraySectionExpr(
26398 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
26399 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
26400}
26401
26402ExprResult SemaOpenMP::ActOnOMPArrayShapingExpr(
26403 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
26404 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
26405 ASTContext &Context = getASTContext();
26406 if (Base->hasPlaceholderType()) {
26407 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base);
26408 if (Result.isInvalid())
26409 return ExprError();
26410 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26411 if (Result.isInvalid())
26412 return ExprError();
26413 Base = Result.get();
26414 }
26415 QualType BaseTy = Base->getType();
26416 // Delay analysis of the types/expressions if instantiation/specialization is
26417 // required.
26418 if (!BaseTy->isPointerType() && Base->isTypeDependent())
26419 return OMPArrayShapingExpr::Create(Context, T: Context.DependentTy, Op: Base,
26420 L: LParenLoc, R: RParenLoc, Dims, BracketRanges: Brackets);
26421 if (!BaseTy->isPointerType() ||
26422 (!Base->isTypeDependent() &&
26423 BaseTy->getPointeeType()->isIncompleteType()))
26424 return ExprError(Diag(Loc: Base->getExprLoc(),
26425 DiagID: diag::err_omp_non_pointer_type_array_shaping_base)
26426 << Base->getSourceRange());
26427
26428 SmallVector<Expr *, 4> NewDims;
26429 bool ErrorFound = false;
26430 for (Expr *Dim : Dims) {
26431 if (Dim->hasPlaceholderType()) {
26432 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Dim);
26433 if (Result.isInvalid()) {
26434 ErrorFound = true;
26435 continue;
26436 }
26437 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26438 if (Result.isInvalid()) {
26439 ErrorFound = true;
26440 continue;
26441 }
26442 Dim = Result.get();
26443 }
26444 if (!Dim->isTypeDependent()) {
26445 ExprResult Result =
26446 PerformOpenMPImplicitIntegerConversion(Loc: Dim->getExprLoc(), Op: Dim);
26447 if (Result.isInvalid()) {
26448 ErrorFound = true;
26449 Diag(Loc: Dim->getExprLoc(), DiagID: diag::err_omp_typecheck_shaping_not_integer)
26450 << Dim->getSourceRange();
26451 continue;
26452 }
26453 Dim = Result.get();
26454 Expr::EvalResult EvResult;
26455 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(Result&: EvResult, Ctx: Context)) {
26456 // OpenMP 5.0, [2.1.4 Array Shaping]
26457 // Each si is an integral type expression that must evaluate to a
26458 // positive integer.
26459 llvm::APSInt Value = EvResult.Val.getInt();
26460 if (!Value.isStrictlyPositive()) {
26461 Diag(Loc: Dim->getExprLoc(), DiagID: diag::err_omp_shaping_dimension_not_positive)
26462 << toString(I: Value, /*Radix=*/10, /*Signed=*/true)
26463 << Dim->getSourceRange();
26464 ErrorFound = true;
26465 continue;
26466 }
26467 }
26468 }
26469 NewDims.push_back(Elt: Dim);
26470 }
26471 if (ErrorFound)
26472 return ExprError();
26473 return OMPArrayShapingExpr::Create(Context, T: Context.OMPArrayShapingTy, Op: Base,
26474 L: LParenLoc, R: RParenLoc, Dims: NewDims, BracketRanges: Brackets);
26475}
26476
26477ExprResult SemaOpenMP::ActOnOMPIteratorExpr(Scope *S,
26478 SourceLocation IteratorKwLoc,
26479 SourceLocation LLoc,
26480 SourceLocation RLoc,
26481 ArrayRef<OMPIteratorData> Data) {
26482 ASTContext &Context = getASTContext();
26483 SmallVector<OMPIteratorExpr::IteratorDefinition, 4> ID;
26484 bool IsCorrect = true;
26485 for (const OMPIteratorData &D : Data) {
26486 TypeSourceInfo *TInfo = nullptr;
26487 SourceLocation StartLoc;
26488 QualType DeclTy;
26489 if (!D.Type.getAsOpaquePtr()) {
26490 // OpenMP 5.0, 2.1.6 Iterators
26491 // In an iterator-specifier, if the iterator-type is not specified then
26492 // the type of that iterator is of int type.
26493 DeclTy = Context.IntTy;
26494 StartLoc = D.DeclIdentLoc;
26495 } else {
26496 DeclTy = Sema::GetTypeFromParser(Ty: D.Type, TInfo: &TInfo);
26497 StartLoc = TInfo->getTypeLoc().getBeginLoc();
26498 }
26499
26500 bool IsDeclTyDependent = DeclTy->isDependentType() ||
26501 DeclTy->containsUnexpandedParameterPack() ||
26502 DeclTy->isInstantiationDependentType();
26503 if (!IsDeclTyDependent) {
26504 if (!DeclTy->isIntegralType(Ctx: Context) && !DeclTy->isAnyPointerType()) {
26505 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
26506 // The iterator-type must be an integral or pointer type.
26507 Diag(Loc: StartLoc, DiagID: diag::err_omp_iterator_not_integral_or_pointer)
26508 << DeclTy;
26509 IsCorrect = false;
26510 continue;
26511 }
26512 if (DeclTy.isConstant(Ctx: Context)) {
26513 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
26514 // The iterator-type must not be const qualified.
26515 Diag(Loc: StartLoc, DiagID: diag::err_omp_iterator_not_integral_or_pointer)
26516 << DeclTy;
26517 IsCorrect = false;
26518 continue;
26519 }
26520 }
26521
26522 // Iterator declaration.
26523 assert(D.DeclIdent && "Identifier expected.");
26524 // Always try to create iterator declarator to avoid extra error messages
26525 // about unknown declarations use.
26526 auto *VD =
26527 VarDecl::Create(C&: Context, DC: SemaRef.CurContext, StartLoc, IdLoc: D.DeclIdentLoc,
26528 Id: D.DeclIdent, T: DeclTy, TInfo, S: SC_None);
26529 VD->setImplicit();
26530 if (S) {
26531 // Check for conflicting previous declaration.
26532 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
26533 LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
26534 RedeclarationKind::ForVisibleRedeclaration);
26535 Previous.suppressDiagnostics();
26536 SemaRef.LookupName(R&: Previous, S);
26537
26538 SemaRef.FilterLookupForScope(R&: Previous, Ctx: SemaRef.CurContext, S,
26539 /*ConsiderLinkage=*/false,
26540 /*AllowInlineNamespace=*/false);
26541 if (!Previous.empty()) {
26542 NamedDecl *Old = Previous.getRepresentativeDecl();
26543 Diag(Loc: D.DeclIdentLoc, DiagID: diag::err_redefinition) << VD->getDeclName();
26544 Diag(Loc: Old->getLocation(), DiagID: diag::note_previous_definition);
26545 } else {
26546 SemaRef.PushOnScopeChains(D: VD, S);
26547 }
26548 } else {
26549 SemaRef.CurContext->addDecl(D: VD);
26550 }
26551
26552 /// Act on the iterator variable declaration.
26553 ActOnOpenMPIteratorVarDecl(VD);
26554
26555 Expr *Begin = D.Range.Begin;
26556 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
26557 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
26558 From: Begin, ToType: DeclTy, Action: AssignmentAction::Converting);
26559 Begin = BeginRes.get();
26560 }
26561 Expr *End = D.Range.End;
26562 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
26563 ExprResult EndRes = SemaRef.PerformImplicitConversion(
26564 From: End, ToType: DeclTy, Action: AssignmentAction::Converting);
26565 End = EndRes.get();
26566 }
26567 Expr *Step = D.Range.Step;
26568 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
26569 if (!Step->getType()->isIntegralType(Ctx: Context)) {
26570 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_iterator_step_not_integral)
26571 << Step << Step->getSourceRange();
26572 IsCorrect = false;
26573 continue;
26574 }
26575 std::optional<llvm::APSInt> Result =
26576 Step->getIntegerConstantExpr(Ctx: Context);
26577 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
26578 // If the step expression of a range-specification equals zero, the
26579 // behavior is unspecified.
26580 if (Result && Result->isZero()) {
26581 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_iterator_step_constant_zero)
26582 << Step << Step->getSourceRange();
26583 IsCorrect = false;
26584 continue;
26585 }
26586 }
26587 if (!Begin || !End || !IsCorrect) {
26588 IsCorrect = false;
26589 continue;
26590 }
26591 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
26592 IDElem.IteratorDecl = VD;
26593 IDElem.AssignmentLoc = D.AssignLoc;
26594 IDElem.Range.Begin = Begin;
26595 IDElem.Range.End = End;
26596 IDElem.Range.Step = Step;
26597 IDElem.ColonLoc = D.ColonLoc;
26598 IDElem.SecondColonLoc = D.SecColonLoc;
26599 }
26600 if (!IsCorrect) {
26601 // Invalidate all created iterator declarations if error is found.
26602 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
26603 if (Decl *ID = D.IteratorDecl)
26604 ID->setInvalidDecl();
26605 }
26606 return ExprError();
26607 }
26608 SmallVector<OMPIteratorHelperData, 4> Helpers;
26609 if (!SemaRef.CurContext->isDependentContext()) {
26610 // Build number of ityeration for each iteration range.
26611 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
26612 // ((Begini-Stepi-1-Endi) / -Stepi);
26613 for (OMPIteratorExpr::IteratorDefinition &D : ID) {
26614 // (Endi - Begini)
26615 ExprResult Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Sub,
26616 LHSExpr: D.Range.End, RHSExpr: D.Range.Begin);
26617 if (!Res.isUsable()) {
26618 IsCorrect = false;
26619 continue;
26620 }
26621 ExprResult St, St1;
26622 if (D.Range.Step) {
26623 St = D.Range.Step;
26624 // (Endi - Begini) + Stepi
26625 Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add, LHSExpr: Res.get(),
26626 RHSExpr: St.get());
26627 if (!Res.isUsable()) {
26628 IsCorrect = false;
26629 continue;
26630 }
26631 // (Endi - Begini) + Stepi - 1
26632 Res = SemaRef.CreateBuiltinBinOp(
26633 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: Res.get(),
26634 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 1).get());
26635 if (!Res.isUsable()) {
26636 IsCorrect = false;
26637 continue;
26638 }
26639 // ((Endi - Begini) + Stepi - 1) / Stepi
26640 Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Div, LHSExpr: Res.get(),
26641 RHSExpr: St.get());
26642 if (!Res.isUsable()) {
26643 IsCorrect = false;
26644 continue;
26645 }
26646 St1 = SemaRef.CreateBuiltinUnaryOp(OpLoc: D.AssignmentLoc, Opc: UO_Minus,
26647 InputExpr: D.Range.Step);
26648 // (Begini - Endi)
26649 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
26650 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: D.Range.Begin, RHSExpr: D.Range.End);
26651 if (!Res1.isUsable()) {
26652 IsCorrect = false;
26653 continue;
26654 }
26655 // (Begini - Endi) - Stepi
26656 Res1 = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add, LHSExpr: Res1.get(),
26657 RHSExpr: St1.get());
26658 if (!Res1.isUsable()) {
26659 IsCorrect = false;
26660 continue;
26661 }
26662 // (Begini - Endi) - Stepi - 1
26663 Res1 = SemaRef.CreateBuiltinBinOp(
26664 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: Res1.get(),
26665 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 1).get());
26666 if (!Res1.isUsable()) {
26667 IsCorrect = false;
26668 continue;
26669 }
26670 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
26671 Res1 = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Div, LHSExpr: Res1.get(),
26672 RHSExpr: St1.get());
26673 if (!Res1.isUsable()) {
26674 IsCorrect = false;
26675 continue;
26676 }
26677 // Stepi > 0.
26678 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
26679 OpLoc: D.AssignmentLoc, Opc: BO_GT, LHSExpr: D.Range.Step,
26680 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 0).get());
26681 if (!CmpRes.isUsable()) {
26682 IsCorrect = false;
26683 continue;
26684 }
26685 Res = SemaRef.ActOnConditionalOp(QuestionLoc: D.AssignmentLoc, ColonLoc: D.AssignmentLoc,
26686 CondExpr: CmpRes.get(), LHSExpr: Res.get(), RHSExpr: Res1.get());
26687 if (!Res.isUsable()) {
26688 IsCorrect = false;
26689 continue;
26690 }
26691 }
26692 Res = SemaRef.ActOnFinishFullExpr(Expr: Res.get(), /*DiscardedValue=*/false);
26693 if (!Res.isUsable()) {
26694 IsCorrect = false;
26695 continue;
26696 }
26697
26698 // Build counter update.
26699 // Build counter.
26700 auto *CounterVD = VarDecl::Create(C&: Context, DC: SemaRef.CurContext,
26701 StartLoc: D.IteratorDecl->getBeginLoc(),
26702 IdLoc: D.IteratorDecl->getBeginLoc(), Id: nullptr,
26703 T: Res.get()->getType(), TInfo: nullptr, S: SC_None);
26704 CounterVD->setImplicit();
26705 ExprResult RefRes =
26706 SemaRef.BuildDeclRefExpr(D: CounterVD, Ty: CounterVD->getType(), VK: VK_LValue,
26707 Loc: D.IteratorDecl->getBeginLoc());
26708 // Build counter update.
26709 // I = Begini + counter * Stepi;
26710 ExprResult UpdateRes;
26711 if (D.Range.Step) {
26712 UpdateRes = SemaRef.CreateBuiltinBinOp(
26713 OpLoc: D.AssignmentLoc, Opc: BO_Mul,
26714 LHSExpr: SemaRef.DefaultLvalueConversion(E: RefRes.get()).get(), RHSExpr: St.get());
26715 } else {
26716 UpdateRes = SemaRef.DefaultLvalueConversion(E: RefRes.get());
26717 }
26718 if (!UpdateRes.isUsable()) {
26719 IsCorrect = false;
26720 continue;
26721 }
26722 UpdateRes = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add,
26723 LHSExpr: D.Range.Begin, RHSExpr: UpdateRes.get());
26724 if (!UpdateRes.isUsable()) {
26725 IsCorrect = false;
26726 continue;
26727 }
26728 ExprResult VDRes =
26729 SemaRef.BuildDeclRefExpr(D: cast<VarDecl>(Val: D.IteratorDecl),
26730 Ty: cast<VarDecl>(Val: D.IteratorDecl)->getType(),
26731 VK: VK_LValue, Loc: D.IteratorDecl->getBeginLoc());
26732 UpdateRes = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Assign,
26733 LHSExpr: VDRes.get(), RHSExpr: UpdateRes.get());
26734 if (!UpdateRes.isUsable()) {
26735 IsCorrect = false;
26736 continue;
26737 }
26738 UpdateRes =
26739 SemaRef.ActOnFinishFullExpr(Expr: UpdateRes.get(), /*DiscardedValue=*/true);
26740 if (!UpdateRes.isUsable()) {
26741 IsCorrect = false;
26742 continue;
26743 }
26744 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
26745 OpLoc: D.AssignmentLoc, Opc: UO_PreInc, InputExpr: RefRes.get());
26746 if (!CounterUpdateRes.isUsable()) {
26747 IsCorrect = false;
26748 continue;
26749 }
26750 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(Expr: CounterUpdateRes.get(),
26751 /*DiscardedValue=*/true);
26752 if (!CounterUpdateRes.isUsable()) {
26753 IsCorrect = false;
26754 continue;
26755 }
26756 OMPIteratorHelperData &HD = Helpers.emplace_back();
26757 HD.CounterVD = CounterVD;
26758 HD.Upper = Res.get();
26759 HD.Update = UpdateRes.get();
26760 HD.CounterUpdate = CounterUpdateRes.get();
26761 }
26762 } else {
26763 Helpers.assign(NumElts: ID.size(), Elt: {});
26764 }
26765 if (!IsCorrect) {
26766 // Invalidate all created iterator declarations if error is found.
26767 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
26768 if (Decl *ID = D.IteratorDecl)
26769 ID->setInvalidDecl();
26770 }
26771 return ExprError();
26772 }
26773 return OMPIteratorExpr::Create(Context, T: Context.OMPIteratorTy, IteratorKwLoc,
26774 L: LLoc, R: RLoc, Data: ID, Helpers);
26775}
26776
26777/// Check if \p AssumptionStr is a known assumption and warn if not.
26778static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc,
26779 StringRef AssumptionStr) {
26780 if (llvm::getKnownAssumptionStrings().count(Key: AssumptionStr))
26781 return;
26782
26783 unsigned BestEditDistance = 3;
26784 StringRef Suggestion;
26785 for (const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
26786 unsigned EditDistance =
26787 AssumptionStr.edit_distance(Other: KnownAssumptionIt.getKey());
26788 if (EditDistance < BestEditDistance) {
26789 Suggestion = KnownAssumptionIt.getKey();
26790 BestEditDistance = EditDistance;
26791 }
26792 }
26793
26794 if (!Suggestion.empty())
26795 S.Diag(Loc, DiagID: diag::warn_omp_assume_attribute_string_unknown_suggested)
26796 << AssumptionStr << Suggestion;
26797 else
26798 S.Diag(Loc, DiagID: diag::warn_omp_assume_attribute_string_unknown)
26799 << AssumptionStr;
26800}
26801
26802void SemaOpenMP::handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL) {
26803 // Handle the case where the attribute has a text message.
26804 StringRef Str;
26805 SourceLocation AttrStrLoc;
26806 if (!SemaRef.checkStringLiteralArgumentAttr(Attr: AL, ArgNum: 0, Str, ArgLocation: &AttrStrLoc))
26807 return;
26808
26809 checkOMPAssumeAttr(S&: SemaRef, Loc: AttrStrLoc, AssumptionStr: Str);
26810
26811 D->addAttr(A: ::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
26812}
26813
26814SemaOpenMP::SemaOpenMP(Sema &S)
26815 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
26816