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 void setOrderedToBlockAssociated() {
1260 assert(getCurrentDirective() == OMPD_ordered_standalone);
1261 getTopOfStack().Directive = OMPD_ordered_blockassoc;
1262 }
1263};
1264
1265bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1266 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1267}
1268
1269bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1270 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(Kind: DKind) ||
1271 DKind == OMPD_unknown;
1272}
1273
1274} // namespace
1275
1276static const Expr *getExprAsWritten(const Expr *E) {
1277 if (const auto *FE = dyn_cast<FullExpr>(Val: E))
1278 E = FE->getSubExpr();
1279
1280 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Val: E))
1281 E = MTE->getSubExpr();
1282
1283 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(Val: E))
1284 E = Binder->getSubExpr();
1285
1286 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(Val: E))
1287 E = ICE->getSubExprAsWritten();
1288 return E->IgnoreParens();
1289}
1290
1291static Expr *getExprAsWritten(Expr *E) {
1292 return const_cast<Expr *>(getExprAsWritten(E: const_cast<const Expr *>(E)));
1293}
1294
1295static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1296 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: D))
1297 if (const auto *ME = dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit())))
1298 D = ME->getMemberDecl();
1299
1300 D = cast<ValueDecl>(Val: D->getCanonicalDecl());
1301 return D;
1302}
1303
1304static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1305 return const_cast<ValueDecl *>(
1306 getCanonicalDecl(D: const_cast<const ValueDecl *>(D)));
1307}
1308
1309static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C) {
1310 if (C == OMPC_threadprivate)
1311 return getOpenMPClauseName(C).str() + " or thread local";
1312 return getOpenMPClauseName(C).str();
1313}
1314
1315DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1316 ValueDecl *D) const {
1317 D = getCanonicalDecl(D);
1318 auto *VD = dyn_cast<VarDecl>(Val: D);
1319 const auto *FD = dyn_cast<FieldDecl>(Val: D);
1320 DSAVarData DVar;
1321 if (Iter == end()) {
1322 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1323 // in a region but not in construct]
1324 // File-scope or namespace-scope variables referenced in called routines
1325 // in the region are shared unless they appear in a threadprivate
1326 // directive.
1327 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(Val: VD))
1328 DVar.CKind = OMPC_shared;
1329
1330 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1331 // in a region but not in construct]
1332 // Variables with static storage duration that are declared in called
1333 // routines in the region are shared.
1334 if (VD && VD->hasGlobalStorage())
1335 DVar.CKind = OMPC_shared;
1336
1337 // Non-static data members are shared by default.
1338 if (FD)
1339 DVar.CKind = OMPC_shared;
1340
1341 return DVar;
1342 }
1343
1344 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1345 // in a Construct, C/C++, predetermined, p.1]
1346 // Variables with automatic storage duration that are declared in a scope
1347 // inside the construct are private.
1348 if (VD && isOpenMPLocal(D: VD, Iter) && VD->isLocalVarDecl() &&
1349 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1350 DVar.CKind = OMPC_private;
1351 return DVar;
1352 }
1353
1354 DVar.DKind = Iter->Directive;
1355 // Explicitly specified attributes and local variables with predetermined
1356 // attributes.
1357 if (Iter->SharingMap.count(Val: D)) {
1358 const DSAInfo &Data = Iter->SharingMap.lookup(Val: D);
1359 DVar.RefExpr = Data.RefExpr.getPointer();
1360 DVar.PrivateCopy = Data.PrivateCopy;
1361 DVar.CKind = Data.Attributes;
1362 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1363 DVar.Modifier = Data.Modifier;
1364 DVar.AppliedToPointee = Data.AppliedToPointee;
1365 return DVar;
1366 }
1367
1368 DefaultDataSharingAttributes IterDA = Iter->DefaultAttr;
1369 switch (Iter->DefaultVCAttr) {
1370 case DSA_VC_aggregate:
1371 if (!D->getType()->isAggregateType())
1372 IterDA = DSA_none;
1373 break;
1374 case DSA_VC_pointer:
1375 if (!D->getType()->isPointerType())
1376 IterDA = DSA_none;
1377 break;
1378 case DSA_VC_scalar:
1379 if (!D->getType()->isScalarType())
1380 IterDA = DSA_none;
1381 break;
1382 case DSA_VC_all:
1383 break;
1384 }
1385
1386 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1387 // in a Construct, C/C++, implicitly determined, p.1]
1388 // In a parallel or task construct, the data-sharing attributes of these
1389 // variables are determined by the default clause, if present.
1390 switch (IterDA) {
1391 case DSA_shared:
1392 DVar.CKind = OMPC_shared;
1393 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1394 return DVar;
1395 case DSA_none:
1396 return DVar;
1397 case DSA_firstprivate:
1398 if (VD && VD->getStorageDuration() == SD_Static &&
1399 VD->getDeclContext()->isFileContext()) {
1400 DVar.CKind = OMPC_unknown;
1401 } else {
1402 DVar.CKind = OMPC_firstprivate;
1403 }
1404 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1405 return DVar;
1406 case DSA_private:
1407 // each variable with static storage duration that is declared
1408 // in a namespace or global scope and referenced in the construct,
1409 // and that does not have a predetermined data-sharing attribute
1410 if (VD && VD->getStorageDuration() == SD_Static &&
1411 VD->getDeclContext()->isFileContext()) {
1412 DVar.CKind = OMPC_unknown;
1413 } else {
1414 DVar.CKind = OMPC_private;
1415 }
1416 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1417 return DVar;
1418 case DSA_unspecified:
1419 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1420 // in a Construct, implicitly determined, p.2]
1421 // In a parallel construct, if no default clause is present, these
1422 // variables are shared.
1423 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1424 if ((isOpenMPParallelDirective(DKind: DVar.DKind) &&
1425 !isOpenMPTaskLoopDirective(DKind: DVar.DKind)) ||
1426 isOpenMPTeamsDirective(DKind: DVar.DKind)) {
1427 DVar.CKind = OMPC_shared;
1428 return DVar;
1429 }
1430
1431 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1432 // in a Construct, implicitly determined, p.4]
1433 // In a task construct, if no default clause is present, a variable that in
1434 // the enclosing context is determined to be shared by all implicit tasks
1435 // bound to the current team is shared.
1436 if (isOpenMPTaskingDirective(Kind: DVar.DKind)) {
1437 DSAVarData DVarTemp;
1438 const_iterator I = Iter, E = end();
1439 do {
1440 ++I;
1441 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1442 // Referenced in a Construct, implicitly determined, p.6]
1443 // In a task construct, if no default clause is present, a variable
1444 // whose data-sharing attribute is not determined by the rules above is
1445 // firstprivate.
1446 DVarTemp = getDSA(Iter&: I, D);
1447 if (DVarTemp.CKind != OMPC_shared) {
1448 DVar.RefExpr = nullptr;
1449 DVar.CKind = OMPC_firstprivate;
1450 return DVar;
1451 }
1452 } while (I != E && !isImplicitTaskingRegion(DKind: I->Directive));
1453 DVar.CKind =
1454 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1455 return DVar;
1456 }
1457 }
1458 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1459 // in a Construct, implicitly determined, p.3]
1460 // For constructs other than task, if no default clause is present, these
1461 // variables inherit their data-sharing attributes from the enclosing
1462 // context.
1463 return getDSA(Iter&: ++Iter, D);
1464}
1465
1466const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1467 const Expr *NewDE) {
1468 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1469 D = getCanonicalDecl(D);
1470 SharingMapTy &StackElem = getTopOfStack();
1471 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(Key: D, Args&: NewDE);
1472 if (Inserted) {
1473 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1474 return nullptr;
1475 }
1476 assert(It->second && "Unexpected nullptr expr in the aligned map");
1477 return It->second;
1478}
1479
1480const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1481 const Expr *NewDE) {
1482 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1483 D = getCanonicalDecl(D);
1484 SharingMapTy &StackElem = getTopOfStack();
1485 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(Key: D, Args&: NewDE);
1486 if (Inserted) {
1487 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1488 return nullptr;
1489 }
1490 assert(It->second && "Unexpected nullptr expr in the aligned map");
1491 return It->second;
1492}
1493
1494void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1495 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1496 D = getCanonicalDecl(D);
1497 SharingMapTy &StackElem = getTopOfStack();
1498 StackElem.LCVMap.try_emplace(
1499 Key: D, Args: LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1500}
1501
1502const DSAStackTy::LCDeclInfo
1503DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1504 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1505 D = getCanonicalDecl(D);
1506 const SharingMapTy &StackElem = getTopOfStack();
1507 auto It = StackElem.LCVMap.find(Val: D);
1508 if (It != StackElem.LCVMap.end())
1509 return It->second;
1510 return {0, nullptr};
1511}
1512
1513const DSAStackTy::LCDeclInfo
1514DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1515 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1516 D = getCanonicalDecl(D);
1517 for (unsigned I = Level + 1; I > 0; --I) {
1518 const SharingMapTy &StackElem = getStackElemAtLevel(Level: I - 1);
1519 auto It = StackElem.LCVMap.find(Val: D);
1520 if (It != StackElem.LCVMap.end())
1521 return It->second;
1522 }
1523 return {0, nullptr};
1524}
1525
1526const DSAStackTy::LCDeclInfo
1527DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1528 const SharingMapTy *Parent = getSecondOnStackOrNull();
1529 assert(Parent && "Data-sharing attributes stack is empty");
1530 D = getCanonicalDecl(D);
1531 auto It = Parent->LCVMap.find(Val: D);
1532 if (It != Parent->LCVMap.end())
1533 return It->second;
1534 return {0, nullptr};
1535}
1536
1537const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1538 const SharingMapTy *Parent = getSecondOnStackOrNull();
1539 assert(Parent && "Data-sharing attributes stack is empty");
1540 if (Parent->LCVMap.size() < I)
1541 return nullptr;
1542 for (const auto &Pair : Parent->LCVMap)
1543 if (Pair.second.first == I)
1544 return Pair.first;
1545 return nullptr;
1546}
1547
1548void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1549 DeclRefExpr *PrivateCopy, unsigned Modifier,
1550 bool AppliedToPointee) {
1551 D = getCanonicalDecl(D);
1552 if (A == OMPC_threadprivate) {
1553 DSAInfo &Data = Threadprivates[D];
1554 Data.Attributes = A;
1555 Data.RefExpr.setPointer(E);
1556 Data.PrivateCopy = nullptr;
1557 Data.Modifier = Modifier;
1558 } else if (A == OMPC_groupprivate) {
1559 DSAInfo &Data = Groupprivates[D];
1560 Data.Attributes = A;
1561 Data.RefExpr.setPointer(E);
1562 Data.PrivateCopy = nullptr;
1563 Data.Modifier = Modifier;
1564 } else {
1565 DSAInfo &Data = getTopOfStack().SharingMap[D];
1566 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1567 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1568 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1569 (isLoopControlVariable(D).first && A == OMPC_private));
1570 Data.Modifier = Modifier;
1571 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1572 Data.RefExpr.setInt(/*IntVal=*/true);
1573 return;
1574 }
1575 const bool IsLastprivate =
1576 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1577 Data.Attributes = A;
1578 Data.RefExpr.setPointerAndInt(PtrVal: E, IntVal: IsLastprivate);
1579 Data.PrivateCopy = PrivateCopy;
1580 Data.AppliedToPointee = AppliedToPointee;
1581 if (PrivateCopy) {
1582 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1583 Data.Modifier = Modifier;
1584 Data.Attributes = A;
1585 Data.RefExpr.setPointerAndInt(PtrVal: PrivateCopy, IntVal: IsLastprivate);
1586 Data.PrivateCopy = nullptr;
1587 Data.AppliedToPointee = AppliedToPointee;
1588 }
1589 }
1590}
1591
1592/// Build a variable declaration for OpenMP loop iteration variable.
1593static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
1594 StringRef Name, const AttrVec *Attrs = nullptr,
1595 DeclRefExpr *OrigRef = nullptr) {
1596 DeclContext *DC = SemaRef.CurContext;
1597 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1598 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(T: Type, Loc);
1599 auto *Decl =
1600 VarDecl::Create(C&: SemaRef.Context, DC, StartLoc: Loc, IdLoc: Loc, Id: II, T: Type, TInfo, S: SC_None);
1601 if (Attrs) {
1602 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1603 I != E; ++I)
1604 Decl->addAttr(A: *I);
1605 }
1606 Decl->setImplicit();
1607 if (OrigRef) {
1608 Decl->addAttr(
1609 A: OMPReferencedVarAttr::CreateImplicit(Ctx&: SemaRef.Context, Ref: OrigRef));
1610 }
1611 return Decl;
1612}
1613
1614static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
1615 SourceLocation Loc,
1616 bool RefersToCapture = false) {
1617 D->setReferenced();
1618 D->markUsed(C&: S.Context);
1619 return DeclRefExpr::Create(Context: S.getASTContext(), QualifierLoc: NestedNameSpecifierLoc(),
1620 TemplateKWLoc: SourceLocation(), D, RefersToEnclosingVariableOrCapture: RefersToCapture, NameLoc: Loc, T: Ty,
1621 VK: VK_LValue);
1622}
1623
1624void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1625 BinaryOperatorKind BOK) {
1626 D = getCanonicalDecl(D);
1627 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1628 assert(
1629 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1630 "Additional reduction info may be specified only for reduction items.");
1631 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1632 assert(ReductionData.ReductionRange.isInvalid() &&
1633 (getTopOfStack().Directive == OMPD_taskgroup ||
1634 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1635 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1636 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1637 "Additional reduction info may be specified only once for reduction "
1638 "items.");
1639 ReductionData.set(BO: BOK, RR: SR);
1640 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1641 if (!TaskgroupReductionRef) {
1642 VarDecl *VD = buildVarDecl(SemaRef, Loc: SR.getBegin(),
1643 Type: SemaRef.Context.VoidPtrTy, Name: ".task_red.");
1644 TaskgroupReductionRef =
1645 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: SemaRef.Context.VoidPtrTy, Loc: SR.getBegin());
1646 }
1647}
1648
1649void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1650 const Expr *ReductionRef) {
1651 D = getCanonicalDecl(D);
1652 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1653 assert(
1654 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1655 "Additional reduction info may be specified only for reduction items.");
1656 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1657 assert(ReductionData.ReductionRange.isInvalid() &&
1658 (getTopOfStack().Directive == OMPD_taskgroup ||
1659 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1660 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1661 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1662 "Additional reduction info may be specified only once for reduction "
1663 "items.");
1664 ReductionData.set(RefExpr: ReductionRef, RR: SR);
1665 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1666 if (!TaskgroupReductionRef) {
1667 VarDecl *VD = buildVarDecl(SemaRef, Loc: SR.getBegin(),
1668 Type: SemaRef.Context.VoidPtrTy, Name: ".task_red.");
1669 TaskgroupReductionRef =
1670 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: SemaRef.Context.VoidPtrTy, Loc: SR.getBegin());
1671 }
1672}
1673
1674const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1675 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1676 Expr *&TaskgroupDescriptor) const {
1677 D = getCanonicalDecl(D);
1678 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1679 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1680 const DSAInfo &Data = I->SharingMap.lookup(Val: D);
1681 if (Data.Attributes != OMPC_reduction ||
1682 Data.Modifier != OMPC_REDUCTION_task)
1683 continue;
1684 const ReductionData &ReductionData = I->ReductionMap.lookup(Val: D);
1685 if (!ReductionData.ReductionOp ||
1686 isa<const Expr *>(Val: ReductionData.ReductionOp))
1687 return DSAVarData();
1688 SR = ReductionData.ReductionRange;
1689 BOK = cast<ReductionData::BOKPtrType>(Val: ReductionData.ReductionOp);
1690 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1691 "expression for the descriptor is not "
1692 "set.");
1693 TaskgroupDescriptor = I->TaskgroupReductionRef;
1694 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1695 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1696 /*AppliedToPointee=*/false);
1697 }
1698 return DSAVarData();
1699}
1700
1701const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1702 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1703 Expr *&TaskgroupDescriptor) const {
1704 D = getCanonicalDecl(D);
1705 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1706 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1707 const DSAInfo &Data = I->SharingMap.lookup(Val: D);
1708 if (Data.Attributes != OMPC_reduction ||
1709 Data.Modifier != OMPC_REDUCTION_task)
1710 continue;
1711 const ReductionData &ReductionData = I->ReductionMap.lookup(Val: D);
1712 if (!ReductionData.ReductionOp ||
1713 !isa<const Expr *>(Val: ReductionData.ReductionOp))
1714 return DSAVarData();
1715 SR = ReductionData.ReductionRange;
1716 ReductionRef = cast<const Expr *>(Val: ReductionData.ReductionOp);
1717 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1718 "expression for the descriptor is not "
1719 "set.");
1720 TaskgroupDescriptor = I->TaskgroupReductionRef;
1721 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1722 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1723 /*AppliedToPointee=*/false);
1724 }
1725 return DSAVarData();
1726}
1727
1728bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1729 D = D->getCanonicalDecl();
1730 for (const_iterator E = end(); I != E; ++I) {
1731 if (isImplicitOrExplicitTaskingRegion(DKind: I->Directive) ||
1732 isOpenMPTargetExecutionDirective(DKind: I->Directive)) {
1733 if (I->CurScope) {
1734 Scope *TopScope = I->CurScope->getParent();
1735 Scope *CurScope = getCurScope();
1736 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1737 CurScope = CurScope->getParent();
1738 return CurScope != TopScope;
1739 }
1740 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1741 if (I->Context == DC)
1742 return true;
1743 return false;
1744 }
1745 }
1746 return false;
1747}
1748
1749static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
1750 bool AcceptIfMutable = true,
1751 bool *IsClassType = nullptr) {
1752 ASTContext &Context = SemaRef.getASTContext();
1753 Type = Type.getNonReferenceType().getCanonicalType();
1754 bool IsConstant = Type.isConstant(Ctx: Context);
1755 Type = Context.getBaseElementType(QT: Type);
1756 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1757 ? Type->getAsCXXRecordDecl()
1758 : nullptr;
1759 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(Val: RD))
1760 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1761 RD = CTD->getTemplatedDecl();
1762 if (IsClassType)
1763 *IsClassType = RD;
1764 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1765 RD->hasDefinition() && RD->hasMutableFields());
1766}
1767
1768static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1769 QualType Type, OpenMPClauseKind CKind,
1770 SourceLocation ELoc,
1771 bool AcceptIfMutable = true,
1772 bool ListItemNotVar = false) {
1773 ASTContext &Context = SemaRef.getASTContext();
1774 bool IsClassType;
1775 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, IsClassType: &IsClassType)) {
1776 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1777 : IsClassType ? diag::err_omp_const_not_mutable_variable
1778 : diag::err_omp_const_variable;
1779 SemaRef.Diag(Loc: ELoc, DiagID: Diag) << getOpenMPClauseNameForDiag(C: CKind);
1780 if (!ListItemNotVar && D) {
1781 const VarDecl *VD = dyn_cast<VarDecl>(Val: D);
1782 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1783 VarDecl::DeclarationOnly;
1784 SemaRef.Diag(Loc: D->getLocation(),
1785 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1786 << D;
1787 }
1788 return true;
1789 }
1790 return false;
1791}
1792
1793const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1794 bool FromParent) {
1795 D = getCanonicalDecl(D);
1796 DSAVarData DVar;
1797
1798 auto *VD = dyn_cast<VarDecl>(Val: D);
1799 auto TI = Threadprivates.find(Val: D);
1800 if (TI != Threadprivates.end()) {
1801 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1802 DVar.CKind = OMPC_threadprivate;
1803 DVar.Modifier = TI->getSecond().Modifier;
1804 return DVar;
1805 }
1806 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1807 DVar.RefExpr = buildDeclRefExpr(
1808 S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1809 Loc: VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1810 DVar.CKind = OMPC_threadprivate;
1811 addDSA(D, E: DVar.RefExpr, A: OMPC_threadprivate);
1812 return DVar;
1813 }
1814 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1815 // in a Construct, C/C++, predetermined, p.1]
1816 // Variables appearing in threadprivate directives are threadprivate.
1817 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1818 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1819 SemaRef.getLangOpts().OpenMPUseTLS &&
1820 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1821 (VD && VD->getStorageClass() == SC_Register &&
1822 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1823 DVar.RefExpr = buildDeclRefExpr(
1824 S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(), Loc: D->getLocation());
1825 DVar.CKind = OMPC_threadprivate;
1826 addDSA(D, E: DVar.RefExpr, A: OMPC_threadprivate);
1827 return DVar;
1828 }
1829 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1830 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1831 !isLoopControlVariable(D).first) {
1832 const_iterator IterTarget =
1833 std::find_if(first: begin(), last: end(), pred: [](const SharingMapTy &Data) {
1834 return isOpenMPTargetExecutionDirective(DKind: Data.Directive);
1835 });
1836 if (IterTarget != end()) {
1837 const_iterator ParentIterTarget = IterTarget + 1;
1838 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1839 if (isOpenMPLocal(D: VD, I: Iter)) {
1840 DVar.RefExpr =
1841 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1842 Loc: D->getLocation());
1843 DVar.CKind = OMPC_threadprivate;
1844 return DVar;
1845 }
1846 }
1847 if (!isClauseParsingMode() || IterTarget != begin()) {
1848 auto DSAIter = IterTarget->SharingMap.find(Val: D);
1849 if (DSAIter != IterTarget->SharingMap.end() &&
1850 isOpenMPPrivate(Kind: DSAIter->getSecond().Attributes)) {
1851 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1852 DVar.CKind = OMPC_threadprivate;
1853 return DVar;
1854 }
1855 const_iterator End = end();
1856 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1857 D, Level: std::distance(first: ParentIterTarget, last: End),
1858 /*OpenMPCaptureLevel=*/0)) {
1859 DVar.RefExpr =
1860 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1861 Loc: IterTarget->ConstructLoc);
1862 DVar.CKind = OMPC_threadprivate;
1863 return DVar;
1864 }
1865 }
1866 }
1867 }
1868
1869 if (isStackEmpty())
1870 // Not in OpenMP execution region and top scope was already checked.
1871 return DVar;
1872
1873 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1874 // in a Construct, C/C++, predetermined, p.4]
1875 // Static data members are shared.
1876 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1877 // in a Construct, C/C++, predetermined, p.7]
1878 // Variables with static storage duration that are declared in a scope
1879 // inside the construct are shared.
1880 if (VD && VD->isStaticDataMember()) {
1881 // Check for explicitly specified attributes.
1882 const_iterator I = begin();
1883 const_iterator EndI = end();
1884 if (FromParent && I != EndI)
1885 ++I;
1886 if (I != EndI) {
1887 auto It = I->SharingMap.find(Val: D);
1888 if (It != I->SharingMap.end()) {
1889 const DSAInfo &Data = It->getSecond();
1890 DVar.RefExpr = Data.RefExpr.getPointer();
1891 DVar.PrivateCopy = Data.PrivateCopy;
1892 DVar.CKind = Data.Attributes;
1893 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1894 DVar.DKind = I->Directive;
1895 DVar.Modifier = Data.Modifier;
1896 DVar.AppliedToPointee = Data.AppliedToPointee;
1897 return DVar;
1898 }
1899 }
1900
1901 DVar.CKind = OMPC_shared;
1902 return DVar;
1903 }
1904
1905 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1906 // The predetermined shared attribute for const-qualified types having no
1907 // mutable members was removed after OpenMP 3.1.
1908 if (SemaRef.LangOpts.OpenMP <= 31) {
1909 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1910 // in a Construct, C/C++, predetermined, p.6]
1911 // Variables with const qualified type having no mutable member are
1912 // shared.
1913 if (isConstNotMutableType(SemaRef, Type: D->getType())) {
1914 // Variables with const-qualified type having no mutable member may be
1915 // listed in a firstprivate clause, even if they are static data members.
1916 DSAVarData DVarTemp = hasInnermostDSA(
1917 D,
1918 CPred: [](OpenMPClauseKind C, bool) {
1919 return C == OMPC_firstprivate || C == OMPC_shared;
1920 },
1921 DPred: MatchesAlways, FromParent);
1922 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1923 return DVarTemp;
1924
1925 DVar.CKind = OMPC_shared;
1926 return DVar;
1927 }
1928 }
1929
1930 // Explicitly specified attributes and local variables with predetermined
1931 // attributes.
1932 const_iterator I = begin();
1933 const_iterator EndI = end();
1934 if (FromParent && I != EndI)
1935 ++I;
1936 if (I == EndI)
1937 return DVar;
1938 auto It = I->SharingMap.find(Val: D);
1939 if (It != I->SharingMap.end()) {
1940 const DSAInfo &Data = It->getSecond();
1941 DVar.RefExpr = Data.RefExpr.getPointer();
1942 DVar.PrivateCopy = Data.PrivateCopy;
1943 DVar.CKind = Data.Attributes;
1944 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1945 DVar.DKind = I->Directive;
1946 DVar.Modifier = Data.Modifier;
1947 DVar.AppliedToPointee = Data.AppliedToPointee;
1948 }
1949
1950 return DVar;
1951}
1952
1953const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1954 bool FromParent) const {
1955 if (isStackEmpty()) {
1956 const_iterator I;
1957 return getDSA(Iter&: I, D);
1958 }
1959 D = getCanonicalDecl(D);
1960 const_iterator StartI = begin();
1961 const_iterator EndI = end();
1962 if (FromParent && StartI != EndI)
1963 ++StartI;
1964 return getDSA(Iter&: StartI, D);
1965}
1966
1967const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1968 unsigned Level) const {
1969 if (getStackSize() <= Level)
1970 return DSAVarData();
1971 D = getCanonicalDecl(D);
1972 const_iterator StartI = std::next(x: begin(), n: getStackSize() - 1 - Level);
1973 return getDSA(Iter&: StartI, D);
1974}
1975
1976const DSAStackTy::DSAVarData
1977DSAStackTy::hasDSA(ValueDecl *D,
1978 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1979 DefaultDataSharingAttributes)>
1980 CPred,
1981 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1982 bool FromParent) const {
1983 if (isStackEmpty())
1984 return {};
1985 D = getCanonicalDecl(D);
1986 const_iterator I = begin();
1987 const_iterator EndI = end();
1988 if (FromParent && I != EndI)
1989 ++I;
1990 for (; I != EndI; ++I) {
1991 if (!DPred(I->Directive) &&
1992 !isImplicitOrExplicitTaskingRegion(DKind: I->Directive))
1993 continue;
1994 const_iterator NewI = I;
1995 DSAVarData DVar = getDSA(Iter&: NewI, D);
1996 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1997 return DVar;
1998 }
1999 return {};
2000}
2001
2002const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
2003 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2004 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2005 bool FromParent) const {
2006 if (isStackEmpty())
2007 return {};
2008 D = getCanonicalDecl(D);
2009 const_iterator StartI = begin();
2010 const_iterator EndI = end();
2011 if (FromParent && StartI != EndI)
2012 ++StartI;
2013 if (StartI == EndI || !DPred(StartI->Directive))
2014 return {};
2015 const_iterator NewI = StartI;
2016 DSAVarData DVar = getDSA(Iter&: NewI, D);
2017 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
2018 ? DVar
2019 : DSAVarData();
2020}
2021
2022bool DSAStackTy::hasExplicitDSA(
2023 const ValueDecl *D,
2024 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2025 unsigned Level, bool NotLastprivate) const {
2026 if (getStackSize() <= Level)
2027 return false;
2028 D = getCanonicalDecl(D);
2029 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2030 auto I = StackElem.SharingMap.find(Val: D);
2031 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
2032 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
2033 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
2034 return true;
2035 // Check predetermined rules for the loop control variables.
2036 auto LI = StackElem.LCVMap.find(Val: D);
2037 if (LI != StackElem.LCVMap.end())
2038 return CPred(OMPC_private, /*AppliedToPointee=*/false);
2039 return false;
2040}
2041
2042bool DSAStackTy::hasExplicitDirective(
2043 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2044 unsigned Level) const {
2045 if (getStackSize() <= Level)
2046 return false;
2047 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2048 return DPred(StackElem.Directive);
2049}
2050
2051bool DSAStackTy::hasDirective(
2052 const llvm::function_ref<bool(OpenMPDirectiveKind,
2053 const DeclarationNameInfo &, SourceLocation)>
2054 DPred,
2055 bool FromParent) const {
2056 // We look only in the enclosing region.
2057 size_t Skip = FromParent ? 2 : 1;
2058 for (const_iterator I = begin() + std::min(a: Skip, b: getStackSize()), E = end();
2059 I != E; ++I) {
2060 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2061 return true;
2062 }
2063 return false;
2064}
2065
2066void SemaOpenMP::InitDataSharingAttributesStack() {
2067 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2068}
2069
2070#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2071
2072void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2073
2074void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2075 DSAStack->popFunction(OldFSI);
2076}
2077
2078static bool isOpenMPDeviceDelayedContext(Sema &S) {
2079 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2080 "Expected OpenMP device compilation.");
2081 return !S.OpenMP().isInOpenMPTargetExecutionDirective();
2082}
2083
2084namespace {
2085/// Status of the function emission on the host/device.
2086enum class FunctionEmissionStatus {
2087 Emitted,
2088 Discarded,
2089 Unknown,
2090};
2091} // anonymous namespace
2092
2093SemaBase::SemaDiagnosticBuilder
2094SemaOpenMP::diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID,
2095 const FunctionDecl *FD) {
2096 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2097 "Expected OpenMP device compilation.");
2098
2099 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2100 if (FD) {
2101 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(Decl: FD);
2102 switch (FES) {
2103 case Sema::FunctionEmissionStatus::Emitted:
2104 Kind = SemaDiagnosticBuilder::K_Immediate;
2105 break;
2106 case Sema::FunctionEmissionStatus::Unknown:
2107 // TODO: We should always delay diagnostics here in case a target
2108 // region is in a function we do not emit. However, as the
2109 // current diagnostics are associated with the function containing
2110 // the target region and we do not emit that one, we would miss out
2111 // on diagnostics for the target region itself. We need to anchor
2112 // the diagnostics with the new generated function *or* ensure we
2113 // emit diagnostics associated with the surrounding function.
2114 Kind = isOpenMPDeviceDelayedContext(S&: SemaRef)
2115 ? SemaDiagnosticBuilder::K_Deferred
2116 : SemaDiagnosticBuilder::K_Immediate;
2117 break;
2118 case Sema::FunctionEmissionStatus::TemplateDiscarded:
2119 case Sema::FunctionEmissionStatus::OMPDiscarded:
2120 Kind = SemaDiagnosticBuilder::K_Nop;
2121 break;
2122 case Sema::FunctionEmissionStatus::CUDADiscarded:
2123 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2124 break;
2125 }
2126 }
2127
2128 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2129}
2130
2131SemaBase::SemaDiagnosticBuilder
2132SemaOpenMP::diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID,
2133 const FunctionDecl *FD) {
2134 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2135 "Expected OpenMP host compilation.");
2136
2137 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2138 if (FD) {
2139 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(Decl: FD);
2140 switch (FES) {
2141 case Sema::FunctionEmissionStatus::Emitted:
2142 Kind = SemaDiagnosticBuilder::K_Immediate;
2143 break;
2144 case Sema::FunctionEmissionStatus::Unknown:
2145 Kind = SemaDiagnosticBuilder::K_Deferred;
2146 break;
2147 case Sema::FunctionEmissionStatus::TemplateDiscarded:
2148 case Sema::FunctionEmissionStatus::OMPDiscarded:
2149 case Sema::FunctionEmissionStatus::CUDADiscarded:
2150 Kind = SemaDiagnosticBuilder::K_Nop;
2151 break;
2152 }
2153 }
2154
2155 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2156}
2157
2158static OpenMPDefaultmapClauseKind
2159getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) {
2160 if (LO.OpenMP <= 45) {
2161 if (VD->getType().getNonReferenceType()->isScalarType())
2162 return OMPC_DEFAULTMAP_scalar;
2163 return OMPC_DEFAULTMAP_aggregate;
2164 }
2165 if (VD->getType().getNonReferenceType()->isAnyPointerType())
2166 return OMPC_DEFAULTMAP_pointer;
2167 if (VD->getType().getNonReferenceType()->isScalarType())
2168 return OMPC_DEFAULTMAP_scalar;
2169 return OMPC_DEFAULTMAP_aggregate;
2170}
2171
2172bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2173 unsigned OpenMPCaptureLevel) const {
2174 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2175
2176 ASTContext &Ctx = getASTContext();
2177 bool IsByRef = true;
2178
2179 // Find the directive that is associated with the provided scope.
2180 D = cast<ValueDecl>(Val: D->getCanonicalDecl());
2181 QualType Ty = D->getType();
2182
2183 bool IsVariableUsedInMapClause = false;
2184 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective, Level)) {
2185 // This table summarizes how a given variable should be passed to the device
2186 // given its type and the clauses where it appears. This table is based on
2187 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2188 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2189 //
2190 // =========================================================================
2191 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2192 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2193 // =========================================================================
2194 // | scl | | | | - | | bycopy|
2195 // | scl | | - | x | - | - | bycopy|
2196 // | scl | | x | - | - | - | null |
2197 // | scl | x | | | - | | byref |
2198 // | scl | x | - | x | - | - | bycopy|
2199 // | scl | x | x | - | - | - | null |
2200 // | scl | | - | - | - | x | byref |
2201 // | scl | x | - | - | - | x | byref |
2202 //
2203 // | agg | n.a. | | | - | | byref |
2204 // | agg | n.a. | - | x | - | - | byref |
2205 // | agg | n.a. | x | - | - | - | null |
2206 // | agg | n.a. | - | - | - | x | byref |
2207 // | agg | n.a. | - | - | - | x[] | byref |
2208 //
2209 // | ptr | n.a. | | | - | | bycopy|
2210 // | ptr | n.a. | - | x | - | - | bycopy|
2211 // | ptr | n.a. | x | - | - | - | null |
2212 // | ptr | n.a. | - | - | - | x | byref |
2213 // | ptr | n.a. | - | - | - | x, x[] | bycopy|
2214 // | ptr | n.a. | - | - | - | x[] | bycopy|
2215 // | ptr | n.a. | - | - | x | | bycopy|
2216 // | ptr | n.a. | - | - | x | x | bycopy|
2217 // | ptr | n.a. | - | - | x | x[] | bycopy|
2218 // =========================================================================
2219 // Legend:
2220 // scl - scalar
2221 // ptr - pointer
2222 // agg - aggregate
2223 // x - applies
2224 // - - invalid in this combination
2225 // [] - mapped with an array section
2226 // byref - should be mapped by reference
2227 // byval - should be mapped by value
2228 // null - initialize a local variable to null on the device
2229 //
2230 // Observations:
2231 // - All scalar declarations that show up in a map clause have to be passed
2232 // by reference, because they may have been mapped in the enclosing data
2233 // environment.
2234 // - If the scalar value does not fit the size of uintptr, it has to be
2235 // passed by reference, regardless the result in the table above.
2236 // - For pointers mapped by value that have either an implicit map or an
2237 // array section, the runtime library may pass the NULL value to the
2238 // device instead of the value passed to it by the compiler.
2239 // - If both a pointer and a dereference of it are mapped, then the pointer
2240 // should be passed by reference.
2241
2242 if (Ty->isReferenceType())
2243 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2244
2245 // Locate map clauses and see if the variable being captured is mapped by
2246 // itself, or referred to, in any of those clauses. Here we only care about
2247 // variables, not fields, because fields are part of aggregates.
2248 bool IsVariableAssociatedWithSection = false;
2249 bool IsVariableItselfMapped = false;
2250
2251 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2252 VD: D, Level,
2253 Check: [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2254 &IsVariableItselfMapped,
2255 D](OMPClauseMappableExprCommon::MappableExprComponentListRef
2256 MapExprComponents,
2257 OpenMPClauseKind WhereFoundClauseKind) {
2258 // Both map and has_device_addr clauses information influences how a
2259 // variable is captured. E.g. is_device_ptr does not require changing
2260 // the default behavior.
2261 if (WhereFoundClauseKind != OMPC_map &&
2262 WhereFoundClauseKind != OMPC_has_device_addr)
2263 return false;
2264
2265 auto EI = MapExprComponents.rbegin();
2266 auto EE = MapExprComponents.rend();
2267
2268 assert(EI != EE && "Invalid map expression!");
2269
2270 if (isa<DeclRefExpr>(Val: EI->getAssociatedExpression()) &&
2271 EI->getAssociatedDeclaration() == D) {
2272 IsVariableUsedInMapClause = true;
2273
2274 // If the component list has only one element, it's for mapping the
2275 // variable itself, like map(p). This takes precedence in
2276 // determining how it's captured, so we don't need to look further
2277 // for any other maps that use the variable (like map(p[0]) etc.)
2278 if (MapExprComponents.size() == 1) {
2279 IsVariableItselfMapped = true;
2280 return true;
2281 }
2282 }
2283
2284 ++EI;
2285 if (EI == EE)
2286 return false;
2287 auto Last = std::prev(x: EE);
2288 const auto *UO =
2289 dyn_cast<UnaryOperator>(Val: Last->getAssociatedExpression());
2290 if ((UO && UO->getOpcode() == UO_Deref) ||
2291 isa<ArraySubscriptExpr>(Val: Last->getAssociatedExpression()) ||
2292 isa<ArraySectionExpr>(Val: Last->getAssociatedExpression()) ||
2293 isa<MemberExpr>(Val: EI->getAssociatedExpression()) ||
2294 isa<OMPArrayShapingExpr>(Val: Last->getAssociatedExpression())) {
2295 IsVariableAssociatedWithSection = true;
2296 // We've found a case like map(p[0]) or map(p->a) or map(*p),
2297 // so we are done with this particular map, but we need to keep
2298 // looking in case we find a map(p).
2299 return false;
2300 }
2301
2302 // Keep looking for more map info.
2303 return false;
2304 });
2305
2306 if (IsVariableUsedInMapClause) {
2307 // If variable is identified in a map clause it is always captured by
2308 // reference except if it is a pointer that is dereferenced somehow, but
2309 // not itself mapped.
2310 //
2311 // OpenMP 6.0, 7.1.1: Data sharing attribute rules, variables referenced
2312 // in a construct::
2313 // If a list item in a has_device_addr clause or in a map clause on the
2314 // target construct has a base pointer, and the base pointer is a scalar
2315 // variable *that is not a list item in a map clause on the construct*,
2316 // the base pointer is firstprivate.
2317 //
2318 // OpenMP 4.5, 2.15.1.1: Data-sharing Attribute Rules for Variables
2319 // Referenced in a Construct:
2320 // If an array section is a list item in a map clause on the target
2321 // construct and the array section is derived from a variable for which
2322 // the type is pointer then that variable is firstprivate.
2323 IsByRef = IsVariableItselfMapped ||
2324 !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2325 } else {
2326 // By default, all the data that has a scalar type is mapped by copy
2327 // (except for reduction variables).
2328 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2329 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2330 !Ty->isAnyPointerType()) ||
2331 !Ty->isScalarType() ||
2332 DSAStack->isDefaultmapCapturedByRef(
2333 Level, Kind: getVariableCategoryFromDecl(LO: getLangOpts(), VD: D)) ||
2334 DSAStack->hasExplicitDSA(
2335 D,
2336 CPred: [](OpenMPClauseKind K, bool AppliedToPointee) {
2337 return K == OMPC_reduction && !AppliedToPointee;
2338 },
2339 Level);
2340 }
2341 }
2342
2343 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2344 IsByRef =
2345 ((IsVariableUsedInMapClause &&
2346 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2347 OMPD_target) ||
2348 !(DSAStack->hasExplicitDSA(
2349 D,
2350 CPred: [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2351 return K == OMPC_firstprivate ||
2352 (K == OMPC_reduction && AppliedToPointee);
2353 },
2354 Level, /*NotLastprivate=*/true) ||
2355 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2356 // If the variable is artificial and must be captured by value - try to
2357 // capture by value.
2358 !(isa<OMPCapturedExprDecl>(Val: D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2359 !cast<OMPCapturedExprDecl>(Val: D)->getInit()->isGLValue()) &&
2360 // If the variable is implicitly firstprivate and scalar - capture by
2361 // copy
2362 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2363 DSAStack->getDefaultDSA() == DSA_private) &&
2364 !DSAStack->hasExplicitDSA(
2365 D, CPred: [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2366 Level) &&
2367 !DSAStack->isLoopControlVariable(D, Level).first);
2368 }
2369
2370 // When passing data by copy, we need to make sure it fits the uintptr size
2371 // and alignment, because the runtime library only deals with uintptr types.
2372 // If it does not fit the uintptr size, we need to pass the data by reference
2373 // instead.
2374 if (!IsByRef && (Ctx.getTypeSizeInChars(T: Ty) >
2375 Ctx.getTypeSizeInChars(T: Ctx.getUIntPtrType()) ||
2376 Ctx.getAlignOfGlobalVarInChars(T: Ty, VD: dyn_cast<VarDecl>(Val: D)) >
2377 Ctx.getTypeAlignInChars(T: Ctx.getUIntPtrType()))) {
2378 IsByRef = true;
2379 }
2380
2381 return IsByRef;
2382}
2383
2384unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2385 assert(getLangOpts().OpenMP);
2386 return DSAStack->getNestingLevel();
2387}
2388
2389bool SemaOpenMP::isInOpenMPTaskUntiedContext() const {
2390 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2391 DSAStack->isUntiedRegion();
2392}
2393
2394bool SemaOpenMP::isInOpenMPTargetExecutionDirective() const {
2395 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2396 !DSAStack->isClauseParsingMode()) ||
2397 DSAStack->hasDirective(
2398 DPred: [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2399 SourceLocation) -> bool {
2400 return isOpenMPTargetExecutionDirective(DKind: K);
2401 },
2402 FromParent: false);
2403}
2404
2405bool SemaOpenMP::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2406 // Only rebuild for Field.
2407 if (!isa<FieldDecl>(Val: D))
2408 return false;
2409 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2410 D,
2411 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2412 DefaultDataSharingAttributes DefaultAttr) {
2413 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2414 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2415 },
2416 DPred: [](OpenMPDirectiveKind) { return true; },
2417 DSAStack->isClauseParsingMode());
2418 if (DVarPrivate.CKind != OMPC_unknown)
2419 return true;
2420 return false;
2421}
2422
2423static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
2424 Expr *CaptureExpr, bool WithInit,
2425 DeclContext *CurContext,
2426 bool AsExpression);
2427
2428VarDecl *SemaOpenMP::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2429 unsigned StopAt) {
2430 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2431 D = getCanonicalDecl(D);
2432
2433 auto *VD = dyn_cast<VarDecl>(Val: D);
2434 // Do not capture constexpr variables.
2435 if (VD && VD->isConstexpr())
2436 return nullptr;
2437
2438 // If we want to determine whether the variable should be captured from the
2439 // perspective of the current capturing scope, and we've already left all the
2440 // capturing scopes of the top directive on the stack, check from the
2441 // perspective of its parent directive (if any) instead.
2442 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2443 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2444
2445 // If we are attempting to capture a global variable in a directive with
2446 // 'target' we return true so that this global is also mapped to the device.
2447 //
2448 if (VD && !VD->hasLocalStorage() &&
2449 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2450 SemaRef.getCurLambda())) {
2451 if (isInOpenMPTargetExecutionDirective()) {
2452 DSAStackTy::DSAVarData DVarTop =
2453 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2454 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2455 return VD;
2456 // If the declaration is enclosed in a 'declare target' directive,
2457 // then it should not be captured.
2458 //
2459 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2460 return nullptr;
2461 CapturedRegionScopeInfo *CSI = nullptr;
2462 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2463 RangeOrContainer: llvm::reverse(C&: SemaRef.FunctionScopes),
2464 N: CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2465 : 0)) {
2466 if (!isa<CapturingScopeInfo>(Val: FSI))
2467 return nullptr;
2468 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(Val: FSI))
2469 if (RSI->CapRegionKind == CR_OpenMP) {
2470 CSI = RSI;
2471 break;
2472 }
2473 }
2474 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2475 SmallVector<OpenMPDirectiveKind, 4> Regions;
2476 getOpenMPCaptureRegions(CaptureRegions&: Regions,
2477 DSAStack->getDirective(Level: CSI->OpenMPLevel));
2478 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2479 return VD;
2480 }
2481 if (isInOpenMPDeclareTargetContext()) {
2482 // Try to mark variable as declare target if it is used in capturing
2483 // regions.
2484 if (getLangOpts().OpenMP <= 45 &&
2485 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2486 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: VD);
2487 return nullptr;
2488 }
2489 }
2490
2491 if (CheckScopeInfo) {
2492 bool OpenMPFound = false;
2493 for (unsigned I = StopAt + 1; I > 0; --I) {
2494 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2495 if (!isa<CapturingScopeInfo>(Val: FSI))
2496 return nullptr;
2497 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(Val: FSI))
2498 if (RSI->CapRegionKind == CR_OpenMP) {
2499 OpenMPFound = true;
2500 break;
2501 }
2502 }
2503 if (!OpenMPFound)
2504 return nullptr;
2505 }
2506
2507 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2508 (!DSAStack->isClauseParsingMode() ||
2509 DSAStack->getParentDirective() != OMPD_unknown)) {
2510 auto &&Info = DSAStack->isLoopControlVariable(D);
2511 if (Info.first ||
2512 (VD && VD->hasLocalStorage() &&
2513 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2514 (VD && DSAStack->isForceVarCapturing()))
2515 return VD ? VD : Info.second;
2516 DSAStackTy::DSAVarData DVarTop =
2517 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2518 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(Kind: DVarTop.CKind) &&
2519 (!VD || VD->hasLocalStorage() ||
2520 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2521 return VD ? VD : cast<VarDecl>(Val: DVarTop.PrivateCopy->getDecl());
2522 // Threadprivate variables must not be captured.
2523 if (isOpenMPThreadPrivate(Kind: DVarTop.CKind))
2524 return nullptr;
2525 // The variable is not private or it is the variable in the directive with
2526 // default(none) clause and not used in any clause.
2527 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2528 D,
2529 CPred: [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2530 return isOpenMPPrivate(Kind: C) && !AppliedToPointee;
2531 },
2532 DPred: [](OpenMPDirectiveKind) { return true; },
2533 DSAStack->isClauseParsingMode());
2534 // Global shared must not be captured.
2535 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2536 ((DSAStack->getDefaultDSA() != DSA_none &&
2537 DSAStack->getDefaultDSA() != DSA_private &&
2538 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2539 DVarTop.CKind == OMPC_shared))
2540 return nullptr;
2541 auto *FD = dyn_cast<FieldDecl>(Val: D);
2542 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2543 !DVarPrivate.PrivateCopy) {
2544 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2545 D,
2546 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2547 DefaultDataSharingAttributes DefaultAttr) {
2548 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2549 (DefaultAttr == DSA_firstprivate ||
2550 DefaultAttr == DSA_private);
2551 },
2552 DPred: [](OpenMPDirectiveKind) { return true; },
2553 DSAStack->isClauseParsingMode());
2554 if (DVarPrivate.CKind == OMPC_unknown)
2555 return nullptr;
2556
2557 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2558 if (VD)
2559 return VD;
2560 if (SemaRef.getCurrentThisType().isNull())
2561 return nullptr;
2562 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(Loc: SourceLocation(),
2563 Type: SemaRef.getCurrentThisType(),
2564 /*IsImplicit=*/true);
2565 const CXXScopeSpec CS = CXXScopeSpec();
2566 Expr *ME = SemaRef.BuildMemberExpr(
2567 Base: ThisExpr, /*IsArrow=*/true, OpLoc: SourceLocation(),
2568 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: FD,
2569 FoundDecl: DeclAccessPair::make(D: FD, AS: FD->getAccess()),
2570 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(), Ty: FD->getType(),
2571 VK: VK_LValue, OK: OK_Ordinary);
2572 OMPCapturedExprDecl *CD = buildCaptureDecl(
2573 S&: SemaRef, Id: FD->getIdentifier(), CaptureExpr: ME, WithInit: DVarPrivate.CKind != OMPC_private,
2574 CurContext: SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2575 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2576 S&: SemaRef, D: CD, Ty: CD->getType().getNonReferenceType(), Loc: SourceLocation());
2577 VD = cast<VarDecl>(Val: VDPrivateRefExpr->getDecl());
2578 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2579 return VD;
2580 }
2581 if (DVarPrivate.CKind != OMPC_unknown ||
2582 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2583 DSAStack->getDefaultDSA() == DSA_private ||
2584 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2585 return VD ? VD : cast<VarDecl>(Val: DVarPrivate.PrivateCopy->getDecl());
2586 }
2587 return nullptr;
2588}
2589
2590void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2591 unsigned Level) const {
2592 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2593}
2594
2595void SemaOpenMP::startOpenMPLoop() {
2596 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2597 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2598 DSAStack->loopInit();
2599}
2600
2601void SemaOpenMP::startOpenMPCXXRangeFor() {
2602 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2603 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2604 DSAStack->resetPossibleLoopCounter();
2605 DSAStack->loopStart();
2606 }
2607}
2608
2609OpenMPClauseKind SemaOpenMP::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2610 unsigned CapLevel) const {
2611 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2612 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2613 (!DSAStack->isClauseParsingMode() ||
2614 DSAStack->getParentDirective() != OMPD_unknown)) {
2615 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2616 D,
2617 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2618 DefaultDataSharingAttributes DefaultAttr) {
2619 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2620 DefaultAttr == DSA_private;
2621 },
2622 DPred: [](OpenMPDirectiveKind) { return true; },
2623 DSAStack->isClauseParsingMode());
2624 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(Val: D) &&
2625 DSAStack->isImplicitDefaultFirstprivateFD(VD: cast<VarDecl>(Val: D)) &&
2626 !DSAStack->isLoopControlVariable(D).first)
2627 return OMPC_private;
2628 }
2629 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTaskingDirective, Level)) {
2630 bool IsTriviallyCopyable =
2631 D->getType().getNonReferenceType().isTriviallyCopyableType(
2632 Context: getASTContext()) &&
2633 !D->getType()
2634 .getNonReferenceType()
2635 .getCanonicalType()
2636 ->getAsCXXRecordDecl();
2637 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2638 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2639 getOpenMPCaptureRegions(CaptureRegions, DKind);
2640 if (isOpenMPTaskingDirective(Kind: CaptureRegions[CapLevel]) &&
2641 (IsTriviallyCopyable ||
2642 !isOpenMPTaskLoopDirective(DKind: CaptureRegions[CapLevel]))) {
2643 if (DSAStack->hasExplicitDSA(
2644 D,
2645 CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2646 Level, /*NotLastprivate=*/true))
2647 return OMPC_firstprivate;
2648 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2649 if (DVar.CKind != OMPC_shared &&
2650 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2651 DSAStack->addImplicitTaskFirstprivate(Level, D);
2652 return OMPC_firstprivate;
2653 }
2654 }
2655 }
2656 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2657 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2658 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2659 DSAStack->resetPossibleLoopCounter(D);
2660 DSAStack->loopStart();
2661 return OMPC_private;
2662 }
2663 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2664 DSAStack->isLoopControlVariable(D).first) &&
2665 !DSAStack->hasExplicitDSA(
2666 D, CPred: [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2667 Level) &&
2668 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2669 return OMPC_private;
2670 }
2671 if (const auto *VD = dyn_cast<VarDecl>(Val: D)) {
2672 if (DSAStack->isThreadPrivate(D: const_cast<VarDecl *>(VD)) &&
2673 DSAStack->isForceVarCapturing() &&
2674 !DSAStack->hasExplicitDSA(
2675 D, CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2676 Level))
2677 return OMPC_private;
2678 }
2679 // User-defined allocators are private since they must be defined in the
2680 // context of target region.
2681 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective, Level) &&
2682 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2683 u: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2684 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2685 return OMPC_private;
2686 return (DSAStack->hasExplicitDSA(
2687 D, CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2688 Level) ||
2689 (DSAStack->isClauseParsingMode() &&
2690 DSAStack->getClauseParsingMode() == OMPC_private) ||
2691 // Consider taskgroup reduction descriptor variable a private
2692 // to avoid possible capture in the region.
2693 (DSAStack->hasExplicitDirective(
2694 DPred: [](OpenMPDirectiveKind K) {
2695 return K == OMPD_taskgroup ||
2696 ((isOpenMPParallelDirective(DKind: K) ||
2697 isOpenMPWorksharingDirective(DKind: K)) &&
2698 !isOpenMPSimdDirective(DKind: K));
2699 },
2700 Level) &&
2701 DSAStack->isTaskgroupReductionRef(VD: D, Level)))
2702 ? OMPC_private
2703 : OMPC_unknown;
2704}
2705
2706void SemaOpenMP::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2707 unsigned Level) {
2708 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2709 D = getCanonicalDecl(D);
2710 OpenMPClauseKind OMPC = OMPC_unknown;
2711 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2712 const unsigned NewLevel = I - 1;
2713 if (DSAStack->hasExplicitDSA(
2714 D,
2715 CPred: [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2716 if (isOpenMPPrivate(Kind: K) && !AppliedToPointee) {
2717 OMPC = K;
2718 return true;
2719 }
2720 return false;
2721 },
2722 Level: NewLevel))
2723 break;
2724 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2725 VD: D, Level: NewLevel,
2726 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2727 OpenMPClauseKind) { return true; })) {
2728 OMPC = OMPC_map;
2729 break;
2730 }
2731 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective,
2732 Level: NewLevel)) {
2733 OMPC = OMPC_map;
2734 if (DSAStack->mustBeFirstprivateAtLevel(
2735 Level: NewLevel, Kind: getVariableCategoryFromDecl(LO: getLangOpts(), VD: D)))
2736 OMPC = OMPC_firstprivate;
2737 break;
2738 }
2739 }
2740 if (OMPC != OMPC_unknown)
2741 FD->addAttr(
2742 A: OMPCaptureKindAttr::CreateImplicit(Ctx&: getASTContext(), CaptureKindVal: unsigned(OMPC)));
2743}
2744
2745bool SemaOpenMP::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2746 unsigned CaptureLevel) const {
2747 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2748 // Return true if the current level is no longer enclosed in a target region.
2749
2750 SmallVector<OpenMPDirectiveKind, 4> Regions;
2751 getOpenMPCaptureRegions(CaptureRegions&: Regions, DSAStack->getDirective(Level));
2752 const auto *VD = dyn_cast<VarDecl>(Val: D);
2753 return VD && !VD->hasLocalStorage() &&
2754 DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective,
2755 Level) &&
2756 Regions[CaptureLevel] != OMPD_task;
2757}
2758
2759bool SemaOpenMP::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2760 unsigned CaptureLevel) const {
2761 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2762 // Return true if the current level is no longer enclosed in a target region.
2763
2764 if (const auto *VD = dyn_cast<VarDecl>(Val: D)) {
2765 if (!VD->hasLocalStorage()) {
2766 if (isInOpenMPTargetExecutionDirective())
2767 return true;
2768 DSAStackTy::DSAVarData TopDVar =
2769 DSAStack->getTopDSA(D, /*FromParent=*/false);
2770 unsigned NumLevels =
2771 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2772 if (Level == 0)
2773 // non-file scope static variable with default(firstprivate)
2774 // should be global captured.
2775 return (NumLevels == CaptureLevel + 1 &&
2776 (TopDVar.CKind != OMPC_shared ||
2777 DSAStack->getDefaultDSA() == DSA_firstprivate));
2778 do {
2779 --Level;
2780 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2781 if (DVar.CKind != OMPC_shared)
2782 return true;
2783 } while (Level > 0);
2784 }
2785 }
2786 return true;
2787}
2788
2789void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2790
2791void SemaOpenMP::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2792 OMPTraitInfo &TI) {
2793 OMPDeclareVariantScopes.push_back(Elt: OMPDeclareVariantScope(TI));
2794}
2795
2796void SemaOpenMP::ActOnOpenMPEndDeclareVariant() {
2797 assert(isInOpenMPDeclareVariantScope() &&
2798 "Not in OpenMP declare variant scope!");
2799
2800 OMPDeclareVariantScopes.pop_back();
2801}
2802
2803void SemaOpenMP::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2804 const FunctionDecl *Callee,
2805 SourceLocation Loc) {
2806 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2807 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2808 OMPDeclareTargetDeclAttr::getDeviceType(VD: Caller->getMostRecentDecl());
2809 // Ignore host functions during device analysis.
2810 if (getLangOpts().OpenMPIsTargetDevice &&
2811 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2812 return;
2813 // Ignore nohost functions during host analysis.
2814 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2815 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2816 return;
2817 const FunctionDecl *FD = Callee->getMostRecentDecl();
2818 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(VD: FD);
2819 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2820 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2821 // Diagnose host function called during device codegen.
2822 StringRef HostDevTy =
2823 getOpenMPSimpleClauseTypeName(Kind: OMPC_device_type, Type: OMPC_DEVICE_TYPE_host);
2824 Diag(Loc, DiagID: diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2825 Diag(Loc: *OMPDeclareTargetDeclAttr::getLocation(VD: FD),
2826 DiagID: diag::note_omp_marked_device_type_here)
2827 << HostDevTy;
2828 return;
2829 }
2830 if (!getLangOpts().OpenMPIsTargetDevice &&
2831 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2832 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2833 // In OpenMP 5.2 or later, if the function has a host variant then allow
2834 // that to be called instead
2835 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2836 for (OMPDeclareVariantAttr *A :
2837 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2838 auto *DeclRefVariant = cast<DeclRefExpr>(Val: A->getVariantFuncRef());
2839 auto *VariantFD = cast<FunctionDecl>(Val: DeclRefVariant->getDecl());
2840 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2841 OMPDeclareTargetDeclAttr::getDeviceType(
2842 VD: VariantFD->getMostRecentDecl());
2843 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2844 return true;
2845 }
2846 return false;
2847 };
2848 if (getLangOpts().OpenMP >= 52 &&
2849 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2850 return;
2851 // Diagnose nohost function called during host codegen.
2852 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2853 Kind: OMPC_device_type, Type: OMPC_DEVICE_TYPE_nohost);
2854 Diag(Loc, DiagID: diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2855 Diag(Loc: *OMPDeclareTargetDeclAttr::getLocation(VD: FD),
2856 DiagID: diag::note_omp_marked_device_type_here)
2857 << NoHostDevTy;
2858 }
2859}
2860
2861void SemaOpenMP::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2862 const DeclarationNameInfo &DirName,
2863 Scope *CurScope, SourceLocation Loc) {
2864 DSAStack->push(DKind, DirName, CurScope, Loc);
2865 SemaRef.PushExpressionEvaluationContext(
2866 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
2867}
2868
2869void SemaOpenMP::StartOpenMPClause(OpenMPClauseKind K) {
2870 DSAStack->setClauseParsingMode(K);
2871}
2872
2873void SemaOpenMP::EndOpenMPClause() {
2874 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2875 SemaRef.CleanupVarDeclMarking();
2876}
2877
2878static std::pair<ValueDecl *, bool>
2879getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2880 SourceRange &ERange, bool AllowArraySection = false,
2881 bool AllowAssumedSizeArray = false, StringRef DiagType = "");
2882
2883/// Check consistency of the reduction clauses.
2884static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2885 ArrayRef<OMPClause *> Clauses) {
2886 bool InscanFound = false;
2887 SourceLocation InscanLoc;
2888 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2889 // A reduction clause without the inscan reduction-modifier may not appear on
2890 // a construct on which a reduction clause with the inscan reduction-modifier
2891 // appears.
2892 for (OMPClause *C : Clauses) {
2893 if (C->getClauseKind() != OMPC_reduction)
2894 continue;
2895 auto *RC = cast<OMPReductionClause>(Val: C);
2896 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2897 InscanFound = true;
2898 InscanLoc = RC->getModifierLoc();
2899 continue;
2900 }
2901 if (RC->getModifier() == OMPC_REDUCTION_task) {
2902 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2903 // A reduction clause with the task reduction-modifier may only appear on
2904 // a parallel construct, a worksharing construct or a combined or
2905 // composite construct for which any of the aforementioned constructs is a
2906 // constituent construct and simd or loop are not constituent constructs.
2907 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2908 if (!(isOpenMPParallelDirective(DKind: CurDir) ||
2909 isOpenMPWorksharingDirective(DKind: CurDir)) ||
2910 isOpenMPSimdDirective(DKind: CurDir))
2911 S.Diag(Loc: RC->getModifierLoc(),
2912 DiagID: diag::err_omp_reduction_task_not_parallel_or_worksharing);
2913 continue;
2914 }
2915 }
2916 if (InscanFound) {
2917 for (OMPClause *C : Clauses) {
2918 if (C->getClauseKind() != OMPC_reduction)
2919 continue;
2920 auto *RC = cast<OMPReductionClause>(Val: C);
2921 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2922 S.Diag(Loc: RC->getModifier() == OMPC_REDUCTION_unknown
2923 ? RC->getBeginLoc()
2924 : RC->getModifierLoc(),
2925 DiagID: diag::err_omp_inscan_reduction_expected);
2926 S.Diag(Loc: InscanLoc, DiagID: diag::note_omp_previous_inscan_reduction);
2927 continue;
2928 }
2929 for (Expr *Ref : RC->varlist()) {
2930 assert(Ref && "NULL expr in OpenMP reduction clause.");
2931 SourceLocation ELoc;
2932 SourceRange ERange;
2933 Expr *SimpleRefExpr = Ref;
2934 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
2935 /*AllowArraySection=*/true);
2936 ValueDecl *D = Res.first;
2937 if (!D)
2938 continue;
2939 if (!Stack->isUsedInScanDirective(D: getCanonicalDecl(D))) {
2940 S.Diag(Loc: Ref->getExprLoc(),
2941 DiagID: diag::err_omp_reduction_not_inclusive_exclusive)
2942 << Ref->getSourceRange();
2943 }
2944 }
2945 }
2946 }
2947}
2948
2949static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2950 ArrayRef<OMPClause *> Clauses);
2951static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2952 bool WithInit);
2953
2954static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2955 const ValueDecl *D,
2956 const DSAStackTy::DSAVarData &DVar,
2957 bool IsLoopIterVar = false);
2958
2959void SemaOpenMP::EndOpenMPDSABlock(Stmt *CurDirective) {
2960 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2961 // A variable of class type (or array thereof) that appears in a lastprivate
2962 // clause requires an accessible, unambiguous default constructor for the
2963 // class type, unless the list item is also specified in a firstprivate
2964 // clause.
2965
2966 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2967 SmallVector<Expr *, 8> PrivateCopies;
2968 for (Expr *DE : Clause->varlist()) {
2969 if (DE->isValueDependent() || DE->isTypeDependent()) {
2970 PrivateCopies.push_back(Elt: nullptr);
2971 continue;
2972 }
2973 auto *DRE = cast<DeclRefExpr>(Val: DE->IgnoreParens());
2974 auto *VD = cast<VarDecl>(Val: DRE->getDecl());
2975 QualType Type = VD->getType().getNonReferenceType();
2976 const DSAStackTy::DSAVarData DVar =
2977 DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
2978 if (DVar.CKind != OMPC_lastprivate) {
2979 // The variable is also a firstprivate, so initialization sequence
2980 // for private copy is generated already.
2981 PrivateCopies.push_back(Elt: nullptr);
2982 continue;
2983 }
2984 // Generate helper private variable and initialize it with the
2985 // default value. The address of the original variable is replaced
2986 // by the address of the new private variable in CodeGen. This new
2987 // variable is not added to IdResolver, so the code in the OpenMP
2988 // region uses original variable for proper diagnostics.
2989 VarDecl *VDPrivate = buildVarDecl(
2990 SemaRef, Loc: DE->getExprLoc(), Type: Type.getUnqualifiedType(), Name: VD->getName(),
2991 Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr, OrigRef: DRE);
2992 SemaRef.ActOnUninitializedDecl(dcl: VDPrivate);
2993 if (VDPrivate->isInvalidDecl()) {
2994 PrivateCopies.push_back(Elt: nullptr);
2995 continue;
2996 }
2997 PrivateCopies.push_back(Elt: buildDeclRefExpr(
2998 S&: SemaRef, D: VDPrivate, Ty: DE->getType(), Loc: DE->getExprLoc()));
2999 }
3000 Clause->setPrivateCopies(PrivateCopies);
3001 };
3002
3003 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
3004 // Finalize nontemporal clause by handling private copies, if any.
3005 SmallVector<Expr *, 8> PrivateRefs;
3006 for (Expr *RefExpr : Clause->varlist()) {
3007 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
3008 SourceLocation ELoc;
3009 SourceRange ERange;
3010 Expr *SimpleRefExpr = RefExpr;
3011 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
3012 if (Res.second)
3013 // It will be analyzed later.
3014 PrivateRefs.push_back(Elt: RefExpr);
3015 ValueDecl *D = Res.first;
3016 if (!D)
3017 continue;
3018
3019 const DSAStackTy::DSAVarData DVar =
3020 DSAStack->getTopDSA(D, /*FromParent=*/false);
3021 PrivateRefs.push_back(Elt: DVar.PrivateCopy ? DVar.PrivateCopy
3022 : SimpleRefExpr);
3023 }
3024 Clause->setPrivateRefs(PrivateRefs);
3025 };
3026
3027 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
3028 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3029 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
3030 auto *DRE = dyn_cast<DeclRefExpr>(Val: D.Allocator->IgnoreParenImpCasts());
3031 if (!DRE)
3032 continue;
3033 ValueDecl *VD = DRE->getDecl();
3034 if (!VD || !isa<VarDecl>(Val: VD))
3035 continue;
3036 DSAStackTy::DSAVarData DVar =
3037 DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
3038 // OpenMP [2.12.5, target Construct]
3039 // Memory allocators that appear in a uses_allocators clause cannot
3040 // appear in other data-sharing attribute clauses or data-mapping
3041 // attribute clauses in the same construct.
3042 Expr *MapExpr = nullptr;
3043 if (DVar.RefExpr ||
3044 DSAStack->checkMappableExprComponentListsForDecl(
3045 VD, /*CurrentRegionOnly=*/true,
3046 Check: [VD, &MapExpr](
3047 OMPClauseMappableExprCommon::MappableExprComponentListRef
3048 MapExprComponents,
3049 OpenMPClauseKind C) {
3050 auto MI = MapExprComponents.rbegin();
3051 auto ME = MapExprComponents.rend();
3052 if (MI != ME &&
3053 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3054 VD->getCanonicalDecl()) {
3055 MapExpr = MI->getAssociatedExpression();
3056 return true;
3057 }
3058 return false;
3059 })) {
3060 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::err_omp_allocator_used_in_clauses)
3061 << D.Allocator->getSourceRange();
3062 if (DVar.RefExpr)
3063 reportOriginalDsa(SemaRef, DSAStack, D: VD, DVar);
3064 else
3065 Diag(Loc: MapExpr->getExprLoc(), DiagID: diag::note_used_here)
3066 << MapExpr->getSourceRange();
3067 }
3068 }
3069 };
3070
3071 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(Val: CurDirective)) {
3072 for (OMPClause *C : D->clauses()) {
3073 if (auto *Clause = dyn_cast<OMPLastprivateClause>(Val: C)) {
3074 FinalizeLastprivate(Clause);
3075 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(Val: C)) {
3076 FinalizeNontemporal(Clause);
3077 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(Val: C)) {
3078 FinalizeAllocators(Clause);
3079 }
3080 }
3081 // Check allocate clauses.
3082 if (!SemaRef.CurContext->isDependentContext())
3083 checkAllocateClauses(S&: SemaRef, DSAStack, Clauses: D->clauses());
3084 checkReductionClauses(S&: SemaRef, DSAStack, Clauses: D->clauses());
3085 }
3086
3087 DSAStack->pop();
3088 SemaRef.DiscardCleanupsInEvaluationContext();
3089 SemaRef.PopExpressionEvaluationContext();
3090}
3091
3092static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3093 Expr *NumIterations, Sema &SemaRef,
3094 Scope *S, DSAStackTy *Stack);
3095
3096static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
3097 OMPLoopBasedDirective::HelperExprs &B,
3098 DSAStackTy *Stack) {
3099 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3100 "loop exprs were not built");
3101
3102 if (SemaRef.CurContext->isDependentContext())
3103 return false;
3104
3105 // Finalize the clauses that need pre-built expressions for CodeGen.
3106 for (OMPClause *C : Clauses) {
3107 auto *LC = dyn_cast<OMPLinearClause>(Val: C);
3108 if (!LC)
3109 continue;
3110 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
3111 NumIterations: B.NumIterations, SemaRef,
3112 S: SemaRef.getCurScope(), Stack))
3113 return true;
3114 }
3115
3116 return false;
3117}
3118
3119namespace {
3120
3121class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3122private:
3123 Sema &SemaRef;
3124
3125public:
3126 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3127 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3128 NamedDecl *ND = Candidate.getCorrectionDecl();
3129 if (const auto *VD = dyn_cast_or_null<VarDecl>(Val: ND)) {
3130 return VD->hasGlobalStorage() &&
3131 SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(),
3132 S: SemaRef.getCurScope());
3133 }
3134 return false;
3135 }
3136
3137 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3138 return std::make_unique<VarDeclFilterCCC>(args&: *this);
3139 }
3140};
3141
3142class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3143private:
3144 Sema &SemaRef;
3145
3146public:
3147 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3148 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3149 NamedDecl *ND = Candidate.getCorrectionDecl();
3150 if (ND && ((isa<VarDecl>(Val: ND) && ND->getKind() == Decl::Var) ||
3151 isa<FunctionDecl>(Val: ND))) {
3152 return SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(),
3153 S: SemaRef.getCurScope());
3154 }
3155 return false;
3156 }
3157
3158 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3159 return std::make_unique<VarOrFuncDeclFilterCCC>(args&: *this);
3160 }
3161};
3162
3163} // namespace
3164
3165ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope,
3166 CXXScopeSpec &ScopeSpec,
3167 const DeclarationNameInfo &Id,
3168 OpenMPDirectiveKind Kind) {
3169 ASTContext &Context = getASTContext();
3170 unsigned OMPVersion = getLangOpts().OpenMP;
3171 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
3172 SemaRef.LookupParsedName(R&: Lookup, S: CurScope, SS: &ScopeSpec,
3173 /*ObjectType=*/QualType(),
3174 /*AllowBuiltinCreation=*/true);
3175
3176 if (Lookup.isAmbiguous())
3177 return ExprError();
3178
3179 VarDecl *VD;
3180 if (!Lookup.isSingleResult()) {
3181 VarDeclFilterCCC CCC(SemaRef);
3182 if (TypoCorrection Corrected =
3183 SemaRef.CorrectTypo(Typo: Id, LookupKind: Sema::LookupOrdinaryName, S: CurScope, SS: nullptr,
3184 CCC, Mode: CorrectTypoKind::ErrorRecovery)) {
3185 SemaRef.diagnoseTypo(
3186 Correction: Corrected,
3187 TypoDiag: SemaRef.PDiag(DiagID: Lookup.empty() ? diag::err_undeclared_var_use_suggest
3188 : diag::err_omp_expected_var_arg_suggest)
3189 << Id.getName());
3190 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3191 } else {
3192 Diag(Loc: Id.getLoc(), DiagID: Lookup.empty() ? diag::err_undeclared_var_use
3193 : diag::err_omp_expected_var_arg)
3194 << Id.getName();
3195 return ExprError();
3196 }
3197 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3198 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_expected_var_arg) << Id.getName();
3199 Diag(Loc: Lookup.getFoundDecl()->getLocation(), DiagID: diag::note_declared_at);
3200 return ExprError();
3201 }
3202 Lookup.suppressDiagnostics();
3203
3204 // OpenMP [2.9.2, Syntax, C/C++]
3205 // Variables must be file-scope, namespace-scope, or static block-scope.
3206 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3207 !VD->hasGlobalStorage()) {
3208 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_global_var_arg)
3209 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << !VD->isStaticLocal();
3210 bool IsDecl =
3211 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3212 Diag(Loc: VD->getLocation(),
3213 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3214 << VD;
3215 return ExprError();
3216 }
3217
3218 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3219 NamedDecl *ND = CanonicalVD;
3220 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3221 // A threadprivate or groupprivate directive for file-scope variables must
3222 // appear outside any definition or declaration.
3223 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3224 !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3225 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3226 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3227 bool IsDecl =
3228 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3229 Diag(Loc: VD->getLocation(),
3230 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3231 << VD;
3232 return ExprError();
3233 }
3234 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3235 // A threadprivate or groupprivate directive for static class member
3236 // variables must appear in the class definition, in the same scope in which
3237 // the member variables are declared.
3238 if (CanonicalVD->isStaticDataMember() &&
3239 !CanonicalVD->getDeclContext()->Equals(DC: SemaRef.getCurLexicalContext())) {
3240 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3241 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3242 bool IsDecl =
3243 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3244 Diag(Loc: VD->getLocation(),
3245 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3246 << VD;
3247 return ExprError();
3248 }
3249 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3250 // A threadprivate or groupprivate directive for namespace-scope variables
3251 // must appear outside any definition or declaration other than the
3252 // namespace definition itself.
3253 if (CanonicalVD->getDeclContext()->isNamespace() &&
3254 (!SemaRef.getCurLexicalContext()->isFileContext() ||
3255 !SemaRef.getCurLexicalContext()->Encloses(
3256 DC: CanonicalVD->getDeclContext()))) {
3257 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3258 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3259 bool IsDecl =
3260 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3261 Diag(Loc: VD->getLocation(),
3262 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3263 << VD;
3264 return ExprError();
3265 }
3266 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3267 // A threadprivate or groupprivate directive for static block-scope
3268 // variables must appear in the scope of the variable and not in a nested
3269 // scope.
3270 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3271 !SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(), S: CurScope)) {
3272 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3273 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3274 bool IsDecl =
3275 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3276 Diag(Loc: VD->getLocation(),
3277 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3278 << VD;
3279 return ExprError();
3280 }
3281
3282 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3283 // A threadprivate or groupprivate directive must lexically precede all
3284 // references to any of the variables in its list.
3285 if ((Kind == OMPD_threadprivate && VD->isUsed() &&
3286 !DSAStack->isThreadPrivate(D: VD)) ||
3287 (Kind == OMPD_groupprivate && VD->isUsed())) {
3288 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_used)
3289 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3290 return ExprError();
3291 }
3292
3293 QualType ExprType = VD->getType().getNonReferenceType();
3294 return DeclRefExpr::Create(Context, QualifierLoc: NestedNameSpecifierLoc(),
3295 TemplateKWLoc: SourceLocation(), D: VD,
3296 /*RefersToEnclosingVariableOrCapture=*/false,
3297 NameLoc: Id.getLoc(), T: ExprType, VK: VK_LValue);
3298}
3299
3300SemaOpenMP::DeclGroupPtrTy
3301SemaOpenMP::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3302 ArrayRef<Expr *> VarList) {
3303 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3304 SemaRef.CurContext->addDecl(D);
3305 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3306 }
3307 return nullptr;
3308}
3309
3310SemaOpenMP::DeclGroupPtrTy
3311SemaOpenMP::ActOnOpenMPGroupPrivateDirective(SourceLocation Loc,
3312 ArrayRef<Expr *> VarList) {
3313 if (!getLangOpts().OpenMP || getLangOpts().OpenMP < 60) {
3314 Diag(Loc, DiagID: diag::err_omp_unexpected_directive)
3315 << getOpenMPDirectiveName(D: OMPD_groupprivate, Ver: getLangOpts().OpenMP);
3316 return nullptr;
3317 }
3318 if (OMPGroupPrivateDecl *D = CheckOMPGroupPrivateDecl(Loc, VarList)) {
3319 SemaRef.CurContext->addDecl(D);
3320 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3321 }
3322 return nullptr;
3323}
3324
3325namespace {
3326class LocalVarRefChecker final
3327 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3328 Sema &SemaRef;
3329
3330public:
3331 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3332 if (const auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
3333 if (VD->hasLocalStorage()) {
3334 SemaRef.Diag(Loc: E->getBeginLoc(),
3335 DiagID: diag::err_omp_local_var_in_threadprivate_init)
3336 << E->getSourceRange();
3337 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::note_defined_here)
3338 << VD << VD->getSourceRange();
3339 return true;
3340 }
3341 }
3342 return false;
3343 }
3344 bool VisitStmt(const Stmt *S) {
3345 for (const Stmt *Child : S->children()) {
3346 if (Child && Visit(S: Child))
3347 return true;
3348 }
3349 return false;
3350 }
3351 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3352};
3353} // namespace
3354
3355OMPThreadPrivateDecl *
3356SemaOpenMP::CheckOMPThreadPrivateDecl(SourceLocation Loc,
3357 ArrayRef<Expr *> VarList) {
3358 ASTContext &Context = getASTContext();
3359 SmallVector<Expr *, 8> Vars;
3360 for (Expr *RefExpr : VarList) {
3361 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3362 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3363 SourceLocation ILoc = DE->getExprLoc();
3364
3365 // Mark variable as used.
3366 VD->setReferenced();
3367 VD->markUsed(C&: Context);
3368
3369 QualType QType = VD->getType();
3370 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3371 // It will be analyzed later.
3372 Vars.push_back(Elt: DE);
3373 continue;
3374 }
3375
3376 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3377 // A threadprivate variable must not have an incomplete type.
3378 if (SemaRef.RequireCompleteType(
3379 Loc: ILoc, T: VD->getType(), DiagID: diag::err_omp_threadprivate_incomplete_type)) {
3380 continue;
3381 }
3382
3383 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3384 // A threadprivate variable must not have a reference type.
3385 if (VD->getType()->isReferenceType()) {
3386 unsigned OMPVersion = getLangOpts().OpenMP;
3387 Diag(Loc: ILoc, DiagID: diag::err_omp_ref_type_arg)
3388 << getOpenMPDirectiveName(D: OMPD_threadprivate, Ver: OMPVersion)
3389 << VD->getType();
3390 bool IsDecl =
3391 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3392 Diag(Loc: VD->getLocation(),
3393 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3394 << VD;
3395 continue;
3396 }
3397
3398 // Check if this is a TLS variable. If TLS is not being supported, produce
3399 // the corresponding diagnostic.
3400 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3401 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3402 getLangOpts().OpenMPUseTLS &&
3403 getASTContext().getTargetInfo().isTLSSupported())) ||
3404 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3405 !VD->isLocalVarDecl())) {
3406 Diag(Loc: ILoc, DiagID: diag::err_omp_var_thread_local)
3407 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3408 bool IsDecl =
3409 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3410 Diag(Loc: VD->getLocation(),
3411 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3412 << VD;
3413 continue;
3414 }
3415
3416 // Check if initial value of threadprivate variable reference variable with
3417 // local storage (it is not supported by runtime).
3418 if (const Expr *Init = VD->getAnyInitializer()) {
3419 LocalVarRefChecker Checker(SemaRef);
3420 if (Checker.Visit(S: Init))
3421 continue;
3422 }
3423
3424 Vars.push_back(Elt: RefExpr);
3425 DSAStack->addDSA(D: VD, E: DE, A: OMPC_threadprivate);
3426 VD->addAttr(A: OMPThreadPrivateDeclAttr::CreateImplicit(
3427 Ctx&: Context, Range: SourceRange(Loc, Loc)));
3428 if (ASTMutationListener *ML = Context.getASTMutationListener())
3429 ML->DeclarationMarkedOpenMPThreadPrivate(D: VD);
3430 }
3431 OMPThreadPrivateDecl *D = nullptr;
3432 if (!Vars.empty()) {
3433 D = OMPThreadPrivateDecl::Create(C&: Context, DC: SemaRef.getCurLexicalContext(),
3434 L: Loc, VL: Vars);
3435 D->setAccess(AS_public);
3436 }
3437 return D;
3438}
3439
3440OMPGroupPrivateDecl *
3441SemaOpenMP::CheckOMPGroupPrivateDecl(SourceLocation Loc,
3442 ArrayRef<Expr *> VarList) {
3443 ASTContext &Context = getASTContext();
3444 SmallVector<Expr *, 8> Vars;
3445 for (Expr *RefExpr : VarList) {
3446 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3447 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3448 SourceLocation ILoc = DE->getExprLoc();
3449
3450 // Mark variable as used.
3451 VD->setReferenced();
3452 VD->markUsed(C&: Context);
3453
3454 QualType QType = VD->getType();
3455 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3456 // It will be analyzed later.
3457 Vars.push_back(Elt: DE);
3458 continue;
3459 }
3460
3461 // OpenMP groupprivate restrictions:
3462 // A groupprivate variable must not have an incomplete type.
3463 if (SemaRef.RequireCompleteType(
3464 Loc: ILoc, T: VD->getType(), DiagID: diag::err_omp_groupprivate_incomplete_type)) {
3465 continue;
3466 }
3467
3468 // A groupprivate variable must not have a reference type.
3469 if (VD->getType()->isReferenceType()) {
3470 Diag(Loc: ILoc, DiagID: diag::err_omp_ref_type_arg)
3471 << getOpenMPDirectiveName(D: OMPD_groupprivate) << VD->getType();
3472 bool IsDecl =
3473 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3474 Diag(Loc: VD->getLocation(),
3475 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3476 << VD;
3477 continue;
3478 }
3479
3480 // A variable that is declared with an initializer must not appear in a
3481 // groupprivate directive.
3482 if (VD->getAnyInitializer()) {
3483 Diag(Loc: ILoc, DiagID: diag::err_omp_groupprivate_with_initializer)
3484 << VD->getDeclName();
3485 bool IsDecl =
3486 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3487 Diag(Loc: VD->getLocation(),
3488 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3489 << VD;
3490 continue;
3491 }
3492
3493 Vars.push_back(Elt: RefExpr);
3494 DSAStack->addDSA(D: VD, E: DE, A: OMPC_groupprivate);
3495 VD->addAttr(A: OMPGroupPrivateDeclAttr::CreateImplicit(Ctx&: Context,
3496 Range: SourceRange(Loc, Loc)));
3497 if (ASTMutationListener *ML = Context.getASTMutationListener())
3498 ML->DeclarationMarkedOpenMPGroupPrivate(D: VD);
3499 }
3500 OMPGroupPrivateDecl *D = nullptr;
3501 if (!Vars.empty()) {
3502 D = OMPGroupPrivateDecl::Create(C&: Context, DC: SemaRef.getCurLexicalContext(),
3503 L: Loc, VL: Vars);
3504 D->setAccess(AS_public);
3505 }
3506 return D;
3507}
3508
3509static OMPAllocateDeclAttr::AllocatorTypeTy
3510getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3511 if (!Allocator)
3512 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3513 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3514 Allocator->isInstantiationDependent() ||
3515 Allocator->containsUnexpandedParameterPack())
3516 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3517 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3518 llvm::FoldingSetNodeID AEId;
3519 const Expr *AE = Allocator->IgnoreParenImpCasts();
3520 AE->IgnoreImpCasts()->Profile(ID&: AEId, Context: S.getASTContext(), /*Canonical=*/true);
3521 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3522 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3523 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3524 llvm::FoldingSetNodeID DAEId;
3525 DefAllocator->IgnoreImpCasts()->Profile(ID&: DAEId, Context: S.getASTContext(),
3526 /*Canonical=*/true);
3527 if (AEId == DAEId) {
3528 AllocatorKindRes = AllocatorKind;
3529 break;
3530 }
3531 }
3532 return AllocatorKindRes;
3533}
3534
3535static bool checkPreviousOMPAllocateAttribute(
3536 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3537 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3538 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3539 return false;
3540 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3541 Expr *PrevAllocator = A->getAllocator();
3542 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3543 getAllocatorKind(S, Stack, Allocator: PrevAllocator);
3544 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3545 if (AllocatorsMatch &&
3546 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3547 Allocator && PrevAllocator) {
3548 const Expr *AE = Allocator->IgnoreParenImpCasts();
3549 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3550 llvm::FoldingSetNodeID AEId, PAEId;
3551 AE->Profile(ID&: AEId, Context: S.Context, /*Canonical=*/true);
3552 PAE->Profile(ID&: PAEId, Context: S.Context, /*Canonical=*/true);
3553 AllocatorsMatch = AEId == PAEId;
3554 }
3555 if (!AllocatorsMatch) {
3556 SmallString<256> AllocatorBuffer;
3557 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3558 if (Allocator)
3559 Allocator->printPretty(OS&: AllocatorStream, Helper: nullptr, Policy: S.getPrintingPolicy());
3560 SmallString<256> PrevAllocatorBuffer;
3561 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3562 if (PrevAllocator)
3563 PrevAllocator->printPretty(OS&: PrevAllocatorStream, Helper: nullptr,
3564 Policy: S.getPrintingPolicy());
3565
3566 SourceLocation AllocatorLoc =
3567 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3568 SourceRange AllocatorRange =
3569 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3570 SourceLocation PrevAllocatorLoc =
3571 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3572 SourceRange PrevAllocatorRange =
3573 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3574 S.Diag(Loc: AllocatorLoc, DiagID: diag::warn_omp_used_different_allocator)
3575 << (Allocator ? 1 : 0) << AllocatorStream.str()
3576 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3577 << AllocatorRange;
3578 S.Diag(Loc: PrevAllocatorLoc, DiagID: diag::note_omp_previous_allocator)
3579 << PrevAllocatorRange;
3580 return true;
3581 }
3582 return false;
3583}
3584
3585static void
3586applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3587 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3588 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3589 if (VD->hasAttr<OMPAllocateDeclAttr>())
3590 return;
3591 if (Alignment &&
3592 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3593 Alignment->isInstantiationDependent() ||
3594 Alignment->containsUnexpandedParameterPack()))
3595 // Apply later when we have a usable value.
3596 return;
3597 if (Allocator &&
3598 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3599 Allocator->isInstantiationDependent() ||
3600 Allocator->containsUnexpandedParameterPack()))
3601 return;
3602 auto *A = OMPAllocateDeclAttr::CreateImplicit(Ctx&: S.Context, AllocatorType: AllocatorKind,
3603 Allocator, Alignment, Range: SR);
3604 VD->addAttr(A);
3605 if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3606 ML->DeclarationMarkedOpenMPAllocate(D: VD, A);
3607}
3608
3609SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPAllocateDirective(
3610 SourceLocation Loc, ArrayRef<Expr *> VarList, ArrayRef<OMPClause *> Clauses,
3611 DeclContext *Owner) {
3612 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3613 Expr *Alignment = nullptr;
3614 Expr *Allocator = nullptr;
3615 if (Clauses.empty()) {
3616 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3617 // allocate directives that appear in a target region must specify an
3618 // allocator clause unless a requires directive with the dynamic_allocators
3619 // clause is present in the same compilation unit.
3620 if (getLangOpts().OpenMPIsTargetDevice &&
3621 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3622 SemaRef.targetDiag(Loc, DiagID: diag::err_expected_allocator_clause);
3623 } else {
3624 for (const OMPClause *C : Clauses)
3625 if (const auto *AC = dyn_cast<OMPAllocatorClause>(Val: C))
3626 Allocator = AC->getAllocator();
3627 else if (const auto *AC = dyn_cast<OMPAlignClause>(Val: C))
3628 Alignment = AC->getAlignment();
3629 else
3630 llvm_unreachable("Unexpected clause on allocate directive");
3631 }
3632 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3633 getAllocatorKind(S&: SemaRef, DSAStack, Allocator);
3634 SmallVector<Expr *, 8> Vars;
3635 for (Expr *RefExpr : VarList) {
3636 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3637 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3638
3639 // Check if this is a TLS variable or global register.
3640 if (VD->getTLSKind() != VarDecl::TLS_None ||
3641 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3642 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3643 !VD->isLocalVarDecl()))
3644 continue;
3645
3646 // If the used several times in the allocate directive, the same allocator
3647 // must be used.
3648 if (checkPreviousOMPAllocateAttribute(S&: SemaRef, DSAStack, RefExpr, VD,
3649 AllocatorKind, Allocator))
3650 continue;
3651
3652 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3653 // If a list item has a static storage type, the allocator expression in the
3654 // allocator clause must be a constant expression that evaluates to one of
3655 // the predefined memory allocator values.
3656 if (Allocator && VD->hasGlobalStorage()) {
3657 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3658 Diag(Loc: Allocator->getExprLoc(),
3659 DiagID: diag::err_omp_expected_predefined_allocator)
3660 << Allocator->getSourceRange();
3661 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3662 VarDecl::DeclarationOnly;
3663 Diag(Loc: VD->getLocation(),
3664 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3665 << VD;
3666 continue;
3667 }
3668 }
3669
3670 Vars.push_back(Elt: RefExpr);
3671 applyOMPAllocateAttribute(S&: SemaRef, VD, AllocatorKind, Allocator, Alignment,
3672 SR: DE->getSourceRange());
3673 }
3674 if (Vars.empty())
3675 return nullptr;
3676 if (!Owner)
3677 Owner = SemaRef.getCurLexicalContext();
3678 auto *D = OMPAllocateDecl::Create(C&: getASTContext(), DC: Owner, L: Loc, VL: Vars, CL: Clauses);
3679 D->setAccess(AS_public);
3680 Owner->addDecl(D);
3681 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3682}
3683
3684SemaOpenMP::DeclGroupPtrTy
3685SemaOpenMP::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3686 ArrayRef<OMPClause *> ClauseList) {
3687 OMPRequiresDecl *D = nullptr;
3688 if (!SemaRef.CurContext->isFileContext()) {
3689 Diag(Loc, DiagID: diag::err_omp_invalid_scope) << "requires";
3690 } else {
3691 D = CheckOMPRequiresDecl(Loc, Clauses: ClauseList);
3692 if (D) {
3693 SemaRef.CurContext->addDecl(D);
3694 DSAStack->addRequiresDecl(RD: D);
3695 }
3696 }
3697 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3698}
3699
3700void SemaOpenMP::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3701 OpenMPDirectiveKind DKind,
3702 ArrayRef<std::string> Assumptions,
3703 bool SkippedClauses) {
3704 if (!SkippedClauses && Assumptions.empty()) {
3705 unsigned OMPVersion = getLangOpts().OpenMP;
3706 Diag(Loc, DiagID: diag::err_omp_no_clause_for_directive)
3707 << llvm::omp::getAllAssumeClauseOptions()
3708 << llvm::omp::getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
3709 }
3710
3711 auto *AA =
3712 OMPAssumeAttr::Create(Ctx&: getASTContext(), Assumption: llvm::join(R&: Assumptions, Separator: ","), Range: Loc);
3713 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3714 OMPAssumeScoped.push_back(Elt: AA);
3715 return;
3716 }
3717
3718 // Global assumes without assumption clauses are ignored.
3719 if (Assumptions.empty())
3720 return;
3721
3722 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3723 "Unexpected omp assumption directive!");
3724 OMPAssumeGlobal.push_back(Elt: AA);
3725
3726 // The OMPAssumeGlobal scope above will take care of new declarations but
3727 // we also want to apply the assumption to existing ones, e.g., to
3728 // declarations in included headers. To this end, we traverse all existing
3729 // declaration contexts and annotate function declarations here.
3730 SmallVector<DeclContext *, 8> DeclContexts;
3731 auto *Ctx = SemaRef.CurContext;
3732 while (Ctx->getLexicalParent())
3733 Ctx = Ctx->getLexicalParent();
3734 DeclContexts.push_back(Elt: Ctx);
3735 while (!DeclContexts.empty()) {
3736 DeclContext *DC = DeclContexts.pop_back_val();
3737 for (auto *SubDC : DC->decls()) {
3738 if (SubDC->isInvalidDecl())
3739 continue;
3740 if (auto *CTD = dyn_cast<ClassTemplateDecl>(Val: SubDC)) {
3741 DeclContexts.push_back(Elt: CTD->getTemplatedDecl());
3742 llvm::append_range(C&: DeclContexts, R: CTD->specializations());
3743 continue;
3744 }
3745 if (auto *DC = dyn_cast<DeclContext>(Val: SubDC))
3746 DeclContexts.push_back(Elt: DC);
3747 if (auto *F = dyn_cast<FunctionDecl>(Val: SubDC)) {
3748 F->addAttr(A: AA);
3749 continue;
3750 }
3751 }
3752 }
3753}
3754
3755void SemaOpenMP::ActOnOpenMPEndAssumesDirective() {
3756 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3757 OMPAssumeScoped.pop_back();
3758}
3759
3760StmtResult SemaOpenMP::ActOnOpenMPAssumeDirective(ArrayRef<OMPClause *> Clauses,
3761 Stmt *AStmt,
3762 SourceLocation StartLoc,
3763 SourceLocation EndLoc) {
3764 if (!AStmt)
3765 return StmtError();
3766
3767 return OMPAssumeDirective::Create(Ctx: getASTContext(), StartLoc, EndLoc, Clauses,
3768 AStmt);
3769}
3770
3771OMPRequiresDecl *
3772SemaOpenMP::CheckOMPRequiresDecl(SourceLocation Loc,
3773 ArrayRef<OMPClause *> ClauseList) {
3774 /// For target specific clauses, the requires directive cannot be
3775 /// specified after the handling of any of the target regions in the
3776 /// current compilation unit.
3777 ArrayRef<SourceLocation> TargetLocations =
3778 DSAStack->getEncounteredTargetLocs();
3779 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3780 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3781 for (const OMPClause *CNew : ClauseList) {
3782 // Check if any of the requires clauses affect target regions.
3783 if (isa<OMPUnifiedSharedMemoryClause>(Val: CNew) ||
3784 isa<OMPUnifiedAddressClause>(Val: CNew) ||
3785 isa<OMPReverseOffloadClause>(Val: CNew) ||
3786 isa<OMPDynamicAllocatorsClause>(Val: CNew)) {
3787 Diag(Loc, DiagID: diag::err_omp_directive_before_requires)
3788 << "target" << getOpenMPClauseNameForDiag(C: CNew->getClauseKind());
3789 for (SourceLocation TargetLoc : TargetLocations) {
3790 Diag(Loc: TargetLoc, DiagID: diag::note_omp_requires_encountered_directive)
3791 << "target";
3792 }
3793 } else if (!AtomicLoc.isInvalid() &&
3794 isa<OMPAtomicDefaultMemOrderClause>(Val: CNew)) {
3795 Diag(Loc, DiagID: diag::err_omp_directive_before_requires)
3796 << "atomic" << getOpenMPClauseNameForDiag(C: CNew->getClauseKind());
3797 Diag(Loc: AtomicLoc, DiagID: diag::note_omp_requires_encountered_directive)
3798 << "atomic";
3799 }
3800 }
3801 }
3802
3803 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3804 return OMPRequiresDecl::Create(
3805 C&: getASTContext(), DC: SemaRef.getCurLexicalContext(), L: Loc, CL: ClauseList);
3806 return nullptr;
3807}
3808
3809static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3810 const ValueDecl *D,
3811 const DSAStackTy::DSAVarData &DVar,
3812 bool IsLoopIterVar) {
3813 if (DVar.RefExpr) {
3814 SemaRef.Diag(Loc: DVar.RefExpr->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
3815 << getOpenMPClauseNameForDiag(C: DVar.CKind);
3816 return;
3817 }
3818 enum {
3819 PDSA_StaticMemberShared,
3820 PDSA_StaticLocalVarShared,
3821 PDSA_LoopIterVarPrivate,
3822 PDSA_LoopIterVarLinear,
3823 PDSA_LoopIterVarLastprivate,
3824 PDSA_ConstVarShared,
3825 PDSA_GlobalVarShared,
3826 PDSA_TaskVarFirstprivate,
3827 PDSA_LocalVarPrivate,
3828 PDSA_Implicit
3829 } Reason = PDSA_Implicit;
3830 bool ReportHint = false;
3831 auto ReportLoc = D->getLocation();
3832 auto *VD = dyn_cast<VarDecl>(Val: D);
3833 if (IsLoopIterVar) {
3834 if (DVar.CKind == OMPC_private)
3835 Reason = PDSA_LoopIterVarPrivate;
3836 else if (DVar.CKind == OMPC_lastprivate)
3837 Reason = PDSA_LoopIterVarLastprivate;
3838 else
3839 Reason = PDSA_LoopIterVarLinear;
3840 } else if (isOpenMPTaskingDirective(Kind: DVar.DKind) &&
3841 DVar.CKind == OMPC_firstprivate) {
3842 Reason = PDSA_TaskVarFirstprivate;
3843 ReportLoc = DVar.ImplicitDSALoc;
3844 } else if (VD && VD->isStaticLocal())
3845 Reason = PDSA_StaticLocalVarShared;
3846 else if (VD && VD->isStaticDataMember())
3847 Reason = PDSA_StaticMemberShared;
3848 else if (VD && VD->isFileVarDecl())
3849 Reason = PDSA_GlobalVarShared;
3850 else if (D->getType().isConstant(Ctx: SemaRef.getASTContext()))
3851 Reason = PDSA_ConstVarShared;
3852 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3853 ReportHint = true;
3854 Reason = PDSA_LocalVarPrivate;
3855 }
3856 if (Reason != PDSA_Implicit) {
3857 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
3858 SemaRef.Diag(Loc: ReportLoc, DiagID: diag::note_omp_predetermined_dsa)
3859 << Reason << ReportHint
3860 << getOpenMPDirectiveName(D: Stack->getCurrentDirective(), Ver: OMPVersion);
3861 } else if (DVar.ImplicitDSALoc.isValid()) {
3862 SemaRef.Diag(Loc: DVar.ImplicitDSALoc, DiagID: diag::note_omp_implicit_dsa)
3863 << getOpenMPClauseNameForDiag(C: DVar.CKind);
3864 }
3865}
3866
3867static OpenMPMapClauseKind
3868getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
3869 bool IsAggregateOrDeclareTarget,
3870 bool HasConstQualifier) {
3871 OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
3872 switch (M) {
3873 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3874 case OMPC_DEFAULTMAP_MODIFIER_storage:
3875 Kind = OMPC_MAP_alloc;
3876 break;
3877 case OMPC_DEFAULTMAP_MODIFIER_to:
3878 Kind = OMPC_MAP_to;
3879 break;
3880 case OMPC_DEFAULTMAP_MODIFIER_from:
3881 Kind = OMPC_MAP_from;
3882 break;
3883 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3884 Kind = OMPC_MAP_tofrom;
3885 break;
3886 case OMPC_DEFAULTMAP_MODIFIER_present:
3887 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3888 // If implicit-behavior is present, each variable referenced in the
3889 // construct in the category specified by variable-category is treated as if
3890 // it had been listed in a map clause with the map-type of alloc and
3891 // map-type-modifier of present.
3892 Kind = OMPC_MAP_alloc;
3893 break;
3894 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3895 case OMPC_DEFAULTMAP_MODIFIER_private:
3896 case OMPC_DEFAULTMAP_MODIFIER_last:
3897 llvm_unreachable("Unexpected defaultmap implicit behavior");
3898 case OMPC_DEFAULTMAP_MODIFIER_none:
3899 case OMPC_DEFAULTMAP_MODIFIER_default:
3900 case OMPC_DEFAULTMAP_MODIFIER_unknown:
3901 // IsAggregateOrDeclareTarget could be true if:
3902 // 1. the implicit behavior for aggregate is tofrom
3903 // 2. it's a declare target link
3904 if (IsAggregateOrDeclareTarget) {
3905 if (HasConstQualifier)
3906 Kind = OMPC_MAP_to;
3907 else
3908 Kind = OMPC_MAP_tofrom;
3909 break;
3910 }
3911 llvm_unreachable("Unexpected defaultmap implicit behavior");
3912 }
3913 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3914 return Kind;
3915}
3916
3917static bool hasNoMutableFields(const CXXRecordDecl *RD) {
3918 for (const auto *FD : RD->fields()) {
3919 if (FD->isMutable())
3920 return false;
3921 QualType FT = FD->getType();
3922 while (FT->isArrayType())
3923 FT = FT->getAsArrayTypeUnsafe()->getElementType();
3924 if (const auto *NestedRD = FT->getAsCXXRecordDecl())
3925 if (!hasNoMutableFields(RD: NestedRD))
3926 return false;
3927 }
3928 return true;
3929}
3930
3931static bool hasConstQualifiedMappingType(QualType T) {
3932 while (T->isArrayType())
3933 T = T->getAsArrayTypeUnsafe()->getElementType();
3934 if (!T.isConstQualified())
3935 return false;
3936 if (const auto *RD = T->getAsCXXRecordDecl())
3937 // TODO : Per OpenMP 6.0 p299 lines 3-4, non-mutable members of a
3938 // const-qualified struct should also be ignored for 'from'. This
3939 // requires per-member mapping granularity via compiler-generated
3940 // default mappers and a mechanism to ensure constness to the mapper.
3941 // For now we conservatively treat any struct with mutable members as
3942 // requiring full 'tofrom'.
3943 return hasNoMutableFields(RD);
3944 return true;
3945}
3946
3947namespace {
3948struct VariableImplicitInfo {
3949 static const unsigned MapKindNum = OMPC_MAP_unknown;
3950 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3951
3952 llvm::SetVector<Expr *> Privates;
3953 llvm::SetVector<Expr *> Firstprivates;
3954 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3955 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3956 MapModifiers[DefaultmapKindNum];
3957};
3958
3959class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3960 DSAStackTy *Stack;
3961 Sema &SemaRef;
3962 OpenMPDirectiveKind DKind = OMPD_unknown;
3963 bool ErrorFound = false;
3964 bool TryCaptureCXXThisMembers = false;
3965 CapturedStmt *CS = nullptr;
3966
3967 VariableImplicitInfo ImpInfo;
3968 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3969 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3970
3971 void VisitSubCaptures(OMPExecutableDirective *S) {
3972 // Check implicitly captured variables.
3973 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3974 return;
3975 if (S->getDirectiveKind() == OMPD_atomic ||
3976 S->getDirectiveKind() == OMPD_critical ||
3977 S->getDirectiveKind() == OMPD_section ||
3978 S->getDirectiveKind() == OMPD_master ||
3979 S->getDirectiveKind() == OMPD_masked ||
3980 S->getDirectiveKind() == OMPD_scope ||
3981 S->getDirectiveKind() == OMPD_assume ||
3982 isOpenMPLoopTransformationDirective(DKind: S->getDirectiveKind())) {
3983 Visit(S: S->getAssociatedStmt());
3984 return;
3985 }
3986 visitSubCaptures(S: S->getInnermostCapturedStmt());
3987 // Try to capture inner this->member references to generate correct mappings
3988 // and diagnostics.
3989 if (TryCaptureCXXThisMembers ||
3990 (isOpenMPTargetExecutionDirective(DKind) &&
3991 llvm::any_of(Range: S->getInnermostCapturedStmt()->captures(),
3992 P: [](const CapturedStmt::Capture &C) {
3993 return C.capturesThis();
3994 }))) {
3995 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3996 TryCaptureCXXThisMembers = true;
3997 Visit(S: S->getInnermostCapturedStmt()->getCapturedStmt());
3998 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3999 }
4000 // In tasks firstprivates are not captured anymore, need to analyze them
4001 // explicitly.
4002 if (isOpenMPTaskingDirective(Kind: S->getDirectiveKind()) &&
4003 !isOpenMPTaskLoopDirective(DKind: S->getDirectiveKind())) {
4004 for (OMPClause *C : S->clauses())
4005 if (auto *FC = dyn_cast<OMPFirstprivateClause>(Val: C)) {
4006 for (Expr *Ref : FC->varlist())
4007 Visit(S: Ref);
4008 }
4009 }
4010 }
4011
4012public:
4013 void VisitDeclRefExpr(DeclRefExpr *E) {
4014 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
4015 E->isValueDependent() || E->containsUnexpandedParameterPack() ||
4016 E->isInstantiationDependent() ||
4017 E->isNonOdrUse() == clang::NOUR_Unevaluated)
4018 return;
4019 if (auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
4020 // Check the datasharing rules for the expressions in the clauses.
4021 if (!CS || (isa<OMPCapturedExprDecl>(Val: VD) && !CS->capturesVariable(Var: VD) &&
4022 !Stack->getTopDSA(D: VD, /*FromParent=*/false).RefExpr &&
4023 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
4024 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: VD))
4025 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
4026 Visit(S: CED->getInit());
4027 return;
4028 }
4029 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(Val: VD))
4030 // Do not analyze internal variables and do not enclose them into
4031 // implicit clauses.
4032 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
4033 return;
4034 VD = VD->getCanonicalDecl();
4035 // Skip internally declared variables.
4036 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(Var: VD) &&
4037 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4038 !Stack->isImplicitTaskFirstprivate(D: VD))
4039 return;
4040 // Skip allocators in uses_allocators clauses.
4041 if (Stack->isUsesAllocatorsDecl(D: VD))
4042 return;
4043
4044 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D: VD, /*FromParent=*/false);
4045 // Check if the variable has explicit DSA set and stop analysis if it so.
4046 if (DVar.RefExpr || !ImplicitDeclarations.insert(V: VD).second)
4047 return;
4048
4049 // Skip internally declared static variables.
4050 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
4051 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
4052 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(Var: VD) &&
4053 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
4054 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
4055 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4056 !Stack->isImplicitTaskFirstprivate(D: VD))
4057 return;
4058
4059 SourceLocation ELoc = E->getExprLoc();
4060 // The default(none) clause requires that each variable that is referenced
4061 // in the construct, and does not have a predetermined data-sharing
4062 // attribute, must have its data-sharing attribute explicitly determined
4063 // by being listed in a data-sharing attribute clause.
4064 if (DVar.CKind == OMPC_unknown &&
4065 (Stack->getDefaultDSA() == DSA_none ||
4066 Stack->getDefaultDSA() == DSA_private ||
4067 Stack->getDefaultDSA() == DSA_firstprivate) &&
4068 isImplicitOrExplicitTaskingRegion(DKind) &&
4069 VarsWithInheritedDSA.count(Val: VD) == 0) {
4070 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4071 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4072 Stack->getDefaultDSA() == DSA_private)) {
4073 DSAStackTy::DSAVarData DVar =
4074 Stack->getImplicitDSA(D: VD, /*FromParent=*/false);
4075 InheritedDSA = DVar.CKind == OMPC_unknown;
4076 }
4077 if (InheritedDSA)
4078 VarsWithInheritedDSA[VD] = E;
4079 if (Stack->getDefaultDSA() == DSA_none)
4080 return;
4081 }
4082
4083 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
4084 // If implicit-behavior is none, each variable referenced in the
4085 // construct that does not have a predetermined data-sharing attribute
4086 // and does not appear in a to or link clause on a declare target
4087 // directive must be listed in a data-mapping attribute clause, a
4088 // data-sharing attribute clause (including a data-sharing attribute
4089 // clause on a combined construct where target. is one of the
4090 // constituent constructs), or an is_device_ptr clause.
4091 OpenMPDefaultmapClauseKind ClauseKind =
4092 getVariableCategoryFromDecl(LO: SemaRef.getLangOpts(), VD);
4093 if (SemaRef.getLangOpts().OpenMP >= 50) {
4094 bool IsModifierNone = Stack->getDefaultmapModifier(Kind: ClauseKind) ==
4095 OMPC_DEFAULTMAP_MODIFIER_none;
4096 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4097 VarsWithInheritedDSA.count(Val: VD) == 0 && !Res) {
4098 // Only check for data-mapping attribute and is_device_ptr here
4099 // since we have already make sure that the declaration does not
4100 // have a data-sharing attribute above
4101 if (!Stack->checkMappableExprComponentListsForDecl(
4102 VD, /*CurrentRegionOnly=*/true,
4103 Check: [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
4104 MapExprComponents,
4105 OpenMPClauseKind) {
4106 auto MI = MapExprComponents.rbegin();
4107 auto ME = MapExprComponents.rend();
4108 return MI != ME && MI->getAssociatedDeclaration() == VD;
4109 })) {
4110 VarsWithInheritedDSA[VD] = E;
4111 return;
4112 }
4113 }
4114 }
4115 if (SemaRef.getLangOpts().OpenMP > 50) {
4116 bool IsModifierPresent = Stack->getDefaultmapModifier(Kind: ClauseKind) ==
4117 OMPC_DEFAULTMAP_MODIFIER_present;
4118 if (IsModifierPresent) {
4119 if (!llvm::is_contained(Range&: ImpInfo.MapModifiers[ClauseKind],
4120 Element: OMPC_MAP_MODIFIER_present)) {
4121 ImpInfo.MapModifiers[ClauseKind].push_back(
4122 Elt: OMPC_MAP_MODIFIER_present);
4123 }
4124 }
4125 }
4126
4127 if (isOpenMPTargetExecutionDirective(DKind) &&
4128 !Stack->isLoopControlVariable(D: VD).first) {
4129 if (!Stack->checkMappableExprComponentListsForDecl(
4130 VD, /*CurrentRegionOnly=*/true,
4131 Check: [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
4132 StackComponents,
4133 OpenMPClauseKind) {
4134 if (SemaRef.LangOpts.OpenMP >= 50)
4135 return !StackComponents.empty();
4136 // Variable is used if it has been marked as an array, array
4137 // section, array shaping or the variable itself.
4138 return StackComponents.size() == 1 ||
4139 llvm::all_of(
4140 Range: llvm::drop_begin(RangeOrContainer: llvm::reverse(C&: StackComponents)),
4141 P: [](const OMPClauseMappableExprCommon::
4142 MappableComponent &MC) {
4143 return MC.getAssociatedDeclaration() ==
4144 nullptr &&
4145 (isa<ArraySectionExpr>(
4146 Val: MC.getAssociatedExpression()) ||
4147 isa<OMPArrayShapingExpr>(
4148 Val: MC.getAssociatedExpression()) ||
4149 isa<ArraySubscriptExpr>(
4150 Val: MC.getAssociatedExpression()));
4151 });
4152 })) {
4153 bool IsFirstprivate = false;
4154 // By default lambdas are captured as firstprivates.
4155 if (const auto *RD =
4156 VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
4157 IsFirstprivate = RD->isLambda();
4158 IsFirstprivate =
4159 IsFirstprivate || (Stack->mustBeFirstprivate(Kind: ClauseKind) && !Res);
4160 if (IsFirstprivate) {
4161 ImpInfo.Firstprivates.insert(X: E);
4162 } else {
4163 OpenMPDefaultmapClauseModifier M =
4164 Stack->getDefaultmapModifier(Kind: ClauseKind);
4165 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4166 ImpInfo.Privates.insert(X: E);
4167 } else {
4168 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
4169 M, IsAggregateOrDeclareTarget: ClauseKind == OMPC_DEFAULTMAP_aggregate || Res,
4170 HasConstQualifier: hasConstQualifiedMappingType(T: E->getType()));
4171 ImpInfo.Mappings[ClauseKind][Kind].insert(X: E);
4172 }
4173 }
4174 return;
4175 }
4176 }
4177
4178 // OpenMP [2.9.3.6, Restrictions, p.2]
4179 // A list item that appears in a reduction clause of the innermost
4180 // enclosing worksharing or parallel construct may not be accessed in an
4181 // explicit task.
4182 DVar = Stack->hasInnermostDSA(
4183 D: VD,
4184 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
4185 return C == OMPC_reduction && !AppliedToPointee;
4186 },
4187 DPred: [](OpenMPDirectiveKind K) {
4188 return isOpenMPParallelDirective(DKind: K) ||
4189 isOpenMPWorksharingDirective(DKind: K) || isOpenMPTeamsDirective(DKind: K);
4190 },
4191 /*FromParent=*/true);
4192 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind == OMPC_reduction) {
4193 ErrorFound = true;
4194 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_in_task);
4195 reportOriginalDsa(SemaRef, Stack, D: VD, DVar);
4196 return;
4197 }
4198
4199 // Define implicit data-sharing attributes for task.
4200 DVar = Stack->getImplicitDSA(D: VD, /*FromParent=*/false);
4201 if (((isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind != OMPC_shared) ||
4202 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4203 DVar.CKind == OMPC_firstprivate) ||
4204 (Stack->getDefaultDSA() == DSA_private &&
4205 DVar.CKind == OMPC_private)) &&
4206 !DVar.RefExpr)) &&
4207 !Stack->isLoopControlVariable(D: VD).first) {
4208 if (Stack->getDefaultDSA() == DSA_private)
4209 ImpInfo.Privates.insert(X: E);
4210 else
4211 ImpInfo.Firstprivates.insert(X: E);
4212 return;
4213 }
4214
4215 // Store implicitly used globals with declare target link for parent
4216 // target.
4217 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
4218 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4219 Stack->addToParentTargetRegionLinkGlobals(E);
4220 return;
4221 }
4222 }
4223 }
4224 void VisitMemberExpr(MemberExpr *E) {
4225 if (E->isTypeDependent() || E->isValueDependent() ||
4226 E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
4227 return;
4228 auto *FD = dyn_cast<FieldDecl>(Val: E->getMemberDecl());
4229 if (auto *TE = dyn_cast<CXXThisExpr>(Val: E->getBase()->IgnoreParenCasts())) {
4230 if (!FD)
4231 return;
4232 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D: FD, /*FromParent=*/false);
4233 // Check if the variable has explicit DSA set and stop analysis if it
4234 // so.
4235 if (DVar.RefExpr || !ImplicitDeclarations.insert(V: FD).second)
4236 return;
4237
4238 if (isOpenMPTargetExecutionDirective(DKind) &&
4239 !Stack->isLoopControlVariable(D: FD).first &&
4240 !Stack->checkMappableExprComponentListsForDecl(
4241 VD: FD, /*CurrentRegionOnly=*/true,
4242 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef
4243 StackComponents,
4244 OpenMPClauseKind) {
4245 return isa<CXXThisExpr>(
4246 Val: cast<MemberExpr>(
4247 Val: StackComponents.back().getAssociatedExpression())
4248 ->getBase()
4249 ->IgnoreParens());
4250 })) {
4251 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4252 // A bit-field cannot appear in a map clause.
4253 //
4254 if (FD->isBitField())
4255 return;
4256
4257 // Check to see if the member expression is referencing a class that
4258 // has already been explicitly mapped
4259 if (Stack->isClassPreviouslyMapped(QT: TE->getType()))
4260 return;
4261
4262 OpenMPDefaultmapClauseModifier Modifier =
4263 Stack->getDefaultmapModifier(Kind: OMPC_DEFAULTMAP_aggregate);
4264 OpenMPDefaultmapClauseKind ClauseKind =
4265 getVariableCategoryFromDecl(LO: SemaRef.getLangOpts(), VD: FD);
4266 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
4267 M: Modifier, /*IsAggregateOrDeclareTarget=*/true,
4268 /*HasConstQualifier=*/false);
4269 ImpInfo.Mappings[ClauseKind][Kind].insert(X: E);
4270 return;
4271 }
4272
4273 SourceLocation ELoc = E->getExprLoc();
4274 // OpenMP [2.9.3.6, Restrictions, p.2]
4275 // A list item that appears in a reduction clause of the innermost
4276 // enclosing worksharing or parallel construct may not be accessed in
4277 // an explicit task.
4278 DVar = Stack->hasInnermostDSA(
4279 D: FD,
4280 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
4281 return C == OMPC_reduction && !AppliedToPointee;
4282 },
4283 DPred: [](OpenMPDirectiveKind K) {
4284 return isOpenMPParallelDirective(DKind: K) ||
4285 isOpenMPWorksharingDirective(DKind: K) || isOpenMPTeamsDirective(DKind: K);
4286 },
4287 /*FromParent=*/true);
4288 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind == OMPC_reduction) {
4289 ErrorFound = true;
4290 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_in_task);
4291 reportOriginalDsa(SemaRef, Stack, D: FD, DVar);
4292 return;
4293 }
4294
4295 // Define implicit data-sharing attributes for task.
4296 DVar = Stack->getImplicitDSA(D: FD, /*FromParent=*/false);
4297 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind != OMPC_shared &&
4298 !Stack->isLoopControlVariable(D: FD).first) {
4299 // Check if there is a captured expression for the current field in the
4300 // region. Do not mark it as firstprivate unless there is no captured
4301 // expression.
4302 // TODO: try to make it firstprivate.
4303 if (DVar.CKind != OMPC_unknown)
4304 ImpInfo.Firstprivates.insert(X: E);
4305 }
4306 return;
4307 }
4308 if (isOpenMPTargetExecutionDirective(DKind)) {
4309 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
4310 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, CKind: OMPC_map,
4311 DKind, /*NoDiagnose=*/true))
4312 return;
4313 const auto *VD = cast<ValueDecl>(
4314 Val: CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4315 if (!Stack->checkMappableExprComponentListsForDecl(
4316 VD, /*CurrentRegionOnly=*/true,
4317 Check: [&CurComponents](
4318 OMPClauseMappableExprCommon::MappableExprComponentListRef
4319 StackComponents,
4320 OpenMPClauseKind) {
4321 auto CCI = CurComponents.rbegin();
4322 auto CCE = CurComponents.rend();
4323 for (const auto &SC : llvm::reverse(C&: StackComponents)) {
4324 // Do both expressions have the same kind?
4325 if (CCI->getAssociatedExpression()->getStmtClass() !=
4326 SC.getAssociatedExpression()->getStmtClass())
4327 if (!((isa<ArraySectionExpr>(
4328 Val: SC.getAssociatedExpression()) ||
4329 isa<OMPArrayShapingExpr>(
4330 Val: SC.getAssociatedExpression())) &&
4331 isa<ArraySubscriptExpr>(
4332 Val: CCI->getAssociatedExpression())))
4333 return false;
4334
4335 const Decl *CCD = CCI->getAssociatedDeclaration();
4336 const Decl *SCD = SC.getAssociatedDeclaration();
4337 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4338 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4339 if (SCD != CCD)
4340 return false;
4341 std::advance(i&: CCI, n: 1);
4342 if (CCI == CCE)
4343 break;
4344 }
4345 return true;
4346 })) {
4347 Visit(S: E->getBase());
4348 }
4349 } else if (!TryCaptureCXXThisMembers) {
4350 Visit(S: E->getBase());
4351 }
4352 }
4353 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4354 for (OMPClause *C : S->clauses()) {
4355 // Skip analysis of arguments of private clauses for task|target
4356 // directives.
4357 if (isa_and_nonnull<OMPPrivateClause>(Val: C))
4358 continue;
4359 // Skip analysis of arguments of implicitly defined firstprivate clause
4360 // for task|target directives.
4361 // Skip analysis of arguments of implicitly defined map clause for target
4362 // directives.
4363 if (C && !((isa<OMPFirstprivateClause>(Val: C) || isa<OMPMapClause>(Val: C)) &&
4364 C->isImplicit() && !isOpenMPTaskingDirective(Kind: DKind))) {
4365 for (Stmt *CC : C->children()) {
4366 if (CC)
4367 Visit(S: CC);
4368 }
4369 }
4370 }
4371 // Check implicitly captured variables.
4372 VisitSubCaptures(S);
4373 }
4374
4375 void VisitOMPCanonicalLoopNestTransformationDirective(
4376 OMPCanonicalLoopNestTransformationDirective *S) {
4377 // Loop transformation directives do not introduce data sharing
4378 VisitStmt(S);
4379 }
4380
4381 void VisitCallExpr(CallExpr *S) {
4382 for (Stmt *C : S->arguments()) {
4383 if (C) {
4384 // Check implicitly captured variables in the task-based directives to
4385 // check if they must be firstprivatized.
4386 Visit(S: C);
4387 }
4388 }
4389 if (Expr *Callee = S->getCallee()) {
4390 auto *CI = Callee->IgnoreParenImpCasts();
4391 if (auto *CE = dyn_cast<MemberExpr>(Val: CI))
4392 Visit(S: CE->getBase());
4393 else if (auto *CE = dyn_cast<DeclRefExpr>(Val: CI))
4394 Visit(S: CE);
4395 }
4396 }
4397 void VisitStmt(Stmt *S) {
4398 for (Stmt *C : S->children()) {
4399 if (C) {
4400 // Check implicitly captured variables in the task-based directives to
4401 // check if they must be firstprivatized.
4402 Visit(S: C);
4403 }
4404 }
4405 }
4406
4407 void visitSubCaptures(CapturedStmt *S) {
4408 for (const CapturedStmt::Capture &Cap : S->captures()) {
4409 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4410 continue;
4411 VarDecl *VD = Cap.getCapturedVar();
4412 // Do not try to map the variable if it or its sub-component was mapped
4413 // already.
4414 if (isOpenMPTargetExecutionDirective(DKind) &&
4415 Stack->checkMappableExprComponentListsForDecl(
4416 VD, /*CurrentRegionOnly=*/true,
4417 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4418 OpenMPClauseKind) { return true; }))
4419 continue;
4420 DeclRefExpr *DRE = buildDeclRefExpr(
4421 S&: SemaRef, D: VD, Ty: VD->getType().getNonLValueExprType(Context: SemaRef.Context),
4422 Loc: Cap.getLocation(), /*RefersToCapture=*/true);
4423 Visit(S: DRE);
4424 }
4425 }
4426 bool isErrorFound() const { return ErrorFound; }
4427 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4428 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4429 return VarsWithInheritedDSA;
4430 }
4431
4432 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4433 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4434 DKind = S->getCurrentDirective();
4435 // Process declare target link variables for the target directives.
4436 if (isOpenMPTargetExecutionDirective(DKind)) {
4437 for (DeclRefExpr *E : Stack->getLinkGlobals())
4438 Visit(S: E);
4439 }
4440 }
4441};
4442} // namespace
4443
4444static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4445 OpenMPDirectiveKind DKind,
4446 bool ScopeEntry) {
4447 SmallVector<llvm::omp::TraitProperty, 8> Traits;
4448 if (isOpenMPTargetExecutionDirective(DKind))
4449 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_target_target);
4450 if (isOpenMPTeamsDirective(DKind))
4451 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_teams_teams);
4452 if (isOpenMPParallelDirective(DKind))
4453 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_parallel_parallel);
4454 if (isOpenMPWorksharingDirective(DKind))
4455 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_for_for);
4456 if (isOpenMPSimdDirective(DKind))
4457 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_simd_simd);
4458 Stack->handleConstructTrait(Traits, ScopeEntry);
4459}
4460
4461static SmallVector<SemaOpenMP::CapturedParamNameType>
4462getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4463 ASTContext &Context = SemaRef.getASTContext();
4464 QualType KmpInt32Ty =
4465 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4466 QualType KmpInt32PtrTy =
4467 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4468 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4469 std::make_pair(x: ".global_tid.", y&: KmpInt32PtrTy),
4470 std::make_pair(x: ".bound_tid.", y&: KmpInt32PtrTy),
4471 };
4472 if (LoopBoundSharing) {
4473 QualType KmpSizeTy = Context.getSizeType().withConst();
4474 Params.push_back(Elt: std::make_pair(x: ".previous.lb.", y&: KmpSizeTy));
4475 Params.push_back(Elt: std::make_pair(x: ".previous.ub.", y&: KmpSizeTy));
4476 }
4477
4478 // __context with shared vars
4479 Params.push_back(Elt: std::make_pair(x: StringRef(), y: QualType()));
4480 return Params;
4481}
4482
4483static SmallVector<SemaOpenMP::CapturedParamNameType>
4484getTeamsRegionParams(Sema &SemaRef) {
4485 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4486}
4487
4488static SmallVector<SemaOpenMP::CapturedParamNameType>
4489getTaskRegionParams(Sema &SemaRef) {
4490 ASTContext &Context = SemaRef.getASTContext();
4491 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(DestWidth: 32, Signed: 1).withConst();
4492 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4493 QualType KmpInt32PtrTy =
4494 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4495 QualType Args[] = {VoidPtrTy};
4496 FunctionProtoType::ExtProtoInfo EPI;
4497 EPI.Variadic = true;
4498 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4499 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4500 std::make_pair(x: ".global_tid.", y&: KmpInt32Ty),
4501 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4502 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4503 std::make_pair(
4504 x: ".copy_fn.",
4505 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4506 std::make_pair(x: ".task_t.", y: Context.VoidPtrTy.withConst()),
4507 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4508 };
4509 return Params;
4510}
4511
4512static SmallVector<SemaOpenMP::CapturedParamNameType>
4513getTargetRegionParams(Sema &SemaRef) {
4514 ASTContext &Context = SemaRef.getASTContext();
4515 SmallVector<SemaOpenMP::CapturedParamNameType> Params;
4516 // __context with shared vars
4517 Params.push_back(Elt: std::make_pair(x: StringRef(), y: QualType()));
4518 // Implicit dyn_ptr argument, appended as the last parameter. Present on both
4519 // host and device so argument counts match without runtime manipulation.
4520 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4521 Params.push_back(Elt: std::make_pair(x: StringRef("dyn_ptr"), y&: VoidPtrTy));
4522 return Params;
4523}
4524
4525static SmallVector<SemaOpenMP::CapturedParamNameType>
4526getUnknownRegionParams(Sema &SemaRef) {
4527 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4528 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4529 };
4530 return Params;
4531}
4532
4533static SmallVector<SemaOpenMP::CapturedParamNameType>
4534getTaskloopRegionParams(Sema &SemaRef) {
4535 ASTContext &Context = SemaRef.getASTContext();
4536 QualType KmpInt32Ty =
4537 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4538 QualType KmpUInt64Ty =
4539 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4540 QualType KmpInt64Ty =
4541 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4542 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4543 QualType KmpInt32PtrTy =
4544 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4545 QualType Args[] = {VoidPtrTy};
4546 FunctionProtoType::ExtProtoInfo EPI;
4547 EPI.Variadic = true;
4548 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4549 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4550 std::make_pair(x: ".global_tid.", y&: KmpInt32Ty),
4551 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4552 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4553 std::make_pair(
4554 x: ".copy_fn.",
4555 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4556 std::make_pair(x: ".task_t.", y: Context.VoidPtrTy.withConst()),
4557 std::make_pair(x: ".lb.", y&: KmpUInt64Ty),
4558 std::make_pair(x: ".ub.", y&: KmpUInt64Ty),
4559 std::make_pair(x: ".st.", y&: KmpInt64Ty),
4560 std::make_pair(x: ".liter.", y&: KmpInt32Ty),
4561 std::make_pair(x: ".reductions.", y&: VoidPtrTy),
4562 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4563 };
4564 return Params;
4565}
4566
4567static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind,
4568 Scope *CurScope, SourceLocation Loc) {
4569 SmallVector<OpenMPDirectiveKind> Regions;
4570 getOpenMPCaptureRegions(CaptureRegions&: Regions, DKind);
4571
4572 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(Kind: DKind);
4573
4574 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4575 CSI->TheCapturedDecl->addAttr(A: AlwaysInlineAttr::CreateImplicit(
4576 Ctx&: SemaRef.getASTContext(), Range: {}, S: AlwaysInlineAttr::Keyword_forceinline));
4577 };
4578
4579 for (auto [Level, RKind] : llvm::enumerate(First&: Regions)) {
4580 switch (RKind) {
4581 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4582 // are listed here.
4583 case OMPD_parallel:
4584 SemaRef.ActOnCapturedRegionStart(
4585 Loc, CurScope, Kind: CR_OpenMP,
4586 Params: getParallelRegionParams(SemaRef, LoopBoundSharing), OpenMPCaptureLevel: Level);
4587 break;
4588 case OMPD_teams:
4589 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4590 Params: getTeamsRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4591 break;
4592 case OMPD_task:
4593 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4594 Params: getTaskRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4595 // Mark this captured region as inlined, because we don't use outlined
4596 // function directly.
4597 MarkAsInlined(SemaRef.getCurCapturedRegion());
4598 break;
4599 case OMPD_taskloop:
4600 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4601 Params: getTaskloopRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4602 // Mark this captured region as inlined, because we don't use outlined
4603 // function directly.
4604 MarkAsInlined(SemaRef.getCurCapturedRegion());
4605 break;
4606 case OMPD_target:
4607 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4608 Params: getTargetRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4609 break;
4610 case OMPD_unknown:
4611 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4612 Params: getUnknownRegionParams(SemaRef));
4613 break;
4614 case OMPD_metadirective:
4615 case OMPD_nothing:
4616 default:
4617 llvm_unreachable("Unexpected capture region");
4618 }
4619 }
4620}
4621
4622void SemaOpenMP::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,
4623 Scope *CurScope) {
4624 if (DKind == OMPD_ordered_blockassoc &&
4625 DSAStack->getCurrentDirective() == OMPD_ordered_standalone) {
4626 DSAStack->setOrderedToBlockAssociated();
4627 }
4628 switch (DKind) {
4629 case OMPD_atomic:
4630 case OMPD_critical:
4631 case OMPD_masked:
4632 case OMPD_master:
4633 case OMPD_section:
4634 case OMPD_tile:
4635 case OMPD_stripe:
4636 case OMPD_unroll:
4637 case OMPD_reverse:
4638 case OMPD_split:
4639 case OMPD_interchange:
4640 case OMPD_fuse:
4641 case OMPD_assume:
4642 break;
4643 default:
4644 processCapturedRegions(SemaRef, DKind, CurScope,
4645 DSAStack->getConstructLoc());
4646 break;
4647 }
4648
4649 DSAStack->setContext(SemaRef.CurContext);
4650 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4651}
4652
4653int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4654 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4655}
4656
4657int SemaOpenMP::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4658 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4659 getOpenMPCaptureRegions(CaptureRegions, DKind);
4660 return CaptureRegions.size();
4661}
4662
4663static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
4664 Expr *CaptureExpr, bool WithInit,
4665 DeclContext *CurContext,
4666 bool AsExpression) {
4667 assert(CaptureExpr);
4668 ASTContext &C = S.getASTContext();
4669 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4670 QualType Ty = Init->getType();
4671 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4672 if (S.getLangOpts().CPlusPlus) {
4673 Ty = C.getLValueReferenceType(T: Ty);
4674 } else {
4675 Ty = C.getPointerType(T: Ty);
4676 ExprResult Res =
4677 S.CreateBuiltinUnaryOp(OpLoc: CaptureExpr->getExprLoc(), Opc: UO_AddrOf, InputExpr: Init);
4678 if (!Res.isUsable())
4679 return nullptr;
4680 Init = Res.get();
4681 }
4682 WithInit = true;
4683 }
4684 auto *CED = OMPCapturedExprDecl::Create(C, DC: CurContext, Id, T: Ty,
4685 StartLoc: CaptureExpr->getBeginLoc());
4686 if (!WithInit)
4687 CED->addAttr(A: OMPCaptureNoInitAttr::CreateImplicit(Ctx&: C));
4688 CurContext->addHiddenDecl(D: CED);
4689 Sema::TentativeAnalysisScope Trap(S);
4690 S.AddInitializerToDecl(dcl: CED, init: Init, /*DirectInit=*/false);
4691 return CED;
4692}
4693
4694static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4695 bool WithInit) {
4696 OMPCapturedExprDecl *CD;
4697 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4698 CD = cast<OMPCapturedExprDecl>(Val: VD);
4699 else
4700 CD = buildCaptureDecl(S, Id: D->getIdentifier(), CaptureExpr, WithInit,
4701 CurContext: S.CurContext,
4702 /*AsExpression=*/false);
4703 return buildDeclRefExpr(S, D: CD, Ty: CD->getType().getNonReferenceType(),
4704 Loc: CaptureExpr->getExprLoc());
4705}
4706
4707static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4708 StringRef Name) {
4709 CaptureExpr = S.DefaultLvalueConversion(E: CaptureExpr).get();
4710 if (!Ref) {
4711 OMPCapturedExprDecl *CD = buildCaptureDecl(
4712 S, Id: &S.getASTContext().Idents.get(Name), CaptureExpr,
4713 /*WithInit=*/true, CurContext: S.CurContext, /*AsExpression=*/true);
4714 Ref = buildDeclRefExpr(S, D: CD, Ty: CD->getType().getNonReferenceType(),
4715 Loc: CaptureExpr->getExprLoc());
4716 }
4717 ExprResult Res = Ref;
4718 if (!S.getLangOpts().CPlusPlus &&
4719 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4720 Ref->getType()->isPointerType()) {
4721 Res = S.CreateBuiltinUnaryOp(OpLoc: CaptureExpr->getExprLoc(), Opc: UO_Deref, InputExpr: Ref);
4722 if (!Res.isUsable())
4723 return ExprError();
4724 }
4725 return S.DefaultLvalueConversion(E: Res.get());
4726}
4727
4728namespace {
4729// OpenMP directives parsed in this section are represented as a
4730// CapturedStatement with an associated statement. If a syntax error
4731// is detected during the parsing of the associated statement, the
4732// compiler must abort processing and close the CapturedStatement.
4733//
4734// Combined directives such as 'target parallel' have more than one
4735// nested CapturedStatements. This RAII ensures that we unwind out
4736// of all the nested CapturedStatements when an error is found.
4737class CaptureRegionUnwinderRAII {
4738private:
4739 Sema &S;
4740 bool &ErrorFound;
4741 OpenMPDirectiveKind DKind = OMPD_unknown;
4742
4743public:
4744 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4745 OpenMPDirectiveKind DKind)
4746 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4747 ~CaptureRegionUnwinderRAII() {
4748 if (ErrorFound) {
4749 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4750 while (--ThisCaptureLevel >= 0)
4751 S.ActOnCapturedRegionError();
4752 }
4753 }
4754};
4755} // namespace
4756
4757void SemaOpenMP::tryCaptureOpenMPLambdas(ValueDecl *V) {
4758 // Capture variables captured by reference in lambdas for target-based
4759 // directives.
4760 if (!SemaRef.CurContext->isDependentContext() &&
4761 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4762 isOpenMPTargetDataManagementDirective(
4763 DSAStack->getCurrentDirective()))) {
4764 QualType Type = V->getType();
4765 if (const auto *RD = Type.getCanonicalType()
4766 .getNonReferenceType()
4767 ->getAsCXXRecordDecl()) {
4768 bool SavedForceCaptureByReferenceInTargetExecutable =
4769 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4770 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4771 /*V=*/true);
4772 if (RD->isLambda()) {
4773 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4774 FieldDecl *ThisCapture;
4775 RD->getCaptureFields(Captures, ThisCapture);
4776 for (const LambdaCapture &LC : RD->captures()) {
4777 if (LC.getCaptureKind() == LCK_ByRef) {
4778 VarDecl *VD = cast<VarDecl>(Val: LC.getCapturedVar());
4779 DeclContext *VDC = VD->getDeclContext();
4780 if (!VDC->Encloses(DC: SemaRef.CurContext))
4781 continue;
4782 SemaRef.MarkVariableReferenced(Loc: LC.getLocation(), Var: VD);
4783 } else if (LC.getCaptureKind() == LCK_This) {
4784 QualType ThisTy = SemaRef.getCurrentThisType();
4785 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4786 T1: ThisTy, T2: ThisCapture->getType()))
4787 SemaRef.CheckCXXThisCapture(Loc: LC.getLocation());
4788 }
4789 }
4790 }
4791 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4792 SavedForceCaptureByReferenceInTargetExecutable);
4793 }
4794 }
4795}
4796
4797static bool checkOrderedOrderSpecified(Sema &S,
4798 const ArrayRef<OMPClause *> Clauses) {
4799 const OMPOrderedClause *Ordered = nullptr;
4800 const OMPOrderClause *Order = nullptr;
4801
4802 for (const OMPClause *Clause : Clauses) {
4803 if (Clause->getClauseKind() == OMPC_ordered)
4804 Ordered = cast<OMPOrderedClause>(Val: Clause);
4805 else if (Clause->getClauseKind() == OMPC_order) {
4806 Order = cast<OMPOrderClause>(Val: Clause);
4807 if (Order->getKind() != OMPC_ORDER_concurrent)
4808 Order = nullptr;
4809 }
4810 if (Ordered && Order)
4811 break;
4812 }
4813
4814 if (Ordered && Order) {
4815 S.Diag(Loc: Order->getKindKwLoc(),
4816 DiagID: diag::err_omp_simple_clause_incompatible_with_ordered)
4817 << getOpenMPClauseNameForDiag(C: OMPC_order)
4818 << getOpenMPSimpleClauseTypeName(Kind: OMPC_order, Type: OMPC_ORDER_concurrent)
4819 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4820 S.Diag(Loc: Ordered->getBeginLoc(), DiagID: diag::note_omp_ordered_param)
4821 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4822 return true;
4823 }
4824 return false;
4825}
4826
4827StmtResult SemaOpenMP::ActOnOpenMPRegionEnd(StmtResult S,
4828 ArrayRef<OMPClause *> Clauses) {
4829 handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(),
4830 /*ScopeEntry=*/false);
4831 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4832 return S;
4833
4834 bool ErrorFound = false;
4835 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4836 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4837 if (!S.isUsable()) {
4838 ErrorFound = true;
4839 return StmtError();
4840 }
4841
4842 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4843 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4844 OMPOrderedClause *OC = nullptr;
4845 OMPScheduleClause *SC = nullptr;
4846 SmallVector<const OMPLinearClause *, 4> LCs;
4847 SmallVector<const OMPClauseWithPreInit *, 4> PICs;
4848 // This is required for proper codegen.
4849 for (OMPClause *Clause : Clauses) {
4850 if (!getLangOpts().OpenMPSimd &&
4851 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4852 DSAStack->getCurrentDirective() == OMPD_target) &&
4853 Clause->getClauseKind() == OMPC_in_reduction) {
4854 // Capture taskgroup task_reduction descriptors inside the tasking regions
4855 // with the corresponding in_reduction items.
4856 auto *IRC = cast<OMPInReductionClause>(Val: Clause);
4857 for (Expr *E : IRC->taskgroup_descriptors())
4858 if (E)
4859 SemaRef.MarkDeclarationsReferencedInExpr(E);
4860 }
4861 if (isOpenMPPrivate(Kind: Clause->getClauseKind()) ||
4862 Clause->getClauseKind() == OMPC_copyprivate ||
4863 (getLangOpts().OpenMPUseTLS &&
4864 getASTContext().getTargetInfo().isTLSSupported() &&
4865 Clause->getClauseKind() == OMPC_copyin)) {
4866 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4867 // Mark all variables in private list clauses as used in inner region.
4868 for (Stmt *VarRef : Clause->children()) {
4869 if (auto *E = cast_or_null<Expr>(Val: VarRef)) {
4870 SemaRef.MarkDeclarationsReferencedInExpr(E);
4871 }
4872 }
4873 DSAStack->setForceVarCapturing(/*V=*/false);
4874 } else if (CaptureRegions.size() > 1 ||
4875 CaptureRegions.back() != OMPD_unknown) {
4876 if (auto *C = OMPClauseWithPreInit::get(C: Clause))
4877 PICs.push_back(Elt: C);
4878 if (auto *C = OMPClauseWithPostUpdate::get(C: Clause)) {
4879 if (Expr *E = C->getPostUpdateExpr())
4880 SemaRef.MarkDeclarationsReferencedInExpr(E);
4881 }
4882 }
4883 if (Clause->getClauseKind() == OMPC_schedule)
4884 SC = cast<OMPScheduleClause>(Val: Clause);
4885 else if (Clause->getClauseKind() == OMPC_ordered)
4886 OC = cast<OMPOrderedClause>(Val: Clause);
4887 else if (Clause->getClauseKind() == OMPC_linear)
4888 LCs.push_back(Elt: cast<OMPLinearClause>(Val: Clause));
4889 }
4890 // Capture allocator expressions if used.
4891 for (Expr *E : DSAStack->getInnerAllocators())
4892 SemaRef.MarkDeclarationsReferencedInExpr(E);
4893 // OpenMP, 2.7.1 Loop Construct, Restrictions
4894 // The nonmonotonic modifier cannot be specified if an ordered clause is
4895 // specified.
4896 if (SC &&
4897 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4898 SC->getSecondScheduleModifier() ==
4899 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4900 OC) {
4901 Diag(Loc: SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4902 ? SC->getFirstScheduleModifierLoc()
4903 : SC->getSecondScheduleModifierLoc(),
4904 DiagID: diag::err_omp_simple_clause_incompatible_with_ordered)
4905 << getOpenMPClauseNameForDiag(C: OMPC_schedule)
4906 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule,
4907 Type: OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4908 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4909 ErrorFound = true;
4910 }
4911 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4912 // If an order(concurrent) clause is present, an ordered clause may not appear
4913 // on the same directive.
4914 if (checkOrderedOrderSpecified(S&: SemaRef, Clauses))
4915 ErrorFound = true;
4916 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4917 for (const OMPLinearClause *C : LCs) {
4918 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_linear_ordered)
4919 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4920 }
4921 ErrorFound = true;
4922 }
4923 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4924 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4925 OC->getNumForLoops()) {
4926 unsigned OMPVersion = getLangOpts().OpenMP;
4927 Diag(Loc: OC->getBeginLoc(), DiagID: diag::err_omp_ordered_simd)
4928 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), Ver: OMPVersion);
4929 ErrorFound = true;
4930 }
4931 if (ErrorFound) {
4932 return StmtError();
4933 }
4934 StmtResult SR = S;
4935 unsigned CompletedRegions = 0;
4936 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(C&: CaptureRegions)) {
4937 // Mark all variables in private list clauses as used in inner region.
4938 // Required for proper codegen of combined directives.
4939 // TODO: add processing for other clauses.
4940 if (ThisCaptureRegion != OMPD_unknown) {
4941 for (const clang::OMPClauseWithPreInit *C : PICs) {
4942 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4943 // Find the particular capture region for the clause if the
4944 // directive is a combined one with multiple capture regions.
4945 // If the directive is not a combined one, the capture region
4946 // associated with the clause is OMPD_unknown and is generated
4947 // only once.
4948 if (CaptureRegion == ThisCaptureRegion ||
4949 CaptureRegion == OMPD_unknown) {
4950 if (auto *DS = cast_or_null<DeclStmt>(Val: C->getPreInitStmt())) {
4951 for (Decl *D : DS->decls())
4952 SemaRef.MarkVariableReferenced(Loc: D->getLocation(),
4953 Var: cast<VarDecl>(Val: D));
4954 }
4955 }
4956 }
4957 }
4958 if (ThisCaptureRegion == OMPD_target) {
4959 // Capture allocator traits in the target region. They are used implicitly
4960 // and, thus, are not captured by default.
4961 for (OMPClause *C : Clauses) {
4962 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(Val: C)) {
4963 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4964 ++I) {
4965 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4966 if (Expr *E = D.AllocatorTraits)
4967 SemaRef.MarkDeclarationsReferencedInExpr(E);
4968 }
4969 continue;
4970 }
4971 }
4972 }
4973 if (ThisCaptureRegion == OMPD_parallel) {
4974 // Capture temp arrays for inscan reductions and locals in aligned
4975 // clauses.
4976 for (OMPClause *C : Clauses) {
4977 if (auto *RC = dyn_cast<OMPReductionClause>(Val: C)) {
4978 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4979 continue;
4980 for (Expr *E : RC->copy_array_temps())
4981 if (E)
4982 SemaRef.MarkDeclarationsReferencedInExpr(E);
4983 }
4984 if (auto *AC = dyn_cast<OMPAlignedClause>(Val: C)) {
4985 for (Expr *E : AC->varlist())
4986 SemaRef.MarkDeclarationsReferencedInExpr(E);
4987 }
4988 }
4989 }
4990 if (++CompletedRegions == CaptureRegions.size())
4991 DSAStack->setBodyComplete();
4992 SR = SemaRef.ActOnCapturedRegionEnd(S: SR.get());
4993 }
4994 return SR;
4995}
4996
4997static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4998 OpenMPDirectiveKind CancelRegion,
4999 SourceLocation StartLoc) {
5000 // CancelRegion is only needed for cancel and cancellation_point.
5001 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
5002 return false;
5003
5004 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
5005 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
5006 return false;
5007
5008 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
5009 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_wrong_cancel_region)
5010 << getOpenMPDirectiveName(D: CancelRegion, Ver: OMPVersion);
5011 return true;
5012}
5013
5014static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
5015 OpenMPDirectiveKind CurrentRegion,
5016 const DeclarationNameInfo &CurrentName,
5017 OpenMPDirectiveKind CancelRegion,
5018 OpenMPBindClauseKind BindKind,
5019 SourceLocation StartLoc) {
5020 if (!Stack->getCurScope())
5021 return false;
5022
5023 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
5024 OpenMPDirectiveKind OffendingRegion = ParentRegion;
5025 bool NestingProhibited = false;
5026 bool CloseNesting = true;
5027 bool OrphanSeen = false;
5028 enum {
5029 NoRecommend,
5030 ShouldBeInParallelRegion,
5031 ShouldBeInOrderedRegion,
5032 ShouldBeInTargetRegion,
5033 ShouldBeInTeamsRegion,
5034 ShouldBeInLoopSimdRegion,
5035 } Recommend = NoRecommend;
5036
5037 SmallVector<OpenMPDirectiveKind, 4> LeafOrComposite;
5038 ArrayRef<OpenMPDirectiveKind> ParentLOC =
5039 getLeafOrCompositeConstructs(D: ParentRegion, Output&: LeafOrComposite);
5040 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
5041 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
5042
5043 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
5044 !isOpenMPOrderConcurrentNestableDirective(DKind: CurrentRegion,
5045 LangOpts: SemaRef.LangOpts)) {
5046 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_order)
5047 << getOpenMPDirectiveName(D: CurrentRegion, Ver: OMPVersion);
5048 return true;
5049 }
5050 if (isOpenMPSimdDirective(DKind: ParentRegion) &&
5051 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered_blockassoc) ||
5052 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered_blockassoc &&
5053 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5054 CurrentRegion != OMPD_scan))) {
5055 // OpenMP [2.16, Nesting of Regions]
5056 // OpenMP constructs may not be nested inside a simd region.
5057 // OpenMP [2.8.1,simd Construct, Restrictions]
5058 // An ordered construct with the simd clause is the only OpenMP
5059 // construct that can appear in the simd region.
5060 // Allowing a SIMD construct nested in another SIMD construct is an
5061 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5062 // message.
5063 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5064 // The only OpenMP constructs that can be encountered during execution of
5065 // a simd region are the atomic construct, the loop construct, the simd
5066 // construct and the ordered construct with the simd clause.
5067 SemaRef.Diag(Loc: StartLoc, DiagID: (CurrentRegion != OMPD_simd)
5068 ? diag::err_omp_prohibited_region_simd
5069 : diag::warn_omp_nesting_simd)
5070 << (OMPVersion >= 50 ? 1 : 0);
5071 return CurrentRegion != OMPD_simd;
5072 }
5073 if (EnclosingConstruct == OMPD_atomic) {
5074 // OpenMP [2.16, Nesting of Regions]
5075 // OpenMP constructs may not be nested inside an atomic region.
5076 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_atomic);
5077 return true;
5078 }
5079 if (CurrentRegion == OMPD_section) {
5080 // OpenMP [2.7.2, sections Construct, Restrictions]
5081 // Orphaned section directives are prohibited. That is, the section
5082 // directives must appear within the sections construct and must not be
5083 // encountered elsewhere in the sections region.
5084 if (EnclosingConstruct != OMPD_sections) {
5085 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_section_directive)
5086 << (ParentRegion != OMPD_unknown)
5087 << getOpenMPDirectiveName(D: ParentRegion, Ver: OMPVersion);
5088 return true;
5089 }
5090 return false;
5091 }
5092 // Allow some constructs (except teams and cancellation constructs) to be
5093 // orphaned (they could be used in functions, called from OpenMP regions
5094 // with the required preconditions).
5095 if (ParentRegion == OMPD_unknown &&
5096 !isOpenMPNestingTeamsDirective(DKind: CurrentRegion) &&
5097 CurrentRegion != OMPD_cancellation_point &&
5098 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5099 return false;
5100 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5101 // for a detailed explanation
5102 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5103 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5104 (isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5105 EnclosingConstruct == OMPD_loop)) {
5106 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5107 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region)
5108 << true << getOpenMPDirectiveName(D: ParentRegion, Ver: OMPVersion)
5109 << ErrorMsgNumber << getOpenMPDirectiveName(D: CurrentRegion, Ver: OMPVersion);
5110 return true;
5111 }
5112 if (CurrentRegion == OMPD_cancellation_point ||
5113 CurrentRegion == OMPD_cancel) {
5114 // OpenMP [2.16, Nesting of Regions]
5115 // A cancellation point construct for which construct-type-clause is
5116 // taskgroup must be nested inside a task construct. A cancellation
5117 // point construct for which construct-type-clause is not taskgroup must
5118 // be closely nested inside an OpenMP construct that matches the type
5119 // specified in construct-type-clause.
5120 // A cancel construct for which construct-type-clause is taskgroup must be
5121 // nested inside a task construct. A cancel construct for which
5122 // construct-type-clause is not taskgroup must be closely nested inside an
5123 // OpenMP construct that matches the type specified in
5124 // construct-type-clause.
5125 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(D: ParentRegion);
5126 if (CancelRegion == OMPD_taskgroup) {
5127 NestingProhibited =
5128 EnclosingConstruct != OMPD_task &&
5129 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5130 } else if (CancelRegion == OMPD_sections) {
5131 NestingProhibited = EnclosingConstruct != OMPD_section &&
5132 EnclosingConstruct != OMPD_sections;
5133 } else {
5134 NestingProhibited = CancelRegion != Leafs.back();
5135 }
5136 OrphanSeen = ParentRegion == OMPD_unknown;
5137 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5138 // OpenMP 5.1 [2.22, Nesting of Regions]
5139 // A masked region may not be closely nested inside a worksharing, loop,
5140 // atomic, task, or taskloop region.
5141 NestingProhibited = isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5142 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
5143 isOpenMPTaskingDirective(Kind: ParentRegion);
5144 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5145 // OpenMP [2.16, Nesting of Regions]
5146 // A critical region may not be nested (closely or otherwise) inside a
5147 // critical region with the same name. Note that this restriction is not
5148 // sufficient to prevent deadlock.
5149 SourceLocation PreviousCriticalLoc;
5150 bool DeadLock = Stack->hasDirective(
5151 DPred: [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5152 const DeclarationNameInfo &DNI,
5153 SourceLocation Loc) {
5154 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5155 PreviousCriticalLoc = Loc;
5156 return true;
5157 }
5158 return false;
5159 },
5160 FromParent: false /* skip top directive */);
5161 if (DeadLock) {
5162 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_critical_same_name)
5163 << CurrentName.getName();
5164 if (PreviousCriticalLoc.isValid())
5165 SemaRef.Diag(Loc: PreviousCriticalLoc,
5166 DiagID: diag::note_omp_previous_critical_region);
5167 return true;
5168 }
5169 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5170 // OpenMP 5.1 [2.22, Nesting of Regions]
5171 // A scope region may not be closely nested inside a worksharing, loop,
5172 // task, taskloop, critical, ordered, atomic, or masked region.
5173 // OpenMP 5.1 [2.22, Nesting of Regions]
5174 // A barrier region may not be closely nested inside a worksharing, loop,
5175 // task, taskloop, critical, ordered, atomic, or masked region.
5176 NestingProhibited =
5177 isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5178 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
5179 isOpenMPTaskingDirective(Kind: ParentRegion) ||
5180 llvm::is_contained(
5181 Set: {OMPD_masked, OMPD_master, OMPD_critical, OMPD_ordered_blockassoc},
5182 Element: EnclosingConstruct);
5183 } else if (isOpenMPWorksharingDirective(DKind: CurrentRegion) &&
5184 !isOpenMPParallelDirective(DKind: CurrentRegion) &&
5185 !isOpenMPTeamsDirective(DKind: CurrentRegion)) {
5186 // OpenMP 5.1 [2.22, Nesting of Regions]
5187 // A loop region that binds to a parallel region or a worksharing region
5188 // may not be closely nested inside a worksharing, loop, task, taskloop,
5189 // critical, ordered, atomic, or masked region.
5190 NestingProhibited =
5191 isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5192 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
5193 isOpenMPTaskingDirective(Kind: ParentRegion) ||
5194 llvm::is_contained(
5195 Set: {OMPD_masked, OMPD_master, OMPD_critical, OMPD_ordered_blockassoc},
5196 Element: EnclosingConstruct);
5197 Recommend = ShouldBeInParallelRegion;
5198 } else if (CurrentRegion == OMPD_ordered_blockassoc ||
5199 CurrentRegion == OMPD_ordered_standalone) {
5200 // OpenMP [2.16, Nesting of Regions]
5201 // An ordered region may not be closely nested inside a critical,
5202 // atomic, or explicit task region.
5203 // An ordered region must be closely nested inside a loop region (or
5204 // parallel loop region) with an ordered clause.
5205 // OpenMP [2.8.1,simd Construct, Restrictions]
5206 // An ordered construct with the simd clause is the only OpenMP construct
5207 // that can appear in the simd region.
5208 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5209 isOpenMPTaskingDirective(Kind: ParentRegion) ||
5210 !(isOpenMPSimdDirective(DKind: ParentRegion) ||
5211 Stack->isParentOrderedRegion());
5212 Recommend = ShouldBeInOrderedRegion;
5213 } else if (isOpenMPNestingTeamsDirective(DKind: CurrentRegion)) {
5214 // OpenMP [2.16, Nesting of Regions]
5215 // If specified, a teams construct must be contained within a target
5216 // construct.
5217 NestingProhibited =
5218 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5219 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5220 EnclosingConstruct != OMPD_target);
5221 OrphanSeen = ParentRegion == OMPD_unknown;
5222 Recommend = ShouldBeInTargetRegion;
5223 } else if (CurrentRegion == OMPD_scan) {
5224 if (OMPVersion >= 50) {
5225 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
5226 // simd, or for simd. This has to take into account combined directives.
5227 // In 5.2 this seems to be implied by the fact that the specified
5228 // separated constructs are do, for, and simd.
5229 NestingProhibited = !llvm::is_contained(
5230 Set: {OMPD_for, OMPD_simd, OMPD_for_simd}, Element: EnclosingConstruct);
5231 } else {
5232 NestingProhibited = true;
5233 }
5234 OrphanSeen = ParentRegion == OMPD_unknown;
5235 Recommend = ShouldBeInLoopSimdRegion;
5236 }
5237 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(DKind: CurrentRegion) &&
5238 !isOpenMPTargetDataManagementDirective(DKind: CurrentRegion) &&
5239 EnclosingConstruct == OMPD_teams) {
5240 // OpenMP [5.1, 2.22, Nesting of Regions]
5241 // distribute, distribute simd, distribute parallel worksharing-loop,
5242 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5243 // including any parallel regions arising from combined constructs,
5244 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5245 // only OpenMP regions that may be strictly nested inside the teams
5246 // region.
5247 //
5248 // As an extension, we permit atomic within teams as well.
5249 NestingProhibited = !isOpenMPParallelDirective(DKind: CurrentRegion) &&
5250 !isOpenMPDistributeDirective(DKind: CurrentRegion) &&
5251 CurrentRegion != OMPD_loop &&
5252 !(SemaRef.getLangOpts().OpenMPExtensions &&
5253 CurrentRegion == OMPD_atomic);
5254 Recommend = ShouldBeInParallelRegion;
5255 }
5256 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5257 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5258 // If the bind clause is present on the loop construct and binding is
5259 // teams then the corresponding loop region must be strictly nested inside
5260 // a teams region.
5261 NestingProhibited =
5262 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5263 Recommend = ShouldBeInTeamsRegion;
5264 }
5265 if (!NestingProhibited && isOpenMPNestingDistributeDirective(DKind: CurrentRegion)) {
5266 // OpenMP 4.5 [2.17 Nesting of Regions]
5267 // The region associated with the distribute construct must be strictly
5268 // nested inside a teams region
5269 NestingProhibited = EnclosingConstruct != OMPD_teams;
5270 Recommend = ShouldBeInTeamsRegion;
5271 }
5272 if (!NestingProhibited &&
5273 (isOpenMPTargetExecutionDirective(DKind: CurrentRegion) ||
5274 isOpenMPTargetDataManagementDirective(DKind: CurrentRegion))) {
5275 // OpenMP 4.5 [2.17 Nesting of Regions]
5276 // If a target, target update, target data, target enter data, or
5277 // target exit data construct is encountered during execution of a
5278 // target region, the behavior is unspecified.
5279 NestingProhibited = Stack->hasDirective(
5280 DPred: [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5281 SourceLocation) {
5282 if (isOpenMPTargetExecutionDirective(DKind: K)) {
5283 OffendingRegion = K;
5284 return true;
5285 }
5286 return false;
5287 },
5288 FromParent: false /* don't skip top directive */);
5289 CloseNesting = false;
5290 }
5291 if (NestingProhibited) {
5292 if (OrphanSeen) {
5293 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_device_directive)
5294 << getOpenMPDirectiveName(D: CurrentRegion, Ver: OMPVersion) << Recommend;
5295 } else {
5296 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region)
5297 << CloseNesting << getOpenMPDirectiveName(D: OffendingRegion, Ver: OMPVersion)
5298 << Recommend << getOpenMPDirectiveName(D: CurrentRegion, Ver: OMPVersion);
5299 }
5300 return true;
5301 }
5302 return false;
5303}
5304
5305struct Kind2Unsigned {
5306 using argument_type = OpenMPDirectiveKind;
5307 unsigned operator()(argument_type DK) { return unsigned(DK); }
5308};
5309static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5310 ArrayRef<OMPClause *> Clauses,
5311 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5312 bool ErrorFound = false;
5313 unsigned NamedModifiersNumber = 0;
5314 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5315 FoundNameModifiers.resize(S: llvm::omp::Directive_enumSize + 1);
5316 SmallVector<SourceLocation, 4> NameModifierLoc;
5317 unsigned OMPVersion = S.getLangOpts().OpenMP;
5318 for (const OMPClause *C : Clauses) {
5319 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(Val: C)) {
5320 // At most one if clause without a directive-name-modifier can appear on
5321 // the directive.
5322 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5323 auto &FNM = FoundNameModifiers[CurNM];
5324 if (FNM) {
5325 S.Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_more_one_clause)
5326 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion)
5327 << getOpenMPClauseNameForDiag(C: OMPC_if) << (CurNM != OMPD_unknown)
5328 << getOpenMPDirectiveName(D: CurNM, Ver: OMPVersion);
5329 ErrorFound = true;
5330 } else if (CurNM != OMPD_unknown) {
5331 NameModifierLoc.push_back(Elt: IC->getNameModifierLoc());
5332 ++NamedModifiersNumber;
5333 }
5334 FNM = IC;
5335 if (CurNM == OMPD_unknown)
5336 continue;
5337 // Check if the specified name modifier is allowed for the current
5338 // directive.
5339 // At most one if clause with the particular directive-name-modifier can
5340 // appear on the directive.
5341 if (!llvm::is_contained(Range&: AllowedNameModifiers, Element: CurNM)) {
5342 S.Diag(Loc: IC->getNameModifierLoc(),
5343 DiagID: diag::err_omp_wrong_if_directive_name_modifier)
5344 << getOpenMPDirectiveName(D: CurNM, Ver: OMPVersion)
5345 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion);
5346 ErrorFound = true;
5347 }
5348 }
5349 }
5350 // If any if clause on the directive includes a directive-name-modifier then
5351 // all if clauses on the directive must include a directive-name-modifier.
5352 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5353 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5354 S.Diag(Loc: FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5355 DiagID: diag::err_omp_no_more_if_clause);
5356 } else {
5357 std::string Values;
5358 std::string Sep(", ");
5359 unsigned AllowedCnt = 0;
5360 unsigned TotalAllowedNum =
5361 AllowedNameModifiers.size() - NamedModifiersNumber;
5362 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5363 ++Cnt) {
5364 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5365 if (!FoundNameModifiers[NM]) {
5366 Values += "'";
5367 Values += getOpenMPDirectiveName(D: NM, Ver: OMPVersion);
5368 Values += "'";
5369 if (AllowedCnt + 2 == TotalAllowedNum)
5370 Values += " or ";
5371 else if (AllowedCnt + 1 != TotalAllowedNum)
5372 Values += Sep;
5373 ++AllowedCnt;
5374 }
5375 }
5376 S.Diag(Loc: FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5377 DiagID: diag::err_omp_unnamed_if_clause)
5378 << (TotalAllowedNum > 1) << Values;
5379 }
5380 for (SourceLocation Loc : NameModifierLoc) {
5381 S.Diag(Loc, DiagID: diag::note_omp_previous_named_if_clause);
5382 }
5383 ErrorFound = true;
5384 }
5385 return ErrorFound;
5386}
5387
5388static std::pair<ValueDecl *, bool>
5389getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
5390 SourceRange &ERange, bool AllowArraySection,
5391 bool AllowAssumedSizeArray, StringRef DiagType) {
5392 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5393 RefExpr->containsUnexpandedParameterPack())
5394 return std::make_pair(x: nullptr, y: true);
5395
5396 // OpenMP [3.1, C/C++]
5397 // A list item is a variable name.
5398 // OpenMP [2.9.3.3, Restrictions, p.1]
5399 // A variable that is part of another variable (as an array or
5400 // structure element) cannot appear in a private clause.
5401 //
5402 // OpenMP [6.0]
5403 // 5.2.5 Array Sections, p. 166, L28-29
5404 // When the length is absent and the size of the dimension is not known,
5405 // the array section is an assumed-size array.
5406 // 2 Glossary, p. 23, L4-6
5407 // assumed-size array
5408 // For C/C++, an array section for which the length is absent and the
5409 // size of the dimensions is not known.
5410 // 5.2.5 Array Sections, p. 168, L11
5411 // An assumed-size array can appear only in clauses for which it is
5412 // explicitly allowed.
5413 // 7.4 List Item Privatization, Restrictions, p. 222, L15
5414 // Assumed-size arrays must not be privatized.
5415 RefExpr = RefExpr->IgnoreParens();
5416 enum {
5417 NoArrayExpr = -1,
5418 ArraySubscript = 0,
5419 OMPArraySection = 1
5420 } IsArrayExpr = NoArrayExpr;
5421 if (AllowArraySection) {
5422 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(Val: RefExpr)) {
5423 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5424 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base))
5425 Base = TempASE->getBase()->IgnoreParenImpCasts();
5426 RefExpr = Base;
5427 IsArrayExpr = ArraySubscript;
5428 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(Val: RefExpr)) {
5429 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5430 if (S.getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5431 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5432 QualType BaseType = ArraySectionExpr::getBaseOriginalType(Base);
5433 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5434 !BaseType->isVariableArrayType())) {
5435 S.Diag(Loc: OASE->getColonLocFirst(),
5436 DiagID: diag::err_omp_section_length_undefined)
5437 << (!BaseType.isNull() && BaseType->isArrayType());
5438 return std::make_pair(x: nullptr, y: false);
5439 }
5440 }
5441 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Val: Base))
5442 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5443 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base))
5444 Base = TempASE->getBase()->IgnoreParenImpCasts();
5445 RefExpr = Base;
5446 IsArrayExpr = OMPArraySection;
5447 }
5448 }
5449 ELoc = RefExpr->getExprLoc();
5450 ERange = RefExpr->getSourceRange();
5451 RefExpr = RefExpr->IgnoreParenImpCasts();
5452 auto *DE = dyn_cast_or_null<DeclRefExpr>(Val: RefExpr);
5453 auto *ME = dyn_cast_or_null<MemberExpr>(Val: RefExpr);
5454 if ((!DE || !isa<VarDecl>(Val: DE->getDecl())) &&
5455 (S.getCurrentThisType().isNull() || !ME ||
5456 !isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()) ||
5457 !isa<FieldDecl>(Val: ME->getMemberDecl()))) {
5458 if (IsArrayExpr != NoArrayExpr) {
5459 S.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
5460 << IsArrayExpr << ERange;
5461 } else if (!DiagType.empty()) {
5462 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5463 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5464 : 0;
5465 S.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_var_name_member_expr_with_type)
5466 << DiagSelect << DiagType << ERange;
5467 } else {
5468 S.Diag(Loc: ELoc,
5469 DiagID: AllowArraySection
5470 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5471 : diag::err_omp_expected_var_name_member_expr)
5472 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5473 }
5474 return std::make_pair(x: nullptr, y: false);
5475 }
5476 return std::make_pair(
5477 x: getCanonicalDecl(D: DE ? DE->getDecl() : ME->getMemberDecl()), y: false);
5478}
5479
5480namespace {
5481/// Checks if the allocator is used in uses_allocators clause to be allowed in
5482/// target regions.
5483class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5484 DSAStackTy *S = nullptr;
5485
5486public:
5487 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5488 return S->isUsesAllocatorsDecl(D: E->getDecl())
5489 .value_or(u: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5490 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5491 }
5492 bool VisitStmt(const Stmt *S) {
5493 for (const Stmt *Child : S->children()) {
5494 if (Child && Visit(S: Child))
5495 return true;
5496 }
5497 return false;
5498 }
5499 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5500};
5501} // namespace
5502
5503static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5504 ArrayRef<OMPClause *> Clauses) {
5505 assert(!S.CurContext->isDependentContext() &&
5506 "Expected non-dependent context.");
5507 auto AllocateRange =
5508 llvm::make_filter_range(Range&: Clauses, Pred: OMPAllocateClause::classof);
5509 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5510 auto PrivateRange = llvm::make_filter_range(Range&: Clauses, Pred: [](const OMPClause *C) {
5511 return isOpenMPPrivate(Kind: C->getClauseKind());
5512 });
5513 for (OMPClause *Cl : PrivateRange) {
5514 MutableArrayRef<Expr *>::iterator I, It, Et;
5515 if (Cl->getClauseKind() == OMPC_private) {
5516 auto *PC = cast<OMPPrivateClause>(Val: Cl);
5517 I = PC->private_copies().begin();
5518 It = PC->varlist_begin();
5519 Et = PC->varlist_end();
5520 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5521 auto *PC = cast<OMPFirstprivateClause>(Val: Cl);
5522 I = PC->private_copies().begin();
5523 It = PC->varlist_begin();
5524 Et = PC->varlist_end();
5525 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5526 auto *PC = cast<OMPLastprivateClause>(Val: Cl);
5527 I = PC->private_copies().begin();
5528 It = PC->varlist_begin();
5529 Et = PC->varlist_end();
5530 } else if (Cl->getClauseKind() == OMPC_linear) {
5531 auto *PC = cast<OMPLinearClause>(Val: Cl);
5532 I = PC->privates().begin();
5533 It = PC->varlist_begin();
5534 Et = PC->varlist_end();
5535 } else if (Cl->getClauseKind() == OMPC_reduction) {
5536 auto *PC = cast<OMPReductionClause>(Val: Cl);
5537 I = PC->privates().begin();
5538 It = PC->varlist_begin();
5539 Et = PC->varlist_end();
5540 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5541 auto *PC = cast<OMPTaskReductionClause>(Val: Cl);
5542 I = PC->privates().begin();
5543 It = PC->varlist_begin();
5544 Et = PC->varlist_end();
5545 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5546 auto *PC = cast<OMPInReductionClause>(Val: Cl);
5547 I = PC->privates().begin();
5548 It = PC->varlist_begin();
5549 Et = PC->varlist_end();
5550 } else {
5551 llvm_unreachable("Expected private clause.");
5552 }
5553 for (Expr *E : llvm::make_range(x: It, y: Et)) {
5554 if (!*I) {
5555 ++I;
5556 continue;
5557 }
5558 SourceLocation ELoc;
5559 SourceRange ERange;
5560 Expr *SimpleRefExpr = E;
5561 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
5562 /*AllowArraySection=*/true);
5563 DeclToCopy.try_emplace(Key: Res.first,
5564 Args: cast<VarDecl>(Val: cast<DeclRefExpr>(Val: *I)->getDecl()));
5565 ++I;
5566 }
5567 }
5568 for (OMPClause *C : AllocateRange) {
5569 auto *AC = cast<OMPAllocateClause>(Val: C);
5570 if (S.getLangOpts().OpenMP >= 50 &&
5571 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5572 isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective()) &&
5573 AC->getAllocator()) {
5574 Expr *Allocator = AC->getAllocator();
5575 // OpenMP, 2.12.5 target Construct
5576 // Memory allocators that do not appear in a uses_allocators clause cannot
5577 // appear as an allocator in an allocate clause or be used in the target
5578 // region unless a requires directive with the dynamic_allocators clause
5579 // is present in the same compilation unit.
5580 AllocatorChecker Checker(Stack);
5581 if (Checker.Visit(S: Allocator))
5582 S.Diag(Loc: Allocator->getExprLoc(),
5583 DiagID: diag::err_omp_allocator_not_in_uses_allocators)
5584 << Allocator->getSourceRange();
5585 }
5586 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5587 getAllocatorKind(S, Stack, Allocator: AC->getAllocator());
5588 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5589 // For task, taskloop or target directives, allocation requests to memory
5590 // allocators with the trait access set to thread result in unspecified
5591 // behavior.
5592 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5593 (isOpenMPTaskingDirective(Kind: Stack->getCurrentDirective()) ||
5594 isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective()))) {
5595 unsigned OMPVersion = S.getLangOpts().OpenMP;
5596 S.Diag(Loc: AC->getAllocator()->getExprLoc(),
5597 DiagID: diag::warn_omp_allocate_thread_on_task_target_directive)
5598 << getOpenMPDirectiveName(D: Stack->getCurrentDirective(), Ver: OMPVersion);
5599 }
5600 for (Expr *E : AC->varlist()) {
5601 SourceLocation ELoc;
5602 SourceRange ERange;
5603 Expr *SimpleRefExpr = E;
5604 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange);
5605 ValueDecl *VD = Res.first;
5606 if (!VD)
5607 continue;
5608 DSAStackTy::DSAVarData Data = Stack->getTopDSA(D: VD, /*FromParent=*/false);
5609 if (!isOpenMPPrivate(Kind: Data.CKind)) {
5610 S.Diag(Loc: E->getExprLoc(),
5611 DiagID: diag::err_omp_expected_private_copy_for_allocate);
5612 continue;
5613 }
5614 VarDecl *PrivateVD = DeclToCopy[VD];
5615 if (checkPreviousOMPAllocateAttribute(S, Stack, RefExpr: E, VD: PrivateVD,
5616 AllocatorKind, Allocator: AC->getAllocator()))
5617 continue;
5618 applyOMPAllocateAttribute(S, VD: PrivateVD, AllocatorKind, Allocator: AC->getAllocator(),
5619 Alignment: AC->getAlignment(), SR: E->getSourceRange());
5620 }
5621 }
5622}
5623
5624namespace {
5625/// Rewrite statements and expressions for Sema \p Actions CurContext.
5626///
5627/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5628/// context. DeclRefExpr used inside the new context are changed to refer to the
5629/// captured variable instead.
5630class CaptureVars : public TreeTransform<CaptureVars> {
5631 using BaseTransform = TreeTransform<CaptureVars>;
5632
5633public:
5634 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5635
5636 bool AlwaysRebuild() { return true; }
5637};
5638} // namespace
5639
5640static VarDecl *precomputeExpr(Sema &Actions,
5641 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5642 StringRef Name) {
5643 Expr *NewE = AssertSuccess(R: CaptureVars(Actions).TransformExpr(E));
5644 VarDecl *NewVar = buildVarDecl(SemaRef&: Actions, Loc: {}, Type: NewE->getType(), Name, Attrs: nullptr,
5645 OrigRef: dyn_cast<DeclRefExpr>(Val: E->IgnoreImplicit()));
5646 auto *NewDeclStmt = cast<DeclStmt>(Val: AssertSuccess(
5647 R: Actions.ActOnDeclStmt(Decl: Actions.ConvertDeclToDeclGroup(Ptr: NewVar), StartLoc: {}, EndLoc: {})));
5648 Actions.AddInitializerToDecl(dcl: NewDeclStmt->getSingleDecl(), init: NewE, DirectInit: false);
5649 BodyStmts.push_back(Elt: NewDeclStmt);
5650 return NewVar;
5651}
5652
5653/// Create a closure that computes the number of iterations of a loop.
5654///
5655/// \param Actions The Sema object.
5656/// \param LogicalTy Type for the logical iteration number.
5657/// \param Rel Comparison operator of the loop condition.
5658/// \param StartExpr Value of the loop counter at the first iteration.
5659/// \param StopExpr Expression the loop counter is compared against in the loop
5660/// condition. \param StepExpr Amount of increment after each iteration.
5661///
5662/// \return Closure (CapturedStmt) of the distance calculation.
5663static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5664 BinaryOperator::Opcode Rel,
5665 Expr *StartExpr, Expr *StopExpr,
5666 Expr *StepExpr) {
5667 ASTContext &Ctx = Actions.getASTContext();
5668 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(T: LogicalTy);
5669
5670 // Captured regions currently don't support return values, we use an
5671 // out-parameter instead. All inputs are implicit captures.
5672 // TODO: Instead of capturing each DeclRefExpr occurring in
5673 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5674 QualType ResultTy = Ctx.getLValueReferenceType(T: LogicalTy);
5675 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5676 {StringRef(), QualType()}};
5677 Actions.ActOnCapturedRegionStart(Loc: {}, CurScope: nullptr, Kind: CR_Default, Params);
5678
5679 Stmt *Body;
5680 {
5681 Sema::CompoundScopeRAII CompoundScope(Actions);
5682 CapturedDecl *CS = cast<CapturedDecl>(Val: Actions.CurContext);
5683
5684 // Get the LValue expression for the result.
5685 ImplicitParamDecl *DistParam = CS->getParam(i: 0);
5686 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5687 D: DistParam, Ty: LogicalTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
5688
5689 SmallVector<Stmt *, 4> BodyStmts;
5690
5691 // Capture all referenced variable references.
5692 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5693 // CapturedStmt, we could compute them before and capture the result, to be
5694 // used jointly with the LoopVar function.
5695 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, E: StartExpr, Name: ".start");
5696 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, E: StopExpr, Name: ".stop");
5697 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, E: StepExpr, Name: ".step");
5698 auto BuildVarRef = [&](VarDecl *VD) {
5699 return buildDeclRefExpr(S&: Actions, D: VD, Ty: VD->getType(), Loc: {});
5700 };
5701
5702 IntegerLiteral *Zero = IntegerLiteral::Create(
5703 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 0), type: LogicalTy, l: {});
5704 IntegerLiteral *One = IntegerLiteral::Create(
5705 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 1), type: LogicalTy, l: {});
5706 Expr *Dist;
5707 if (Rel == BO_NE) {
5708 // When using a != comparison, the increment can be +1 or -1. This can be
5709 // dynamic at runtime, so we need to check for the direction.
5710 Expr *IsNegStep = AssertSuccess(
5711 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_LT, LHSExpr: BuildVarRef(NewStep), RHSExpr: Zero));
5712
5713 // Positive increment.
5714 Expr *ForwardRange = AssertSuccess(R: Actions.BuildBinOp(
5715 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStop), RHSExpr: BuildVarRef(NewStart)));
5716 ForwardRange = AssertSuccess(
5717 R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: ForwardRange));
5718 Expr *ForwardDist = AssertSuccess(R: Actions.BuildBinOp(
5719 S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: ForwardRange, RHSExpr: BuildVarRef(NewStep)));
5720
5721 // Negative increment.
5722 Expr *BackwardRange = AssertSuccess(R: Actions.BuildBinOp(
5723 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5724 BackwardRange = AssertSuccess(
5725 R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: BackwardRange));
5726 Expr *NegIncAmount = AssertSuccess(
5727 R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: BuildVarRef(NewStep)));
5728 Expr *BackwardDist = AssertSuccess(
5729 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: BackwardRange, RHSExpr: NegIncAmount));
5730
5731 // Use the appropriate case.
5732 Dist = AssertSuccess(R: Actions.ActOnConditionalOp(
5733 QuestionLoc: {}, ColonLoc: {}, CondExpr: IsNegStep, LHSExpr: BackwardDist, RHSExpr: ForwardDist));
5734 } else {
5735 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5736 "Expected one of these relational operators");
5737
5738 // We can derive the direction from any other comparison operator. It is
5739 // non well-formed OpenMP if Step increments/decrements in the other
5740 // directions. Whether at least the first iteration passes the loop
5741 // condition.
5742 Expr *HasAnyIteration = AssertSuccess(R: Actions.BuildBinOp(
5743 S: nullptr, OpLoc: {}, Opc: Rel, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5744
5745 // Compute the range between first and last counter value.
5746 Expr *Range;
5747 if (Rel == BO_GE || Rel == BO_GT)
5748 Range = AssertSuccess(R: Actions.BuildBinOp(
5749 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5750 else
5751 Range = AssertSuccess(R: Actions.BuildBinOp(
5752 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStop), RHSExpr: BuildVarRef(NewStart)));
5753
5754 // Ensure unsigned range space.
5755 Range =
5756 AssertSuccess(R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: Range));
5757
5758 if (Rel == BO_LE || Rel == BO_GE) {
5759 // Add one to the range if the relational operator is inclusive.
5760 Range =
5761 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: Range, RHSExpr: One));
5762 }
5763
5764 // Divide by the absolute step amount. If the range is not a multiple of
5765 // the step size, rounding-up the effective upper bound ensures that the
5766 // last iteration is included.
5767 // Note that the rounding-up may cause an overflow in a temporary that
5768 // could be avoided, but would have occurred in a C-style for-loop as
5769 // well.
5770 Expr *Divisor = BuildVarRef(NewStep);
5771 if (Rel == BO_GE || Rel == BO_GT)
5772 Divisor =
5773 AssertSuccess(R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: Divisor));
5774 Expr *DivisorMinusOne =
5775 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: Divisor, RHSExpr: One));
5776 Expr *RangeRoundUp = AssertSuccess(
5777 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: Range, RHSExpr: DivisorMinusOne));
5778 Dist = AssertSuccess(
5779 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: RangeRoundUp, RHSExpr: Divisor));
5780
5781 // If there is not at least one iteration, the range contains garbage. Fix
5782 // to zero in this case.
5783 Dist = AssertSuccess(
5784 R: Actions.ActOnConditionalOp(QuestionLoc: {}, ColonLoc: {}, CondExpr: HasAnyIteration, LHSExpr: Dist, RHSExpr: Zero));
5785 }
5786
5787 // Assign the result to the out-parameter.
5788 Stmt *ResultAssign = AssertSuccess(R: Actions.BuildBinOp(
5789 S: Actions.getCurScope(), OpLoc: {}, Opc: BO_Assign, LHSExpr: DistRef, RHSExpr: Dist));
5790 BodyStmts.push_back(Elt: ResultAssign);
5791
5792 Body = AssertSuccess(R: Actions.ActOnCompoundStmt(L: {}, R: {}, Elts: BodyStmts, isStmtExpr: false));
5793 }
5794
5795 return cast<CapturedStmt>(
5796 Val: AssertSuccess(R: Actions.ActOnCapturedRegionEnd(S: Body)));
5797}
5798
5799/// Create a closure that computes the loop variable from the logical iteration
5800/// number.
5801///
5802/// \param Actions The Sema object.
5803/// \param LoopVarTy Type for the loop variable used for result value.
5804/// \param LogicalTy Type for the logical iteration number.
5805/// \param StartExpr Value of the loop counter at the first iteration.
5806/// \param Step Amount of increment after each iteration.
5807/// \param Deref Whether the loop variable is a dereference of the loop
5808/// counter variable.
5809///
5810/// \return Closure (CapturedStmt) of the loop value calculation.
5811static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5812 QualType LogicalTy,
5813 DeclRefExpr *StartExpr, Expr *Step,
5814 bool Deref) {
5815 ASTContext &Ctx = Actions.getASTContext();
5816
5817 // Pass the result as an out-parameter. Passing as return value would require
5818 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5819 // invoke a copy constructor.
5820 QualType TargetParamTy = Ctx.getLValueReferenceType(T: LoopVarTy);
5821 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5822 {"Logical", LogicalTy},
5823 {StringRef(), QualType()}};
5824 Actions.ActOnCapturedRegionStart(Loc: {}, CurScope: nullptr, Kind: CR_Default, Params);
5825
5826 // Capture the initial iterator which represents the LoopVar value at the
5827 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5828 // it in every iteration, capture it by value before it is modified.
5829 VarDecl *StartVar = cast<VarDecl>(Val: StartExpr->getDecl());
5830 bool Invalid = Actions.tryCaptureVariable(Var: StartVar, Loc: {},
5831 Kind: TryCaptureKind::ExplicitByVal, EllipsisLoc: {});
5832 (void)Invalid;
5833 assert(!Invalid && "Expecting capture-by-value to work.");
5834
5835 Expr *Body;
5836 {
5837 Sema::CompoundScopeRAII CompoundScope(Actions);
5838 auto *CS = cast<CapturedDecl>(Val: Actions.CurContext);
5839
5840 ImplicitParamDecl *TargetParam = CS->getParam(i: 0);
5841 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5842 D: TargetParam, Ty: LoopVarTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
5843 ImplicitParamDecl *IndvarParam = CS->getParam(i: 1);
5844 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5845 D: IndvarParam, Ty: LogicalTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
5846
5847 // Capture the Start expression.
5848 CaptureVars Recap(Actions);
5849 Expr *NewStart = AssertSuccess(R: Recap.TransformExpr(E: StartExpr));
5850 Expr *NewStep = AssertSuccess(R: Recap.TransformExpr(E: Step));
5851
5852 Expr *Skip = AssertSuccess(
5853 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Mul, LHSExpr: NewStep, RHSExpr: LogicalRef));
5854 // TODO: Explicitly cast to the iterator's difference_type instead of
5855 // relying on implicit conversion.
5856 Expr *Advanced =
5857 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: NewStart, RHSExpr: Skip));
5858
5859 if (Deref) {
5860 // For range-based for-loops convert the loop counter value to a concrete
5861 // loop variable value by dereferencing the iterator.
5862 Advanced =
5863 AssertSuccess(R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Deref, Input: Advanced));
5864 }
5865
5866 // Assign the result to the output parameter.
5867 Body = AssertSuccess(R: Actions.BuildBinOp(S: Actions.getCurScope(), OpLoc: {},
5868 Opc: BO_Assign, LHSExpr: TargetRef, RHSExpr: Advanced));
5869 }
5870 return cast<CapturedStmt>(
5871 Val: AssertSuccess(R: Actions.ActOnCapturedRegionEnd(S: Body)));
5872}
5873
5874StmtResult SemaOpenMP::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
5875 ASTContext &Ctx = getASTContext();
5876
5877 // Extract the common elements of ForStmt and CXXForRangeStmt:
5878 // Loop variable, repeat condition, increment
5879 Expr *Cond, *Inc;
5880 VarDecl *LIVDecl, *LUVDecl;
5881 if (auto *For = dyn_cast<ForStmt>(Val: AStmt)) {
5882 Stmt *Init = For->getInit();
5883 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Val: Init)) {
5884 // For statement declares loop variable.
5885 LIVDecl = cast<VarDecl>(Val: LCVarDeclStmt->getSingleDecl());
5886 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Val: Init)) {
5887 // For statement reuses variable.
5888 assert(LCAssign->getOpcode() == BO_Assign &&
5889 "init part must be a loop variable assignment");
5890 auto *CounterRef = cast<DeclRefExpr>(Val: LCAssign->getLHS());
5891 LIVDecl = cast<VarDecl>(Val: CounterRef->getDecl());
5892 } else
5893 llvm_unreachable("Cannot determine loop variable");
5894 LUVDecl = LIVDecl;
5895
5896 Cond = For->getCond();
5897 Inc = For->getInc();
5898 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(Val: AStmt)) {
5899 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5900 LIVDecl = cast<VarDecl>(Val: BeginStmt->getSingleDecl());
5901 LUVDecl = RangeFor->getLoopVariable();
5902
5903 Cond = RangeFor->getCond();
5904 Inc = RangeFor->getInc();
5905 } else
5906 llvm_unreachable("unhandled kind of loop");
5907
5908 QualType CounterTy = LIVDecl->getType();
5909 QualType LVTy = LUVDecl->getType();
5910
5911 // Analyze the loop condition.
5912 Expr *LHS, *RHS;
5913 BinaryOperator::Opcode CondRel;
5914 Cond = Cond->IgnoreImplicit();
5915 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Val: Cond)) {
5916 LHS = CondBinExpr->getLHS();
5917 RHS = CondBinExpr->getRHS();
5918 CondRel = CondBinExpr->getOpcode();
5919 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Val: Cond)) {
5920 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5921 LHS = CondCXXOp->getArg(Arg: 0);
5922 RHS = CondCXXOp->getArg(Arg: 1);
5923 switch (CondCXXOp->getOperator()) {
5924 case OO_ExclaimEqual:
5925 CondRel = BO_NE;
5926 break;
5927 case OO_Less:
5928 CondRel = BO_LT;
5929 break;
5930 case OO_LessEqual:
5931 CondRel = BO_LE;
5932 break;
5933 case OO_Greater:
5934 CondRel = BO_GT;
5935 break;
5936 case OO_GreaterEqual:
5937 CondRel = BO_GE;
5938 break;
5939 default:
5940 llvm_unreachable("unexpected iterator operator");
5941 }
5942 } else
5943 llvm_unreachable("unexpected loop condition");
5944
5945 // Normalize such that the loop counter is on the LHS.
5946 if (!isa<DeclRefExpr>(Val: LHS->IgnoreImplicit()) ||
5947 cast<DeclRefExpr>(Val: LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5948 std::swap(a&: LHS, b&: RHS);
5949 CondRel = BinaryOperator::reverseComparisonOp(Opc: CondRel);
5950 }
5951 auto *CounterRef = cast<DeclRefExpr>(Val: LHS->IgnoreImplicit());
5952
5953 // Decide the bit width for the logical iteration counter. By default use the
5954 // unsigned ptrdiff_t integer size (for iterators and pointers).
5955 // TODO: For iterators, use iterator::difference_type,
5956 // std::iterator_traits<>::difference_type or decltype(it - end).
5957 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5958 if (CounterTy->isIntegerType()) {
5959 unsigned BitWidth = Ctx.getIntWidth(T: CounterTy);
5960 LogicalTy = Ctx.getIntTypeForBitwidth(DestWidth: BitWidth, Signed: false);
5961 }
5962
5963 // Analyze the loop increment.
5964 Expr *Step;
5965 if (auto *IncUn = dyn_cast<UnaryOperator>(Val: Inc)) {
5966 int Direction;
5967 switch (IncUn->getOpcode()) {
5968 case UO_PreInc:
5969 case UO_PostInc:
5970 Direction = 1;
5971 break;
5972 case UO_PreDec:
5973 case UO_PostDec:
5974 Direction = -1;
5975 break;
5976 default:
5977 llvm_unreachable("unhandled unary increment operator");
5978 }
5979 Step = IntegerLiteral::Create(
5980 C: Ctx,
5981 V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), Direction, /*isSigned=*/true),
5982 type: LogicalTy, l: {});
5983 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Val: Inc)) {
5984 if (IncBin->getOpcode() == BO_AddAssign) {
5985 Step = IncBin->getRHS();
5986 } else if (IncBin->getOpcode() == BO_SubAssign) {
5987 Step = AssertSuccess(
5988 R: SemaRef.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: IncBin->getRHS()));
5989 } else
5990 llvm_unreachable("unhandled binary increment operator");
5991 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Val: Inc)) {
5992 switch (CondCXXOp->getOperator()) {
5993 case OO_PlusPlus:
5994 Step = IntegerLiteral::Create(
5995 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 1), type: LogicalTy, l: {});
5996 break;
5997 case OO_MinusMinus:
5998 Step = IntegerLiteral::Create(
5999 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), -1), type: LogicalTy, l: {});
6000 break;
6001 case OO_PlusEqual:
6002 Step = CondCXXOp->getArg(Arg: 1);
6003 break;
6004 case OO_MinusEqual:
6005 Step = AssertSuccess(
6006 R: SemaRef.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: CondCXXOp->getArg(Arg: 1)));
6007 break;
6008 default:
6009 llvm_unreachable("unhandled overloaded increment operator");
6010 }
6011 } else
6012 llvm_unreachable("unknown increment expression");
6013
6014 CapturedStmt *DistanceFunc =
6015 buildDistanceFunc(Actions&: SemaRef, LogicalTy, Rel: CondRel, StartExpr: LHS, StopExpr: RHS, StepExpr: Step);
6016 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
6017 Actions&: SemaRef, LoopVarTy: LVTy, LogicalTy, StartExpr: CounterRef, Step, Deref: isa<CXXForRangeStmt>(Val: AStmt));
6018 DeclRefExpr *LVRef =
6019 SemaRef.BuildDeclRefExpr(D: LUVDecl, Ty: LUVDecl->getType(), VK: VK_LValue, NameInfo: {},
6020 SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
6021 return OMPCanonicalLoop::create(Ctx: getASTContext(), LoopStmt: AStmt, DistanceFunc,
6022 LoopVarFunc, LoopVarRef: LVRef);
6023}
6024
6025StmtResult SemaOpenMP::ActOnOpenMPLoopnest(Stmt *AStmt) {
6026 // Handle a literal loop.
6027 if (isa<ForStmt>(Val: AStmt) || isa<CXXForRangeStmt>(Val: AStmt))
6028 return ActOnOpenMPCanonicalLoop(AStmt);
6029
6030 // If not a literal loop, it must be the result of a loop transformation.
6031 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(Val: AStmt);
6032 assert(
6033 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
6034 "Loop transformation directive expected");
6035 return LoopTransform;
6036}
6037
6038static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
6039 CXXScopeSpec &MapperIdScopeSpec,
6040 const DeclarationNameInfo &MapperId,
6041 QualType Type,
6042 Expr *UnresolvedMapper);
6043
6044/// Perform DFS through the structure/class data members trying to find
6045/// member(s) with user-defined 'default' mapper and generate implicit map
6046/// clauses for such members with the found 'default' mapper.
6047static void
6048processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
6049 SmallVectorImpl<OMPClause *> &Clauses) {
6050 // Check for the default mapper for data members.
6051 if (S.getLangOpts().OpenMP < 50)
6052 return;
6053 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6054 auto *C = dyn_cast<OMPMapClause>(Val: Clauses[Cnt]);
6055 if (!C)
6056 continue;
6057 SmallVector<Expr *, 4> SubExprs;
6058 auto *MI = C->mapperlist_begin();
6059 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
6060 ++I, ++MI) {
6061 // Expression is mapped using mapper - skip it.
6062 if (*MI)
6063 continue;
6064 Expr *E = *I;
6065 // Expression is dependent - skip it, build the mapper when it gets
6066 // instantiated.
6067 if (E->isTypeDependent() || E->isValueDependent() ||
6068 E->containsUnexpandedParameterPack())
6069 continue;
6070 // Array section - need to check for the mapping of the array section
6071 // element.
6072 QualType CanonType = E->getType().getCanonicalType();
6073 if (CanonType->isSpecificBuiltinType(K: BuiltinType::ArraySection)) {
6074 const auto *OASE = cast<ArraySectionExpr>(Val: E->IgnoreParenImpCasts());
6075 QualType BaseType =
6076 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
6077 QualType ElemType;
6078 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6079 ElemType = ATy->getElementType();
6080 else
6081 ElemType = BaseType->getPointeeType();
6082 CanonType = ElemType;
6083 }
6084
6085 // DFS over data members in structures/classes.
6086 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
6087 1, {CanonType, nullptr});
6088 llvm::DenseMap<const Type *, Expr *> Visited;
6089 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
6090 1, {nullptr, 1});
6091 while (!Types.empty()) {
6092 QualType BaseType;
6093 FieldDecl *CurFD;
6094 std::tie(args&: BaseType, args&: CurFD) = Types.pop_back_val();
6095 while (ParentChain.back().second == 0)
6096 ParentChain.pop_back();
6097 --ParentChain.back().second;
6098 if (BaseType.isNull())
6099 continue;
6100 // Only structs/classes are allowed to have mappers.
6101 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6102 if (!RD)
6103 continue;
6104 auto It = Visited.find(Val: BaseType.getTypePtr());
6105 if (It == Visited.end()) {
6106 // Try to find the associated user-defined mapper.
6107 CXXScopeSpec MapperIdScopeSpec;
6108 DeclarationNameInfo DefaultMapperId;
6109 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
6110 ID: &S.Context.Idents.get(Name: "default")));
6111 DefaultMapperId.setLoc(E->getExprLoc());
6112 ExprResult ER = buildUserDefinedMapperRef(
6113 SemaRef&: S, S: Stack->getCurScope(), MapperIdScopeSpec, MapperId: DefaultMapperId,
6114 Type: BaseType, /*UnresolvedMapper=*/nullptr);
6115 if (ER.isInvalid())
6116 continue;
6117 It = Visited.try_emplace(Key: BaseType.getTypePtr(), Args: ER.get()).first;
6118 }
6119 // Found default mapper.
6120 if (It->second) {
6121 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6122 VK_LValue, OK_Ordinary, E);
6123 OE->setIsUnique(/*V=*/true);
6124 Expr *BaseExpr = OE;
6125 for (const auto &P : ParentChain) {
6126 if (P.first) {
6127 BaseExpr = S.BuildMemberExpr(
6128 Base: BaseExpr, /*IsArrow=*/false, OpLoc: E->getExprLoc(),
6129 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: P.first,
6130 FoundDecl: DeclAccessPair::make(D: P.first, AS: P.first->getAccess()),
6131 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(),
6132 Ty: P.first->getType(), VK: VK_LValue, OK: OK_Ordinary);
6133 BaseExpr = S.DefaultLvalueConversion(E: BaseExpr).get();
6134 }
6135 }
6136 if (CurFD)
6137 BaseExpr = S.BuildMemberExpr(
6138 Base: BaseExpr, /*IsArrow=*/false, OpLoc: E->getExprLoc(),
6139 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: CurFD,
6140 FoundDecl: DeclAccessPair::make(D: CurFD, AS: CurFD->getAccess()),
6141 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(),
6142 Ty: CurFD->getType(), VK: VK_LValue, OK: OK_Ordinary);
6143 SubExprs.push_back(Elt: BaseExpr);
6144 continue;
6145 }
6146 // Check for the "default" mapper for data members.
6147 bool FirstIter = true;
6148 for (FieldDecl *FD : RD->fields()) {
6149 if (!FD)
6150 continue;
6151 QualType FieldTy = FD->getType();
6152 if (FieldTy.isNull() ||
6153 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6154 continue;
6155 if (FirstIter) {
6156 FirstIter = false;
6157 ParentChain.emplace_back(Args&: CurFD, Args: 1);
6158 } else {
6159 ++ParentChain.back().second;
6160 }
6161 Types.emplace_back(Args&: FieldTy, Args&: FD);
6162 }
6163 }
6164 }
6165 if (SubExprs.empty())
6166 continue;
6167 CXXScopeSpec MapperIdScopeSpec;
6168 DeclarationNameInfo MapperId;
6169 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
6170 IteratorModifier: nullptr, MapTypeModifiers: C->getMapTypeModifiers(), MapTypeModifiersLoc: C->getMapTypeModifiersLoc(),
6171 MapperIdScopeSpec, MapperId, MapType: C->getMapType(),
6172 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(),
6173 VarList: SubExprs, Locs: OMPVarListLocTy()))
6174 Clauses.push_back(Elt: NewClause);
6175 }
6176}
6177
6178namespace {
6179/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
6180/// call in the associated loop-nest cannot be a 'parallel for'.
6181class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
6182 Sema &SemaRef;
6183
6184public:
6185 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
6186
6187 // Is there a nested OpenMP loop bind(parallel)
6188 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
6189 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6190 if (const auto *C = D->getSingleClause<OMPBindClause>())
6191 if (C->getBindKind() == OMPC_BIND_parallel) {
6192 TeamsLoopCanBeParallelFor = false;
6193 // No need to continue visiting any more
6194 return;
6195 }
6196 }
6197 for (const Stmt *Child : D->children())
6198 if (Child)
6199 Visit(S: Child);
6200 }
6201
6202 void VisitCallExpr(const CallExpr *C) {
6203 // Function calls inhibit parallel loop translation of 'target teams loop'
6204 // unless the assume-no-nested-parallelism flag has been specified.
6205 // OpenMP API runtime library calls do not inhibit parallel loop
6206 // translation, regardless of the assume-no-nested-parallelism.
6207 bool IsOpenMPAPI = false;
6208 auto *FD = dyn_cast_or_null<FunctionDecl>(Val: C->getCalleeDecl());
6209 if (FD) {
6210 std::string Name = FD->getNameInfo().getAsString();
6211 IsOpenMPAPI = Name.find(s: "omp_") == 0;
6212 }
6213 TeamsLoopCanBeParallelFor =
6214 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6215 if (!TeamsLoopCanBeParallelFor)
6216 return;
6217
6218 for (const Stmt *Child : C->children())
6219 if (Child)
6220 Visit(S: Child);
6221 }
6222
6223 void VisitCapturedStmt(const CapturedStmt *S) {
6224 if (!S)
6225 return;
6226 Visit(S: S->getCapturedDecl()->getBody());
6227 }
6228
6229 void VisitStmt(const Stmt *S) {
6230 if (!S)
6231 return;
6232 for (const Stmt *Child : S->children())
6233 if (Child)
6234 Visit(S: Child);
6235 }
6236 explicit TeamsLoopChecker(Sema &SemaRef)
6237 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
6238
6239private:
6240 bool TeamsLoopCanBeParallelFor;
6241};
6242} // namespace
6243
6244static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
6245 TeamsLoopChecker Checker(SemaRef);
6246 Checker.Visit(S: AStmt);
6247 return Checker.teamsLoopCanBeParallelFor();
6248}
6249
6250StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective(
6251 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6252 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6253 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6254 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
6255
6256 StmtResult Res = StmtError();
6257 OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
6258 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6259
6260 if (const OMPBindClause *BC =
6261 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6262 BindKind = BC->getBindKind();
6263
6264 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6265 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6266
6267 // Setting the enclosing teams or parallel construct for the loop
6268 // directive without bind clause.
6269 // [5.0:129:25-28] If the bind clause is not present on the construct and
6270 // the loop construct is closely nested inside a teams or parallel
6271 // construct, the binding region is the corresponding teams or parallel
6272 // region. If none of those conditions hold, the binding region is not
6273 // defined.
6274 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6275 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6276 getLeafConstructsOrSelf(D: ParentDirective);
6277
6278 if (ParentDirective == OMPD_unknown) {
6279 Diag(DSAStack->getDefaultDSALocation(),
6280 DiagID: diag::err_omp_bind_required_on_loop);
6281 } else if (ParentLeafs.back() == OMPD_parallel) {
6282 BindKind = OMPC_BIND_parallel;
6283 } else if (ParentLeafs.back() == OMPD_teams) {
6284 BindKind = OMPC_BIND_teams;
6285 }
6286
6287 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6288
6289 OMPClause *C =
6290 ActOnOpenMPBindClause(Kind: BindKind, KindLoc: SourceLocation(), StartLoc: SourceLocation(),
6291 LParenLoc: SourceLocation(), EndLoc: SourceLocation());
6292 ClausesWithImplicit.push_back(Elt: C);
6293 }
6294
6295 // Diagnose "loop bind(teams)" with "reduction".
6296 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6297 for (OMPClause *C : Clauses) {
6298 if (C->getClauseKind() == OMPC_reduction)
6299 Diag(DSAStack->getDefaultDSALocation(),
6300 DiagID: diag::err_omp_loop_reduction_clause);
6301 }
6302 }
6303
6304 // First check CancelRegion which is then used in checkNestingOfRegions.
6305 if (checkCancelRegion(SemaRef, CurrentRegion: Kind, CancelRegion, StartLoc) ||
6306 checkNestingOfRegions(SemaRef, DSAStack, CurrentRegion: Kind, CurrentName: DirName, CancelRegion,
6307 BindKind, StartLoc)) {
6308 return StmtError();
6309 }
6310
6311 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6312 if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(DKind: Kind) ||
6313 isOpenMPTargetDataManagementDirective(DKind: Kind)))
6314 Diag(Loc: StartLoc, DiagID: diag::warn_hip_omp_target_directives);
6315
6316 VarsWithInheritedDSAType VarsWithInheritedDSA;
6317 bool ErrorFound = false;
6318 ClausesWithImplicit.append(in_start: Clauses.begin(), in_end: Clauses.end());
6319
6320 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6321 isOpenMPCapturingDirective(DKind: Kind)) {
6322 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6323
6324 // Check default data sharing attributes for referenced variables.
6325 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(Val: AStmt));
6326 int ThisCaptureLevel = getOpenMPCaptureLevels(DKind: Kind);
6327 Stmt *S = AStmt;
6328 while (--ThisCaptureLevel >= 0)
6329 S = cast<CapturedStmt>(Val: S)->getCapturedStmt();
6330 DSAChecker.Visit(S);
6331 if (!isOpenMPTargetDataManagementDirective(DKind: Kind) &&
6332 !isOpenMPTaskingDirective(Kind)) {
6333 // Visit subcaptures to generate implicit clauses for captured vars.
6334 auto *CS = cast<CapturedStmt>(Val: AStmt);
6335 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
6336 getOpenMPCaptureRegions(CaptureRegions, DKind: Kind);
6337 // Ignore outer tasking regions for target directives.
6338 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6339 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
6340 DSAChecker.visitSubCaptures(S: CS);
6341 }
6342 if (DSAChecker.isErrorFound())
6343 return StmtError();
6344 // Generate list of implicitly defined firstprivate variables.
6345 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6346 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6347
6348 SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
6349 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6350 // Get the original location of present modifier from Defaultmap clause.
6351 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6352 for (OMPClause *C : Clauses) {
6353 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(Val: C))
6354 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6355 PresentModifierLocs[DMC->getDefaultmapKind()] =
6356 DMC->getDefaultmapModifierLoc();
6357 }
6358
6359 for (OpenMPDefaultmapClauseKind K :
6360 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6361 Begin: OpenMPDefaultmapClauseKind(), End: OMPC_DEFAULTMAP_unknown)) {
6362 std::fill_n(first: std::back_inserter(x&: ImplicitMapModifiersLoc[K]),
6363 n: ImpInfo.MapModifiers[K].size(), value: PresentModifierLocs[K]);
6364 }
6365 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6366 for (OMPClause *C : Clauses) {
6367 if (auto *IRC = dyn_cast<OMPInReductionClause>(Val: C)) {
6368 for (Expr *E : IRC->taskgroup_descriptors())
6369 if (E)
6370 ImpInfo.Firstprivates.insert(X: E);
6371 }
6372 // OpenMP 5.0, 2.10.1 task Construct
6373 // [detach clause]... The event-handle will be considered as if it was
6374 // specified on a firstprivate clause.
6375 if (auto *DC = dyn_cast<OMPDetachClause>(Val: C))
6376 ImpInfo.Firstprivates.insert(X: DC->getEventHandler());
6377 }
6378 if (!ImpInfo.Firstprivates.empty()) {
6379 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6380 VarList: ImpInfo.Firstprivates.getArrayRef(), StartLoc: SourceLocation(),
6381 LParenLoc: SourceLocation(), EndLoc: SourceLocation())) {
6382 ClausesWithImplicit.push_back(Elt: Implicit);
6383 ErrorFound = cast<OMPFirstprivateClause>(Val: Implicit)->varlist_size() !=
6384 ImpInfo.Firstprivates.size();
6385 } else {
6386 ErrorFound = true;
6387 }
6388 }
6389 if (!ImpInfo.Privates.empty()) {
6390 if (OMPClause *Implicit = ActOnOpenMPPrivateClause(
6391 VarList: ImpInfo.Privates.getArrayRef(), StartLoc: SourceLocation(),
6392 LParenLoc: SourceLocation(), EndLoc: SourceLocation())) {
6393 ClausesWithImplicit.push_back(Elt: Implicit);
6394 ErrorFound = cast<OMPPrivateClause>(Val: Implicit)->varlist_size() !=
6395 ImpInfo.Privates.size();
6396 } else {
6397 ErrorFound = true;
6398 }
6399 }
6400 // OpenMP 5.0 [2.19.7]
6401 // If a list item appears in a reduction, lastprivate or linear
6402 // clause on a combined target construct then it is treated as
6403 // if it also appears in a map clause with a map-type of tofrom
6404 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6405 isOpenMPTargetExecutionDirective(DKind: Kind)) {
6406 SmallVector<Expr *, 4> ImplicitExprs;
6407 for (OMPClause *C : Clauses) {
6408 if (auto *RC = dyn_cast<OMPReductionClause>(Val: C))
6409 for (Expr *E : RC->varlist())
6410 if (!isa<DeclRefExpr>(Val: E->IgnoreParenImpCasts()))
6411 ImplicitExprs.emplace_back(Args&: E);
6412 }
6413 if (!ImplicitExprs.empty()) {
6414 ArrayRef<Expr *> Exprs = ImplicitExprs;
6415 CXXScopeSpec MapperIdScopeSpec;
6416 DeclarationNameInfo MapperId;
6417 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6418 IteratorModifier: nullptr, MapTypeModifiers: OMPC_MAP_MODIFIER_unknown, MapTypeModifiersLoc: SourceLocation(),
6419 MapperIdScopeSpec, MapperId, MapType: OMPC_MAP_tofrom,
6420 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(),
6421 VarList: Exprs, Locs: OMPVarListLocTy(), /*NoDiagnose=*/true))
6422 ClausesWithImplicit.emplace_back(Args&: Implicit);
6423 }
6424 }
6425 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6426 int ClauseKindCnt = -1;
6427 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6428 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6429 ++ClauseKindCnt;
6430 if (ImplicitMap.empty())
6431 continue;
6432 CXXScopeSpec MapperIdScopeSpec;
6433 DeclarationNameInfo MapperId;
6434 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6435 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6436 IteratorModifier: nullptr, MapTypeModifiers: ImpInfo.MapModifiers[I], MapTypeModifiersLoc: ImplicitMapModifiersLoc[I],
6437 MapperIdScopeSpec, MapperId, MapType: K, /*IsMapTypeImplicit=*/true,
6438 MapLoc: SourceLocation(), ColonLoc: SourceLocation(), VarList: ImplicitMap,
6439 Locs: OMPVarListLocTy())) {
6440 ClausesWithImplicit.emplace_back(Args&: Implicit);
6441 ErrorFound |= cast<OMPMapClause>(Val: Implicit)->varlist_size() !=
6442 ImplicitMap.size();
6443 } else {
6444 ErrorFound = true;
6445 }
6446 }
6447 }
6448 // Build expressions for implicit maps of data members with 'default'
6449 // mappers.
6450 if (getLangOpts().OpenMP >= 50)
6451 processImplicitMapsWithDefaultMappers(S&: SemaRef, DSAStack,
6452 Clauses&: ClausesWithImplicit);
6453 }
6454
6455 switch (Kind) {
6456 case OMPD_parallel:
6457 Res = ActOnOpenMPParallelDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6458 EndLoc);
6459 break;
6460 case OMPD_simd:
6461 Res = ActOnOpenMPSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6462 VarsWithImplicitDSA&: VarsWithInheritedDSA);
6463 break;
6464 case OMPD_tile:
6465 Res =
6466 ActOnOpenMPTileDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6467 break;
6468 case OMPD_stripe:
6469 Res = ActOnOpenMPStripeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6470 EndLoc);
6471 break;
6472 case OMPD_unroll:
6473 Res = ActOnOpenMPUnrollDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6474 EndLoc);
6475 break;
6476 case OMPD_reverse:
6477 assert(ClausesWithImplicit.empty() &&
6478 "reverse directive does not support any clauses");
6479 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6480 break;
6481 case OMPD_split:
6482 Res =
6483 ActOnOpenMPSplitDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6484 break;
6485 case OMPD_interchange:
6486 Res = ActOnOpenMPInterchangeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6487 EndLoc);
6488 break;
6489 case OMPD_fuse:
6490 Res =
6491 ActOnOpenMPFuseDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6492 break;
6493 case OMPD_for:
6494 Res = ActOnOpenMPForDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6495 VarsWithImplicitDSA&: VarsWithInheritedDSA);
6496 break;
6497 case OMPD_for_simd:
6498 Res = ActOnOpenMPForSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6499 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6500 break;
6501 case OMPD_sections:
6502 Res = ActOnOpenMPSectionsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6503 EndLoc);
6504 break;
6505 case OMPD_section:
6506 assert(ClausesWithImplicit.empty() &&
6507 "No clauses are allowed for 'omp section' directive");
6508 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6509 break;
6510 case OMPD_single:
6511 Res = ActOnOpenMPSingleDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6512 EndLoc);
6513 break;
6514 case OMPD_master:
6515 assert(ClausesWithImplicit.empty() &&
6516 "No clauses are allowed for 'omp master' directive");
6517 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6518 break;
6519 case OMPD_masked:
6520 Res = ActOnOpenMPMaskedDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6521 EndLoc);
6522 break;
6523 case OMPD_critical:
6524 Res = ActOnOpenMPCriticalDirective(DirName, Clauses: ClausesWithImplicit, AStmt,
6525 StartLoc, EndLoc);
6526 break;
6527 case OMPD_parallel_for:
6528 Res = ActOnOpenMPParallelForDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6529 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6530 break;
6531 case OMPD_parallel_for_simd:
6532 Res = ActOnOpenMPParallelForSimdDirective(
6533 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6534 break;
6535 case OMPD_scope:
6536 Res =
6537 ActOnOpenMPScopeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6538 break;
6539 case OMPD_parallel_master:
6540 Res = ActOnOpenMPParallelMasterDirective(Clauses: ClausesWithImplicit, AStmt,
6541 StartLoc, EndLoc);
6542 break;
6543 case OMPD_parallel_masked:
6544 Res = ActOnOpenMPParallelMaskedDirective(Clauses: ClausesWithImplicit, AStmt,
6545 StartLoc, EndLoc);
6546 break;
6547 case OMPD_parallel_sections:
6548 Res = ActOnOpenMPParallelSectionsDirective(Clauses: ClausesWithImplicit, AStmt,
6549 StartLoc, EndLoc);
6550 break;
6551 case OMPD_task:
6552 Res =
6553 ActOnOpenMPTaskDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6554 break;
6555 case OMPD_taskyield:
6556 assert(ClausesWithImplicit.empty() &&
6557 "No clauses are allowed for 'omp taskyield' directive");
6558 assert(AStmt == nullptr &&
6559 "No associated statement allowed for 'omp taskyield' directive");
6560 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6561 break;
6562 case OMPD_error:
6563 assert(AStmt == nullptr &&
6564 "No associated statement allowed for 'omp error' directive");
6565 Res = ActOnOpenMPErrorDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6566 break;
6567 case OMPD_barrier:
6568 assert(ClausesWithImplicit.empty() &&
6569 "No clauses are allowed for 'omp barrier' directive");
6570 assert(AStmt == nullptr &&
6571 "No associated statement allowed for 'omp barrier' directive");
6572 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6573 break;
6574 case OMPD_taskwait:
6575 assert(AStmt == nullptr &&
6576 "No associated statement allowed for 'omp taskwait' directive");
6577 Res = ActOnOpenMPTaskwaitDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6578 break;
6579 case OMPD_taskgroup:
6580 Res = ActOnOpenMPTaskgroupDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6581 EndLoc);
6582 break;
6583 case OMPD_flush:
6584 assert(AStmt == nullptr &&
6585 "No associated statement allowed for 'omp flush' directive");
6586 Res = ActOnOpenMPFlushDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6587 break;
6588 case OMPD_depobj:
6589 assert(AStmt == nullptr &&
6590 "No associated statement allowed for 'omp depobj' directive");
6591 Res = ActOnOpenMPDepobjDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6592 break;
6593 case OMPD_scan:
6594 assert(AStmt == nullptr &&
6595 "No associated statement allowed for 'omp scan' directive");
6596 Res = ActOnOpenMPScanDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6597 break;
6598 case OMPD_ordered_blockassoc:
6599 case OMPD_ordered_standalone:
6600 Res = ActOnOpenMPOrderedDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6601 EndLoc);
6602 break;
6603 case OMPD_atomic:
6604 Res = ActOnOpenMPAtomicDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6605 EndLoc);
6606 break;
6607 case OMPD_teams:
6608 Res =
6609 ActOnOpenMPTeamsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6610 break;
6611 case OMPD_target:
6612 Res = ActOnOpenMPTargetDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6613 EndLoc);
6614 break;
6615 case OMPD_target_parallel:
6616 Res = ActOnOpenMPTargetParallelDirective(Clauses: ClausesWithImplicit, AStmt,
6617 StartLoc, EndLoc);
6618 break;
6619 case OMPD_target_parallel_for:
6620 Res = ActOnOpenMPTargetParallelForDirective(
6621 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6622 break;
6623 case OMPD_cancellation_point:
6624 assert(ClausesWithImplicit.empty() &&
6625 "No clauses are allowed for 'omp cancellation point' directive");
6626 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6627 "cancellation point' directive");
6628 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6629 break;
6630 case OMPD_cancel:
6631 assert(AStmt == nullptr &&
6632 "No associated statement allowed for 'omp cancel' directive");
6633 Res = ActOnOpenMPCancelDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc,
6634 CancelRegion);
6635 break;
6636 case OMPD_target_data:
6637 Res = ActOnOpenMPTargetDataDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6638 EndLoc);
6639 break;
6640 case OMPD_target_enter_data:
6641 Res = ActOnOpenMPTargetEnterDataDirective(Clauses: ClausesWithImplicit, StartLoc,
6642 EndLoc, AStmt);
6643 break;
6644 case OMPD_target_exit_data:
6645 Res = ActOnOpenMPTargetExitDataDirective(Clauses: ClausesWithImplicit, StartLoc,
6646 EndLoc, AStmt);
6647 break;
6648 case OMPD_taskloop:
6649 Res = ActOnOpenMPTaskLoopDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6650 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6651 break;
6652 case OMPD_taskloop_simd:
6653 Res = ActOnOpenMPTaskLoopSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6654 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6655 break;
6656 case OMPD_master_taskloop:
6657 Res = ActOnOpenMPMasterTaskLoopDirective(
6658 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6659 break;
6660 case OMPD_masked_taskloop:
6661 Res = ActOnOpenMPMaskedTaskLoopDirective(
6662 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6663 break;
6664 case OMPD_master_taskloop_simd:
6665 Res = ActOnOpenMPMasterTaskLoopSimdDirective(
6666 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6667 break;
6668 case OMPD_masked_taskloop_simd:
6669 Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
6670 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6671 break;
6672 case OMPD_parallel_master_taskloop:
6673 Res = ActOnOpenMPParallelMasterTaskLoopDirective(
6674 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6675 break;
6676 case OMPD_parallel_masked_taskloop:
6677 Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
6678 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6679 break;
6680 case OMPD_parallel_master_taskloop_simd:
6681 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6682 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6683 break;
6684 case OMPD_parallel_masked_taskloop_simd:
6685 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6686 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6687 break;
6688 case OMPD_distribute:
6689 Res = ActOnOpenMPDistributeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6690 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6691 break;
6692 case OMPD_target_update:
6693 Res = ActOnOpenMPTargetUpdateDirective(Clauses: ClausesWithImplicit, StartLoc,
6694 EndLoc, AStmt);
6695 break;
6696 case OMPD_distribute_parallel_for:
6697 Res = ActOnOpenMPDistributeParallelForDirective(
6698 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6699 break;
6700 case OMPD_distribute_parallel_for_simd:
6701 Res = ActOnOpenMPDistributeParallelForSimdDirective(
6702 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6703 break;
6704 case OMPD_distribute_simd:
6705 Res = ActOnOpenMPDistributeSimdDirective(
6706 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6707 break;
6708 case OMPD_target_parallel_for_simd:
6709 Res = ActOnOpenMPTargetParallelForSimdDirective(
6710 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6711 break;
6712 case OMPD_target_simd:
6713 Res = ActOnOpenMPTargetSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6714 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6715 break;
6716 case OMPD_teams_distribute:
6717 Res = ActOnOpenMPTeamsDistributeDirective(
6718 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6719 break;
6720 case OMPD_teams_distribute_simd:
6721 Res = ActOnOpenMPTeamsDistributeSimdDirective(
6722 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6723 break;
6724 case OMPD_teams_distribute_parallel_for_simd:
6725 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6726 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6727 break;
6728 case OMPD_teams_distribute_parallel_for:
6729 Res = ActOnOpenMPTeamsDistributeParallelForDirective(
6730 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6731 break;
6732 case OMPD_target_teams:
6733 Res = ActOnOpenMPTargetTeamsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6734 EndLoc);
6735 break;
6736 case OMPD_target_teams_distribute:
6737 Res = ActOnOpenMPTargetTeamsDistributeDirective(
6738 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6739 break;
6740 case OMPD_target_teams_distribute_parallel_for:
6741 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6742 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6743 break;
6744 case OMPD_target_teams_distribute_parallel_for_simd:
6745 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6746 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6747 break;
6748 case OMPD_target_teams_distribute_simd:
6749 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
6750 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6751 break;
6752 case OMPD_interop:
6753 assert(AStmt == nullptr &&
6754 "No associated statement allowed for 'omp interop' directive");
6755 Res = ActOnOpenMPInteropDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6756 break;
6757 case OMPD_dispatch:
6758 Res = ActOnOpenMPDispatchDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6759 EndLoc);
6760 break;
6761 case OMPD_loop:
6762 Res = ActOnOpenMPGenericLoopDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6763 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6764 break;
6765 case OMPD_teams_loop:
6766 Res = ActOnOpenMPTeamsGenericLoopDirective(
6767 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6768 break;
6769 case OMPD_target_teams_loop:
6770 Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
6771 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6772 break;
6773 case OMPD_parallel_loop:
6774 Res = ActOnOpenMPParallelGenericLoopDirective(
6775 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6776 break;
6777 case OMPD_target_parallel_loop:
6778 Res = ActOnOpenMPTargetParallelGenericLoopDirective(
6779 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6780 break;
6781 case OMPD_declare_target:
6782 case OMPD_end_declare_target:
6783 case OMPD_threadprivate:
6784 case OMPD_allocate:
6785 case OMPD_declare_reduction:
6786 case OMPD_declare_mapper:
6787 case OMPD_declare_simd:
6788 case OMPD_requires:
6789 case OMPD_declare_variant:
6790 case OMPD_begin_declare_variant:
6791 case OMPD_end_declare_variant:
6792 llvm_unreachable("OpenMP Directive is not allowed");
6793 case OMPD_taskgraph:
6794 Diag(Loc: StartLoc, DiagID: diag::err_omp_unexpected_directive)
6795 << 1 << getOpenMPDirectiveName(D: OMPD_taskgraph);
6796 return StmtError();
6797 case OMPD_unknown:
6798 default:
6799 llvm_unreachable("Unknown OpenMP directive");
6800 }
6801
6802 ErrorFound = Res.isInvalid() || ErrorFound;
6803
6804 // Check variables in the clauses if default(none) or
6805 // default(firstprivate) was specified.
6806 if (DSAStack->getDefaultDSA() == DSA_none ||
6807 DSAStack->getDefaultDSA() == DSA_private ||
6808 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6809 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6810 for (OMPClause *C : Clauses) {
6811 switch (C->getClauseKind()) {
6812 case OMPC_num_threads:
6813 case OMPC_dist_schedule:
6814 // Do not analyze if no parent teams directive.
6815 if (isOpenMPTeamsDirective(DKind: Kind))
6816 break;
6817 continue;
6818 case OMPC_if:
6819 if (isOpenMPTeamsDirective(DKind: Kind) &&
6820 cast<OMPIfClause>(Val: C)->getNameModifier() != OMPD_target)
6821 break;
6822 if (isOpenMPParallelDirective(DKind: Kind) &&
6823 isOpenMPTaskLoopDirective(DKind: Kind) &&
6824 cast<OMPIfClause>(Val: C)->getNameModifier() != OMPD_parallel)
6825 break;
6826 continue;
6827 case OMPC_schedule:
6828 case OMPC_detach:
6829 break;
6830 case OMPC_grainsize:
6831 case OMPC_num_tasks:
6832 case OMPC_final:
6833 case OMPC_priority:
6834 case OMPC_novariants:
6835 case OMPC_nocontext:
6836 // Do not analyze if no parent parallel directive.
6837 if (isOpenMPParallelDirective(DKind: Kind))
6838 break;
6839 continue;
6840 case OMPC_ordered:
6841 case OMPC_device:
6842 case OMPC_num_teams:
6843 case OMPC_thread_limit:
6844 case OMPC_hint:
6845 case OMPC_collapse:
6846 case OMPC_safelen:
6847 case OMPC_simdlen:
6848 case OMPC_sizes:
6849 case OMPC_default:
6850 case OMPC_proc_bind:
6851 case OMPC_private:
6852 case OMPC_firstprivate:
6853 case OMPC_lastprivate:
6854 case OMPC_shared:
6855 case OMPC_reduction:
6856 case OMPC_task_reduction:
6857 case OMPC_in_reduction:
6858 case OMPC_linear:
6859 case OMPC_aligned:
6860 case OMPC_copyin:
6861 case OMPC_copyprivate:
6862 case OMPC_nowait:
6863 case OMPC_untied:
6864 case OMPC_mergeable:
6865 case OMPC_allocate:
6866 case OMPC_read:
6867 case OMPC_write:
6868 case OMPC_update:
6869 case OMPC_capture:
6870 case OMPC_compare:
6871 case OMPC_seq_cst:
6872 case OMPC_acq_rel:
6873 case OMPC_acquire:
6874 case OMPC_release:
6875 case OMPC_relaxed:
6876 case OMPC_depend:
6877 case OMPC_threads:
6878 case OMPC_simd:
6879 case OMPC_map:
6880 case OMPC_nogroup:
6881 case OMPC_defaultmap:
6882 case OMPC_to:
6883 case OMPC_from:
6884 case OMPC_use_device_ptr:
6885 case OMPC_use_device_addr:
6886 case OMPC_is_device_ptr:
6887 case OMPC_has_device_addr:
6888 case OMPC_nontemporal:
6889 case OMPC_order:
6890 case OMPC_destroy:
6891 case OMPC_inclusive:
6892 case OMPC_exclusive:
6893 case OMPC_uses_allocators:
6894 case OMPC_affinity:
6895 case OMPC_bind:
6896 case OMPC_filter:
6897 case OMPC_severity:
6898 case OMPC_message:
6899 continue;
6900 case OMPC_allocator:
6901 case OMPC_flush:
6902 case OMPC_depobj:
6903 case OMPC_threadprivate:
6904 case OMPC_groupprivate:
6905 case OMPC_uniform:
6906 case OMPC_unknown:
6907 case OMPC_unified_address:
6908 case OMPC_unified_shared_memory:
6909 case OMPC_reverse_offload:
6910 case OMPC_dynamic_allocators:
6911 case OMPC_atomic_default_mem_order:
6912 case OMPC_self_maps:
6913 case OMPC_device_type:
6914 case OMPC_match:
6915 case OMPC_when:
6916 case OMPC_at:
6917 default:
6918 llvm_unreachable("Unexpected clause");
6919 }
6920 for (Stmt *CC : C->children()) {
6921 if (CC)
6922 DSAChecker.Visit(S: CC);
6923 }
6924 }
6925 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6926 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6927 }
6928 for (const auto &P : VarsWithInheritedDSA) {
6929 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(Val: P.getFirst()))
6930 continue;
6931 ErrorFound = true;
6932 if (DSAStack->getDefaultDSA() == DSA_none ||
6933 DSAStack->getDefaultDSA() == DSA_private ||
6934 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6935 Diag(Loc: P.second->getExprLoc(), DiagID: diag::err_omp_no_dsa_for_variable)
6936 << P.first << P.second->getSourceRange();
6937 Diag(DSAStack->getDefaultDSALocation(), DiagID: diag::note_omp_default_dsa_none);
6938 } else if (getLangOpts().OpenMP >= 50) {
6939 Diag(Loc: P.second->getExprLoc(),
6940 DiagID: diag::err_omp_defaultmap_no_attr_for_variable)
6941 << P.first << P.second->getSourceRange();
6942 Diag(DSAStack->getDefaultDSALocation(),
6943 DiagID: diag::note_omp_defaultmap_attr_none);
6944 }
6945 }
6946
6947 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6948 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(D: Kind)) {
6949 if (isAllowedClauseForDirective(D, C: OMPC_if, Version: getLangOpts().OpenMP))
6950 AllowedNameModifiers.push_back(Elt: D);
6951 }
6952 if (!AllowedNameModifiers.empty())
6953 ErrorFound = checkIfClauses(S&: SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6954 ErrorFound;
6955
6956 if (ErrorFound)
6957 return StmtError();
6958
6959 if (!SemaRef.CurContext->isDependentContext() &&
6960 isOpenMPTargetExecutionDirective(DKind: Kind) &&
6961 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6962 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6963 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6964 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6965 // Register target to DSA Stack.
6966 DSAStack->addTargetDirLocation(LocStart: StartLoc);
6967 }
6968
6969 return Res;
6970}
6971
6972SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareSimdDirective(
6973 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6974 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6975 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6976 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6977 assert(Aligneds.size() == Alignments.size());
6978 assert(Linears.size() == LinModifiers.size());
6979 assert(Linears.size() == Steps.size());
6980 if (!DG || DG.get().isNull())
6981 return DeclGroupPtrTy();
6982
6983 const int SimdId = 0;
6984 if (!DG.get().isSingleDecl()) {
6985 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_single_decl_in_declare_simd_variant)
6986 << SimdId;
6987 return DG;
6988 }
6989 Decl *ADecl = DG.get().getSingleDecl();
6990 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: ADecl))
6991 ADecl = FTD->getTemplatedDecl();
6992
6993 auto *FD = dyn_cast<FunctionDecl>(Val: ADecl);
6994 if (!FD) {
6995 Diag(Loc: ADecl->getLocation(), DiagID: diag::err_omp_function_expected) << SimdId;
6996 return DeclGroupPtrTy();
6997 }
6998
6999 // OpenMP [2.8.2, declare simd construct, Description]
7000 // The parameter of the simdlen clause must be a constant positive integer
7001 // expression.
7002 ExprResult SL;
7003 if (Simdlen)
7004 SL = VerifyPositiveIntegerConstantInClause(Op: Simdlen, CKind: OMPC_simdlen);
7005 // OpenMP [2.8.2, declare simd construct, Description]
7006 // The special this pointer can be used as if was one of the arguments to the
7007 // function in any of the linear, aligned, or uniform clauses.
7008 // The uniform clause declares one or more arguments to have an invariant
7009 // value for all concurrent invocations of the function in the execution of a
7010 // single SIMD loop.
7011 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
7012 const Expr *UniformedLinearThis = nullptr;
7013 for (const Expr *E : Uniforms) {
7014 E = E->IgnoreParenImpCasts();
7015 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7016 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl()))
7017 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7018 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7019 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
7020 UniformedArgs.try_emplace(Key: PVD->getCanonicalDecl(), Args&: E);
7021 continue;
7022 }
7023 if (isa<CXXThisExpr>(Val: E)) {
7024 UniformedLinearThis = E;
7025 continue;
7026 }
7027 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
7028 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
7029 }
7030 // OpenMP [2.8.2, declare simd construct, Description]
7031 // The aligned clause declares that the object to which each list item points
7032 // is aligned to the number of bytes expressed in the optional parameter of
7033 // the aligned clause.
7034 // The special this pointer can be used as if was one of the arguments to the
7035 // function in any of the linear, aligned, or uniform clauses.
7036 // The type of list items appearing in the aligned clause must be array,
7037 // pointer, reference to array, or reference to pointer.
7038 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
7039 const Expr *AlignedThis = nullptr;
7040 for (const Expr *E : Aligneds) {
7041 E = E->IgnoreParenImpCasts();
7042 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7043 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7044 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7045 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7046 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7047 ->getCanonicalDecl() == CanonPVD) {
7048 // OpenMP [2.8.1, simd construct, Restrictions]
7049 // A list-item cannot appear in more than one aligned clause.
7050 auto [It, Inserted] = AlignedArgs.try_emplace(Key: CanonPVD, Args&: E);
7051 if (!Inserted) {
7052 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_used_in_clause_twice)
7053 << 1 << getOpenMPClauseNameForDiag(C: OMPC_aligned)
7054 << E->getSourceRange();
7055 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7056 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
7057 continue;
7058 }
7059 QualType QTy = PVD->getType()
7060 .getNonReferenceType()
7061 .getUnqualifiedType()
7062 .getCanonicalType();
7063 const Type *Ty = QTy.getTypePtrOrNull();
7064 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
7065 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_aligned_expected_array_or_ptr)
7066 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
7067 Diag(Loc: PVD->getLocation(), DiagID: diag::note_previous_decl) << PVD;
7068 }
7069 continue;
7070 }
7071 }
7072 if (isa<CXXThisExpr>(Val: E)) {
7073 if (AlignedThis) {
7074 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_used_in_clause_twice)
7075 << 2 << getOpenMPClauseNameForDiag(C: OMPC_aligned)
7076 << E->getSourceRange();
7077 Diag(Loc: AlignedThis->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7078 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
7079 }
7080 AlignedThis = E;
7081 continue;
7082 }
7083 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
7084 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
7085 }
7086 // The optional parameter of the aligned clause, alignment, must be a constant
7087 // positive integer expression. If no optional parameter is specified,
7088 // implementation-defined default alignments for SIMD instructions on the
7089 // target platforms are assumed.
7090 SmallVector<const Expr *, 4> NewAligns;
7091 for (Expr *E : Alignments) {
7092 ExprResult Align;
7093 if (E)
7094 Align = VerifyPositiveIntegerConstantInClause(Op: E, CKind: OMPC_aligned);
7095 NewAligns.push_back(Elt: Align.get());
7096 }
7097 // OpenMP [2.8.2, declare simd construct, Description]
7098 // The linear clause declares one or more list items to be private to a SIMD
7099 // lane and to have a linear relationship with respect to the iteration space
7100 // of a loop.
7101 // The special this pointer can be used as if was one of the arguments to the
7102 // function in any of the linear, aligned, or uniform clauses.
7103 // When a linear-step expression is specified in a linear clause it must be
7104 // either a constant integer expression or an integer-typed parameter that is
7105 // specified in a uniform clause on the directive.
7106 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7107 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7108 auto MI = LinModifiers.begin();
7109 for (const Expr *E : Linears) {
7110 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7111 ++MI;
7112 E = E->IgnoreParenImpCasts();
7113 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7114 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7115 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7116 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7117 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7118 ->getCanonicalDecl() == CanonPVD) {
7119 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7120 // A list-item cannot appear in more than one linear clause.
7121 if (auto It = LinearArgs.find(Val: CanonPVD); It != LinearArgs.end()) {
7122 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
7123 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7124 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7125 << E->getSourceRange();
7126 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7127 << getOpenMPClauseNameForDiag(C: OMPC_linear);
7128 continue;
7129 }
7130 // Each argument can appear in at most one uniform or linear clause.
7131 if (auto It = UniformedArgs.find(Val: CanonPVD);
7132 It != UniformedArgs.end()) {
7133 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
7134 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7135 << getOpenMPClauseNameForDiag(C: OMPC_uniform)
7136 << E->getSourceRange();
7137 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7138 << getOpenMPClauseNameForDiag(C: OMPC_uniform);
7139 continue;
7140 }
7141 LinearArgs[CanonPVD] = E;
7142 if (E->isValueDependent() || E->isTypeDependent() ||
7143 E->isInstantiationDependent() ||
7144 E->containsUnexpandedParameterPack())
7145 continue;
7146 (void)CheckOpenMPLinearDecl(D: CanonPVD, ELoc: E->getExprLoc(), LinKind,
7147 Type: PVD->getOriginalType(),
7148 /*IsDeclareSimd=*/true);
7149 continue;
7150 }
7151 }
7152 if (isa<CXXThisExpr>(Val: E)) {
7153 if (UniformedLinearThis) {
7154 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
7155 << getOpenMPClauseNameForDiag(C: OMPC_linear)
7156 << getOpenMPClauseNameForDiag(C: IsUniformedThis ? OMPC_uniform
7157 : OMPC_linear)
7158 << E->getSourceRange();
7159 Diag(Loc: UniformedLinearThis->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
7160 << getOpenMPClauseNameForDiag(C: IsUniformedThis ? OMPC_uniform
7161 : OMPC_linear);
7162 continue;
7163 }
7164 UniformedLinearThis = E;
7165 if (E->isValueDependent() || E->isTypeDependent() ||
7166 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
7167 continue;
7168 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, ELoc: E->getExprLoc(), LinKind,
7169 Type: E->getType(), /*IsDeclareSimd=*/true);
7170 continue;
7171 }
7172 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
7173 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
7174 }
7175 Expr *Step = nullptr;
7176 Expr *NewStep = nullptr;
7177 SmallVector<Expr *, 4> NewSteps;
7178 for (Expr *E : Steps) {
7179 // Skip the same step expression, it was checked already.
7180 if (Step == E || !E) {
7181 NewSteps.push_back(Elt: E ? NewStep : nullptr);
7182 continue;
7183 }
7184 Step = E;
7185 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: Step))
7186 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7187 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7188 if (UniformedArgs.count(Val: CanonPVD) == 0) {
7189 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_expected_uniform_param)
7190 << Step->getSourceRange();
7191 } else if (E->isValueDependent() || E->isTypeDependent() ||
7192 E->isInstantiationDependent() ||
7193 E->containsUnexpandedParameterPack() ||
7194 CanonPVD->getType()->hasIntegerRepresentation()) {
7195 NewSteps.push_back(Elt: Step);
7196 } else {
7197 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_expected_int_param)
7198 << Step->getSourceRange();
7199 }
7200 continue;
7201 }
7202 NewStep = Step;
7203 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7204 !Step->isInstantiationDependent() &&
7205 !Step->containsUnexpandedParameterPack()) {
7206 NewStep = PerformOpenMPImplicitIntegerConversion(OpLoc: Step->getExprLoc(), Op: Step)
7207 .get();
7208 if (NewStep)
7209 NewStep = SemaRef
7210 .VerifyIntegerConstantExpression(
7211 E: NewStep, /*FIXME*/ CanFold: AllowFoldKind::Allow)
7212 .get();
7213 }
7214 NewSteps.push_back(Elt: NewStep);
7215 }
7216 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7217 Ctx&: getASTContext(), BranchState: BS, Simdlen: SL.get(), Uniforms: const_cast<Expr **>(Uniforms.data()),
7218 UniformsSize: Uniforms.size(), Aligneds: const_cast<Expr **>(Aligneds.data()), AlignedsSize: Aligneds.size(),
7219 Alignments: const_cast<Expr **>(NewAligns.data()), AlignmentsSize: NewAligns.size(),
7220 Linears: const_cast<Expr **>(Linears.data()), LinearsSize: Linears.size(),
7221 Modifiers: const_cast<unsigned *>(LinModifiers.data()), ModifiersSize: LinModifiers.size(),
7222 Steps: NewSteps.data(), StepsSize: NewSteps.size(), Range: SR);
7223 ADecl->addAttr(A: NewAttr);
7224 return DG;
7225}
7226
7227StmtResult SemaOpenMP::ActOnOpenMPInformationalDirective(
7228 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
7229 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
7230 SourceLocation EndLoc) {
7231 assert(isOpenMPInformationalDirective(Kind) &&
7232 "Unexpected directive category");
7233
7234 StmtResult Res = StmtError();
7235
7236 switch (Kind) {
7237 case OMPD_assume:
7238 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
7239 break;
7240 default:
7241 llvm_unreachable("Unknown OpenMP directive");
7242 }
7243
7244 return Res;
7245}
7246
7247static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7248 QualType NewType) {
7249 assert(NewType->isFunctionProtoType() &&
7250 "Expected function type with prototype.");
7251 assert(FD->getType()->isFunctionNoProtoType() &&
7252 "Expected function with type with no prototype.");
7253 assert(FDWithProto->getType()->isFunctionProtoType() &&
7254 "Expected function with prototype.");
7255 // Synthesize parameters with the same types.
7256 FD->setType(NewType);
7257 SmallVector<ParmVarDecl *, 16> Params;
7258 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7259 auto *Param = ParmVarDecl::Create(C&: S.getASTContext(), DC: FD, StartLoc: SourceLocation(),
7260 IdLoc: SourceLocation(), Id: nullptr, T: P->getType(),
7261 /*TInfo=*/nullptr, S: SC_None, DefArg: nullptr);
7262 Param->setScopeInfo(scopeDepth: 0, parameterIndex: Params.size());
7263 Param->setImplicit();
7264 Params.push_back(Elt: Param);
7265 }
7266
7267 FD->setParams(Params);
7268}
7269
7270void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
7271 if (D->isInvalidDecl())
7272 return;
7273 FunctionDecl *FD = nullptr;
7274 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(Val: D))
7275 FD = UTemplDecl->getTemplatedDecl();
7276 else
7277 FD = cast<FunctionDecl>(Val: D);
7278 assert(FD && "Expected a function declaration!");
7279
7280 // If we are instantiating templates we do *not* apply scoped assumptions but
7281 // only global ones. We apply scoped assumption to the template definition
7282 // though.
7283 if (!SemaRef.inTemplateInstantiation()) {
7284 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7285 FD->addAttr(A: AA);
7286 }
7287 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7288 FD->addAttr(A: AA);
7289}
7290
7291SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7292 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7293
7294void SemaOpenMP::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7295 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7296 SmallVectorImpl<FunctionDecl *> &Bases) {
7297 if (!D.getIdentifier())
7298 return;
7299
7300 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7301
7302 // Template specialization is an extension, check if we do it.
7303 bool IsTemplated = !TemplateParamLists.empty();
7304 if (IsTemplated &&
7305 !DVScope.TI->isExtensionActive(
7306 TP: llvm::omp::TraitProperty::implementation_extension_allow_templates))
7307 return;
7308
7309 const IdentifierInfo *BaseII = D.getIdentifier();
7310 LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(),
7311 Sema::LookupOrdinaryName);
7312 SemaRef.LookupParsedName(R&: Lookup, S, SS: &D.getCXXScopeSpec(),
7313 /*ObjectType=*/QualType());
7314
7315 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7316 QualType FType = TInfo->getType();
7317
7318 bool IsConstexpr =
7319 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7320 bool IsConsteval =
7321 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7322
7323 for (auto *Candidate : Lookup) {
7324 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7325 FunctionDecl *UDecl = nullptr;
7326 if (IsTemplated && isa<FunctionTemplateDecl>(Val: CandidateDecl)) {
7327 auto *FTD = cast<FunctionTemplateDecl>(Val: CandidateDecl);
7328 // FIXME: Should this compare the template parameter lists on all levels?
7329 if (SemaRef.Context.isSameTemplateParameterList(
7330 X: FTD->getTemplateParameters(), Y: TemplateParamLists.back()))
7331 UDecl = FTD->getTemplatedDecl();
7332 } else if (!IsTemplated)
7333 UDecl = dyn_cast<FunctionDecl>(Val: CandidateDecl);
7334 if (!UDecl)
7335 continue;
7336
7337 // Don't specialize constexpr/consteval functions with
7338 // non-constexpr/consteval functions.
7339 if (UDecl->isConstexpr() && !IsConstexpr)
7340 continue;
7341 if (UDecl->isConsteval() && !IsConsteval)
7342 continue;
7343
7344 QualType UDeclTy = UDecl->getType();
7345 if (!UDeclTy->isDependentType()) {
7346 QualType NewType = getASTContext().mergeFunctionTypes(
7347 FType, UDeclTy, /*OfBlockPointer=*/false,
7348 /*Unqualified=*/false, /*AllowCXX=*/true);
7349 if (NewType.isNull())
7350 continue;
7351 }
7352
7353 // Found a base!
7354 Bases.push_back(Elt: UDecl);
7355 }
7356
7357 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7358 TP: llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7359 // If no base was found we create a declaration that we use as base.
7360 if (Bases.empty() && UseImplicitBase) {
7361 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7362 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParameterLists: TemplateParamLists);
7363 BaseD->setImplicit(true);
7364 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(Val: BaseD))
7365 Bases.push_back(Elt: BaseTemplD->getTemplatedDecl());
7366 else
7367 Bases.push_back(Elt: cast<FunctionDecl>(Val: BaseD));
7368 }
7369
7370 std::string MangledName;
7371 MangledName += D.getIdentifier()->getName();
7372 MangledName += getOpenMPVariantManglingSeparatorStr();
7373 MangledName += DVScope.NameSuffix;
7374 IdentifierInfo &VariantII = getASTContext().Idents.get(Name: MangledName);
7375
7376 VariantII.setMangledOpenMPVariantName(true);
7377 D.SetIdentifier(Id: &VariantII, IdLoc: D.getBeginLoc());
7378}
7379
7380void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7381 Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
7382 // Do not mark function as is used to prevent its emission if this is the
7383 // only place where it is used.
7384 EnterExpressionEvaluationContext Unevaluated(
7385 SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);
7386
7387 FunctionDecl *FD = nullptr;
7388 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(Val: D))
7389 FD = UTemplDecl->getTemplatedDecl();
7390 else
7391 FD = cast<FunctionDecl>(Val: D);
7392 auto *VariantFuncRef = DeclRefExpr::Create(
7393 Context: getASTContext(), QualifierLoc: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), D: FD,
7394 /*RefersToEnclosingVariableOrCapture=*/false,
7395 /*NameLoc=*/FD->getLocation(), T: FD->getType(), VK: ExprValueKind::VK_PRValue);
7396
7397 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7398 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7399 Ctx&: getASTContext(), VariantFuncRef, TraitInfos: DVScope.TI,
7400 /*NothingArgs=*/AdjustArgsNothing: nullptr, /*NothingArgsSize=*/AdjustArgsNothingSize: 0,
7401 /*NeedDevicePtrArgs=*/AdjustArgsNeedDevicePtr: nullptr, /*NeedDevicePtrArgsSize=*/AdjustArgsNeedDevicePtrSize: 0,
7402 /*NeedDeviceAddrArgs=*/AdjustArgsNeedDeviceAddr: nullptr, /*NeedDeviceAddrArgsSize=*/AdjustArgsNeedDeviceAddrSize: 0,
7403 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7404 for (FunctionDecl *BaseFD : Bases)
7405 BaseFD->addAttr(A: OMPDeclareVariantA);
7406}
7407
7408ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
7409 SourceLocation LParenLoc,
7410 MultiExprArg ArgExprs,
7411 SourceLocation RParenLoc,
7412 Expr *ExecConfig) {
7413 // The common case is a regular call we do not want to specialize at all. Try
7414 // to make that case fast by bailing early.
7415 CallExpr *CE = dyn_cast<CallExpr>(Val: Call.get());
7416 if (!CE)
7417 return Call;
7418
7419 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7420
7421 // Mark indirect calls inside target regions, to allow for insertion of
7422 // __llvm_omp_indirect_call_lookup calls during codegen.
7423 if (!CalleeFnDecl) {
7424 if (isInOpenMPTargetExecutionDirective()) {
7425 Expr *E = CE->getCallee()->IgnoreParenImpCasts();
7426 DeclRefExpr *DRE = nullptr;
7427 while (E) {
7428 if ((DRE = dyn_cast<DeclRefExpr>(Val: E)))
7429 break;
7430 if (auto *ME = dyn_cast<MemberExpr>(Val: E))
7431 E = ME->getBase()->IgnoreParenImpCasts();
7432 else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: E))
7433 E = ASE->getBase()->IgnoreParenImpCasts();
7434 else
7435 break;
7436 }
7437 VarDecl *VD = DRE ? dyn_cast<VarDecl>(Val: DRE->getDecl()) : nullptr;
7438 if (VD && !VD->hasAttr<OMPTargetIndirectCallAttr>()) {
7439 VD->addAttr(A: OMPTargetIndirectCallAttr::CreateImplicit(Ctx&: getASTContext()));
7440 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
7441 ML->DeclarationMarkedOpenMPIndirectCall(D: VD);
7442 }
7443 }
7444
7445 return Call;
7446 }
7447
7448 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7449 CalleeFnDecl->getIdentifier() &&
7450 CalleeFnDecl->getName().starts_with_insensitive(Prefix: "omp_")) {
7451 // checking for any calls inside an Order region
7452 if (Scope && Scope->isOpenMPOrderClauseScope())
7453 Diag(Loc: LParenLoc, DiagID: diag::err_omp_unexpected_call_to_omp_runtime_api);
7454 }
7455
7456 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7457 return Call;
7458
7459 ASTContext &Context = getASTContext();
7460 std::function<void(StringRef)> DiagUnknownTrait = [this,
7461 CE](StringRef ISATrait) {
7462 // TODO Track the selector locations in a way that is accessible here to
7463 // improve the diagnostic location.
7464 Diag(Loc: CE->getBeginLoc(), DiagID: diag::warn_unknown_declare_variant_isa_trait)
7465 << ISATrait;
7466 };
7467 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7468 SemaRef.getCurFunctionDecl(),
7469 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7470
7471 QualType CalleeFnType = CalleeFnDecl->getType();
7472
7473 SmallVector<Expr *, 4> Exprs;
7474 SmallVector<VariantMatchInfo, 4> VMIs;
7475 while (CalleeFnDecl) {
7476 for (OMPDeclareVariantAttr *A :
7477 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7478 Expr *VariantRef = A->getVariantFuncRef();
7479
7480 VariantMatchInfo VMI;
7481 OMPTraitInfo &TI = A->getTraitInfo();
7482 TI.getAsVariantMatchInfo(ASTCtx&: Context, VMI);
7483 if (!isVariantApplicableInContext(VMI, Ctx: OMPCtx,
7484 /*DeviceSetOnly=*/DeviceOrImplementationSetOnly: false))
7485 continue;
7486
7487 VMIs.push_back(Elt: VMI);
7488 Exprs.push_back(Elt: VariantRef);
7489 }
7490
7491 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7492 }
7493
7494 ExprResult NewCall;
7495 do {
7496 int BestIdx = getBestVariantMatchForContext(VMIs, Ctx: OMPCtx);
7497 if (BestIdx < 0)
7498 return Call;
7499 Expr *BestExpr = cast<DeclRefExpr>(Val: Exprs[BestIdx]);
7500 Decl *BestDecl = cast<DeclRefExpr>(Val: BestExpr)->getDecl();
7501
7502 {
7503 // Try to build a (member) call expression for the current best applicable
7504 // variant expression. We allow this to fail in which case we continue
7505 // with the next best variant expression. The fail case is part of the
7506 // implementation defined behavior in the OpenMP standard when it talks
7507 // about what differences in the function prototypes: "Any differences
7508 // that the specific OpenMP context requires in the prototype of the
7509 // variant from the base function prototype are implementation defined."
7510 // This wording is there to allow the specialized variant to have a
7511 // different type than the base function. This is intended and OK but if
7512 // we cannot create a call the difference is not in the "implementation
7513 // defined range" we allow.
7514 Sema::TentativeAnalysisScope Trap(SemaRef);
7515
7516 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(Val: BestDecl)) {
7517 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(Val: CE);
7518 BestExpr = MemberExpr::CreateImplicit(
7519 C: Context, Base: MemberCall->getImplicitObjectArgument(),
7520 /*IsArrow=*/false, MemberDecl: SpecializedMethod, T: Context.BoundMemberTy,
7521 VK: MemberCall->getValueKind(), OK: MemberCall->getObjectKind());
7522 }
7523 NewCall = SemaRef.BuildCallExpr(S: Scope, Fn: BestExpr, LParenLoc, ArgExprs,
7524 RParenLoc, ExecConfig);
7525 if (NewCall.isUsable()) {
7526 if (CallExpr *NCE = dyn_cast<CallExpr>(Val: NewCall.get())) {
7527 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7528 QualType NewType = getASTContext().mergeFunctionTypes(
7529 CalleeFnType, NewCalleeFnDecl->getType(),
7530 /*OfBlockPointer=*/false,
7531 /*Unqualified=*/false, /*AllowCXX=*/true);
7532 if (!NewType.isNull())
7533 break;
7534 // Don't use the call if the function type was not compatible.
7535 NewCall = nullptr;
7536 }
7537 }
7538 }
7539
7540 VMIs.erase(CI: VMIs.begin() + BestIdx);
7541 Exprs.erase(CI: Exprs.begin() + BestIdx);
7542 } while (!VMIs.empty());
7543
7544 if (!NewCall.isUsable())
7545 return Call;
7546 return PseudoObjectExpr::Create(Context: getASTContext(), syntactic: CE, semantic: {NewCall.get()}, resultIndex: 0);
7547}
7548
7549std::optional<std::pair<FunctionDecl *, Expr *>>
7550SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG,
7551 Expr *VariantRef,
7552 OMPTraitInfo &TI,
7553 unsigned NumAppendArgs,
7554 SourceRange SR) {
7555 ASTContext &Context = getASTContext();
7556 if (!DG || DG.get().isNull())
7557 return std::nullopt;
7558
7559 const int VariantId = 1;
7560 // Must be applied only to single decl.
7561 if (!DG.get().isSingleDecl()) {
7562 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_single_decl_in_declare_simd_variant)
7563 << VariantId << SR;
7564 return std::nullopt;
7565 }
7566 Decl *ADecl = DG.get().getSingleDecl();
7567 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: ADecl))
7568 ADecl = FTD->getTemplatedDecl();
7569
7570 // Decl must be a function.
7571 auto *FD = dyn_cast<FunctionDecl>(Val: ADecl);
7572 if (!FD) {
7573 Diag(Loc: ADecl->getLocation(), DiagID: diag::err_omp_function_expected)
7574 << VariantId << SR;
7575 return std::nullopt;
7576 }
7577
7578 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7579 // The 'target' attribute needs to be separately checked because it does
7580 // not always signify a multiversion function declaration.
7581 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7582 };
7583 // OpenMP is not compatible with multiversion function attributes.
7584 if (HasMultiVersionAttributes(FD)) {
7585 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_incompat_attributes)
7586 << SR;
7587 return std::nullopt;
7588 }
7589
7590 // Allow #pragma omp declare variant only if the function is not used.
7591 if (FD->isUsed(CheckUsedAttr: false))
7592 Diag(Loc: SR.getBegin(), DiagID: diag::warn_omp_declare_variant_after_used)
7593 << FD->getLocation();
7594
7595 // Check if the function was emitted already.
7596 const FunctionDecl *Definition;
7597 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7598 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(D: Definition)))
7599 Diag(Loc: SR.getBegin(), DiagID: diag::warn_omp_declare_variant_after_emitted)
7600 << FD->getLocation();
7601
7602 // The VariantRef must point to function.
7603 if (!VariantRef) {
7604 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_function_expected) << VariantId;
7605 return std::nullopt;
7606 }
7607
7608 auto ShouldDelayChecks = [](Expr *&E, bool) {
7609 return E && (E->isTypeDependent() || E->isValueDependent() ||
7610 E->containsUnexpandedParameterPack() ||
7611 E->isInstantiationDependent());
7612 };
7613 // Do not check templates, wait until instantiation.
7614 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7615 TI.anyScoreOrCondition(Cond: ShouldDelayChecks))
7616 return std::make_pair(x&: FD, y&: VariantRef);
7617
7618 // Deal with non-constant score and user condition expressions.
7619 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7620 bool IsScore) -> bool {
7621 if (!E || E->isIntegerConstantExpr(Ctx: getASTContext()))
7622 return false;
7623
7624 if (IsScore) {
7625 // We warn on non-constant scores and pretend they were not present.
7626 Diag(Loc: E->getExprLoc(), DiagID: diag::warn_omp_declare_variant_score_not_constant)
7627 << E;
7628 E = nullptr;
7629 } else {
7630 // We could replace a non-constant user condition with "false" but we
7631 // will soon need to handle these anyway for the dynamic version of
7632 // OpenMP context selectors.
7633 Diag(Loc: E->getExprLoc(),
7634 DiagID: diag::err_omp_declare_variant_user_condition_not_constant)
7635 << E;
7636 }
7637 return true;
7638 };
7639 if (TI.anyScoreOrCondition(Cond: HandleNonConstantScoresAndConditions))
7640 return std::nullopt;
7641
7642 QualType AdjustedFnType = FD->getType();
7643 if (NumAppendArgs) {
7644 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7645 if (!PTy) {
7646 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_prototype_required)
7647 << SR;
7648 return std::nullopt;
7649 }
7650 // Adjust the function type to account for an extra omp_interop_t for each
7651 // specified in the append_args clause.
7652 const TypeDecl *TD = nullptr;
7653 LookupResult Result(SemaRef, &Context.Idents.get(Name: "omp_interop_t"),
7654 SR.getBegin(), Sema::LookupOrdinaryName);
7655 if (SemaRef.LookupName(R&: Result, S: SemaRef.getCurScope())) {
7656 NamedDecl *ND = Result.getFoundDecl();
7657 TD = dyn_cast_or_null<TypeDecl>(Val: ND);
7658 }
7659 if (!TD) {
7660 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_interop_type_not_found) << SR;
7661 return std::nullopt;
7662 }
7663 QualType InteropType =
7664 Context.getTypeDeclType(Keyword: ElaboratedTypeKeyword::None,
7665 /*Qualifier=*/std::nullopt, Decl: TD);
7666 if (PTy->isVariadic()) {
7667 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_append_args_with_varargs) << SR;
7668 return std::nullopt;
7669 }
7670 llvm::SmallVector<QualType, 8> Params;
7671 Params.append(in_start: PTy->param_type_begin(), in_end: PTy->param_type_end());
7672 Params.insert(I: Params.end(), NumToInsert: NumAppendArgs, Elt: InteropType);
7673 AdjustedFnType = Context.getFunctionType(ResultTy: PTy->getReturnType(), Args: Params,
7674 EPI: PTy->getExtProtoInfo());
7675 }
7676
7677 // Convert VariantRef expression to the type of the original function to
7678 // resolve possible conflicts.
7679 ExprResult VariantRefCast = VariantRef;
7680 if (getLangOpts().CPlusPlus) {
7681 QualType FnPtrType;
7682 auto *Method = dyn_cast<CXXMethodDecl>(Val: FD);
7683 if (Method && !Method->isStatic()) {
7684 FnPtrType = Context.getMemberPointerType(
7685 T: AdjustedFnType, /*Qualifier=*/std::nullopt, Cls: Method->getParent());
7686 ExprResult ER;
7687 {
7688 // Build addr_of unary op to correctly handle type checks for member
7689 // functions.
7690 Sema::TentativeAnalysisScope Trap(SemaRef);
7691 ER = SemaRef.CreateBuiltinUnaryOp(OpLoc: VariantRef->getBeginLoc(), Opc: UO_AddrOf,
7692 InputExpr: VariantRef);
7693 }
7694 if (!ER.isUsable()) {
7695 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7696 << VariantId << VariantRef->getSourceRange();
7697 return std::nullopt;
7698 }
7699 VariantRef = ER.get();
7700 } else {
7701 FnPtrType = Context.getPointerType(T: AdjustedFnType);
7702 }
7703 QualType VarianPtrType = Context.getPointerType(T: VariantRef->getType());
7704 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7705 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7706 From: VariantRef, ToType: FnPtrType.getUnqualifiedType(),
7707 /*SuppressUserConversions=*/false, AllowExplicit: Sema::AllowedExplicit::None,
7708 /*InOverloadResolution=*/false,
7709 /*CStyle=*/false,
7710 /*AllowObjCWritebackConversion=*/false);
7711 if (ICS.isFailure()) {
7712 Diag(Loc: VariantRef->getExprLoc(),
7713 DiagID: diag::err_omp_declare_variant_incompat_types)
7714 << VariantRef->getType()
7715 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7716 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7717 return std::nullopt;
7718 }
7719 VariantRefCast = SemaRef.PerformImplicitConversion(
7720 From: VariantRef, ToType: FnPtrType.getUnqualifiedType(),
7721 Action: AssignmentAction::Converting);
7722 if (!VariantRefCast.isUsable())
7723 return std::nullopt;
7724 }
7725 // Drop previously built artificial addr_of unary op for member functions.
7726 if (Method && !Method->isStatic()) {
7727 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7728 if (auto *UO = dyn_cast<UnaryOperator>(
7729 Val: PossibleAddrOfVariantRef->IgnoreImplicit()))
7730 VariantRefCast = UO->getSubExpr();
7731 }
7732 }
7733
7734 ExprResult ER = SemaRef.CheckPlaceholderExpr(E: VariantRefCast.get());
7735 if (!ER.isUsable() ||
7736 !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7737 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7738 << VariantId << VariantRef->getSourceRange();
7739 return std::nullopt;
7740 }
7741
7742 // The VariantRef must point to function.
7743 auto *DRE = dyn_cast<DeclRefExpr>(Val: ER.get()->IgnoreParenImpCasts());
7744 if (!DRE) {
7745 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7746 << VariantId << VariantRef->getSourceRange();
7747 return std::nullopt;
7748 }
7749 auto *NewFD = dyn_cast_or_null<FunctionDecl>(Val: DRE->getDecl());
7750 if (!NewFD) {
7751 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7752 << VariantId << VariantRef->getSourceRange();
7753 return std::nullopt;
7754 }
7755
7756 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7757 Diag(Loc: VariantRef->getExprLoc(),
7758 DiagID: diag::err_omp_declare_variant_same_base_function)
7759 << VariantRef->getSourceRange();
7760 return std::nullopt;
7761 }
7762
7763 // Check if function types are compatible in C.
7764 if (!getLangOpts().CPlusPlus) {
7765 QualType NewType =
7766 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7767 if (NewType.isNull()) {
7768 Diag(Loc: VariantRef->getExprLoc(),
7769 DiagID: diag::err_omp_declare_variant_incompat_types)
7770 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7771 << VariantRef->getSourceRange();
7772 return std::nullopt;
7773 }
7774 if (NewType->isFunctionProtoType()) {
7775 if (FD->getType()->isFunctionNoProtoType())
7776 setPrototype(S&: SemaRef, FD, FDWithProto: NewFD, NewType);
7777 else if (NewFD->getType()->isFunctionNoProtoType())
7778 setPrototype(S&: SemaRef, FD: NewFD, FDWithProto: FD, NewType);
7779 }
7780 }
7781
7782 // Check if variant function is not marked with declare variant directive.
7783 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7784 Diag(Loc: VariantRef->getExprLoc(),
7785 DiagID: diag::warn_omp_declare_variant_marked_as_declare_variant)
7786 << VariantRef->getSourceRange();
7787 SourceRange SR =
7788 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7789 Diag(Loc: SR.getBegin(), DiagID: diag::note_omp_marked_declare_variant_here) << SR;
7790 return std::nullopt;
7791 }
7792
7793 enum DoesntSupport {
7794 VirtFuncs = 1,
7795 Constructors = 3,
7796 Destructors = 4,
7797 DeletedFuncs = 5,
7798 DefaultedFuncs = 6,
7799 ConstexprFuncs = 7,
7800 ConstevalFuncs = 8,
7801 };
7802 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(Val: FD)) {
7803 if (CXXFD->isVirtual()) {
7804 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7805 << VirtFuncs;
7806 return std::nullopt;
7807 }
7808
7809 if (isa<CXXConstructorDecl>(Val: FD)) {
7810 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7811 << Constructors;
7812 return std::nullopt;
7813 }
7814
7815 if (isa<CXXDestructorDecl>(Val: FD)) {
7816 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7817 << Destructors;
7818 return std::nullopt;
7819 }
7820 }
7821
7822 if (FD->isDeleted()) {
7823 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7824 << DeletedFuncs;
7825 return std::nullopt;
7826 }
7827
7828 if (FD->isDefaulted()) {
7829 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7830 << DefaultedFuncs;
7831 return std::nullopt;
7832 }
7833
7834 if (FD->isConstexpr()) {
7835 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7836 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7837 return std::nullopt;
7838 }
7839
7840 // Check general compatibility.
7841 if (SemaRef.areMultiversionVariantFunctionsCompatible(
7842 OldFD: FD, NewFD, NoProtoDiagID: PartialDiagnostic::NullDiagnostic(),
7843 NoteCausedDiagIDAt: PartialDiagnosticAt(SourceLocation(),
7844 PartialDiagnostic::NullDiagnostic()),
7845 NoSupportDiagIDAt: PartialDiagnosticAt(
7846 VariantRef->getExprLoc(),
7847 SemaRef.PDiag(DiagID: diag::err_omp_declare_variant_doesnt_support)),
7848 DiffDiagIDAt: PartialDiagnosticAt(VariantRef->getExprLoc(),
7849 SemaRef.PDiag(DiagID: diag::err_omp_declare_variant_diff)
7850 << FD->getLocation()),
7851 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7852 /*CLinkageMayDiffer=*/true))
7853 return std::nullopt;
7854 return std::make_pair(x&: FD, y: cast<Expr>(Val: DRE));
7855}
7856
7857/// Validate prefer_type fr() and attr() arguments in an OMPInteropInfo.
7858/// fr() must be a string literal or constant integer expression.
7859/// attr() must be a string literal starting with "ompx_" and containing no
7860/// commas. Returns true if valid; emits diagnostic and returns false on first
7861/// error.
7862static bool checkPreferTypeArgs(SemaOpenMP &S, const OMPInteropInfo &Info) {
7863 auto isDependent = [](const Expr *E) {
7864 return E->isValueDependent() || E->isTypeDependent() ||
7865 E->isInstantiationDependent() ||
7866 E->containsUnexpandedParameterPack();
7867 };
7868 for (const OMPInteropPref &P : Info.Prefs) {
7869 const Expr *E = P.Fr;
7870 if (!E) {
7871 assert(Info.HasPreferAttrs && "null Fr requires OMP 6.0 syntax");
7872 } else if (!isDependent(E)) {
7873 if (!E->isIntegerConstantExpr(Ctx: S.getASTContext()) &&
7874 !isa<StringLiteral>(Val: E)) {
7875 S.Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_interop_prefer_type);
7876 return false;
7877 }
7878 }
7879 for (const Expr *A : P.Attrs) {
7880 if (isDependent(A))
7881 continue;
7882 const auto *SL = dyn_cast<StringLiteral>(Val: A);
7883 if (!SL) {
7884 S.Diag(Loc: A->getExprLoc(), DiagID: diag::err_omp_interop_attr_not_string);
7885 return false;
7886 }
7887 StringRef Str = SL->getString();
7888 if (!Str.starts_with(Prefix: "ompx_")) {
7889 S.Diag(Loc: A->getExprLoc(), DiagID: diag::err_omp_interop_attr_missing_ompx_prefix)
7890 << Str;
7891 return false;
7892 }
7893 if (Str.contains(C: ',')) {
7894 S.Diag(Loc: A->getExprLoc(), DiagID: diag::err_omp_interop_attr_contains_comma)
7895 << Str;
7896 return false;
7897 }
7898 }
7899 }
7900 return true;
7901}
7902
7903void SemaOpenMP::ActOnOpenMPDeclareVariantDirective(
7904 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7905 ArrayRef<Expr *> AdjustArgsNothing,
7906 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7907 ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
7908 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7909 SourceLocation AppendArgsLoc, SourceRange SR) {
7910
7911 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7912 // An adjust_args clause or append_args clause can only be specified if the
7913 // dispatch selector of the construct selector set appears in the match
7914 // clause.
7915
7916 SmallVector<Expr *, 8> AllAdjustArgs;
7917 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNothing);
7918 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNeedDevicePtr);
7919 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNeedDeviceAddr);
7920
7921 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7922 VariantMatchInfo VMI;
7923 TI.getAsVariantMatchInfo(ASTCtx&: getASTContext(), VMI);
7924 if (!llvm::is_contained(
7925 Range&: VMI.ConstructTraits,
7926 Element: llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7927 if (!AllAdjustArgs.empty())
7928 Diag(Loc: AdjustArgsLoc, DiagID: diag::err_omp_clause_requires_dispatch_construct)
7929 << getOpenMPClauseNameForDiag(C: OMPC_adjust_args);
7930 if (!AppendArgs.empty())
7931 Diag(Loc: AppendArgsLoc, DiagID: diag::err_omp_clause_requires_dispatch_construct)
7932 << getOpenMPClauseNameForDiag(C: OMPC_append_args);
7933 return;
7934 }
7935 }
7936
7937 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7938 // Each argument can only appear in a single adjust_args clause for each
7939 // declare variant directive.
7940 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
7941
7942 for (Expr *E : AllAdjustArgs) {
7943 E = E->IgnoreParenImpCasts();
7944 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E)) {
7945 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7946 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7947 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7948 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7949 ->getCanonicalDecl() == CanonPVD) {
7950 // It's a parameter of the function, check duplicates.
7951 if (!AdjustVars.insert(Ptr: CanonPVD).second) {
7952 Diag(Loc: DRE->getLocation(), DiagID: diag::err_omp_adjust_arg_multiple_clauses)
7953 << PVD;
7954 return;
7955 }
7956 continue;
7957 }
7958 }
7959 }
7960 // Anything that is not a function parameter is an error.
7961 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause) << FD << 0;
7962 return;
7963 }
7964
7965 // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
7966 // If the `need_device_addr` adjust-op modifier is present, each list item
7967 // that appears in the clause must refer to an argument in the declaration of
7968 // the function variant that has a reference type
7969 if (getLangOpts().OpenMP >= 60) {
7970 for (Expr *E : AdjustArgsNeedDeviceAddr) {
7971 E = E->IgnoreParenImpCasts();
7972 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E)) {
7973 if (const auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl())) {
7974 if (!VD->getType()->isReferenceType())
7975 Diag(Loc: E->getExprLoc(),
7976 DiagID: diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7977 }
7978 }
7979 }
7980 }
7981
7982 // OpenMP 6.0 [16.1.3] Check prefer_type fr()/attr() arguments in
7983 // append_args.
7984 for (const OMPInteropInfo &Info : AppendArgs) {
7985 if (!checkPreferTypeArgs(S&: *this, Info))
7986 return;
7987 }
7988
7989 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7990 Ctx&: getASTContext(), VariantFuncRef: VariantRef, TraitInfos: &TI,
7991 AdjustArgsNothing: const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothingSize: AdjustArgsNothing.size(),
7992 AdjustArgsNeedDevicePtr: const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7993 AdjustArgsNeedDevicePtrSize: AdjustArgsNeedDevicePtr.size(),
7994 AdjustArgsNeedDeviceAddr: const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
7995 AdjustArgsNeedDeviceAddrSize: AdjustArgsNeedDeviceAddr.size(),
7996 AppendArgs: const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgsSize: AppendArgs.size(), Range: SR);
7997 FD->addAttr(A: NewAttr);
7998}
7999
8000static CapturedStmt *
8001setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt) {
8002 auto *CS = dyn_cast<CapturedStmt>(Val: AStmt);
8003 assert(CS && "Captured statement expected");
8004 // 1.2.2 OpenMP Language Terminology
8005 // Structured block - An executable statement with a single entry at the
8006 // top and a single exit at the bottom.
8007 // The point of exit cannot be a branch out of the structured block.
8008 // longjmp() and throw() must not violate the entry/exit criteria.
8009 CS->getCapturedDecl()->setNothrow();
8010
8011 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
8012 ThisCaptureLevel > 1; --ThisCaptureLevel) {
8013 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
8014 // 1.2.2 OpenMP Language Terminology
8015 // Structured block - An executable statement with a single entry at the
8016 // top and a single exit at the bottom.
8017 // The point of exit cannot be a branch out of the structured block.
8018 // longjmp() and throw() must not violate the entry/exit criteria.
8019 CS->getCapturedDecl()->setNothrow();
8020 }
8021 SemaRef.setFunctionHasBranchProtectedScope();
8022 return CS;
8023}
8024
8025StmtResult
8026SemaOpenMP::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
8027 Stmt *AStmt, SourceLocation StartLoc,
8028 SourceLocation EndLoc) {
8029 if (!AStmt)
8030 return StmtError();
8031
8032 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel, AStmt);
8033
8034 return OMPParallelDirective::Create(
8035 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
8036 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
8037}
8038
8039namespace {
8040/// Iteration space of a single for loop.
8041struct LoopIterationSpace final {
8042 /// True if the condition operator is the strict compare operator (<, > or
8043 /// !=).
8044 bool IsStrictCompare = false;
8045 /// Condition of the loop.
8046 Expr *PreCond = nullptr;
8047 /// This expression calculates the number of iterations in the loop.
8048 /// It is always possible to calculate it before starting the loop.
8049 Expr *NumIterations = nullptr;
8050 /// The loop counter variable.
8051 Expr *CounterVar = nullptr;
8052 /// Private loop counter variable.
8053 Expr *PrivateCounterVar = nullptr;
8054 /// This is initializer for the initial value of #CounterVar.
8055 Expr *CounterInit = nullptr;
8056 /// This is step for the #CounterVar used to generate its update:
8057 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
8058 Expr *CounterStep = nullptr;
8059 /// Should step be subtracted?
8060 bool Subtract = false;
8061 /// Source range of the loop init.
8062 SourceRange InitSrcRange;
8063 /// Source range of the loop condition.
8064 SourceRange CondSrcRange;
8065 /// Source range of the loop increment.
8066 SourceRange IncSrcRange;
8067 /// Minimum value that can have the loop control variable. Used to support
8068 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
8069 /// since only such variables can be used in non-loop invariant expressions.
8070 Expr *MinValue = nullptr;
8071 /// Maximum value that can have the loop control variable. Used to support
8072 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
8073 /// since only such variables can be used in non-loop invariant expressions.
8074 Expr *MaxValue = nullptr;
8075 /// true, if the lower bound depends on the outer loop control var.
8076 bool IsNonRectangularLB = false;
8077 /// true, if the upper bound depends on the outer loop control var.
8078 bool IsNonRectangularUB = false;
8079 /// Index of the loop this loop depends on and forms non-rectangular loop
8080 /// nest.
8081 unsigned LoopDependentIdx = 0;
8082 /// Final condition for the non-rectangular loop nest support. It is used to
8083 /// check that the number of iterations for this particular counter must be
8084 /// finished.
8085 Expr *FinalCondition = nullptr;
8086};
8087
8088/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
8089/// set are referenced. Used for verifying loop nest structure before
8090/// performing a loop collapse operation.
8091class ForSubExprChecker : public DynamicRecursiveASTVisitor {
8092 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8093 VarDecl *ForbiddenVar = nullptr;
8094 SourceRange ErrLoc;
8095
8096public:
8097 explicit ForSubExprChecker(
8098 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
8099 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
8100 // We want to visit implicit code, i.e. synthetic initialisation statements
8101 // created during range-for lowering.
8102 ShouldVisitImplicitCode = true;
8103 }
8104
8105 bool VisitDeclRefExpr(DeclRefExpr *E) override {
8106 ValueDecl *VD = E->getDecl();
8107 if (!isa<VarDecl, BindingDecl>(Val: VD))
8108 return true;
8109 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
8110 if (V->getType()->isReferenceType()) {
8111 VarDecl *VD = V->getDefinition();
8112 if (VD && VD->hasInit()) {
8113 Expr *I = VD->getInit();
8114 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Val: I);
8115 if (!DRE)
8116 return true;
8117 V = DRE->getDecl()->getPotentiallyDecomposedVarDecl();
8118 }
8119 }
8120 Decl *Canon = V->getCanonicalDecl();
8121 if (CollapsedLoopVarDecls.contains(Ptr: Canon)) {
8122 ForbiddenVar = V;
8123 ErrLoc = E->getSourceRange();
8124 return false;
8125 }
8126
8127 return true;
8128 }
8129
8130 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
8131 SourceRange getErrRange() const { return ErrLoc; }
8132};
8133
8134/// Helper class for checking canonical form of the OpenMP loops and
8135/// extracting iteration space of each loop in the loop nest, that will be used
8136/// for IR generation.
8137class OpenMPIterationSpaceChecker {
8138 /// Reference to Sema.
8139 Sema &SemaRef;
8140 /// Does the loop associated directive support non-rectangular loops?
8141 bool SupportsNonRectangular;
8142 /// Data-sharing stack.
8143 DSAStackTy &Stack;
8144 /// A location for diagnostics (when there is no some better location).
8145 SourceLocation DefaultLoc;
8146 /// A location for diagnostics (when increment is not compatible).
8147 SourceLocation ConditionLoc;
8148 /// The set of variables declared within the (to be collapsed) loop nest.
8149 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8150 /// The set of induction variables from outer collapsed loops.
8151 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars;
8152 /// A source location for referring to loop init later.
8153 SourceRange InitSrcRange;
8154 /// A source location for referring to condition later.
8155 SourceRange ConditionSrcRange;
8156 /// A source location for referring to increment later.
8157 SourceRange IncrementSrcRange;
8158 /// Loop variable.
8159 ValueDecl *LCDecl = nullptr;
8160 /// Reference to loop variable.
8161 Expr *LCRef = nullptr;
8162 /// Lower bound (initializer for the var).
8163 Expr *LB = nullptr;
8164 /// Upper bound.
8165 Expr *UB = nullptr;
8166 /// Loop step (increment).
8167 Expr *Step = nullptr;
8168 /// This flag is true when condition is one of:
8169 /// Var < UB
8170 /// Var <= UB
8171 /// UB > Var
8172 /// UB >= Var
8173 /// This will have no value when the condition is !=
8174 std::optional<bool> TestIsLessOp;
8175 /// This flag is true when condition is strict ( < or > ).
8176 bool TestIsStrictOp = false;
8177 /// This flag is true when step is subtracted on each iteration.
8178 bool SubtractStep = false;
8179 /// The outer loop counter this loop depends on (if any).
8180 const ValueDecl *DepDecl = nullptr;
8181 /// Contains number of loop (starts from 1) on which loop counter init
8182 /// expression of this loop depends on.
8183 std::optional<unsigned> InitDependOnLC;
8184 /// Contains number of loop (starts from 1) on which loop counter condition
8185 /// expression of this loop depends on.
8186 std::optional<unsigned> CondDependOnLC;
8187 /// Checks if the provide statement depends on the loop counter.
8188 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8189 bool IsInitializer);
8190 /// Original condition required for checking of the exit condition for
8191 /// non-rectangular loop.
8192 Expr *Condition = nullptr;
8193
8194public:
8195 OpenMPIterationSpaceChecker(
8196 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
8197 SourceLocation DefaultLoc,
8198 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls,
8199 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars)
8200 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8201 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8202 CollapsedLoopVarDecls(CollapsedLoopDecls),
8203 CollapsedLoopInductionVars(CollapsedLoopInductionVars) {}
8204 /// Check init-expr for canonical loop form and save loop counter
8205 /// variable - #Var and its initialization value - #LB.
8206 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8207 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8208 /// for less/greater and for strict/non-strict comparison.
8209 bool checkAndSetCond(Expr *S);
8210 /// Check incr-expr for canonical loop form and return true if it
8211 /// does not conform, otherwise save loop step (#Step).
8212 bool checkAndSetInc(Expr *S);
8213 /// Return the loop counter variable.
8214 ValueDecl *getLoopDecl() const { return LCDecl; }
8215 /// Return the reference expression to loop counter variable.
8216 Expr *getLoopDeclRefExpr() const { return LCRef; }
8217 /// Source range of the loop init.
8218 SourceRange getInitSrcRange() const { return InitSrcRange; }
8219 /// Source range of the loop condition.
8220 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8221 /// Source range of the loop increment.
8222 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8223 /// True if the step should be subtracted.
8224 bool shouldSubtractStep() const { return SubtractStep; }
8225 /// True, if the compare operator is strict (<, > or !=).
8226 bool isStrictTestOp() const { return TestIsStrictOp; }
8227 /// Build the expression to calculate the number of iterations.
8228 Expr *buildNumIterations(
8229 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8230 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8231 /// Build the precondition expression for the loops.
8232 Expr *
8233 buildPreCond(Scope *S, Expr *Cond,
8234 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8235 /// Build reference expression to the counter be used for codegen.
8236 DeclRefExpr *
8237 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8238 DSAStackTy &DSA) const;
8239 /// Build reference expression to the private counter be used for
8240 /// codegen.
8241 Expr *buildPrivateCounterVar() const;
8242 /// Build initialization of the counter be used for codegen.
8243 Expr *buildCounterInit() const;
8244 /// Build step of the counter be used for codegen.
8245 Expr *buildCounterStep() const;
8246 /// Build loop data with counter value for depend clauses in ordered
8247 /// directives.
8248 Expr *
8249 buildOrderedLoopData(Scope *S, Expr *Counter,
8250 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8251 SourceLocation Loc, Expr *Inc = nullptr,
8252 OverloadedOperatorKind OOK = OO_Amp);
8253 /// Builds the minimum value for the loop counter.
8254 std::pair<Expr *, Expr *> buildMinMaxValues(
8255 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8256 /// Builds final condition for the non-rectangular loops.
8257 Expr *buildFinalCondition(Scope *S) const;
8258 /// Return true if any expression is dependent.
8259 bool dependent() const;
8260 /// Returns true if the initializer forms non-rectangular loop.
8261 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8262 /// Returns true if the condition forms non-rectangular loop.
8263 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8264 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8265 unsigned getLoopDependentIdx() const {
8266 return InitDependOnLC.value_or(u: CondDependOnLC.value_or(u: 0));
8267 }
8268
8269private:
8270 /// Check the right-hand side of an assignment in the increment
8271 /// expression.
8272 bool checkAndSetIncRHS(Expr *RHS);
8273 /// Helper to set loop counter variable and its initializer.
8274 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8275 bool EmitDiags);
8276 /// Helper to set upper bound.
8277 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8278 SourceRange SR, SourceLocation SL);
8279 /// Helper to set loop increment.
8280 bool setStep(Expr *NewStep, bool Subtract);
8281};
8282
8283bool OpenMPIterationSpaceChecker::dependent() const {
8284 if (!LCDecl) {
8285 assert(!LB && !UB && !Step);
8286 return false;
8287 }
8288 return LCDecl->getType()->isDependentType() ||
8289 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8290 (Step && Step->isValueDependent());
8291}
8292
8293bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8294 Expr *NewLCRefExpr,
8295 Expr *NewLB, bool EmitDiags) {
8296 // State consistency checking to ensure correct usage.
8297 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8298 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8299 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8300 return true;
8301 LCDecl = getCanonicalDecl(D: NewLCDecl);
8302 LCRef = NewLCRefExpr;
8303 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(Val: NewLB))
8304 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8305 if ((Ctor->isCopyOrMoveConstructor() ||
8306 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8307 CE->getNumArgs() > 0 && CE->getArg(Arg: 0) != nullptr)
8308 NewLB = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
8309 LB = NewLB;
8310 if (EmitDiags)
8311 InitDependOnLC = doesDependOnLoopCounter(S: LB, /*IsInitializer=*/true);
8312 return false;
8313}
8314
8315bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8316 bool StrictOp, SourceRange SR,
8317 SourceLocation SL) {
8318 // State consistency checking to ensure correct usage.
8319 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8320 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8321 if (!NewUB || NewUB->containsErrors())
8322 return true;
8323 UB = NewUB;
8324 if (LessOp)
8325 TestIsLessOp = LessOp;
8326 TestIsStrictOp = StrictOp;
8327 ConditionSrcRange = SR;
8328 ConditionLoc = SL;
8329 CondDependOnLC = doesDependOnLoopCounter(S: UB, /*IsInitializer=*/false);
8330 return false;
8331}
8332
8333bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8334 // State consistency checking to ensure correct usage.
8335 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8336 if (!NewStep || NewStep->containsErrors())
8337 return true;
8338 if (!NewStep->isValueDependent()) {
8339 // Check that the step is integer expression.
8340 SourceLocation StepLoc = NewStep->getBeginLoc();
8341 ExprResult Val = SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(
8342 OpLoc: StepLoc, Op: getExprAsWritten(E: NewStep));
8343 if (Val.isInvalid())
8344 return true;
8345 NewStep = Val.get();
8346
8347 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8348 // If test-expr is of form var relational-op b and relational-op is < or
8349 // <= then incr-expr must cause var to increase on each iteration of the
8350 // loop. If test-expr is of form var relational-op b and relational-op is
8351 // > or >= then incr-expr must cause var to decrease on each iteration of
8352 // the loop.
8353 // If test-expr is of form b relational-op var and relational-op is < or
8354 // <= then incr-expr must cause var to decrease on each iteration of the
8355 // loop. If test-expr is of form b relational-op var and relational-op is
8356 // > or >= then incr-expr must cause var to increase on each iteration of
8357 // the loop.
8358 std::optional<llvm::APSInt> Result =
8359 NewStep->getIntegerConstantExpr(Ctx: SemaRef.Context);
8360 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8361 bool IsConstNeg =
8362 Result && Result->isSigned() && (Subtract != Result->isNegative());
8363 bool IsConstPos =
8364 Result && Result->isSigned() && (Subtract == Result->isNegative());
8365 bool IsConstZero = Result && !Result->getBoolValue();
8366
8367 // != with increment is treated as <; != with decrement is treated as >
8368 if (!TestIsLessOp)
8369 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8370 if (UB && (IsConstZero ||
8371 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8372 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8373 SemaRef.Diag(Loc: NewStep->getExprLoc(),
8374 DiagID: diag::err_omp_loop_incr_not_compatible)
8375 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8376 SemaRef.Diag(Loc: ConditionLoc,
8377 DiagID: diag::note_omp_loop_cond_requires_compatible_incr)
8378 << *TestIsLessOp << ConditionSrcRange;
8379 return true;
8380 }
8381 if (*TestIsLessOp == Subtract) {
8382 NewStep =
8383 SemaRef.CreateBuiltinUnaryOp(OpLoc: NewStep->getExprLoc(), Opc: UO_Minus, InputExpr: NewStep)
8384 .get();
8385 Subtract = !Subtract;
8386 }
8387 }
8388
8389 Step = NewStep;
8390 SubtractStep = Subtract;
8391 return false;
8392}
8393
8394namespace {
8395/// Checker for the non-rectangular loops. Checks if the initializer or
8396/// condition expression references loop counter variable.
8397class LoopCounterRefChecker final
8398 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8399 Sema &SemaRef;
8400 DSAStackTy &Stack;
8401 const ValueDecl *CurLCDecl = nullptr;
8402 const ValueDecl *DepDecl = nullptr;
8403 const ValueDecl *PrevDepDecl = nullptr;
8404 bool IsInitializer = true;
8405 bool SupportsNonRectangular;
8406 unsigned BaseLoopId = 0;
8407 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8408 if (getCanonicalDecl(D: VD) == getCanonicalDecl(D: CurLCDecl)) {
8409 SemaRef.Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_stmt_depends_on_loop_counter)
8410 << (IsInitializer ? 0 : 1);
8411 return false;
8412 }
8413 const auto &&Data = Stack.isLoopControlVariable(D: VD);
8414 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8415 // The type of the loop iterator on which we depend may not have a random
8416 // access iterator type.
8417 if (Data.first && VD->getType()->isRecordType()) {
8418 SmallString<128> Name;
8419 llvm::raw_svector_ostream OS(Name);
8420 VD->getNameForDiagnostic(OS, Policy: SemaRef.getPrintingPolicy(),
8421 /*Qualified=*/true);
8422 SemaRef.Diag(Loc: E->getExprLoc(),
8423 DiagID: diag::err_omp_wrong_dependency_iterator_type)
8424 << OS.str();
8425 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::note_previous_decl) << VD;
8426 return false;
8427 }
8428 if (Data.first && !SupportsNonRectangular) {
8429 SemaRef.Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_invariant_dependency);
8430 return false;
8431 }
8432 if (Data.first &&
8433 (DepDecl || (PrevDepDecl &&
8434 getCanonicalDecl(D: VD) != getCanonicalDecl(D: PrevDepDecl)))) {
8435 if (!DepDecl && PrevDepDecl)
8436 DepDecl = PrevDepDecl;
8437 SmallString<128> Name;
8438 llvm::raw_svector_ostream OS(Name);
8439 DepDecl->getNameForDiagnostic(OS, Policy: SemaRef.getPrintingPolicy(),
8440 /*Qualified=*/true);
8441 SemaRef.Diag(Loc: E->getExprLoc(),
8442 DiagID: diag::err_omp_invariant_or_linear_dependency)
8443 << OS.str();
8444 return false;
8445 }
8446 if (Data.first) {
8447 DepDecl = VD;
8448 BaseLoopId = Data.first;
8449 }
8450 return Data.first;
8451 }
8452
8453public:
8454 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8455 const ValueDecl *VD = E->getDecl();
8456 if (isa<VarDecl>(Val: VD))
8457 return checkDecl(E, VD);
8458 return false;
8459 }
8460 bool VisitMemberExpr(const MemberExpr *E) {
8461 if (isa<CXXThisExpr>(Val: E->getBase()->IgnoreParens())) {
8462 const ValueDecl *VD = E->getMemberDecl();
8463 if (isa<VarDecl>(Val: VD) || isa<FieldDecl>(Val: VD))
8464 return checkDecl(E, VD);
8465 }
8466 return false;
8467 }
8468 bool VisitStmt(const Stmt *S) {
8469 bool Res = false;
8470 for (const Stmt *Child : S->children())
8471 Res = (Child && Visit(S: Child)) || Res;
8472 return Res;
8473 }
8474 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8475 const ValueDecl *CurLCDecl, bool IsInitializer,
8476 const ValueDecl *PrevDepDecl = nullptr,
8477 bool SupportsNonRectangular = true)
8478 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8479 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8480 SupportsNonRectangular(SupportsNonRectangular) {}
8481 unsigned getBaseLoopId() const {
8482 assert(CurLCDecl && "Expected loop dependency.");
8483 return BaseLoopId;
8484 }
8485 const ValueDecl *getDepDecl() const {
8486 assert(CurLCDecl && "Expected loop dependency.");
8487 return DepDecl;
8488 }
8489};
8490} // namespace
8491
8492std::optional<unsigned>
8493OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8494 bool IsInitializer) {
8495 // Check for the non-rectangular loops.
8496 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8497 DepDecl, SupportsNonRectangular);
8498 if (LoopStmtChecker.Visit(S)) {
8499 DepDecl = LoopStmtChecker.getDepDecl();
8500 return LoopStmtChecker.getBaseLoopId();
8501 }
8502 return std::nullopt;
8503}
8504
8505bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8506 // Check init-expr for canonical loop form and save loop counter
8507 // variable - #Var and its initialization value - #LB.
8508 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8509 // var = lb
8510 // integer-type var = lb
8511 // random-access-iterator-type var = lb
8512 // pointer-type var = lb
8513 //
8514 if (!S) {
8515 if (EmitDiags) {
8516 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_init);
8517 }
8518 return true;
8519 }
8520 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: S))
8521 if (!ExprTemp->cleanupsHaveSideEffects())
8522 S = ExprTemp->getSubExpr();
8523
8524 if (!CollapsedLoopVarDecls.empty()) {
8525 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8526 if (!FSEC.TraverseStmt(S)) {
8527 SourceRange Range = FSEC.getErrRange();
8528 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
8529 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8530 return true;
8531 }
8532 }
8533
8534 // Helper lambda to check if a loop variable is already used in an outer
8535 // loop.
8536 auto CheckLoopVarReuse = [&](ValueDecl *LoopVar, SourceLocation Loc) -> bool {
8537 if (EmitDiags &&
8538 CollapsedLoopInductionVars.count(Ptr: LoopVar->getCanonicalDecl())) {
8539 SemaRef.Diag(Loc, DiagID: diag::err_omp_loop_var_reused_in_collapsed_loop)
8540 << LoopVar;
8541 return true;
8542 }
8543 return false;
8544 };
8545
8546 InitSrcRange = S->getSourceRange();
8547 if (Expr *E = dyn_cast<Expr>(Val: S))
8548 S = E->IgnoreParens();
8549 if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8550 if (BO->getOpcode() == BO_Assign) {
8551 Expr *LHS = BO->getLHS()->IgnoreParens();
8552 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS)) {
8553 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: DRE->getDecl()))
8554 if (auto *ME =
8555 dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit()))) {
8556 ValueDecl *LoopVar = ME->getMemberDecl();
8557 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8558 return true;
8559 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: BO->getRHS(), EmitDiags);
8560 }
8561 ValueDecl *LoopVar = DRE->getDecl();
8562 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8563 return true;
8564 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: DRE, NewLB: BO->getRHS(), EmitDiags);
8565 }
8566 if (auto *ME = dyn_cast<MemberExpr>(Val: LHS)) {
8567 if (ME->isArrow() &&
8568 isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts())) {
8569 ValueDecl *LoopVar = ME->getMemberDecl();
8570 if (CheckLoopVarReuse(LoopVar, LHS->getBeginLoc()))
8571 return true;
8572 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: BO->getRHS(), EmitDiags);
8573 }
8574 }
8575 }
8576 } else if (auto *DS = dyn_cast<DeclStmt>(Val: S)) {
8577 if (DS->isSingleDecl()) {
8578 if (auto *Var = dyn_cast_or_null<VarDecl>(Val: DS->getSingleDecl())) {
8579 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8580 // Accept non-canonical init form here but emit ext. warning.
8581 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8582 SemaRef.Diag(Loc: S->getBeginLoc(),
8583 DiagID: diag::ext_omp_loop_not_canonical_init)
8584 << S->getSourceRange();
8585 if (CheckLoopVarReuse(Var, Var->getLocation()))
8586 return true;
8587 return setLCDeclAndLB(
8588 NewLCDecl: Var,
8589 NewLCRefExpr: buildDeclRefExpr(S&: SemaRef, D: Var,
8590 Ty: Var->getType().getNonReferenceType(),
8591 Loc: DS->getBeginLoc()),
8592 NewLB: Var->getInit(), EmitDiags);
8593 }
8594 }
8595 }
8596 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8597 if (CE->getOperator() == OO_Equal) {
8598 Expr *LHS = CE->getArg(Arg: 0);
8599 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS)) {
8600 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: DRE->getDecl()))
8601 if (auto *ME =
8602 dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit()))) {
8603 ValueDecl *LoopVar = ME->getMemberDecl();
8604 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8605 return true;
8606 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: CE->getArg(Arg: 1), EmitDiags);
8607 }
8608 ValueDecl *LoopVar = DRE->getDecl();
8609 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8610 return true;
8611 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: DRE, NewLB: CE->getArg(Arg: 1), EmitDiags);
8612 }
8613 if (auto *ME = dyn_cast<MemberExpr>(Val: LHS)) {
8614 if (ME->isArrow() &&
8615 isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts())) {
8616 ValueDecl *LoopVar = ME->getMemberDecl();
8617 if (CheckLoopVarReuse(LoopVar, LHS->getBeginLoc()))
8618 return true;
8619 return setLCDeclAndLB(NewLCDecl: LoopVar, NewLCRefExpr: ME, NewLB: CE->getArg(Arg: 1), EmitDiags);
8620 }
8621 }
8622 }
8623 }
8624
8625 if (dependent() || SemaRef.CurContext->isDependentContext())
8626 return false;
8627 if (EmitDiags) {
8628 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_init)
8629 << S->getSourceRange();
8630 }
8631 return true;
8632}
8633
8634/// Ignore parenthesizes, implicit casts, copy constructor and return the
8635/// variable (which may be the loop variable) if possible.
8636static const ValueDecl *getInitLCDecl(const Expr *E) {
8637 if (!E)
8638 return nullptr;
8639 E = getExprAsWritten(E);
8640 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(Val: E))
8641 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8642 if ((Ctor->isCopyOrMoveConstructor() ||
8643 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8644 CE->getNumArgs() > 0 && CE->getArg(Arg: 0) != nullptr)
8645 E = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
8646 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(Val: E)) {
8647 if (const auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
8648 return getCanonicalDecl(D: VD);
8649 }
8650 if (const auto *ME = dyn_cast_or_null<MemberExpr>(Val: E))
8651 if (ME->isArrow() && isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
8652 return getCanonicalDecl(D: ME->getMemberDecl());
8653 return nullptr;
8654}
8655
8656bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8657 // Check test-expr for canonical form, save upper-bound UB, flags for
8658 // less/greater and for strict/non-strict comparison.
8659 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8660 // var relational-op b
8661 // b relational-op var
8662 //
8663 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8664 if (!S) {
8665 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_cond)
8666 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8667 return true;
8668 }
8669 Condition = S;
8670 S = getExprAsWritten(E: S);
8671
8672 if (!CollapsedLoopVarDecls.empty()) {
8673 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8674 if (!FSEC.TraverseStmt(S)) {
8675 SourceRange Range = FSEC.getErrRange();
8676 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
8677 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8678 return true;
8679 }
8680 }
8681
8682 SourceLocation CondLoc = S->getBeginLoc();
8683 auto &&CheckAndSetCond =
8684 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8685 const Expr *RHS, SourceRange SR,
8686 SourceLocation OpLoc) -> std::optional<bool> {
8687 if (BinaryOperator::isRelationalOp(Opc: Opcode)) {
8688 if (getInitLCDecl(E: LHS) == LCDecl)
8689 return setUB(NewUB: const_cast<Expr *>(RHS),
8690 LessOp: (Opcode == BO_LT || Opcode == BO_LE),
8691 StrictOp: (Opcode == BO_LT || Opcode == BO_GT), SR, SL: OpLoc);
8692 if (getInitLCDecl(E: RHS) == LCDecl)
8693 return setUB(NewUB: const_cast<Expr *>(LHS),
8694 LessOp: (Opcode == BO_GT || Opcode == BO_GE),
8695 StrictOp: (Opcode == BO_LT || Opcode == BO_GT), SR, SL: OpLoc);
8696 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8697 return setUB(NewUB: const_cast<Expr *>(getInitLCDecl(E: LHS) == LCDecl ? RHS : LHS),
8698 /*LessOp=*/std::nullopt,
8699 /*StrictOp=*/true, SR, SL: OpLoc);
8700 }
8701 return std::nullopt;
8702 };
8703 std::optional<bool> Res;
8704 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(Val: S)) {
8705 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8706 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8707 RBO->getOperatorLoc());
8708 } else if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8709 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8710 BO->getSourceRange(), BO->getOperatorLoc());
8711 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8712 if (CE->getNumArgs() == 2) {
8713 Res = CheckAndSetCond(
8714 BinaryOperator::getOverloadedOpcode(OO: CE->getOperator()), CE->getArg(Arg: 0),
8715 CE->getArg(Arg: 1), CE->getSourceRange(), CE->getOperatorLoc());
8716 }
8717 }
8718 if (Res)
8719 return *Res;
8720 if (dependent() || SemaRef.CurContext->isDependentContext())
8721 return false;
8722 SemaRef.Diag(Loc: CondLoc, DiagID: diag::err_omp_loop_not_canonical_cond)
8723 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8724 return true;
8725}
8726
8727bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8728 // RHS of canonical loop form increment can be:
8729 // var + incr
8730 // incr + var
8731 // var - incr
8732 //
8733 RHS = RHS->IgnoreParenImpCasts();
8734 if (auto *BO = dyn_cast<BinaryOperator>(Val: RHS)) {
8735 if (BO->isAdditiveOp()) {
8736 bool IsAdd = BO->getOpcode() == BO_Add;
8737 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8738 return setStep(NewStep: BO->getRHS(), Subtract: !IsAdd);
8739 if (IsAdd && getInitLCDecl(E: BO->getRHS()) == LCDecl)
8740 return setStep(NewStep: BO->getLHS(), /*Subtract=*/false);
8741 }
8742 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: RHS)) {
8743 bool IsAdd = CE->getOperator() == OO_Plus;
8744 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8745 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8746 return setStep(NewStep: CE->getArg(Arg: 1), Subtract: !IsAdd);
8747 if (IsAdd && getInitLCDecl(E: CE->getArg(Arg: 1)) == LCDecl)
8748 return setStep(NewStep: CE->getArg(Arg: 0), /*Subtract=*/false);
8749 }
8750 }
8751 if (dependent() || SemaRef.CurContext->isDependentContext())
8752 return false;
8753 SemaRef.Diag(Loc: RHS->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_incr)
8754 << RHS->getSourceRange() << LCDecl;
8755 return true;
8756}
8757
8758bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8759 // Check incr-expr for canonical loop form and return true if it
8760 // does not conform.
8761 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8762 // ++var
8763 // var++
8764 // --var
8765 // var--
8766 // var += incr
8767 // var -= incr
8768 // var = var + incr
8769 // var = incr + var
8770 // var = var - incr
8771 //
8772 if (!S) {
8773 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_incr) << LCDecl;
8774 return true;
8775 }
8776 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: S))
8777 if (!ExprTemp->cleanupsHaveSideEffects())
8778 S = ExprTemp->getSubExpr();
8779
8780 if (!CollapsedLoopVarDecls.empty()) {
8781 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8782 if (!FSEC.TraverseStmt(S)) {
8783 SourceRange Range = FSEC.getErrRange();
8784 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
8785 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8786 return true;
8787 }
8788 }
8789
8790 IncrementSrcRange = S->getSourceRange();
8791 S = S->IgnoreParens();
8792 if (auto *UO = dyn_cast<UnaryOperator>(Val: S)) {
8793 if (UO->isIncrementDecrementOp() &&
8794 getInitLCDecl(E: UO->getSubExpr()) == LCDecl)
8795 return setStep(NewStep: SemaRef
8796 .ActOnIntegerConstant(Loc: UO->getBeginLoc(),
8797 Val: (UO->isDecrementOp() ? -1 : 1))
8798 .get(),
8799 /*Subtract=*/false);
8800 } else if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8801 switch (BO->getOpcode()) {
8802 case BO_AddAssign:
8803 case BO_SubAssign:
8804 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8805 return setStep(NewStep: BO->getRHS(), Subtract: BO->getOpcode() == BO_SubAssign);
8806 break;
8807 case BO_Assign:
8808 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8809 return checkAndSetIncRHS(RHS: BO->getRHS());
8810 break;
8811 default:
8812 break;
8813 }
8814 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8815 switch (CE->getOperator()) {
8816 case OO_PlusPlus:
8817 case OO_MinusMinus:
8818 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8819 return setStep(NewStep: SemaRef
8820 .ActOnIntegerConstant(
8821 Loc: CE->getBeginLoc(),
8822 Val: ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8823 .get(),
8824 /*Subtract=*/false);
8825 break;
8826 case OO_PlusEqual:
8827 case OO_MinusEqual:
8828 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8829 return setStep(NewStep: CE->getArg(Arg: 1), Subtract: CE->getOperator() == OO_MinusEqual);
8830 break;
8831 case OO_Equal:
8832 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8833 return checkAndSetIncRHS(RHS: CE->getArg(Arg: 1));
8834 break;
8835 default:
8836 break;
8837 }
8838 }
8839 if (dependent() || SemaRef.CurContext->isDependentContext())
8840 return false;
8841 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_incr)
8842 << S->getSourceRange() << LCDecl;
8843 return true;
8844}
8845
8846static ExprResult
8847tryBuildCapture(Sema &SemaRef, Expr *Capture,
8848 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8849 StringRef Name = ".capture_expr.") {
8850 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8851 return Capture;
8852 if (Capture->isEvaluatable(Ctx: SemaRef.Context, AllowSideEffects: Expr::SE_AllowSideEffects))
8853 return SemaRef.PerformImplicitConversion(From: Capture->IgnoreImpCasts(),
8854 ToType: Capture->getType(),
8855 Action: AssignmentAction::Converting,
8856 /*AllowExplicit=*/true);
8857 auto I = Captures.find(Key: Capture);
8858 if (I != Captures.end())
8859 return buildCapture(S&: SemaRef, CaptureExpr: Capture, Ref&: I->second, Name);
8860 DeclRefExpr *Ref = nullptr;
8861 ExprResult Res = buildCapture(S&: SemaRef, CaptureExpr: Capture, Ref, Name);
8862 Captures[Capture] = Ref;
8863 return Res;
8864}
8865
8866/// Calculate number of iterations, transforming to unsigned, if number of
8867/// iterations may be larger than the original type.
8868static Expr *
8869calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8870 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8871 bool TestIsStrictOp, bool RoundToStep,
8872 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8873 std::optional<unsigned> InitDependOnLC,
8874 std::optional<unsigned> CondDependOnLC) {
8875 ExprResult NewStep = tryBuildCapture(SemaRef, Capture: Step, Captures, Name: ".new_step");
8876 if (!NewStep.isUsable())
8877 return nullptr;
8878 llvm::APSInt LRes, SRes;
8879 bool IsLowerConst = false, IsStepConst = false;
8880 if (std::optional<llvm::APSInt> Res =
8881 Lower->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8882 LRes = *Res;
8883 IsLowerConst = true;
8884 }
8885 if (std::optional<llvm::APSInt> Res =
8886 Step->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8887 SRes = *Res;
8888 IsStepConst = true;
8889 }
8890 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8891 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8892 (TestIsStrictOp && LRes.isStrictlyPositive()));
8893 bool NeedToReorganize = false;
8894 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8895 if (!NoNeedToConvert && IsLowerConst &&
8896 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8897 NoNeedToConvert = true;
8898 if (RoundToStep) {
8899 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8900 ? LRes.getBitWidth()
8901 : SRes.getBitWidth();
8902 LRes = LRes.extend(width: BW + 1);
8903 LRes.setIsSigned(true);
8904 SRes = SRes.extend(width: BW + 1);
8905 SRes.setIsSigned(true);
8906 LRes -= SRes;
8907 NoNeedToConvert = LRes.trunc(width: BW).extend(width: BW + 1) == LRes;
8908 LRes = LRes.trunc(width: BW);
8909 }
8910 if (TestIsStrictOp) {
8911 unsigned BW = LRes.getBitWidth();
8912 LRes = LRes.extend(width: BW + 1);
8913 LRes.setIsSigned(true);
8914 ++LRes;
8915 NoNeedToConvert =
8916 NoNeedToConvert && LRes.trunc(width: BW).extend(width: BW + 1) == LRes;
8917 // truncate to the original bitwidth.
8918 LRes = LRes.trunc(width: BW);
8919 }
8920 NeedToReorganize = NoNeedToConvert;
8921 }
8922 llvm::APSInt URes;
8923 bool IsUpperConst = false;
8924 if (std::optional<llvm::APSInt> Res =
8925 Upper->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8926 URes = *Res;
8927 IsUpperConst = true;
8928 }
8929 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8930 (!RoundToStep || IsStepConst)) {
8931 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8932 : URes.getBitWidth();
8933 LRes = LRes.extend(width: BW + 1);
8934 LRes.setIsSigned(true);
8935 URes = URes.extend(width: BW + 1);
8936 URes.setIsSigned(true);
8937 URes -= LRes;
8938 NoNeedToConvert = URes.trunc(width: BW).extend(width: BW + 1) == URes;
8939 NeedToReorganize = NoNeedToConvert;
8940 }
8941 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8942 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8943 // unsigned.
8944 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8945 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8946 QualType LowerTy = Lower->getType();
8947 QualType UpperTy = Upper->getType();
8948 uint64_t LowerSize = SemaRef.Context.getTypeSize(T: LowerTy);
8949 uint64_t UpperSize = SemaRef.Context.getTypeSize(T: UpperTy);
8950 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8951 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8952 QualType CastType = SemaRef.Context.getIntTypeForBitwidth(
8953 DestWidth: LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8954 Upper =
8955 SemaRef
8956 .PerformImplicitConversion(
8957 From: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Upper).get(),
8958 ToType: CastType, Action: AssignmentAction::Converting)
8959 .get();
8960 Lower = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Lower).get();
8961 NewStep = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: NewStep.get());
8962 }
8963 }
8964 if (!Lower || !Upper || NewStep.isInvalid())
8965 return nullptr;
8966
8967 ExprResult Diff;
8968
8969 // For nested triangular loops (depth >= 2), use already computed Upper and
8970 // Lower bounds to calculate the number of iterations: Upper - Lower + 1.
8971 // Don't apply to first-level triangular loops as the standard formula handles
8972 // those correctly.
8973 if (TestIsStrictOp && InitDependOnLC.has_value() &&
8974 InitDependOnLC.value() >= 2 && !CondDependOnLC.has_value()) {
8975 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Lower);
8976 if (!Diff.isUsable())
8977 return nullptr;
8978
8979 Diff =
8980 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(),
8981 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: DefaultLoc, Val: 1).get());
8982 if (!Diff.isUsable())
8983 return nullptr;
8984
8985 return Diff.get();
8986 }
8987
8988 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8989 // 1]).
8990 if (NeedToReorganize) {
8991 Diff = Lower;
8992
8993 if (RoundToStep) {
8994 // Lower - Step
8995 Diff =
8996 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8997 if (!Diff.isUsable())
8998 return nullptr;
8999 }
9000
9001 // Lower - Step [+ 1]
9002 if (TestIsStrictOp)
9003 Diff = SemaRef.BuildBinOp(
9004 S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(),
9005 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
9006 if (!Diff.isUsable())
9007 return nullptr;
9008
9009 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9010 if (!Diff.isUsable())
9011 return nullptr;
9012
9013 // Upper - (Lower - Step [+ 1]).
9014 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Diff.get());
9015 if (!Diff.isUsable())
9016 return nullptr;
9017 } else {
9018 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Lower);
9019
9020 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
9021 // BuildBinOp already emitted error, this one is to point user to upper
9022 // and lower bound, and to tell what is passed to 'operator-'.
9023 SemaRef.Diag(Loc: Upper->getBeginLoc(), DiagID: diag::err_omp_loop_diff_cxx)
9024 << Upper->getSourceRange() << Lower->getSourceRange();
9025 return nullptr;
9026 }
9027
9028 if (!Diff.isUsable())
9029 return nullptr;
9030
9031 // Upper - Lower [- 1]
9032 if (TestIsStrictOp)
9033 Diff = SemaRef.BuildBinOp(
9034 S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Diff.get(),
9035 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
9036 if (!Diff.isUsable())
9037 return nullptr;
9038
9039 if (RoundToStep) {
9040 // Upper - Lower [- 1] + Step
9041 Diff =
9042 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
9043 if (!Diff.isUsable())
9044 return nullptr;
9045 }
9046 }
9047
9048 // Parentheses (for dumping/debugging purposes only).
9049 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9050 if (!Diff.isUsable())
9051 return nullptr;
9052
9053 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
9054 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Div, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
9055 if (!Diff.isUsable())
9056 return nullptr;
9057
9058 return Diff.get();
9059}
9060
9061/// Build the expression to calculate the number of iterations.
9062Expr *OpenMPIterationSpaceChecker::buildNumIterations(
9063 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
9064 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9065 QualType VarType = LCDecl->getType().getNonReferenceType();
9066 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9067 !SemaRef.getLangOpts().CPlusPlus)
9068 return nullptr;
9069 Expr *LBVal = LB;
9070 Expr *UBVal = UB;
9071 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
9072 // max(LB(MinVal), LB(MaxVal)))
9073 if (InitDependOnLC) {
9074 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
9075 if (!IS.MinValue || !IS.MaxValue)
9076 return nullptr;
9077 // OuterVar = Min
9078 ExprResult MinValue =
9079 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MinValue);
9080 if (!MinValue.isUsable())
9081 return nullptr;
9082
9083 ExprResult LBMinVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9084 LHSExpr: IS.CounterVar, RHSExpr: MinValue.get());
9085 if (!LBMinVal.isUsable())
9086 return nullptr;
9087 // OuterVar = Min, LBVal
9088 LBMinVal =
9089 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: LBMinVal.get(), RHSExpr: LBVal);
9090 if (!LBMinVal.isUsable())
9091 return nullptr;
9092 // (OuterVar = Min, LBVal)
9093 LBMinVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: LBMinVal.get());
9094 if (!LBMinVal.isUsable())
9095 return nullptr;
9096
9097 // OuterVar = Max
9098 ExprResult MaxValue =
9099 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MaxValue);
9100 if (!MaxValue.isUsable())
9101 return nullptr;
9102
9103 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9104 LHSExpr: IS.CounterVar, RHSExpr: MaxValue.get());
9105 if (!LBMaxVal.isUsable())
9106 return nullptr;
9107 // OuterVar = Max, LBVal
9108 LBMaxVal =
9109 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: LBMaxVal.get(), RHSExpr: LBVal);
9110 if (!LBMaxVal.isUsable())
9111 return nullptr;
9112 // (OuterVar = Max, LBVal)
9113 LBMaxVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: LBMaxVal.get());
9114 if (!LBMaxVal.isUsable())
9115 return nullptr;
9116
9117 Expr *LBMin =
9118 tryBuildCapture(SemaRef, Capture: LBMinVal.get(), Captures, Name: ".lb_min").get();
9119 Expr *LBMax =
9120 tryBuildCapture(SemaRef, Capture: LBMaxVal.get(), Captures, Name: ".lb_max").get();
9121 if (!LBMin || !LBMax)
9122 return nullptr;
9123 // LB(MinVal) < LB(MaxVal)
9124 ExprResult MinLessMaxRes =
9125 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_LT, LHSExpr: LBMin, RHSExpr: LBMax);
9126 if (!MinLessMaxRes.isUsable())
9127 return nullptr;
9128 Expr *MinLessMax =
9129 tryBuildCapture(SemaRef, Capture: MinLessMaxRes.get(), Captures, Name: ".min_less_max")
9130 .get();
9131 if (!MinLessMax)
9132 return nullptr;
9133 if (*TestIsLessOp) {
9134 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
9135 // LB(MaxVal))
9136 ExprResult MinLB = SemaRef.ActOnConditionalOp(QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc,
9137 CondExpr: MinLessMax, LHSExpr: LBMin, RHSExpr: LBMax);
9138 if (!MinLB.isUsable())
9139 return nullptr;
9140 LBVal = MinLB.get();
9141 } else {
9142 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
9143 // LB(MaxVal))
9144 ExprResult MaxLB = SemaRef.ActOnConditionalOp(QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc,
9145 CondExpr: MinLessMax, LHSExpr: LBMax, RHSExpr: LBMin);
9146 if (!MaxLB.isUsable())
9147 return nullptr;
9148 LBVal = MaxLB.get();
9149 }
9150 // OuterVar = LB
9151 LBMinVal =
9152 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign, LHSExpr: IS.CounterVar, RHSExpr: LBVal);
9153 if (!LBMinVal.isUsable())
9154 return nullptr;
9155 LBVal = LBMinVal.get();
9156 }
9157 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
9158 // min(UB(MinVal), UB(MaxVal))
9159 if (CondDependOnLC) {
9160 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
9161 if (!IS.MinValue || !IS.MaxValue)
9162 return nullptr;
9163 // OuterVar = Min
9164 ExprResult MinValue =
9165 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MinValue);
9166 if (!MinValue.isUsable())
9167 return nullptr;
9168
9169 ExprResult UBMinVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9170 LHSExpr: IS.CounterVar, RHSExpr: MinValue.get());
9171 if (!UBMinVal.isUsable())
9172 return nullptr;
9173 // OuterVar = Min, UBVal
9174 UBMinVal =
9175 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: UBMinVal.get(), RHSExpr: UBVal);
9176 if (!UBMinVal.isUsable())
9177 return nullptr;
9178 // (OuterVar = Min, UBVal)
9179 UBMinVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: UBMinVal.get());
9180 if (!UBMinVal.isUsable())
9181 return nullptr;
9182
9183 // OuterVar = Max
9184 ExprResult MaxValue =
9185 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MaxValue);
9186 if (!MaxValue.isUsable())
9187 return nullptr;
9188
9189 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
9190 LHSExpr: IS.CounterVar, RHSExpr: MaxValue.get());
9191 if (!UBMaxVal.isUsable())
9192 return nullptr;
9193 // OuterVar = Max, UBVal
9194 UBMaxVal =
9195 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: UBMaxVal.get(), RHSExpr: UBVal);
9196 if (!UBMaxVal.isUsable())
9197 return nullptr;
9198 // (OuterVar = Max, UBVal)
9199 UBMaxVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: UBMaxVal.get());
9200 if (!UBMaxVal.isUsable())
9201 return nullptr;
9202
9203 Expr *UBMin =
9204 tryBuildCapture(SemaRef, Capture: UBMinVal.get(), Captures, Name: ".ub_min").get();
9205 Expr *UBMax =
9206 tryBuildCapture(SemaRef, Capture: UBMaxVal.get(), Captures, Name: ".ub_max").get();
9207 if (!UBMin || !UBMax)
9208 return nullptr;
9209 // UB(MinVal) > UB(MaxVal)
9210 ExprResult MinGreaterMaxRes =
9211 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_GT, LHSExpr: UBMin, RHSExpr: UBMax);
9212 if (!MinGreaterMaxRes.isUsable())
9213 return nullptr;
9214 Expr *MinGreaterMax = tryBuildCapture(SemaRef, Capture: MinGreaterMaxRes.get(),
9215 Captures, Name: ".min_greater_max")
9216 .get();
9217 if (!MinGreaterMax)
9218 return nullptr;
9219 if (*TestIsLessOp) {
9220 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
9221 // UB(MaxVal))
9222 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
9223 QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc, CondExpr: MinGreaterMax, LHSExpr: UBMin, RHSExpr: UBMax);
9224 if (!MaxUB.isUsable())
9225 return nullptr;
9226 UBVal = MaxUB.get();
9227 } else {
9228 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9229 // UB(MaxVal))
9230 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9231 QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc, CondExpr: MinGreaterMax, LHSExpr: UBMax, RHSExpr: UBMin);
9232 if (!MinUB.isUsable())
9233 return nullptr;
9234 UBVal = MinUB.get();
9235 }
9236 }
9237 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9238 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9239 Expr *Upper = tryBuildCapture(SemaRef, Capture: UBExpr, Captures, Name: ".upper").get();
9240 Expr *Lower = tryBuildCapture(SemaRef, Capture: LBExpr, Captures, Name: ".lower").get();
9241 if (!Upper || !Lower)
9242 return nullptr;
9243
9244 ExprResult Diff = calculateNumIters(
9245 SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType, TestIsStrictOp,
9246 /*RoundToStep=*/true, Captures, InitDependOnLC, CondDependOnLC);
9247 if (!Diff.isUsable())
9248 return nullptr;
9249
9250 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9251 QualType Type = Diff.get()->getType();
9252 ASTContext &C = SemaRef.Context;
9253 bool UseVarType = VarType->hasIntegerRepresentation() &&
9254 C.getTypeSize(T: Type) > C.getTypeSize(T: VarType);
9255 if (!Type->isIntegerType() || UseVarType) {
9256 unsigned NewSize =
9257 UseVarType ? C.getTypeSize(T: VarType) : C.getTypeSize(T: Type);
9258 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9259 : Type->hasSignedIntegerRepresentation();
9260 Type = C.getIntTypeForBitwidth(DestWidth: NewSize, Signed: IsSigned);
9261 if (!SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: Type)) {
9262 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: Type,
9263 Action: AssignmentAction::Converting,
9264 /*AllowExplicit=*/true);
9265 if (!Diff.isUsable())
9266 return nullptr;
9267 }
9268 }
9269 if (LimitedType) {
9270 unsigned NewSize = (C.getTypeSize(T: Type) > 32) ? 64 : 32;
9271 if (NewSize != C.getTypeSize(T: Type)) {
9272 if (NewSize < C.getTypeSize(T: Type)) {
9273 assert(NewSize == 64 && "incorrect loop var size");
9274 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::warn_omp_loop_64_bit_var)
9275 << InitSrcRange << ConditionSrcRange;
9276 }
9277 QualType NewType = C.getIntTypeForBitwidth(
9278 DestWidth: NewSize, Signed: Type->hasSignedIntegerRepresentation() ||
9279 C.getTypeSize(T: Type) < NewSize);
9280 if (!SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: NewType)) {
9281 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: NewType,
9282 Action: AssignmentAction::Converting,
9283 /*AllowExplicit=*/true);
9284 if (!Diff.isUsable())
9285 return nullptr;
9286 }
9287 }
9288 }
9289
9290 return Diff.get();
9291}
9292
9293std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9294 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9295 // Do not build for iterators, they cannot be used in non-rectangular loop
9296 // nests.
9297 if (LCDecl->getType()->isRecordType())
9298 return std::make_pair(x: nullptr, y: nullptr);
9299 // If we subtract, the min is in the condition, otherwise the min is in the
9300 // init value.
9301 Expr *MinExpr = nullptr;
9302 Expr *MaxExpr = nullptr;
9303 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9304 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9305 bool LBNonRect =
9306 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9307 bool UBNonRect =
9308 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9309 Expr *Lower =
9310 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, Capture: LBExpr, Captures).get();
9311 Expr *Upper =
9312 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, Capture: UBExpr, Captures).get();
9313 if (!Upper || !Lower)
9314 return std::make_pair(x: nullptr, y: nullptr);
9315
9316 if (*TestIsLessOp)
9317 MinExpr = Lower;
9318 else
9319 MaxExpr = Upper;
9320
9321 // Build minimum/maximum value based on number of iterations.
9322 QualType VarType = LCDecl->getType().getNonReferenceType();
9323
9324 ExprResult Diff = calculateNumIters(
9325 SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType, TestIsStrictOp,
9326 /*RoundToStep=*/false, Captures, InitDependOnLC, CondDependOnLC);
9327
9328 if (!Diff.isUsable())
9329 return std::make_pair(x: nullptr, y: nullptr);
9330
9331 // ((Upper - Lower [- 1]) / Step) * Step
9332 // Parentheses (for dumping/debugging purposes only).
9333 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9334 if (!Diff.isUsable())
9335 return std::make_pair(x: nullptr, y: nullptr);
9336
9337 ExprResult NewStep = tryBuildCapture(SemaRef, Capture: Step, Captures, Name: ".new_step");
9338 if (!NewStep.isUsable())
9339 return std::make_pair(x: nullptr, y: nullptr);
9340 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Mul, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
9341 if (!Diff.isUsable())
9342 return std::make_pair(x: nullptr, y: nullptr);
9343
9344 // Parentheses (for dumping/debugging purposes only).
9345 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9346 if (!Diff.isUsable())
9347 return std::make_pair(x: nullptr, y: nullptr);
9348
9349 // Convert to the ptrdiff_t, if original type is pointer.
9350 if (VarType->isAnyPointerType() &&
9351 !SemaRef.Context.hasSameType(
9352 T1: Diff.get()->getType(),
9353 T2: SemaRef.Context.getUnsignedPointerDiffType())) {
9354 Diff = SemaRef.PerformImplicitConversion(
9355 From: Diff.get(), ToType: SemaRef.Context.getUnsignedPointerDiffType(),
9356 Action: AssignmentAction::Converting, /*AllowExplicit=*/true);
9357 }
9358 if (!Diff.isUsable())
9359 return std::make_pair(x: nullptr, y: nullptr);
9360
9361 if (*TestIsLessOp) {
9362 // MinExpr = Lower;
9363 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9364 Diff = SemaRef.BuildBinOp(
9365 S, OpLoc: DefaultLoc, Opc: BO_Add,
9366 LHSExpr: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Lower).get(),
9367 RHSExpr: Diff.get());
9368 if (!Diff.isUsable())
9369 return std::make_pair(x: nullptr, y: nullptr);
9370 } else {
9371 // MaxExpr = Upper;
9372 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9373 Diff = SemaRef.BuildBinOp(
9374 S, OpLoc: DefaultLoc, Opc: BO_Sub,
9375 LHSExpr: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Upper).get(),
9376 RHSExpr: Diff.get());
9377 if (!Diff.isUsable())
9378 return std::make_pair(x: nullptr, y: nullptr);
9379 }
9380
9381 // Convert to the original type.
9382 if (SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: VarType))
9383 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: VarType,
9384 Action: AssignmentAction::Converting,
9385 /*AllowExplicit=*/true);
9386 if (!Diff.isUsable())
9387 return std::make_pair(x: nullptr, y: nullptr);
9388
9389 Sema::TentativeAnalysisScope Trap(SemaRef);
9390 Diff = SemaRef.ActOnFinishFullExpr(Expr: Diff.get(), /*DiscardedValue=*/false);
9391 if (!Diff.isUsable())
9392 return std::make_pair(x: nullptr, y: nullptr);
9393
9394 if (*TestIsLessOp)
9395 MaxExpr = Diff.get();
9396 else
9397 MinExpr = Diff.get();
9398
9399 return std::make_pair(x&: MinExpr, y&: MaxExpr);
9400}
9401
9402Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9403 if (InitDependOnLC || CondDependOnLC)
9404 return Condition;
9405 return nullptr;
9406}
9407
9408Expr *OpenMPIterationSpaceChecker::buildPreCond(
9409 Scope *S, Expr *Cond,
9410 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9411 // Do not build a precondition when the condition/initialization is dependent
9412 // to prevent pessimistic early loop exit.
9413 // TODO: this can be improved by calculating min/max values but not sure that
9414 // it will be very effective.
9415 if (CondDependOnLC || InitDependOnLC)
9416 return SemaRef
9417 .PerformImplicitConversion(
9418 From: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get(),
9419 ToType: SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
9420 /*AllowExplicit=*/true)
9421 .get();
9422
9423 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9424 Sema::TentativeAnalysisScope Trap(SemaRef);
9425
9426 ExprResult NewLB = tryBuildCapture(SemaRef, Capture: LB, Captures);
9427 ExprResult NewUB = tryBuildCapture(SemaRef, Capture: UB, Captures);
9428 if (!NewLB.isUsable() || !NewUB.isUsable())
9429 return nullptr;
9430
9431 ExprResult CondExpr =
9432 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc,
9433 Opc: *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9434 : (TestIsStrictOp ? BO_GT : BO_GE),
9435 LHSExpr: NewLB.get(), RHSExpr: NewUB.get());
9436 if (CondExpr.isUsable()) {
9437 if (!SemaRef.Context.hasSameUnqualifiedType(T1: CondExpr.get()->getType(),
9438 T2: SemaRef.Context.BoolTy))
9439 CondExpr = SemaRef.PerformImplicitConversion(
9440 From: CondExpr.get(), ToType: SemaRef.Context.BoolTy,
9441 /*Action=*/AssignmentAction::Casting,
9442 /*AllowExplicit=*/true);
9443 }
9444
9445 // Otherwise use original loop condition and evaluate it in runtime.
9446 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9447}
9448
9449/// Build reference expression to the counter be used for codegen.
9450DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9451 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9452 DSAStackTy &DSA) const {
9453 auto *VD = dyn_cast<VarDecl>(Val: LCDecl);
9454 if (!VD) {
9455 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(D: LCDecl);
9456 DeclRefExpr *Ref = buildDeclRefExpr(
9457 S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(), Loc: DefaultLoc);
9458 const DSAStackTy::DSAVarData Data =
9459 DSA.getTopDSA(D: LCDecl, /*FromParent=*/false);
9460 // If the loop control decl is explicitly marked as private, do not mark it
9461 // as captured again.
9462 if (!isOpenMPPrivate(Kind: Data.CKind) || !Data.RefExpr)
9463 Captures.insert(KV: std::make_pair(x: LCRef, y&: Ref));
9464 return Ref;
9465 }
9466 return cast<DeclRefExpr>(Val: LCRef);
9467}
9468
9469Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9470 if (LCDecl && !LCDecl->isInvalidDecl()) {
9471 QualType Type = LCDecl->getType().getNonReferenceType();
9472 VarDecl *PrivateVar = buildVarDecl(
9473 SemaRef, Loc: DefaultLoc, Type, Name: LCDecl->getName(),
9474 Attrs: LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9475 OrigRef: isa<VarDecl>(Val: LCDecl)
9476 ? buildDeclRefExpr(S&: SemaRef, D: cast<VarDecl>(Val: LCDecl), Ty: Type, Loc: DefaultLoc)
9477 : nullptr);
9478 if (PrivateVar->isInvalidDecl())
9479 return nullptr;
9480 return buildDeclRefExpr(S&: SemaRef, D: PrivateVar, Ty: Type, Loc: DefaultLoc);
9481 }
9482 return nullptr;
9483}
9484
9485/// Build initialization of the counter to be used for codegen.
9486Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9487
9488/// Build step of the counter be used for codegen.
9489Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9490
9491Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9492 Scope *S, Expr *Counter,
9493 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9494 Expr *Inc, OverloadedOperatorKind OOK) {
9495 Expr *Cnt = SemaRef.DefaultLvalueConversion(E: Counter).get();
9496 if (!Cnt)
9497 return nullptr;
9498 if (Inc) {
9499 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9500 "Expected only + or - operations for depend clauses.");
9501 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9502 Cnt = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BOK, LHSExpr: Cnt, RHSExpr: Inc).get();
9503 if (!Cnt)
9504 return nullptr;
9505 }
9506 QualType VarType = LCDecl->getType().getNonReferenceType();
9507 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9508 !SemaRef.getLangOpts().CPlusPlus)
9509 return nullptr;
9510 // Upper - Lower
9511 Expr *Upper =
9512 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, Capture: LB, Captures).get();
9513 Expr *Lower =
9514 *TestIsLessOp ? tryBuildCapture(SemaRef, Capture: LB, Captures).get() : Cnt;
9515 if (!Upper || !Lower)
9516 return nullptr;
9517
9518 ExprResult Diff =
9519 calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType,
9520 /*TestIsStrictOp=*/false, /*RoundToStep=*/false,
9521 Captures, InitDependOnLC, CondDependOnLC);
9522 if (!Diff.isUsable())
9523 return nullptr;
9524
9525 return Diff.get();
9526}
9527} // namespace
9528
9529void SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc,
9530 Stmt *Init) {
9531 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9532 assert(Init && "Expected loop in canonical form.");
9533 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9534 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9535 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9536 return;
9537
9538 DSAStack->loopStart();
9539 llvm::SmallPtrSet<const Decl *, 1> EmptyDeclSet;
9540 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9541 *DSAStack, ForLoc, EmptyDeclSet,
9542 EmptyDeclSet);
9543 if (!ISC.checkAndSetInit(S: Init, /*EmitDiags=*/false)) {
9544 if (ValueDecl *D = ISC.getLoopDecl()) {
9545 auto *VD = dyn_cast<VarDecl>(Val: D);
9546 DeclRefExpr *PrivateRef = nullptr;
9547 if (!VD) {
9548 if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9549 VD = Private;
9550 } else {
9551 PrivateRef = buildCapture(S&: SemaRef, D, CaptureExpr: ISC.getLoopDeclRefExpr(),
9552 /*WithInit=*/false);
9553 VD = cast<VarDecl>(Val: PrivateRef->getDecl());
9554 }
9555 }
9556 DSAStack->addLoopControlVariable(D, Capture: VD);
9557 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9558 if (LD != D->getCanonicalDecl()) {
9559 DSAStack->resetPossibleLoopCounter();
9560 if (auto *Var = dyn_cast_or_null<VarDecl>(Val: LD))
9561 SemaRef.MarkDeclarationsReferencedInExpr(E: buildDeclRefExpr(
9562 S&: SemaRef, D: const_cast<VarDecl *>(Var),
9563 Ty: Var->getType().getNonLValueExprType(Context: getASTContext()), Loc: ForLoc,
9564 /*RefersToCapture=*/true));
9565 }
9566 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9567 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9568 // associated for-loop of a simd construct with just one associated
9569 // for-loop may be listed in a linear clause with a constant-linear-step
9570 // that is the increment of the associated for-loop. The loop iteration
9571 // variable(s) in the associated for-loop(s) of a for or parallel for
9572 // construct may be listed in a private or lastprivate clause.
9573 DSAStackTy::DSAVarData DVar =
9574 DSAStack->getTopDSA(D, /*FromParent=*/false);
9575 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9576 // is declared in the loop and it is predetermined as a private.
9577 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9578 OpenMPClauseKind PredeterminedCKind =
9579 isOpenMPSimdDirective(DKind)
9580 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9581 : OMPC_private;
9582 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9583 return getLeafConstructsOrSelf(D: DK).back() == OMPD_taskloop;
9584 };
9585 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9586 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9587 (getLangOpts().OpenMP <= 45 ||
9588 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9589 ((isOpenMPWorksharingDirective(DKind) ||
9590 IsOpenMPTaskloopDirective(DKind) ||
9591 isOpenMPDistributeDirective(DKind)) &&
9592 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9593 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9594 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9595 unsigned OMPVersion = getLangOpts().OpenMP;
9596 Diag(Loc: Init->getBeginLoc(), DiagID: diag::err_omp_loop_var_dsa)
9597 << getOpenMPClauseNameForDiag(C: DVar.CKind)
9598 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion)
9599 << getOpenMPClauseNameForDiag(C: PredeterminedCKind);
9600 if (DVar.RefExpr == nullptr)
9601 DVar.CKind = PredeterminedCKind;
9602 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9603 } else if (LoopDeclRefExpr) {
9604 // Make the loop iteration variable private (for worksharing
9605 // constructs), linear (for simd directives with the only one
9606 // associated loop) or lastprivate (for simd directives with several
9607 // collapsed or ordered loops).
9608 if (DVar.CKind == OMPC_unknown)
9609 DSAStack->addDSA(D, E: LoopDeclRefExpr, A: PredeterminedCKind, PrivateCopy: PrivateRef);
9610 }
9611 }
9612 }
9613 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9614}
9615
9616namespace {
9617// Utility for OpenMP doacross clause kind
9618class OMPDoacrossKind {
9619public:
9620 bool isSource(const OMPDoacrossClause *C) {
9621 return C->getDependenceType() == OMPC_DOACROSS_source ||
9622 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9623 }
9624 bool isSink(const OMPDoacrossClause *C) {
9625 return C->getDependenceType() == OMPC_DOACROSS_sink;
9626 }
9627 bool isSinkIter(const OMPDoacrossClause *C) {
9628 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9629 }
9630};
9631} // namespace
9632/// Called on a for stmt to check and extract its iteration space
9633/// for further processing (such as collapsing).
9634static bool checkOpenMPIterationSpace(
9635 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9636 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9637 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9638 Expr *OrderedLoopCountExpr,
9639 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9640 llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
9641 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9642 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls,
9643 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars) {
9644 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9645 // OpenMP [2.9.1, Canonical Loop Form]
9646 // for (init-expr; test-expr; incr-expr) structured-block
9647 // for (range-decl: range-expr) structured-block
9648 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(Val: S))
9649 S = CanonLoop->getLoopStmt();
9650 auto *For = dyn_cast_or_null<ForStmt>(Val: S);
9651 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(Val: S);
9652 // Ranged for is supported only in OpenMP 5.0.
9653 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9654 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
9655 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_not_for)
9656 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9657 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion) << TotalNestedLoopCount
9658 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9659 if (TotalNestedLoopCount > 1) {
9660 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9661 SemaRef.Diag(Loc: DSA.getConstructLoc(),
9662 DiagID: diag::note_omp_collapse_ordered_expr)
9663 << 2 << CollapseLoopCountExpr->getSourceRange()
9664 << OrderedLoopCountExpr->getSourceRange();
9665 else if (CollapseLoopCountExpr)
9666 SemaRef.Diag(Loc: CollapseLoopCountExpr->getExprLoc(),
9667 DiagID: diag::note_omp_collapse_ordered_expr)
9668 << 0 << CollapseLoopCountExpr->getSourceRange();
9669 else if (OrderedLoopCountExpr)
9670 SemaRef.Diag(Loc: OrderedLoopCountExpr->getExprLoc(),
9671 DiagID: diag::note_omp_collapse_ordered_expr)
9672 << 1 << OrderedLoopCountExpr->getSourceRange();
9673 }
9674 return true;
9675 }
9676 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9677 "No loop body.");
9678 // Postpone analysis in dependent contexts for ranged for loops.
9679 if (CXXFor && SemaRef.CurContext->isDependentContext())
9680 return false;
9681
9682 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9683 For ? For->getForLoc() : CXXFor->getForLoc(),
9684 CollapsedLoopVarDecls,
9685 CollapsedLoopInductionVars);
9686
9687 // Check init.
9688 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9689 if (ISC.checkAndSetInit(S: Init))
9690 return true;
9691
9692 bool HasErrors = false;
9693
9694 // Check loop variable's type.
9695 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9696 // OpenMP [2.6, Canonical Loop Form]
9697 // Var is one of the following:
9698 // A variable of signed or unsigned integer type.
9699 // For C++, a variable of a random access iterator type.
9700 // For C, a variable of a pointer type.
9701 QualType VarType = LCDecl->getType().getNonReferenceType();
9702 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9703 !VarType->isPointerType() &&
9704 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9705 SemaRef.Diag(Loc: Init->getBeginLoc(), DiagID: diag::err_omp_loop_variable_type)
9706 << SemaRef.getLangOpts().CPlusPlus;
9707 HasErrors = true;
9708 }
9709
9710 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9711 // a Construct
9712 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9713 // parallel for construct is (are) private.
9714 // The loop iteration variable in the associated for-loop of a simd
9715 // construct with just one associated for-loop is linear with a
9716 // constant-linear-step that is the increment of the associated for-loop.
9717 // Exclude loop var from the list of variables with implicitly defined data
9718 // sharing attributes.
9719 VarsWithImplicitDSA.erase(Val: LCDecl);
9720
9721 assert((isOpenMPLoopDirective(DKind) ||
9722 isOpenMPCanonicalLoopSequenceTransformationDirective(DKind)) &&
9723 "DSA for non-loop vars");
9724
9725 // Check test-expr.
9726 HasErrors |= ISC.checkAndSetCond(S: For ? For->getCond() : CXXFor->getCond());
9727
9728 // Check incr-expr.
9729 HasErrors |= ISC.checkAndSetInc(S: For ? For->getInc() : CXXFor->getInc());
9730 }
9731
9732 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9733 return HasErrors;
9734
9735 // Build the loop's iteration space representation.
9736 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9737 S: DSA.getCurScope(), Cond: For ? For->getCond() : CXXFor->getCond(), Captures);
9738 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9739 ISC.buildNumIterations(S: DSA.getCurScope(), ResultIterSpaces,
9740 LimitedType: (isOpenMPWorksharingDirective(DKind) ||
9741 isOpenMPGenericLoopDirective(DKind) ||
9742 isOpenMPTaskLoopDirective(DKind) ||
9743 isOpenMPDistributeDirective(DKind) ||
9744 isOpenMPLoopTransformationDirective(DKind)),
9745 Captures);
9746 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9747 ISC.buildCounterVar(Captures, DSA);
9748 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9749 ISC.buildPrivateCounterVar();
9750 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9751 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9752 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9753 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9754 ISC.getConditionSrcRange();
9755 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9756 ISC.getIncrementSrcRange();
9757 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9758 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9759 ISC.isStrictTestOp();
9760 std::tie(args&: ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9761 args&: ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9762 ISC.buildMinMaxValues(S: DSA.getCurScope(), Captures);
9763 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9764 ISC.buildFinalCondition(S: DSA.getCurScope());
9765 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9766 ISC.doesInitDependOnLC();
9767 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9768 ISC.doesCondDependOnLC();
9769 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9770 ISC.getLoopDependentIdx();
9771
9772 HasErrors |=
9773 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9774 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9775 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9776 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9777 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9778 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9779 if (!HasErrors && DSA.isOrderedRegion()) {
9780 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9781 if (CurrentNestedLoopCount <
9782 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9783 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9784 NumLoop: CurrentNestedLoopCount,
9785 NumIterations: ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9786 DSA.getOrderedRegionParam().second->setLoopCounter(
9787 NumLoop: CurrentNestedLoopCount,
9788 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9789 }
9790 }
9791 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9792 auto *DependC = dyn_cast<OMPDependClause>(Val: Pair.first);
9793 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Val: Pair.first);
9794 unsigned NumLoops =
9795 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9796 if (CurrentNestedLoopCount >= NumLoops) {
9797 // Erroneous case - clause has some problems.
9798 continue;
9799 }
9800 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9801 Pair.second.size() <= CurrentNestedLoopCount) {
9802 // Erroneous case - clause has some problems.
9803 DependC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: nullptr);
9804 continue;
9805 }
9806 OMPDoacrossKind ODK;
9807 if (DoacrossC && ODK.isSink(C: DoacrossC) &&
9808 Pair.second.size() <= CurrentNestedLoopCount) {
9809 // Erroneous case - clause has some problems.
9810 DoacrossC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: nullptr);
9811 continue;
9812 }
9813 Expr *CntValue;
9814 SourceLocation DepLoc =
9815 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9816 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9817 (DoacrossC && ODK.isSource(C: DoacrossC)))
9818 CntValue = ISC.buildOrderedLoopData(
9819 S: DSA.getCurScope(),
9820 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9821 Loc: DepLoc);
9822 else if (DoacrossC && ODK.isSinkIter(C: DoacrossC)) {
9823 Expr *Cnt = SemaRef
9824 .DefaultLvalueConversion(
9825 E: ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9826 .get();
9827 if (!Cnt)
9828 continue;
9829 // build CounterVar - 1
9830 Expr *Inc =
9831 SemaRef.ActOnIntegerConstant(Loc: DoacrossC->getColonLoc(), /*Val=*/1)
9832 .get();
9833 CntValue = ISC.buildOrderedLoopData(
9834 S: DSA.getCurScope(),
9835 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9836 Loc: DepLoc, Inc, OOK: clang::OO_Minus);
9837 } else
9838 CntValue = ISC.buildOrderedLoopData(
9839 S: DSA.getCurScope(),
9840 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9841 Loc: DepLoc, Inc: Pair.second[CurrentNestedLoopCount].first,
9842 OOK: Pair.second[CurrentNestedLoopCount].second);
9843 if (DependC)
9844 DependC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: CntValue);
9845 else
9846 DoacrossC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: CntValue);
9847 }
9848 }
9849 // Record the loop induction variable for nested loop reuse checking.
9850 if (CurrentNestedLoopCount < NestedLoopCount && !HasErrors) {
9851 if (const ValueDecl *LCDecl = ISC.getLoopDecl())
9852 CollapsedLoopInductionVars.insert(Ptr: LCDecl->getCanonicalDecl());
9853 }
9854 return HasErrors;
9855}
9856
9857/// Build 'VarRef = Start.
9858static ExprResult
9859buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9860 ExprResult Start, bool IsNonRectangularLB,
9861 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9862 // Build 'VarRef = Start.
9863 ExprResult NewStart = IsNonRectangularLB
9864 ? Start.get()
9865 : tryBuildCapture(SemaRef, Capture: Start.get(), Captures);
9866 if (!NewStart.isUsable())
9867 return ExprError();
9868 if (!SemaRef.Context.hasSameType(T1: NewStart.get()->getType(),
9869 T2: VarRef.get()->getType())) {
9870 NewStart = SemaRef.PerformImplicitConversion(
9871 From: NewStart.get(), ToType: VarRef.get()->getType(), Action: AssignmentAction::Converting,
9872 /*AllowExplicit=*/true);
9873 if (!NewStart.isUsable())
9874 return ExprError();
9875 }
9876
9877 ExprResult Init =
9878 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: NewStart.get());
9879 return Init;
9880}
9881
9882/// Build 'VarRef = Start + Iter * Step'.
9883static ExprResult buildCounterUpdate(
9884 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9885 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9886 bool IsNonRectangularLB,
9887 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9888 // Add parentheses (for debugging purposes only).
9889 Iter = SemaRef.ActOnParenExpr(L: Loc, R: Loc, E: Iter.get());
9890 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9891 !Step.isUsable())
9892 return ExprError();
9893
9894 ExprResult NewStep = Step;
9895 if (Captures)
9896 NewStep = tryBuildCapture(SemaRef, Capture: Step.get(), Captures&: *Captures);
9897 if (NewStep.isInvalid())
9898 return ExprError();
9899 ExprResult Update =
9900 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Mul, LHSExpr: Iter.get(), RHSExpr: NewStep.get());
9901 if (!Update.isUsable())
9902 return ExprError();
9903
9904 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9905 // 'VarRef = Start (+|-) Iter * Step'.
9906 if (!Start.isUsable())
9907 return ExprError();
9908 ExprResult NewStart = SemaRef.ActOnParenExpr(L: Loc, R: Loc, E: Start.get());
9909 if (!NewStart.isUsable())
9910 return ExprError();
9911 if (Captures && !IsNonRectangularLB)
9912 NewStart = tryBuildCapture(SemaRef, Capture: Start.get(), Captures&: *Captures);
9913 if (NewStart.isInvalid())
9914 return ExprError();
9915
9916 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9917 ExprResult SavedUpdate = Update;
9918 ExprResult UpdateVal;
9919 if (VarRef.get()->getType()->isOverloadableType() ||
9920 NewStart.get()->getType()->isOverloadableType() ||
9921 Update.get()->getType()->isOverloadableType()) {
9922 Sema::TentativeAnalysisScope Trap(SemaRef);
9923
9924 Update =
9925 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: NewStart.get());
9926 if (Update.isUsable()) {
9927 UpdateVal =
9928 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: Subtract ? BO_SubAssign : BO_AddAssign,
9929 LHSExpr: VarRef.get(), RHSExpr: SavedUpdate.get());
9930 if (UpdateVal.isUsable()) {
9931 Update = SemaRef.CreateBuiltinBinOp(OpLoc: Loc, Opc: BO_Comma, LHSExpr: Update.get(),
9932 RHSExpr: UpdateVal.get());
9933 }
9934 }
9935 }
9936
9937 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9938 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9939 Update = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: Subtract ? BO_Sub : BO_Add,
9940 LHSExpr: NewStart.get(), RHSExpr: SavedUpdate.get());
9941 if (!Update.isUsable())
9942 return ExprError();
9943
9944 if (!SemaRef.Context.hasSameType(T1: Update.get()->getType(),
9945 T2: VarRef.get()->getType())) {
9946 Update = SemaRef.PerformImplicitConversion(
9947 From: Update.get(), ToType: VarRef.get()->getType(), Action: AssignmentAction::Converting,
9948 /*AllowExplicit=*/true);
9949 if (!Update.isUsable())
9950 return ExprError();
9951 }
9952
9953 Update = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: Update.get());
9954 }
9955 return Update;
9956}
9957
9958/// Convert integer expression \a E to make it have at least \a Bits
9959/// bits.
9960static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9961 if (E == nullptr)
9962 return ExprError();
9963 ASTContext &C = SemaRef.Context;
9964 QualType OldType = E->getType();
9965 unsigned HasBits = C.getTypeSize(T: OldType);
9966 if (HasBits >= Bits)
9967 return ExprResult(E);
9968 // OK to convert to signed, because new type has more bits than old.
9969 QualType NewType = C.getIntTypeForBitwidth(DestWidth: Bits, /*Signed=*/true);
9970 return SemaRef.PerformImplicitConversion(
9971 From: E, ToType: NewType, Action: AssignmentAction::Converting, /*AllowExplicit=*/true);
9972}
9973
9974/// Check if the given expression \a E is a constant integer that fits
9975/// into \a Bits bits.
9976static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9977 if (E == nullptr)
9978 return false;
9979 if (std::optional<llvm::APSInt> Result =
9980 E->getIntegerConstantExpr(Ctx: SemaRef.Context))
9981 return Signed ? Result->isSignedIntN(N: Bits) : Result->isIntN(N: Bits);
9982 return false;
9983}
9984
9985/// Build preinits statement for the given declarations.
9986static Stmt *buildPreInits(ASTContext &Context,
9987 MutableArrayRef<Decl *> PreInits) {
9988 if (!PreInits.empty()) {
9989 return new (Context) DeclStmt(
9990 DeclGroupRef::Create(C&: Context, Decls: PreInits.begin(), NumDecls: PreInits.size()),
9991 SourceLocation(), SourceLocation());
9992 }
9993 return nullptr;
9994}
9995
9996/// Append the \p Item or the content of a CompoundStmt to the list \p
9997/// TargetList.
9998///
9999/// A CompoundStmt is used as container in case multiple statements need to be
10000/// stored in lieu of using an explicit list. Flattening is necessary because
10001/// contained DeclStmts need to be visible after the execution of the list. Used
10002/// for OpenMP pre-init declarations/statements.
10003static void appendFlattenedStmtList(SmallVectorImpl<Stmt *> &TargetList,
10004 Stmt *Item) {
10005 // nullptr represents an empty list.
10006 if (!Item)
10007 return;
10008
10009 if (auto *CS = dyn_cast<CompoundStmt>(Val: Item))
10010 llvm::append_range(C&: TargetList, R: CS->body());
10011 else
10012 TargetList.push_back(Elt: Item);
10013}
10014
10015/// Build preinits statement for the given declarations.
10016static Stmt *
10017buildPreInits(ASTContext &Context,
10018 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
10019 if (!Captures.empty()) {
10020 SmallVector<Decl *, 16> PreInits;
10021 for (const auto &Pair : Captures)
10022 PreInits.push_back(Elt: Pair.second->getDecl());
10023 return buildPreInits(Context, PreInits);
10024 }
10025 return nullptr;
10026}
10027
10028/// Build pre-init statement for the given statements.
10029static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
10030 if (PreInits.empty())
10031 return nullptr;
10032
10033 SmallVector<Stmt *> Stmts;
10034 for (Stmt *S : PreInits)
10035 appendFlattenedStmtList(TargetList&: Stmts, Item: S);
10036 return CompoundStmt::Create(C: Context, Stmts: PreInits, FPFeatures: FPOptionsOverride(), LB: {}, RB: {});
10037}
10038
10039/// Build postupdate expression for the given list of postupdates expressions.
10040static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
10041 Expr *PostUpdate = nullptr;
10042 if (!PostUpdates.empty()) {
10043 for (Expr *E : PostUpdates) {
10044 Expr *ConvE = S.BuildCStyleCastExpr(
10045 LParenLoc: E->getExprLoc(),
10046 Ty: S.Context.getTrivialTypeSourceInfo(T: S.Context.VoidTy),
10047 RParenLoc: E->getExprLoc(), Op: E)
10048 .get();
10049 PostUpdate = PostUpdate
10050 ? S.CreateBuiltinBinOp(OpLoc: ConvE->getExprLoc(), Opc: BO_Comma,
10051 LHSExpr: PostUpdate, RHSExpr: ConvE)
10052 .get()
10053 : ConvE;
10054 }
10055 }
10056 return PostUpdate;
10057}
10058
10059/// Look for variables declared in the body parts of a for-loop nest. Used
10060/// for verifying loop nest structure before performing a loop collapse
10061/// operation.
10062class ForVarDeclFinder : public DynamicRecursiveASTVisitor {
10063 int NestingDepth = 0;
10064 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
10065
10066public:
10067 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
10068 : VarDecls(VD) {}
10069
10070 bool VisitForStmt(ForStmt *F) override {
10071 ++NestingDepth;
10072 TraverseStmt(S: F->getBody());
10073 --NestingDepth;
10074 return false;
10075 }
10076
10077 bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override {
10078 ++NestingDepth;
10079 TraverseStmt(S: RF->getBody());
10080 --NestingDepth;
10081 return false;
10082 }
10083
10084 bool VisitVarDecl(VarDecl *D) override {
10085 Decl *C = D->getCanonicalDecl();
10086 if (NestingDepth > 0)
10087 VarDecls.insert(Ptr: C);
10088 return true;
10089 }
10090};
10091
10092/// Called on a for stmt to check itself and nested loops (if any).
10093/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
10094/// number of collapsed loops otherwise.
10095static unsigned
10096checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
10097 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
10098 DSAStackTy &DSA,
10099 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
10100 OMPLoopBasedDirective::HelperExprs &Built) {
10101 // If either of the loop expressions exist and contain errors, we bail out
10102 // early because diagnostics have already been emitted and we can't reliably
10103 // check more about the loop.
10104 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
10105 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
10106 return 0;
10107
10108 unsigned NestedLoopCount = 1;
10109 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
10110 !isOpenMPLoopTransformationDirective(DKind);
10111 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
10112 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopInductionVars;
10113
10114 if (CollapseLoopCountExpr) {
10115 // Found 'collapse' clause - calculate collapse number.
10116 Expr::EvalResult Result;
10117 if (!CollapseLoopCountExpr->isValueDependent() &&
10118 CollapseLoopCountExpr->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext())) {
10119 NestedLoopCount = Result.Val.getInt().getLimitedValue();
10120
10121 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
10122 FVDF.TraverseStmt(S: AStmt);
10123 } else {
10124 Built.clear(/*Size=*/1);
10125 return 1;
10126 }
10127 }
10128 unsigned OrderedLoopCount = 1;
10129 if (OrderedLoopCountExpr) {
10130 // Found 'ordered' clause - calculate collapse number.
10131 Expr::EvalResult EVResult;
10132 if (!OrderedLoopCountExpr->isValueDependent() &&
10133 OrderedLoopCountExpr->EvaluateAsInt(Result&: EVResult,
10134 Ctx: SemaRef.getASTContext())) {
10135 llvm::APSInt Result = EVResult.Val.getInt();
10136 if (Result.getLimitedValue() < NestedLoopCount) {
10137 SemaRef.Diag(Loc: OrderedLoopCountExpr->getExprLoc(),
10138 DiagID: diag::err_omp_wrong_ordered_loop_count)
10139 << OrderedLoopCountExpr->getSourceRange();
10140 SemaRef.Diag(Loc: CollapseLoopCountExpr->getExprLoc(),
10141 DiagID: diag::note_collapse_loop_count)
10142 << CollapseLoopCountExpr->getSourceRange();
10143 }
10144 OrderedLoopCount = Result.getLimitedValue();
10145 } else {
10146 Built.clear(/*Size=*/1);
10147 return 1;
10148 }
10149 }
10150 // This is helper routine for loop directives (e.g., 'for', 'simd',
10151 // 'for simd', etc.).
10152 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
10153 unsigned NumLoops = std::max(a: OrderedLoopCount, b: NestedLoopCount);
10154 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
10155 if (!OMPLoopBasedDirective::doForAllLoops(
10156 CurStmt: AStmt->IgnoreContainers(
10157 IgnoreCaptured: !isOpenMPCanonicalLoopNestTransformationDirective(DKind)),
10158 TryImperfectlyNestedLoops: SupportsNonPerfectlyNested, NumLoops,
10159 Callback: [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
10160 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
10161 &IterSpaces, &Captures, &CollapsedLoopVarDecls,
10162 &CollapsedLoopInductionVars](unsigned Cnt, Stmt *CurStmt) {
10163 if (checkOpenMPIterationSpace(
10164 DKind, S: CurStmt, SemaRef, DSA, CurrentNestedLoopCount: Cnt, NestedLoopCount,
10165 TotalNestedLoopCount: NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
10166 VarsWithImplicitDSA, ResultIterSpaces: IterSpaces, Captures,
10167 CollapsedLoopVarDecls, CollapsedLoopInductionVars))
10168 return true;
10169 if (Cnt > 0 && Cnt >= NestedLoopCount &&
10170 IterSpaces[Cnt].CounterVar) {
10171 // Handle initialization of captured loop iterator variables.
10172 auto *DRE = cast<DeclRefExpr>(Val: IterSpaces[Cnt].CounterVar);
10173 if (isa<OMPCapturedExprDecl>(Val: DRE->getDecl())) {
10174 Captures[DRE] = DRE;
10175 }
10176 }
10177 return false;
10178 },
10179 OnTransformationCallback: [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
10180 Stmt *DependentPreInits = Transform->getPreInits();
10181 if (!DependentPreInits)
10182 return;
10183
10184 // Search for pre-init declared variables that need to be captured
10185 // to be referenceable inside the directive.
10186 SmallVector<Stmt *> Constituents;
10187 appendFlattenedStmtList(TargetList&: Constituents, Item: DependentPreInits);
10188 for (Stmt *S : Constituents) {
10189 if (auto *DC = dyn_cast<DeclStmt>(Val: S)) {
10190 for (Decl *C : DC->decls()) {
10191 auto *D = cast<VarDecl>(Val: C);
10192 DeclRefExpr *Ref = buildDeclRefExpr(
10193 S&: SemaRef, D, Ty: D->getType().getNonReferenceType(),
10194 Loc: cast<OMPExecutableDirective>(Val: Transform->getDirective())
10195 ->getBeginLoc());
10196 Captures[Ref] = Ref;
10197 }
10198 }
10199 }
10200 }))
10201 return 0;
10202
10203 Built.clear(/*size=*/Size: NestedLoopCount);
10204
10205 if (SemaRef.CurContext->isDependentContext())
10206 return NestedLoopCount;
10207
10208 // An example of what is generated for the following code:
10209 //
10210 // #pragma omp simd collapse(2) ordered(2)
10211 // for (i = 0; i < NI; ++i)
10212 // for (k = 0; k < NK; ++k)
10213 // for (j = J0; j < NJ; j+=2) {
10214 // <loop body>
10215 // }
10216 //
10217 // We generate the code below.
10218 // Note: the loop body may be outlined in CodeGen.
10219 // Note: some counters may be C++ classes, operator- is used to find number of
10220 // iterations and operator+= to calculate counter value.
10221 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
10222 // or i64 is currently supported).
10223 //
10224 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
10225 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
10226 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
10227 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
10228 // // similar updates for vars in clauses (e.g. 'linear')
10229 // <loop body (using local i and j)>
10230 // }
10231 // i = NI; // assign final values of counters
10232 // j = NJ;
10233 //
10234
10235 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
10236 // the iteration counts of the collapsed for loops.
10237 // Precondition tests if there is at least one iteration (all conditions are
10238 // true).
10239 auto PreCond = ExprResult(IterSpaces[0].PreCond);
10240 Expr *N0 = IterSpaces[0].NumIterations;
10241 ExprResult LastIteration32 = widenIterationCount(
10242 /*Bits=*/32,
10243 E: SemaRef
10244 .PerformImplicitConversion(From: N0->IgnoreImpCasts(), ToType: N0->getType(),
10245 Action: AssignmentAction::Converting,
10246 /*AllowExplicit=*/true)
10247 .get(),
10248 SemaRef);
10249 ExprResult LastIteration64 = widenIterationCount(
10250 /*Bits=*/64,
10251 E: SemaRef
10252 .PerformImplicitConversion(From: N0->IgnoreImpCasts(), ToType: N0->getType(),
10253 Action: AssignmentAction::Converting,
10254 /*AllowExplicit=*/true)
10255 .get(),
10256 SemaRef);
10257
10258 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
10259 return NestedLoopCount;
10260
10261 ASTContext &C = SemaRef.Context;
10262 bool AllCountsNeedLessThan32Bits = C.getTypeSize(T: N0->getType()) < 32;
10263
10264 Scope *CurScope = DSA.getCurScope();
10265 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10266 if (PreCond.isUsable()) {
10267 PreCond =
10268 SemaRef.BuildBinOp(S: CurScope, OpLoc: PreCond.get()->getExprLoc(), Opc: BO_LAnd,
10269 LHSExpr: PreCond.get(), RHSExpr: IterSpaces[Cnt].PreCond);
10270 }
10271 Expr *N = IterSpaces[Cnt].NumIterations;
10272 SourceLocation Loc = N->getExprLoc();
10273 AllCountsNeedLessThan32Bits &= C.getTypeSize(T: N->getType()) < 32;
10274 if (LastIteration32.isUsable())
10275 LastIteration32 = SemaRef.BuildBinOp(
10276 S: CurScope, OpLoc: Loc, Opc: BO_Mul, LHSExpr: LastIteration32.get(),
10277 RHSExpr: SemaRef
10278 .PerformImplicitConversion(From: N->IgnoreImpCasts(), ToType: N->getType(),
10279 Action: AssignmentAction::Converting,
10280 /*AllowExplicit=*/true)
10281 .get());
10282 if (LastIteration64.isUsable())
10283 LastIteration64 = SemaRef.BuildBinOp(
10284 S: CurScope, OpLoc: Loc, Opc: BO_Mul, LHSExpr: LastIteration64.get(),
10285 RHSExpr: SemaRef
10286 .PerformImplicitConversion(From: N->IgnoreImpCasts(), ToType: N->getType(),
10287 Action: AssignmentAction::Converting,
10288 /*AllowExplicit=*/true)
10289 .get());
10290 }
10291
10292 // Choose either the 32-bit or 64-bit version.
10293 ExprResult LastIteration = LastIteration64;
10294 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
10295 (LastIteration32.isUsable() &&
10296 C.getTypeSize(T: LastIteration32.get()->getType()) == 32 &&
10297 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10298 fitsInto(
10299 /*Bits=*/32,
10300 Signed: LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
10301 E: LastIteration64.get(), SemaRef))))
10302 LastIteration = LastIteration32;
10303 QualType VType = LastIteration.get()->getType();
10304 QualType RealVType = VType;
10305 QualType StrideVType = VType;
10306 if (isOpenMPTaskLoopDirective(DKind)) {
10307 VType =
10308 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
10309 StrideVType =
10310 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
10311 }
10312
10313 if (!LastIteration.isUsable())
10314 return 0;
10315
10316 // Save the number of iterations.
10317 ExprResult NumIterations = LastIteration;
10318 {
10319 LastIteration = SemaRef.BuildBinOp(
10320 S: CurScope, OpLoc: LastIteration.get()->getExprLoc(), Opc: BO_Sub,
10321 LHSExpr: LastIteration.get(),
10322 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
10323 if (!LastIteration.isUsable())
10324 return 0;
10325 }
10326
10327 // Calculate the last iteration number beforehand instead of doing this on
10328 // each iteration. Do not do this if the number of iterations may be kfold-ed.
10329 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(Ctx: SemaRef.Context);
10330 ExprResult CalcLastIteration;
10331 if (!IsConstant) {
10332 ExprResult SaveRef =
10333 tryBuildCapture(SemaRef, Capture: LastIteration.get(), Captures);
10334 LastIteration = SaveRef;
10335
10336 // Prepare SaveRef + 1.
10337 NumIterations = SemaRef.BuildBinOp(
10338 S: CurScope, OpLoc: SaveRef.get()->getExprLoc(), Opc: BO_Add, LHSExpr: SaveRef.get(),
10339 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
10340 if (!NumIterations.isUsable())
10341 return 0;
10342 }
10343
10344 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
10345
10346 // Build variables passed into runtime, necessary for worksharing directives.
10347 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10348 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
10349 isOpenMPDistributeDirective(DKind) ||
10350 isOpenMPGenericLoopDirective(DKind) ||
10351 isOpenMPLoopTransformationDirective(DKind)) {
10352 // Lower bound variable, initialized with zero.
10353 VarDecl *LBDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.lb");
10354 LB = buildDeclRefExpr(S&: SemaRef, D: LBDecl, Ty: VType, Loc: InitLoc);
10355 SemaRef.AddInitializerToDecl(dcl: LBDecl,
10356 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
10357 /*DirectInit=*/false);
10358
10359 // Upper bound variable, initialized with last iteration number.
10360 VarDecl *UBDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.ub");
10361 UB = buildDeclRefExpr(S&: SemaRef, D: UBDecl, Ty: VType, Loc: InitLoc);
10362 SemaRef.AddInitializerToDecl(dcl: UBDecl, init: LastIteration.get(),
10363 /*DirectInit=*/false);
10364
10365 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
10366 // This will be used to implement clause 'lastprivate'.
10367 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(DestWidth: 32, Signed: true);
10368 VarDecl *ILDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: Int32Ty, Name: ".omp.is_last");
10369 IL = buildDeclRefExpr(S&: SemaRef, D: ILDecl, Ty: Int32Ty, Loc: InitLoc);
10370 SemaRef.AddInitializerToDecl(dcl: ILDecl,
10371 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
10372 /*DirectInit=*/false);
10373
10374 // Stride variable returned by runtime (we initialize it to 1 by default).
10375 VarDecl *STDecl =
10376 buildVarDecl(SemaRef, Loc: InitLoc, Type: StrideVType, Name: ".omp.stride");
10377 ST = buildDeclRefExpr(S&: SemaRef, D: STDecl, Ty: StrideVType, Loc: InitLoc);
10378 SemaRef.AddInitializerToDecl(dcl: STDecl,
10379 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 1).get(),
10380 /*DirectInit=*/false);
10381
10382 // Build expression: UB = min(UB, LastIteration)
10383 // It is necessary for CodeGen of directives with static scheduling.
10384 ExprResult IsUBGreater = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_GT,
10385 LHSExpr: UB.get(), RHSExpr: LastIteration.get());
10386 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10387 QuestionLoc: LastIteration.get()->getExprLoc(), ColonLoc: InitLoc, CondExpr: IsUBGreater.get(),
10388 LHSExpr: LastIteration.get(), RHSExpr: UB.get());
10389 EUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: UB.get(),
10390 RHSExpr: CondOp.get());
10391 EUB = SemaRef.ActOnFinishFullExpr(Expr: EUB.get(), /*DiscardedValue=*/false);
10392
10393 // If we have a combined directive that combines 'distribute', 'for' or
10394 // 'simd' we need to be able to access the bounds of the schedule of the
10395 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10396 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10397 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10398 // Lower bound variable, initialized with zero.
10399 VarDecl *CombLBDecl =
10400 buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.comb.lb");
10401 CombLB = buildDeclRefExpr(S&: SemaRef, D: CombLBDecl, Ty: VType, Loc: InitLoc);
10402 SemaRef.AddInitializerToDecl(
10403 dcl: CombLBDecl, init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
10404 /*DirectInit=*/false);
10405
10406 // Upper bound variable, initialized with last iteration number.
10407 VarDecl *CombUBDecl =
10408 buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.comb.ub");
10409 CombUB = buildDeclRefExpr(S&: SemaRef, D: CombUBDecl, Ty: VType, Loc: InitLoc);
10410 SemaRef.AddInitializerToDecl(dcl: CombUBDecl, init: LastIteration.get(),
10411 /*DirectInit=*/false);
10412
10413 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10414 S: CurScope, OpLoc: InitLoc, Opc: BO_GT, LHSExpr: CombUB.get(), RHSExpr: LastIteration.get());
10415 ExprResult CombCondOp =
10416 SemaRef.ActOnConditionalOp(QuestionLoc: InitLoc, ColonLoc: InitLoc, CondExpr: CombIsUBGreater.get(),
10417 LHSExpr: LastIteration.get(), RHSExpr: CombUB.get());
10418 CombEUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: CombUB.get(),
10419 RHSExpr: CombCondOp.get());
10420 CombEUB =
10421 SemaRef.ActOnFinishFullExpr(Expr: CombEUB.get(), /*DiscardedValue=*/false);
10422
10423 const CapturedDecl *CD = cast<CapturedStmt>(Val: AStmt)->getCapturedDecl();
10424 // We expect to have at least 2 more parameters than the 'parallel'
10425 // directive does - the lower and upper bounds of the previous schedule.
10426 assert(CD->getNumParams() >= 4 &&
10427 "Unexpected number of parameters in loop combined directive");
10428
10429 // Set the proper type for the bounds given what we learned from the
10430 // enclosed loops.
10431 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/i: 2);
10432 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/i: 3);
10433
10434 // Previous lower and upper bounds are obtained from the region
10435 // parameters.
10436 PrevLB =
10437 buildDeclRefExpr(S&: SemaRef, D: PrevLBDecl, Ty: PrevLBDecl->getType(), Loc: InitLoc);
10438 PrevUB =
10439 buildDeclRefExpr(S&: SemaRef, D: PrevUBDecl, Ty: PrevUBDecl->getType(), Loc: InitLoc);
10440 }
10441 }
10442
10443 // Build the iteration variable and its initialization before loop.
10444 ExprResult IV;
10445 ExprResult Init, CombInit;
10446 {
10447 VarDecl *IVDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: RealVType, Name: ".omp.iv");
10448 IV = buildDeclRefExpr(S&: SemaRef, D: IVDecl, Ty: RealVType, Loc: InitLoc);
10449 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10450 isOpenMPGenericLoopDirective(DKind) ||
10451 isOpenMPTaskLoopDirective(DKind) ||
10452 isOpenMPDistributeDirective(DKind) ||
10453 isOpenMPLoopTransformationDirective(DKind))
10454 ? LB.get()
10455 : SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 0).get();
10456 Init = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: RHS);
10457 Init = SemaRef.ActOnFinishFullExpr(Expr: Init.get(), /*DiscardedValue=*/false);
10458
10459 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10460 Expr *CombRHS =
10461 (isOpenMPWorksharingDirective(DKind) ||
10462 isOpenMPGenericLoopDirective(DKind) ||
10463 isOpenMPTaskLoopDirective(DKind) ||
10464 isOpenMPDistributeDirective(DKind))
10465 ? CombLB.get()
10466 : SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 0).get();
10467 CombInit =
10468 SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: CombRHS);
10469 CombInit =
10470 SemaRef.ActOnFinishFullExpr(Expr: CombInit.get(), /*DiscardedValue=*/false);
10471 }
10472 }
10473
10474 bool UseStrictCompare =
10475 RealVType->hasUnsignedIntegerRepresentation() &&
10476 llvm::all_of(Range&: IterSpaces, P: [](const LoopIterationSpace &LIS) {
10477 return LIS.IsStrictCompare;
10478 });
10479 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10480 // unsigned IV)) for worksharing loops.
10481 SourceLocation CondLoc = AStmt->getBeginLoc();
10482 Expr *BoundUB = UB.get();
10483 if (UseStrictCompare) {
10484 BoundUB =
10485 SemaRef
10486 .BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundUB,
10487 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10488 .get();
10489 BoundUB =
10490 SemaRef.ActOnFinishFullExpr(Expr: BoundUB, /*DiscardedValue=*/false).get();
10491 }
10492 ExprResult Cond =
10493 (isOpenMPWorksharingDirective(DKind) ||
10494 isOpenMPGenericLoopDirective(DKind) ||
10495 isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
10496 isOpenMPLoopTransformationDirective(DKind))
10497 ? SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc,
10498 Opc: UseStrictCompare ? BO_LT : BO_LE, LHSExpr: IV.get(),
10499 RHSExpr: BoundUB)
10500 : SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LT, LHSExpr: IV.get(),
10501 RHSExpr: NumIterations.get());
10502 ExprResult CombDistCond;
10503 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10504 CombDistCond = SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LT, LHSExpr: IV.get(),
10505 RHSExpr: NumIterations.get());
10506 }
10507
10508 ExprResult CombCond;
10509 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10510 Expr *BoundCombUB = CombUB.get();
10511 if (UseStrictCompare) {
10512 BoundCombUB =
10513 SemaRef
10514 .BuildBinOp(
10515 S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundCombUB,
10516 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10517 .get();
10518 BoundCombUB =
10519 SemaRef.ActOnFinishFullExpr(Expr: BoundCombUB, /*DiscardedValue=*/false)
10520 .get();
10521 }
10522 CombCond =
10523 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE,
10524 LHSExpr: IV.get(), RHSExpr: BoundCombUB);
10525 }
10526 // Loop increment (IV = IV + 1)
10527 SourceLocation IncLoc = AStmt->getBeginLoc();
10528 ExprResult Inc =
10529 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: IV.get(),
10530 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: IncLoc, Val: 1).get());
10531 if (!Inc.isUsable())
10532 return 0;
10533 Inc = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: Inc.get());
10534 Inc = SemaRef.ActOnFinishFullExpr(Expr: Inc.get(), /*DiscardedValue=*/false);
10535 if (!Inc.isUsable())
10536 return 0;
10537
10538 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10539 // Used for directives with static scheduling.
10540 // In combined construct, add combined version that use CombLB and CombUB
10541 // base variables for the update
10542 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10543 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
10544 isOpenMPGenericLoopDirective(DKind) ||
10545 isOpenMPDistributeDirective(DKind) ||
10546 isOpenMPLoopTransformationDirective(DKind)) {
10547 // LB + ST
10548 NextLB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: LB.get(), RHSExpr: ST.get());
10549 if (!NextLB.isUsable())
10550 return 0;
10551 // LB = LB + ST
10552 NextLB =
10553 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: LB.get(), RHSExpr: NextLB.get());
10554 NextLB =
10555 SemaRef.ActOnFinishFullExpr(Expr: NextLB.get(), /*DiscardedValue=*/false);
10556 if (!NextLB.isUsable())
10557 return 0;
10558 // UB + ST
10559 NextUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: UB.get(), RHSExpr: ST.get());
10560 if (!NextUB.isUsable())
10561 return 0;
10562 // UB = UB + ST
10563 NextUB =
10564 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: UB.get(), RHSExpr: NextUB.get());
10565 NextUB =
10566 SemaRef.ActOnFinishFullExpr(Expr: NextUB.get(), /*DiscardedValue=*/false);
10567 if (!NextUB.isUsable())
10568 return 0;
10569 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10570 CombNextLB =
10571 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: CombLB.get(), RHSExpr: ST.get());
10572 if (!NextLB.isUsable())
10573 return 0;
10574 // LB = LB + ST
10575 CombNextLB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: CombLB.get(),
10576 RHSExpr: CombNextLB.get());
10577 CombNextLB = SemaRef.ActOnFinishFullExpr(Expr: CombNextLB.get(),
10578 /*DiscardedValue=*/false);
10579 if (!CombNextLB.isUsable())
10580 return 0;
10581 // UB + ST
10582 CombNextUB =
10583 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: CombUB.get(), RHSExpr: ST.get());
10584 if (!CombNextUB.isUsable())
10585 return 0;
10586 // UB = UB + ST
10587 CombNextUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: CombUB.get(),
10588 RHSExpr: CombNextUB.get());
10589 CombNextUB = SemaRef.ActOnFinishFullExpr(Expr: CombNextUB.get(),
10590 /*DiscardedValue=*/false);
10591 if (!CombNextUB.isUsable())
10592 return 0;
10593 }
10594 }
10595
10596 // Create increment expression for distribute loop when combined in a same
10597 // directive with for as IV = IV + ST; ensure upper bound expression based
10598 // on PrevUB instead of NumIterations - used to implement 'for' when found
10599 // in combination with 'distribute', like in 'distribute parallel for'
10600 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10601 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10602 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10603 DistCond = SemaRef.BuildBinOp(
10604 S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE, LHSExpr: IV.get(), RHSExpr: BoundUB);
10605 assert(DistCond.isUsable() && "distribute cond expr was not built");
10606
10607 DistInc =
10608 SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Add, LHSExpr: IV.get(), RHSExpr: ST.get());
10609 assert(DistInc.isUsable() && "distribute inc expr was not built");
10610 DistInc = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Assign, LHSExpr: IV.get(),
10611 RHSExpr: DistInc.get());
10612 DistInc =
10613 SemaRef.ActOnFinishFullExpr(Expr: DistInc.get(), /*DiscardedValue=*/false);
10614 assert(DistInc.isUsable() && "distribute inc expr was not built");
10615
10616 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10617 // construct
10618 ExprResult NewPrevUB = PrevUB;
10619 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10620 if (!SemaRef.Context.hasSameType(T1: UB.get()->getType(),
10621 T2: PrevUB.get()->getType())) {
10622 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10623 LParenLoc: DistEUBLoc,
10624 Ty: SemaRef.Context.getTrivialTypeSourceInfo(T: UB.get()->getType()),
10625 RParenLoc: DistEUBLoc, Op: NewPrevUB.get());
10626 if (!NewPrevUB.isUsable())
10627 return 0;
10628 }
10629 ExprResult IsUBGreater = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistEUBLoc, Opc: BO_GT,
10630 LHSExpr: UB.get(), RHSExpr: NewPrevUB.get());
10631 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10632 QuestionLoc: DistEUBLoc, ColonLoc: DistEUBLoc, CondExpr: IsUBGreater.get(), LHSExpr: NewPrevUB.get(), RHSExpr: UB.get());
10633 PrevEUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Assign, LHSExpr: UB.get(),
10634 RHSExpr: CondOp.get());
10635 PrevEUB =
10636 SemaRef.ActOnFinishFullExpr(Expr: PrevEUB.get(), /*DiscardedValue=*/false);
10637
10638 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10639 // parallel for is in combination with a distribute directive with
10640 // schedule(static, 1)
10641 Expr *BoundPrevUB = PrevUB.get();
10642 if (UseStrictCompare) {
10643 BoundPrevUB =
10644 SemaRef
10645 .BuildBinOp(
10646 S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundPrevUB,
10647 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10648 .get();
10649 BoundPrevUB =
10650 SemaRef.ActOnFinishFullExpr(Expr: BoundPrevUB, /*DiscardedValue=*/false)
10651 .get();
10652 }
10653 ParForInDistCond =
10654 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE,
10655 LHSExpr: IV.get(), RHSExpr: BoundPrevUB);
10656 }
10657
10658 // Build updates and final values of the loop counters.
10659 bool HasErrors = false;
10660 Built.Counters.resize(N: NestedLoopCount);
10661 Built.Inits.resize(N: NestedLoopCount);
10662 Built.Updates.resize(N: NestedLoopCount);
10663 Built.Finals.resize(N: NestedLoopCount);
10664 Built.DependentCounters.resize(N: NestedLoopCount);
10665 Built.DependentInits.resize(N: NestedLoopCount);
10666 Built.FinalsConditions.resize(N: NestedLoopCount);
10667 {
10668 // We implement the following algorithm for obtaining the
10669 // original loop iteration variable values based on the
10670 // value of the collapsed loop iteration variable IV.
10671 //
10672 // Let n+1 be the number of collapsed loops in the nest.
10673 // Iteration variables (I0, I1, .... In)
10674 // Iteration counts (N0, N1, ... Nn)
10675 //
10676 // Acc = IV;
10677 //
10678 // To compute Ik for loop k, 0 <= k <= n, generate:
10679 // Prod = N(k+1) * N(k+2) * ... * Nn;
10680 // Ik = Acc / Prod;
10681 // Acc -= Ik * Prod;
10682 //
10683 ExprResult Acc = IV;
10684 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10685 LoopIterationSpace &IS = IterSpaces[Cnt];
10686 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10687 ExprResult Iter;
10688
10689 // Compute prod
10690 ExprResult Prod = SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get();
10691 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10692 Prod = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Mul, LHSExpr: Prod.get(),
10693 RHSExpr: IterSpaces[K].NumIterations);
10694
10695 // Iter = Acc / Prod
10696 // If there is at least one more inner loop to avoid
10697 // multiplication by 1.
10698 if (Cnt + 1 < NestedLoopCount)
10699 Iter =
10700 SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Div, LHSExpr: Acc.get(), RHSExpr: Prod.get());
10701 else
10702 Iter = Acc;
10703 if (!Iter.isUsable()) {
10704 HasErrors = true;
10705 break;
10706 }
10707
10708 // Update Acc:
10709 // Acc -= Iter * Prod
10710 // Check if there is at least one more inner loop to avoid
10711 // multiplication by 1.
10712 if (Cnt + 1 < NestedLoopCount)
10713 Prod = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Mul, LHSExpr: Iter.get(),
10714 RHSExpr: Prod.get());
10715 else
10716 Prod = Iter;
10717 Acc = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Sub, LHSExpr: Acc.get(), RHSExpr: Prod.get());
10718
10719 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10720 auto *VD = cast<VarDecl>(Val: cast<DeclRefExpr>(Val: IS.CounterVar)->getDecl());
10721 DeclRefExpr *CounterVar = buildDeclRefExpr(
10722 S&: SemaRef, D: VD, Ty: IS.CounterVar->getType(), Loc: IS.CounterVar->getExprLoc(),
10723 /*RefersToCapture=*/true);
10724 ExprResult Init =
10725 buildCounterInit(SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar,
10726 Start: IS.CounterInit, IsNonRectangularLB: IS.IsNonRectangularLB, Captures);
10727 if (!Init.isUsable()) {
10728 HasErrors = true;
10729 break;
10730 }
10731 ExprResult Update = buildCounterUpdate(
10732 SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar, Start: IS.CounterInit, Iter,
10733 Step: IS.CounterStep, Subtract: IS.Subtract, IsNonRectangularLB: IS.IsNonRectangularLB, Captures: &Captures);
10734 if (!Update.isUsable()) {
10735 HasErrors = true;
10736 break;
10737 }
10738
10739 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10740 ExprResult Final =
10741 buildCounterUpdate(SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar,
10742 Start: IS.CounterInit, Iter: IS.NumIterations, Step: IS.CounterStep,
10743 Subtract: IS.Subtract, IsNonRectangularLB: IS.IsNonRectangularLB, Captures: &Captures);
10744 if (!Final.isUsable()) {
10745 HasErrors = true;
10746 break;
10747 }
10748
10749 if (!Update.isUsable() || !Final.isUsable()) {
10750 HasErrors = true;
10751 break;
10752 }
10753 // Save results
10754 Built.Counters[Cnt] = IS.CounterVar;
10755 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10756 Built.Inits[Cnt] = Init.get();
10757 Built.Updates[Cnt] = Update.get();
10758 Built.Finals[Cnt] = Final.get();
10759 Built.DependentCounters[Cnt] = nullptr;
10760 Built.DependentInits[Cnt] = nullptr;
10761 Built.FinalsConditions[Cnt] = nullptr;
10762 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10763 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10764 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10765 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10766 }
10767 }
10768 }
10769
10770 if (HasErrors)
10771 return 0;
10772
10773 // Save results
10774 Built.IterationVarRef = IV.get();
10775 Built.LastIteration = LastIteration.get();
10776 Built.NumIterations = NumIterations.get();
10777 Built.CalcLastIteration = SemaRef
10778 .ActOnFinishFullExpr(Expr: CalcLastIteration.get(),
10779 /*DiscardedValue=*/false)
10780 .get();
10781 Built.PreCond = PreCond.get();
10782 Built.PreInits = buildPreInits(Context&: C, Captures);
10783 Built.Cond = Cond.get();
10784 Built.Init = Init.get();
10785 Built.Inc = Inc.get();
10786 Built.LB = LB.get();
10787 Built.UB = UB.get();
10788 Built.IL = IL.get();
10789 Built.ST = ST.get();
10790 Built.EUB = EUB.get();
10791 Built.NLB = NextLB.get();
10792 Built.NUB = NextUB.get();
10793 Built.PrevLB = PrevLB.get();
10794 Built.PrevUB = PrevUB.get();
10795 Built.DistInc = DistInc.get();
10796 Built.PrevEUB = PrevEUB.get();
10797 Built.DistCombinedFields.LB = CombLB.get();
10798 Built.DistCombinedFields.UB = CombUB.get();
10799 Built.DistCombinedFields.EUB = CombEUB.get();
10800 Built.DistCombinedFields.Init = CombInit.get();
10801 Built.DistCombinedFields.Cond = CombCond.get();
10802 Built.DistCombinedFields.NLB = CombNextLB.get();
10803 Built.DistCombinedFields.NUB = CombNextUB.get();
10804 Built.DistCombinedFields.DistCond = CombDistCond.get();
10805 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10806
10807 return NestedLoopCount;
10808}
10809
10810static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
10811 auto CollapseClauses =
10812 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10813 if (CollapseClauses.begin() != CollapseClauses.end())
10814 return (*CollapseClauses.begin())->getNumForLoops();
10815 return nullptr;
10816}
10817
10818static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
10819 auto OrderedClauses =
10820 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10821 if (OrderedClauses.begin() != OrderedClauses.end())
10822 return (*OrderedClauses.begin())->getNumForLoops();
10823 return nullptr;
10824}
10825
10826static bool checkSimdlenSafelenSpecified(Sema &S,
10827 const ArrayRef<OMPClause *> Clauses) {
10828 const OMPSafelenClause *Safelen = nullptr;
10829 const OMPSimdlenClause *Simdlen = nullptr;
10830
10831 for (const OMPClause *Clause : Clauses) {
10832 if (Clause->getClauseKind() == OMPC_safelen)
10833 Safelen = cast<OMPSafelenClause>(Val: Clause);
10834 else if (Clause->getClauseKind() == OMPC_simdlen)
10835 Simdlen = cast<OMPSimdlenClause>(Val: Clause);
10836 if (Safelen && Simdlen)
10837 break;
10838 }
10839
10840 if (Simdlen && Safelen) {
10841 const Expr *SimdlenLength = Simdlen->getSimdlen();
10842 const Expr *SafelenLength = Safelen->getSafelen();
10843 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10844 SimdlenLength->isInstantiationDependent() ||
10845 SimdlenLength->containsUnexpandedParameterPack())
10846 return false;
10847 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10848 SafelenLength->isInstantiationDependent() ||
10849 SafelenLength->containsUnexpandedParameterPack())
10850 return false;
10851 Expr::EvalResult SimdlenResult, SafelenResult;
10852 SimdlenLength->EvaluateAsInt(Result&: SimdlenResult, Ctx: S.Context);
10853 SafelenLength->EvaluateAsInt(Result&: SafelenResult, Ctx: S.Context);
10854 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10855 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10856 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10857 // If both simdlen and safelen clauses are specified, the value of the
10858 // simdlen parameter must be less than or equal to the value of the safelen
10859 // parameter.
10860 if (SimdlenRes > SafelenRes) {
10861 S.Diag(Loc: SimdlenLength->getExprLoc(),
10862 DiagID: diag::err_omp_wrong_simdlen_safelen_values)
10863 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10864 return true;
10865 }
10866 }
10867 return false;
10868}
10869
10870StmtResult SemaOpenMP::ActOnOpenMPSimdDirective(
10871 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10872 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10873 if (!AStmt)
10874 return StmtError();
10875
10876 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_simd, AStmt);
10877
10878 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10879 OMPLoopBasedDirective::HelperExprs B;
10880 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10881 // define the nested loops number.
10882 unsigned NestedLoopCount = checkOpenMPLoop(
10883 DKind: OMPD_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
10884 AStmt: CS, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
10885 if (NestedLoopCount == 0)
10886 return StmtError();
10887
10888 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10889 return StmtError();
10890
10891 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
10892 return StmtError();
10893
10894 auto *SimdDirective = OMPSimdDirective::Create(
10895 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10896 return SimdDirective;
10897}
10898
10899StmtResult SemaOpenMP::ActOnOpenMPForDirective(
10900 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10901 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10902 if (!AStmt)
10903 return StmtError();
10904
10905 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10906 OMPLoopBasedDirective::HelperExprs B;
10907 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10908 // define the nested loops number.
10909 unsigned NestedLoopCount = checkOpenMPLoop(
10910 DKind: OMPD_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
10911 AStmt, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
10912 if (NestedLoopCount == 0)
10913 return StmtError();
10914
10915 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10916 return StmtError();
10917
10918 auto *ForDirective = OMPForDirective::Create(
10919 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
10920 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10921 return ForDirective;
10922}
10923
10924StmtResult SemaOpenMP::ActOnOpenMPForSimdDirective(
10925 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10926 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10927 if (!AStmt)
10928 return StmtError();
10929
10930 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_for_simd, AStmt);
10931
10932 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10933 OMPLoopBasedDirective::HelperExprs B;
10934 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10935 // define the nested loops number.
10936 unsigned NestedLoopCount =
10937 checkOpenMPLoop(DKind: OMPD_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
10938 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
10939 VarsWithImplicitDSA, Built&: B);
10940 if (NestedLoopCount == 0)
10941 return StmtError();
10942
10943 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10944 return StmtError();
10945
10946 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
10947 return StmtError();
10948
10949 return OMPForSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
10950 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10951}
10952
10953static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind,
10954 Stmt *AStmt, DSAStackTy *Stack) {
10955 if (!AStmt)
10956 return true;
10957
10958 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10959 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
10960 auto BaseStmt = AStmt;
10961 while (auto *CS = dyn_cast_or_null<CapturedStmt>(Val: BaseStmt))
10962 BaseStmt = CS->getCapturedStmt();
10963 if (auto *C = dyn_cast_or_null<CompoundStmt>(Val: BaseStmt)) {
10964 auto S = C->children();
10965 if (S.begin() == S.end())
10966 return true;
10967 // All associated statements must be '#pragma omp section' except for
10968 // the first one.
10969 for (Stmt *SectionStmt : llvm::drop_begin(RangeOrContainer&: S)) {
10970 if (!SectionStmt || !isa<OMPSectionDirective>(Val: SectionStmt)) {
10971 if (SectionStmt)
10972 SemaRef.Diag(Loc: SectionStmt->getBeginLoc(),
10973 DiagID: diag::err_omp_sections_substmt_not_section)
10974 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
10975 return true;
10976 }
10977 cast<OMPSectionDirective>(Val: SectionStmt)
10978 ->setHasCancel(Stack->isCancelRegion());
10979 }
10980 } else {
10981 SemaRef.Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_sections_not_compound_stmt)
10982 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
10983 return true;
10984 }
10985 return false;
10986}
10987
10988StmtResult
10989SemaOpenMP::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
10990 Stmt *AStmt, SourceLocation StartLoc,
10991 SourceLocation EndLoc) {
10992 if (checkSectionsDirective(SemaRef, DKind: OMPD_sections, AStmt, DSAStack))
10993 return StmtError();
10994
10995 SemaRef.setFunctionHasBranchProtectedScope();
10996
10997 return OMPSectionsDirective::Create(
10998 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
10999 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11000}
11001
11002StmtResult SemaOpenMP::ActOnOpenMPSectionDirective(Stmt *AStmt,
11003 SourceLocation StartLoc,
11004 SourceLocation EndLoc) {
11005 if (!AStmt)
11006 return StmtError();
11007
11008 SemaRef.setFunctionHasBranchProtectedScope();
11009 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
11010
11011 return OMPSectionDirective::Create(C: getASTContext(), StartLoc, EndLoc, AssociatedStmt: AStmt,
11012 DSAStack->isCancelRegion());
11013}
11014
11015static Expr *getDirectCallExpr(Expr *E) {
11016 E = E->IgnoreParenCasts()->IgnoreImplicit();
11017 if (auto *CE = dyn_cast<CallExpr>(Val: E))
11018 if (CE->getDirectCallee())
11019 return E;
11020 return nullptr;
11021}
11022
11023StmtResult
11024SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
11025 Stmt *AStmt, SourceLocation StartLoc,
11026 SourceLocation EndLoc) {
11027 if (!AStmt)
11028 return StmtError();
11029
11030 Stmt *S = cast<CapturedStmt>(Val: AStmt)->getCapturedStmt();
11031
11032 // 5.1 OpenMP
11033 // expression-stmt : an expression statement with one of the following forms:
11034 // expression = target-call ( [expression-list] );
11035 // target-call ( [expression-list] );
11036
11037 SourceLocation TargetCallLoc;
11038
11039 if (!SemaRef.CurContext->isDependentContext()) {
11040 Expr *TargetCall = nullptr;
11041
11042 auto *E = dyn_cast<Expr>(Val: S);
11043 if (!E) {
11044 Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_dispatch_statement_call);
11045 return StmtError();
11046 }
11047
11048 E = E->IgnoreParenCasts()->IgnoreImplicit();
11049
11050 if (auto *BO = dyn_cast<BinaryOperator>(Val: E)) {
11051 if (BO->getOpcode() == BO_Assign)
11052 TargetCall = getDirectCallExpr(E: BO->getRHS());
11053 } else {
11054 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(Val: E))
11055 if (COCE->getOperator() == OO_Equal)
11056 TargetCall = getDirectCallExpr(E: COCE->getArg(Arg: 1));
11057 if (!TargetCall)
11058 TargetCall = getDirectCallExpr(E);
11059 }
11060 if (!TargetCall) {
11061 Diag(Loc: E->getBeginLoc(), DiagID: diag::err_omp_dispatch_statement_call);
11062 return StmtError();
11063 }
11064 TargetCallLoc = TargetCall->getExprLoc();
11065 }
11066
11067 SemaRef.setFunctionHasBranchProtectedScope();
11068
11069 return OMPDispatchDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11070 Clauses, AssociatedStmt: AStmt, TargetCallLoc);
11071}
11072
11073static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
11074 OpenMPDirectiveKind K,
11075 DSAStackTy *Stack) {
11076 bool ErrorFound = false;
11077 for (OMPClause *C : Clauses) {
11078 if (auto *LPC = dyn_cast<OMPLastprivateClause>(Val: C)) {
11079 for (Expr *RefExpr : LPC->varlist()) {
11080 SourceLocation ELoc;
11081 SourceRange ERange;
11082 Expr *SimpleRefExpr = RefExpr;
11083 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange);
11084 if (ValueDecl *D = Res.first) {
11085 auto &&Info = Stack->isLoopControlVariable(D);
11086 if (!Info.first) {
11087 unsigned OMPVersion = S.getLangOpts().OpenMP;
11088 S.Diag(Loc: ELoc, DiagID: diag::err_omp_lastprivate_loop_var_non_loop_iteration)
11089 << getOpenMPDirectiveName(D: K, Ver: OMPVersion);
11090 ErrorFound = true;
11091 }
11092 }
11093 }
11094 }
11095 }
11096 return ErrorFound;
11097}
11098
11099StmtResult SemaOpenMP::ActOnOpenMPGenericLoopDirective(
11100 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11101 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11102 if (!AStmt)
11103 return StmtError();
11104
11105 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11106 // A list item may not appear in a lastprivate clause unless it is the
11107 // loop iteration variable of a loop that is associated with the construct.
11108 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_loop, DSAStack))
11109 return StmtError();
11110
11111 setBranchProtectedScope(SemaRef, DKind: OMPD_loop, AStmt);
11112
11113 OMPLoopDirective::HelperExprs B;
11114 // In presence of clause 'collapse', it will define the nested loops number.
11115 unsigned NestedLoopCount = checkOpenMPLoop(
11116 DKind: OMPD_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
11117 AStmt, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
11118 if (NestedLoopCount == 0)
11119 return StmtError();
11120
11121 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11122 "omp loop exprs were not built");
11123
11124 return OMPGenericLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11125 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11126}
11127
11128/// Check the number of expressions specified in a multidimensional clause and
11129/// return whether an error was encountered.
11130static bool validateMultidimClauseExprs(
11131 SemaBase &SemaRef, OpenMPClauseKind ClauseKind,
11132 SourceLocation ClauseBeginLoc, ArrayRef<const Expr *> ClauseVarList,
11133 const Expr *DimsModifierExpr, const OMPXBareClause *BareClause = nullptr) {
11134 const uint64_t NumVars = ClauseVarList.size();
11135
11136 // The ompx_bare clause allows up to three expressions.
11137 if (BareClause) {
11138 if (NumVars > 3) {
11139 SemaRef.Diag(Loc: ClauseBeginLoc,
11140 DiagID: diag::err_ompx_more_than_three_expr_not_allowed)
11141 << getOpenMPClauseName(C: ClauseKind);
11142 return true;
11143 }
11144 return false;
11145 }
11146
11147 // By default, only one expression accepted.
11148 uint64_t MaxExprs = 1;
11149 if (DimsModifierExpr) {
11150 // Cannot verify the expected size yet.
11151 if (DimsModifierExpr->isInstantiationDependent())
11152 return false;
11153
11154 // The dims modifier determines the exact number of expressions.
11155 MaxExprs = DimsModifierExpr->EvaluateKnownConstInt(Ctx: SemaRef.getASTContext())
11156 .getExtValue();
11157 }
11158
11159 if (NumVars != MaxExprs) {
11160 SemaRef.Diag(Loc: ClauseBeginLoc, DiagID: diag::err_omp_unexpected_num_exprs)
11161 << getOpenMPClauseName(C: ClauseKind) << MaxExprs << NumVars;
11162 return true;
11163 }
11164 if (NumVars > 3) {
11165 SemaRef.Diag(Loc: ClauseBeginLoc, DiagID: diag::err_omp_max_three_exprs)
11166 << getOpenMPClauseName(C: ClauseKind);
11167 return true;
11168 }
11169 return false;
11170}
11171
11172/// Check the number of expressions specified in a multidimensional clause and
11173/// return whether an error was encountered.
11174template <typename ClauseT>
11175static bool validateMultidimClauseExprs(SemaBase &SemaRef,
11176 const ClauseT *Clause,
11177 const OMPXBareClause *BareClause) {
11178 if (!Clause)
11179 return false;
11180 return validateMultidimClauseExprs(
11181 SemaRef, Clause->getClauseKind(), Clause->getBeginLoc(),
11182 Clause->getVarRefs(), Clause->getDimsModifierExpr(), BareClause);
11183}
11184
11185/// Check the number of expressions specified in clauses that can contain
11186/// multidimensional values, e.g., num_teams and thread_limit. The function
11187/// returns true on error.
11188static bool validateMultidimClauses(SemaBase &SemaRef,
11189 ArrayRef<OMPClause *> Clauses,
11190 bool MayHaveBareClause = false) {
11191 auto BareClauseIt =
11192 MayHaveBareClause ? llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OMPXBareClause>)
11193 : Clauses.end();
11194 auto ThreadLimitIt =
11195 llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OMPThreadLimitClause>);
11196 auto NumTeamsIt = llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OMPNumTeamsClause>);
11197
11198 const auto *BareClause = BareClauseIt != Clauses.end()
11199 ? cast<OMPXBareClause>(Val: *BareClauseIt)
11200 : nullptr;
11201 const auto *ThreadLimitClause =
11202 ThreadLimitIt != Clauses.end()
11203 ? cast<OMPThreadLimitClause>(Val: *ThreadLimitIt)
11204 : nullptr;
11205 const auto *NumTeamsClause = NumTeamsIt != Clauses.end()
11206 ? cast<OMPNumTeamsClause>(Val: *NumTeamsIt)
11207 : nullptr;
11208
11209 if (BareClause) {
11210 if (!NumTeamsClause || !ThreadLimitClause) {
11211 SemaRef.Diag(Loc: BareClause->getBeginLoc(), DiagID: diag::err_ompx_bare_no_grid);
11212 return true;
11213 }
11214 if (ThreadLimitClause->getModifier() == OMPC_THREADLIMIT_dims ||
11215 NumTeamsClause->getModifier() == OMPC_NUMTEAMS_dims) {
11216 SemaRef.Diag(Loc: BareClause->getBeginLoc(), DiagID: diag::err_ompx_bare_no_dims);
11217 return true;
11218 }
11219 }
11220 return validateMultidimClauseExprs(SemaRef, Clause: ThreadLimitClause, BareClause) ||
11221 validateMultidimClauseExprs(SemaRef, Clause: NumTeamsClause, BareClause);
11222}
11223
11224StmtResult SemaOpenMP::ActOnOpenMPTeamsGenericLoopDirective(
11225 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11226 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11227 if (!AStmt)
11228 return StmtError();
11229
11230 if (validateMultidimClauses(SemaRef&: *this, Clauses))
11231 return StmtError();
11232
11233 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11234 // A list item may not appear in a lastprivate clause unless it is the
11235 // loop iteration variable of a loop that is associated with the construct.
11236 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_teams_loop, DSAStack))
11237 return StmtError();
11238
11239 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_teams_loop, AStmt);
11240
11241 OMPLoopDirective::HelperExprs B;
11242 // In presence of clause 'collapse', it will define the nested loops number.
11243 unsigned NestedLoopCount =
11244 checkOpenMPLoop(DKind: OMPD_teams_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11245 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11246 VarsWithImplicitDSA, Built&: B);
11247 if (NestedLoopCount == 0)
11248 return StmtError();
11249
11250 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11251 "omp loop exprs were not built");
11252
11253 DSAStack->setParentTeamsRegionLoc(StartLoc);
11254
11255 return OMPTeamsGenericLoopDirective::Create(
11256 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11257}
11258
11259StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsGenericLoopDirective(
11260 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11261 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11262 if (!AStmt)
11263 return StmtError();
11264
11265 if (validateMultidimClauses(SemaRef&: *this, Clauses))
11266 return StmtError();
11267
11268 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11269 // A list item may not appear in a lastprivate clause unless it is the
11270 // loop iteration variable of a loop that is associated with the construct.
11271 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_target_teams_loop,
11272 DSAStack))
11273 return StmtError();
11274
11275 CapturedStmt *CS =
11276 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams_loop, AStmt);
11277
11278 OMPLoopDirective::HelperExprs B;
11279 // In presence of clause 'collapse', it will define the nested loops number.
11280 unsigned NestedLoopCount =
11281 checkOpenMPLoop(DKind: OMPD_target_teams_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11282 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11283 VarsWithImplicitDSA, Built&: B);
11284 if (NestedLoopCount == 0)
11285 return StmtError();
11286
11287 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11288 "omp loop exprs were not built");
11289
11290 return OMPTargetTeamsGenericLoopDirective::Create(
11291 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
11292 CanBeParallelFor: teamsLoopCanBeParallelFor(AStmt, SemaRef));
11293}
11294
11295StmtResult SemaOpenMP::ActOnOpenMPParallelGenericLoopDirective(
11296 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11297 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11298 if (!AStmt)
11299 return StmtError();
11300
11301 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11302 // A list item may not appear in a lastprivate clause unless it is the
11303 // loop iteration variable of a loop that is associated with the construct.
11304 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_parallel_loop,
11305 DSAStack))
11306 return StmtError();
11307
11308 CapturedStmt *CS =
11309 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_loop, AStmt);
11310
11311 OMPLoopDirective::HelperExprs B;
11312 // In presence of clause 'collapse', it will define the nested loops number.
11313 unsigned NestedLoopCount =
11314 checkOpenMPLoop(DKind: OMPD_parallel_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11315 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11316 VarsWithImplicitDSA, Built&: B);
11317 if (NestedLoopCount == 0)
11318 return StmtError();
11319
11320 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11321 "omp loop exprs were not built");
11322
11323 return OMPParallelGenericLoopDirective::Create(
11324 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11325}
11326
11327StmtResult SemaOpenMP::ActOnOpenMPTargetParallelGenericLoopDirective(
11328 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11329 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11330 if (!AStmt)
11331 return StmtError();
11332
11333 if (validateMultidimClauses(SemaRef&: *this, Clauses))
11334 return StmtError();
11335
11336 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11337 // A list item may not appear in a lastprivate clause unless it is the
11338 // loop iteration variable of a loop that is associated with the construct.
11339 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_target_parallel_loop,
11340 DSAStack))
11341 return StmtError();
11342
11343 CapturedStmt *CS =
11344 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_loop, AStmt);
11345
11346 OMPLoopDirective::HelperExprs B;
11347 // In presence of clause 'collapse', it will define the nested loops number.
11348 unsigned NestedLoopCount =
11349 checkOpenMPLoop(DKind: OMPD_target_parallel_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11350 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
11351 VarsWithImplicitDSA, Built&: B);
11352 if (NestedLoopCount == 0)
11353 return StmtError();
11354
11355 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11356 "omp loop exprs were not built");
11357
11358 return OMPTargetParallelGenericLoopDirective::Create(
11359 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11360}
11361
11362StmtResult SemaOpenMP::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
11363 Stmt *AStmt,
11364 SourceLocation StartLoc,
11365 SourceLocation EndLoc) {
11366 if (!AStmt)
11367 return StmtError();
11368
11369 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11370
11371 SemaRef.setFunctionHasBranchProtectedScope();
11372
11373 // OpenMP [2.7.3, single Construct, Restrictions]
11374 // The copyprivate clause must not be used with the nowait clause.
11375 const OMPClause *Nowait = nullptr;
11376 const OMPClause *Copyprivate = nullptr;
11377 for (const OMPClause *Clause : Clauses) {
11378 if (Clause->getClauseKind() == OMPC_nowait)
11379 Nowait = Clause;
11380 else if (Clause->getClauseKind() == OMPC_copyprivate)
11381 Copyprivate = Clause;
11382 if (Copyprivate && Nowait) {
11383 Diag(Loc: Copyprivate->getBeginLoc(),
11384 DiagID: diag::err_omp_single_copyprivate_with_nowait);
11385 Diag(Loc: Nowait->getBeginLoc(), DiagID: diag::note_omp_nowait_clause_here);
11386 return StmtError();
11387 }
11388 }
11389
11390 return OMPSingleDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11391 AssociatedStmt: AStmt);
11392}
11393
11394StmtResult SemaOpenMP::ActOnOpenMPMasterDirective(Stmt *AStmt,
11395 SourceLocation StartLoc,
11396 SourceLocation EndLoc) {
11397 if (!AStmt)
11398 return StmtError();
11399
11400 SemaRef.setFunctionHasBranchProtectedScope();
11401
11402 return OMPMasterDirective::Create(C: getASTContext(), StartLoc, EndLoc, AssociatedStmt: AStmt);
11403}
11404
11405StmtResult SemaOpenMP::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
11406 Stmt *AStmt,
11407 SourceLocation StartLoc,
11408 SourceLocation EndLoc) {
11409 if (!AStmt)
11410 return StmtError();
11411
11412 SemaRef.setFunctionHasBranchProtectedScope();
11413
11414 return OMPMaskedDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11415 AssociatedStmt: AStmt);
11416}
11417
11418StmtResult SemaOpenMP::ActOnOpenMPCriticalDirective(
11419 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11420 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11421 if (!AStmt)
11422 return StmtError();
11423
11424 bool ErrorFound = false;
11425 llvm::APSInt Hint;
11426 SourceLocation HintLoc;
11427 bool DependentHint = false;
11428 for (const OMPClause *C : Clauses) {
11429 if (C->getClauseKind() == OMPC_hint) {
11430 if (!DirName.getName()) {
11431 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_hint_clause_no_name);
11432 ErrorFound = true;
11433 }
11434 Expr *E = cast<OMPHintClause>(Val: C)->getHint();
11435 if (E->isTypeDependent() || E->isValueDependent() ||
11436 E->isInstantiationDependent()) {
11437 DependentHint = true;
11438 } else {
11439 Hint = E->EvaluateKnownConstInt(Ctx: getASTContext());
11440 HintLoc = C->getBeginLoc();
11441 }
11442 }
11443 }
11444 if (ErrorFound)
11445 return StmtError();
11446 const auto Pair = DSAStack->getCriticalWithHint(Name: DirName);
11447 if (Pair.first && DirName.getName() && !DependentHint) {
11448 if (llvm::APSInt::compareValues(I1: Hint, I2: Pair.second) != 0) {
11449 Diag(Loc: StartLoc, DiagID: diag::err_omp_critical_with_hint);
11450 if (HintLoc.isValid())
11451 Diag(Loc: HintLoc, DiagID: diag::note_omp_critical_hint_here)
11452 << 0 << toString(I: Hint, /*Radix=*/10, /*Signed=*/false);
11453 else
11454 Diag(Loc: StartLoc, DiagID: diag::note_omp_critical_no_hint) << 0;
11455 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11456 Diag(Loc: C->getBeginLoc(), DiagID: diag::note_omp_critical_hint_here)
11457 << 1
11458 << toString(I: C->getHint()->EvaluateKnownConstInt(Ctx: getASTContext()),
11459 /*Radix=*/10, /*Signed=*/false);
11460 } else {
11461 Diag(Loc: Pair.first->getBeginLoc(), DiagID: diag::note_omp_critical_no_hint) << 1;
11462 }
11463 }
11464 }
11465
11466 SemaRef.setFunctionHasBranchProtectedScope();
11467
11468 auto *Dir = OMPCriticalDirective::Create(C: getASTContext(), Name: DirName, StartLoc,
11469 EndLoc, Clauses, AssociatedStmt: AStmt);
11470 if (!Pair.first && DirName.getName() && !DependentHint)
11471 DSAStack->addCriticalWithHint(D: Dir, Hint);
11472 return Dir;
11473}
11474
11475StmtResult SemaOpenMP::ActOnOpenMPParallelForDirective(
11476 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11477 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11478 if (!AStmt)
11479 return StmtError();
11480
11481 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_for, AStmt);
11482
11483 OMPLoopBasedDirective::HelperExprs B;
11484 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11485 // define the nested loops number.
11486 unsigned NestedLoopCount =
11487 checkOpenMPLoop(DKind: OMPD_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11488 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt, SemaRef, DSA&: *DSAStack,
11489 VarsWithImplicitDSA, Built&: B);
11490 if (NestedLoopCount == 0)
11491 return StmtError();
11492
11493 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11494 return StmtError();
11495
11496 return OMPParallelForDirective::Create(
11497 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
11498 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11499}
11500
11501StmtResult SemaOpenMP::ActOnOpenMPParallelForSimdDirective(
11502 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11503 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11504 if (!AStmt)
11505 return StmtError();
11506
11507 CapturedStmt *CS =
11508 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_for_simd, AStmt);
11509
11510 OMPLoopBasedDirective::HelperExprs B;
11511 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11512 // define the nested loops number.
11513 unsigned NestedLoopCount =
11514 checkOpenMPLoop(DKind: OMPD_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
11515 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
11516 VarsWithImplicitDSA, Built&: B);
11517 if (NestedLoopCount == 0)
11518 return StmtError();
11519
11520 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11521 return StmtError();
11522
11523 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
11524 return StmtError();
11525
11526 return OMPParallelForSimdDirective::Create(
11527 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11528}
11529
11530StmtResult SemaOpenMP::ActOnOpenMPParallelMasterDirective(
11531 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11532 SourceLocation EndLoc) {
11533 if (!AStmt)
11534 return StmtError();
11535
11536 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_master, AStmt);
11537
11538 return OMPParallelMasterDirective::Create(
11539 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11540 DSAStack->getTaskgroupReductionRef());
11541}
11542
11543StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedDirective(
11544 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11545 SourceLocation EndLoc) {
11546 if (!AStmt)
11547 return StmtError();
11548
11549 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_masked, AStmt);
11550
11551 return OMPParallelMaskedDirective::Create(
11552 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11553 DSAStack->getTaskgroupReductionRef());
11554}
11555
11556StmtResult SemaOpenMP::ActOnOpenMPParallelSectionsDirective(
11557 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11558 SourceLocation EndLoc) {
11559 if (checkSectionsDirective(SemaRef, DKind: OMPD_parallel_sections, AStmt, DSAStack))
11560 return StmtError();
11561
11562 SemaRef.setFunctionHasBranchProtectedScope();
11563
11564 return OMPParallelSectionsDirective::Create(
11565 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11566 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11567}
11568
11569/// Find and diagnose mutually exclusive clause kinds.
11570static bool checkMutuallyExclusiveClauses(
11571 Sema &S, ArrayRef<OMPClause *> Clauses,
11572 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11573 const OMPClause *PrevClause = nullptr;
11574 bool ErrorFound = false;
11575 for (const OMPClause *C : Clauses) {
11576 if (llvm::is_contained(Range&: MutuallyExclusiveClauses, Element: C->getClauseKind())) {
11577 if (!PrevClause) {
11578 PrevClause = C;
11579 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11580 S.Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_clauses_mutually_exclusive)
11581 << getOpenMPClauseNameForDiag(C: C->getClauseKind())
11582 << getOpenMPClauseNameForDiag(C: PrevClause->getClauseKind());
11583 S.Diag(Loc: PrevClause->getBeginLoc(), DiagID: diag::note_omp_previous_clause)
11584 << getOpenMPClauseNameForDiag(C: PrevClause->getClauseKind());
11585 ErrorFound = true;
11586 }
11587 }
11588 }
11589 return ErrorFound;
11590}
11591
11592StmtResult SemaOpenMP::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
11593 Stmt *AStmt,
11594 SourceLocation StartLoc,
11595 SourceLocation EndLoc) {
11596 if (!AStmt)
11597 return StmtError();
11598
11599 // OpenMP 5.0, 2.10.1 task Construct
11600 // If a detach clause appears on the directive, then a mergeable clause cannot
11601 // appear on the same directive.
11602 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
11603 MutuallyExclusiveClauses: {OMPC_detach, OMPC_mergeable}))
11604 return StmtError();
11605
11606 setBranchProtectedScope(SemaRef, DKind: OMPD_task, AStmt);
11607
11608 return OMPTaskDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11609 AssociatedStmt: AStmt, DSAStack->isCancelRegion());
11610}
11611
11612StmtResult SemaOpenMP::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
11613 SourceLocation EndLoc) {
11614 return OMPTaskyieldDirective::Create(C: getASTContext(), StartLoc, EndLoc);
11615}
11616
11617StmtResult SemaOpenMP::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
11618 SourceLocation EndLoc) {
11619 return OMPBarrierDirective::Create(C: getASTContext(), StartLoc, EndLoc);
11620}
11621
11622StmtResult SemaOpenMP::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
11623 SourceLocation StartLoc,
11624 SourceLocation EndLoc,
11625 bool InExContext) {
11626 const OMPAtClause *AtC =
11627 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11628
11629 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11630 Diag(Loc: AtC->getAtKindKwLoc(), DiagID: diag::err_omp_unexpected_execution_modifier);
11631 return StmtError();
11632 }
11633
11634 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11635 const OMPSeverityClause *SeverityC =
11636 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11637 const OMPMessageClause *MessageC =
11638 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11639 std::optional<std::string> SL =
11640 MessageC ? MessageC->tryEvaluateString(Ctx&: getASTContext()) : std::nullopt;
11641
11642 if (MessageC && !SL)
11643 Diag(Loc: MessageC->getMessageString()->getBeginLoc(),
11644 DiagID: diag::warn_clause_expected_string)
11645 << getOpenMPClauseNameForDiag(C: OMPC_message) << 1;
11646 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11647 Diag(Loc: SeverityC->getSeverityKindKwLoc(), DiagID: diag::warn_diagnose_if_succeeded)
11648 << SL.value_or(u: "WARNING");
11649 else
11650 Diag(Loc: StartLoc, DiagID: diag::err_diagnose_if_succeeded) << SL.value_or(u: "ERROR");
11651 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11652 return StmtError();
11653 }
11654
11655 return OMPErrorDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11656}
11657
11658StmtResult
11659SemaOpenMP::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
11660 SourceLocation StartLoc,
11661 SourceLocation EndLoc) {
11662 const OMPNowaitClause *NowaitC =
11663 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11664 bool HasDependC =
11665 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11666 .empty();
11667 if (NowaitC && !HasDependC) {
11668 Diag(Loc: StartLoc, DiagID: diag::err_omp_nowait_clause_without_depend);
11669 return StmtError();
11670 }
11671
11672 return OMPTaskwaitDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11673 Clauses);
11674}
11675
11676StmtResult
11677SemaOpenMP::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
11678 Stmt *AStmt, SourceLocation StartLoc,
11679 SourceLocation EndLoc) {
11680 if (!AStmt)
11681 return StmtError();
11682
11683 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11684
11685 SemaRef.setFunctionHasBranchProtectedScope();
11686
11687 return OMPTaskgroupDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11688 Clauses, AssociatedStmt: AStmt,
11689 DSAStack->getTaskgroupReductionRef());
11690}
11691
11692StmtResult SemaOpenMP::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
11693 SourceLocation StartLoc,
11694 SourceLocation EndLoc) {
11695 OMPFlushClause *FC = nullptr;
11696 OMPClause *OrderClause = nullptr;
11697 for (OMPClause *C : Clauses) {
11698 if (C->getClauseKind() == OMPC_flush)
11699 FC = cast<OMPFlushClause>(Val: C);
11700 else
11701 OrderClause = C;
11702 }
11703 unsigned OMPVersion = getLangOpts().OpenMP;
11704 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11705 SourceLocation MemOrderLoc;
11706 for (const OMPClause *C : Clauses) {
11707 if (C->getClauseKind() == OMPC_acq_rel ||
11708 C->getClauseKind() == OMPC_acquire ||
11709 C->getClauseKind() == OMPC_release ||
11710 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11711 if (MemOrderKind != OMPC_unknown) {
11712 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_several_mem_order_clauses)
11713 << getOpenMPDirectiveName(D: OMPD_flush, Ver: OMPVersion) << 1
11714 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11715 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
11716 << getOpenMPClauseNameForDiag(C: MemOrderKind);
11717 } else {
11718 MemOrderKind = C->getClauseKind();
11719 MemOrderLoc = C->getBeginLoc();
11720 }
11721 }
11722 }
11723 if (FC && OrderClause) {
11724 Diag(Loc: FC->getLParenLoc(), DiagID: diag::err_omp_flush_order_clause_and_list)
11725 << getOpenMPClauseNameForDiag(C: OrderClause->getClauseKind());
11726 Diag(Loc: OrderClause->getBeginLoc(), DiagID: diag::note_omp_flush_order_clause_here)
11727 << getOpenMPClauseNameForDiag(C: OrderClause->getClauseKind());
11728 return StmtError();
11729 }
11730 return OMPFlushDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11731}
11732
11733StmtResult SemaOpenMP::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
11734 SourceLocation StartLoc,
11735 SourceLocation EndLoc) {
11736 if (Clauses.empty()) {
11737 Diag(Loc: StartLoc, DiagID: diag::err_omp_depobj_expected);
11738 return StmtError();
11739 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11740 Diag(Loc: Clauses[0]->getBeginLoc(), DiagID: diag::err_omp_depobj_expected);
11741 return StmtError();
11742 }
11743 // Only depobj expression and another single clause is allowed.
11744 if (Clauses.size() > 2) {
11745 Diag(Loc: Clauses[2]->getBeginLoc(),
11746 DiagID: diag::err_omp_depobj_single_clause_expected);
11747 return StmtError();
11748 } else if (Clauses.size() < 1) {
11749 Diag(Loc: Clauses[0]->getEndLoc(), DiagID: diag::err_omp_depobj_single_clause_expected);
11750 return StmtError();
11751 }
11752 return OMPDepobjDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11753}
11754
11755StmtResult SemaOpenMP::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
11756 SourceLocation StartLoc,
11757 SourceLocation EndLoc) {
11758 // Check that exactly one clause is specified.
11759 if (Clauses.size() != 1) {
11760 Diag(Loc: Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11761 DiagID: diag::err_omp_scan_single_clause_expected);
11762 return StmtError();
11763 }
11764 // Check that scan directive is used in the scope of the OpenMP loop body.
11765 if (Scope *S = DSAStack->getCurScope()) {
11766 Scope *ParentS = S->getParent();
11767 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11768 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11769 unsigned OMPVersion = getLangOpts().OpenMP;
11770 return StmtError(Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_device_directive)
11771 << getOpenMPDirectiveName(D: OMPD_scan, Ver: OMPVersion) << 5);
11772 }
11773 }
11774 // Check that only one instance of scan directives is used in the same outer
11775 // region.
11776 if (DSAStack->doesParentHasScanDirective()) {
11777 Diag(Loc: StartLoc, DiagID: diag::err_omp_several_directives_in_region) << "scan";
11778 Diag(DSAStack->getParentScanDirectiveLoc(),
11779 DiagID: diag::note_omp_previous_directive)
11780 << "scan";
11781 return StmtError();
11782 }
11783 DSAStack->setParentHasScanDirective(StartLoc);
11784 return OMPScanDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11785}
11786
11787StmtResult
11788SemaOpenMP::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
11789 Stmt *AStmt, SourceLocation StartLoc,
11790 SourceLocation EndLoc) {
11791 const OMPClause *DependFound = nullptr;
11792 const OMPClause *DependSourceClause = nullptr;
11793 const OMPClause *DependSinkClause = nullptr;
11794 const OMPClause *DoacrossFound = nullptr;
11795 const OMPClause *DoacrossSourceClause = nullptr;
11796 const OMPClause *DoacrossSinkClause = nullptr;
11797 bool ErrorFound = false;
11798 const OMPThreadsClause *TC = nullptr;
11799 const OMPSIMDClause *SC = nullptr;
11800 for (const OMPClause *C : Clauses) {
11801 auto DOC = dyn_cast<OMPDoacrossClause>(Val: C);
11802 auto DC = dyn_cast<OMPDependClause>(Val: C);
11803 if (DC || DOC) {
11804 DependFound = DC ? C : nullptr;
11805 DoacrossFound = DOC ? C : nullptr;
11806 OMPDoacrossKind ODK;
11807 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11808 (DOC && (ODK.isSource(C: DOC)))) {
11809 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11810 unsigned OMPVersion = getLangOpts().OpenMP;
11811 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_more_one_clause)
11812 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
11813 Ver: OMPVersion)
11814 << getOpenMPClauseNameForDiag(C: DC ? OMPC_depend : OMPC_doacross)
11815 << 2;
11816 ErrorFound = true;
11817 } else {
11818 if (DC)
11819 DependSourceClause = C;
11820 else
11821 DoacrossSourceClause = C;
11822 }
11823 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11824 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_sink_and_source_not_allowed)
11825 << (DC ? "depend" : "doacross") << 0;
11826 ErrorFound = true;
11827 }
11828 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11829 (DOC && (ODK.isSink(C: DOC) || ODK.isSinkIter(C: DOC)))) {
11830 if (DependSourceClause || DoacrossSourceClause) {
11831 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_sink_and_source_not_allowed)
11832 << (DC ? "depend" : "doacross") << 1;
11833 ErrorFound = true;
11834 }
11835 if (DC)
11836 DependSinkClause = C;
11837 else
11838 DoacrossSinkClause = C;
11839 }
11840 } else if (C->getClauseKind() == OMPC_threads) {
11841 TC = cast<OMPThreadsClause>(Val: C);
11842 } else if (C->getClauseKind() == OMPC_simd) {
11843 SC = cast<OMPSIMDClause>(Val: C);
11844 }
11845 }
11846 if (!ErrorFound && !SC &&
11847 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11848 // OpenMP [2.8.1,simd Construct, Restrictions]
11849 // An ordered construct with the simd clause is the only OpenMP construct
11850 // that can appear in the simd region.
11851 Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_simd)
11852 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11853 ErrorFound = true;
11854 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11855 SourceLocation Loc =
11856 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11857 Diag(Loc, DiagID: diag::err_omp_depend_clause_thread_simd)
11858 << getOpenMPClauseNameForDiag(C: DependFound ? OMPC_depend : OMPC_doacross)
11859 << getOpenMPClauseNameForDiag(C: TC ? TC->getClauseKind()
11860 : SC->getClauseKind());
11861 ErrorFound = true;
11862 } else if ((DependFound || DoacrossFound) &&
11863 !DSAStack->getParentOrderedRegionParam().first) {
11864 SourceLocation Loc =
11865 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11866 Diag(Loc, DiagID: diag::err_omp_ordered_directive_without_param)
11867 << getOpenMPClauseNameForDiag(C: DependFound ? OMPC_depend
11868 : OMPC_doacross);
11869 ErrorFound = true;
11870 } else if (TC || Clauses.empty()) {
11871 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11872 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11873 Diag(Loc: ErrLoc, DiagID: diag::err_omp_ordered_directive_with_param)
11874 << (TC != nullptr);
11875 Diag(Loc: Param->getBeginLoc(), DiagID: diag::note_omp_ordered_param) << 1;
11876 ErrorFound = true;
11877 }
11878 }
11879 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11880 return StmtError();
11881
11882 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11883 // During execution of an iteration of a worksharing-loop or a loop nest
11884 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11885 // must not execute more than one ordered region corresponding to an ordered
11886 // construct without a depend clause.
11887 if (!DependFound && !DoacrossFound) {
11888 if (DSAStack->doesParentHasOrderedDirective()) {
11889 Diag(Loc: StartLoc, DiagID: diag::err_omp_several_directives_in_region) << "ordered";
11890 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11891 DiagID: diag::note_omp_previous_directive)
11892 << "ordered";
11893 return StmtError();
11894 }
11895 DSAStack->setParentHasOrderedDirective(StartLoc);
11896 }
11897
11898 if (AStmt) {
11899 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11900
11901 SemaRef.setFunctionHasBranchProtectedScope();
11902 }
11903
11904 if (!AStmt)
11905 return OMPOrderedStandaloneDirective::Create(C: getASTContext(), StartLoc,
11906 EndLoc, Clauses);
11907 return OMPOrderedBlockAssocDirective::Create(C: getASTContext(), StartLoc,
11908 EndLoc, Clauses, AssociatedStmt: AStmt);
11909}
11910
11911namespace {
11912/// Helper class for checking expression in 'omp atomic [update]'
11913/// construct.
11914class OpenMPAtomicUpdateChecker {
11915 /// Error results for atomic update expressions.
11916 enum ExprAnalysisErrorCode {
11917 /// A statement is not an expression statement.
11918 NotAnExpression,
11919 /// Expression is not builtin binary or unary operation.
11920 NotABinaryOrUnaryExpression,
11921 /// Unary operation is not post-/pre- increment/decrement operation.
11922 NotAnUnaryIncDecExpression,
11923 /// An expression is not of scalar type.
11924 NotAScalarType,
11925 /// A binary operation is not an assignment operation.
11926 NotAnAssignmentOp,
11927 /// RHS part of the binary operation is not a binary expression.
11928 NotABinaryExpression,
11929 /// RHS part is not additive/multiplicative/shift/bitwise binary
11930 /// expression.
11931 NotABinaryOperator,
11932 /// RHS binary operation does not have reference to the updated LHS
11933 /// part.
11934 NotAnUpdateExpression,
11935 /// An expression contains semantical error not related to
11936 /// 'omp atomic [update]'
11937 NotAValidExpression,
11938 /// No errors is found.
11939 NoError
11940 };
11941 /// Reference to Sema.
11942 Sema &SemaRef;
11943 /// A location for note diagnostics (when error is found).
11944 SourceLocation NoteLoc;
11945 /// 'x' lvalue part of the source atomic expression.
11946 Expr *X;
11947 /// 'expr' rvalue part of the source atomic expression.
11948 Expr *E;
11949 /// Helper expression of the form
11950 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11951 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11952 Expr *UpdateExpr;
11953 /// Is 'x' a LHS in a RHS part of full update expression. It is
11954 /// important for non-associative operations.
11955 bool IsXLHSInRHSPart;
11956 BinaryOperatorKind Op;
11957 SourceLocation OpLoc;
11958 /// true if the source expression is a postfix unary operation, false
11959 /// if it is a prefix unary operation.
11960 bool IsPostfixUpdate;
11961
11962public:
11963 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11964 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11965 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11966 /// Check specified statement that it is suitable for 'atomic update'
11967 /// constructs and extract 'x', 'expr' and Operation from the original
11968 /// expression. If DiagId and NoteId == 0, then only check is performed
11969 /// without error notification.
11970 /// \param DiagId Diagnostic which should be emitted if error is found.
11971 /// \param NoteId Diagnostic note for the main error message.
11972 /// \return true if statement is not an update expression, false otherwise.
11973 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11974 /// Return the 'x' lvalue part of the source atomic expression.
11975 Expr *getX() const { return X; }
11976 /// Return the 'expr' rvalue part of the source atomic expression.
11977 Expr *getExpr() const { return E; }
11978 /// Return the update expression used in calculation of the updated
11979 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11980 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11981 Expr *getUpdateExpr() const { return UpdateExpr; }
11982 /// Return true if 'x' is LHS in RHS part of full update expression,
11983 /// false otherwise.
11984 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11985
11986 /// true if the source expression is a postfix unary operation, false
11987 /// if it is a prefix unary operation.
11988 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11989
11990private:
11991 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11992 unsigned NoteId = 0);
11993};
11994
11995bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11996 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11997 ExprAnalysisErrorCode ErrorFound = NoError;
11998 SourceLocation ErrorLoc, NoteLoc;
11999 SourceRange ErrorRange, NoteRange;
12000 // Allowed constructs are:
12001 // x = x binop expr;
12002 // x = expr binop x;
12003 if (AtomicBinOp->getOpcode() == BO_Assign) {
12004 X = AtomicBinOp->getLHS();
12005 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
12006 Val: AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
12007 if (AtomicInnerBinOp->isMultiplicativeOp() ||
12008 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
12009 AtomicInnerBinOp->isBitwiseOp()) {
12010 Op = AtomicInnerBinOp->getOpcode();
12011 OpLoc = AtomicInnerBinOp->getOperatorLoc();
12012 Expr *LHS = AtomicInnerBinOp->getLHS();
12013 Expr *RHS = AtomicInnerBinOp->getRHS();
12014 llvm::FoldingSetNodeID XId, LHSId, RHSId;
12015 X->IgnoreParenImpCasts()->Profile(ID&: XId, Context: SemaRef.getASTContext(),
12016 /*Canonical=*/true);
12017 LHS->IgnoreParenImpCasts()->Profile(ID&: LHSId, Context: SemaRef.getASTContext(),
12018 /*Canonical=*/true);
12019 RHS->IgnoreParenImpCasts()->Profile(ID&: RHSId, Context: SemaRef.getASTContext(),
12020 /*Canonical=*/true);
12021 if (XId == LHSId) {
12022 E = RHS;
12023 IsXLHSInRHSPart = true;
12024 } else if (XId == RHSId) {
12025 E = LHS;
12026 IsXLHSInRHSPart = false;
12027 } else {
12028 ErrorLoc = AtomicInnerBinOp->getExprLoc();
12029 ErrorRange = AtomicInnerBinOp->getSourceRange();
12030 NoteLoc = X->getExprLoc();
12031 NoteRange = X->getSourceRange();
12032 ErrorFound = NotAnUpdateExpression;
12033 }
12034 } else {
12035 ErrorLoc = AtomicInnerBinOp->getExprLoc();
12036 ErrorRange = AtomicInnerBinOp->getSourceRange();
12037 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
12038 NoteRange = SourceRange(NoteLoc, NoteLoc);
12039 ErrorFound = NotABinaryOperator;
12040 }
12041 } else {
12042 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
12043 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
12044 ErrorFound = NotABinaryExpression;
12045 }
12046 } else {
12047 ErrorLoc = AtomicBinOp->getExprLoc();
12048 ErrorRange = AtomicBinOp->getSourceRange();
12049 NoteLoc = AtomicBinOp->getOperatorLoc();
12050 NoteRange = SourceRange(NoteLoc, NoteLoc);
12051 ErrorFound = NotAnAssignmentOp;
12052 }
12053 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
12054 SemaRef.Diag(Loc: ErrorLoc, DiagID: DiagId) << ErrorRange;
12055 SemaRef.Diag(Loc: NoteLoc, DiagID: NoteId) << ErrorFound << NoteRange;
12056 return true;
12057 }
12058 if (SemaRef.CurContext->isDependentContext())
12059 E = X = UpdateExpr = nullptr;
12060 return ErrorFound != NoError;
12061}
12062
12063bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
12064 unsigned NoteId) {
12065 ExprAnalysisErrorCode ErrorFound = NoError;
12066 SourceLocation ErrorLoc, NoteLoc;
12067 SourceRange ErrorRange, NoteRange;
12068 // Allowed constructs are:
12069 // x++;
12070 // x--;
12071 // ++x;
12072 // --x;
12073 // x binop= expr;
12074 // x = x binop expr;
12075 // x = expr binop x;
12076 if (auto *AtomicBody = dyn_cast<Expr>(Val: S)) {
12077 AtomicBody = AtomicBody->IgnoreParenImpCasts();
12078 if (AtomicBody->getType()->isScalarType() ||
12079 AtomicBody->isInstantiationDependent()) {
12080 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
12081 Val: AtomicBody->IgnoreParenImpCasts())) {
12082 // Check for Compound Assignment Operation
12083 Op = BinaryOperator::getOpForCompoundAssignment(
12084 Opc: AtomicCompAssignOp->getOpcode());
12085 OpLoc = AtomicCompAssignOp->getOperatorLoc();
12086 E = AtomicCompAssignOp->getRHS();
12087 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
12088 IsXLHSInRHSPart = true;
12089 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
12090 Val: AtomicBody->IgnoreParenImpCasts())) {
12091 // Check for Binary Operation
12092 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
12093 return true;
12094 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
12095 Val: AtomicBody->IgnoreParenImpCasts())) {
12096 // Check for Unary Operation
12097 if (AtomicUnaryOp->isIncrementDecrementOp()) {
12098 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
12099 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
12100 OpLoc = AtomicUnaryOp->getOperatorLoc();
12101 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
12102 E = SemaRef.ActOnIntegerConstant(Loc: OpLoc, /*uint64_t Val=*/Val: 1).get();
12103 IsXLHSInRHSPart = true;
12104 } else {
12105 ErrorFound = NotAnUnaryIncDecExpression;
12106 ErrorLoc = AtomicUnaryOp->getExprLoc();
12107 ErrorRange = AtomicUnaryOp->getSourceRange();
12108 NoteLoc = AtomicUnaryOp->getOperatorLoc();
12109 NoteRange = SourceRange(NoteLoc, NoteLoc);
12110 }
12111 } else if (!AtomicBody->isInstantiationDependent()) {
12112 ErrorFound = NotABinaryOrUnaryExpression;
12113 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
12114 NoteRange = ErrorRange = AtomicBody->getSourceRange();
12115 } else if (AtomicBody->containsErrors()) {
12116 ErrorFound = NotAValidExpression;
12117 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
12118 NoteRange = ErrorRange = AtomicBody->getSourceRange();
12119 }
12120 } else {
12121 ErrorFound = NotAScalarType;
12122 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
12123 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12124 }
12125 } else {
12126 ErrorFound = NotAnExpression;
12127 NoteLoc = ErrorLoc = S->getBeginLoc();
12128 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12129 }
12130 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
12131 SemaRef.Diag(Loc: ErrorLoc, DiagID: DiagId) << ErrorRange;
12132 SemaRef.Diag(Loc: NoteLoc, DiagID: NoteId) << ErrorFound << NoteRange;
12133 return true;
12134 }
12135 if (SemaRef.CurContext->isDependentContext())
12136 E = X = UpdateExpr = nullptr;
12137 if (ErrorFound == NoError && E && X) {
12138 // Build an update expression of form 'OpaqueValueExpr(x) binop
12139 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
12140 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
12141 auto *OVEX = new (SemaRef.getASTContext())
12142 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
12143 auto *OVEExpr = new (SemaRef.getASTContext())
12144 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
12145 ExprResult Update =
12146 SemaRef.CreateBuiltinBinOp(OpLoc, Opc: Op, LHSExpr: IsXLHSInRHSPart ? OVEX : OVEExpr,
12147 RHSExpr: IsXLHSInRHSPart ? OVEExpr : OVEX);
12148 if (Update.isInvalid())
12149 return true;
12150 Update = SemaRef.PerformImplicitConversion(From: Update.get(), ToType: X->getType(),
12151 Action: AssignmentAction::Casting);
12152 if (Update.isInvalid())
12153 return true;
12154 UpdateExpr = Update.get();
12155 }
12156 return ErrorFound != NoError;
12157}
12158
12159/// Get the node id of the fixed point of an expression \a S.
12160llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
12161 llvm::FoldingSetNodeID Id;
12162 S->IgnoreParenImpCasts()->Profile(ID&: Id, Context, Canonical: true);
12163 return Id;
12164}
12165
12166/// Check if two expressions are same.
12167bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
12168 const Expr *RHS) {
12169 return getNodeId(Context, S: LHS) == getNodeId(Context, S: RHS);
12170}
12171
12172class OpenMPAtomicCompareChecker {
12173public:
12174 /// All kinds of errors that can occur in `atomic compare`
12175 enum ErrorTy {
12176 /// Empty compound statement.
12177 NoStmt = 0,
12178 /// More than one statement in a compound statement.
12179 MoreThanOneStmt,
12180 /// Not an assignment binary operator.
12181 NotAnAssignment,
12182 /// Not a conditional operator.
12183 NotCondOp,
12184 /// Wrong false expr. According to the spec, 'x' should be at the false
12185 /// expression of a conditional expression.
12186 WrongFalseExpr,
12187 /// The condition of a conditional expression is not a binary operator.
12188 NotABinaryOp,
12189 /// Invalid binary operator (not <, >, or ==).
12190 InvalidBinaryOp,
12191 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
12192 InvalidComparison,
12193 /// X is not a lvalue.
12194 XNotLValue,
12195 /// Not a scalar.
12196 NotScalar,
12197 /// Not an integer.
12198 NotInteger,
12199 /// 'else' statement is not expected.
12200 UnexpectedElse,
12201 /// Not an equality operator.
12202 NotEQ,
12203 /// Invalid assignment (not v == x).
12204 InvalidAssignment,
12205 /// Not if statement
12206 NotIfStmt,
12207 /// More than two statements in a compound statement.
12208 MoreThanTwoStmts,
12209 /// Not a compound statement.
12210 NotCompoundStmt,
12211 /// No else statement.
12212 NoElse,
12213 /// Not 'if (r)'.
12214 InvalidCondition,
12215 /// No error.
12216 NoError,
12217 };
12218
12219 struct ErrorInfoTy {
12220 ErrorTy Error;
12221 SourceLocation ErrorLoc;
12222 SourceRange ErrorRange;
12223 SourceLocation NoteLoc;
12224 SourceRange NoteRange;
12225 };
12226
12227 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
12228
12229 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
12230 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12231
12232 Expr *getX() const { return X; }
12233 Expr *getE() const { return E; }
12234 Expr *getD() const { return D; }
12235 Expr *getCond() const { return C; }
12236 bool isXBinopExpr() const { return IsXBinopExpr; }
12237
12238protected:
12239 /// Reference to ASTContext
12240 ASTContext &ContextRef;
12241 /// 'x' lvalue part of the source atomic expression.
12242 Expr *X = nullptr;
12243 /// 'expr' or 'e' rvalue part of the source atomic expression.
12244 Expr *E = nullptr;
12245 /// 'd' rvalue part of the source atomic expression.
12246 Expr *D = nullptr;
12247 /// 'cond' part of the source atomic expression. It is in one of the following
12248 /// forms:
12249 /// expr ordop x
12250 /// x ordop expr
12251 /// x == e
12252 /// e == x
12253 Expr *C = nullptr;
12254 /// True if the cond expr is in the form of 'x ordop expr'.
12255 bool IsXBinopExpr = true;
12256
12257 /// Check if it is a valid conditional update statement (cond-update-stmt).
12258 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
12259
12260 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
12261 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12262
12263 /// Check if all captured values have right type.
12264 bool checkType(ErrorInfoTy &ErrorInfo) const;
12265
12266 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
12267 bool ShouldBeLValue, bool ShouldBeInteger = false) {
12268 if (E->isInstantiationDependent())
12269 return true;
12270
12271 if (ShouldBeLValue && !E->isLValue()) {
12272 ErrorInfo.Error = ErrorTy::XNotLValue;
12273 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12274 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12275 return false;
12276 }
12277
12278 QualType QTy = E->getType();
12279 if (!QTy->isScalarType()) {
12280 ErrorInfo.Error = ErrorTy::NotScalar;
12281 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12282 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12283 return false;
12284 }
12285 if (ShouldBeInteger && !QTy->isIntegerType()) {
12286 ErrorInfo.Error = ErrorTy::NotInteger;
12287 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12288 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12289 return false;
12290 }
12291
12292 return true;
12293 }
12294};
12295
12296bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
12297 ErrorInfoTy &ErrorInfo) {
12298 auto *Then = S->getThen();
12299 if (auto *CS = dyn_cast<CompoundStmt>(Val: Then)) {
12300 if (CS->body_empty()) {
12301 ErrorInfo.Error = ErrorTy::NoStmt;
12302 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12303 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12304 return false;
12305 }
12306 if (CS->size() > 1) {
12307 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12308 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12309 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12310 return false;
12311 }
12312 Then = CS->body_front();
12313 }
12314
12315 auto *BO = dyn_cast<BinaryOperator>(Val: Then);
12316 if (!BO) {
12317 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12318 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12319 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12320 return false;
12321 }
12322 if (BO->getOpcode() != BO_Assign) {
12323 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12324 ErrorInfo.ErrorLoc = BO->getExprLoc();
12325 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12326 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12327 return false;
12328 }
12329
12330 X = BO->getLHS();
12331
12332 auto *Cond = dyn_cast<BinaryOperator>(Val: S->getCond());
12333 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: S->getCond());
12334 Expr *LHS = nullptr;
12335 Expr *RHS = nullptr;
12336 if (Cond) {
12337 LHS = Cond->getLHS();
12338 RHS = Cond->getRHS();
12339 } else if (Call) {
12340 LHS = Call->getArg(Arg: 0);
12341 RHS = Call->getArg(Arg: 1);
12342 } else {
12343 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12344 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12345 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12346 return false;
12347 }
12348
12349 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12350 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12351 C = S->getCond();
12352 D = BO->getRHS();
12353 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
12354 E = RHS;
12355 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12356 E = LHS;
12357 } else {
12358 ErrorInfo.Error = ErrorTy::InvalidComparison;
12359 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12360 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12361 S->getCond()->getSourceRange();
12362 return false;
12363 }
12364 } else if ((Cond &&
12365 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12366 (Call &&
12367 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12368 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12369 E = BO->getRHS();
12370 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS) &&
12371 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS)) {
12372 C = S->getCond();
12373 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: LHS) &&
12374 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12375 C = S->getCond();
12376 IsXBinopExpr = false;
12377 } else {
12378 ErrorInfo.Error = ErrorTy::InvalidComparison;
12379 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12380 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12381 S->getCond()->getSourceRange();
12382 return false;
12383 }
12384 } else {
12385 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12386 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12387 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12388 return false;
12389 }
12390
12391 if (S->getElse()) {
12392 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12393 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12394 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12395 return false;
12396 }
12397
12398 return true;
12399}
12400
12401bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12402 ErrorInfoTy &ErrorInfo) {
12403 auto *BO = dyn_cast<BinaryOperator>(Val: S);
12404 if (!BO) {
12405 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12406 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12407 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12408 return false;
12409 }
12410 if (BO->getOpcode() != BO_Assign) {
12411 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12412 ErrorInfo.ErrorLoc = BO->getExprLoc();
12413 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12414 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12415 return false;
12416 }
12417
12418 X = BO->getLHS();
12419
12420 auto *CO = dyn_cast<ConditionalOperator>(Val: BO->getRHS()->IgnoreParenImpCasts());
12421 if (!CO) {
12422 ErrorInfo.Error = ErrorTy::NotCondOp;
12423 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12424 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12425 return false;
12426 }
12427
12428 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: CO->getFalseExpr())) {
12429 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12430 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12431 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12432 CO->getFalseExpr()->getSourceRange();
12433 return false;
12434 }
12435
12436 auto *Cond = dyn_cast<BinaryOperator>(Val: CO->getCond());
12437 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: CO->getCond());
12438 Expr *LHS = nullptr;
12439 Expr *RHS = nullptr;
12440 if (Cond) {
12441 LHS = Cond->getLHS();
12442 RHS = Cond->getRHS();
12443 } else if (Call) {
12444 LHS = Call->getArg(Arg: 0);
12445 RHS = Call->getArg(Arg: 1);
12446 } else {
12447 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12448 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12449 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12450 CO->getCond()->getSourceRange();
12451 return false;
12452 }
12453
12454 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12455 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12456 C = CO->getCond();
12457 D = CO->getTrueExpr();
12458 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
12459 E = RHS;
12460 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12461 E = LHS;
12462 } else {
12463 ErrorInfo.Error = ErrorTy::InvalidComparison;
12464 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12465 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12466 CO->getCond()->getSourceRange();
12467 return false;
12468 }
12469 } else if ((Cond &&
12470 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12471 (Call &&
12472 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12473 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12474
12475 E = CO->getTrueExpr();
12476 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS) &&
12477 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS)) {
12478 C = CO->getCond();
12479 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: LHS) &&
12480 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12481 C = CO->getCond();
12482 IsXBinopExpr = false;
12483 } else {
12484 ErrorInfo.Error = ErrorTy::InvalidComparison;
12485 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12486 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12487 CO->getCond()->getSourceRange();
12488 return false;
12489 }
12490 } else {
12491 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12492 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12493 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12494 CO->getCond()->getSourceRange();
12495 return false;
12496 }
12497
12498 return true;
12499}
12500
12501bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12502 // 'x' and 'e' cannot be nullptr
12503 assert(X && E && "X and E cannot be nullptr");
12504
12505 if (!CheckValue(E: X, ErrorInfo, ShouldBeLValue: true))
12506 return false;
12507
12508 if (!CheckValue(E, ErrorInfo, ShouldBeLValue: false))
12509 return false;
12510
12511 if (D && !CheckValue(E: D, ErrorInfo, ShouldBeLValue: false))
12512 return false;
12513
12514 return true;
12515}
12516
12517bool OpenMPAtomicCompareChecker::checkStmt(
12518 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12519 auto *CS = dyn_cast<CompoundStmt>(Val: S);
12520 if (CS) {
12521 if (CS->body_empty()) {
12522 ErrorInfo.Error = ErrorTy::NoStmt;
12523 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12524 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12525 return false;
12526 }
12527
12528 if (CS->size() != 1) {
12529 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12530 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12531 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12532 return false;
12533 }
12534 S = CS->body_front();
12535 }
12536
12537 auto Res = false;
12538
12539 if (auto *IS = dyn_cast<IfStmt>(Val: S)) {
12540 // Check if the statement is in one of the following forms
12541 // (cond-update-stmt):
12542 // if (expr ordop x) { x = expr; }
12543 // if (x ordop expr) { x = expr; }
12544 // if (x == e) { x = d; }
12545 Res = checkCondUpdateStmt(S: IS, ErrorInfo);
12546 } else {
12547 // Check if the statement is in one of the following forms (cond-expr-stmt):
12548 // x = expr ordop x ? expr : x;
12549 // x = x ordop expr ? expr : x;
12550 // x = x == e ? d : x;
12551 Res = checkCondExprStmt(S, ErrorInfo);
12552 }
12553
12554 if (!Res)
12555 return false;
12556
12557 return checkType(ErrorInfo);
12558}
12559
12560class OpenMPAtomicCompareCaptureChecker final
12561 : public OpenMPAtomicCompareChecker {
12562public:
12563 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12564
12565 Expr *getV() const { return V; }
12566 Expr *getR() const { return R; }
12567 bool isFailOnly() const { return IsFailOnly; }
12568 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12569
12570 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12571 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12572
12573private:
12574 bool checkType(ErrorInfoTy &ErrorInfo);
12575
12576 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12577 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12578 // spec p.p. 82:
12579 // (1) { v = x; cond-update-stmt }
12580 // (2) { cond-update-stmt v = x; }
12581 // (3) if(x == e) { x = d; } else { v = x; }
12582 // (4) { r = x == e; if(r) { x = d; } }
12583 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12584
12585 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12586 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12587
12588 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12589 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12590 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12591
12592 /// 'v' lvalue part of the source atomic expression.
12593 Expr *V = nullptr;
12594 /// 'r' lvalue part of the source atomic expression.
12595 Expr *R = nullptr;
12596 /// If 'v' is only updated when the comparison fails.
12597 bool IsFailOnly = false;
12598 /// If original value of 'x' must be stored in 'v', not an updated one.
12599 bool IsPostfixUpdate = false;
12600};
12601
12602bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12603 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12604 return false;
12605
12606 if (V && !CheckValue(E: V, ErrorInfo, ShouldBeLValue: true))
12607 return false;
12608
12609 if (R && !CheckValue(E: R, ErrorInfo, ShouldBeLValue: true, ShouldBeInteger: true))
12610 return false;
12611
12612 return true;
12613}
12614
12615bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12616 ErrorInfoTy &ErrorInfo) {
12617 IsFailOnly = true;
12618
12619 auto *Then = S->getThen();
12620 if (auto *CS = dyn_cast<CompoundStmt>(Val: Then)) {
12621 if (CS->body_empty()) {
12622 ErrorInfo.Error = ErrorTy::NoStmt;
12623 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12624 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12625 return false;
12626 }
12627 if (CS->size() > 1) {
12628 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12629 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12630 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12631 return false;
12632 }
12633 Then = CS->body_front();
12634 }
12635
12636 auto *BO = dyn_cast<BinaryOperator>(Val: Then);
12637 if (!BO) {
12638 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12639 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12640 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12641 return false;
12642 }
12643 if (BO->getOpcode() != BO_Assign) {
12644 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12645 ErrorInfo.ErrorLoc = BO->getExprLoc();
12646 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12647 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12648 return false;
12649 }
12650
12651 X = BO->getLHS();
12652 D = BO->getRHS();
12653
12654 auto *Cond = dyn_cast<BinaryOperator>(Val: S->getCond());
12655 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: S->getCond());
12656 Expr *LHS = nullptr;
12657 Expr *RHS = nullptr;
12658 if (Cond) {
12659 LHS = Cond->getLHS();
12660 RHS = Cond->getRHS();
12661 } else if (Call) {
12662 LHS = Call->getArg(Arg: 0);
12663 RHS = Call->getArg(Arg: 1);
12664 } else {
12665 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12666 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12667 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12668 return false;
12669 }
12670 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12671 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12672 ErrorInfo.Error = ErrorTy::NotEQ;
12673 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12674 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12675 return false;
12676 }
12677
12678 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
12679 E = RHS;
12680 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12681 E = LHS;
12682 } else {
12683 ErrorInfo.Error = ErrorTy::InvalidComparison;
12684 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12685 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12686 return false;
12687 }
12688
12689 C = S->getCond();
12690
12691 if (!S->getElse()) {
12692 ErrorInfo.Error = ErrorTy::NoElse;
12693 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12694 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12695 return false;
12696 }
12697
12698 auto *Else = S->getElse();
12699 if (auto *CS = dyn_cast<CompoundStmt>(Val: Else)) {
12700 if (CS->body_empty()) {
12701 ErrorInfo.Error = ErrorTy::NoStmt;
12702 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12703 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12704 return false;
12705 }
12706 if (CS->size() > 1) {
12707 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12708 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12709 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12710 return false;
12711 }
12712 Else = CS->body_front();
12713 }
12714
12715 auto *ElseBO = dyn_cast<BinaryOperator>(Val: Else);
12716 if (!ElseBO) {
12717 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12718 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12719 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12720 return false;
12721 }
12722 if (ElseBO->getOpcode() != BO_Assign) {
12723 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12724 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12725 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12726 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12727 return false;
12728 }
12729
12730 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: ElseBO->getRHS())) {
12731 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12732 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12733 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12734 ElseBO->getRHS()->getSourceRange();
12735 return false;
12736 }
12737
12738 V = ElseBO->getLHS();
12739
12740 return checkType(ErrorInfo);
12741}
12742
12743bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12744 ErrorInfoTy &ErrorInfo) {
12745 // We don't check here as they should be already done before call this
12746 // function.
12747 auto *CS = cast<CompoundStmt>(Val: S);
12748 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12749 auto *S1 = cast<BinaryOperator>(Val: CS->body_front());
12750 auto *S2 = cast<IfStmt>(Val: CS->body_back());
12751 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12752
12753 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: S1->getLHS(), RHS: S2->getCond())) {
12754 ErrorInfo.Error = ErrorTy::InvalidCondition;
12755 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12756 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12757 return false;
12758 }
12759
12760 R = S1->getLHS();
12761
12762 auto *Then = S2->getThen();
12763 if (auto *ThenCS = dyn_cast<CompoundStmt>(Val: Then)) {
12764 if (ThenCS->body_empty()) {
12765 ErrorInfo.Error = ErrorTy::NoStmt;
12766 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12767 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12768 return false;
12769 }
12770 if (ThenCS->size() > 1) {
12771 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12772 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12773 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12774 return false;
12775 }
12776 Then = ThenCS->body_front();
12777 }
12778
12779 auto *ThenBO = dyn_cast<BinaryOperator>(Val: Then);
12780 if (!ThenBO) {
12781 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12782 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12783 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12784 return false;
12785 }
12786 if (ThenBO->getOpcode() != BO_Assign) {
12787 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12788 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12789 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12790 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12791 return false;
12792 }
12793
12794 X = ThenBO->getLHS();
12795 D = ThenBO->getRHS();
12796
12797 auto *BO = cast<BinaryOperator>(Val: S1->getRHS()->IgnoreImpCasts());
12798 if (BO->getOpcode() != BO_EQ) {
12799 ErrorInfo.Error = ErrorTy::NotEQ;
12800 ErrorInfo.ErrorLoc = BO->getExprLoc();
12801 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12802 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12803 return false;
12804 }
12805
12806 C = BO;
12807
12808 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: BO->getLHS())) {
12809 E = BO->getRHS();
12810 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: BO->getRHS())) {
12811 E = BO->getLHS();
12812 } else {
12813 ErrorInfo.Error = ErrorTy::InvalidComparison;
12814 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12815 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12816 return false;
12817 }
12818
12819 if (S2->getElse()) {
12820 IsFailOnly = true;
12821
12822 auto *Else = S2->getElse();
12823 if (auto *ElseCS = dyn_cast<CompoundStmt>(Val: Else)) {
12824 if (ElseCS->body_empty()) {
12825 ErrorInfo.Error = ErrorTy::NoStmt;
12826 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12827 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12828 return false;
12829 }
12830 if (ElseCS->size() > 1) {
12831 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12832 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12833 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12834 return false;
12835 }
12836 Else = ElseCS->body_front();
12837 }
12838
12839 auto *ElseBO = dyn_cast<BinaryOperator>(Val: Else);
12840 if (!ElseBO) {
12841 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12842 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12843 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12844 return false;
12845 }
12846 if (ElseBO->getOpcode() != BO_Assign) {
12847 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12848 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12849 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12850 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12851 return false;
12852 }
12853 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: ElseBO->getRHS())) {
12854 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12855 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12856 ErrorInfo.NoteLoc = X->getExprLoc();
12857 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12858 ErrorInfo.NoteRange = X->getSourceRange();
12859 return false;
12860 }
12861
12862 V = ElseBO->getLHS();
12863 }
12864
12865 return checkType(ErrorInfo);
12866}
12867
12868bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12869 ErrorInfoTy &ErrorInfo) {
12870 // if(x == e) { x = d; } else { v = x; }
12871 if (auto *IS = dyn_cast<IfStmt>(Val: S))
12872 return checkForm3(S: IS, ErrorInfo);
12873
12874 auto *CS = dyn_cast<CompoundStmt>(Val: S);
12875 if (!CS) {
12876 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12877 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12878 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12879 return false;
12880 }
12881 if (CS->body_empty()) {
12882 ErrorInfo.Error = ErrorTy::NoStmt;
12883 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12884 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12885 return false;
12886 }
12887
12888 // { if(x == e) { x = d; } else { v = x; } }
12889 if (CS->size() == 1) {
12890 auto *IS = dyn_cast<IfStmt>(Val: CS->body_front());
12891 if (!IS) {
12892 ErrorInfo.Error = ErrorTy::NotIfStmt;
12893 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12894 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12895 CS->body_front()->getSourceRange();
12896 return false;
12897 }
12898
12899 return checkForm3(S: IS, ErrorInfo);
12900 } else if (CS->size() == 2) {
12901 auto *S1 = CS->body_front();
12902 auto *S2 = CS->body_back();
12903
12904 Stmt *UpdateStmt = nullptr;
12905 Stmt *CondUpdateStmt = nullptr;
12906 Stmt *CondExprStmt = nullptr;
12907
12908 if (auto *BO = dyn_cast<BinaryOperator>(Val: S1)) {
12909 // It could be one of the following cases:
12910 // { v = x; cond-update-stmt }
12911 // { v = x; cond-expr-stmt }
12912 // { cond-expr-stmt; v = x; }
12913 // form 45
12914 if (isa<BinaryOperator>(Val: BO->getRHS()->IgnoreImpCasts()) ||
12915 isa<ConditionalOperator>(Val: BO->getRHS()->IgnoreImpCasts())) {
12916 // check if form 45
12917 if (isa<IfStmt>(Val: S2))
12918 return checkForm45(S: CS, ErrorInfo);
12919 // { cond-expr-stmt; v = x; }
12920 CondExprStmt = S1;
12921 UpdateStmt = S2;
12922 } else {
12923 IsPostfixUpdate = true;
12924 UpdateStmt = S1;
12925 if (isa<IfStmt>(Val: S2)) {
12926 // { v = x; cond-update-stmt }
12927 CondUpdateStmt = S2;
12928 } else {
12929 // { v = x; cond-expr-stmt }
12930 CondExprStmt = S2;
12931 }
12932 }
12933 } else {
12934 // { cond-update-stmt v = x; }
12935 UpdateStmt = S2;
12936 CondUpdateStmt = S1;
12937 }
12938
12939 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12940 auto *IS = dyn_cast<IfStmt>(Val: CUS);
12941 if (!IS) {
12942 ErrorInfo.Error = ErrorTy::NotIfStmt;
12943 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12944 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12945 return false;
12946 }
12947
12948 return checkCondUpdateStmt(S: IS, ErrorInfo);
12949 };
12950
12951 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12952 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12953 auto *BO = dyn_cast<BinaryOperator>(Val: US);
12954 if (!BO) {
12955 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12956 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12957 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12958 return false;
12959 }
12960 if (BO->getOpcode() != BO_Assign) {
12961 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12962 ErrorInfo.ErrorLoc = BO->getExprLoc();
12963 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12964 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12965 return false;
12966 }
12967 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: this->X, RHS: BO->getRHS())) {
12968 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12969 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12970 ErrorInfo.NoteLoc = this->X->getExprLoc();
12971 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12972 ErrorInfo.NoteRange = this->X->getSourceRange();
12973 return false;
12974 }
12975
12976 this->V = BO->getLHS();
12977
12978 return true;
12979 };
12980
12981 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12982 return false;
12983 if (CondExprStmt && !checkCondExprStmt(S: CondExprStmt, ErrorInfo))
12984 return false;
12985 if (!CheckUpdateStmt(UpdateStmt))
12986 return false;
12987 } else {
12988 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12989 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12990 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12991 return false;
12992 }
12993
12994 return checkType(ErrorInfo);
12995}
12996} // namespace
12997
12998StmtResult SemaOpenMP::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
12999 Stmt *AStmt,
13000 SourceLocation StartLoc,
13001 SourceLocation EndLoc) {
13002 ASTContext &Context = getASTContext();
13003 unsigned OMPVersion = getLangOpts().OpenMP;
13004 // Register location of the first atomic directive.
13005 DSAStack->addAtomicDirectiveLoc(Loc: StartLoc);
13006 if (!AStmt)
13007 return StmtError();
13008
13009 // 1.2.2 OpenMP Language Terminology
13010 // Structured block - An executable statement with a single entry at the
13011 // top and a single exit at the bottom.
13012 // The point of exit cannot be a branch out of the structured block.
13013 // longjmp() and throw() must not violate the entry/exit criteria.
13014 OpenMPClauseKind AtomicKind = OMPC_unknown;
13015 SourceLocation AtomicKindLoc;
13016 OpenMPClauseKind MemOrderKind = OMPC_unknown;
13017 SourceLocation MemOrderLoc;
13018 bool MutexClauseEncountered = false;
13019 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
13020 for (const OMPClause *C : Clauses) {
13021 switch (C->getClauseKind()) {
13022 case OMPC_read:
13023 case OMPC_write:
13024 case OMPC_update:
13025 MutexClauseEncountered = true;
13026 [[fallthrough]];
13027 case OMPC_capture:
13028 case OMPC_compare: {
13029 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
13030 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_several_clauses)
13031 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13032 Diag(Loc: AtomicKindLoc, DiagID: diag::note_omp_previous_mem_order_clause)
13033 << getOpenMPClauseNameForDiag(C: AtomicKind);
13034 } else {
13035 AtomicKind = C->getClauseKind();
13036 AtomicKindLoc = C->getBeginLoc();
13037 if (!EncounteredAtomicKinds.insert(V: C->getClauseKind()).second) {
13038 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_several_clauses)
13039 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13040 Diag(Loc: AtomicKindLoc, DiagID: diag::note_omp_previous_mem_order_clause)
13041 << getOpenMPClauseNameForDiag(C: AtomicKind);
13042 }
13043 }
13044 break;
13045 }
13046 case OMPC_weak:
13047 case OMPC_fail: {
13048 if (!EncounteredAtomicKinds.contains(V: OMPC_compare)) {
13049 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_no_compare)
13050 << getOpenMPClauseNameForDiag(C: C->getClauseKind())
13051 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13052 return StmtError();
13053 }
13054 break;
13055 }
13056 case OMPC_seq_cst:
13057 case OMPC_acq_rel:
13058 case OMPC_acquire:
13059 case OMPC_release:
13060 case OMPC_relaxed: {
13061 if (MemOrderKind != OMPC_unknown) {
13062 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_several_mem_order_clauses)
13063 << getOpenMPDirectiveName(D: OMPD_atomic, Ver: OMPVersion) << 0
13064 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13065 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
13066 << getOpenMPClauseNameForDiag(C: MemOrderKind);
13067 } else {
13068 MemOrderKind = C->getClauseKind();
13069 MemOrderLoc = C->getBeginLoc();
13070 }
13071 break;
13072 }
13073 // The following clauses are allowed, but we don't need to do anything here.
13074 case OMPC_hint:
13075 break;
13076 default:
13077 llvm_unreachable("unknown clause is encountered");
13078 }
13079 }
13080 bool IsCompareCapture = false;
13081 if (EncounteredAtomicKinds.contains(V: OMPC_compare) &&
13082 EncounteredAtomicKinds.contains(V: OMPC_capture)) {
13083 IsCompareCapture = true;
13084 AtomicKind = OMPC_compare;
13085 }
13086 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
13087 // If atomic-clause is read then memory-order-clause must not be acq_rel or
13088 // release.
13089 // If atomic-clause is write then memory-order-clause must not be acq_rel or
13090 // acquire.
13091 // If atomic-clause is update or not present then memory-order-clause must not
13092 // be acq_rel or acquire.
13093 if ((AtomicKind == OMPC_read &&
13094 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
13095 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
13096 AtomicKind == OMPC_unknown) &&
13097 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
13098 SourceLocation Loc = AtomicKindLoc;
13099 if (AtomicKind == OMPC_unknown)
13100 Loc = StartLoc;
13101 Diag(Loc, DiagID: diag::err_omp_atomic_incompatible_mem_order_clause)
13102 << getOpenMPClauseNameForDiag(C: AtomicKind)
13103 << (AtomicKind == OMPC_unknown ? 1 : 0)
13104 << getOpenMPClauseNameForDiag(C: MemOrderKind);
13105 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
13106 << getOpenMPClauseNameForDiag(C: MemOrderKind);
13107 }
13108
13109 Stmt *Body = AStmt;
13110 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: Body))
13111 Body = EWC->getSubExpr();
13112
13113 Expr *X = nullptr;
13114 Expr *V = nullptr;
13115 Expr *E = nullptr;
13116 Expr *UE = nullptr;
13117 Expr *D = nullptr;
13118 Expr *CE = nullptr;
13119 Expr *R = nullptr;
13120 bool IsXLHSInRHSPart = false;
13121 bool IsPostfixUpdate = false;
13122 bool IsFailOnly = false;
13123 // OpenMP [2.12.6, atomic Construct]
13124 // In the next expressions:
13125 // * x and v (as applicable) are both l-value expressions with scalar type.
13126 // * During the execution of an atomic region, multiple syntactic
13127 // occurrences of x must designate the same storage location.
13128 // * Neither of v and expr (as applicable) may access the storage location
13129 // designated by x.
13130 // * Neither of x and expr (as applicable) may access the storage location
13131 // designated by v.
13132 // * expr is an expression with scalar type.
13133 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
13134 // * binop, binop=, ++, and -- are not overloaded operators.
13135 // * The expression x binop expr must be numerically equivalent to x binop
13136 // (expr). This requirement is satisfied if the operators in expr have
13137 // precedence greater than binop, or by using parentheses around expr or
13138 // subexpressions of expr.
13139 // * The expression expr binop x must be numerically equivalent to (expr)
13140 // binop x. This requirement is satisfied if the operators in expr have
13141 // precedence equal to or greater than binop, or by using parentheses around
13142 // expr or subexpressions of expr.
13143 // * For forms that allow multiple occurrences of x, the number of times
13144 // that x is evaluated is unspecified.
13145 if (AtomicKind == OMPC_read) {
13146 enum {
13147 NotAnExpression,
13148 NotAnAssignmentOp,
13149 NotAScalarType,
13150 NotAnLValue,
13151 NoError
13152 } ErrorFound = NoError;
13153 SourceLocation ErrorLoc, NoteLoc;
13154 SourceRange ErrorRange, NoteRange;
13155 // If clause is read:
13156 // v = x;
13157 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
13158 const auto *AtomicBinOp =
13159 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
13160 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13161 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
13162 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
13163 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
13164 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
13165 if (!X->isLValue() || !V->isLValue()) {
13166 const Expr *NotLValueExpr = X->isLValue() ? V : X;
13167 ErrorFound = NotAnLValue;
13168 ErrorLoc = AtomicBinOp->getExprLoc();
13169 ErrorRange = AtomicBinOp->getSourceRange();
13170 NoteLoc = NotLValueExpr->getExprLoc();
13171 NoteRange = NotLValueExpr->getSourceRange();
13172 }
13173 } else if (!X->isInstantiationDependent() ||
13174 !V->isInstantiationDependent()) {
13175 const Expr *NotScalarExpr =
13176 (X->isInstantiationDependent() || X->getType()->isScalarType())
13177 ? V
13178 : X;
13179 ErrorFound = NotAScalarType;
13180 ErrorLoc = AtomicBinOp->getExprLoc();
13181 ErrorRange = AtomicBinOp->getSourceRange();
13182 NoteLoc = NotScalarExpr->getExprLoc();
13183 NoteRange = NotScalarExpr->getSourceRange();
13184 }
13185 } else if (!AtomicBody->isInstantiationDependent()) {
13186 ErrorFound = NotAnAssignmentOp;
13187 ErrorLoc = AtomicBody->getExprLoc();
13188 ErrorRange = AtomicBody->getSourceRange();
13189 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13190 : AtomicBody->getExprLoc();
13191 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13192 : AtomicBody->getSourceRange();
13193 }
13194 } else {
13195 ErrorFound = NotAnExpression;
13196 NoteLoc = ErrorLoc = Body->getBeginLoc();
13197 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
13198 }
13199 if (ErrorFound != NoError) {
13200 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_read_not_expression_statement)
13201 << ErrorRange;
13202 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_read_write)
13203 << ErrorFound << NoteRange;
13204 return StmtError();
13205 }
13206 if (SemaRef.CurContext->isDependentContext())
13207 V = X = nullptr;
13208 } else if (AtomicKind == OMPC_write) {
13209 enum {
13210 NotAnExpression,
13211 NotAnAssignmentOp,
13212 NotAScalarType,
13213 NotAnLValue,
13214 NoError
13215 } ErrorFound = NoError;
13216 SourceLocation ErrorLoc, NoteLoc;
13217 SourceRange ErrorRange, NoteRange;
13218 // If clause is write:
13219 // x = expr;
13220 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
13221 const auto *AtomicBinOp =
13222 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
13223 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13224 X = AtomicBinOp->getLHS();
13225 E = AtomicBinOp->getRHS();
13226 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
13227 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
13228 if (!X->isLValue()) {
13229 ErrorFound = NotAnLValue;
13230 ErrorLoc = AtomicBinOp->getExprLoc();
13231 ErrorRange = AtomicBinOp->getSourceRange();
13232 NoteLoc = X->getExprLoc();
13233 NoteRange = X->getSourceRange();
13234 }
13235 } else if (!X->isInstantiationDependent() ||
13236 !E->isInstantiationDependent()) {
13237 const Expr *NotScalarExpr =
13238 (X->isInstantiationDependent() || X->getType()->isScalarType())
13239 ? E
13240 : X;
13241 ErrorFound = NotAScalarType;
13242 ErrorLoc = AtomicBinOp->getExprLoc();
13243 ErrorRange = AtomicBinOp->getSourceRange();
13244 NoteLoc = NotScalarExpr->getExprLoc();
13245 NoteRange = NotScalarExpr->getSourceRange();
13246 }
13247 } else if (!AtomicBody->isInstantiationDependent()) {
13248 ErrorFound = NotAnAssignmentOp;
13249 ErrorLoc = AtomicBody->getExprLoc();
13250 ErrorRange = AtomicBody->getSourceRange();
13251 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13252 : AtomicBody->getExprLoc();
13253 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13254 : AtomicBody->getSourceRange();
13255 }
13256 } else {
13257 ErrorFound = NotAnExpression;
13258 NoteLoc = ErrorLoc = Body->getBeginLoc();
13259 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
13260 }
13261 if (ErrorFound != NoError) {
13262 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_write_not_expression_statement)
13263 << ErrorRange;
13264 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_read_write)
13265 << ErrorFound << NoteRange;
13266 return StmtError();
13267 }
13268 if (SemaRef.CurContext->isDependentContext())
13269 E = X = nullptr;
13270 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
13271 // If clause is update:
13272 // x++;
13273 // x--;
13274 // ++x;
13275 // --x;
13276 // x binop= expr;
13277 // x = x binop expr;
13278 // x = expr binop x;
13279 OpenMPAtomicUpdateChecker Checker(SemaRef);
13280 if (Checker.checkStatement(
13281 S: Body,
13282 DiagId: (AtomicKind == OMPC_update)
13283 ? diag::err_omp_atomic_update_not_expression_statement
13284 : diag::err_omp_atomic_not_expression_statement,
13285 NoteId: diag::note_omp_atomic_update))
13286 return StmtError();
13287 if (!SemaRef.CurContext->isDependentContext()) {
13288 E = Checker.getExpr();
13289 X = Checker.getX();
13290 UE = Checker.getUpdateExpr();
13291 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13292 }
13293 } else if (AtomicKind == OMPC_capture) {
13294 enum {
13295 NotAnAssignmentOp,
13296 NotACompoundStatement,
13297 NotTwoSubstatements,
13298 NotASpecificExpression,
13299 NoError
13300 } ErrorFound = NoError;
13301 SourceLocation ErrorLoc, NoteLoc;
13302 SourceRange ErrorRange, NoteRange;
13303 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
13304 // If clause is a capture:
13305 // v = x++;
13306 // v = x--;
13307 // v = ++x;
13308 // v = --x;
13309 // v = x binop= expr;
13310 // v = x = x binop expr;
13311 // v = x = expr binop x;
13312 const auto *AtomicBinOp =
13313 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
13314 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13315 V = AtomicBinOp->getLHS();
13316 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
13317 OpenMPAtomicUpdateChecker Checker(SemaRef);
13318 if (Checker.checkStatement(
13319 S: Body, DiagId: diag::err_omp_atomic_capture_not_expression_statement,
13320 NoteId: diag::note_omp_atomic_update))
13321 return StmtError();
13322 E = Checker.getExpr();
13323 X = Checker.getX();
13324 UE = Checker.getUpdateExpr();
13325 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13326 IsPostfixUpdate = Checker.isPostfixUpdate();
13327 } else if (!AtomicBody->isInstantiationDependent()) {
13328 ErrorLoc = AtomicBody->getExprLoc();
13329 ErrorRange = AtomicBody->getSourceRange();
13330 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13331 : AtomicBody->getExprLoc();
13332 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13333 : AtomicBody->getSourceRange();
13334 ErrorFound = NotAnAssignmentOp;
13335 }
13336 if (ErrorFound != NoError) {
13337 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_capture_not_expression_statement)
13338 << ErrorRange;
13339 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13340 return StmtError();
13341 }
13342 if (SemaRef.CurContext->isDependentContext())
13343 UE = V = E = X = nullptr;
13344 } else {
13345 // If clause is a capture:
13346 // { v = x; x = expr; }
13347 // { v = x; x++; }
13348 // { v = x; x--; }
13349 // { v = x; ++x; }
13350 // { v = x; --x; }
13351 // { v = x; x binop= expr; }
13352 // { v = x; x = x binop expr; }
13353 // { v = x; x = expr binop x; }
13354 // { x++; v = x; }
13355 // { x--; v = x; }
13356 // { ++x; v = x; }
13357 // { --x; v = x; }
13358 // { x binop= expr; v = x; }
13359 // { x = x binop expr; v = x; }
13360 // { x = expr binop x; v = x; }
13361 if (auto *CS = dyn_cast<CompoundStmt>(Val: Body)) {
13362 // Check that this is { expr1; expr2; }
13363 if (CS->size() == 2) {
13364 Stmt *First = CS->body_front();
13365 Stmt *Second = CS->body_back();
13366 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: First))
13367 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13368 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: Second))
13369 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13370 // Need to find what subexpression is 'v' and what is 'x'.
13371 OpenMPAtomicUpdateChecker Checker(SemaRef);
13372 bool IsUpdateExprFound = !Checker.checkStatement(S: Second);
13373 BinaryOperator *BinOp = nullptr;
13374 if (IsUpdateExprFound) {
13375 BinOp = dyn_cast<BinaryOperator>(Val: First);
13376 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13377 }
13378 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
13379 // { v = x; x++; }
13380 // { v = x; x--; }
13381 // { v = x; ++x; }
13382 // { v = x; --x; }
13383 // { v = x; x binop= expr; }
13384 // { v = x; x = x binop expr; }
13385 // { v = x; x = expr binop x; }
13386 // Check that the first expression has form v = x.
13387 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13388 llvm::FoldingSetNodeID XId, PossibleXId;
13389 Checker.getX()->Profile(ID&: XId, Context, /*Canonical=*/true);
13390 PossibleX->Profile(ID&: PossibleXId, Context, /*Canonical=*/true);
13391 IsUpdateExprFound = XId == PossibleXId;
13392 if (IsUpdateExprFound) {
13393 V = BinOp->getLHS();
13394 X = Checker.getX();
13395 E = Checker.getExpr();
13396 UE = Checker.getUpdateExpr();
13397 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13398 IsPostfixUpdate = true;
13399 }
13400 }
13401 if (!IsUpdateExprFound) {
13402 IsUpdateExprFound = !Checker.checkStatement(S: First);
13403 BinOp = nullptr;
13404 if (IsUpdateExprFound) {
13405 BinOp = dyn_cast<BinaryOperator>(Val: Second);
13406 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13407 }
13408 if (IsUpdateExprFound &&
13409 !SemaRef.CurContext->isDependentContext()) {
13410 // { x++; v = x; }
13411 // { x--; v = x; }
13412 // { ++x; v = x; }
13413 // { --x; v = x; }
13414 // { x binop= expr; v = x; }
13415 // { x = x binop expr; v = x; }
13416 // { x = expr binop x; v = x; }
13417 // Check that the second expression has form v = x.
13418 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13419 llvm::FoldingSetNodeID XId, PossibleXId;
13420 Checker.getX()->Profile(ID&: XId, Context, /*Canonical=*/true);
13421 PossibleX->Profile(ID&: PossibleXId, Context, /*Canonical=*/true);
13422 IsUpdateExprFound = XId == PossibleXId;
13423 if (IsUpdateExprFound) {
13424 V = BinOp->getLHS();
13425 X = Checker.getX();
13426 E = Checker.getExpr();
13427 UE = Checker.getUpdateExpr();
13428 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13429 IsPostfixUpdate = false;
13430 }
13431 }
13432 }
13433 if (!IsUpdateExprFound) {
13434 // { v = x; x = expr; }
13435 auto *FirstExpr = dyn_cast<Expr>(Val: First);
13436 auto *SecondExpr = dyn_cast<Expr>(Val: Second);
13437 if (!FirstExpr || !SecondExpr ||
13438 !(FirstExpr->isInstantiationDependent() ||
13439 SecondExpr->isInstantiationDependent())) {
13440 auto *FirstBinOp = dyn_cast<BinaryOperator>(Val: First);
13441 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13442 ErrorFound = NotAnAssignmentOp;
13443 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13444 : First->getBeginLoc();
13445 NoteRange = ErrorRange = FirstBinOp
13446 ? FirstBinOp->getSourceRange()
13447 : SourceRange(ErrorLoc, ErrorLoc);
13448 } else {
13449 auto *SecondBinOp = dyn_cast<BinaryOperator>(Val: Second);
13450 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13451 ErrorFound = NotAnAssignmentOp;
13452 NoteLoc = ErrorLoc = SecondBinOp
13453 ? SecondBinOp->getOperatorLoc()
13454 : Second->getBeginLoc();
13455 NoteRange = ErrorRange =
13456 SecondBinOp ? SecondBinOp->getSourceRange()
13457 : SourceRange(ErrorLoc, ErrorLoc);
13458 } else {
13459 Expr *PossibleXRHSInFirst =
13460 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13461 Expr *PossibleXLHSInSecond =
13462 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13463 llvm::FoldingSetNodeID X1Id, X2Id;
13464 PossibleXRHSInFirst->Profile(ID&: X1Id, Context,
13465 /*Canonical=*/true);
13466 PossibleXLHSInSecond->Profile(ID&: X2Id, Context,
13467 /*Canonical=*/true);
13468 IsUpdateExprFound = X1Id == X2Id;
13469 if (IsUpdateExprFound) {
13470 V = FirstBinOp->getLHS();
13471 X = SecondBinOp->getLHS();
13472 E = SecondBinOp->getRHS();
13473 UE = nullptr;
13474 IsXLHSInRHSPart = false;
13475 IsPostfixUpdate = true;
13476 } else {
13477 ErrorFound = NotASpecificExpression;
13478 ErrorLoc = FirstBinOp->getExprLoc();
13479 ErrorRange = FirstBinOp->getSourceRange();
13480 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13481 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13482 }
13483 }
13484 }
13485 }
13486 }
13487 } else {
13488 NoteLoc = ErrorLoc = Body->getBeginLoc();
13489 NoteRange = ErrorRange =
13490 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13491 ErrorFound = NotTwoSubstatements;
13492 }
13493 } else {
13494 NoteLoc = ErrorLoc = Body->getBeginLoc();
13495 NoteRange = ErrorRange =
13496 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13497 ErrorFound = NotACompoundStatement;
13498 }
13499 }
13500 if (ErrorFound != NoError) {
13501 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_capture_not_compound_statement)
13502 << ErrorRange;
13503 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13504 return StmtError();
13505 }
13506 if (SemaRef.CurContext->isDependentContext())
13507 UE = V = E = X = nullptr;
13508 } else if (AtomicKind == OMPC_compare) {
13509 if (IsCompareCapture) {
13510 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13511 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
13512 if (!Checker.checkStmt(S: Body, ErrorInfo)) {
13513 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_compare_capture)
13514 << ErrorInfo.ErrorRange;
13515 Diag(Loc: ErrorInfo.NoteLoc, DiagID: diag::note_omp_atomic_compare)
13516 << ErrorInfo.Error << ErrorInfo.NoteRange;
13517 return StmtError();
13518 }
13519 X = Checker.getX();
13520 E = Checker.getE();
13521 D = Checker.getD();
13522 CE = Checker.getCond();
13523 V = Checker.getV();
13524 R = Checker.getR();
13525 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13526 IsXLHSInRHSPart = Checker.isXBinopExpr();
13527 IsFailOnly = Checker.isFailOnly();
13528 IsPostfixUpdate = Checker.isPostfixUpdate();
13529 } else {
13530 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13531 OpenMPAtomicCompareChecker Checker(SemaRef);
13532 if (!Checker.checkStmt(S: Body, ErrorInfo)) {
13533 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_compare)
13534 << ErrorInfo.ErrorRange;
13535 Diag(Loc: ErrorInfo.NoteLoc, DiagID: diag::note_omp_atomic_compare)
13536 << ErrorInfo.Error << ErrorInfo.NoteRange;
13537 return StmtError();
13538 }
13539 X = Checker.getX();
13540 E = Checker.getE();
13541 D = Checker.getD();
13542 CE = Checker.getCond();
13543 // The weak clause may only appear if the resulting atomic operation is
13544 // an atomic conditional update for which the comparison tests for
13545 // equality. It was not possible to do this check in
13546 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13547 // could not be performed (Clauses are not available).
13548 auto *It = find_if(Range&: Clauses, P: [](OMPClause *C) {
13549 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13550 });
13551 if (It != Clauses.end()) {
13552 auto *Cond = dyn_cast<BinaryOperator>(Val: CE);
13553 if (Cond->getOpcode() != BO_EQ) {
13554 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13555 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13556 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13557 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13558
13559 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_weak_no_equality)
13560 << ErrorInfo.ErrorRange;
13561 return StmtError();
13562 }
13563 }
13564 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13565 IsXLHSInRHSPart = Checker.isXBinopExpr();
13566 }
13567 }
13568
13569 SemaRef.setFunctionHasBranchProtectedScope();
13570
13571 return OMPAtomicDirective::Create(
13572 C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
13573 Exprs: {.X: X, .V: V, .R: R, .E: E, .UE: UE, .D: D, .Cond: CE, .IsXLHSInRHSPart: IsXLHSInRHSPart, .IsPostfixUpdate: IsPostfixUpdate, .IsFailOnly: IsFailOnly});
13574}
13575
13576StmtResult SemaOpenMP::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
13577 Stmt *AStmt,
13578 SourceLocation StartLoc,
13579 SourceLocation EndLoc) {
13580 if (!AStmt)
13581 return StmtError();
13582
13583 if (validateMultidimClauses(SemaRef&: *this, Clauses))
13584 return StmtError();
13585
13586 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_target, AStmt);
13587
13588 // OpenMP [2.16, Nesting of Regions]
13589 // If specified, a teams construct must be contained within a target
13590 // construct. That target construct must contain no statements or directives
13591 // outside of the teams construct.
13592 if (DSAStack->hasInnerTeamsRegion()) {
13593 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13594 bool OMPTeamsFound = true;
13595 if (const auto *CS = dyn_cast<CompoundStmt>(Val: S)) {
13596 auto I = CS->body_begin();
13597 while (I != CS->body_end()) {
13598 const auto *OED = dyn_cast<OMPExecutableDirective>(Val: *I);
13599 bool IsTeams = OED && isOpenMPTeamsDirective(DKind: OED->getDirectiveKind());
13600 if (!IsTeams || I != CS->body_begin()) {
13601 OMPTeamsFound = false;
13602 if (IsTeams && I != CS->body_begin()) {
13603 // This is the two teams case. Since the InnerTeamsRegionLoc will
13604 // point to this second one reset the iterator to the other teams.
13605 --I;
13606 }
13607 break;
13608 }
13609 ++I;
13610 }
13611 assert(I != CS->body_end() && "Not found statement");
13612 S = *I;
13613 } else {
13614 const auto *OED = dyn_cast<OMPExecutableDirective>(Val: S);
13615 OMPTeamsFound = OED && isOpenMPTeamsDirective(DKind: OED->getDirectiveKind());
13616 }
13617 if (!OMPTeamsFound) {
13618 Diag(Loc: StartLoc, DiagID: diag::err_omp_target_contains_not_only_teams);
13619 Diag(DSAStack->getInnerTeamsRegionLoc(),
13620 DiagID: diag::note_omp_nested_teams_construct_here);
13621 Diag(Loc: S->getBeginLoc(), DiagID: diag::note_omp_nested_statement_here)
13622 << isa<OMPExecutableDirective>(Val: S);
13623 return StmtError();
13624 }
13625 }
13626
13627 return OMPTargetDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
13628 AssociatedStmt: AStmt);
13629}
13630
13631StmtResult SemaOpenMP::ActOnOpenMPTargetParallelDirective(
13632 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13633 SourceLocation EndLoc) {
13634 if (!AStmt)
13635 return StmtError();
13636
13637 if (validateMultidimClauses(SemaRef&: *this, Clauses))
13638 return StmtError();
13639
13640 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel, AStmt);
13641
13642 return OMPTargetParallelDirective::Create(
13643 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
13644 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13645}
13646
13647StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForDirective(
13648 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13649 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13650 if (!AStmt)
13651 return StmtError();
13652
13653 if (validateMultidimClauses(SemaRef&: *this, Clauses))
13654 return StmtError();
13655
13656 CapturedStmt *CS =
13657 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_for, AStmt);
13658
13659 OMPLoopBasedDirective::HelperExprs B;
13660 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13661 // define the nested loops number.
13662 unsigned NestedLoopCount =
13663 checkOpenMPLoop(DKind: OMPD_target_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13664 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
13665 VarsWithImplicitDSA, Built&: B);
13666 if (NestedLoopCount == 0)
13667 return StmtError();
13668
13669 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13670 return StmtError();
13671
13672 return OMPTargetParallelForDirective::Create(
13673 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13674 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13675}
13676
13677/// Check for existence of a map clause in the list of clauses.
13678static bool hasClauses(ArrayRef<OMPClause *> Clauses,
13679 const OpenMPClauseKind K) {
13680 return llvm::any_of(
13681 Range&: Clauses, P: [K](const OMPClause *C) { return C->getClauseKind() == K; });
13682}
13683
13684template <typename... Params>
13685static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
13686 const Params... ClauseTypes) {
13687 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13688}
13689
13690/// Check if the variables in the mapping clause are externally visible.
13691static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
13692 for (const OMPClause *C : Clauses) {
13693 if (auto *TC = dyn_cast<OMPToClause>(Val: C))
13694 return llvm::all_of(Range: TC->all_decls(), P: [](ValueDecl *VD) {
13695 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13696 (VD->isExternallyVisible() &&
13697 VD->getVisibility() != HiddenVisibility);
13698 });
13699 else if (auto *FC = dyn_cast<OMPFromClause>(Val: C))
13700 return llvm::all_of(Range: FC->all_decls(), P: [](ValueDecl *VD) {
13701 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13702 (VD->isExternallyVisible() &&
13703 VD->getVisibility() != HiddenVisibility);
13704 });
13705 }
13706
13707 return true;
13708}
13709
13710StmtResult
13711SemaOpenMP::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
13712 Stmt *AStmt, SourceLocation StartLoc,
13713 SourceLocation EndLoc) {
13714 if (!AStmt)
13715 return StmtError();
13716
13717 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13718
13719 // OpenMP [2.12.2, target data Construct, Restrictions]
13720 // At least one map, use_device_addr or use_device_ptr clause must appear on
13721 // the directive.
13722 if (!hasClauses(Clauses, K: OMPC_map, ClauseTypes: OMPC_use_device_ptr) &&
13723 (getLangOpts().OpenMP < 50 ||
13724 !hasClauses(Clauses, K: OMPC_use_device_addr))) {
13725 StringRef Expected;
13726 if (getLangOpts().OpenMP < 50)
13727 Expected = "'map' or 'use_device_ptr'";
13728 else
13729 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13730 unsigned OMPVersion = getLangOpts().OpenMP;
13731 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
13732 << Expected << getOpenMPDirectiveName(D: OMPD_target_data, Ver: OMPVersion);
13733 return StmtError();
13734 }
13735
13736 SemaRef.setFunctionHasBranchProtectedScope();
13737
13738 return OMPTargetDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13739 Clauses, AssociatedStmt: AStmt);
13740}
13741
13742StmtResult SemaOpenMP::ActOnOpenMPTargetEnterDataDirective(
13743 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13744 SourceLocation EndLoc, Stmt *AStmt) {
13745 if (!AStmt)
13746 return StmtError();
13747
13748 setBranchProtectedScope(SemaRef, DKind: OMPD_target_enter_data, AStmt);
13749
13750 // OpenMP [2.10.2, Restrictions, p. 99]
13751 // At least one map clause must appear on the directive.
13752 if (!hasClauses(Clauses, K: OMPC_map)) {
13753 unsigned OMPVersion = getLangOpts().OpenMP;
13754 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
13755 << "'map'"
13756 << getOpenMPDirectiveName(D: OMPD_target_enter_data, Ver: OMPVersion);
13757 return StmtError();
13758 }
13759
13760 return OMPTargetEnterDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13761 Clauses, AssociatedStmt: AStmt);
13762}
13763
13764StmtResult SemaOpenMP::ActOnOpenMPTargetExitDataDirective(
13765 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13766 SourceLocation EndLoc, Stmt *AStmt) {
13767 if (!AStmt)
13768 return StmtError();
13769
13770 setBranchProtectedScope(SemaRef, DKind: OMPD_target_exit_data, AStmt);
13771
13772 // OpenMP [2.10.3, Restrictions, p. 102]
13773 // At least one map clause must appear on the directive.
13774 if (!hasClauses(Clauses, K: OMPC_map)) {
13775 unsigned OMPVersion = getLangOpts().OpenMP;
13776 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
13777 << "'map'" << getOpenMPDirectiveName(D: OMPD_target_exit_data, Ver: OMPVersion);
13778 return StmtError();
13779 }
13780
13781 return OMPTargetExitDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13782 Clauses, AssociatedStmt: AStmt);
13783}
13784
13785StmtResult SemaOpenMP::ActOnOpenMPTargetUpdateDirective(
13786 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13787 SourceLocation EndLoc, Stmt *AStmt) {
13788 if (!AStmt)
13789 return StmtError();
13790
13791 setBranchProtectedScope(SemaRef, DKind: OMPD_target_update, AStmt);
13792
13793 if (!hasClauses(Clauses, K: OMPC_to, ClauseTypes: OMPC_from)) {
13794 Diag(Loc: StartLoc, DiagID: diag::err_omp_at_least_one_motion_clause_required);
13795 return StmtError();
13796 }
13797
13798 if (!isClauseMappable(Clauses)) {
13799 Diag(Loc: StartLoc, DiagID: diag::err_omp_cannot_update_with_internal_linkage);
13800 return StmtError();
13801 }
13802
13803 return OMPTargetUpdateDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13804 Clauses, AssociatedStmt: AStmt);
13805}
13806
13807StmtResult SemaOpenMP::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
13808 Stmt *AStmt,
13809 SourceLocation StartLoc,
13810 SourceLocation EndLoc) {
13811 if (!AStmt)
13812 return StmtError();
13813
13814 if (validateMultidimClauses(SemaRef&: *this, Clauses))
13815 return StmtError();
13816
13817 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13818 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13819 Diag(Loc: StartLoc, DiagID: diag::warn_hip_omp_target_directives);
13820
13821 setBranchProtectedScope(SemaRef, DKind: OMPD_teams, AStmt);
13822
13823 DSAStack->setParentTeamsRegionLoc(StartLoc);
13824
13825 return OMPTeamsDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
13826 AssociatedStmt: AStmt);
13827}
13828
13829StmtResult SemaOpenMP::ActOnOpenMPCancellationPointDirective(
13830 SourceLocation StartLoc, SourceLocation EndLoc,
13831 OpenMPDirectiveKind CancelRegion) {
13832 if (DSAStack->isParentNowaitRegion()) {
13833 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_nowait) << 0;
13834 return StmtError();
13835 }
13836 if (DSAStack->isParentOrderedRegion()) {
13837 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_ordered) << 0;
13838 return StmtError();
13839 }
13840 return OMPCancellationPointDirective::Create(C: getASTContext(), StartLoc,
13841 EndLoc, CancelRegion);
13842}
13843
13844StmtResult SemaOpenMP::ActOnOpenMPCancelDirective(
13845 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13846 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13847 if (DSAStack->isParentNowaitRegion()) {
13848 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_nowait) << 1;
13849 return StmtError();
13850 }
13851 if (DSAStack->isParentOrderedRegion()) {
13852 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_ordered) << 1;
13853 return StmtError();
13854 }
13855 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13856 return OMPCancelDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
13857 CancelRegion);
13858}
13859
13860static bool checkReductionClauseWithNogroup(Sema &S,
13861 ArrayRef<OMPClause *> Clauses) {
13862 const OMPClause *ReductionClause = nullptr;
13863 const OMPClause *NogroupClause = nullptr;
13864 for (const OMPClause *C : Clauses) {
13865 if (C->getClauseKind() == OMPC_reduction) {
13866 ReductionClause = C;
13867 if (NogroupClause)
13868 break;
13869 continue;
13870 }
13871 if (C->getClauseKind() == OMPC_nogroup) {
13872 NogroupClause = C;
13873 if (ReductionClause)
13874 break;
13875 continue;
13876 }
13877 }
13878 if (ReductionClause && NogroupClause) {
13879 S.Diag(Loc: ReductionClause->getBeginLoc(), DiagID: diag::err_omp_reduction_with_nogroup)
13880 << SourceRange(NogroupClause->getBeginLoc(),
13881 NogroupClause->getEndLoc());
13882 return true;
13883 }
13884 return false;
13885}
13886
13887StmtResult SemaOpenMP::ActOnOpenMPTaskLoopDirective(
13888 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13889 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13890 if (!AStmt)
13891 return StmtError();
13892
13893 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13894 OMPLoopBasedDirective::HelperExprs B;
13895 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13896 // define the nested loops number.
13897 unsigned NestedLoopCount =
13898 checkOpenMPLoop(DKind: OMPD_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13899 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13900 DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
13901 if (NestedLoopCount == 0)
13902 return StmtError();
13903
13904 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13905 "omp for loop exprs were not built");
13906
13907 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13908 // The grainsize clause and num_tasks clause are mutually exclusive and may
13909 // not appear on the same taskloop directive.
13910 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13911 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13912 return StmtError();
13913 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13914 // If a reduction clause is present on the taskloop directive, the nogroup
13915 // clause must not be specified.
13916 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13917 return StmtError();
13918
13919 SemaRef.setFunctionHasBranchProtectedScope();
13920 return OMPTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13921 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13922 DSAStack->isCancelRegion());
13923}
13924
13925StmtResult SemaOpenMP::ActOnOpenMPTaskLoopSimdDirective(
13926 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13927 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13928 if (!AStmt)
13929 return StmtError();
13930
13931 CapturedStmt *CS =
13932 setBranchProtectedScope(SemaRef, DKind: OMPD_taskloop_simd, AStmt);
13933
13934 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13935 OMPLoopBasedDirective::HelperExprs B;
13936 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13937 // define the nested loops number.
13938 unsigned NestedLoopCount =
13939 checkOpenMPLoop(DKind: OMPD_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13940 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
13941 VarsWithImplicitDSA, Built&: B);
13942 if (NestedLoopCount == 0)
13943 return StmtError();
13944
13945 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13946 return StmtError();
13947
13948 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13949 // The grainsize clause and num_tasks clause are mutually exclusive and may
13950 // not appear on the same taskloop directive.
13951 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13952 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13953 return StmtError();
13954 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13955 // If a reduction clause is present on the taskloop directive, the nogroup
13956 // clause must not be specified.
13957 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13958 return StmtError();
13959 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13960 return StmtError();
13961
13962 return OMPTaskLoopSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13963 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13964}
13965
13966StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopDirective(
13967 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13968 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13969 if (!AStmt)
13970 return StmtError();
13971
13972 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13973 OMPLoopBasedDirective::HelperExprs B;
13974 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13975 // define the nested loops number.
13976 unsigned NestedLoopCount =
13977 checkOpenMPLoop(DKind: OMPD_master_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13978 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13979 DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
13980 if (NestedLoopCount == 0)
13981 return StmtError();
13982
13983 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13984 "omp for loop exprs were not built");
13985
13986 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13987 // The grainsize clause and num_tasks clause are mutually exclusive and may
13988 // not appear on the same taskloop directive.
13989 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13990 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13991 return StmtError();
13992 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13993 // If a reduction clause is present on the taskloop directive, the nogroup
13994 // clause must not be specified.
13995 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13996 return StmtError();
13997
13998 SemaRef.setFunctionHasBranchProtectedScope();
13999 return OMPMasterTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14000 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14001 DSAStack->isCancelRegion());
14002}
14003
14004StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopDirective(
14005 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14006 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14007 if (!AStmt)
14008 return StmtError();
14009
14010 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
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 =
14015 checkOpenMPLoop(DKind: OMPD_masked_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14016 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
14017 DSA&: *DSAStack, 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 SemaRef.setFunctionHasBranchProtectedScope();
14037 return OMPMaskedTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14038 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14039 DSAStack->isCancelRegion());
14040}
14041
14042StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopSimdDirective(
14043 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14044 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14045 if (!AStmt)
14046 return StmtError();
14047
14048 CapturedStmt *CS =
14049 setBranchProtectedScope(SemaRef, DKind: OMPD_master_taskloop_simd, AStmt);
14050
14051 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14052 OMPLoopBasedDirective::HelperExprs B;
14053 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14054 // define the nested loops number.
14055 unsigned NestedLoopCount =
14056 checkOpenMPLoop(DKind: OMPD_master_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14057 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14058 VarsWithImplicitDSA, Built&: B);
14059 if (NestedLoopCount == 0)
14060 return StmtError();
14061
14062 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14063 return StmtError();
14064
14065 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14066 // The grainsize clause and num_tasks clause are mutually exclusive and may
14067 // not appear on the same taskloop directive.
14068 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14069 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14070 return StmtError();
14071 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14072 // If a reduction clause is present on the taskloop directive, the nogroup
14073 // clause must not be specified.
14074 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14075 return StmtError();
14076 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14077 return StmtError();
14078
14079 return OMPMasterTaskLoopSimdDirective::Create(
14080 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14081}
14082
14083StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopSimdDirective(
14084 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14085 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14086 if (!AStmt)
14087 return StmtError();
14088
14089 CapturedStmt *CS =
14090 setBranchProtectedScope(SemaRef, DKind: OMPD_masked_taskloop_simd, AStmt);
14091
14092 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14093 OMPLoopBasedDirective::HelperExprs B;
14094 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14095 // define the nested loops number.
14096 unsigned NestedLoopCount =
14097 checkOpenMPLoop(DKind: OMPD_masked_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14098 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14099 VarsWithImplicitDSA, Built&: B);
14100 if (NestedLoopCount == 0)
14101 return StmtError();
14102
14103 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14104 return StmtError();
14105
14106 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14107 // The grainsize clause and num_tasks clause are mutually exclusive and may
14108 // not appear on the same taskloop directive.
14109 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14110 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14111 return StmtError();
14112 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14113 // If a reduction clause is present on the taskloop directive, the nogroup
14114 // clause must not be specified.
14115 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14116 return StmtError();
14117 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14118 return StmtError();
14119
14120 return OMPMaskedTaskLoopSimdDirective::Create(
14121 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14122}
14123
14124StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopDirective(
14125 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14126 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14127 if (!AStmt)
14128 return StmtError();
14129
14130 CapturedStmt *CS =
14131 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_master_taskloop, AStmt);
14132
14133 OMPLoopBasedDirective::HelperExprs B;
14134 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14135 // define the nested loops number.
14136 unsigned NestedLoopCount = checkOpenMPLoop(
14137 DKind: OMPD_parallel_master_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14138 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14139 VarsWithImplicitDSA, Built&: B);
14140 if (NestedLoopCount == 0)
14141 return StmtError();
14142
14143 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14144 "omp for loop exprs were not built");
14145
14146 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14147 // The grainsize clause and num_tasks clause are mutually exclusive and may
14148 // not appear on the same taskloop directive.
14149 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14150 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14151 return StmtError();
14152 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14153 // If a reduction clause is present on the taskloop directive, the nogroup
14154 // clause must not be specified.
14155 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14156 return StmtError();
14157
14158 return OMPParallelMasterTaskLoopDirective::Create(
14159 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14160 DSAStack->isCancelRegion());
14161}
14162
14163StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopDirective(
14164 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14165 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14166 if (!AStmt)
14167 return StmtError();
14168
14169 CapturedStmt *CS =
14170 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_masked_taskloop, AStmt);
14171
14172 OMPLoopBasedDirective::HelperExprs B;
14173 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14174 // define the nested loops number.
14175 unsigned NestedLoopCount = checkOpenMPLoop(
14176 DKind: OMPD_parallel_masked_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14177 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14178 VarsWithImplicitDSA, Built&: B);
14179 if (NestedLoopCount == 0)
14180 return StmtError();
14181
14182 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14183 "omp for loop exprs were not built");
14184
14185 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14186 // The grainsize clause and num_tasks clause are mutually exclusive and may
14187 // not appear on the same taskloop directive.
14188 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14189 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14190 return StmtError();
14191 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14192 // If a reduction clause is present on the taskloop directive, the nogroup
14193 // clause must not be specified.
14194 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14195 return StmtError();
14196
14197 return OMPParallelMaskedTaskLoopDirective::Create(
14198 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14199 DSAStack->isCancelRegion());
14200}
14201
14202StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
14203 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14204 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14205 if (!AStmt)
14206 return StmtError();
14207
14208 CapturedStmt *CS = setBranchProtectedScope(
14209 SemaRef, DKind: OMPD_parallel_master_taskloop_simd, AStmt);
14210
14211 OMPLoopBasedDirective::HelperExprs B;
14212 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14213 // define the nested loops number.
14214 unsigned NestedLoopCount = checkOpenMPLoop(
14215 DKind: OMPD_parallel_master_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14216 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14217 VarsWithImplicitDSA, Built&: B);
14218 if (NestedLoopCount == 0)
14219 return StmtError();
14220
14221 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14222 return StmtError();
14223
14224 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14225 // The grainsize clause and num_tasks clause are mutually exclusive and may
14226 // not appear on the same taskloop directive.
14227 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14228 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14229 return StmtError();
14230 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14231 // If a reduction clause is present on the taskloop directive, the nogroup
14232 // clause must not be specified.
14233 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14234 return StmtError();
14235 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14236 return StmtError();
14237
14238 return OMPParallelMasterTaskLoopSimdDirective::Create(
14239 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14240}
14241
14242StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
14243 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14244 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14245 if (!AStmt)
14246 return StmtError();
14247
14248 CapturedStmt *CS = setBranchProtectedScope(
14249 SemaRef, DKind: OMPD_parallel_masked_taskloop_simd, AStmt);
14250
14251 OMPLoopBasedDirective::HelperExprs B;
14252 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14253 // define the nested loops number.
14254 unsigned NestedLoopCount = checkOpenMPLoop(
14255 DKind: OMPD_parallel_masked_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14256 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
14257 VarsWithImplicitDSA, Built&: B);
14258 if (NestedLoopCount == 0)
14259 return StmtError();
14260
14261 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14262 return StmtError();
14263
14264 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14265 // The grainsize clause and num_tasks clause are mutually exclusive and may
14266 // not appear on the same taskloop directive.
14267 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14268 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
14269 return StmtError();
14270 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14271 // If a reduction clause is present on the taskloop directive, the nogroup
14272 // clause must not be specified.
14273 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
14274 return StmtError();
14275 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14276 return StmtError();
14277
14278 return OMPParallelMaskedTaskLoopSimdDirective::Create(
14279 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14280}
14281
14282StmtResult SemaOpenMP::ActOnOpenMPDistributeDirective(
14283 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14284 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14285 if (!AStmt)
14286 return StmtError();
14287
14288 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14289 OMPLoopBasedDirective::HelperExprs B;
14290 // In presence of clause 'collapse' with number of loops, it will
14291 // define the nested loops number.
14292 unsigned NestedLoopCount =
14293 checkOpenMPLoop(DKind: OMPD_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14294 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt,
14295 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14296 if (NestedLoopCount == 0)
14297 return StmtError();
14298
14299 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14300 "omp for loop exprs were not built");
14301
14302 SemaRef.setFunctionHasBranchProtectedScope();
14303 auto *DistributeDirective = OMPDistributeDirective::Create(
14304 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14305 return DistributeDirective;
14306}
14307
14308StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForDirective(
14309 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14310 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14311 if (!AStmt)
14312 return StmtError();
14313
14314 CapturedStmt *CS =
14315 setBranchProtectedScope(SemaRef, DKind: OMPD_distribute_parallel_for, AStmt);
14316
14317 OMPLoopBasedDirective::HelperExprs B;
14318 // In presence of clause 'collapse' with number of loops, it will
14319 // define the nested loops number.
14320 unsigned NestedLoopCount = checkOpenMPLoop(
14321 DKind: OMPD_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14322 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14323 VarsWithImplicitDSA, Built&: B);
14324 if (NestedLoopCount == 0)
14325 return StmtError();
14326
14327 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14328 "omp for loop exprs were not built");
14329
14330 return OMPDistributeParallelForDirective::Create(
14331 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14332 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14333}
14334
14335StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForSimdDirective(
14336 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14337 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14338 if (!AStmt)
14339 return StmtError();
14340
14341 CapturedStmt *CS = setBranchProtectedScope(
14342 SemaRef, DKind: OMPD_distribute_parallel_for_simd, AStmt);
14343
14344 OMPLoopBasedDirective::HelperExprs B;
14345 // In presence of clause 'collapse' with number of loops, it will
14346 // define the nested loops number.
14347 unsigned NestedLoopCount = checkOpenMPLoop(
14348 DKind: OMPD_distribute_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14349 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14350 VarsWithImplicitDSA, Built&: B);
14351 if (NestedLoopCount == 0)
14352 return StmtError();
14353
14354 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14355 return StmtError();
14356
14357 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14358 return StmtError();
14359
14360 return OMPDistributeParallelForSimdDirective::Create(
14361 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14362}
14363
14364StmtResult SemaOpenMP::ActOnOpenMPDistributeSimdDirective(
14365 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14366 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14367 if (!AStmt)
14368 return StmtError();
14369
14370 CapturedStmt *CS =
14371 setBranchProtectedScope(SemaRef, DKind: OMPD_distribute_simd, AStmt);
14372
14373 OMPLoopBasedDirective::HelperExprs B;
14374 // In presence of clause 'collapse' with number of loops, it will
14375 // define the nested loops number.
14376 unsigned NestedLoopCount =
14377 checkOpenMPLoop(DKind: OMPD_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14378 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
14379 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14380 if (NestedLoopCount == 0)
14381 return StmtError();
14382
14383 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14384 return StmtError();
14385
14386 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14387 return StmtError();
14388
14389 return OMPDistributeSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14390 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14391}
14392
14393StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForSimdDirective(
14394 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14395 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14396 if (!AStmt)
14397 return StmtError();
14398
14399 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14400 return StmtError();
14401
14402 CapturedStmt *CS =
14403 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_for_simd, AStmt);
14404
14405 OMPLoopBasedDirective::HelperExprs B;
14406 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14407 // define the nested loops number.
14408 unsigned NestedLoopCount = checkOpenMPLoop(
14409 DKind: OMPD_target_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14410 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
14411 VarsWithImplicitDSA, Built&: B);
14412 if (NestedLoopCount == 0)
14413 return StmtError();
14414
14415 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14416 return StmtError();
14417
14418 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14419 return StmtError();
14420
14421 return OMPTargetParallelForSimdDirective::Create(
14422 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14423}
14424
14425StmtResult SemaOpenMP::ActOnOpenMPTargetSimdDirective(
14426 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14427 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14428 if (!AStmt)
14429 return StmtError();
14430
14431 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14432 return StmtError();
14433
14434 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_target_simd, AStmt);
14435
14436 OMPLoopBasedDirective::HelperExprs B;
14437 // In presence of clause 'collapse' with number of loops, it will define the
14438 // nested loops number.
14439 unsigned NestedLoopCount =
14440 checkOpenMPLoop(DKind: OMPD_target_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14441 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
14442 VarsWithImplicitDSA, Built&: B);
14443 if (NestedLoopCount == 0)
14444 return StmtError();
14445
14446 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14447 return StmtError();
14448
14449 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14450 return StmtError();
14451
14452 return OMPTargetSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14453 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14454}
14455
14456StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeDirective(
14457 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14458 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14459 if (!AStmt)
14460 return StmtError();
14461
14462 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14463 return StmtError();
14464
14465 CapturedStmt *CS =
14466 setBranchProtectedScope(SemaRef, DKind: OMPD_teams_distribute, AStmt);
14467
14468 OMPLoopBasedDirective::HelperExprs B;
14469 // In presence of clause 'collapse' with number of loops, it will
14470 // define the nested loops number.
14471 unsigned NestedLoopCount =
14472 checkOpenMPLoop(DKind: OMPD_teams_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14473 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
14474 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14475 if (NestedLoopCount == 0)
14476 return StmtError();
14477
14478 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14479 "omp teams distribute loop exprs were not built");
14480
14481 DSAStack->setParentTeamsRegionLoc(StartLoc);
14482
14483 return OMPTeamsDistributeDirective::Create(
14484 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14485}
14486
14487StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeSimdDirective(
14488 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14489 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14490 if (!AStmt)
14491 return StmtError();
14492
14493 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14494 return StmtError();
14495
14496 CapturedStmt *CS =
14497 setBranchProtectedScope(SemaRef, DKind: OMPD_teams_distribute_simd, AStmt);
14498
14499 OMPLoopBasedDirective::HelperExprs B;
14500 // In presence of clause 'collapse' with number of loops, it will
14501 // define the nested loops number.
14502 unsigned NestedLoopCount = checkOpenMPLoop(
14503 DKind: OMPD_teams_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14504 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14505 VarsWithImplicitDSA, Built&: B);
14506 if (NestedLoopCount == 0)
14507 return StmtError();
14508
14509 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14510 return StmtError();
14511
14512 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14513 return StmtError();
14514
14515 DSAStack->setParentTeamsRegionLoc(StartLoc);
14516
14517 return OMPTeamsDistributeSimdDirective::Create(
14518 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14519}
14520
14521StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
14522 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14523 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14524 if (!AStmt)
14525 return StmtError();
14526
14527 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14528 return StmtError();
14529
14530 CapturedStmt *CS = setBranchProtectedScope(
14531 SemaRef, DKind: OMPD_teams_distribute_parallel_for_simd, AStmt);
14532
14533 OMPLoopBasedDirective::HelperExprs B;
14534 // In presence of clause 'collapse' with number of loops, it will
14535 // define the nested loops number.
14536 unsigned NestedLoopCount = checkOpenMPLoop(
14537 DKind: OMPD_teams_distribute_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14538 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14539 VarsWithImplicitDSA, Built&: B);
14540 if (NestedLoopCount == 0)
14541 return StmtError();
14542
14543 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14544 return StmtError();
14545
14546 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14547 return StmtError();
14548
14549 DSAStack->setParentTeamsRegionLoc(StartLoc);
14550
14551 return OMPTeamsDistributeParallelForSimdDirective::Create(
14552 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14553}
14554
14555StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForDirective(
14556 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14557 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14558 if (!AStmt)
14559 return StmtError();
14560
14561 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14562 return StmtError();
14563
14564 CapturedStmt *CS = setBranchProtectedScope(
14565 SemaRef, DKind: OMPD_teams_distribute_parallel_for, AStmt);
14566
14567 OMPLoopBasedDirective::HelperExprs B;
14568 // In presence of clause 'collapse' with number of loops, it will
14569 // define the nested loops number.
14570 unsigned NestedLoopCount = checkOpenMPLoop(
14571 DKind: OMPD_teams_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14572 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14573 VarsWithImplicitDSA, Built&: B);
14574
14575 if (NestedLoopCount == 0)
14576 return StmtError();
14577
14578 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14579 "omp for loop exprs were not built");
14580
14581 DSAStack->setParentTeamsRegionLoc(StartLoc);
14582
14583 return OMPTeamsDistributeParallelForDirective::Create(
14584 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14585 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14586}
14587
14588StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDirective(
14589 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14590 SourceLocation EndLoc) {
14591 if (!AStmt)
14592 return StmtError();
14593
14594 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams, AStmt);
14595
14596 if (validateMultidimClauses(SemaRef&: *this, Clauses, /*MayHaveBareClause=*/true))
14597 return StmtError();
14598
14599 return OMPTargetTeamsDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14600 Clauses, AssociatedStmt: AStmt);
14601}
14602
14603StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeDirective(
14604 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14605 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14606 if (!AStmt)
14607 return StmtError();
14608
14609 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14610 return StmtError();
14611
14612 CapturedStmt *CS =
14613 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams_distribute, AStmt);
14614
14615 OMPLoopBasedDirective::HelperExprs B;
14616 // In presence of clause 'collapse' with number of loops, it will
14617 // define the nested loops number.
14618 unsigned NestedLoopCount = checkOpenMPLoop(
14619 DKind: OMPD_target_teams_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14620 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14621 VarsWithImplicitDSA, Built&: B);
14622 if (NestedLoopCount == 0)
14623 return StmtError();
14624
14625 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14626 "omp target teams distribute loop exprs were not built");
14627
14628 return OMPTargetTeamsDistributeDirective::Create(
14629 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14630}
14631
14632StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14633 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14634 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14635 if (!AStmt)
14636 return StmtError();
14637
14638 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14639 return StmtError();
14640
14641 CapturedStmt *CS = setBranchProtectedScope(
14642 SemaRef, DKind: OMPD_target_teams_distribute_parallel_for, AStmt);
14643
14644 OMPLoopBasedDirective::HelperExprs B;
14645 // In presence of clause 'collapse' with number of loops, it will
14646 // define the nested loops number.
14647 unsigned NestedLoopCount = checkOpenMPLoop(
14648 DKind: OMPD_target_teams_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14649 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14650 VarsWithImplicitDSA, Built&: B);
14651 if (NestedLoopCount == 0)
14652 return StmtError();
14653
14654 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14655 return StmtError();
14656
14657 return OMPTargetTeamsDistributeParallelForDirective::Create(
14658 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14659 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14660}
14661
14662StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14663 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14664 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14665 if (!AStmt)
14666 return StmtError();
14667
14668 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14669 return StmtError();
14670
14671 CapturedStmt *CS = setBranchProtectedScope(
14672 SemaRef, DKind: OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14673
14674 OMPLoopBasedDirective::HelperExprs B;
14675 // In presence of clause 'collapse' with number of loops, it will
14676 // define the nested loops number.
14677 unsigned NestedLoopCount =
14678 checkOpenMPLoop(DKind: OMPD_target_teams_distribute_parallel_for_simd,
14679 CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14680 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
14681 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14682 if (NestedLoopCount == 0)
14683 return StmtError();
14684
14685 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14686 return StmtError();
14687
14688 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14689 return StmtError();
14690
14691 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14692 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14693}
14694
14695StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14696 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14697 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14698 if (!AStmt)
14699 return StmtError();
14700
14701 if (validateMultidimClauses(SemaRef&: *this, Clauses))
14702 return StmtError();
14703
14704 CapturedStmt *CS = setBranchProtectedScope(
14705 SemaRef, DKind: OMPD_target_teams_distribute_simd, AStmt);
14706
14707 OMPLoopBasedDirective::HelperExprs B;
14708 // In presence of clause 'collapse' with number of loops, it will
14709 // define the nested loops number.
14710 unsigned NestedLoopCount = checkOpenMPLoop(
14711 DKind: OMPD_target_teams_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14712 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14713 VarsWithImplicitDSA, Built&: B);
14714 if (NestedLoopCount == 0)
14715 return StmtError();
14716
14717 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14718 return StmtError();
14719
14720 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14721 return StmtError();
14722
14723 return OMPTargetTeamsDistributeSimdDirective::Create(
14724 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14725}
14726
14727/// Updates OriginalInits by checking Transform against loop transformation
14728/// directives and appending their pre-inits if a match is found.
14729static void updatePreInits(OMPLoopTransformationDirective *Transform,
14730 SmallVectorImpl<Stmt *> &PreInits) {
14731 Stmt *Dir = Transform->getDirective();
14732 switch (Dir->getStmtClass()) {
14733#define STMT(CLASS, PARENT)
14734#define ABSTRACT_STMT(CLASS)
14735#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14736 case Stmt::CLASS##Class: \
14737 appendFlattenedStmtList(PreInits, \
14738 static_cast<const CLASS *>(Dir)->getPreInits()); \
14739 break;
14740#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14741 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14742#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14743 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14744#include "clang/AST/StmtNodes.inc"
14745#undef COMMON_OMP_LOOP_TRANSFORMATION
14746 default:
14747 llvm_unreachable("Not a loop transformation");
14748 }
14749}
14750
14751bool SemaOpenMP::checkTransformableLoopNest(
14752 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14753 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14754 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *>> &OriginalInits) {
14755 OriginalInits.emplace_back();
14756 bool Result = OMPLoopBasedDirective::doForAllLoops(
14757 CurStmt: AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14758 Callback: [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14759 Stmt *CurStmt) {
14760 VarsWithInheritedDSAType TmpDSA;
14761 unsigned SingleNumLoops =
14762 checkOpenMPLoop(DKind: Kind, CollapseLoopCountExpr: nullptr, OrderedLoopCountExpr: nullptr, AStmt: CurStmt, SemaRef, DSA&: *DSAStack,
14763 VarsWithImplicitDSA&: TmpDSA, Built&: LoopHelpers[Cnt]);
14764 if (SingleNumLoops == 0)
14765 return true;
14766 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14767 if (auto *For = dyn_cast<ForStmt>(Val: CurStmt)) {
14768 OriginalInits.back().push_back(Elt: For->getInit());
14769 Body = For->getBody();
14770 } else {
14771 assert(isa<CXXForRangeStmt>(CurStmt) &&
14772 "Expected canonical for or range-based for loops.");
14773 auto *CXXFor = cast<CXXForRangeStmt>(Val: CurStmt);
14774 OriginalInits.back().push_back(Elt: CXXFor->getBeginStmt());
14775 Body = CXXFor->getBody();
14776 }
14777 OriginalInits.emplace_back();
14778 return false;
14779 },
14780 OnTransformationCallback: [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14781 updatePreInits(Transform, PreInits&: OriginalInits.back());
14782 });
14783 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14784 OriginalInits.pop_back();
14785 return Result;
14786}
14787
14788/// Counts the total number of OpenMP canonical nested loops, including the
14789/// outermost loop (the original loop). PRECONDITION of this visitor is that it
14790/// must be invoked from the original loop to be analyzed. The traversal stops
14791/// for Decl's and Expr's given that they may contain inner loops that must not
14792/// be counted.
14793///
14794/// Example AST structure for the code:
14795///
14796/// int main() {
14797/// #pragma omp fuse
14798/// {
14799/// for (int i = 0; i < 100; i++) { <-- Outer loop
14800/// []() {
14801/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (1)
14802/// };
14803/// for(int j = 0; j < 5; ++j) {} <-- Inner loop
14804/// }
14805/// for (int r = 0; i < 100; i++) { <-- Outer loop
14806/// struct LocalClass {
14807/// void bar() {
14808/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (2)
14809/// }
14810/// };
14811/// for(int k = 0; k < 10; ++k) {} <-- Inner loop
14812/// {x = 5; for(k = 0; k < 10; ++k) x += k; x}; <-- NOT A LOOP (3)
14813/// }
14814/// }
14815/// }
14816/// (1) because in a different function (here: a lambda)
14817/// (2) because in a different function (here: class method)
14818/// (3) because considered to be intervening-code of non-perfectly nested loop
14819/// Result: Loop 'i' contains 2 loops, Loop 'r' also contains 2 loops.
14820class NestedLoopCounterVisitor final : public DynamicRecursiveASTVisitor {
14821private:
14822 unsigned NestedLoopCount = 0;
14823
14824public:
14825 explicit NestedLoopCounterVisitor() = default;
14826
14827 unsigned getNestedLoopCount() const { return NestedLoopCount; }
14828
14829 bool VisitForStmt(ForStmt *FS) override {
14830 ++NestedLoopCount;
14831 return true;
14832 }
14833
14834 bool VisitCXXForRangeStmt(CXXForRangeStmt *FRS) override {
14835 ++NestedLoopCount;
14836 return true;
14837 }
14838
14839 bool TraverseStmt(Stmt *S) override {
14840 if (!S)
14841 return true;
14842
14843 // Skip traversal of all expressions, including special cases like
14844 // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
14845 // may contain inner statements (and even loops), but they are not part
14846 // of the syntactic body of the surrounding loop structure.
14847 // Therefore must not be counted.
14848 if (isa<Expr>(Val: S))
14849 return true;
14850
14851 // Only recurse into CompoundStmt (block {}) and loop bodies.
14852 if (isa<CompoundStmt, ForStmt, CXXForRangeStmt>(Val: S)) {
14853 return DynamicRecursiveASTVisitor::TraverseStmt(S);
14854 }
14855
14856 // Stop traversal of the rest of statements, that break perfect
14857 // loop nesting, such as control flow (IfStmt, SwitchStmt...).
14858 return true;
14859 }
14860
14861 bool TraverseDecl(Decl *D) override {
14862 // Stop in the case of finding a declaration, it is not important
14863 // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
14864 // FunctionDecl...).
14865 return true;
14866 }
14867};
14868
14869bool SemaOpenMP::analyzeLoopSequence(Stmt *LoopSeqStmt,
14870 LoopSequenceAnalysis &SeqAnalysis,
14871 ASTContext &Context,
14872 OpenMPDirectiveKind Kind) {
14873 VarsWithInheritedDSAType TmpDSA;
14874 // Helper Lambda to handle storing initialization and body statements for
14875 // both ForStmt and CXXForRangeStmt.
14876 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14877 if (auto *For = dyn_cast<ForStmt>(Val: LoopStmt)) {
14878 Analysis.OriginalInits.push_back(Elt: For->getInit());
14879 Analysis.TheForStmt = For;
14880 } else {
14881 auto *CXXFor = cast<CXXForRangeStmt>(Val: LoopStmt);
14882 Analysis.OriginalInits.push_back(Elt: CXXFor->getBeginStmt());
14883 Analysis.TheForStmt = CXXFor;
14884 }
14885 };
14886
14887 // Helper lambda functions to encapsulate the processing of different
14888 // derivations of the canonical loop sequence grammar
14889 // Modularized code for handling loop generation and transformations.
14890 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14891 auto *LoopTransform = cast<OMPLoopTransformationDirective>(Val: Child);
14892 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14893 unsigned NumGeneratedTopLevelLoops =
14894 LoopTransform->getNumGeneratedTopLevelLoops();
14895 // Handle the case where transformed statement is not available due to
14896 // dependent contexts
14897 if (!TransformedStmt) {
14898 if (NumGeneratedTopLevelLoops > 0) {
14899 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14900 return true;
14901 }
14902 // Unroll full (0 loops produced)
14903 Diag(Loc: Child->getBeginLoc(), DiagID: diag::err_omp_not_for)
14904 << 0 << getOpenMPDirectiveName(D: Kind);
14905 return false;
14906 }
14907 // Handle loop transformations with multiple loop nests
14908 // Unroll full
14909 if (!NumGeneratedTopLevelLoops) {
14910 Diag(Loc: Child->getBeginLoc(), DiagID: diag::err_omp_not_for)
14911 << 0 << getOpenMPDirectiveName(D: Kind);
14912 return false;
14913 }
14914 // Loop transformatons such as split or loopranged fuse
14915 if (NumGeneratedTopLevelLoops > 1) {
14916 // Get the preinits related to this loop sequence generating
14917 // loop transformation (i.e loopranged fuse, split...)
14918 // These preinits differ slightly from regular inits/pre-inits related
14919 // to single loop generating loop transformations (interchange, unroll)
14920 // given that they are not bounded to a particular loop nest
14921 // so they need to be treated independently
14922 updatePreInits(Transform: LoopTransform, PreInits&: SeqAnalysis.LoopSequencePreInits);
14923 return analyzeLoopSequence(LoopSeqStmt: TransformedStmt, SeqAnalysis, Context, Kind);
14924 }
14925 // Vast majority: (Tile, Unroll, Stripe, Reverse, Interchange, Fuse all)
14926 // Process the transformed loop statement
14927 LoopAnalysis &NewTransformedSingleLoop =
14928 SeqAnalysis.Loops.emplace_back(Args&: Child);
14929 unsigned IsCanonical = checkOpenMPLoop(
14930 DKind: Kind, CollapseLoopCountExpr: nullptr, OrderedLoopCountExpr: nullptr, AStmt: TransformedStmt, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA&: TmpDSA,
14931 Built&: NewTransformedSingleLoop.HelperExprs);
14932
14933 if (!IsCanonical)
14934 return false;
14935
14936 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
14937 updatePreInits(Transform: LoopTransform, PreInits&: NewTransformedSingleLoop.TransformsPreInits);
14938
14939 SeqAnalysis.LoopSeqSize++;
14940 return true;
14941 };
14942
14943 // Modularized code for handling regular canonical loops.
14944 auto AnalyzeRegularLoop = [&](Stmt *Child) {
14945 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Args&: Child);
14946 unsigned IsCanonical =
14947 checkOpenMPLoop(DKind: Kind, CollapseLoopCountExpr: nullptr, OrderedLoopCountExpr: nullptr, AStmt: Child, SemaRef, DSA&: *DSAStack,
14948 VarsWithImplicitDSA&: TmpDSA, Built&: NewRegularLoop.HelperExprs);
14949
14950 if (!IsCanonical)
14951 return false;
14952
14953 StoreLoopStatements(NewRegularLoop, Child);
14954 NestedLoopCounterVisitor NLCV;
14955 NLCV.TraverseStmt(S: Child);
14956 return true;
14957 };
14958
14959 // High level grammar validation.
14960 for (Stmt *Child : LoopSeqStmt->children()) {
14961 if (!Child)
14962 continue;
14963 // Skip over non-loop-sequence statements.
14964 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(S: Child)) {
14965 Child = Child->IgnoreContainers();
14966 // Ignore empty compound statement.
14967 if (!Child)
14968 continue;
14969 // In the case of a nested loop sequence ignoring containers would not
14970 // be enough, a recurisve transversal of the loop sequence is required.
14971 if (isa<CompoundStmt>(Val: Child)) {
14972 if (!analyzeLoopSequence(LoopSeqStmt: Child, SeqAnalysis, Context, Kind))
14973 return false;
14974 // Already been treated, skip this children
14975 continue;
14976 }
14977 }
14978 // Regular loop sequence handling.
14979 if (LoopSequenceAnalysis::isLoopSequenceDerivation(S: Child)) {
14980 if (LoopAnalysis::isLoopTransformation(S: Child)) {
14981 if (!AnalyzeLoopGeneration(Child))
14982 return false;
14983 // AnalyzeLoopGeneration updates SeqAnalysis.LoopSeqSize accordingly.
14984 } else {
14985 if (!AnalyzeRegularLoop(Child))
14986 return false;
14987 SeqAnalysis.LoopSeqSize++;
14988 }
14989 } else {
14990 // Report error for invalid statement inside canonical loop sequence.
14991 Diag(Loc: Child->getBeginLoc(), DiagID: diag::err_omp_not_for)
14992 << 0 << getOpenMPDirectiveName(D: Kind);
14993 return false;
14994 }
14995 }
14996 return true;
14997}
14998
14999bool SemaOpenMP::checkTransformableLoopSequence(
15000 OpenMPDirectiveKind Kind, Stmt *AStmt, LoopSequenceAnalysis &SeqAnalysis,
15001 ASTContext &Context) {
15002 // Following OpenMP 6.0 API Specification, a Canonical Loop Sequence follows
15003 // the grammar:
15004 //
15005 // canonical-loop-sequence:
15006 // {
15007 // loop-sequence+
15008 // }
15009 // where loop-sequence can be any of the following:
15010 // 1. canonical-loop-sequence
15011 // 2. loop-nest
15012 // 3. loop-sequence-generating-construct (i.e OMPLoopTransformationDirective)
15013 //
15014 // To recognise and traverse this structure the helper function
15015 // analyzeLoopSequence serves as the recurisve entry point
15016 // and tries to match the input AST to the canonical loop sequence grammar
15017 // structure. This function will perform both a semantic and syntactical
15018 // analysis of the given statement according to OpenMP 6.0 definition of
15019 // the aforementioned canonical loop sequence.
15020
15021 // We expect an outer compound statement.
15022 if (!isa<CompoundStmt>(Val: AStmt)) {
15023 Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_not_a_loop_sequence)
15024 << getOpenMPDirectiveName(D: Kind);
15025 return false;
15026 }
15027
15028 // Recursive entry point to process the main loop sequence
15029 if (!analyzeLoopSequence(LoopSeqStmt: AStmt, SeqAnalysis, Context, Kind))
15030 return false;
15031
15032 // Diagnose an empty loop sequence.
15033 if (!SeqAnalysis.LoopSeqSize) {
15034 Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_empty_loop_sequence)
15035 << getOpenMPDirectiveName(D: Kind);
15036 return false;
15037 }
15038 return true;
15039}
15040
15041/// Add preinit statements that need to be propagated from the selected loop.
15042static void addLoopPreInits(ASTContext &Context,
15043 OMPLoopBasedDirective::HelperExprs &LoopHelper,
15044 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
15045 SmallVectorImpl<Stmt *> &PreInits) {
15046
15047 // For range-based for-statements, ensure that their syntactic sugar is
15048 // executed by adding them as pre-init statements.
15049 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt)) {
15050 Stmt *RangeInit = CXXRangeFor->getInit();
15051 if (RangeInit)
15052 PreInits.push_back(Elt: RangeInit);
15053
15054 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
15055 PreInits.push_back(Elt: new (Context) DeclStmt(RangeStmt->getDeclGroup(),
15056 RangeStmt->getBeginLoc(),
15057 RangeStmt->getEndLoc()));
15058
15059 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
15060 PreInits.push_back(Elt: new (Context) DeclStmt(RangeEnd->getDeclGroup(),
15061 RangeEnd->getBeginLoc(),
15062 RangeEnd->getEndLoc()));
15063 }
15064
15065 llvm::append_range(C&: PreInits, R&: OriginalInit);
15066
15067 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
15068 if (auto *PI = cast_or_null<DeclStmt>(Val: LoopHelper.PreInits)) {
15069 PreInits.push_back(Elt: new (Context) DeclStmt(
15070 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
15071 }
15072
15073 // Gather declarations for the data members used as counters.
15074 for (Expr *CounterRef : LoopHelper.Counters) {
15075 auto *CounterDecl = cast<DeclRefExpr>(Val: CounterRef)->getDecl();
15076 if (isa<OMPCapturedExprDecl>(Val: CounterDecl))
15077 PreInits.push_back(Elt: new (Context) DeclStmt(
15078 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
15079 }
15080}
15081
15082/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
15083/// loop of a construct.
15084static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
15085 size_t NumLoops = LoopStmts.size();
15086 OMPLoopBasedDirective::doForAllLoops(
15087 CurStmt: AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
15088 Callback: [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
15089 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
15090 LoopStmts[Cnt] = CurStmt;
15091 return false;
15092 });
15093 assert(!is_contained(LoopStmts, nullptr) &&
15094 "Expecting a loop statement for each affected loop");
15095}
15096
15097/// Build and return a DeclRefExpr for the floor induction variable using the
15098/// SemaRef and the provided parameters.
15099static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
15100 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
15101 return buildDeclRefExpr(S&: SemaRef, D: FloorIndVars[I], Ty: IVTy,
15102 Loc: OrigCntVar->getExprLoc());
15103}
15104
15105StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
15106 Stmt *AStmt,
15107 SourceLocation StartLoc,
15108 SourceLocation EndLoc) {
15109 ASTContext &Context = getASTContext();
15110 Scope *CurScope = SemaRef.getCurScope();
15111
15112 const auto *SizesClause =
15113 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15114 if (!SizesClause ||
15115 llvm::any_of(Range: SizesClause->getSizesRefs(), P: [](Expr *E) { return !E; }))
15116 return StmtError();
15117 unsigned NumLoops = SizesClause->getNumSizes();
15118
15119 // Empty statement should only be possible if there already was an error.
15120 if (!AStmt)
15121 return StmtError();
15122
15123 // Verify and diagnose loop nest.
15124 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
15125 Stmt *Body = nullptr;
15126 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
15127 if (!checkTransformableLoopNest(Kind: OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
15128 OriginalInits))
15129 return StmtError();
15130
15131 // Delay tiling to when template is completely instantiated.
15132 if (SemaRef.CurContext->isDependentContext())
15133 return OMPTileDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15134 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
15135
15136 assert(LoopHelpers.size() == NumLoops &&
15137 "Expecting loop iteration space dimensionality to match number of "
15138 "affected loops");
15139 assert(OriginalInits.size() == NumLoops &&
15140 "Expecting loop iteration space dimensionality to match number of "
15141 "affected loops");
15142
15143 // Collect all affected loop statements.
15144 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15145 collectLoopStmts(AStmt, LoopStmts);
15146
15147 SmallVector<Stmt *, 4> PreInits;
15148 CaptureVars CopyTransformer(SemaRef);
15149
15150 // Create iteration variables for the generated loops.
15151 SmallVector<VarDecl *, 4> FloorIndVars;
15152 SmallVector<VarDecl *, 4> TileIndVars;
15153 FloorIndVars.resize(N: NumLoops);
15154 TileIndVars.resize(N: NumLoops);
15155 for (unsigned I = 0; I < NumLoops; ++I) {
15156 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15157
15158 assert(LoopHelper.Counters.size() == 1 &&
15159 "Expect single-dimensional loop iteration space");
15160 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15161 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15162 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15163 QualType CntTy = IterVarRef->getType();
15164
15165 // Iteration variable for the floor (i.e. outer) loop.
15166 {
15167 std::string FloorCntName =
15168 (Twine(".floor_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15169 VarDecl *FloorCntDecl =
15170 buildVarDecl(SemaRef, Loc: {}, Type: CntTy, Name: FloorCntName, Attrs: nullptr, OrigRef: OrigCntVar);
15171 FloorIndVars[I] = FloorCntDecl;
15172 }
15173
15174 // Iteration variable for the tile (i.e. inner) loop.
15175 {
15176 std::string TileCntName =
15177 (Twine(".tile_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15178
15179 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15180 // used by the expressions to derive the original iteration variable's
15181 // value from the logical iteration number.
15182 auto *TileCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
15183 TileCntDecl->setDeclName(
15184 &SemaRef.PP.getIdentifierTable().get(Name: TileCntName));
15185 TileIndVars[I] = TileCntDecl;
15186 }
15187
15188 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
15189 PreInits);
15190 }
15191
15192 // Once the original iteration values are set, append the innermost body.
15193 Stmt *Inner = Body;
15194
15195 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
15196 SizesClause, CurScope](int I) -> Expr * {
15197 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
15198
15199 if (DimTileSizeExpr->containsErrors())
15200 return nullptr;
15201
15202 if (isa<ConstantExpr>(Val: DimTileSizeExpr))
15203 return AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr));
15204
15205 // When the tile size is not a constant but a variable, it is possible to
15206 // pass non-positive numbers. For instance:
15207 // \code{c}
15208 // int a = 0;
15209 // #pragma omp tile sizes(a)
15210 // for (int i = 0; i < 42; ++i)
15211 // body(i);
15212 // \endcode
15213 // Although there is no meaningful interpretation of the tile size, the body
15214 // should still be executed 42 times to avoid surprises. To preserve the
15215 // invariant that every loop iteration is executed exactly once and not
15216 // cause an infinite loop, apply a minimum tile size of one.
15217 // Build expr:
15218 // \code{c}
15219 // (TS <= 0) ? 1 : TS
15220 // \endcode
15221 QualType DimTy = DimTileSizeExpr->getType();
15222 uint64_t DimWidth = Context.getTypeSize(T: DimTy);
15223 IntegerLiteral *Zero = IntegerLiteral::Create(
15224 C: Context, V: llvm::APInt::getZero(numBits: DimWidth), type: DimTy, l: {});
15225 IntegerLiteral *One =
15226 IntegerLiteral::Create(C: Context, V: llvm::APInt(DimWidth, 1), type: DimTy, l: {});
15227 Expr *Cond = AssertSuccess(R: SemaRef.BuildBinOp(
15228 S: CurScope, OpLoc: {}, Opc: BO_LE,
15229 LHSExpr: AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr)), RHSExpr: Zero));
15230 Expr *MinOne = new (Context) ConditionalOperator(
15231 Cond, {}, One, {},
15232 AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr)), DimTy,
15233 VK_PRValue, OK_Ordinary);
15234 return MinOne;
15235 };
15236
15237 // Create tile loops from the inside to the outside.
15238 for (int I = NumLoops - 1; I >= 0; --I) {
15239 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15240 Expr *NumIterations = LoopHelper.NumIterations;
15241 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15242 QualType IVTy = NumIterations->getType();
15243 Stmt *LoopStmt = LoopStmts[I];
15244
15245 // Commonly used variables. One of the constraints of an AST is that every
15246 // node object must appear at most once, hence we define a lambda that
15247 // creates a new AST node at every use.
15248 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
15249 OrigCntVar]() {
15250 return buildDeclRefExpr(S&: SemaRef, D: TileIndVars[I], Ty: IVTy,
15251 Loc: OrigCntVar->getExprLoc());
15252 };
15253
15254 // For init-statement: auto .tile.iv = .floor.iv
15255 SemaRef.AddInitializerToDecl(
15256 dcl: TileIndVars[I],
15257 init: SemaRef
15258 .DefaultLvalueConversion(
15259 E: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15260 .get(),
15261 /*DirectInit=*/false);
15262 Decl *CounterDecl = TileIndVars[I];
15263 StmtResult InitStmt = new (Context)
15264 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15265 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15266 if (!InitStmt.isUsable())
15267 return StmtError();
15268
15269 // For cond-expression:
15270 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
15271 Expr *DimTileSize = MakeDimTileSize(I);
15272 if (!DimTileSize)
15273 return StmtError();
15274 ExprResult EndOfTile = SemaRef.BuildBinOp(
15275 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
15276 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15277 RHSExpr: DimTileSize);
15278 if (!EndOfTile.isUsable())
15279 return StmtError();
15280 ExprResult IsPartialTile =
15281 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15282 LHSExpr: NumIterations, RHSExpr: EndOfTile.get());
15283 if (!IsPartialTile.isUsable())
15284 return StmtError();
15285 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
15286 QuestionLoc: LoopHelper.Cond->getBeginLoc(), ColonLoc: LoopHelper.Cond->getEndLoc(),
15287 CondExpr: IsPartialTile.get(), LHSExpr: NumIterations, RHSExpr: EndOfTile.get());
15288 if (!MinTileAndIterSpace.isUsable())
15289 return StmtError();
15290 ExprResult CondExpr =
15291 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15292 LHSExpr: MakeTileIVRef(), RHSExpr: MinTileAndIterSpace.get());
15293 if (!CondExpr.isUsable())
15294 return StmtError();
15295
15296 // For incr-statement: ++.tile.iv
15297 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15298 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeTileIVRef());
15299 if (!IncrStmt.isUsable())
15300 return StmtError();
15301
15302 // Statements to set the original iteration variable's value from the
15303 // logical iteration number.
15304 // Generated for loop is:
15305 // \code
15306 // Original_for_init;
15307 // for (auto .tile.iv = .floor.iv;
15308 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
15309 // ++.tile.iv) {
15310 // Original_Body;
15311 // Original_counter_update;
15312 // }
15313 // \endcode
15314 // FIXME: If the innermost body is an loop itself, inserting these
15315 // statements stops it being recognized as a perfectly nested loop (e.g.
15316 // for applying tiling again). If this is the case, sink the expressions
15317 // further into the inner loop.
15318 SmallVector<Stmt *, 4> BodyParts;
15319 BodyParts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
15320 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
15321 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
15322 BodyParts.push_back(Elt: Inner);
15323 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
15324 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
15325 Inner = new (Context)
15326 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15327 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15328 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15329 }
15330
15331 // Create floor loops from the inside to the outside.
15332 for (int I = NumLoops - 1; I >= 0; --I) {
15333 auto &LoopHelper = LoopHelpers[I];
15334 Expr *NumIterations = LoopHelper.NumIterations;
15335 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15336 QualType IVTy = NumIterations->getType();
15337
15338 // For init-statement: auto .floor.iv = 0
15339 SemaRef.AddInitializerToDecl(
15340 dcl: FloorIndVars[I],
15341 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
15342 /*DirectInit=*/false);
15343 Decl *CounterDecl = FloorIndVars[I];
15344 StmtResult InitStmt = new (Context)
15345 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15346 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15347 if (!InitStmt.isUsable())
15348 return StmtError();
15349
15350 // For cond-expression: .floor.iv < NumIterations
15351 ExprResult CondExpr = SemaRef.BuildBinOp(
15352 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15353 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15354 RHSExpr: NumIterations);
15355 if (!CondExpr.isUsable())
15356 return StmtError();
15357
15358 // For incr-statement: .floor.iv += DimTileSize
15359 Expr *DimTileSize = MakeDimTileSize(I);
15360 if (!DimTileSize)
15361 return StmtError();
15362 ExprResult IncrStmt = SemaRef.BuildBinOp(
15363 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
15364 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15365 RHSExpr: DimTileSize);
15366 if (!IncrStmt.isUsable())
15367 return StmtError();
15368
15369 Inner = new (Context)
15370 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15371 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15372 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15373 }
15374
15375 return OMPTileDirective::Create(C: Context, StartLoc, EndLoc, Clauses, NumLoops,
15376 AssociatedStmt: AStmt, TransformedStmt: Inner,
15377 PreInits: buildPreInits(Context, PreInits));
15378}
15379
15380StmtResult SemaOpenMP::ActOnOpenMPStripeDirective(ArrayRef<OMPClause *> Clauses,
15381 Stmt *AStmt,
15382 SourceLocation StartLoc,
15383 SourceLocation EndLoc) {
15384 ASTContext &Context = getASTContext();
15385 Scope *CurScope = SemaRef.getCurScope();
15386
15387 const auto *SizesClause =
15388 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15389 if (!SizesClause ||
15390 llvm::any_of(Range: SizesClause->getSizesRefs(), P: [](const Expr *SizeExpr) {
15391 return !SizeExpr || SizeExpr->containsErrors();
15392 }))
15393 return StmtError();
15394 unsigned NumLoops = SizesClause->getNumSizes();
15395
15396 // Empty statement should only be possible if there already was an error.
15397 if (!AStmt)
15398 return StmtError();
15399
15400 // Verify and diagnose loop nest.
15401 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
15402 Stmt *Body = nullptr;
15403 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
15404 if (!checkTransformableLoopNest(Kind: OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15405 Body, OriginalInits))
15406 return StmtError();
15407
15408 // Delay striping to when template is completely instantiated.
15409 if (SemaRef.CurContext->isDependentContext())
15410 return OMPStripeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15411 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
15412
15413 assert(LoopHelpers.size() == NumLoops &&
15414 "Expecting loop iteration space dimensionality to match number of "
15415 "affected loops");
15416 assert(OriginalInits.size() == NumLoops &&
15417 "Expecting loop iteration space dimensionality to match number of "
15418 "affected loops");
15419
15420 // Collect all affected loop statements.
15421 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15422 collectLoopStmts(AStmt, LoopStmts);
15423
15424 SmallVector<Stmt *, 4> PreInits;
15425 CaptureVars CopyTransformer(SemaRef);
15426
15427 // Create iteration variables for the generated loops.
15428 SmallVector<VarDecl *, 4> FloorIndVars;
15429 SmallVector<VarDecl *, 4> StripeIndVars;
15430 FloorIndVars.resize(N: NumLoops);
15431 StripeIndVars.resize(N: NumLoops);
15432 for (unsigned I : llvm::seq<unsigned>(Size: NumLoops)) {
15433 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15434
15435 assert(LoopHelper.Counters.size() == 1 &&
15436 "Expect single-dimensional loop iteration space");
15437 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15438 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15439 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15440 QualType CntTy = IterVarRef->getType();
15441
15442 // Iteration variable for the stripe (i.e. outer) loop.
15443 {
15444 std::string FloorCntName =
15445 (Twine(".floor_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15446 VarDecl *FloorCntDecl =
15447 buildVarDecl(SemaRef, Loc: {}, Type: CntTy, Name: FloorCntName, Attrs: nullptr, OrigRef: OrigCntVar);
15448 FloorIndVars[I] = FloorCntDecl;
15449 }
15450
15451 // Iteration variable for the stripe (i.e. inner) loop.
15452 {
15453 std::string StripeCntName =
15454 (Twine(".stripe_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15455
15456 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15457 // used by the expressions to derive the original iteration variable's
15458 // value from the logical iteration number.
15459 auto *StripeCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
15460 StripeCntDecl->setDeclName(
15461 &SemaRef.PP.getIdentifierTable().get(Name: StripeCntName));
15462 StripeIndVars[I] = StripeCntDecl;
15463 }
15464
15465 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
15466 PreInits);
15467 }
15468
15469 // Once the original iteration values are set, append the innermost body.
15470 Stmt *Inner = Body;
15471
15472 auto MakeDimStripeSize = [&](int I) -> Expr * {
15473 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15474 if (isa<ConstantExpr>(Val: DimStripeSizeExpr))
15475 return AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr));
15476
15477 // When the stripe size is not a constant but a variable, it is possible to
15478 // pass non-positive numbers. For instance:
15479 // \code{c}
15480 // int a = 0;
15481 // #pragma omp stripe sizes(a)
15482 // for (int i = 0; i < 42; ++i)
15483 // body(i);
15484 // \endcode
15485 // Although there is no meaningful interpretation of the stripe size, the
15486 // body should still be executed 42 times to avoid surprises. To preserve
15487 // the invariant that every loop iteration is executed exactly once and not
15488 // cause an infinite loop, apply a minimum stripe size of one.
15489 // Build expr:
15490 // \code{c}
15491 // (TS <= 0) ? 1 : TS
15492 // \endcode
15493 QualType DimTy = DimStripeSizeExpr->getType();
15494 uint64_t DimWidth = Context.getTypeSize(T: DimTy);
15495 IntegerLiteral *Zero = IntegerLiteral::Create(
15496 C: Context, V: llvm::APInt::getZero(numBits: DimWidth), type: DimTy, l: {});
15497 IntegerLiteral *One =
15498 IntegerLiteral::Create(C: Context, V: llvm::APInt(DimWidth, 1), type: DimTy, l: {});
15499 Expr *Cond = AssertSuccess(R: SemaRef.BuildBinOp(
15500 S: CurScope, OpLoc: {}, Opc: BO_LE,
15501 LHSExpr: AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr)), RHSExpr: Zero));
15502 Expr *MinOne = new (Context) ConditionalOperator(
15503 Cond, {}, One, {},
15504 AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr)), DimTy,
15505 VK_PRValue, OK_Ordinary);
15506 return MinOne;
15507 };
15508
15509 // Create stripe loops from the inside to the outside.
15510 for (int I = NumLoops - 1; I >= 0; --I) {
15511 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15512 Expr *NumIterations = LoopHelper.NumIterations;
15513 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15514 QualType IVTy = NumIterations->getType();
15515 Stmt *LoopStmt = LoopStmts[I];
15516
15517 // For init-statement: auto .stripe.iv = .floor.iv
15518 SemaRef.AddInitializerToDecl(
15519 dcl: StripeIndVars[I],
15520 init: SemaRef
15521 .DefaultLvalueConversion(
15522 E: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15523 .get(),
15524 /*DirectInit=*/false);
15525 Decl *CounterDecl = StripeIndVars[I];
15526 StmtResult InitStmt = new (Context)
15527 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15528 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15529 if (!InitStmt.isUsable())
15530 return StmtError();
15531
15532 // For cond-expression:
15533 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
15534 ExprResult EndOfStripe = SemaRef.BuildBinOp(
15535 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
15536 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15537 RHSExpr: MakeDimStripeSize(I));
15538 if (!EndOfStripe.isUsable())
15539 return StmtError();
15540 ExprResult IsPartialStripe =
15541 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15542 LHSExpr: NumIterations, RHSExpr: EndOfStripe.get());
15543 if (!IsPartialStripe.isUsable())
15544 return StmtError();
15545 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
15546 QuestionLoc: LoopHelper.Cond->getBeginLoc(), ColonLoc: LoopHelper.Cond->getEndLoc(),
15547 CondExpr: IsPartialStripe.get(), LHSExpr: NumIterations, RHSExpr: EndOfStripe.get());
15548 if (!MinStripeAndIterSpace.isUsable())
15549 return StmtError();
15550 ExprResult CondExpr = SemaRef.BuildBinOp(
15551 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15552 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars: StripeIndVars, I, IVTy, OrigCntVar),
15553 RHSExpr: MinStripeAndIterSpace.get());
15554 if (!CondExpr.isUsable())
15555 return StmtError();
15556
15557 // For incr-statement: ++.stripe.iv
15558 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15559 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc,
15560 Input: makeFloorIVRef(SemaRef, FloorIndVars: StripeIndVars, I, IVTy, OrigCntVar));
15561 if (!IncrStmt.isUsable())
15562 return StmtError();
15563
15564 // Statements to set the original iteration variable's value from the
15565 // logical iteration number.
15566 // Generated for loop is:
15567 // \code
15568 // Original_for_init;
15569 // for (auto .stripe.iv = .floor.iv;
15570 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
15571 // ++.stripe.iv) {
15572 // Original_Body;
15573 // Original_counter_update;
15574 // }
15575 // \endcode
15576 // FIXME: If the innermost body is a loop itself, inserting these
15577 // statements stops it being recognized as a perfectly nested loop (e.g.
15578 // for applying another loop transformation). If this is the case, sink the
15579 // expressions further into the inner loop.
15580 SmallVector<Stmt *, 4> BodyParts;
15581 BodyParts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
15582 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
15583 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
15584 BodyParts.push_back(Elt: Inner);
15585 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
15586 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
15587 Inner = new (Context)
15588 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15589 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15590 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15591 }
15592
15593 // Create grid loops from the inside to the outside.
15594 for (int I = NumLoops - 1; I >= 0; --I) {
15595 auto &LoopHelper = LoopHelpers[I];
15596 Expr *NumIterations = LoopHelper.NumIterations;
15597 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15598 QualType IVTy = NumIterations->getType();
15599
15600 // For init-statement: auto .grid.iv = 0
15601 SemaRef.AddInitializerToDecl(
15602 dcl: FloorIndVars[I],
15603 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
15604 /*DirectInit=*/false);
15605 Decl *CounterDecl = FloorIndVars[I];
15606 StmtResult InitStmt = new (Context)
15607 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15608 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15609 if (!InitStmt.isUsable())
15610 return StmtError();
15611
15612 // For cond-expression: .floor.iv < NumIterations
15613 ExprResult CondExpr = SemaRef.BuildBinOp(
15614 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15615 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15616 RHSExpr: NumIterations);
15617 if (!CondExpr.isUsable())
15618 return StmtError();
15619
15620 // For incr-statement: .floor.iv += DimStripeSize
15621 ExprResult IncrStmt = SemaRef.BuildBinOp(
15622 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
15623 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15624 RHSExpr: MakeDimStripeSize(I));
15625 if (!IncrStmt.isUsable())
15626 return StmtError();
15627
15628 Inner = new (Context)
15629 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15630 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15631 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15632 }
15633
15634 return OMPStripeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15635 NumLoops, AssociatedStmt: AStmt, TransformedStmt: Inner,
15636 PreInits: buildPreInits(Context, PreInits));
15637}
15638
15639StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
15640 Stmt *AStmt,
15641 SourceLocation StartLoc,
15642 SourceLocation EndLoc) {
15643 ASTContext &Context = getASTContext();
15644 Scope *CurScope = SemaRef.getCurScope();
15645 // Empty statement should only be possible if there already was an error.
15646 if (!AStmt)
15647 return StmtError();
15648
15649 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
15650 MutuallyExclusiveClauses: {OMPC_partial, OMPC_full}))
15651 return StmtError();
15652
15653 const OMPFullClause *FullClause =
15654 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15655 const OMPPartialClause *PartialClause =
15656 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15657 assert(!(FullClause && PartialClause) &&
15658 "mutual exclusivity must have been checked before");
15659
15660 constexpr unsigned NumLoops = 1;
15661 Stmt *Body = nullptr;
15662 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
15663 NumLoops);
15664 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15665 if (!checkTransformableLoopNest(Kind: OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15666 Body, OriginalInits))
15667 return StmtError();
15668
15669 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15670
15671 // Delay unrolling to when template is completely instantiated.
15672 if (SemaRef.CurContext->isDependentContext())
15673 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
15674 NumGeneratedTopLevelLoops, TransformedStmt: nullptr,
15675 PreInits: nullptr);
15676
15677 assert(LoopHelpers.size() == NumLoops &&
15678 "Expecting a single-dimensional loop iteration space");
15679 assert(OriginalInits.size() == NumLoops &&
15680 "Expecting a single-dimensional loop iteration space");
15681 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15682
15683 if (FullClause) {
15684 if (!VerifyPositiveIntegerConstantInClause(
15685 Op: LoopHelper.NumIterations, CKind: OMPC_full, /*StrictlyPositive=*/false,
15686 /*SuppressExprDiags=*/true)
15687 .isUsable()) {
15688 Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_unroll_full_variable_trip_count);
15689 Diag(Loc: FullClause->getBeginLoc(), DiagID: diag::note_omp_directive_here)
15690 << "#pragma omp unroll full";
15691 return StmtError();
15692 }
15693 }
15694
15695 // The generated loop may only be passed to other loop-associated directive
15696 // when a partial clause is specified. Without the requirement it is
15697 // sufficient to generate loop unroll metadata at code-generation.
15698 if (NumGeneratedTopLevelLoops == 0)
15699 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
15700 NumGeneratedTopLevelLoops, TransformedStmt: nullptr,
15701 PreInits: nullptr);
15702
15703 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15704 // associated with another loop directive.
15705 //
15706 // The canonical loop analysis return by checkTransformableLoopNest assumes
15707 // the following structure to be the same loop without transformations or
15708 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15709 // LoopHelper.Counters;
15710 // for (; IV < LoopHelper.NumIterations; ++IV) {
15711 // LoopHelper.Updates;
15712 // Body;
15713 // }
15714 // \endcode
15715 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15716 // and referenced by LoopHelper.IterationVarRef.
15717 //
15718 // The unrolling directive transforms this into the following loop:
15719 // \code
15720 // OriginalInits; \
15721 // LoopHelper.PreInits; > NewPreInits
15722 // LoopHelper.Counters; /
15723 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15724 // #pragma clang loop unroll_count(Factor)
15725 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15726 // {
15727 // LoopHelper.Updates;
15728 // Body;
15729 // }
15730 // }
15731 // \endcode
15732 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15733 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15734 // references it. If the partially unrolled loop is associated with another
15735 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15736 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15737 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15738 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15739 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15740 // property of the OMPLoopBasedDirective instead of statements in
15741 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15742 // of a canonical loop nest where these PreInits are emitted before the
15743 // outermost directive.
15744
15745 // Find the loop statement.
15746 Stmt *LoopStmt = nullptr;
15747 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
15748
15749 // Determine the PreInit declarations.
15750 SmallVector<Stmt *, 4> PreInits;
15751 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
15752
15753 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15754 QualType IVTy = IterationVarRef->getType();
15755 assert(LoopHelper.Counters.size() == 1 &&
15756 "Expecting a single-dimensional loop iteration space");
15757 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15758
15759 // Determine the unroll factor.
15760 uint64_t Factor;
15761 SourceLocation FactorLoc;
15762 if (Expr *FactorVal = PartialClause->getFactor();
15763 FactorVal && !FactorVal->containsErrors()) {
15764 Factor = FactorVal->getIntegerConstantExpr(Ctx: Context)->getZExtValue();
15765 FactorLoc = FactorVal->getExprLoc();
15766 } else {
15767 // TODO: Use a better profitability model.
15768 Factor = 2;
15769 }
15770 assert(Factor > 0 && "Expected positive unroll factor");
15771 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15772 return IntegerLiteral::Create(
15773 C: getASTContext(), V: llvm::APInt(getASTContext().getIntWidth(T: IVTy), Factor),
15774 type: IVTy, l: FactorLoc);
15775 };
15776
15777 // Iteration variable SourceLocations.
15778 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15779 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15780 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15781
15782 // Internal variable names.
15783 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15784 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15785 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15786
15787 // Create the iteration variable for the unrolled loop.
15788 VarDecl *OuterIVDecl =
15789 buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: OuterIVName, Attrs: nullptr, OrigRef: OrigVar);
15790 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15791 return buildDeclRefExpr(S&: SemaRef, D: OuterIVDecl, Ty: IVTy, Loc: OrigVarLoc);
15792 };
15793
15794 // Iteration variable for the inner loop: Reuse the iteration variable created
15795 // by checkOpenMPLoop.
15796 auto *InnerIVDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
15797 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name: InnerIVName));
15798 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15799 return buildDeclRefExpr(S&: SemaRef, D: InnerIVDecl, Ty: IVTy, Loc: OrigVarLoc);
15800 };
15801
15802 // Make a copy of the NumIterations expression for each use: By the AST
15803 // constraints, every expression object in a DeclContext must be unique.
15804 CaptureVars CopyTransformer(SemaRef);
15805 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15806 return AssertSuccess(
15807 R: CopyTransformer.TransformExpr(E: LoopHelper.NumIterations));
15808 };
15809
15810 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15811 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(E: MakeOuterRef());
15812 SemaRef.AddInitializerToDecl(dcl: InnerIVDecl, init: LValueConv.get(),
15813 /*DirectInit=*/false);
15814 StmtResult InnerInit = new (Context)
15815 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15816 if (!InnerInit.isUsable())
15817 return StmtError();
15818
15819 // Inner For cond-expression:
15820 // \code
15821 // .unroll_inner.iv < .unrolled.iv + Factor &&
15822 // .unroll_inner.iv < NumIterations
15823 // \endcode
15824 // This conjunction of two conditions allows ScalarEvolution to derive the
15825 // maximum trip count of the inner loop.
15826 ExprResult EndOfTile =
15827 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
15828 LHSExpr: MakeOuterRef(), RHSExpr: MakeFactorExpr());
15829 if (!EndOfTile.isUsable())
15830 return StmtError();
15831 ExprResult InnerCond1 =
15832 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15833 LHSExpr: MakeInnerRef(), RHSExpr: EndOfTile.get());
15834 if (!InnerCond1.isUsable())
15835 return StmtError();
15836 ExprResult InnerCond2 =
15837 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15838 LHSExpr: MakeInnerRef(), RHSExpr: MakeNumIterations());
15839 if (!InnerCond2.isUsable())
15840 return StmtError();
15841 ExprResult InnerCond =
15842 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LAnd,
15843 LHSExpr: InnerCond1.get(), RHSExpr: InnerCond2.get());
15844 if (!InnerCond.isUsable())
15845 return StmtError();
15846
15847 // Inner For incr-statement: ++.unroll_inner.iv
15848 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15849 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeInnerRef());
15850 if (!InnerIncr.isUsable())
15851 return StmtError();
15852
15853 // Inner For statement.
15854 SmallVector<Stmt *> InnerBodyStmts;
15855 InnerBodyStmts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
15856 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
15857 InnerBodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
15858 InnerBodyStmts.push_back(Elt: Body);
15859 CompoundStmt *InnerBody =
15860 CompoundStmt::Create(C: getASTContext(), Stmts: InnerBodyStmts, FPFeatures: FPOptionsOverride(),
15861 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
15862 ForStmt *InnerFor = new (Context)
15863 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15864 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15865 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15866
15867 // Unroll metadata for the inner loop.
15868 // This needs to take into account the remainder portion of the unrolled loop,
15869 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15870 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15871 // the maximum trip count, which will also generate a remainder loop. Just
15872 // `unroll(enable)` (which could have been useful if the user has not
15873 // specified a concrete factor; even though the outer loop cannot be
15874 // influenced anymore, would avoid more code bloat than necessary) will refuse
15875 // the loop because "Won't unroll; remainder loop could not be generated when
15876 // assuming runtime trip count". Even if it did work, it must not choose a
15877 // larger unroll factor than the maximum loop length, or it would always just
15878 // execute the remainder loop.
15879 LoopHintAttr *UnrollHintAttr =
15880 LoopHintAttr::CreateImplicit(Ctx&: Context, Option: LoopHintAttr::UnrollCount,
15881 State: LoopHintAttr::Numeric, Value: MakeFactorExpr());
15882 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15883 C: getASTContext(), Loc: StartLoc, Attrs: {UnrollHintAttr}, SubStmt: InnerFor);
15884
15885 // Outer For init-statement: auto .unrolled.iv = 0
15886 SemaRef.AddInitializerToDecl(
15887 dcl: OuterIVDecl,
15888 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
15889 /*DirectInit=*/false);
15890 StmtResult OuterInit = new (Context)
15891 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15892 if (!OuterInit.isUsable())
15893 return StmtError();
15894
15895 // Outer For cond-expression: .unrolled.iv < NumIterations
15896 ExprResult OuterConde =
15897 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15898 LHSExpr: MakeOuterRef(), RHSExpr: MakeNumIterations());
15899 if (!OuterConde.isUsable())
15900 return StmtError();
15901
15902 // Outer For incr-statement: .unrolled.iv += Factor
15903 ExprResult OuterIncr =
15904 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
15905 LHSExpr: MakeOuterRef(), RHSExpr: MakeFactorExpr());
15906 if (!OuterIncr.isUsable())
15907 return StmtError();
15908
15909 // Outer For statement.
15910 ForStmt *OuterFor = new (Context)
15911 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15912 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15913 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15914
15915 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
15916 NumGeneratedTopLevelLoops, TransformedStmt: OuterFor,
15917 PreInits: buildPreInits(Context, PreInits));
15918}
15919
15920StmtResult SemaOpenMP::ActOnOpenMPReverseDirective(Stmt *AStmt,
15921 SourceLocation StartLoc,
15922 SourceLocation EndLoc) {
15923 ASTContext &Context = getASTContext();
15924 Scope *CurScope = SemaRef.getCurScope();
15925
15926 // Empty statement should only be possible if there already was an error.
15927 if (!AStmt)
15928 return StmtError();
15929
15930 constexpr unsigned NumLoops = 1;
15931 Stmt *Body = nullptr;
15932 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
15933 NumLoops);
15934 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15935 if (!checkTransformableLoopNest(Kind: OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15936 Body, OriginalInits))
15937 return StmtError();
15938
15939 // Delay applying the transformation to when template is completely
15940 // instantiated.
15941 if (SemaRef.CurContext->isDependentContext())
15942 return OMPReverseDirective::Create(C: Context, StartLoc, EndLoc, AssociatedStmt: AStmt,
15943 NumLoops, TransformedStmt: nullptr, PreInits: nullptr);
15944
15945 assert(LoopHelpers.size() == NumLoops &&
15946 "Expecting a single-dimensional loop iteration space");
15947 assert(OriginalInits.size() == NumLoops &&
15948 "Expecting a single-dimensional loop iteration space");
15949 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15950
15951 // Find the loop statement.
15952 Stmt *LoopStmt = nullptr;
15953 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
15954
15955 // Determine the PreInit declarations.
15956 SmallVector<Stmt *> PreInits;
15957 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
15958
15959 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15960 QualType IVTy = IterationVarRef->getType();
15961 uint64_t IVWidth = Context.getTypeSize(T: IVTy);
15962 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15963
15964 // Iteration variable SourceLocations.
15965 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15966 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15967 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15968
15969 // Locations pointing to the transformation.
15970 SourceLocation TransformLoc = StartLoc;
15971 SourceLocation TransformLocBegin = StartLoc;
15972 SourceLocation TransformLocEnd = EndLoc;
15973
15974 // Internal variable names.
15975 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15976 SmallString<64> ForwardIVName(".forward.iv.");
15977 ForwardIVName += OrigVarName;
15978 SmallString<64> ReversedIVName(".reversed.iv.");
15979 ReversedIVName += OrigVarName;
15980
15981 // LoopHelper.Updates will read the logical iteration number from
15982 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
15983 // that logical iteration from it, then assign it to the user loop counter
15984 // variable. We cannot directly use LoopHelper.IterationVarRef as the
15985 // induction variable of the generated loop because it may cause an underflow:
15986 // \code{.c}
15987 // for (unsigned i = 0; i < n; ++i)
15988 // body(i);
15989 // \endcode
15990 //
15991 // Naive reversal:
15992 // \code{.c}
15993 // for (unsigned i = n-1; i >= 0; --i)
15994 // body(i);
15995 // \endcode
15996 //
15997 // Instead, we introduce a new iteration variable representing the logical
15998 // iteration counter of the original loop, convert it to the logical iteration
15999 // number of the reversed loop, then let LoopHelper.Updates compute the user's
16000 // loop iteration variable from it.
16001 // \code{.cpp}
16002 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
16003 // auto .reversed.iv = n - .forward.iv - 1;
16004 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
16005 // body(i); // Body
16006 // }
16007 // \endcode
16008
16009 // Subexpressions with more than one use. One of the constraints of an AST is
16010 // that every node object must appear at most once, hence we define a lambda
16011 // that creates a new AST node at every use.
16012 CaptureVars CopyTransformer(SemaRef);
16013 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
16014 return AssertSuccess(
16015 R: CopyTransformer.TransformExpr(E: LoopHelper.NumIterations));
16016 };
16017
16018 // Create the iteration variable for the forward loop (from 0 to n-1).
16019 VarDecl *ForwardIVDecl =
16020 buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: ForwardIVName, Attrs: nullptr, OrigRef: OrigVar);
16021 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
16022 OrigVarLoc]() {
16023 return buildDeclRefExpr(S&: SemaRef, D: ForwardIVDecl, Ty: IVTy, Loc: OrigVarLoc);
16024 };
16025
16026 // Iteration variable for the reversed induction variable (from n-1 downto 0):
16027 // Reuse the iteration variable created by checkOpenMPLoop.
16028 auto *ReversedIVDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
16029 ReversedIVDecl->setDeclName(
16030 &SemaRef.PP.getIdentifierTable().get(Name: ReversedIVName));
16031
16032 // For init-statement:
16033 // \code{.cpp}
16034 // auto .forward.iv = 0;
16035 // \endcode
16036 auto *Zero = IntegerLiteral::Create(C: Context, V: llvm::APInt::getZero(numBits: IVWidth),
16037 type: ForwardIVDecl->getType(), l: OrigVarLoc);
16038 SemaRef.AddInitializerToDecl(dcl: ForwardIVDecl, init: Zero, /*DirectInit=*/false);
16039 StmtResult Init = new (Context)
16040 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
16041 if (!Init.isUsable())
16042 return StmtError();
16043
16044 // Forward iv cond-expression:
16045 // \code{.cpp}
16046 // .forward.iv < MakeNumIterations()
16047 // \endcode
16048 ExprResult Cond =
16049 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
16050 LHSExpr: MakeForwardRef(), RHSExpr: MakeNumIterations());
16051 if (!Cond.isUsable())
16052 return StmtError();
16053
16054 // Forward incr-statement:
16055 // \code{.c}
16056 // ++.forward.iv
16057 // \endcode
16058 ExprResult Incr = SemaRef.BuildUnaryOp(S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(),
16059 Opc: UO_PreInc, Input: MakeForwardRef());
16060 if (!Incr.isUsable())
16061 return StmtError();
16062
16063 // Reverse the forward-iv:
16064 // \code{.cpp}
16065 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
16066 // \endcode
16067 auto *One = IntegerLiteral::Create(C: Context, V: llvm::APInt(IVWidth, 1), type: IVTy,
16068 l: TransformLoc);
16069 ExprResult Minus = SemaRef.BuildBinOp(S: CurScope, OpLoc: TransformLoc, Opc: BO_Sub,
16070 LHSExpr: MakeNumIterations(), RHSExpr: One);
16071 if (!Minus.isUsable())
16072 return StmtError();
16073 Minus = SemaRef.BuildBinOp(S: CurScope, OpLoc: TransformLoc, Opc: BO_Sub, LHSExpr: Minus.get(),
16074 RHSExpr: MakeForwardRef());
16075 if (!Minus.isUsable())
16076 return StmtError();
16077 StmtResult InitReversed = new (Context) DeclStmt(
16078 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
16079 if (!InitReversed.isUsable())
16080 return StmtError();
16081 SemaRef.AddInitializerToDecl(dcl: ReversedIVDecl, init: Minus.get(),
16082 /*DirectInit=*/false);
16083
16084 // The new loop body.
16085 SmallVector<Stmt *, 4> BodyStmts;
16086 BodyStmts.reserve(N: LoopHelper.Updates.size() + 2 +
16087 (isa<CXXForRangeStmt>(Val: LoopStmt) ? 1 : 0));
16088 BodyStmts.push_back(Elt: InitReversed.get());
16089 llvm::append_range(C&: BodyStmts, R&: LoopHelper.Updates);
16090 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
16091 BodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
16092 BodyStmts.push_back(Elt: Body);
16093 auto *ReversedBody =
16094 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
16095 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
16096
16097 // Finally create the reversed For-statement.
16098 auto *ReversedFor = new (Context)
16099 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
16100 ReversedBody, LoopHelper.Init->getBeginLoc(),
16101 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16102 return OMPReverseDirective::Create(C: Context, StartLoc, EndLoc, AssociatedStmt: AStmt, NumLoops,
16103 TransformedStmt: ReversedFor,
16104 PreInits: buildPreInits(Context, PreInits));
16105}
16106
16107/// Build the AST for \#pragma omp split counts(c1, c2, ...).
16108///
16109/// Splits the single associated loop into N consecutive loops, where N is the
16110/// number of count expressions.
16111StmtResult SemaOpenMP::ActOnOpenMPSplitDirective(ArrayRef<OMPClause *> Clauses,
16112 Stmt *AStmt,
16113 SourceLocation StartLoc,
16114 SourceLocation EndLoc) {
16115 ASTContext &Context = getASTContext();
16116 Scope *CurScope = SemaRef.getCurScope();
16117
16118 // Empty statement should only be possible if there already was an error.
16119 if (!AStmt)
16120 return StmtError();
16121
16122 const auto *CountsClause =
16123 OMPExecutableDirective::getSingleClause<OMPCountsClause>(Clauses);
16124 if (!CountsClause)
16125 return StmtError();
16126
16127 // Split applies to a single loop; check it is transformable and get helpers.
16128 constexpr unsigned NumLoops = 1;
16129 Stmt *Body = nullptr;
16130 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
16131 NumLoops);
16132 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
16133 if (!checkTransformableLoopNest(Kind: OMPD_split, AStmt, NumLoops, LoopHelpers,
16134 Body, OriginalInits))
16135 return StmtError();
16136
16137 // Delay applying the transformation to when template is completely
16138 // instantiated.
16139 if (SemaRef.CurContext->isDependentContext())
16140 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16141 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16142
16143 assert(LoopHelpers.size() == NumLoops &&
16144 "Expecting a single-dimensional loop iteration space");
16145 assert(OriginalInits.size() == NumLoops &&
16146 "Expecting a single-dimensional loop iteration space");
16147 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
16148
16149 // Find the loop statement.
16150 Stmt *LoopStmt = nullptr;
16151 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
16152
16153 // Determine the PreInit declarations.
16154 SmallVector<Stmt *> PreInits;
16155 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
16156
16157 // Type and name of the original loop variable; we create one IV per segment
16158 // and assign it to the original var so the body sees the same name.
16159 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
16160 QualType IVTy = IterationVarRef->getType();
16161 uint64_t IVWidth = Context.getTypeSize(T: IVTy);
16162 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
16163
16164 // Iteration variable SourceLocations.
16165 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
16166 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
16167 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
16168 // Internal variable names.
16169 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
16170
16171 if (!CountsClause->hasOmpFill())
16172 return StmtError();
16173 unsigned FillIdx = *CountsClause->getOmpFillIndex();
16174
16175 unsigned NumItems = CountsClause->getNumCounts();
16176 SmallVector<uint64_t, 4> CountValues(NumItems, 0);
16177 ArrayRef<Expr *> Refs = CountsClause->getCountsRefs();
16178 for (unsigned I = 0; I < NumItems; ++I) {
16179 if (I == FillIdx)
16180 continue;
16181 Expr *CountExpr = Refs[I];
16182 if (!CountExpr)
16183 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16184 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16185 std::optional<llvm::APSInt> OptVal =
16186 CountExpr->getIntegerConstantExpr(Ctx: Context);
16187 if (!OptVal || OptVal->isNegative())
16188 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16189 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16190 CountValues[I] = OptVal->getZExtValue();
16191 }
16192
16193 Expr *NumIterExpr = LoopHelper.NumIterations;
16194
16195 uint64_t RightSum = 0;
16196 for (unsigned I = FillIdx + 1; I < NumItems; ++I)
16197 RightSum += CountValues[I];
16198
16199 auto MakeIntLit = [&](uint64_t Val) {
16200 return IntegerLiteral::Create(C: Context, V: llvm::APInt(IVWidth, Val), type: IVTy,
16201 l: OrigVarLoc);
16202 };
16203
16204 size_t NumSegments = NumItems;
16205 SmallVector<Stmt *, 4> SplitLoops;
16206
16207 auto *IterVarDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
16208 SplitLoops.push_back(Elt: new (Context) DeclStmt(DeclGroupRef(IterVarDecl),
16209 IterationVarRef->getBeginLoc(),
16210 IterationVarRef->getEndLoc()));
16211
16212 uint64_t LeftAccum = 0;
16213 uint64_t RightRemaining = RightSum;
16214
16215 for (size_t Seg = 0; Seg < NumSegments; ++Seg) {
16216 Expr *StartExpr = nullptr;
16217 Expr *EndExpr = nullptr;
16218
16219 if (Seg < FillIdx) {
16220 StartExpr = MakeIntLit(LeftAccum);
16221 LeftAccum += CountValues[Seg];
16222 EndExpr = MakeIntLit(LeftAccum);
16223 } else if (Seg == FillIdx) {
16224 StartExpr = MakeIntLit(LeftAccum);
16225 if (RightRemaining == 0) {
16226 EndExpr = NumIterExpr;
16227 } else {
16228 ExprResult Sub =
16229 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16230 RHSExpr: MakeIntLit(RightRemaining));
16231 if (!Sub.isUsable())
16232 return StmtError();
16233 EndExpr = Sub.get();
16234 }
16235 } else {
16236 if (RightRemaining == RightSum) {
16237 if (RightSum == 0)
16238 StartExpr = NumIterExpr;
16239 else {
16240 ExprResult Sub =
16241 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16242 RHSExpr: MakeIntLit(RightRemaining));
16243 if (!Sub.isUsable())
16244 return StmtError();
16245 StartExpr = Sub.get();
16246 }
16247 } else {
16248 ExprResult Sub =
16249 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16250 RHSExpr: MakeIntLit(RightRemaining));
16251 if (!Sub.isUsable())
16252 return StmtError();
16253 StartExpr = Sub.get();
16254 }
16255 RightRemaining -= CountValues[Seg];
16256 if (RightRemaining == 0)
16257 EndExpr = NumIterExpr;
16258 else {
16259 ExprResult Sub =
16260 SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Sub, LHSExpr: NumIterExpr,
16261 RHSExpr: MakeIntLit(RightRemaining));
16262 if (!Sub.isUsable())
16263 return StmtError();
16264 EndExpr = Sub.get();
16265 }
16266 }
16267
16268 SmallString<64> IVName(".split.iv.");
16269 IVName += (Twine(Seg) + "." + OrigVarName).str();
16270 VarDecl *IVDecl = buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: IVName, Attrs: nullptr, OrigRef: OrigVar);
16271 auto MakeIVRef = [&SemaRef = this->SemaRef, IVDecl, IVTy, OrigVarLoc]() {
16272 return buildDeclRefExpr(S&: SemaRef, D: IVDecl, Ty: IVTy, Loc: OrigVarLoc);
16273 };
16274
16275 SemaRef.AddInitializerToDecl(dcl: IVDecl, init: StartExpr, /*DirectInit=*/false);
16276 StmtResult InitStmt = new (Context)
16277 DeclStmt(DeclGroupRef(IVDecl), OrigVarLocBegin, OrigVarLocEnd);
16278 if (!InitStmt.isUsable())
16279 return StmtError();
16280
16281 ExprResult CondExpr = SemaRef.BuildBinOp(
16282 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT, LHSExpr: MakeIVRef(), RHSExpr: EndExpr);
16283 if (!CondExpr.isUsable())
16284 return StmtError();
16285
16286 ExprResult IncrExpr = SemaRef.BuildUnaryOp(
16287 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeIVRef());
16288 if (!IncrExpr.isUsable())
16289 return StmtError();
16290
16291 ExprResult IVAssign = SemaRef.BuildBinOp(S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Assign,
16292 LHSExpr: IterationVarRef, RHSExpr: MakeIVRef());
16293 if (!IVAssign.isUsable())
16294 return StmtError();
16295
16296 SmallVector<Stmt *, 4> BodyStmts;
16297 BodyStmts.push_back(Elt: IVAssign.get());
16298 BodyStmts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
16299 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt)) {
16300 if (Seg == 0) {
16301 BodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
16302 } else {
16303 VarDecl *LoopVar = CXXRangeFor->getLoopVariable();
16304 DeclRefExpr *LVRef = buildDeclRefExpr(
16305 S&: SemaRef, D: LoopVar, Ty: LoopVar->getType().getNonReferenceType(),
16306 Loc: OrigVarLoc);
16307 ExprResult LVAssign = SemaRef.BuildBinOp(
16308 S: CurScope, OpLoc: OrigVarLoc, Opc: BO_Assign, LHSExpr: LVRef, RHSExpr: LoopVar->getInit());
16309 if (!LVAssign.isUsable())
16310 return StmtError();
16311 BodyStmts.push_back(Elt: LVAssign.get());
16312 }
16313 }
16314 BodyStmts.push_back(Elt: Body);
16315
16316 auto *LoopBody =
16317 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
16318 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
16319
16320 auto *For = new (Context)
16321 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
16322 IncrExpr.get(), LoopBody, LoopHelper.Init->getBeginLoc(),
16323 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16324 SplitLoops.push_back(Elt: For);
16325 }
16326
16327 auto *SplitStmt = CompoundStmt::Create(
16328 C: Context, Stmts: SplitLoops, FPFeatures: FPOptionsOverride(),
16329 LB: SplitLoops.front()->getBeginLoc(), RB: SplitLoops.back()->getEndLoc());
16330
16331 return OMPSplitDirective::Create(C: Context, StartLoc, EndLoc, Clauses, NumLoops,
16332 AssociatedStmt: AStmt, TransformedStmt: SplitStmt,
16333 PreInits: buildPreInits(Context, PreInits));
16334}
16335
16336StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
16337 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
16338 SourceLocation EndLoc) {
16339 ASTContext &Context = getASTContext();
16340 DeclContext *CurContext = SemaRef.CurContext;
16341 Scope *CurScope = SemaRef.getCurScope();
16342
16343 // Empty statement should only be possible if there already was an error.
16344 if (!AStmt)
16345 return StmtError();
16346
16347 // interchange without permutation clause swaps two loops.
16348 const OMPPermutationClause *PermutationClause =
16349 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
16350 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
16351
16352 // Verify and diagnose loop nest.
16353 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
16354 Stmt *Body = nullptr;
16355 SmallVector<SmallVector<Stmt *>, 2> OriginalInits;
16356 if (!checkTransformableLoopNest(Kind: OMPD_interchange, AStmt, NumLoops,
16357 LoopHelpers, Body, OriginalInits))
16358 return StmtError();
16359
16360 // Delay interchange to when template is completely instantiated.
16361 if (CurContext->isDependentContext())
16362 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16363 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16364
16365 // An invalid expression in the permutation clause is set to nullptr in
16366 // ActOnOpenMPPermutationClause.
16367 if (PermutationClause &&
16368 llvm::is_contained(Range: PermutationClause->getArgsRefs(), Element: nullptr))
16369 return StmtError();
16370
16371 assert(LoopHelpers.size() == NumLoops &&
16372 "Expecting loop iteration space dimensionaly to match number of "
16373 "affected loops");
16374 assert(OriginalInits.size() == NumLoops &&
16375 "Expecting loop iteration space dimensionaly to match number of "
16376 "affected loops");
16377
16378 // Decode the permutation clause.
16379 SmallVector<uint64_t, 2> Permutation;
16380 if (!PermutationClause) {
16381 Permutation = {1, 0};
16382 } else {
16383 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
16384 llvm::BitVector Flags(PermArgs.size());
16385 for (Expr *PermArg : PermArgs) {
16386 std::optional<llvm::APSInt> PermCstExpr =
16387 PermArg->getIntegerConstantExpr(Ctx: Context);
16388 if (!PermCstExpr)
16389 continue;
16390 uint64_t PermInt = PermCstExpr->getZExtValue();
16391 assert(1 <= PermInt && PermInt <= NumLoops &&
16392 "Must be a permutation; diagnostic emitted in "
16393 "ActOnOpenMPPermutationClause");
16394 if (Flags[PermInt - 1]) {
16395 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
16396 Diag(Loc: PermArg->getExprLoc(),
16397 DiagID: diag::err_omp_interchange_permutation_value_repeated)
16398 << PermInt << ExprRange;
16399 continue;
16400 }
16401 Flags[PermInt - 1] = true;
16402
16403 Permutation.push_back(Elt: PermInt - 1);
16404 }
16405
16406 if (Permutation.size() != NumLoops)
16407 return StmtError();
16408 }
16409
16410 // Nothing to transform with trivial permutation.
16411 if (NumLoops <= 1 || llvm::all_of(Range: llvm::enumerate(First&: Permutation), P: [](auto P) {
16412 auto [Idx, Arg] = P;
16413 return Idx == Arg;
16414 }))
16415 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16416 NumLoops, AssociatedStmt: AStmt, TransformedStmt: AStmt, PreInits: nullptr);
16417
16418 // Find the affected loops.
16419 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
16420 collectLoopStmts(AStmt, LoopStmts);
16421
16422 // Collect pre-init statements on the order before the permuation.
16423 SmallVector<Stmt *> PreInits;
16424 for (auto I : llvm::seq<int>(Size: NumLoops)) {
16425 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16426
16427 assert(LoopHelper.Counters.size() == 1 &&
16428 "Single-dimensional loop iteration space expected");
16429
16430 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
16431 PreInits);
16432 }
16433
16434 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
16435 CaptureVars CopyTransformer(SemaRef);
16436
16437 // Create the permuted loops from the inside to the outside of the
16438 // interchanged loop nest. Body of the innermost new loop is the original
16439 // innermost body.
16440 Stmt *Inner = Body;
16441 for (auto TargetIdx : llvm::reverse(C: llvm::seq<int>(Size: NumLoops))) {
16442 // Get the original loop that belongs to this new position.
16443 uint64_t SourceIdx = Permutation[TargetIdx];
16444 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
16445 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
16446 assert(SourceHelper.Counters.size() == 1 &&
16447 "Single-dimensional loop iteration space expected");
16448 auto *OrigCntVar = cast<DeclRefExpr>(Val: SourceHelper.Counters.front());
16449
16450 // Normalized loop counter variable: From 0 to n-1, always an integer type.
16451 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: SourceHelper.IterationVarRef);
16452 QualType IVTy = IterVarRef->getType();
16453 assert(IVTy->isIntegerType() &&
16454 "Expected the logical iteration counter to be an integer");
16455
16456 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
16457 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
16458
16459 // Make a copy of the NumIterations expression for each use: By the AST
16460 // constraints, every expression object in a DeclContext must be unique.
16461 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
16462 return AssertSuccess(
16463 R: CopyTransformer.TransformExpr(E: SourceHelper.NumIterations));
16464 };
16465
16466 // Iteration variable for the permuted loop. Reuse the one from
16467 // checkOpenMPLoop which will also be used to update the original loop
16468 // variable.
16469 SmallString<64> PermutedCntName(".permuted_");
16470 PermutedCntName.append(Refs: {llvm::utostr(X: TargetIdx), ".iv.", OrigVarName});
16471 auto *PermutedCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
16472 PermutedCntDecl->setDeclName(
16473 &SemaRef.PP.getIdentifierTable().get(Name: PermutedCntName));
16474 PermutedIndVars[TargetIdx] = PermutedCntDecl;
16475 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
16476 return buildDeclRefExpr(S&: SemaRef, D: PermutedCntDecl, Ty: IVTy, Loc: OrigVarLoc);
16477 };
16478
16479 // For init-statement:
16480 // \code
16481 // auto .permuted_{target}.iv = 0
16482 // \endcode
16483 ExprResult Zero = SemaRef.ActOnIntegerConstant(Loc: OrigVarLoc, Val: 0);
16484 if (!Zero.isUsable())
16485 return StmtError();
16486 SemaRef.AddInitializerToDecl(dcl: PermutedCntDecl, init: Zero.get(),
16487 /*DirectInit=*/false);
16488 StmtResult InitStmt = new (Context)
16489 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
16490 OrigCntVar->getEndLoc());
16491 if (!InitStmt.isUsable())
16492 return StmtError();
16493
16494 // For cond-expression:
16495 // \code
16496 // .permuted_{target}.iv < MakeNumIterations()
16497 // \endcode
16498 ExprResult CondExpr =
16499 SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceHelper.Cond->getExprLoc(), Opc: BO_LT,
16500 LHSExpr: MakePermutedRef(), RHSExpr: MakeNumIterations());
16501 if (!CondExpr.isUsable())
16502 return StmtError();
16503
16504 // For incr-statement:
16505 // \code
16506 // ++.tile.iv
16507 // \endcode
16508 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
16509 S: CurScope, OpLoc: SourceHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakePermutedRef());
16510 if (!IncrStmt.isUsable())
16511 return StmtError();
16512
16513 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
16514 SourceHelper.Updates.end());
16515 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: SourceLoopStmt))
16516 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
16517 BodyParts.push_back(Elt: Inner);
16518 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
16519 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
16520 Inner = new (Context) ForStmt(
16521 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
16522 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
16523 SourceHelper.Inc->getEndLoc());
16524 }
16525
16526 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16527 NumLoops, AssociatedStmt: AStmt, TransformedStmt: Inner,
16528 PreInits: buildPreInits(Context, PreInits));
16529}
16530
16531StmtResult SemaOpenMP::ActOnOpenMPFuseDirective(ArrayRef<OMPClause *> Clauses,
16532 Stmt *AStmt,
16533 SourceLocation StartLoc,
16534 SourceLocation EndLoc) {
16535
16536 ASTContext &Context = getASTContext();
16537 DeclContext *CurrContext = SemaRef.CurContext;
16538 Scope *CurScope = SemaRef.getCurScope();
16539 CaptureVars CopyTransformer(SemaRef);
16540
16541 // Ensure the structured block is not empty
16542 if (!AStmt)
16543 return StmtError();
16544
16545 // Defer transformation in dependent contexts
16546 // The NumLoopNests argument is set to a placeholder 1 (even though
16547 // using looprange fuse could yield up to 3 top level loop nests)
16548 // because a dependent context could prevent determining its true value
16549 if (CurrContext->isDependentContext())
16550 return OMPFuseDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
16551 /* NumLoops */ NumGeneratedTopLevelLoops: 1, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
16552
16553 // Validate that the potential loop sequence is transformable for fusion
16554 // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops
16555 LoopSequenceAnalysis SeqAnalysis;
16556 if (!checkTransformableLoopSequence(Kind: OMPD_fuse, AStmt, SeqAnalysis, Context))
16557 return StmtError();
16558
16559 // SeqAnalysis.LoopSeqSize exists mostly to handle dependent contexts,
16560 // otherwise it must be the same as SeqAnalysis.Loops.size().
16561 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16562 "Inconsistent size of the loop sequence and the number of loops "
16563 "found in the sequence");
16564
16565 // Handle clauses, which can be any of the following: [looprange, apply]
16566 const auto *LRC =
16567 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16568
16569 // The clause arguments are invalidated if any error arises
16570 // such as non-constant or non-positive arguments
16571 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16572 return StmtError();
16573
16574 // Delayed semantic check of LoopRange constraint
16575 // Evaluates the loop range arguments and returns the first and count values
16576 auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count,
16577 uint64_t &FirstVal,
16578 uint64_t &CountVal) {
16579 llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Ctx: Context);
16580 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Ctx: Context);
16581 FirstVal = FirstInt.getZExtValue();
16582 CountVal = CountInt.getZExtValue();
16583 };
16584
16585 // OpenMP [6.0, Restrictions]
16586 // first + count - 1 must not evaluate to a value greater than the
16587 // loop sequence length of the associated canonical loop sequence.
16588 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16589 unsigned NumLoops) -> bool {
16590 return FirstVal + CountVal - 1 <= NumLoops;
16591 };
16592 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16593
16594 // Validates the loop range after evaluating the semantic information
16595 // and ensures that the range is valid for the given loop sequence size.
16596 // Expressions are evaluated at compile time to obtain constant values.
16597 if (LRC) {
16598 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16599 CountVal);
16600 if (CountVal == 1)
16601 SemaRef.Diag(Loc: LRC->getCountLoc(), DiagID: diag::warn_omp_redundant_fusion)
16602 << getOpenMPDirectiveName(D: OMPD_fuse);
16603
16604 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16605 SemaRef.Diag(Loc: LRC->getFirstLoc(), DiagID: diag::err_omp_invalid_looprange)
16606 << getOpenMPDirectiveName(D: OMPD_fuse) << FirstVal
16607 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16608 return StmtError();
16609 }
16610
16611 LastVal = FirstVal + CountVal - 1;
16612 }
16613
16614 // Complete fusion generates a single canonical loop nest
16615 // However looprange clause may generate several loop nests
16616 unsigned NumGeneratedTopLevelLoops =
16617 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16618
16619 // Emit a warning for redundant loop fusion when the sequence contains only
16620 // one loop.
16621 if (SeqAnalysis.LoopSeqSize == 1)
16622 SemaRef.Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::warn_omp_redundant_fusion)
16623 << getOpenMPDirectiveName(D: OMPD_fuse);
16624
16625 // Select the type with the largest bit width among all induction variables
16626 QualType IVType =
16627 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16628 for (unsigned I : llvm::seq<unsigned>(Begin: FirstVal, End: LastVal)) {
16629 QualType CurrentIVType =
16630 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16631 if (Context.getTypeSize(T: CurrentIVType) > Context.getTypeSize(T: IVType)) {
16632 IVType = CurrentIVType;
16633 }
16634 }
16635 uint64_t IVBitWidth = Context.getIntWidth(T: IVType);
16636
16637 // Create pre-init declarations for all loops lower bounds, upper bounds,
16638 // strides and num-iterations for every top level loop in the fusion
16639 SmallVector<VarDecl *, 4> LBVarDecls;
16640 SmallVector<VarDecl *, 4> STVarDecls;
16641 SmallVector<VarDecl *, 4> NIVarDecls;
16642 SmallVector<VarDecl *, 4> UBVarDecls;
16643 SmallVector<VarDecl *, 4> IVVarDecls;
16644
16645 // Helper lambda to create variables for bounds, strides, and other
16646 // expressions. Generates both the variable declaration and the corresponding
16647 // initialization statement.
16648 auto CreateHelperVarAndStmt =
16649 [&, &SemaRef = SemaRef](Expr *ExprToCopy, const std::string &BaseName,
16650 unsigned I, bool NeedsNewVD = false) {
16651 Expr *TransformedExpr =
16652 AssertSuccess(R: CopyTransformer.TransformExpr(E: ExprToCopy));
16653 if (!TransformedExpr)
16654 return std::pair<VarDecl *, StmtResult>(nullptr, StmtError());
16655
16656 auto Name = (Twine(".omp.") + BaseName + std::to_string(val: I)).str();
16657
16658 VarDecl *VD;
16659 if (NeedsNewVD) {
16660 VD = buildVarDecl(SemaRef, Loc: SourceLocation(), Type: IVType, Name);
16661 SemaRef.AddInitializerToDecl(dcl: VD, init: TransformedExpr, DirectInit: false);
16662 } else {
16663 // Create a unique variable name
16664 DeclRefExpr *DRE = cast<DeclRefExpr>(Val: TransformedExpr);
16665 VD = cast<VarDecl>(Val: DRE->getDecl());
16666 VD->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name));
16667 }
16668 // Create the corresponding declaration statement
16669 StmtResult DeclStmt = new (Context) class DeclStmt(
16670 DeclGroupRef(VD), SourceLocation(), SourceLocation());
16671 return std::make_pair(x&: VD, y&: DeclStmt);
16672 };
16673
16674 // PreInits hold a sequence of variable declarations that must be executed
16675 // before the fused loop begins. These include bounds, strides, and other
16676 // helper variables required for the transformation. Other loop transforms
16677 // also contain their own preinits
16678 SmallVector<Stmt *> PreInits;
16679
16680 // Update the general preinits using the preinits generated by loop sequence
16681 // generating loop transformations. These preinits differ slightly from
16682 // single-loop transformation preinits, as they can be detached from a
16683 // specific loop inside multiple generated loop nests. This happens
16684 // because certain helper variables, like '.omp.fuse.max', are introduced to
16685 // handle fused iteration spaces and may not be directly tied to a single
16686 // original loop. The preinit structure must ensure that hidden variables
16687 // like '.omp.fuse.max' are still properly handled.
16688 // Transformations that apply this concept: Loopranged Fuse, Split
16689 llvm::append_range(C&: PreInits, R&: SeqAnalysis.LoopSequencePreInits);
16690
16691 // Process each single loop to generate and collect declarations
16692 // and statements for all helper expressions related to
16693 // particular single loop nests
16694
16695 // Also In the case of the fused loops, we keep track of their original
16696 // inits by appending them to their preinits statement, and in the case of
16697 // transformations, also append their preinits (which contain the original
16698 // loop initialization statement or other statements)
16699
16700 // Firstly we need to set TransformIndex to match the begining of the
16701 // looprange section
16702 unsigned int TransformIndex = 0;
16703 for (unsigned I : llvm::seq<unsigned>(Size: FirstVal - 1)) {
16704 if (SeqAnalysis.Loops[I].isLoopTransformation())
16705 ++TransformIndex;
16706 }
16707
16708 for (unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16709 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16710 addLoopPreInits(Context, LoopHelper&: SeqAnalysis.Loops[I].HelperExprs,
16711 LoopStmt: SeqAnalysis.Loops[I].TheForStmt,
16712 OriginalInit: SeqAnalysis.Loops[I].OriginalInits, PreInits);
16713 } else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16714 // For transformed loops, insert both pre-inits and original inits.
16715 // Order matters: pre-inits may define variables used in the original
16716 // inits such as upper bounds...
16717 SmallVector<Stmt *> &TransformPreInit =
16718 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16719 llvm::append_range(C&: PreInits, R&: TransformPreInit);
16720
16721 addLoopPreInits(Context, LoopHelper&: SeqAnalysis.Loops[I].HelperExprs,
16722 LoopStmt: SeqAnalysis.Loops[I].TheForStmt,
16723 OriginalInit: SeqAnalysis.Loops[I].OriginalInits, PreInits);
16724 }
16725 auto [UBVD, UBDStmt] =
16726 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB, "ub", J);
16727 auto [LBVD, LBDStmt] =
16728 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB, "lb", J);
16729 auto [STVD, STDStmt] =
16730 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST, "st", J);
16731 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16732 SeqAnalysis.Loops[I].HelperExprs.NumIterations, "ni", J, true);
16733 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16734 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef, "iv", J);
16735
16736 assert(LBVD && STVD && NIVD && IVVD &&
16737 "OpenMP Fuse Helper variables creation failed");
16738
16739 UBVarDecls.push_back(Elt: UBVD);
16740 LBVarDecls.push_back(Elt: LBVD);
16741 STVarDecls.push_back(Elt: STVD);
16742 NIVarDecls.push_back(Elt: NIVD);
16743 IVVarDecls.push_back(Elt: IVVD);
16744
16745 PreInits.push_back(Elt: LBDStmt.get());
16746 PreInits.push_back(Elt: STDStmt.get());
16747 PreInits.push_back(Elt: NIDStmt.get());
16748 PreInits.push_back(Elt: IVDStmt.get());
16749 }
16750
16751 auto MakeVarDeclRef = [&SemaRef = this->SemaRef](VarDecl *VD) {
16752 return buildDeclRefExpr(S&: SemaRef, D: VD, Ty: VD->getType(), Loc: VD->getLocation(),
16753 RefersToCapture: false);
16754 };
16755
16756 // Following up the creation of the final fused loop will be performed
16757 // which has the following shape (considering the selected loops):
16758 //
16759 // for (fuse.index = 0; fuse.index < max(ni0, ni1..., nik); ++fuse.index) {
16760 // if (fuse.index < ni0){
16761 // iv0 = lb0 + st0 * fuse.index;
16762 // original.index0 = iv0
16763 // body(0);
16764 // }
16765 // if (fuse.index < ni1){
16766 // iv1 = lb1 + st1 * fuse.index;
16767 // original.index1 = iv1
16768 // body(1);
16769 // }
16770 //
16771 // ...
16772 //
16773 // if (fuse.index < nik){
16774 // ivk = lbk + stk * fuse.index;
16775 // original.indexk = ivk
16776 // body(k); Expr *InitVal = IntegerLiteral::Create(Context,
16777 // llvm::APInt(IVWidth, 0),
16778 // }
16779
16780 // 1. Create the initialized fuse index
16781 StringRef IndexName = ".omp.fuse.index";
16782 Expr *InitVal = IntegerLiteral::Create(C: Context, V: llvm::APInt(IVBitWidth, 0),
16783 type: IVType, l: SourceLocation());
16784 VarDecl *IndexDecl =
16785 buildVarDecl(SemaRef, Loc: {}, Type: IVType, Name: IndexName, Attrs: nullptr, OrigRef: nullptr);
16786 SemaRef.AddInitializerToDecl(dcl: IndexDecl, init: InitVal, DirectInit: false);
16787 StmtResult InitStmt = new (Context)
16788 DeclStmt(DeclGroupRef(IndexDecl), SourceLocation(), SourceLocation());
16789
16790 if (!InitStmt.isUsable())
16791 return StmtError();
16792
16793 auto MakeIVRef = [&SemaRef = this->SemaRef, IndexDecl, IVType,
16794 Loc = InitVal->getExprLoc()]() {
16795 return buildDeclRefExpr(S&: SemaRef, D: IndexDecl, Ty: IVType, Loc, RefersToCapture: false);
16796 };
16797
16798 // 2. Iteratively compute the max number of logical iterations Max(NI_1, NI_2,
16799 // ..., NI_k)
16800 //
16801 // This loop accumulates the maximum value across multiple expressions,
16802 // ensuring each step constructs a unique AST node for correctness. By using
16803 // intermediate temporary variables and conditional operators, we maintain
16804 // distinct nodes and avoid duplicating subtrees, For instance, max(a,b,c):
16805 // omp.temp0 = max(a, b)
16806 // omp.temp1 = max(omp.temp0, c)
16807 // omp.fuse.max = max(omp.temp1, omp.temp0)
16808
16809 ExprResult MaxExpr;
16810 // I is the range of loops in the sequence that we fuse.
16811 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16812 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16813 QualType NITy = NIRef->getType();
16814
16815 if (MaxExpr.isUnset()) {
16816 // Initialize MaxExpr with the first NI expression
16817 MaxExpr = NIRef;
16818 } else {
16819 // Create a new acummulator variable t_i = MaxExpr
16820 std::string TempName = (Twine(".omp.temp.") + Twine(J)).str();
16821 VarDecl *TempDecl =
16822 buildVarDecl(SemaRef, Loc: {}, Type: NITy, Name: TempName, Attrs: nullptr, OrigRef: nullptr);
16823 TempDecl->setInit(MaxExpr.get());
16824 DeclRefExpr *TempRef =
16825 buildDeclRefExpr(S&: SemaRef, D: TempDecl, Ty: NITy, Loc: SourceLocation(), RefersToCapture: false);
16826 DeclRefExpr *TempRef2 =
16827 buildDeclRefExpr(S&: SemaRef, D: TempDecl, Ty: NITy, Loc: SourceLocation(), RefersToCapture: false);
16828 // Add a DeclStmt to PreInits to ensure the variable is declared.
16829 StmtResult TempStmt = new (Context)
16830 DeclStmt(DeclGroupRef(TempDecl), SourceLocation(), SourceLocation());
16831
16832 if (!TempStmt.isUsable())
16833 return StmtError();
16834 PreInits.push_back(Elt: TempStmt.get());
16835
16836 // Build MaxExpr <-(MaxExpr > NIRef ? MaxExpr : NIRef)
16837 ExprResult Comparison =
16838 SemaRef.BuildBinOp(S: nullptr, OpLoc: SourceLocation(), Opc: BO_GT, LHSExpr: TempRef, RHSExpr: NIRef);
16839 // Handle any errors in Comparison creation
16840 if (!Comparison.isUsable())
16841 return StmtError();
16842
16843 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
16844 // Update MaxExpr using a conditional expression to hold the max value
16845 MaxExpr = new (Context) ConditionalOperator(
16846 Comparison.get(), SourceLocation(), TempRef2, SourceLocation(),
16847 NIRef2->getExprStmt(), NITy, VK_LValue, OK_Ordinary);
16848
16849 if (!MaxExpr.isUsable())
16850 return StmtError();
16851 }
16852 }
16853 if (!MaxExpr.isUsable())
16854 return StmtError();
16855
16856 // 3. Declare the max variable
16857 const std::string MaxName = Twine(".omp.fuse.max").str();
16858 VarDecl *MaxDecl =
16859 buildVarDecl(SemaRef, Loc: {}, Type: IVType, Name: MaxName, Attrs: nullptr, OrigRef: nullptr);
16860 MaxDecl->setInit(MaxExpr.get());
16861 DeclRefExpr *MaxRef = buildDeclRefExpr(S&: SemaRef, D: MaxDecl, Ty: IVType, Loc: {}, RefersToCapture: false);
16862 StmtResult MaxStmt = new (Context)
16863 DeclStmt(DeclGroupRef(MaxDecl), SourceLocation(), SourceLocation());
16864
16865 if (MaxStmt.isInvalid())
16866 return StmtError();
16867 PreInits.push_back(Elt: MaxStmt.get());
16868
16869 // 4. Create condition Expr: index < n_max
16870 ExprResult CondExpr = SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_LT,
16871 LHSExpr: MakeIVRef(), RHSExpr: MaxRef);
16872 if (!CondExpr.isUsable())
16873 return StmtError();
16874
16875 // 5. Increment Expr: ++index
16876 ExprResult IncrExpr =
16877 SemaRef.BuildUnaryOp(S: CurScope, OpLoc: SourceLocation(), Opc: UO_PreInc, Input: MakeIVRef());
16878 if (!IncrExpr.isUsable())
16879 return StmtError();
16880
16881 // 6. Build the Fused Loop Body
16882 // The final fused loop iterates over the maximum logical range. Inside the
16883 // loop, each original loop's index is calculated dynamically, and its body
16884 // is executed conditionally.
16885 //
16886 // Each sub-loop's body is guarded by a conditional statement to ensure
16887 // it executes only within its logical iteration range:
16888 //
16889 // if (fuse.index < ni_k){
16890 // iv_k = lb_k + st_k * fuse.index;
16891 // original.index = iv_k
16892 // body(k);
16893 // }
16894
16895 CompoundStmt *FusedBody = nullptr;
16896 SmallVector<Stmt *, 4> FusedBodyStmts;
16897 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16898 // Assingment of the original sub-loop index to compute the logical index
16899 // IV_k = LB_k + omp.fuse.index * ST_k
16900 ExprResult IdxExpr =
16901 SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_Mul,
16902 LHSExpr: MakeVarDeclRef(STVarDecls[J]), RHSExpr: MakeIVRef());
16903 if (!IdxExpr.isUsable())
16904 return StmtError();
16905 IdxExpr = SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_Add,
16906 LHSExpr: MakeVarDeclRef(LBVarDecls[J]), RHSExpr: IdxExpr.get());
16907
16908 if (!IdxExpr.isUsable())
16909 return StmtError();
16910 IdxExpr = SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_Assign,
16911 LHSExpr: MakeVarDeclRef(IVVarDecls[J]), RHSExpr: IdxExpr.get());
16912 if (!IdxExpr.isUsable())
16913 return StmtError();
16914
16915 // Update the original i_k = IV_k
16916 SmallVector<Stmt *, 4> BodyStmts;
16917 BodyStmts.push_back(Elt: IdxExpr.get());
16918 llvm::append_range(C&: BodyStmts, R&: SeqAnalysis.Loops[I].HelperExprs.Updates);
16919
16920 // If the loop is a CXXForRangeStmt then the iterator variable is needed
16921 if (auto *SourceCXXFor =
16922 dyn_cast<CXXForRangeStmt>(Val: SeqAnalysis.Loops[I].TheForStmt))
16923 BodyStmts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
16924
16925 Stmt *Body =
16926 (isa<ForStmt>(Val: SeqAnalysis.Loops[I].TheForStmt))
16927 ? cast<ForStmt>(Val: SeqAnalysis.Loops[I].TheForStmt)->getBody()
16928 : cast<CXXForRangeStmt>(Val: SeqAnalysis.Loops[I].TheForStmt)->getBody();
16929 BodyStmts.push_back(Elt: Body);
16930
16931 CompoundStmt *CombinedBody =
16932 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
16933 LB: SourceLocation(), RB: SourceLocation());
16934 ExprResult Condition =
16935 SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceLocation(), Opc: BO_LT, LHSExpr: MakeIVRef(),
16936 RHSExpr: MakeVarDeclRef(NIVarDecls[J]));
16937
16938 if (!Condition.isUsable())
16939 return StmtError();
16940
16941 IfStmt *IfStatement = IfStmt::Create(
16942 Ctx: Context, IL: SourceLocation(), Kind: IfStatementKind::Ordinary, Init: nullptr, Var: nullptr,
16943 Cond: Condition.get(), LPL: SourceLocation(), RPL: SourceLocation(), Then: CombinedBody,
16944 EL: SourceLocation(), Else: nullptr);
16945
16946 FusedBodyStmts.push_back(Elt: IfStatement);
16947 }
16948 FusedBody = CompoundStmt::Create(C: Context, Stmts: FusedBodyStmts, FPFeatures: FPOptionsOverride(),
16949 LB: SourceLocation(), RB: SourceLocation());
16950
16951 // 7. Construct the final fused loop
16952 ForStmt *FusedForStmt = new (Context)
16953 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, IncrExpr.get(),
16954 FusedBody, InitStmt.get()->getBeginLoc(), SourceLocation(),
16955 IncrExpr.get()->getEndLoc());
16956
16957 // In the case of looprange, the result of fuse won't simply
16958 // be a single loop (ForStmt), but rather a loop sequence
16959 // (CompoundStmt) of 3 parts: the pre-fusion loops, the fused loop
16960 // and the post-fusion loops, preserving its original order.
16961 //
16962 // Note: If looprange clause produces a single fused loop nest then
16963 // this compound statement wrapper is unnecessary (Therefore this
16964 // treatment is skipped)
16965
16966 Stmt *FusionStmt = FusedForStmt;
16967 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
16968 SmallVector<Stmt *, 4> FinalLoops;
16969
16970 // Reset the transform index
16971 TransformIndex = 0;
16972
16973 // Collect all non-fused loops before and after the fused region.
16974 // Pre-fusion and post-fusion loops are inserted in order exploiting their
16975 // symmetry, along with their corresponding transformation pre-inits if
16976 // needed. The fused loop is added between the two regions.
16977 for (unsigned I : llvm::seq<unsigned>(Size: SeqAnalysis.LoopSeqSize)) {
16978 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
16979 // Update the Transformation counter to skip already treated
16980 // loop transformations
16981 if (!SeqAnalysis.Loops[I].isLoopTransformation())
16982 ++TransformIndex;
16983 continue;
16984 }
16985
16986 // No need to handle:
16987 // Regular loops: they are kept intact as-is.
16988 // Loop-sequence-generating transformations: already handled earlier.
16989 // Only TransformSingleLoop requires inserting pre-inits here
16990 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16991 const auto &TransformPreInit =
16992 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16993 if (!TransformPreInit.empty())
16994 llvm::append_range(C&: PreInits, R: TransformPreInit);
16995 }
16996
16997 FinalLoops.push_back(Elt: SeqAnalysis.Loops[I].TheForStmt);
16998 }
16999
17000 FinalLoops.insert(I: FinalLoops.begin() + (FirstVal - 1), Elt: FusedForStmt);
17001 FusionStmt = CompoundStmt::Create(C: Context, Stmts: FinalLoops, FPFeatures: FPOptionsOverride(),
17002 LB: SourceLocation(), RB: SourceLocation());
17003 }
17004 return OMPFuseDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
17005 NumGeneratedTopLevelLoops, AssociatedStmt: AStmt, TransformedStmt: FusionStmt,
17006 PreInits: buildPreInits(Context, PreInits));
17007}
17008
17009OMPClause *SemaOpenMP::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
17010 Expr *Expr,
17011 SourceLocation StartLoc,
17012 SourceLocation LParenLoc,
17013 SourceLocation EndLoc) {
17014 OMPClause *Res = nullptr;
17015 switch (Kind) {
17016 case OMPC_final:
17017 Res = ActOnOpenMPFinalClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
17018 break;
17019 case OMPC_safelen:
17020 Res = ActOnOpenMPSafelenClause(Length: Expr, StartLoc, LParenLoc, EndLoc);
17021 break;
17022 case OMPC_simdlen:
17023 Res = ActOnOpenMPSimdlenClause(Length: Expr, StartLoc, LParenLoc, EndLoc);
17024 break;
17025 case OMPC_allocator:
17026 Res = ActOnOpenMPAllocatorClause(Allocator: Expr, StartLoc, LParenLoc, EndLoc);
17027 break;
17028 case OMPC_collapse:
17029 Res = ActOnOpenMPCollapseClause(NumForLoops: Expr, StartLoc, LParenLoc, EndLoc);
17030 break;
17031 case OMPC_ordered:
17032 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, NumForLoops: Expr);
17033 break;
17034 case OMPC_nowait:
17035 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc, LParenLoc, Condition: Expr);
17036 break;
17037 case OMPC_priority:
17038 Res = ActOnOpenMPPriorityClause(Priority: Expr, StartLoc, LParenLoc, EndLoc);
17039 break;
17040 case OMPC_hint:
17041 Res = ActOnOpenMPHintClause(Hint: Expr, StartLoc, LParenLoc, EndLoc);
17042 break;
17043 case OMPC_depobj:
17044 Res = ActOnOpenMPDepobjClause(Depobj: Expr, StartLoc, LParenLoc, EndLoc);
17045 break;
17046 case OMPC_detach:
17047 Res = ActOnOpenMPDetachClause(Evt: Expr, StartLoc, LParenLoc, EndLoc);
17048 break;
17049 case OMPC_novariants:
17050 Res = ActOnOpenMPNovariantsClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
17051 break;
17052 case OMPC_nocontext:
17053 Res = ActOnOpenMPNocontextClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
17054 break;
17055 case OMPC_filter:
17056 Res = ActOnOpenMPFilterClause(ThreadID: Expr, StartLoc, LParenLoc, EndLoc);
17057 break;
17058 case OMPC_partial:
17059 Res = ActOnOpenMPPartialClause(FactorExpr: Expr, StartLoc, LParenLoc, EndLoc);
17060 break;
17061 case OMPC_message:
17062 Res = ActOnOpenMPMessageClause(MS: Expr, StartLoc, LParenLoc, EndLoc);
17063 break;
17064 case OMPC_align:
17065 Res = ActOnOpenMPAlignClause(Alignment: Expr, StartLoc, LParenLoc, EndLoc);
17066 break;
17067 case OMPC_ompx_dyn_cgroup_mem:
17068 Res = ActOnOpenMPXDynCGroupMemClause(Size: Expr, StartLoc, LParenLoc, EndLoc);
17069 break;
17070 case OMPC_holds:
17071 Res = ActOnOpenMPHoldsClause(E: Expr, StartLoc, LParenLoc, EndLoc);
17072 break;
17073 case OMPC_transparent:
17074 Res = ActOnOpenMPTransparentClause(Transparent: Expr, StartLoc, LParenLoc, EndLoc);
17075 break;
17076 case OMPC_dyn_groupprivate:
17077 case OMPC_grainsize:
17078 case OMPC_num_tasks:
17079 case OMPC_num_threads:
17080 case OMPC_device:
17081 case OMPC_if:
17082 case OMPC_default:
17083 case OMPC_proc_bind:
17084 case OMPC_schedule:
17085 case OMPC_private:
17086 case OMPC_firstprivate:
17087 case OMPC_lastprivate:
17088 case OMPC_shared:
17089 case OMPC_reduction:
17090 case OMPC_task_reduction:
17091 case OMPC_in_reduction:
17092 case OMPC_linear:
17093 case OMPC_aligned:
17094 case OMPC_copyin:
17095 case OMPC_copyprivate:
17096 case OMPC_untied:
17097 case OMPC_mergeable:
17098 case OMPC_threadprivate:
17099 case OMPC_groupprivate:
17100 case OMPC_sizes:
17101 case OMPC_allocate:
17102 case OMPC_flush:
17103 case OMPC_read:
17104 case OMPC_write:
17105 case OMPC_update:
17106 case OMPC_capture:
17107 case OMPC_compare:
17108 case OMPC_seq_cst:
17109 case OMPC_acq_rel:
17110 case OMPC_acquire:
17111 case OMPC_release:
17112 case OMPC_relaxed:
17113 case OMPC_depend:
17114 case OMPC_threads:
17115 case OMPC_simd:
17116 case OMPC_map:
17117 case OMPC_nogroup:
17118 case OMPC_dist_schedule:
17119 case OMPC_defaultmap:
17120 case OMPC_unknown:
17121 case OMPC_uniform:
17122 case OMPC_to:
17123 case OMPC_from:
17124 case OMPC_use_device_ptr:
17125 case OMPC_use_device_addr:
17126 case OMPC_is_device_ptr:
17127 case OMPC_unified_address:
17128 case OMPC_unified_shared_memory:
17129 case OMPC_reverse_offload:
17130 case OMPC_dynamic_allocators:
17131 case OMPC_atomic_default_mem_order:
17132 case OMPC_self_maps:
17133 case OMPC_device_type:
17134 case OMPC_match:
17135 case OMPC_nontemporal:
17136 case OMPC_order:
17137 case OMPC_at:
17138 case OMPC_severity:
17139 case OMPC_destroy:
17140 case OMPC_inclusive:
17141 case OMPC_exclusive:
17142 case OMPC_uses_allocators:
17143 case OMPC_affinity:
17144 case OMPC_when:
17145 case OMPC_bind:
17146 case OMPC_num_teams:
17147 case OMPC_thread_limit:
17148 default:
17149 llvm_unreachable("Clause is not allowed.");
17150 }
17151 return Res;
17152}
17153
17154// An OpenMP directive such as 'target parallel' has two captured regions:
17155// for the 'target' and 'parallel' respectively. This function returns
17156// the region in which to capture expressions associated with a clause.
17157// A return value of OMPD_unknown signifies that the expression should not
17158// be captured.
17159static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
17160 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
17161 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
17162 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
17163 "Invalid directive with CKind-clause");
17164
17165 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
17166 if (NameModifier != OMPD_unknown &&
17167 !isAllowedClauseForDirective(D: NameModifier, C: CKind, Version: OpenMPVersion))
17168 return OMPD_unknown;
17169
17170 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(D: DKind);
17171
17172 // [5.2:341:24-30]
17173 // If the clauses have expressions on them, such as for various clauses where
17174 // the argument of the clause is an expression, or lower-bound, length, or
17175 // stride expressions inside array sections (or subscript and stride
17176 // expressions in subscript-triplet for Fortran), or linear-step or alignment
17177 // expressions, the expressions are evaluated immediately before the construct
17178 // to which the clause has been split or duplicated per the above rules
17179 // (therefore inside of the outer leaf constructs). However, the expressions
17180 // inside the num_teams and thread_limit clauses are always evaluated before
17181 // the outermost leaf construct.
17182
17183 // Process special cases first.
17184 switch (CKind) {
17185 case OMPC_if:
17186 switch (DKind) {
17187 case OMPD_teams_loop:
17188 case OMPD_target_teams_loop:
17189 // For [target] teams loop, assume capture region is 'teams' so it's
17190 // available for codegen later to use if/when necessary.
17191 return OMPD_teams;
17192 case OMPD_target_update:
17193 case OMPD_target_enter_data:
17194 case OMPD_target_exit_data:
17195 return OMPD_task;
17196 default:
17197 break;
17198 }
17199 break;
17200 case OMPC_num_teams:
17201 case OMPC_thread_limit:
17202 case OMPC_ompx_dyn_cgroup_mem:
17203 case OMPC_dyn_groupprivate:
17204 // TODO: This may need to consider teams too.
17205 if (Leafs[0] == OMPD_target)
17206 return OMPD_target;
17207 break;
17208 case OMPC_device:
17209 if (Leafs[0] == OMPD_target ||
17210 llvm::is_contained(Set: {OMPD_dispatch, OMPD_target_update,
17211 OMPD_target_enter_data, OMPD_target_exit_data},
17212 Element: DKind))
17213 return OMPD_task;
17214 break;
17215 case OMPC_novariants:
17216 case OMPC_nocontext:
17217 if (DKind == OMPD_dispatch)
17218 return OMPD_task;
17219 break;
17220 case OMPC_when:
17221 if (DKind == OMPD_metadirective)
17222 return OMPD_metadirective;
17223 break;
17224 case OMPC_filter:
17225 return OMPD_unknown;
17226 default:
17227 break;
17228 }
17229
17230 // If none of the special cases above applied, and DKind is a capturing
17231 // directive, find the innermost enclosing leaf construct that allows the
17232 // clause, and returns the corresponding capture region.
17233
17234 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
17235 // Find the index in "Leafs" of the last leaf that allows the given
17236 // clause. The search will only include indexes [0, EndIdx).
17237 // EndIdx may be set to the index of the NameModifier, if present.
17238 int InnermostIdx = [&]() {
17239 for (int I = EndIdx - 1; I >= 0; --I) {
17240 if (isAllowedClauseForDirective(D: Leafs[I], C: Clause, Version: OpenMPVersion))
17241 return I;
17242 }
17243 return -1;
17244 }();
17245
17246 // Find the nearest enclosing capture region.
17247 SmallVector<OpenMPDirectiveKind, 2> Regions;
17248 for (int I = InnermostIdx - 1; I >= 0; --I) {
17249 if (!isOpenMPCapturingDirective(DKind: Leafs[I]))
17250 continue;
17251 Regions.clear();
17252 getOpenMPCaptureRegions(CaptureRegions&: Regions, DKind: Leafs[I]);
17253 if (Regions[0] != OMPD_unknown)
17254 return Regions.back();
17255 }
17256 return OMPD_unknown;
17257 };
17258
17259 if (isOpenMPCapturingDirective(DKind)) {
17260 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
17261 for (int I = 0, E = Leafs.size(); I != E; ++I) {
17262 if (Leafs[I] == Dir)
17263 return I + 1;
17264 }
17265 return 0;
17266 };
17267
17268 int End = NameModifier == OMPD_unknown ? Leafs.size()
17269 : GetLeafIndex(NameModifier);
17270 return GetEnclosingRegion(End, CKind);
17271 }
17272
17273 return OMPD_unknown;
17274}
17275
17276OMPClause *SemaOpenMP::ActOnOpenMPIfClause(
17277 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
17278 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
17279 SourceLocation ColonLoc, SourceLocation EndLoc) {
17280 Expr *ValExpr = Condition;
17281 Stmt *HelperValStmt = nullptr;
17282 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17283 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17284 !Condition->isInstantiationDependent() &&
17285 !Condition->containsUnexpandedParameterPack()) {
17286 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
17287 if (Val.isInvalid())
17288 return nullptr;
17289
17290 ValExpr = Val.get();
17291
17292 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17293 CaptureRegion = getOpenMPCaptureRegionForClause(
17294 DKind, CKind: OMPC_if, OpenMPVersion: getLangOpts().OpenMP, NameModifier);
17295 if (CaptureRegion != OMPD_unknown &&
17296 !SemaRef.CurContext->isDependentContext()) {
17297 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17298 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17299 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17300 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
17301 }
17302 }
17303
17304 return new (getASTContext())
17305 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
17306 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
17307}
17308
17309OMPClause *SemaOpenMP::ActOnOpenMPFinalClause(Expr *Condition,
17310 SourceLocation StartLoc,
17311 SourceLocation LParenLoc,
17312 SourceLocation EndLoc) {
17313 Expr *ValExpr = Condition;
17314 Stmt *HelperValStmt = nullptr;
17315 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17316 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17317 !Condition->isInstantiationDependent() &&
17318 !Condition->containsUnexpandedParameterPack()) {
17319 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
17320 if (Val.isInvalid())
17321 return nullptr;
17322
17323 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
17324
17325 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17326 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_final,
17327 OpenMPVersion: getLangOpts().OpenMP);
17328 if (CaptureRegion != OMPD_unknown &&
17329 !SemaRef.CurContext->isDependentContext()) {
17330 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17331 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17332 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17333 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
17334 }
17335 }
17336
17337 return new (getASTContext()) OMPFinalClause(
17338 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17339}
17340
17341ExprResult
17342SemaOpenMP::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
17343 Expr *Op) {
17344 if (!Op)
17345 return ExprError();
17346
17347 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
17348 public:
17349 IntConvertDiagnoser()
17350 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
17351 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
17352 QualType T) override {
17353 return S.Diag(Loc, DiagID: diag::err_omp_not_integral) << T;
17354 }
17355 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
17356 QualType T) override {
17357 return S.Diag(Loc, DiagID: diag::err_omp_incomplete_type) << T;
17358 }
17359 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
17360 QualType T,
17361 QualType ConvTy) override {
17362 return S.Diag(Loc, DiagID: diag::err_omp_explicit_conversion) << T << ConvTy;
17363 }
17364 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
17365 QualType ConvTy) override {
17366 return S.Diag(Loc: Conv->getLocation(), DiagID: diag::note_omp_conversion_here)
17367 << ConvTy->isEnumeralType() << ConvTy;
17368 }
17369 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
17370 QualType T) override {
17371 return S.Diag(Loc, DiagID: diag::err_omp_ambiguous_conversion) << T;
17372 }
17373 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
17374 QualType ConvTy) override {
17375 return S.Diag(Loc: Conv->getLocation(), DiagID: diag::note_omp_conversion_here)
17376 << ConvTy->isEnumeralType() << ConvTy;
17377 }
17378 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
17379 QualType) override {
17380 llvm_unreachable("conversion functions are permitted");
17381 }
17382 } ConvertDiagnoser;
17383 return SemaRef.PerformContextualImplicitConversion(Loc, FromE: Op, Converter&: ConvertDiagnoser);
17384}
17385
17386static bool
17387isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
17388 bool StrictlyPositive, bool BuildCapture = false,
17389 OpenMPDirectiveKind DKind = OMPD_unknown,
17390 OpenMPDirectiveKind *CaptureRegion = nullptr,
17391 Stmt **HelperValStmt = nullptr) {
17392 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
17393 !ValExpr->isInstantiationDependent()) {
17394 SourceLocation Loc = ValExpr->getExprLoc();
17395 ExprResult Value =
17396 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, Op: ValExpr);
17397 if (Value.isInvalid())
17398 return false;
17399
17400 ValExpr = Value.get();
17401 // The expression must evaluate to a non-negative integer value.
17402 if (std::optional<llvm::APSInt> Result =
17403 ValExpr->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
17404 if (Result->isSigned() &&
17405 !((!StrictlyPositive && Result->isNonNegative()) ||
17406 (StrictlyPositive && Result->isStrictlyPositive()))) {
17407 SemaRef.Diag(Loc, DiagID: diag::err_omp_negative_expression_in_clause)
17408 << getOpenMPClauseNameForDiag(C: CKind) << (StrictlyPositive ? 1 : 0)
17409 << ValExpr->getSourceRange();
17410 return false;
17411 }
17412 }
17413 if (!BuildCapture)
17414 return true;
17415 *CaptureRegion =
17416 getOpenMPCaptureRegionForClause(DKind, CKind, OpenMPVersion: SemaRef.LangOpts.OpenMP);
17417 if (*CaptureRegion != OMPD_unknown &&
17418 !SemaRef.CurContext->isDependentContext()) {
17419 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17420 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17421 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17422 *HelperValStmt = buildPreInits(Context&: SemaRef.Context, Captures);
17423 }
17424 }
17425 return true;
17426}
17427
17428static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
17429 unsigned Last,
17430 ArrayRef<unsigned> Exclude = {}) {
17431 SmallString<256> Buffer;
17432 llvm::raw_svector_ostream Out(Buffer);
17433 unsigned Skipped = Exclude.size();
17434 for (unsigned I = First; I < Last; ++I) {
17435 if (llvm::is_contained(Range&: Exclude, Element: I)) {
17436 --Skipped;
17437 continue;
17438 }
17439 Out << "'" << getOpenMPSimpleClauseTypeName(Kind: K, Type: I) << "'";
17440 if (I + Skipped + 2 == Last)
17441 Out << " or ";
17442 else if (I + Skipped + 1 != Last)
17443 Out << ", ";
17444 }
17445 return std::string(Out.str());
17446}
17447
17448OMPClause *SemaOpenMP::ActOnOpenMPNumThreadsClause(
17449 ArrayRef<Expr *> VarList, OpenMPNumThreadsClauseModifier SimpleModifier,
17450 SourceLocation SimpleModifierLoc,
17451 OpenMPNumThreadsClauseModifier ComplexModifier, Expr *ComplexModifierExpr,
17452 SourceLocation ComplexModifierLoc, SourceLocation StartLoc,
17453 SourceLocation LParenLoc, SourceLocation EndLoc) {
17454 // Check that modifiers were correctly specified.
17455 if (ComplexModifierLoc.isValid() &&
17456 (ComplexModifier != OMPC_NUMTHREADS_dims || !ComplexModifierExpr)) {
17457 Diag(Loc: ComplexModifierLoc, DiagID: diag::err_omp_malformed_complex_modifier)
17458 << getOpenMPSimpleClauseTypeName(Kind: OMPC_num_threads, Type: OMPC_NUMTHREADS_dims)
17459 << getOpenMPClauseName(C: OMPC_num_threads);
17460 return nullptr;
17461 }
17462 if (SimpleModifierLoc.isValid() && SimpleModifier == OMPC_NUMTHREADS_dims) {
17463 Diag(Loc: SimpleModifierLoc, DiagID: diag::err_omp_malformed_complex_modifier)
17464 << getOpenMPSimpleClauseTypeName(Kind: OMPC_num_threads, Type: OMPC_NUMTHREADS_dims)
17465 << getOpenMPClauseName(C: OMPC_num_threads);
17466 return nullptr;
17467 }
17468 if (SimpleModifierLoc.isValid() && SimpleModifier != OMPC_NUMTHREADS_strict) {
17469 Diag(Loc: SimpleModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
17470 << getOpenMPSimpleClauseTypeName(Kind: OMPC_num_threads,
17471 Type: OMPC_NUMTHREADS_strict)
17472 << getOpenMPClauseName(C: OMPC_num_threads);
17473 return nullptr;
17474 }
17475
17476 if (VarList.empty())
17477 return nullptr;
17478
17479 SmallVector<Expr *, 3> Vars(VarList.begin(), VarList.end());
17480 for (Expr *&ValExpr : Vars) {
17481 // OpenMP [2.5, Restrictions]
17482 // The num_threads expression must evaluate to a positive integer value.
17483 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_num_threads,
17484 /*StrictlyPositive=*/true))
17485 return nullptr;
17486 }
17487
17488 if (ComplexModifier == OMPC_NUMTHREADS_dims) {
17489 ExprResult Res = ActOnOpenMPDimsModifier(Kind: OMPC_num_threads, Modifier: ComplexModifier,
17490 ModifierExpr: ComplexModifierExpr,
17491 ModifierLoc: ComplexModifierLoc, VarList: Vars, VarListEndLoc: EndLoc);
17492 if (Res.isInvalid())
17493 return nullptr;
17494 ComplexModifierExpr = Res.get();
17495
17496 if (validateMultidimClauseExprs(SemaRef&: *this, ClauseKind: OMPC_num_threads, ClauseBeginLoc: StartLoc, ClauseVarList: Vars,
17497 DimsModifierExpr: ComplexModifierExpr))
17498 return nullptr;
17499 }
17500 if (SimpleModifier == OMPC_NUMTHREADS_strict && getLangOpts().OpenMP < 60) {
17501 Diag(Loc: SimpleModifierLoc, DiagID: diag::err_omp_modifier_requires_version)
17502 << getOpenMPSimpleClauseTypeName(Kind: OMPC_num_threads, Type: SimpleModifier)
17503 << getOpenMPClauseName(C: OMPC_num_threads) << "6.0";
17504 return nullptr;
17505 }
17506
17507 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17508 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
17509 DKind, CKind: OMPC_num_threads, OpenMPVersion: getLangOpts().OpenMP);
17510 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
17511 return OMPNumThreadsClause::Create(
17512 C: getASTContext(), CaptureRegion, StartLoc, LParenLoc, EndLoc, VL: Vars,
17513 PrescriptivenessModifier: SimpleModifier, DimsModifier: ComplexModifier, PrescriptivenessModifierLoc: SimpleModifierLoc, DimsModifierLoc: ComplexModifierLoc,
17514 DimsModifierExpr: ComplexModifierExpr, /*PreInit=*/nullptr);
17515
17516 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17517 for (Expr *&ValExpr : Vars) {
17518 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17519 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17520 }
17521 if (ComplexModifierExpr) {
17522 ComplexModifierExpr = SemaRef.MakeFullExpr(Arg: ComplexModifierExpr).get();
17523 ComplexModifierExpr =
17524 tryBuildCapture(SemaRef, Capture: ComplexModifierExpr, Captures).get();
17525 }
17526 Stmt *PreInit = buildPreInits(Context&: getASTContext(), Captures);
17527
17528 return OMPNumThreadsClause::Create(
17529 C: getASTContext(), CaptureRegion, StartLoc, LParenLoc, EndLoc, VL: Vars,
17530 PrescriptivenessModifier: SimpleModifier, DimsModifier: ComplexModifier, PrescriptivenessModifierLoc: SimpleModifierLoc, DimsModifierLoc: ComplexModifierLoc,
17531 DimsModifierExpr: ComplexModifierExpr, PreInit);
17532}
17533
17534ExprResult SemaOpenMP::VerifyPositiveIntegerConstantInClause(
17535 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
17536 bool SuppressExprDiags) {
17537 if (!E)
17538 return ExprError();
17539 if (E->isValueDependent() || E->isTypeDependent() ||
17540 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
17541 return E;
17542
17543 llvm::APSInt Result;
17544 ExprResult ICE;
17545 if (SuppressExprDiags) {
17546 // Use a custom diagnoser that suppresses 'note' diagnostics about the
17547 // expression.
17548 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
17549 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
17550 SemaBase::SemaDiagnosticBuilder
17551 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
17552 llvm_unreachable("Diagnostic suppressed");
17553 }
17554 } Diagnoser;
17555 ICE = SemaRef.VerifyIntegerConstantExpression(E, Result: &Result, Diagnoser,
17556 CanFold: AllowFoldKind::Allow);
17557 } else {
17558 ICE =
17559 SemaRef.VerifyIntegerConstantExpression(E, Result: &Result,
17560 /*FIXME*/ CanFold: AllowFoldKind::Allow);
17561 }
17562 if (ICE.isInvalid())
17563 return ExprError();
17564
17565 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
17566 (!StrictlyPositive && !Result.isNonNegative())) {
17567 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_negative_expression_in_clause)
17568 << getOpenMPClauseNameForDiag(C: CKind) << (StrictlyPositive ? 1 : 0)
17569 << E->getSourceRange();
17570 return ExprError();
17571 }
17572 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
17573 CKind == OMPC_allocate) &&
17574 !Result.isPowerOf2()) {
17575 Diag(Loc: E->getExprLoc(), DiagID: diag::warn_omp_alignment_not_power_of_two)
17576 << E->getSourceRange();
17577 return ExprError();
17578 }
17579
17580 if (!Result.isRepresentableByInt64()) {
17581 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_large_expression_in_clause)
17582 << getOpenMPClauseNameForDiag(C: CKind) << E->getSourceRange();
17583 return ExprError();
17584 }
17585
17586 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
17587 DSAStack->setAssociatedLoops(Result.getExtValue());
17588 else if (CKind == OMPC_ordered)
17589 DSAStack->setAssociatedLoops(Result.getExtValue());
17590 return ICE;
17591}
17592
17593void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
17594
17595void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
17596
17597int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
17598
17599void SemaOpenMP::ActOnOpenMPDeviceNum(Expr *DeviceNumExpr) {
17600 llvm::APSInt Result;
17601 Expr::EvalResult EvalResult;
17602 // Evaluate the expression to an integer value
17603 if (!DeviceNumExpr->isValueDependent() &&
17604 DeviceNumExpr->EvaluateAsInt(Result&: EvalResult, Ctx: SemaRef.Context)) {
17605 // The device expression must evaluate to a non-negative integer value.
17606 Result = EvalResult.Val.getInt();
17607 if (Result.isNonNegative()) {
17608 setOpenMPDeviceNum(Result.getZExtValue());
17609 } else {
17610 Diag(Loc: DeviceNumExpr->getExprLoc(),
17611 DiagID: diag::err_omp_negative_expression_in_clause)
17612 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
17613 }
17614 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(Val: DeviceNumExpr)) {
17615 // Check if the expression is an identifier
17616 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
17617 if (IdInfo) {
17618 setOpenMPDeviceNumID(IdInfo->getName());
17619 }
17620 } else {
17621 Diag(Loc: DeviceNumExpr->getExprLoc(), DiagID: diag::err_expected_expression);
17622 }
17623}
17624
17625OMPClause *SemaOpenMP::ActOnOpenMPSafelenClause(Expr *Len,
17626 SourceLocation StartLoc,
17627 SourceLocation LParenLoc,
17628 SourceLocation EndLoc) {
17629 // OpenMP [2.8.1, simd construct, Description]
17630 // The parameter of the safelen clause must be a constant
17631 // positive integer expression.
17632 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(E: Len, CKind: OMPC_safelen);
17633 if (Safelen.isInvalid())
17634 return nullptr;
17635 return new (getASTContext())
17636 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
17637}
17638
17639OMPClause *SemaOpenMP::ActOnOpenMPSimdlenClause(Expr *Len,
17640 SourceLocation StartLoc,
17641 SourceLocation LParenLoc,
17642 SourceLocation EndLoc) {
17643 // OpenMP [2.8.1, simd construct, Description]
17644 // The parameter of the simdlen clause must be a constant
17645 // positive integer expression.
17646 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(E: Len, CKind: OMPC_simdlen);
17647 if (Simdlen.isInvalid())
17648 return nullptr;
17649 return new (getASTContext())
17650 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
17651}
17652
17653/// Tries to find omp_allocator_handle_t type.
17654static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
17655 DSAStackTy *Stack) {
17656 if (!Stack->getOMPAllocatorHandleT().isNull())
17657 return true;
17658
17659 // Set the allocator handle type.
17660 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_allocator_handle_t");
17661 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
17662 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
17663 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found)
17664 << "omp_allocator_handle_t";
17665 return false;
17666 }
17667 QualType AllocatorHandleEnumTy = PT.get();
17668 AllocatorHandleEnumTy.addConst();
17669
17670 // Fill the predefined allocator map.
17671 bool ErrorFound = false;
17672 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17673 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
17674 StringRef Allocator =
17675 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(Val: AllocatorKind);
17676 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Name: Allocator);
17677 auto *VD = dyn_cast_or_null<ValueDecl>(
17678 Val: S.LookupSingleName(S: S.TUScope, Name: AllocatorName, Loc, NameKind: Sema::LookupAnyName));
17679 if (!VD) {
17680 ErrorFound = true;
17681 break;
17682 }
17683 QualType AllocatorType =
17684 VD->getType().getNonLValueExprType(Context: S.getASTContext());
17685 ExprResult Res = S.BuildDeclRefExpr(D: VD, Ty: AllocatorType, VK: VK_LValue, Loc);
17686 if (!Res.isUsable()) {
17687 ErrorFound = true;
17688 break;
17689 }
17690 Res = S.PerformImplicitConversion(From: Res.get(), ToType: AllocatorHandleEnumTy,
17691 Action: AssignmentAction::Initializing,
17692 /*AllowExplicit=*/true);
17693 if (!Res.isUsable()) {
17694 ErrorFound = true;
17695 break;
17696 }
17697 Stack->setAllocator(AllocatorKind, Allocator: Res.get());
17698 }
17699 if (ErrorFound) {
17700 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found)
17701 << "omp_allocator_handle_t";
17702 return false;
17703 }
17704
17705 // Record the type only now. It is what tells a later call that the map above
17706 // is ready to be read, so setting it before the map is filled would let that
17707 // call proceed on a map this one gave up on halfway through.
17708 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17709
17710 return true;
17711}
17712
17713OMPClause *SemaOpenMP::ActOnOpenMPAllocatorClause(Expr *A,
17714 SourceLocation StartLoc,
17715 SourceLocation LParenLoc,
17716 SourceLocation EndLoc) {
17717 // OpenMP [2.11.3, allocate Directive, Description]
17718 // allocator is an expression of omp_allocator_handle_t type.
17719 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: A->getExprLoc(), DSAStack))
17720 return nullptr;
17721
17722 ExprResult Allocator = SemaRef.DefaultLvalueConversion(E: A);
17723 if (Allocator.isInvalid())
17724 return nullptr;
17725 Allocator = SemaRef.PerformImplicitConversion(
17726 From: Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
17727 Action: AssignmentAction::Initializing,
17728 /*AllowExplicit=*/true);
17729 if (Allocator.isInvalid())
17730 return nullptr;
17731 return new (getASTContext())
17732 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
17733}
17734
17735OMPClause *SemaOpenMP::ActOnOpenMPCollapseClause(Expr *NumForLoops,
17736 SourceLocation StartLoc,
17737 SourceLocation LParenLoc,
17738 SourceLocation EndLoc) {
17739 // OpenMP [2.7.1, loop construct, Description]
17740 // OpenMP [2.8.1, simd construct, Description]
17741 // OpenMP [2.9.6, distribute construct, Description]
17742 // The parameter of the collapse clause must be a constant
17743 // positive integer expression.
17744 ExprResult NumForLoopsResult =
17745 VerifyPositiveIntegerConstantInClause(E: NumForLoops, CKind: OMPC_collapse);
17746 if (NumForLoopsResult.isInvalid())
17747 return nullptr;
17748 return new (getASTContext())
17749 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
17750}
17751
17752OMPClause *SemaOpenMP::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
17753 SourceLocation EndLoc,
17754 SourceLocation LParenLoc,
17755 Expr *NumForLoops) {
17756 // OpenMP [2.7.1, loop construct, Description]
17757 // OpenMP [2.8.1, simd construct, Description]
17758 // OpenMP [2.9.6, distribute construct, Description]
17759 // The parameter of the ordered clause must be a constant
17760 // positive integer expression if any.
17761 if (NumForLoops && LParenLoc.isValid()) {
17762 ExprResult NumForLoopsResult =
17763 VerifyPositiveIntegerConstantInClause(E: NumForLoops, CKind: OMPC_ordered);
17764 if (NumForLoopsResult.isInvalid())
17765 return nullptr;
17766 NumForLoops = NumForLoopsResult.get();
17767 } else {
17768 NumForLoops = nullptr;
17769 }
17770 auto *Clause =
17771 OMPOrderedClause::Create(C: getASTContext(), Num: NumForLoops,
17772 NumLoops: NumForLoops ? DSAStack->getAssociatedLoops() : 0,
17773 StartLoc, LParenLoc, EndLoc);
17774 DSAStack->setOrderedRegion(/*IsOrdered=*/true, Param: NumForLoops, Clause);
17775 return Clause;
17776}
17777
17778OMPClause *SemaOpenMP::ActOnOpenMPSimpleClause(
17779 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
17780 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17781 OMPClause *Res = nullptr;
17782 switch (Kind) {
17783 case OMPC_proc_bind:
17784 Res = ActOnOpenMPProcBindClause(Kind: static_cast<ProcBindKind>(Argument),
17785 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17786 break;
17787 case OMPC_atomic_default_mem_order:
17788 Res = ActOnOpenMPAtomicDefaultMemOrderClause(
17789 Kind: static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
17790 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17791 break;
17792 case OMPC_fail:
17793 Res = ActOnOpenMPFailClause(Kind: static_cast<OpenMPClauseKind>(Argument),
17794 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17795 break;
17796 case OMPC_update_depend_objects:
17797 Res = ActOnOpenMPUpdateDependObjectsClause(
17798 Kind: static_cast<OpenMPDependClauseKind>(Argument), KindLoc: ArgumentLoc, StartLoc,
17799 LParenLoc, EndLoc);
17800 break;
17801 case OMPC_bind:
17802 Res = ActOnOpenMPBindClause(Kind: static_cast<OpenMPBindClauseKind>(Argument),
17803 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17804 break;
17805 case OMPC_at:
17806 Res = ActOnOpenMPAtClause(Kind: static_cast<OpenMPAtClauseKind>(Argument),
17807 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17808 break;
17809 case OMPC_severity:
17810 Res = ActOnOpenMPSeverityClause(
17811 Kind: static_cast<OpenMPSeverityClauseKind>(Argument), KindLoc: ArgumentLoc, StartLoc,
17812 LParenLoc, EndLoc);
17813 break;
17814 case OMPC_threadset:
17815 Res = ActOnOpenMPThreadsetClause(Kind: static_cast<OpenMPThreadsetKind>(Argument),
17816 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17817 break;
17818 case OMPC_if:
17819 case OMPC_final:
17820 case OMPC_num_threads:
17821 case OMPC_safelen:
17822 case OMPC_simdlen:
17823 case OMPC_sizes:
17824 case OMPC_allocator:
17825 case OMPC_collapse:
17826 case OMPC_schedule:
17827 case OMPC_private:
17828 case OMPC_firstprivate:
17829 case OMPC_lastprivate:
17830 case OMPC_shared:
17831 case OMPC_reduction:
17832 case OMPC_task_reduction:
17833 case OMPC_in_reduction:
17834 case OMPC_linear:
17835 case OMPC_aligned:
17836 case OMPC_copyin:
17837 case OMPC_copyprivate:
17838 case OMPC_ordered:
17839 case OMPC_nowait:
17840 case OMPC_untied:
17841 case OMPC_mergeable:
17842 case OMPC_threadprivate:
17843 case OMPC_groupprivate:
17844 case OMPC_allocate:
17845 case OMPC_flush:
17846 case OMPC_depobj:
17847 case OMPC_read:
17848 case OMPC_write:
17849 case OMPC_capture:
17850 case OMPC_compare:
17851 case OMPC_update:
17852 case OMPC_seq_cst:
17853 case OMPC_acq_rel:
17854 case OMPC_acquire:
17855 case OMPC_release:
17856 case OMPC_relaxed:
17857 case OMPC_depend:
17858 case OMPC_device:
17859 case OMPC_threads:
17860 case OMPC_simd:
17861 case OMPC_map:
17862 case OMPC_num_teams:
17863 case OMPC_thread_limit:
17864 case OMPC_priority:
17865 case OMPC_grainsize:
17866 case OMPC_nogroup:
17867 case OMPC_num_tasks:
17868 case OMPC_hint:
17869 case OMPC_dist_schedule:
17870 case OMPC_default:
17871 case OMPC_defaultmap:
17872 case OMPC_unknown:
17873 case OMPC_uniform:
17874 case OMPC_to:
17875 case OMPC_from:
17876 case OMPC_use_device_ptr:
17877 case OMPC_use_device_addr:
17878 case OMPC_is_device_ptr:
17879 case OMPC_has_device_addr:
17880 case OMPC_unified_address:
17881 case OMPC_unified_shared_memory:
17882 case OMPC_reverse_offload:
17883 case OMPC_dynamic_allocators:
17884 case OMPC_self_maps:
17885 case OMPC_device_type:
17886 case OMPC_match:
17887 case OMPC_nontemporal:
17888 case OMPC_destroy:
17889 case OMPC_novariants:
17890 case OMPC_nocontext:
17891 case OMPC_detach:
17892 case OMPC_inclusive:
17893 case OMPC_exclusive:
17894 case OMPC_uses_allocators:
17895 case OMPC_affinity:
17896 case OMPC_when:
17897 case OMPC_message:
17898 default:
17899 llvm_unreachable("Clause is not allowed.");
17900 }
17901 return Res;
17902}
17903
17904OMPClause *SemaOpenMP::ActOnOpenMPDefaultClause(
17905 llvm::omp::DefaultKind M, SourceLocation MLoc,
17906 OpenMPDefaultClauseVariableCategory VCKind, SourceLocation VCKindLoc,
17907 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17908 if (M == OMP_DEFAULT_unknown) {
17909 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
17910 << getListOfPossibleValues(K: OMPC_default, /*First=*/0,
17911 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17912 << getOpenMPClauseNameForDiag(C: OMPC_default);
17913 return nullptr;
17914 }
17915 if (VCKind == OMPC_DEFAULT_VC_unknown) {
17916 Diag(Loc: VCKindLoc, DiagID: diag::err_omp_default_vc)
17917 << getOpenMPSimpleClauseTypeName(Kind: OMPC_default, Type: unsigned(M));
17918 return nullptr;
17919 }
17920
17921 bool IsTargetDefault =
17922 getLangOpts().OpenMP >= 60 &&
17923 isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective());
17924
17925 // OpenMP 6.0, page 224, lines 3-4 default Clause, Semantics
17926 // If data-sharing-attribute is shared then the clause has no effect
17927 // on a target construct;
17928 if (IsTargetDefault && M == OMP_DEFAULT_shared)
17929 return nullptr;
17930
17931 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
17932 OpenMPDefaultClauseVariableCategory VCKind) {
17933 OpenMPDefaultmapClauseModifier DefMapMod;
17934 OpenMPDefaultmapClauseKind DefMapKind;
17935 // default data-sharing-attribute
17936 switch (M) {
17937 case OMP_DEFAULT_none:
17938 if (IsTargetDefault)
17939 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
17940 else
17941 DSAStack->setDefaultDSANone(MLoc);
17942 break;
17943 case OMP_DEFAULT_firstprivate:
17944 if (IsTargetDefault)
17945 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
17946 else
17947 DSAStack->setDefaultDSAFirstPrivate(MLoc);
17948 break;
17949 case OMP_DEFAULT_private:
17950 if (IsTargetDefault)
17951 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
17952 else
17953 DSAStack->setDefaultDSAPrivate(MLoc);
17954 break;
17955 case OMP_DEFAULT_shared:
17956 assert(!IsTargetDefault && "DSA shared invalid with target directive");
17957 DSAStack->setDefaultDSAShared(MLoc);
17958 break;
17959 default:
17960 llvm_unreachable("unexpected DSA in OpenMP default clause");
17961 }
17962 // default variable-category
17963 switch (VCKind) {
17964 case OMPC_DEFAULT_VC_aggregate:
17965 if (IsTargetDefault)
17966 DefMapKind = OMPC_DEFAULTMAP_aggregate;
17967 else
17968 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
17969 break;
17970 case OMPC_DEFAULT_VC_pointer:
17971 if (IsTargetDefault)
17972 DefMapKind = OMPC_DEFAULTMAP_pointer;
17973 else
17974 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
17975 break;
17976 case OMPC_DEFAULT_VC_scalar:
17977 if (IsTargetDefault)
17978 DefMapKind = OMPC_DEFAULTMAP_scalar;
17979 else
17980 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
17981 break;
17982 case OMPC_DEFAULT_VC_all:
17983 if (IsTargetDefault)
17984 DefMapKind = OMPC_DEFAULTMAP_all;
17985 else
17986 DSAStack->setDefaultDSAVCAll(VCKindLoc);
17987 break;
17988 default:
17989 llvm_unreachable("unexpected variable category in OpenMP default clause");
17990 }
17991 // OpenMP 6.0, page 224, lines 4-5 default Clause, Semantics
17992 // otherwise, its effect on a target construct is equivalent to
17993 // specifying the defaultmap clause with the same data-sharing-attribute
17994 // and variable-category.
17995 //
17996 // If earlier than OpenMP 6.0, or not a target directive, the default DSA
17997 // is/was set as before.
17998 if (IsTargetDefault) {
17999 if (DefMapKind == OMPC_DEFAULTMAP_all) {
18000 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: OMPC_DEFAULTMAP_aggregate, Loc: MLoc);
18001 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: OMPC_DEFAULTMAP_scalar, Loc: MLoc);
18002 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: OMPC_DEFAULTMAP_pointer, Loc: MLoc);
18003 } else {
18004 DSAStack->setDefaultDMAAttr(M: DefMapMod, Kind: DefMapKind, Loc: MLoc);
18005 }
18006 }
18007 };
18008
18009 SetDefaultClauseAttrs(M, VCKind);
18010 return new (getASTContext())
18011 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
18012}
18013
18014OMPClause *SemaOpenMP::ActOnOpenMPThreadsetClause(OpenMPThreadsetKind Kind,
18015 SourceLocation KindLoc,
18016 SourceLocation StartLoc,
18017 SourceLocation LParenLoc,
18018 SourceLocation EndLoc) {
18019 if (Kind == OMPC_THREADSET_unknown) {
18020 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
18021 << getListOfPossibleValues(K: OMPC_threadset, /*First=*/0,
18022 /*Last=*/unsigned(OMPC_THREADSET_unknown))
18023 << getOpenMPClauseName(C: OMPC_threadset);
18024 return nullptr;
18025 }
18026
18027 return new (getASTContext())
18028 OMPThreadsetClause(Kind, KindLoc, StartLoc, LParenLoc, EndLoc);
18029}
18030
18031static OMPClause *
18032createTransparentClause(Sema &SemaRef, ASTContext &Ctx, Expr *ImpexTypeArg,
18033 Stmt *HelperValStmt, OpenMPDirectiveKind CaptureRegion,
18034 SourceLocation StartLoc, SourceLocation LParenLoc,
18035 SourceLocation EndLoc) {
18036 ExprResult ER = SemaRef.DefaultLvalueConversion(E: ImpexTypeArg);
18037 if (ER.isInvalid())
18038 return nullptr;
18039
18040 return new (Ctx) OMPTransparentClause(ER.get(), HelperValStmt, CaptureRegion,
18041 StartLoc, LParenLoc, EndLoc);
18042}
18043
18044OMPClause *SemaOpenMP::ActOnOpenMPTransparentClause(Expr *ImpexTypeArg,
18045 SourceLocation StartLoc,
18046 SourceLocation LParenLoc,
18047 SourceLocation EndLoc) {
18048 Stmt *HelperValStmt = nullptr;
18049 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18050 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
18051 DKind, CKind: OMPC_transparent, OpenMPVersion: getLangOpts().OpenMP);
18052 if (CaptureRegion != OMPD_unknown &&
18053 !SemaRef.CurContext->isDependentContext()) {
18054 Expr *ValExpr = SemaRef.MakeFullExpr(Arg: ImpexTypeArg).get();
18055 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18056 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
18057 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
18058 }
18059 if (!ImpexTypeArg) {
18060 return new (getASTContext())
18061 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
18062 StartLoc, LParenLoc, EndLoc);
18063 }
18064 QualType Ty = ImpexTypeArg->getType();
18065
18066 if (const auto *TT = Ty->getAs<TypedefType>()) {
18067 const TypedefNameDecl *TypedefDecl = TT->getDecl();
18068 llvm::StringRef TypedefName = TypedefDecl->getName();
18069 IdentifierInfo &II = SemaRef.PP.getIdentifierTable().get(Name: TypedefName);
18070 ParsedType ImpexTy =
18071 SemaRef.getTypeName(II, NameLoc: StartLoc, S: SemaRef.getCurScope());
18072 if (!ImpexTy.getAsOpaquePtr() || ImpexTy.get().isNull()) {
18073 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_implied_type_not_found)
18074 << TypedefName;
18075 return nullptr;
18076 }
18077 return new (getASTContext())
18078 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
18079 StartLoc, LParenLoc, EndLoc);
18080 }
18081
18082 if (Ty->isEnumeralType())
18083 return createTransparentClause(SemaRef, Ctx&: getASTContext(), ImpexTypeArg,
18084 HelperValStmt, CaptureRegion, StartLoc,
18085 LParenLoc, EndLoc);
18086 if (Ty->isIntegerType()) {
18087 if (isNonNegativeIntegerValue(ValExpr&: ImpexTypeArg, SemaRef, CKind: OMPC_transparent,
18088 /*StrictlyPositive=*/false)) {
18089 ExprResult Value =
18090 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc: StartLoc,
18091 Op: ImpexTypeArg);
18092 if (std::optional<llvm::APSInt> Result =
18093 Value.get()->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
18094 if (Result->isNegative() ||
18095 Result >
18096 static_cast<int64_t>(SemaOpenMP::OpenMPImpexType::OMP_Export))
18097 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_transparent_invalid_value);
18098 }
18099 return new (getASTContext())
18100 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
18101 StartLoc, LParenLoc, EndLoc);
18102 }
18103 }
18104 if (!isNonNegativeIntegerValue(ValExpr&: ImpexTypeArg, SemaRef, CKind: OMPC_transparent,
18105 /*StrictlyPositive=*/true))
18106 return nullptr;
18107 return new (getASTContext()) OMPTransparentClause(
18108 ImpexTypeArg, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18109}
18110
18111OMPClause *SemaOpenMP::ActOnOpenMPProcBindClause(ProcBindKind Kind,
18112 SourceLocation KindKwLoc,
18113 SourceLocation StartLoc,
18114 SourceLocation LParenLoc,
18115 SourceLocation EndLoc) {
18116 if (Kind == OMP_PROC_BIND_unknown) {
18117 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
18118 << getListOfPossibleValues(K: OMPC_proc_bind,
18119 /*First=*/unsigned(OMP_PROC_BIND_master),
18120 /*Last=*/
18121 unsigned(getLangOpts().OpenMP > 50
18122 ? OMP_PROC_BIND_primary
18123 : OMP_PROC_BIND_spread) +
18124 1)
18125 << getOpenMPClauseNameForDiag(C: OMPC_proc_bind);
18126 return nullptr;
18127 }
18128 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
18129 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
18130 << getListOfPossibleValues(K: OMPC_proc_bind,
18131 /*First=*/unsigned(OMP_PROC_BIND_master),
18132 /*Last=*/
18133 unsigned(OMP_PROC_BIND_spread) + 1)
18134 << getOpenMPClauseNameForDiag(C: OMPC_proc_bind);
18135 return new (getASTContext())
18136 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
18137}
18138
18139OMPClause *SemaOpenMP::ActOnOpenMPAtomicDefaultMemOrderClause(
18140 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
18141 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
18142 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
18143 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
18144 << getListOfPossibleValues(
18145 K: OMPC_atomic_default_mem_order, /*First=*/0,
18146 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
18147 << getOpenMPClauseNameForDiag(C: OMPC_atomic_default_mem_order);
18148 return nullptr;
18149 }
18150 return new (getASTContext()) OMPAtomicDefaultMemOrderClause(
18151 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
18152}
18153
18154OMPClause *SemaOpenMP::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
18155 SourceLocation KindKwLoc,
18156 SourceLocation StartLoc,
18157 SourceLocation LParenLoc,
18158 SourceLocation EndLoc) {
18159 if (Kind == OMPC_AT_unknown) {
18160 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
18161 << getListOfPossibleValues(K: OMPC_at, /*First=*/0,
18162 /*Last=*/OMPC_AT_unknown)
18163 << getOpenMPClauseNameForDiag(C: OMPC_at);
18164 return nullptr;
18165 }
18166 return new (getASTContext())
18167 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
18168}
18169
18170OMPClause *SemaOpenMP::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
18171 SourceLocation KindKwLoc,
18172 SourceLocation StartLoc,
18173 SourceLocation LParenLoc,
18174 SourceLocation EndLoc) {
18175 if (Kind == OMPC_SEVERITY_unknown) {
18176 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
18177 << getListOfPossibleValues(K: OMPC_severity, /*First=*/0,
18178 /*Last=*/OMPC_SEVERITY_unknown)
18179 << getOpenMPClauseNameForDiag(C: OMPC_severity);
18180 return nullptr;
18181 }
18182 return new (getASTContext())
18183 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
18184}
18185
18186OMPClause *SemaOpenMP::ActOnOpenMPMessageClause(Expr *ME,
18187 SourceLocation StartLoc,
18188 SourceLocation LParenLoc,
18189 SourceLocation EndLoc) {
18190 assert(ME && "NULL expr in Message clause");
18191 QualType Type = ME->getType();
18192 if ((!Type->isPointerType() && !Type->isArrayType()) ||
18193 !Type->getPointeeOrArrayElementType()->isAnyCharacterType()) {
18194 Diag(Loc: ME->getBeginLoc(), DiagID: diag::warn_clause_expected_string)
18195 << getOpenMPClauseNameForDiag(C: OMPC_message) << 0;
18196 return nullptr;
18197 }
18198
18199 Stmt *HelperValStmt = nullptr;
18200
18201 // Depending on whether this clause appears in an executable context or not,
18202 // we may or may not build a capture.
18203 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18204 OpenMPDirectiveKind CaptureRegion =
18205 DKind == OMPD_unknown ? OMPD_unknown
18206 : getOpenMPCaptureRegionForClause(
18207 DKind, CKind: OMPC_message, OpenMPVersion: getLangOpts().OpenMP);
18208 if (CaptureRegion != OMPD_unknown &&
18209 !SemaRef.CurContext->isDependentContext()) {
18210 ME = SemaRef.MakeFullExpr(Arg: ME).get();
18211 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18212 ME = tryBuildCapture(SemaRef, Capture: ME, Captures).get();
18213 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
18214 }
18215
18216 // Convert array type to pointer type if needed.
18217 ME = SemaRef.DefaultFunctionArrayLvalueConversion(E: ME).get();
18218
18219 return new (getASTContext()) OMPMessageClause(
18220 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18221}
18222
18223OMPClause *SemaOpenMP::ActOnOpenMPOrderClause(
18224 OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind,
18225 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
18226 SourceLocation KindLoc, SourceLocation EndLoc) {
18227 if (Kind != OMPC_ORDER_concurrent ||
18228 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
18229 // Kind should be concurrent,
18230 // Modifiers introduced in OpenMP 5.1
18231 static_assert(OMPC_ORDER_unknown > 0,
18232 "OMPC_ORDER_unknown not greater than 0");
18233
18234 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
18235 << getListOfPossibleValues(K: OMPC_order,
18236 /*First=*/0,
18237 /*Last=*/OMPC_ORDER_unknown)
18238 << getOpenMPClauseNameForDiag(C: OMPC_order);
18239 return nullptr;
18240 }
18241 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
18242 MLoc.isValid()) {
18243 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
18244 << getListOfPossibleValues(K: OMPC_order,
18245 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
18246 /*Last=*/OMPC_ORDER_MODIFIER_last)
18247 << getOpenMPClauseNameForDiag(C: OMPC_order);
18248 } else if (getLangOpts().OpenMP >= 50) {
18249 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
18250 if (DSAStack->getCurScope()) {
18251 // mark the current scope with 'order' flag
18252 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
18253 DSAStack->getCurScope()->setFlags(existingFlags |
18254 Scope::OpenMPOrderClauseScope);
18255 }
18256 }
18257 return new (getASTContext()) OMPOrderClause(
18258 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
18259}
18260
18261OMPClause *SemaOpenMP::ActOnOpenMPUpdateDependObjectsClause(
18262 OpenMPDependClauseKind Kind, SourceLocation KindKwLoc,
18263 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
18264 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
18265 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
18266 SmallVector<unsigned> Except = {
18267 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
18268 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
18269 if (getLangOpts().OpenMP < 51)
18270 Except.push_back(Elt: OMPC_DEPEND_inoutset);
18271 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
18272 << getListOfPossibleValues(K: OMPC_depend, /*First=*/0,
18273 /*Last=*/OMPC_DEPEND_unknown, Exclude: Except)
18274 << getOpenMPClauseNameForDiag(C: OMPC_update_depend_objects);
18275 return nullptr;
18276 }
18277 return OMPUpdateDependObjectsClause::Create(
18278 C: getASTContext(), StartLoc, LParenLoc, ArgumentLoc: KindKwLoc, DK: Kind, EndLoc);
18279}
18280
18281OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
18282 SourceLocation StartLoc,
18283 SourceLocation LParenLoc,
18284 SourceLocation EndLoc) {
18285 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
18286
18287 for (Expr *&SizeExpr : SanitizedSizeExprs) {
18288 // Skip if already sanitized, e.g. during a partial template instantiation.
18289 if (!SizeExpr)
18290 continue;
18291
18292 bool IsValid = isNonNegativeIntegerValue(ValExpr&: SizeExpr, SemaRef, CKind: OMPC_sizes,
18293 /*StrictlyPositive=*/true);
18294
18295 // isNonNegativeIntegerValue returns true for non-integral types (but still
18296 // emits error diagnostic), so check for the expected type explicitly.
18297 QualType SizeTy = SizeExpr->getType();
18298 if (!SizeTy->isIntegerType())
18299 IsValid = false;
18300
18301 // Handling in templates is tricky. There are four possibilities to
18302 // consider:
18303 //
18304 // 1a. The expression is valid and we are in a instantiated template or not
18305 // in a template:
18306 // Pass valid expression to be further analysed later in Sema.
18307 // 1b. The expression is valid and we are in a template (including partial
18308 // instantiation):
18309 // isNonNegativeIntegerValue skipped any checks so there is no
18310 // guarantee it will be correct after instantiation.
18311 // ActOnOpenMPSizesClause will be called again at instantiation when
18312 // it is not in a dependent context anymore. This may cause warnings
18313 // to be emitted multiple times.
18314 // 2a. The expression is invalid and we are in an instantiated template or
18315 // not in a template:
18316 // Invalidate the expression with a clearly wrong value (nullptr) so
18317 // later in Sema we do not have to do the same validity analysis again
18318 // or crash from unexpected data. Error diagnostics have already been
18319 // emitted.
18320 // 2b. The expression is invalid and we are in a template (including partial
18321 // instantiation):
18322 // Pass the invalid expression as-is, template instantiation may
18323 // replace unexpected types/values with valid ones. The directives
18324 // with this clause must not try to use these expressions in dependent
18325 // contexts, but delay analysis until full instantiation.
18326 if (!SizeExpr->isInstantiationDependent() && !IsValid)
18327 SizeExpr = nullptr;
18328 }
18329
18330 return OMPSizesClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
18331 Sizes: SanitizedSizeExprs);
18332}
18333
18334OMPClause *SemaOpenMP::ActOnOpenMPCountsClause(ArrayRef<Expr *> CountExprs,
18335 SourceLocation StartLoc,
18336 SourceLocation LParenLoc,
18337 SourceLocation EndLoc,
18338 std::optional<unsigned> FillIdx,
18339 SourceLocation FillLoc,
18340 unsigned FillCount) {
18341 SmallVector<Expr *> SanitizedCountExprs(CountExprs);
18342
18343 // OpenMP 6.0: each list item in counts(...) is either the omp_fill keyword
18344 // or an integral constant expression (non-negative). Runtime variables are
18345 // not permitted; this matches split codegen, which needs segment sizes at
18346 // compile time.
18347 for (unsigned I = 0; I < SanitizedCountExprs.size(); ++I) {
18348 Expr *&CountExpr = SanitizedCountExprs[I];
18349 if (FillIdx && I == *FillIdx)
18350 continue;
18351 if (!CountExpr)
18352 continue;
18353
18354 ExprResult Verified = VerifyPositiveIntegerConstantInClause(
18355 E: CountExpr, CKind: OMPC_counts, /*StrictlyPositive=*/false);
18356 if (Verified.isInvalid())
18357 CountExpr = nullptr;
18358 else
18359 CountExpr = Verified.get();
18360 }
18361
18362 if (FillCount != 1) {
18363 Diag(Loc: FillCount == 0 ? StartLoc : FillLoc,
18364 DiagID: diag::err_omp_split_counts_not_one_omp_fill);
18365 }
18366
18367 return OMPCountsClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
18368 Counts: SanitizedCountExprs, FillIdx, FillLoc);
18369}
18370
18371OMPClause *SemaOpenMP::ActOnOpenMPPermutationClause(ArrayRef<Expr *> PermExprs,
18372 SourceLocation StartLoc,
18373 SourceLocation LParenLoc,
18374 SourceLocation EndLoc) {
18375 size_t NumLoops = PermExprs.size();
18376 SmallVector<Expr *> SanitizedPermExprs;
18377 llvm::append_range(C&: SanitizedPermExprs, R&: PermExprs);
18378
18379 for (Expr *&PermExpr : SanitizedPermExprs) {
18380 // Skip if template-dependent or already sanitized, e.g. during a partial
18381 // template instantiation.
18382 if (!PermExpr || PermExpr->isInstantiationDependent())
18383 continue;
18384
18385 llvm::APSInt PermVal;
18386 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
18387 E: PermExpr, Result: &PermVal, CanFold: AllowFoldKind::Allow);
18388 bool IsValid = PermEvalExpr.isUsable();
18389 if (IsValid)
18390 PermExpr = PermEvalExpr.get();
18391
18392 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
18393 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
18394 PermEvalExpr.get()->getEndLoc());
18395 Diag(Loc: PermEvalExpr.get()->getExprLoc(),
18396 DiagID: diag::err_omp_interchange_permutation_value_range)
18397 << NumLoops << ExprRange;
18398 IsValid = false;
18399 }
18400
18401 if (!PermExpr->isInstantiationDependent() && !IsValid)
18402 PermExpr = nullptr;
18403 }
18404
18405 return OMPPermutationClause::Create(C: getASTContext(), StartLoc, LParenLoc,
18406 EndLoc, Args: SanitizedPermExprs);
18407}
18408
18409OMPClause *SemaOpenMP::ActOnOpenMPFullClause(SourceLocation StartLoc,
18410 SourceLocation EndLoc) {
18411 return OMPFullClause::Create(C: getASTContext(), StartLoc, EndLoc);
18412}
18413
18414OMPClause *SemaOpenMP::ActOnOpenMPPartialClause(Expr *FactorExpr,
18415 SourceLocation StartLoc,
18416 SourceLocation LParenLoc,
18417 SourceLocation EndLoc) {
18418 if (FactorExpr) {
18419 // If an argument is specified, it must be a constant (or an unevaluated
18420 // template expression).
18421 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
18422 E: FactorExpr, CKind: OMPC_partial, /*StrictlyPositive=*/true);
18423 if (FactorResult.isInvalid())
18424 return nullptr;
18425 FactorExpr = FactorResult.get();
18426 }
18427
18428 return OMPPartialClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
18429 Factor: FactorExpr);
18430}
18431
18432OMPClause *SemaOpenMP::ActOnOpenMPLoopRangeClause(
18433 Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc,
18434 SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc) {
18435
18436 // OpenMP [6.0, Restrictions]
18437 // First and Count must be integer expressions with positive value
18438 ExprResult FirstVal =
18439 VerifyPositiveIntegerConstantInClause(E: First, CKind: OMPC_looprange);
18440 if (FirstVal.isInvalid())
18441 First = nullptr;
18442
18443 ExprResult CountVal =
18444 VerifyPositiveIntegerConstantInClause(E: Count, CKind: OMPC_looprange);
18445 if (CountVal.isInvalid())
18446 Count = nullptr;
18447
18448 // OpenMP [6.0, Restrictions]
18449 // first + count - 1 must not evaluate to a value greater than the
18450 // loop sequence length of the associated canonical loop sequence.
18451 // This check must be performed afterwards due to the delayed
18452 // parsing and computation of the associated loop sequence
18453 return OMPLoopRangeClause::Create(C: getASTContext(), StartLoc, LParenLoc,
18454 FirstLoc, CountLoc, EndLoc, First, Count);
18455}
18456
18457OMPClause *SemaOpenMP::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
18458 SourceLocation LParenLoc,
18459 SourceLocation EndLoc) {
18460 ExprResult AlignVal;
18461 AlignVal = VerifyPositiveIntegerConstantInClause(E: A, CKind: OMPC_align);
18462 if (AlignVal.isInvalid())
18463 return nullptr;
18464 return OMPAlignClause::Create(C: getASTContext(), A: AlignVal.get(), StartLoc,
18465 LParenLoc, EndLoc);
18466}
18467
18468OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause(
18469 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
18470 SourceLocation StartLoc, SourceLocation LParenLoc,
18471 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
18472 SourceLocation EndLoc) {
18473 OMPClause *Res = nullptr;
18474 switch (Kind) {
18475 case OMPC_schedule: {
18476 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
18477 assert(Argument.size() == NumberOfElements &&
18478 ArgumentLoc.size() == NumberOfElements);
18479 Res = ActOnOpenMPScheduleClause(
18480 M1: static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
18481 M2: static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
18482 Kind: static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), ChunkSize: Expr,
18483 StartLoc, LParenLoc, M1Loc: ArgumentLoc[Modifier1], M2Loc: ArgumentLoc[Modifier2],
18484 KindLoc: ArgumentLoc[ScheduleKind], CommaLoc: DelimLoc, EndLoc);
18485 break;
18486 }
18487 case OMPC_if:
18488 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
18489 Res = ActOnOpenMPIfClause(NameModifier: static_cast<OpenMPDirectiveKind>(Argument.back()),
18490 Condition: Expr, StartLoc, LParenLoc, NameModifierLoc: ArgumentLoc.back(),
18491 ColonLoc: DelimLoc, EndLoc);
18492 break;
18493 case OMPC_dist_schedule:
18494 Res = ActOnOpenMPDistScheduleClause(
18495 Kind: static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), ChunkSize: Expr,
18496 StartLoc, LParenLoc, KindLoc: ArgumentLoc.back(), CommaLoc: DelimLoc, EndLoc);
18497 break;
18498 case OMPC_default:
18499 enum { DefaultModifier, DefaultVarCategory };
18500 Res = ActOnOpenMPDefaultClause(
18501 M: static_cast<llvm::omp::DefaultKind>(Argument[DefaultModifier]),
18502 MLoc: ArgumentLoc[DefaultModifier],
18503 VCKind: static_cast<OpenMPDefaultClauseVariableCategory>(
18504 Argument[DefaultVarCategory]),
18505 VCKindLoc: ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
18506 break;
18507 case OMPC_defaultmap:
18508 enum { Modifier, DefaultmapKind };
18509 Res = ActOnOpenMPDefaultmapClause(
18510 M: static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
18511 Kind: static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
18512 StartLoc, LParenLoc, MLoc: ArgumentLoc[Modifier], KindLoc: ArgumentLoc[DefaultmapKind],
18513 EndLoc);
18514 break;
18515 case OMPC_order:
18516 enum { OrderModifier, OrderKind };
18517 Res = ActOnOpenMPOrderClause(
18518 Modifier: static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
18519 Kind: static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
18520 LParenLoc, MLoc: ArgumentLoc[OrderModifier], KindLoc: ArgumentLoc[OrderKind], EndLoc);
18521 break;
18522 case OMPC_device:
18523 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
18524 Res = ActOnOpenMPDeviceClause(
18525 Modifier: static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Device: Expr,
18526 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
18527 break;
18528 case OMPC_grainsize:
18529 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
18530 "Modifier for grainsize clause and its location are expected.");
18531 Res = ActOnOpenMPGrainsizeClause(
18532 Modifier: static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Size: Expr,
18533 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
18534 break;
18535 case OMPC_num_tasks:
18536 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
18537 "Modifier for num_tasks clause and its location are expected.");
18538 Res = ActOnOpenMPNumTasksClause(
18539 Modifier: static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), NumTasks: Expr,
18540 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
18541 break;
18542 case OMPC_dyn_groupprivate: {
18543 enum { Modifier1, Modifier2, NumberOfElements };
18544 assert(Argument.size() == NumberOfElements &&
18545 ArgumentLoc.size() == NumberOfElements &&
18546 "Modifiers for dyn_groupprivate clause and their locations are "
18547 "expected.");
18548 Res = ActOnOpenMPDynGroupprivateClause(
18549 M1: static_cast<OpenMPDynGroupprivateClauseModifier>(Argument[Modifier1]),
18550 M2: static_cast<OpenMPDynGroupprivateClauseFallbackModifier>(
18551 Argument[Modifier2]),
18552 Size: Expr, StartLoc, LParenLoc, M1Loc: ArgumentLoc[Modifier1],
18553 M2Loc: ArgumentLoc[Modifier2], EndLoc);
18554 break;
18555 }
18556 case OMPC_final:
18557 case OMPC_safelen:
18558 case OMPC_simdlen:
18559 case OMPC_sizes:
18560 case OMPC_allocator:
18561 case OMPC_collapse:
18562 case OMPC_proc_bind:
18563 case OMPC_private:
18564 case OMPC_firstprivate:
18565 case OMPC_lastprivate:
18566 case OMPC_shared:
18567 case OMPC_reduction:
18568 case OMPC_task_reduction:
18569 case OMPC_in_reduction:
18570 case OMPC_linear:
18571 case OMPC_aligned:
18572 case OMPC_copyin:
18573 case OMPC_copyprivate:
18574 case OMPC_ordered:
18575 case OMPC_nowait:
18576 case OMPC_untied:
18577 case OMPC_mergeable:
18578 case OMPC_threadprivate:
18579 case OMPC_groupprivate:
18580 case OMPC_allocate:
18581 case OMPC_flush:
18582 case OMPC_depobj:
18583 case OMPC_read:
18584 case OMPC_write:
18585 case OMPC_update:
18586 case OMPC_capture:
18587 case OMPC_compare:
18588 case OMPC_seq_cst:
18589 case OMPC_acq_rel:
18590 case OMPC_acquire:
18591 case OMPC_release:
18592 case OMPC_relaxed:
18593 case OMPC_depend:
18594 case OMPC_threads:
18595 case OMPC_simd:
18596 case OMPC_map:
18597 case OMPC_num_teams:
18598 case OMPC_thread_limit:
18599 case OMPC_priority:
18600 case OMPC_nogroup:
18601 case OMPC_hint:
18602 case OMPC_unknown:
18603 case OMPC_uniform:
18604 case OMPC_to:
18605 case OMPC_from:
18606 case OMPC_use_device_ptr:
18607 case OMPC_use_device_addr:
18608 case OMPC_is_device_ptr:
18609 case OMPC_has_device_addr:
18610 case OMPC_unified_address:
18611 case OMPC_unified_shared_memory:
18612 case OMPC_reverse_offload:
18613 case OMPC_dynamic_allocators:
18614 case OMPC_atomic_default_mem_order:
18615 case OMPC_self_maps:
18616 case OMPC_device_type:
18617 case OMPC_match:
18618 case OMPC_nontemporal:
18619 case OMPC_at:
18620 case OMPC_severity:
18621 case OMPC_message:
18622 case OMPC_destroy:
18623 case OMPC_novariants:
18624 case OMPC_nocontext:
18625 case OMPC_detach:
18626 case OMPC_inclusive:
18627 case OMPC_exclusive:
18628 case OMPC_uses_allocators:
18629 case OMPC_affinity:
18630 case OMPC_when:
18631 case OMPC_bind:
18632 default:
18633 llvm_unreachable("Clause is not allowed.");
18634 }
18635 return Res;
18636}
18637
18638static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
18639 OpenMPScheduleClauseModifier M2,
18640 SourceLocation M1Loc, SourceLocation M2Loc) {
18641 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
18642 SmallVector<unsigned, 2> Excluded;
18643 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
18644 Excluded.push_back(Elt: M2);
18645 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
18646 Excluded.push_back(Elt: OMPC_SCHEDULE_MODIFIER_monotonic);
18647 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
18648 Excluded.push_back(Elt: OMPC_SCHEDULE_MODIFIER_nonmonotonic);
18649 S.Diag(Loc: M1Loc, DiagID: diag::err_omp_unexpected_clause_value)
18650 << getListOfPossibleValues(K: OMPC_schedule,
18651 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
18652 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
18653 Exclude: Excluded)
18654 << getOpenMPClauseNameForDiag(C: OMPC_schedule);
18655 return true;
18656 }
18657 return false;
18658}
18659
18660OMPClause *SemaOpenMP::ActOnOpenMPScheduleClause(
18661 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
18662 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
18663 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
18664 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
18665 if (checkScheduleModifiers(S&: SemaRef, M1, M2, M1Loc, M2Loc) ||
18666 checkScheduleModifiers(S&: SemaRef, M1: M2, M2: M1, M1Loc: M2Loc, M2Loc: M1Loc))
18667 return nullptr;
18668 // OpenMP, 2.7.1, Loop Construct, Restrictions
18669 // Either the monotonic modifier or the nonmonotonic modifier can be specified
18670 // but not both.
18671 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
18672 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
18673 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
18674 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
18675 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
18676 Diag(Loc: M2Loc, DiagID: diag::err_omp_unexpected_schedule_modifier)
18677 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule, Type: M2)
18678 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule, Type: M1);
18679 return nullptr;
18680 }
18681 if (Kind == OMPC_SCHEDULE_unknown) {
18682 std::string Values;
18683 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
18684 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
18685 Values = getListOfPossibleValues(K: OMPC_schedule, /*First=*/0,
18686 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
18687 Exclude);
18688 } else {
18689 Values = getListOfPossibleValues(K: OMPC_schedule, /*First=*/0,
18690 /*Last=*/OMPC_SCHEDULE_unknown);
18691 }
18692 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
18693 << Values << getOpenMPClauseNameForDiag(C: OMPC_schedule);
18694 return nullptr;
18695 }
18696 // OpenMP, 2.7.1, Loop Construct, Restrictions
18697 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
18698 // schedule(guided).
18699 // OpenMP 5.0 does not have this restriction.
18700 if (getLangOpts().OpenMP < 50 &&
18701 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
18702 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
18703 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
18704 Diag(Loc: M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
18705 DiagID: diag::err_omp_schedule_nonmonotonic_static);
18706 return nullptr;
18707 }
18708 Expr *ValExpr = ChunkSize;
18709 Stmt *HelperValStmt = nullptr;
18710 if (ChunkSize) {
18711 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
18712 !ChunkSize->isInstantiationDependent() &&
18713 !ChunkSize->containsUnexpandedParameterPack()) {
18714 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
18715 ExprResult Val =
18716 PerformOpenMPImplicitIntegerConversion(Loc: ChunkSizeLoc, Op: ChunkSize);
18717 if (Val.isInvalid())
18718 return nullptr;
18719
18720 ValExpr = Val.get();
18721
18722 // OpenMP [2.7.1, Restrictions]
18723 // chunk_size must be a loop invariant integer expression with a positive
18724 // value.
18725 if (std::optional<llvm::APSInt> Result =
18726 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
18727 if (Result->isSigned() && !Result->isStrictlyPositive()) {
18728 Diag(Loc: ChunkSizeLoc, DiagID: diag::err_omp_negative_expression_in_clause)
18729 << "schedule" << 1 << ChunkSize->getSourceRange();
18730 return nullptr;
18731 }
18732 } else if (getOpenMPCaptureRegionForClause(
18733 DSAStack->getCurrentDirective(), CKind: OMPC_schedule,
18734 OpenMPVersion: getLangOpts().OpenMP) != OMPD_unknown &&
18735 !SemaRef.CurContext->isDependentContext()) {
18736 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
18737 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18738 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
18739 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
18740 }
18741 }
18742 }
18743
18744 return new (getASTContext())
18745 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
18746 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
18747}
18748
18749OMPClause *SemaOpenMP::ActOnOpenMPClause(OpenMPClauseKind Kind,
18750 SourceLocation StartLoc,
18751 SourceLocation EndLoc) {
18752 OMPClause *Res = nullptr;
18753 switch (Kind) {
18754 case OMPC_ordered:
18755 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
18756 break;
18757 case OMPC_nowait:
18758 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc,
18759 /*LParenLoc=*/SourceLocation(),
18760 /*Condition=*/nullptr);
18761 break;
18762 case OMPC_untied:
18763 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
18764 break;
18765 case OMPC_mergeable:
18766 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
18767 break;
18768 case OMPC_read:
18769 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
18770 break;
18771 case OMPC_write:
18772 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
18773 break;
18774 case OMPC_update:
18775 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
18776 break;
18777 case OMPC_capture:
18778 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
18779 break;
18780 case OMPC_compare:
18781 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
18782 break;
18783 case OMPC_fail:
18784 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
18785 break;
18786 case OMPC_seq_cst:
18787 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
18788 break;
18789 case OMPC_acq_rel:
18790 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
18791 break;
18792 case OMPC_acquire:
18793 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
18794 break;
18795 case OMPC_release:
18796 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
18797 break;
18798 case OMPC_relaxed:
18799 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
18800 break;
18801 case OMPC_weak:
18802 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
18803 break;
18804 case OMPC_threads:
18805 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
18806 break;
18807 case OMPC_simd:
18808 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
18809 break;
18810 case OMPC_nogroup:
18811 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
18812 break;
18813 case OMPC_unified_address:
18814 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
18815 break;
18816 case OMPC_unified_shared_memory:
18817 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18818 break;
18819 case OMPC_reverse_offload:
18820 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
18821 break;
18822 case OMPC_dynamic_allocators:
18823 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
18824 break;
18825 case OMPC_self_maps:
18826 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
18827 break;
18828 case OMPC_destroy:
18829 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
18830 /*LParenLoc=*/SourceLocation(),
18831 /*VarLoc=*/SourceLocation(), EndLoc);
18832 break;
18833 case OMPC_full:
18834 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
18835 break;
18836 case OMPC_partial:
18837 Res = ActOnOpenMPPartialClause(FactorExpr: nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
18838 break;
18839 case OMPC_ompx_bare:
18840 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
18841 break;
18842 case OMPC_if:
18843 case OMPC_final:
18844 case OMPC_num_threads:
18845 case OMPC_safelen:
18846 case OMPC_simdlen:
18847 case OMPC_sizes:
18848 case OMPC_allocator:
18849 case OMPC_collapse:
18850 case OMPC_schedule:
18851 case OMPC_private:
18852 case OMPC_firstprivate:
18853 case OMPC_lastprivate:
18854 case OMPC_shared:
18855 case OMPC_reduction:
18856 case OMPC_task_reduction:
18857 case OMPC_in_reduction:
18858 case OMPC_linear:
18859 case OMPC_aligned:
18860 case OMPC_copyin:
18861 case OMPC_copyprivate:
18862 case OMPC_default:
18863 case OMPC_proc_bind:
18864 case OMPC_threadprivate:
18865 case OMPC_groupprivate:
18866 case OMPC_allocate:
18867 case OMPC_flush:
18868 case OMPC_depobj:
18869 case OMPC_depend:
18870 case OMPC_device:
18871 case OMPC_map:
18872 case OMPC_num_teams:
18873 case OMPC_thread_limit:
18874 case OMPC_priority:
18875 case OMPC_grainsize:
18876 case OMPC_num_tasks:
18877 case OMPC_hint:
18878 case OMPC_dist_schedule:
18879 case OMPC_defaultmap:
18880 case OMPC_unknown:
18881 case OMPC_uniform:
18882 case OMPC_to:
18883 case OMPC_from:
18884 case OMPC_use_device_ptr:
18885 case OMPC_use_device_addr:
18886 case OMPC_is_device_ptr:
18887 case OMPC_has_device_addr:
18888 case OMPC_atomic_default_mem_order:
18889 case OMPC_device_type:
18890 case OMPC_match:
18891 case OMPC_nontemporal:
18892 case OMPC_order:
18893 case OMPC_at:
18894 case OMPC_severity:
18895 case OMPC_message:
18896 case OMPC_novariants:
18897 case OMPC_nocontext:
18898 case OMPC_detach:
18899 case OMPC_inclusive:
18900 case OMPC_exclusive:
18901 case OMPC_uses_allocators:
18902 case OMPC_affinity:
18903 case OMPC_when:
18904 case OMPC_ompx_dyn_cgroup_mem:
18905 case OMPC_dyn_groupprivate:
18906 default:
18907 llvm_unreachable("Clause is not allowed.");
18908 }
18909 return Res;
18910}
18911
18912OMPClause *SemaOpenMP::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
18913 SourceLocation EndLoc,
18914 SourceLocation LParenLoc,
18915 Expr *Condition) {
18916 Expr *ValExpr = Condition;
18917 if (Condition && LParenLoc.isValid()) {
18918 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18919 !Condition->isInstantiationDependent() &&
18920 !Condition->containsUnexpandedParameterPack()) {
18921 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
18922 if (Val.isInvalid())
18923 return nullptr;
18924
18925 ValExpr = Val.get();
18926 }
18927 }
18928 DSAStack->setNowaitRegion();
18929 return new (getASTContext())
18930 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
18931}
18932
18933OMPClause *SemaOpenMP::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
18934 SourceLocation EndLoc) {
18935 DSAStack->setUntiedRegion();
18936 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
18937}
18938
18939OMPClause *SemaOpenMP::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
18940 SourceLocation EndLoc) {
18941 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
18942}
18943
18944OMPClause *SemaOpenMP::ActOnOpenMPReadClause(SourceLocation StartLoc,
18945 SourceLocation EndLoc) {
18946 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
18947}
18948
18949OMPClause *SemaOpenMP::ActOnOpenMPWriteClause(SourceLocation StartLoc,
18950 SourceLocation EndLoc) {
18951 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
18952}
18953
18954OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
18955 SourceLocation EndLoc) {
18956 return new (getASTContext()) OMPUpdateClause(StartLoc, EndLoc);
18957}
18958
18959OMPClause *SemaOpenMP::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
18960 SourceLocation EndLoc) {
18961 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
18962}
18963
18964OMPClause *SemaOpenMP::ActOnOpenMPCompareClause(SourceLocation StartLoc,
18965 SourceLocation EndLoc) {
18966 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
18967}
18968
18969OMPClause *SemaOpenMP::ActOnOpenMPFailClause(SourceLocation StartLoc,
18970 SourceLocation EndLoc) {
18971 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
18972}
18973
18974OMPClause *SemaOpenMP::ActOnOpenMPFailClause(OpenMPClauseKind Parameter,
18975 SourceLocation KindLoc,
18976 SourceLocation StartLoc,
18977 SourceLocation LParenLoc,
18978 SourceLocation EndLoc) {
18979
18980 if (!checkFailClauseParameter(FailClauseParameter: Parameter)) {
18981 Diag(Loc: KindLoc, DiagID: diag::err_omp_atomic_fail_wrong_or_no_clauses);
18982 return nullptr;
18983 }
18984 return new (getASTContext())
18985 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
18986}
18987
18988OMPClause *SemaOpenMP::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
18989 SourceLocation EndLoc) {
18990 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
18991}
18992
18993OMPClause *SemaOpenMP::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
18994 SourceLocation EndLoc) {
18995 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
18996}
18997
18998OMPClause *SemaOpenMP::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
18999 SourceLocation EndLoc) {
19000 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
19001}
19002
19003OMPClause *SemaOpenMP::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
19004 SourceLocation EndLoc) {
19005 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
19006}
19007
19008OMPClause *SemaOpenMP::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
19009 SourceLocation EndLoc) {
19010 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
19011}
19012
19013OMPClause *SemaOpenMP::ActOnOpenMPWeakClause(SourceLocation StartLoc,
19014 SourceLocation EndLoc) {
19015 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
19016}
19017
19018OMPClause *SemaOpenMP::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
19019 SourceLocation EndLoc) {
19020 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
19021}
19022
19023OMPClause *SemaOpenMP::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
19024 SourceLocation EndLoc) {
19025 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
19026}
19027
19028OMPClause *SemaOpenMP::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
19029 SourceLocation EndLoc) {
19030 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
19031}
19032
19033OMPClause *SemaOpenMP::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
19034 SourceLocation EndLoc) {
19035 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
19036}
19037
19038OMPClause *
19039SemaOpenMP::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
19040 SourceLocation EndLoc) {
19041 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
19042}
19043
19044OMPClause *SemaOpenMP::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
19045 SourceLocation EndLoc) {
19046 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
19047}
19048
19049OMPClause *
19050SemaOpenMP::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
19051 SourceLocation EndLoc) {
19052 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
19053}
19054
19055OMPClause *SemaOpenMP::ActOnOpenMPSelfMapsClause(SourceLocation StartLoc,
19056 SourceLocation EndLoc) {
19057 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
19058}
19059
19060StmtResult
19061SemaOpenMP::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
19062 SourceLocation StartLoc,
19063 SourceLocation EndLoc) {
19064
19065 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
19066 // At least one action-clause must appear on a directive.
19067 if (!hasClauses(Clauses, K: OMPC_init, ClauseTypes: OMPC_use, ClauseTypes: OMPC_destroy, ClauseTypes: OMPC_nowait)) {
19068 unsigned OMPVersion = getLangOpts().OpenMP;
19069 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
19070 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
19071 << Expected << getOpenMPDirectiveName(D: OMPD_interop, Ver: OMPVersion);
19072 return StmtError();
19073 }
19074
19075 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
19076 // A depend clause can only appear on the directive if a targetsync
19077 // interop-type is present or the interop-var was initialized with
19078 // the targetsync interop-type.
19079
19080 // If there is any 'init' clause diagnose if there is no 'init' clause with
19081 // interop-type of 'targetsync'. Cases involving other directives cannot be
19082 // diagnosed.
19083 const OMPDependClause *DependClause = nullptr;
19084 bool HasInitClause = false;
19085 bool IsTargetSync = false;
19086 for (const OMPClause *C : Clauses) {
19087 if (IsTargetSync)
19088 break;
19089 if (const auto *InitClause = dyn_cast<OMPInitClause>(Val: C)) {
19090 HasInitClause = true;
19091 if (InitClause->getIsTargetSync())
19092 IsTargetSync = true;
19093 } else if (const auto *DC = dyn_cast<OMPDependClause>(Val: C)) {
19094 DependClause = DC;
19095 }
19096 }
19097 if (DependClause && HasInitClause && !IsTargetSync) {
19098 Diag(Loc: DependClause->getBeginLoc(), DiagID: diag::err_omp_interop_bad_depend_clause);
19099 return StmtError();
19100 }
19101
19102 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
19103 // Each interop-var may be specified for at most one action-clause of each
19104 // interop construct.
19105 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
19106 for (OMPClause *C : Clauses) {
19107 OpenMPClauseKind ClauseKind = C->getClauseKind();
19108 std::pair<ValueDecl *, bool> DeclResult;
19109 SourceLocation ELoc;
19110 SourceRange ERange;
19111
19112 if (ClauseKind == OMPC_init) {
19113 auto *E = cast<OMPInitClause>(Val: C)->getInteropVar();
19114 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
19115 } else if (ClauseKind == OMPC_use) {
19116 auto *E = cast<OMPUseClause>(Val: C)->getInteropVar();
19117 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
19118 } else if (ClauseKind == OMPC_destroy) {
19119 auto *E = cast<OMPDestroyClause>(Val: C)->getInteropVar();
19120 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
19121 }
19122
19123 if (DeclResult.first) {
19124 if (!InteropVars.insert(Ptr: DeclResult.first).second) {
19125 Diag(Loc: ELoc, DiagID: diag::err_omp_interop_var_multiple_actions)
19126 << DeclResult.first;
19127 return StmtError();
19128 }
19129 }
19130 }
19131
19132 return OMPInteropDirective::Create(C: getASTContext(), StartLoc, EndLoc,
19133 Clauses);
19134}
19135
19136static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
19137 SourceLocation VarLoc,
19138 OpenMPClauseKind Kind) {
19139 SourceLocation ELoc;
19140 SourceRange ERange;
19141 Expr *RefExpr = InteropVarExpr;
19142 auto Res = getPrivateItem(S&: SemaRef, RefExpr, ELoc, ERange,
19143 /*AllowArraySection=*/false,
19144 /*AllowAssumedSizeArray=*/false,
19145 /*DiagType=*/"omp_interop_t");
19146
19147 if (Res.second) {
19148 // It will be analyzed later.
19149 return true;
19150 }
19151
19152 if (!Res.first)
19153 return false;
19154
19155 // Interop variable should be of type omp_interop_t.
19156 bool HasError = false;
19157 QualType InteropType;
19158 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get(Name: "omp_interop_t"),
19159 VarLoc, Sema::LookupOrdinaryName);
19160 if (SemaRef.LookupName(R&: Result, S: SemaRef.getCurScope())) {
19161 NamedDecl *ND = Result.getFoundDecl();
19162 if (const auto *TD = dyn_cast<TypeDecl>(Val: ND)) {
19163 InteropType = QualType(TD->getTypeForDecl(), 0);
19164 } else {
19165 HasError = true;
19166 }
19167 } else {
19168 HasError = true;
19169 }
19170
19171 if (HasError) {
19172 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_implied_type_not_found)
19173 << "omp_interop_t";
19174 return false;
19175 }
19176
19177 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
19178 if (!SemaRef.Context.hasSameType(T1: InteropType, T2: VarType)) {
19179 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_interop_variable_wrong_type);
19180 return false;
19181 }
19182
19183 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
19184 // The interop-var passed to init or destroy must be non-const.
19185 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
19186 isConstNotMutableType(SemaRef, Type: InteropVarExpr->getType())) {
19187 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_interop_variable_expected)
19188 << /*non-const*/ 1;
19189 return false;
19190 }
19191 return true;
19192}
19193
19194OMPClause *SemaOpenMP::ActOnOpenMPInitClause(
19195 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
19196 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
19197
19198 if (!isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_init))
19199 return nullptr;
19200
19201 if (!checkPreferTypeArgs(S&: *this, Info: InteropInfo))
19202 return nullptr;
19203
19204 return OMPInitClause::Create(C: getASTContext(), InteropVar, InteropInfo,
19205 StartLoc, LParenLoc, VarLoc, EndLoc);
19206}
19207
19208OMPClause *SemaOpenMP::ActOnOpenMPUseClause(Expr *InteropVar,
19209 SourceLocation StartLoc,
19210 SourceLocation LParenLoc,
19211 SourceLocation VarLoc,
19212 SourceLocation EndLoc) {
19213
19214 if (!isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_use))
19215 return nullptr;
19216
19217 return new (getASTContext())
19218 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
19219}
19220
19221OMPClause *SemaOpenMP::ActOnOpenMPDestroyClause(Expr *InteropVar,
19222 SourceLocation StartLoc,
19223 SourceLocation LParenLoc,
19224 SourceLocation VarLoc,
19225 SourceLocation EndLoc) {
19226 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
19227 DSAStack->getCurrentDirective() == OMPD_depobj) {
19228 unsigned OMPVersion = getLangOpts().OpenMP;
19229 Diag(Loc: StartLoc, DiagID: diag::err_omp_expected_clause_argument)
19230 << getOpenMPClauseNameForDiag(C: OMPC_destroy)
19231 << getOpenMPDirectiveName(D: OMPD_depobj, Ver: OMPVersion);
19232 return nullptr;
19233 }
19234 if (InteropVar &&
19235 !isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_destroy))
19236 return nullptr;
19237
19238 return new (getASTContext())
19239 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
19240}
19241
19242OMPClause *SemaOpenMP::ActOnOpenMPNovariantsClause(Expr *Condition,
19243 SourceLocation StartLoc,
19244 SourceLocation LParenLoc,
19245 SourceLocation EndLoc) {
19246 Expr *ValExpr = Condition;
19247 Stmt *HelperValStmt = nullptr;
19248 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
19249 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
19250 !Condition->isInstantiationDependent() &&
19251 !Condition->containsUnexpandedParameterPack()) {
19252 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
19253 if (Val.isInvalid())
19254 return nullptr;
19255
19256 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
19257
19258 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19259 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_novariants,
19260 OpenMPVersion: getLangOpts().OpenMP);
19261 if (CaptureRegion != OMPD_unknown &&
19262 !SemaRef.CurContext->isDependentContext()) {
19263 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
19264 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19265 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
19266 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
19267 }
19268 }
19269
19270 return new (getASTContext()) OMPNovariantsClause(
19271 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19272}
19273
19274OMPClause *SemaOpenMP::ActOnOpenMPNocontextClause(Expr *Condition,
19275 SourceLocation StartLoc,
19276 SourceLocation LParenLoc,
19277 SourceLocation EndLoc) {
19278 Expr *ValExpr = Condition;
19279 Stmt *HelperValStmt = nullptr;
19280 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
19281 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
19282 !Condition->isInstantiationDependent() &&
19283 !Condition->containsUnexpandedParameterPack()) {
19284 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
19285 if (Val.isInvalid())
19286 return nullptr;
19287
19288 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
19289
19290 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19291 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_nocontext,
19292 OpenMPVersion: getLangOpts().OpenMP);
19293 if (CaptureRegion != OMPD_unknown &&
19294 !SemaRef.CurContext->isDependentContext()) {
19295 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
19296 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19297 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
19298 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
19299 }
19300 }
19301
19302 return new (getASTContext()) OMPNocontextClause(
19303 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19304}
19305
19306OMPClause *SemaOpenMP::ActOnOpenMPFilterClause(Expr *ThreadID,
19307 SourceLocation StartLoc,
19308 SourceLocation LParenLoc,
19309 SourceLocation EndLoc) {
19310 Expr *ValExpr = ThreadID;
19311 Stmt *HelperValStmt = nullptr;
19312
19313 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19314 OpenMPDirectiveKind CaptureRegion =
19315 getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_filter, OpenMPVersion: getLangOpts().OpenMP);
19316 if (CaptureRegion != OMPD_unknown &&
19317 !SemaRef.CurContext->isDependentContext()) {
19318 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
19319 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19320 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
19321 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
19322 }
19323
19324 return new (getASTContext()) OMPFilterClause(
19325 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19326}
19327
19328OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
19329 ArrayRef<Expr *> VarList,
19330 const OMPVarListLocTy &Locs,
19331 OpenMPVarListDataTy &Data) {
19332 SourceLocation StartLoc = Locs.StartLoc;
19333 SourceLocation LParenLoc = Locs.LParenLoc;
19334 SourceLocation EndLoc = Locs.EndLoc;
19335 OMPClause *Res = nullptr;
19336 int ExtraModifier = Data.ExtraModifier;
19337 int OriginalSharingModifier = Data.OriginalSharingModifier;
19338 Expr *ExtraModifierExpr = Data.ExtraModifierExpr;
19339 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
19340 SourceLocation ColonLoc = Data.ColonLoc;
19341 switch (Kind) {
19342 case OMPC_private:
19343 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
19344 break;
19345 case OMPC_firstprivate:
19346 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
19347 break;
19348 case OMPC_lastprivate:
19349 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
19350 "Unexpected lastprivate modifier.");
19351 Res = ActOnOpenMPLastprivateClause(
19352 VarList, LPKind: static_cast<OpenMPLastprivateModifier>(ExtraModifier),
19353 LPKindLoc: ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
19354 break;
19355 case OMPC_shared:
19356 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
19357 break;
19358 case OMPC_reduction:
19359 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
19360 "Unexpected lastprivate modifier.");
19361 Res = ActOnOpenMPReductionClause(
19362 VarList,
19363 Modifiers: OpenMPVarListDataTy::OpenMPReductionClauseModifiers(
19364 ExtraModifier, OriginalSharingModifier),
19365 StartLoc, LParenLoc, ModifierLoc: ExtraModifierLoc, ColonLoc, EndLoc,
19366 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
19367 break;
19368 case OMPC_task_reduction:
19369 Res = ActOnOpenMPTaskReductionClause(
19370 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
19371 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
19372 break;
19373 case OMPC_in_reduction:
19374 Res = ActOnOpenMPInReductionClause(
19375 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
19376 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
19377 break;
19378 case OMPC_linear:
19379 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
19380 "Unexpected linear modifier.");
19381 Res = ActOnOpenMPLinearClause(
19382 VarList, Step: Data.DepModOrTailExpr, StartLoc, LParenLoc,
19383 LinKind: static_cast<OpenMPLinearClauseKind>(ExtraModifier), LinLoc: ExtraModifierLoc,
19384 ColonLoc, StepModifierLoc: Data.StepModifierLoc, EndLoc);
19385 break;
19386 case OMPC_aligned:
19387 Res = ActOnOpenMPAlignedClause(VarList, Alignment: Data.DepModOrTailExpr, StartLoc,
19388 LParenLoc, ColonLoc, EndLoc);
19389 break;
19390 case OMPC_copyin:
19391 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
19392 break;
19393 case OMPC_copyprivate:
19394 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
19395 break;
19396 case OMPC_flush:
19397 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
19398 break;
19399 case OMPC_depend:
19400 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
19401 "Unexpected depend modifier.");
19402 Res = ActOnOpenMPDependClause(
19403 Data: {.DepKind: static_cast<OpenMPDependClauseKind>(ExtraModifier), .DepLoc: ExtraModifierLoc,
19404 .ColonLoc: ColonLoc, .OmpAllMemoryLoc: Data.OmpAllMemoryLoc},
19405 DepModifier: Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
19406 break;
19407 case OMPC_map:
19408 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
19409 "Unexpected map modifier.");
19410 Res = ActOnOpenMPMapClause(
19411 IteratorModifier: Data.IteratorExpr, MapTypeModifiers: Data.MapTypeModifiers, MapTypeModifiersLoc: Data.MapTypeModifiersLoc,
19412 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId,
19413 MapType: static_cast<OpenMPMapClauseKind>(ExtraModifier), IsMapTypeImplicit: Data.IsMapTypeImplicit,
19414 MapLoc: ExtraModifierLoc, ColonLoc, VarList, Locs);
19415 break;
19416 case OMPC_to:
19417 Res = ActOnOpenMPToClause(
19418 MotionModifiers: Data.MotionModifiers, MotionModifiersLoc: Data.MotionModifiersLoc, IteratorModifier: Data.IteratorExpr,
19419 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId, ColonLoc,
19420 VarList, Locs);
19421 break;
19422 case OMPC_from:
19423 Res = ActOnOpenMPFromClause(
19424 MotionModifiers: Data.MotionModifiers, MotionModifiersLoc: Data.MotionModifiersLoc, IteratorModifier: Data.IteratorExpr,
19425 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId, ColonLoc,
19426 VarList, Locs);
19427 break;
19428 case OMPC_use_device_ptr:
19429 assert(0 <= Data.ExtraModifier &&
19430 Data.ExtraModifier <= OMPC_USE_DEVICE_PTR_FALLBACK_unknown &&
19431 "Unexpected use_device_ptr fallback modifier.");
19432 Res = ActOnOpenMPUseDevicePtrClause(
19433 VarList, Locs,
19434 FallbackModifier: static_cast<OpenMPUseDevicePtrFallbackModifier>(Data.ExtraModifier),
19435 FallbackModifierLoc: Data.ExtraModifierLoc);
19436 break;
19437 case OMPC_use_device_addr:
19438 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
19439 break;
19440 case OMPC_is_device_ptr:
19441 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
19442 break;
19443 case OMPC_has_device_addr:
19444 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
19445 break;
19446 case OMPC_allocate: {
19447 OpenMPAllocateClauseModifier Modifier1 = OMPC_ALLOCATE_unknown;
19448 OpenMPAllocateClauseModifier Modifier2 = OMPC_ALLOCATE_unknown;
19449 SourceLocation Modifier1Loc, Modifier2Loc;
19450 if (!Data.AllocClauseModifiers.empty()) {
19451 assert(Data.AllocClauseModifiers.size() <= 2 &&
19452 "More allocate modifiers than expected");
19453 Modifier1 = Data.AllocClauseModifiers[0];
19454 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
19455 if (Data.AllocClauseModifiers.size() == 2) {
19456 Modifier2 = Data.AllocClauseModifiers[1];
19457 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
19458 }
19459 }
19460 Res = ActOnOpenMPAllocateClause(
19461 Allocator: Data.DepModOrTailExpr, Alignment: Data.AllocateAlignment, FirstModifier: Modifier1, FirstModifierLoc: Modifier1Loc,
19462 SecondModifier: Modifier2, SecondModifierLoc: Modifier2Loc, VarList, StartLoc, ColonLoc: LParenLoc, LParenLoc: ColonLoc,
19463 EndLoc);
19464 break;
19465 }
19466 case OMPC_nontemporal:
19467 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
19468 break;
19469 case OMPC_inclusive:
19470 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
19471 break;
19472 case OMPC_exclusive:
19473 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
19474 break;
19475 case OMPC_affinity:
19476 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
19477 Modifier: Data.DepModOrTailExpr, Locators: VarList);
19478 break;
19479 case OMPC_doacross:
19480 Res = ActOnOpenMPDoacrossClause(
19481 DepType: static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
19482 DepLoc: ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
19483 break;
19484 case OMPC_num_teams:
19485 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_NUMTEAMS_unknown &&
19486 "Unexpected num_teams modifier.");
19487 Res = ActOnOpenMPNumTeamsClause(
19488 VarList,
19489 Modifier: static_cast<OpenMPNumTeamsClauseModifier>(Data.ExtraModifierArray[0]),
19490 ModifierExpr: Data.ExtraModifierExprArray[0], ModifierLoc: Data.ExtraModifierLocArray[0],
19491 ModifierExtra: static_cast<OpenMPNumTeamsClauseModifier>(Data.ExtraModifierArray[1]),
19492 ModifierExtraExpr: Data.ExtraModifierExprArray[1], ModifierExtraLoc: Data.ExtraModifierLocArray[1], StartLoc,
19493 LParenLoc, EndLoc);
19494 break;
19495 case OMPC_thread_limit:
19496 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_THREADLIMIT_unknown &&
19497 "Unexpected thread_limit modifier.");
19498 Res = ActOnOpenMPThreadLimitClause(
19499 VarList, Modifier: static_cast<OpenMPThreadLimitClauseModifier>(ExtraModifier),
19500 ModifierExpr: ExtraModifierExpr, ModifierLoc: ExtraModifierLoc, StartLoc, LParenLoc, EndLoc);
19501 break;
19502 case OMPC_num_threads:
19503 assert(0 <= Data.ExtraModifierArray[0] &&
19504 Data.ExtraModifierArray[0] <= OMPC_NUMTHREADS_unknown &&
19505 0 <= Data.ExtraModifierArray[1] &&
19506 Data.ExtraModifierArray[1] <= OMPC_NUMTHREADS_unknown &&
19507 "Unexpected num_threads modifier.");
19508 Res = ActOnOpenMPNumThreadsClause(
19509 VarList,
19510 SimpleModifier: static_cast<OpenMPNumThreadsClauseModifier>(Data.ExtraModifierArray[0]),
19511 SimpleModifierLoc: Data.ExtraModifierLocArray[0],
19512 ComplexModifier: static_cast<OpenMPNumThreadsClauseModifier>(Data.ExtraModifierArray[1]),
19513 ComplexModifierExpr: Data.ExtraModifierExprArray[1], ComplexModifierLoc: Data.ExtraModifierLocArray[1], StartLoc,
19514 LParenLoc, EndLoc);
19515 break;
19516 case OMPC_if:
19517 case OMPC_depobj:
19518 case OMPC_final:
19519 case OMPC_safelen:
19520 case OMPC_simdlen:
19521 case OMPC_sizes:
19522 case OMPC_allocator:
19523 case OMPC_collapse:
19524 case OMPC_default:
19525 case OMPC_proc_bind:
19526 case OMPC_schedule:
19527 case OMPC_ordered:
19528 case OMPC_nowait:
19529 case OMPC_untied:
19530 case OMPC_mergeable:
19531 case OMPC_threadprivate:
19532 case OMPC_groupprivate:
19533 case OMPC_read:
19534 case OMPC_write:
19535 case OMPC_update:
19536 case OMPC_capture:
19537 case OMPC_compare:
19538 case OMPC_seq_cst:
19539 case OMPC_acq_rel:
19540 case OMPC_acquire:
19541 case OMPC_release:
19542 case OMPC_relaxed:
19543 case OMPC_device:
19544 case OMPC_threads:
19545 case OMPC_simd:
19546 case OMPC_priority:
19547 case OMPC_grainsize:
19548 case OMPC_nogroup:
19549 case OMPC_num_tasks:
19550 case OMPC_hint:
19551 case OMPC_dist_schedule:
19552 case OMPC_defaultmap:
19553 case OMPC_unknown:
19554 case OMPC_uniform:
19555 case OMPC_unified_address:
19556 case OMPC_unified_shared_memory:
19557 case OMPC_reverse_offload:
19558 case OMPC_dynamic_allocators:
19559 case OMPC_atomic_default_mem_order:
19560 case OMPC_self_maps:
19561 case OMPC_device_type:
19562 case OMPC_match:
19563 case OMPC_order:
19564 case OMPC_at:
19565 case OMPC_severity:
19566 case OMPC_message:
19567 case OMPC_destroy:
19568 case OMPC_novariants:
19569 case OMPC_nocontext:
19570 case OMPC_detach:
19571 case OMPC_uses_allocators:
19572 case OMPC_when:
19573 case OMPC_bind:
19574 default:
19575 llvm_unreachable("Clause is not allowed.");
19576 }
19577 return Res;
19578}
19579
19580ExprResult SemaOpenMP::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
19581 ExprObjectKind OK,
19582 SourceLocation Loc) {
19583 ExprResult Res = SemaRef.BuildDeclRefExpr(
19584 D: Capture, Ty: Capture->getType().getNonReferenceType(), VK: VK_LValue, Loc);
19585 if (!Res.isUsable())
19586 return ExprError();
19587 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
19588 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: Loc, Opc: UO_Deref, InputExpr: Res.get());
19589 if (!Res.isUsable())
19590 return ExprError();
19591 }
19592 if (VK != VK_LValue && Res.get()->isGLValue()) {
19593 Res = SemaRef.DefaultLvalueConversion(E: Res.get());
19594 if (!Res.isUsable())
19595 return ExprError();
19596 }
19597 return Res;
19598}
19599
19600OMPClause *SemaOpenMP::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
19601 SourceLocation StartLoc,
19602 SourceLocation LParenLoc,
19603 SourceLocation EndLoc) {
19604 SmallVector<Expr *, 8> Vars;
19605 SmallVector<Expr *, 8> PrivateCopies;
19606 unsigned OMPVersion = getLangOpts().OpenMP;
19607 bool IsImplicitClause =
19608 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
19609 for (Expr *RefExpr : VarList) {
19610 assert(RefExpr && "NULL expr in OpenMP private clause.");
19611 SourceLocation ELoc;
19612 SourceRange ERange;
19613 Expr *SimpleRefExpr = RefExpr;
19614 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
19615 if (Res.second) {
19616 // It will be analyzed later.
19617 Vars.push_back(Elt: RefExpr);
19618 PrivateCopies.push_back(Elt: nullptr);
19619 }
19620 ValueDecl *D = Res.first;
19621 if (!D)
19622 continue;
19623
19624 QualType Type = D->getType();
19625 auto *VD = dyn_cast<VarDecl>(Val: D);
19626
19627 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19628 // A variable that appears in a private clause must not have an incomplete
19629 // type or a reference type.
19630 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
19631 DiagID: diag::err_omp_private_incomplete_type))
19632 continue;
19633 Type = Type.getNonReferenceType();
19634
19635 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19636 // A variable that is privatized must not have a const-qualified type
19637 // unless it is of class type with a mutable member. This restriction does
19638 // not apply to the firstprivate clause.
19639 //
19640 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
19641 // A variable that appears in a private clause must not have a
19642 // const-qualified type unless it is of class type with a mutable member.
19643 if (rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_private, ELoc))
19644 continue;
19645
19646 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19647 // in a Construct]
19648 // Variables with the predetermined data-sharing attributes may not be
19649 // listed in data-sharing attributes clauses, except for the cases
19650 // listed below. For these exceptions only, listing a predetermined
19651 // variable in a data-sharing attribute clause is allowed and overrides
19652 // the variable's predetermined data-sharing attributes.
19653 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19654 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
19655 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
19656 << getOpenMPClauseNameForDiag(C: DVar.CKind)
19657 << getOpenMPClauseNameForDiag(C: OMPC_private);
19658 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19659 continue;
19660 }
19661
19662 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19663 // Variably modified types are not supported for tasks.
19664 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
19665 isOpenMPTaskingDirective(Kind: CurrDir)) {
19666 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
19667 << getOpenMPClauseNameForDiag(C: OMPC_private) << Type
19668 << getOpenMPDirectiveName(D: CurrDir, Ver: OMPVersion);
19669 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19670 VarDecl::DeclarationOnly;
19671 Diag(Loc: D->getLocation(),
19672 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19673 << D;
19674 continue;
19675 }
19676
19677 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19678 // A list item cannot appear in both a map clause and a data-sharing
19679 // attribute clause on the same construct
19680 //
19681 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19682 // A list item cannot appear in both a map clause and a data-sharing
19683 // attribute clause on the same construct unless the construct is a
19684 // combined construct.
19685 if ((getLangOpts().OpenMP <= 45 &&
19686 isOpenMPTargetExecutionDirective(DKind: CurrDir)) ||
19687 CurrDir == OMPD_target) {
19688 OpenMPClauseKind ConflictKind;
19689 if (DSAStack->checkMappableExprComponentListsForDecl(
19690 VD, /*CurrentRegionOnly=*/true,
19691 Check: [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
19692 OpenMPClauseKind WhereFoundClauseKind) -> bool {
19693 ConflictKind = WhereFoundClauseKind;
19694 return true;
19695 })) {
19696 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
19697 << getOpenMPClauseNameForDiag(C: OMPC_private)
19698 << getOpenMPClauseNameForDiag(C: ConflictKind)
19699 << getOpenMPDirectiveName(D: CurrDir, Ver: OMPVersion);
19700 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19701 continue;
19702 }
19703 }
19704
19705 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
19706 // A variable of class type (or array thereof) that appears in a private
19707 // clause requires an accessible, unambiguous default constructor for the
19708 // class type.
19709 // Generate helper private variable and initialize it with the default
19710 // value. The address of the original variable is replaced by the address of
19711 // the new private variable in CodeGen. This new variable is not added to
19712 // IdResolver, so the code in the OpenMP region uses original variable for
19713 // proper diagnostics.
19714 Type = Type.getUnqualifiedType();
19715 VarDecl *VDPrivate =
19716 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
19717 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
19718 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
19719 SemaRef.ActOnUninitializedDecl(dcl: VDPrivate);
19720 if (VDPrivate->isInvalidDecl())
19721 continue;
19722 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19723 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(), Loc: ELoc);
19724
19725 DeclRefExpr *Ref = nullptr;
19726 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19727 auto *FD = dyn_cast<FieldDecl>(Val: D);
19728 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19729 if (VD)
19730 Ref = buildDeclRefExpr(S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(),
19731 Loc: RefExpr->getExprLoc());
19732 else
19733 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
19734 }
19735 if (!IsImplicitClause)
19736 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_private, PrivateCopy: Ref);
19737 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
19738 ? RefExpr->IgnoreParens()
19739 : Ref);
19740 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
19741 }
19742
19743 if (Vars.empty())
19744 return nullptr;
19745
19746 return OMPPrivateClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
19747 VL: Vars, PrivateVL: PrivateCopies);
19748}
19749
19750OMPClause *SemaOpenMP::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
19751 SourceLocation StartLoc,
19752 SourceLocation LParenLoc,
19753 SourceLocation EndLoc) {
19754 SmallVector<Expr *, 8> Vars;
19755 SmallVector<Expr *, 8> PrivateCopies;
19756 SmallVector<Expr *, 8> Inits;
19757 SmallVector<Decl *, 4> ExprCaptures;
19758 bool IsImplicitClause =
19759 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
19760 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
19761 unsigned OMPVersion = getLangOpts().OpenMP;
19762
19763 for (Expr *RefExpr : VarList) {
19764 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
19765 SourceLocation ELoc;
19766 SourceRange ERange;
19767 Expr *SimpleRefExpr = RefExpr;
19768 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
19769 if (Res.second) {
19770 // It will be analyzed later.
19771 Vars.push_back(Elt: RefExpr);
19772 PrivateCopies.push_back(Elt: nullptr);
19773 Inits.push_back(Elt: nullptr);
19774 }
19775 ValueDecl *D = Res.first;
19776 if (!D)
19777 continue;
19778
19779 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
19780 QualType Type = D->getType();
19781 auto *VD = dyn_cast<VarDecl>(Val: D);
19782
19783 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19784 // A variable that appears in a private clause must not have an incomplete
19785 // type or a reference type.
19786 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
19787 DiagID: diag::err_omp_firstprivate_incomplete_type))
19788 continue;
19789 Type = Type.getNonReferenceType();
19790
19791 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
19792 // A variable of class type (or array thereof) that appears in a private
19793 // clause requires an accessible, unambiguous copy constructor for the
19794 // class type.
19795 QualType ElemType =
19796 getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
19797
19798 // If an implicit firstprivate variable found it was checked already.
19799 DSAStackTy::DSAVarData TopDVar;
19800 if (!IsImplicitClause) {
19801 DSAStackTy::DSAVarData DVar =
19802 DSAStack->getTopDSA(D, /*FromParent=*/false);
19803 TopDVar = DVar;
19804 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19805 bool IsConstant = ElemType.isConstant(Ctx: getASTContext());
19806 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
19807 // A list item that specifies a given variable may not appear in more
19808 // than one clause on the same directive, except that a variable may be
19809 // specified in both firstprivate and lastprivate clauses.
19810 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19811 // A list item may appear in a firstprivate or lastprivate clause but not
19812 // both.
19813 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
19814 (isOpenMPDistributeDirective(DKind: CurrDir) ||
19815 DVar.CKind != OMPC_lastprivate) &&
19816 DVar.RefExpr) {
19817 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
19818 << getOpenMPClauseNameForDiag(C: DVar.CKind)
19819 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
19820 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19821 continue;
19822 }
19823
19824 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19825 // in a Construct]
19826 // Variables with the predetermined data-sharing attributes may not be
19827 // listed in data-sharing attributes clauses, except for the cases
19828 // listed below. For these exceptions only, listing a predetermined
19829 // variable in a data-sharing attribute clause is allowed and overrides
19830 // the variable's predetermined data-sharing attributes.
19831 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19832 // in a Construct, C/C++, p.2]
19833 // Variables with const-qualified type having no mutable member may be
19834 // listed in a firstprivate clause, even if they are static data members.
19835 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
19836 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
19837 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
19838 << getOpenMPClauseNameForDiag(C: DVar.CKind)
19839 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
19840 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19841 continue;
19842 }
19843
19844 // OpenMP [2.9.3.4, Restrictions, p.2]
19845 // A list item that is private within a parallel region must not appear
19846 // in a firstprivate clause on a worksharing construct if any of the
19847 // worksharing regions arising from the worksharing construct ever bind
19848 // to any of the parallel regions arising from the parallel construct.
19849 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19850 // A list item that is private within a teams region must not appear in a
19851 // firstprivate clause on a distribute construct if any of the distribute
19852 // regions arising from the distribute construct ever bind to any of the
19853 // teams regions arising from the teams construct.
19854 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19855 // A list item that appears in a reduction clause of a teams construct
19856 // must not appear in a firstprivate clause on a distribute construct if
19857 // any of the distribute regions arising from the distribute construct
19858 // ever bind to any of the teams regions arising from the teams construct.
19859 if ((isOpenMPWorksharingDirective(DKind: CurrDir) ||
19860 isOpenMPDistributeDirective(DKind: CurrDir)) &&
19861 !isOpenMPParallelDirective(DKind: CurrDir) &&
19862 !isOpenMPTeamsDirective(DKind: CurrDir)) {
19863 DVar = DSAStack->getImplicitDSA(D, FromParent: true);
19864 if (DVar.CKind != OMPC_shared &&
19865 (isOpenMPParallelDirective(DKind: DVar.DKind) ||
19866 isOpenMPTeamsDirective(DKind: DVar.DKind) ||
19867 DVar.DKind == OMPD_unknown)) {
19868 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
19869 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate)
19870 << getOpenMPClauseNameForDiag(C: OMPC_shared);
19871 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19872 continue;
19873 }
19874 }
19875 // OpenMP [2.9.3.4, Restrictions, p.3]
19876 // A list item that appears in a reduction clause of a parallel construct
19877 // must not appear in a firstprivate clause on a worksharing or task
19878 // construct if any of the worksharing or task regions arising from the
19879 // worksharing or task construct ever bind to any of the parallel regions
19880 // arising from the parallel construct.
19881 // OpenMP [2.9.3.4, Restrictions, p.4]
19882 // A list item that appears in a reduction clause in worksharing
19883 // construct must not appear in a firstprivate clause in a task construct
19884 // encountered during execution of any of the worksharing regions arising
19885 // from the worksharing construct.
19886 if (isOpenMPTaskingDirective(Kind: CurrDir)) {
19887 DVar = DSAStack->hasInnermostDSA(
19888 D,
19889 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
19890 return C == OMPC_reduction && !AppliedToPointee;
19891 },
19892 DPred: [](OpenMPDirectiveKind K) {
19893 return isOpenMPParallelDirective(DKind: K) ||
19894 isOpenMPWorksharingDirective(DKind: K) ||
19895 isOpenMPTeamsDirective(DKind: K);
19896 },
19897 /*FromParent=*/true);
19898 if (DVar.CKind == OMPC_reduction &&
19899 (isOpenMPParallelDirective(DKind: DVar.DKind) ||
19900 isOpenMPWorksharingDirective(DKind: DVar.DKind) ||
19901 isOpenMPTeamsDirective(DKind: DVar.DKind))) {
19902 Diag(Loc: ELoc, DiagID: diag::err_omp_parallel_reduction_in_task_firstprivate)
19903 << getOpenMPDirectiveName(D: DVar.DKind, Ver: OMPVersion);
19904 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19905 continue;
19906 }
19907 }
19908
19909 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19910 // A list item cannot appear in both a map clause and a data-sharing
19911 // attribute clause on the same construct
19912 //
19913 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19914 // A list item cannot appear in both a map clause and a data-sharing
19915 // attribute clause on the same construct unless the construct is a
19916 // combined construct.
19917 if ((getLangOpts().OpenMP <= 45 &&
19918 isOpenMPTargetExecutionDirective(DKind: CurrDir)) ||
19919 CurrDir == OMPD_target) {
19920 OpenMPClauseKind ConflictKind;
19921 if (DSAStack->checkMappableExprComponentListsForDecl(
19922 VD, /*CurrentRegionOnly=*/true,
19923 Check: [&ConflictKind](
19924 OMPClauseMappableExprCommon::MappableExprComponentListRef,
19925 OpenMPClauseKind WhereFoundClauseKind) {
19926 ConflictKind = WhereFoundClauseKind;
19927 return true;
19928 })) {
19929 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
19930 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate)
19931 << getOpenMPClauseNameForDiag(C: ConflictKind)
19932 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19933 Ver: OMPVersion);
19934 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19935 continue;
19936 }
19937 }
19938 }
19939
19940 // Variably modified types are not supported for tasks.
19941 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
19942 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
19943 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
19944 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate) << Type
19945 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19946 Ver: OMPVersion);
19947 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19948 VarDecl::DeclarationOnly;
19949 Diag(Loc: D->getLocation(),
19950 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19951 << D;
19952 continue;
19953 }
19954
19955 Type = Type.getUnqualifiedType();
19956 VarDecl *VDPrivate =
19957 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
19958 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
19959 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
19960 // Generate helper private variable and initialize it with the value of the
19961 // original variable. The address of the original variable is replaced by
19962 // the address of the new private variable in the CodeGen. This new variable
19963 // is not added to IdResolver, so the code in the OpenMP region uses
19964 // original variable for proper diagnostics and variable capturing.
19965 Expr *VDInitRefExpr = nullptr;
19966 // For arrays generate initializer for single element and replace it by the
19967 // original array element in CodeGen.
19968 if (Type->isArrayType()) {
19969 VarDecl *VDInit =
19970 buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type: ElemType, Name: D->getName());
19971 VDInitRefExpr = buildDeclRefExpr(S&: SemaRef, D: VDInit, Ty: ElemType, Loc: ELoc);
19972 Expr *Init = SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get();
19973 ElemType = ElemType.getUnqualifiedType();
19974 VarDecl *VDInitTemp = buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(),
19975 Type: ElemType, Name: ".firstprivate.temp");
19976 InitializedEntity Entity =
19977 InitializedEntity::InitializeVariable(Var: VDInitTemp);
19978 InitializationKind Kind = InitializationKind::CreateCopy(InitLoc: ELoc, EqualLoc: ELoc);
19979
19980 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
19981 ExprResult Result = InitSeq.Perform(S&: SemaRef, Entity, Kind, Args: Init);
19982 if (Result.isInvalid())
19983 VDPrivate->setInvalidDecl();
19984 else
19985 VDPrivate->setInit(Result.getAs<Expr>());
19986 // Remove temp variable declaration.
19987 getASTContext().Deallocate(Ptr: VDInitTemp);
19988 } else {
19989 VarDecl *VDInit = buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type,
19990 Name: ".firstprivate.temp");
19991 VDInitRefExpr = buildDeclRefExpr(S&: SemaRef, D: VDInit, Ty: RefExpr->getType(),
19992 Loc: RefExpr->getExprLoc());
19993 SemaRef.AddInitializerToDecl(
19994 dcl: VDPrivate, init: SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get(),
19995 /*DirectInit=*/false);
19996 }
19997 if (VDPrivate->isInvalidDecl()) {
19998 if (IsImplicitClause) {
19999 Diag(Loc: RefExpr->getExprLoc(),
20000 DiagID: diag::note_omp_task_predetermined_firstprivate_here);
20001 }
20002 continue;
20003 }
20004 SemaRef.CurContext->addDecl(D: VDPrivate);
20005 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
20006 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(),
20007 Loc: RefExpr->getExprLoc());
20008 DeclRefExpr *Ref = nullptr;
20009 if (!VD && !SemaRef.CurContext->isDependentContext()) {
20010 if (TopDVar.CKind == OMPC_lastprivate) {
20011 Ref = TopDVar.PrivateCopy;
20012 } else {
20013 auto *FD = dyn_cast<FieldDecl>(Val: D);
20014 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
20015 if (VD)
20016 Ref =
20017 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(),
20018 Loc: RefExpr->getExprLoc());
20019 else
20020 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
20021 if (VD || !isOpenMPCapturedDecl(D))
20022 ExprCaptures.push_back(Elt: Ref->getDecl());
20023 }
20024 }
20025 if (!IsImplicitClause)
20026 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
20027 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
20028 ? RefExpr->IgnoreParens()
20029 : Ref);
20030 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
20031 Inits.push_back(Elt: VDInitRefExpr);
20032 }
20033
20034 if (Vars.empty())
20035 return nullptr;
20036
20037 return OMPFirstprivateClause::Create(
20038 C: getASTContext(), StartLoc, LParenLoc, EndLoc, VL: Vars, PrivateVL: PrivateCopies, InitVL: Inits,
20039 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures));
20040}
20041
20042OMPClause *SemaOpenMP::ActOnOpenMPLastprivateClause(
20043 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
20044 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
20045 SourceLocation LParenLoc, SourceLocation EndLoc) {
20046 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
20047 assert(ColonLoc.isValid() && "Colon location must be valid.");
20048 Diag(Loc: LPKindLoc, DiagID: diag::err_omp_unexpected_clause_value)
20049 << getListOfPossibleValues(K: OMPC_lastprivate, /*First=*/0,
20050 /*Last=*/OMPC_LASTPRIVATE_unknown)
20051 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate);
20052 return nullptr;
20053 }
20054
20055 SmallVector<Expr *, 8> Vars;
20056 SmallVector<Expr *, 8> SrcExprs;
20057 SmallVector<Expr *, 8> DstExprs;
20058 SmallVector<Expr *, 8> AssignmentOps;
20059 SmallVector<Decl *, 4> ExprCaptures;
20060 SmallVector<Expr *, 4> ExprPostUpdates;
20061 for (Expr *RefExpr : VarList) {
20062 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
20063 SourceLocation ELoc;
20064 SourceRange ERange;
20065 Expr *SimpleRefExpr = RefExpr;
20066 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
20067 if (Res.second) {
20068 // It will be analyzed later.
20069 Vars.push_back(Elt: RefExpr);
20070 SrcExprs.push_back(Elt: nullptr);
20071 DstExprs.push_back(Elt: nullptr);
20072 AssignmentOps.push_back(Elt: nullptr);
20073 }
20074 ValueDecl *D = Res.first;
20075 if (!D)
20076 continue;
20077
20078 QualType Type = D->getType();
20079 auto *VD = dyn_cast<VarDecl>(Val: D);
20080
20081 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
20082 // A variable that appears in a lastprivate clause must not have an
20083 // incomplete type or a reference type.
20084 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
20085 DiagID: diag::err_omp_lastprivate_incomplete_type))
20086 continue;
20087 Type = Type.getNonReferenceType();
20088
20089 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20090 // A variable that is privatized must not have a const-qualified type
20091 // unless it is of class type with a mutable member. This restriction does
20092 // not apply to the firstprivate clause.
20093 //
20094 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
20095 // A variable that appears in a lastprivate clause must not have a
20096 // const-qualified type unless it is of class type with a mutable member.
20097 if (rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_lastprivate, ELoc))
20098 continue;
20099
20100 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
20101 // A list item that appears in a lastprivate clause with the conditional
20102 // modifier must be a scalar variable.
20103 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
20104 Diag(Loc: ELoc, DiagID: diag::err_omp_lastprivate_conditional_non_scalar);
20105 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20106 VarDecl::DeclarationOnly;
20107 Diag(Loc: D->getLocation(),
20108 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20109 << D;
20110 continue;
20111 }
20112
20113 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
20114 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
20115 // in a Construct]
20116 // Variables with the predetermined data-sharing attributes may not be
20117 // listed in data-sharing attributes clauses, except for the cases
20118 // listed below.
20119 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
20120 // A list item may appear in a firstprivate or lastprivate clause but not
20121 // both.
20122 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20123 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
20124 (isOpenMPDistributeDirective(DKind: CurrDir) ||
20125 DVar.CKind != OMPC_firstprivate) &&
20126 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
20127 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
20128 << getOpenMPClauseNameForDiag(C: DVar.CKind)
20129 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate);
20130 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20131 continue;
20132 }
20133
20134 // OpenMP [2.14.3.5, Restrictions, p.2]
20135 // A list item that is private within a parallel region, or that appears in
20136 // the reduction clause of a parallel construct, must not appear in a
20137 // lastprivate clause on a worksharing construct if any of the corresponding
20138 // worksharing regions ever binds to any of the corresponding parallel
20139 // regions.
20140 DSAStackTy::DSAVarData TopDVar = DVar;
20141 if (isOpenMPWorksharingDirective(DKind: CurrDir) &&
20142 !isOpenMPParallelDirective(DKind: CurrDir) &&
20143 !isOpenMPTeamsDirective(DKind: CurrDir)) {
20144 DVar = DSAStack->getImplicitDSA(D, FromParent: true);
20145 if (DVar.CKind != OMPC_shared) {
20146 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
20147 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate)
20148 << getOpenMPClauseNameForDiag(C: OMPC_shared);
20149 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20150 continue;
20151 }
20152 }
20153
20154 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
20155 // A variable of class type (or array thereof) that appears in a
20156 // lastprivate clause requires an accessible, unambiguous default
20157 // constructor for the class type, unless the list item is also specified
20158 // in a firstprivate clause.
20159 // A variable of class type (or array thereof) that appears in a
20160 // lastprivate clause requires an accessible, unambiguous copy assignment
20161 // operator for the class type.
20162 Type = getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
20163 VarDecl *SrcVD = buildVarDecl(SemaRef, Loc: ERange.getBegin(),
20164 Type: Type.getUnqualifiedType(), Name: ".lastprivate.src",
20165 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
20166 DeclRefExpr *PseudoSrcExpr =
20167 buildDeclRefExpr(S&: SemaRef, D: SrcVD, Ty: Type.getUnqualifiedType(), Loc: ELoc);
20168 VarDecl *DstVD =
20169 buildVarDecl(SemaRef, Loc: ERange.getBegin(), Type, Name: ".lastprivate.dst",
20170 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
20171 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: Type, Loc: ELoc);
20172 // For arrays generate assignment operation for single element and replace
20173 // it by the original array element in CodeGen.
20174 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, OpLoc: ELoc, Opc: BO_Assign,
20175 LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
20176 if (AssignmentOp.isInvalid())
20177 continue;
20178 AssignmentOp = SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: ELoc,
20179 /*DiscardedValue=*/false);
20180 if (AssignmentOp.isInvalid())
20181 continue;
20182
20183 DeclRefExpr *Ref = nullptr;
20184 if (!VD && !SemaRef.CurContext->isDependentContext()) {
20185 if (TopDVar.CKind == OMPC_firstprivate) {
20186 Ref = TopDVar.PrivateCopy;
20187 } else {
20188 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
20189 if (!isOpenMPCapturedDecl(D))
20190 ExprCaptures.push_back(Elt: Ref->getDecl());
20191 }
20192 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
20193 (!isOpenMPCapturedDecl(D) &&
20194 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
20195 ExprResult RefRes = SemaRef.DefaultLvalueConversion(E: Ref);
20196 if (!RefRes.isUsable())
20197 continue;
20198 ExprResult PostUpdateRes =
20199 SemaRef.BuildBinOp(DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign,
20200 LHSExpr: SimpleRefExpr, RHSExpr: RefRes.get());
20201 if (!PostUpdateRes.isUsable())
20202 continue;
20203 ExprPostUpdates.push_back(
20204 Elt: SemaRef.IgnoredValueConversions(E: PostUpdateRes.get()).get());
20205 }
20206 }
20207 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_lastprivate, PrivateCopy: Ref);
20208 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
20209 ? RefExpr->IgnoreParens()
20210 : Ref);
20211 SrcExprs.push_back(Elt: PseudoSrcExpr);
20212 DstExprs.push_back(Elt: PseudoDstExpr);
20213 AssignmentOps.push_back(Elt: AssignmentOp.get());
20214 }
20215
20216 if (Vars.empty())
20217 return nullptr;
20218
20219 return OMPLastprivateClause::Create(
20220 C: getASTContext(), StartLoc, LParenLoc, EndLoc, VL: Vars, SrcExprs, DstExprs,
20221 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
20222 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures),
20223 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: ExprPostUpdates));
20224}
20225
20226OMPClause *SemaOpenMP::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
20227 SourceLocation StartLoc,
20228 SourceLocation LParenLoc,
20229 SourceLocation EndLoc) {
20230 SmallVector<Expr *, 8> Vars;
20231 for (Expr *RefExpr : VarList) {
20232 assert(RefExpr && "NULL expr in OpenMP shared clause.");
20233 SourceLocation ELoc;
20234 SourceRange ERange;
20235 Expr *SimpleRefExpr = RefExpr;
20236 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
20237 if (Res.second) {
20238 // It will be analyzed later.
20239 Vars.push_back(Elt: RefExpr);
20240 }
20241 ValueDecl *D = Res.first;
20242 if (!D)
20243 continue;
20244
20245 auto *VD = dyn_cast<VarDecl>(Val: D);
20246 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
20247 // in a Construct]
20248 // Variables with the predetermined data-sharing attributes may not be
20249 // listed in data-sharing attributes clauses, except for the cases
20250 // listed below. For these exceptions only, listing a predetermined
20251 // variable in a data-sharing attribute clause is allowed and overrides
20252 // the variable's predetermined data-sharing attributes.
20253 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20254 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
20255 DVar.RefExpr) {
20256 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
20257 << getOpenMPClauseNameForDiag(C: DVar.CKind)
20258 << getOpenMPClauseNameForDiag(C: OMPC_shared);
20259 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20260 continue;
20261 }
20262
20263 DeclRefExpr *Ref = nullptr;
20264 if (!VD && isOpenMPCapturedDecl(D) &&
20265 !SemaRef.CurContext->isDependentContext())
20266 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
20267 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_shared, PrivateCopy: Ref);
20268 Vars.push_back(Elt: (VD || !Ref || SemaRef.CurContext->isDependentContext())
20269 ? RefExpr->IgnoreParens()
20270 : Ref);
20271 }
20272
20273 if (Vars.empty())
20274 return nullptr;
20275
20276 return OMPSharedClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
20277 VL: Vars);
20278}
20279
20280namespace {
20281class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
20282 DSAStackTy *Stack;
20283
20284public:
20285 bool VisitDeclRefExpr(DeclRefExpr *E) {
20286 if (auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
20287 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D: VD, /*FromParent=*/false);
20288 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
20289 return false;
20290 if (DVar.CKind != OMPC_unknown)
20291 return true;
20292 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
20293 D: VD,
20294 CPred: [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
20295 return isOpenMPPrivate(Kind: C) && !AppliedToPointee;
20296 },
20297 DPred: [](OpenMPDirectiveKind) { return true; },
20298 /*FromParent=*/true);
20299 return DVarPrivate.CKind != OMPC_unknown;
20300 }
20301 return false;
20302 }
20303 bool VisitStmt(Stmt *S) {
20304 for (Stmt *Child : S->children()) {
20305 if (Child && Visit(S: Child))
20306 return true;
20307 }
20308 return false;
20309 }
20310 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
20311};
20312} // namespace
20313
20314namespace {
20315// Transform MemberExpression for specified FieldDecl of current class to
20316// DeclRefExpr to specified OMPCapturedExprDecl.
20317class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
20318 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
20319 ValueDecl *Field = nullptr;
20320 DeclRefExpr *CapturedExpr = nullptr;
20321
20322public:
20323 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
20324 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
20325
20326 ExprResult TransformMemberExpr(MemberExpr *E) {
20327 if (isa<CXXThisExpr>(Val: E->getBase()->IgnoreParenImpCasts()) &&
20328 E->getMemberDecl() == Field) {
20329 CapturedExpr = buildCapture(S&: SemaRef, D: Field, CaptureExpr: E, /*WithInit=*/false);
20330 return CapturedExpr;
20331 }
20332 return BaseTransform::TransformMemberExpr(E);
20333 }
20334 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
20335};
20336} // namespace
20337
20338template <typename T, typename U>
20339static T filterLookupForUDReductionAndMapper(
20340 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
20341 for (U &Set : Lookups) {
20342 for (auto *D : Set) {
20343 if (T Res = Gen(cast<ValueDecl>(D)))
20344 return Res;
20345 }
20346 }
20347 return T();
20348}
20349
20350static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
20351 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
20352
20353 for (auto *RD : D->redecls()) {
20354 // Don't bother with extra checks if we already know this one isn't visible.
20355 if (RD == D)
20356 continue;
20357
20358 auto ND = cast<NamedDecl>(Val: RD);
20359 if (LookupResult::isVisible(SemaRef, D: ND))
20360 return ND;
20361 }
20362
20363 return nullptr;
20364}
20365
20366static void
20367argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
20368 SourceLocation Loc, QualType Ty,
20369 SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
20370 // Find all of the associated namespaces and classes based on the
20371 // arguments we have.
20372 Sema::AssociatedNamespaceSet AssociatedNamespaces;
20373 Sema::AssociatedClassSet AssociatedClasses;
20374 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
20375 SemaRef.FindAssociatedClassesAndNamespaces(InstantiationLoc: Loc, Args: &OVE, AssociatedNamespaces,
20376 AssociatedClasses);
20377
20378 // C++ [basic.lookup.argdep]p3:
20379 // Let X be the lookup set produced by unqualified lookup (3.4.1)
20380 // and let Y be the lookup set produced by argument dependent
20381 // lookup (defined as follows). If X contains [...] then Y is
20382 // empty. Otherwise Y is the set of declarations found in the
20383 // namespaces associated with the argument types as described
20384 // below. The set of declarations found by the lookup of the name
20385 // is the union of X and Y.
20386 //
20387 // Here, we compute Y and add its members to the overloaded
20388 // candidate set.
20389 for (auto *NS : AssociatedNamespaces) {
20390 // When considering an associated namespace, the lookup is the
20391 // same as the lookup performed when the associated namespace is
20392 // used as a qualifier (3.4.3.2) except that:
20393 //
20394 // -- Any using-directives in the associated namespace are
20395 // ignored.
20396 //
20397 // -- Any namespace-scope friend functions declared in
20398 // associated classes are visible within their respective
20399 // namespaces even if they are not visible during an ordinary
20400 // lookup (11.4).
20401 DeclContext::lookup_result R = NS->lookup(Name: Id.getName());
20402 for (auto *D : R) {
20403 auto *Underlying = D;
20404 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
20405 Underlying = USD->getTargetDecl();
20406
20407 if (!isa<OMPDeclareReductionDecl>(Val: Underlying) &&
20408 !isa<OMPDeclareMapperDecl>(Val: Underlying))
20409 continue;
20410
20411 if (!SemaRef.isVisible(D)) {
20412 D = findAcceptableDecl(SemaRef, D);
20413 if (!D)
20414 continue;
20415 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
20416 Underlying = USD->getTargetDecl();
20417 }
20418 Lookups.emplace_back();
20419 Lookups.back().addDecl(D: Underlying);
20420 }
20421 }
20422}
20423
20424static ExprResult
20425buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
20426 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
20427 const DeclarationNameInfo &ReductionId, QualType Ty,
20428 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
20429 if (ReductionIdScopeSpec.isInvalid())
20430 return ExprError();
20431 SmallVector<UnresolvedSet<8>, 4> Lookups;
20432 if (S) {
20433 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
20434 Lookup.suppressDiagnostics();
20435 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &ReductionIdScopeSpec,
20436 /*ObjectType=*/QualType())) {
20437 NamedDecl *D = Lookup.getRepresentativeDecl();
20438 do {
20439 S = S->getParent();
20440 } while (S && !S->isDeclScope(D));
20441 if (S)
20442 S = S->getParent();
20443 Lookups.emplace_back();
20444 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
20445 Lookup.clear();
20446 }
20447 } else if (auto *ULE =
20448 cast_or_null<UnresolvedLookupExpr>(Val: UnresolvedReduction)) {
20449 Lookups.push_back(Elt: UnresolvedSet<8>());
20450 Decl *PrevD = nullptr;
20451 for (NamedDecl *D : ULE->decls()) {
20452 if (D == PrevD)
20453 Lookups.push_back(Elt: UnresolvedSet<8>());
20454 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Val: D))
20455 Lookups.back().addDecl(D: DRD);
20456 PrevD = D;
20457 }
20458 }
20459 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
20460 Ty->isInstantiationDependentType() ||
20461 Ty->containsUnexpandedParameterPack() ||
20462 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
20463 return !D->isInvalidDecl() &&
20464 (D->getType()->isDependentType() ||
20465 D->getType()->isInstantiationDependentType() ||
20466 D->getType()->containsUnexpandedParameterPack());
20467 })) {
20468 UnresolvedSet<8> ResSet;
20469 for (const UnresolvedSet<8> &Set : Lookups) {
20470 if (Set.empty())
20471 continue;
20472 ResSet.append(I: Set.begin(), E: Set.end());
20473 // The last item marks the end of all declarations at the specified scope.
20474 ResSet.addDecl(D: Set[Set.size() - 1]);
20475 }
20476 return UnresolvedLookupExpr::Create(
20477 Context: SemaRef.Context, /*NamingClass=*/nullptr,
20478 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: SemaRef.Context), NameInfo: ReductionId,
20479 /*ADL=*/RequiresADL: true, Begin: ResSet.begin(), End: ResSet.end(), /*KnownDependent=*/false,
20480 /*KnownInstantiationDependent=*/false);
20481 }
20482 // Lookup inside the classes.
20483 // C++ [over.match.oper]p3:
20484 // For a unary operator @ with an operand of a type whose
20485 // cv-unqualified version is T1, and for a binary operator @ with
20486 // a left operand of a type whose cv-unqualified version is T1 and
20487 // a right operand of a type whose cv-unqualified version is T2,
20488 // three sets of candidate functions, designated member
20489 // candidates, non-member candidates and built-in candidates, are
20490 // constructed as follows:
20491 // -- If T1 is a complete class type or a class currently being
20492 // defined, the set of member candidates is the result of the
20493 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
20494 // the set of member candidates is empty.
20495 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
20496 Lookup.suppressDiagnostics();
20497 if (Ty->isRecordType()) {
20498 // Complete the type if it can be completed.
20499 // If the type is neither complete nor being defined, bail out now.
20500 bool IsComplete = SemaRef.isCompleteType(Loc, T: Ty);
20501 auto *RD = Ty->castAsRecordDecl();
20502 if (IsComplete || RD->isBeingDefined()) {
20503 Lookup.clear();
20504 SemaRef.LookupQualifiedName(R&: Lookup, LookupCtx: RD);
20505 if (Lookup.empty()) {
20506 Lookups.emplace_back();
20507 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
20508 }
20509 }
20510 }
20511 // Perform ADL.
20512 if (SemaRef.getLangOpts().CPlusPlus)
20513 argumentDependentLookup(SemaRef, Id: ReductionId, Loc, Ty, Lookups);
20514 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20515 Lookups, Gen: [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
20516 if (!D->isInvalidDecl() &&
20517 SemaRef.Context.hasSameType(T1: D->getType(), T2: Ty))
20518 return D;
20519 return nullptr;
20520 }))
20521 return SemaRef.BuildDeclRefExpr(D: VD, Ty: VD->getType().getNonReferenceType(),
20522 VK: VK_LValue, Loc);
20523 if (SemaRef.getLangOpts().CPlusPlus) {
20524 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20525 Lookups, Gen: [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
20526 if (!D->isInvalidDecl() &&
20527 SemaRef.IsDerivedFrom(Loc, Derived: Ty, Base: D->getType()) &&
20528 !Ty.isMoreQualifiedThan(other: D->getType(),
20529 Ctx: SemaRef.getASTContext()))
20530 return D;
20531 return nullptr;
20532 })) {
20533 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
20534 /*DetectVirtual=*/false);
20535 if (SemaRef.IsDerivedFrom(Loc, Derived: Ty, Base: VD->getType(), Paths)) {
20536 if (!Paths.isAmbiguous(BaseType: SemaRef.Context.getCanonicalType(
20537 T: VD->getType().getUnqualifiedType()))) {
20538 if (SemaRef.CheckBaseClassAccess(
20539 AccessLoc: Loc, Base: VD->getType(), Derived: Ty, Path: Paths.front(),
20540 /*DiagID=*/0) != Sema::AR_inaccessible) {
20541 SemaRef.BuildBasePathArray(Paths, BasePath);
20542 return SemaRef.BuildDeclRefExpr(
20543 D: VD, Ty: VD->getType().getNonReferenceType(), VK: VK_LValue, Loc);
20544 }
20545 }
20546 }
20547 }
20548 }
20549 if (ReductionIdScopeSpec.isSet()) {
20550 SemaRef.Diag(Loc, DiagID: diag::err_omp_not_resolved_reduction_identifier)
20551 << Ty << Range;
20552 return ExprError();
20553 }
20554 return ExprEmpty();
20555}
20556
20557namespace {
20558/// Data for the reduction-based clauses.
20559struct ReductionData {
20560 /// List of original reduction items.
20561 SmallVector<Expr *, 8> Vars;
20562 /// List of private copies of the reduction items.
20563 SmallVector<Expr *, 8> Privates;
20564 /// LHS expressions for the reduction_op expressions.
20565 SmallVector<Expr *, 8> LHSs;
20566 /// RHS expressions for the reduction_op expressions.
20567 SmallVector<Expr *, 8> RHSs;
20568 /// Reduction operation expression.
20569 SmallVector<Expr *, 8> ReductionOps;
20570 /// inscan copy operation expressions.
20571 SmallVector<Expr *, 8> InscanCopyOps;
20572 /// inscan copy temp array expressions for prefix sums.
20573 SmallVector<Expr *, 8> InscanCopyArrayTemps;
20574 /// inscan copy temp array element expressions for prefix sums.
20575 SmallVector<Expr *, 8> InscanCopyArrayElems;
20576 /// Taskgroup descriptors for the corresponding reduction items in
20577 /// in_reduction clauses.
20578 SmallVector<Expr *, 8> TaskgroupDescriptors;
20579 /// List of captures for clause.
20580 SmallVector<Decl *, 4> ExprCaptures;
20581 /// List of postupdate expressions.
20582 SmallVector<Expr *, 4> ExprPostUpdates;
20583 /// Reduction modifier.
20584 unsigned RedModifier = 0;
20585 /// Original modifier.
20586 unsigned OrigSharingModifier = 0;
20587 /// Private Variable Reduction
20588 SmallVector<bool, 8> IsPrivateVarReduction;
20589 ReductionData() = delete;
20590 /// Reserves required memory for the reduction data.
20591 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
20592 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
20593 Vars.reserve(N: Size);
20594 Privates.reserve(N: Size);
20595 LHSs.reserve(N: Size);
20596 RHSs.reserve(N: Size);
20597 ReductionOps.reserve(N: Size);
20598 IsPrivateVarReduction.reserve(N: Size);
20599 if (RedModifier == OMPC_REDUCTION_inscan) {
20600 InscanCopyOps.reserve(N: Size);
20601 InscanCopyArrayTemps.reserve(N: Size);
20602 InscanCopyArrayElems.reserve(N: Size);
20603 }
20604 TaskgroupDescriptors.reserve(N: Size);
20605 ExprCaptures.reserve(N: Size);
20606 ExprPostUpdates.reserve(N: Size);
20607 }
20608 /// Stores reduction item and reduction operation only (required for dependent
20609 /// reduction item).
20610 void push(Expr *Item, Expr *ReductionOp) {
20611 Vars.emplace_back(Args&: Item);
20612 Privates.emplace_back(Args: nullptr);
20613 LHSs.emplace_back(Args: nullptr);
20614 RHSs.emplace_back(Args: nullptr);
20615 ReductionOps.emplace_back(Args&: ReductionOp);
20616 IsPrivateVarReduction.emplace_back(Args: false);
20617 TaskgroupDescriptors.emplace_back(Args: nullptr);
20618 if (RedModifier == OMPC_REDUCTION_inscan) {
20619 InscanCopyOps.push_back(Elt: nullptr);
20620 InscanCopyArrayTemps.push_back(Elt: nullptr);
20621 InscanCopyArrayElems.push_back(Elt: nullptr);
20622 }
20623 }
20624 /// Stores reduction data.
20625 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
20626 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
20627 Expr *CopyArrayElem, bool IsPrivate) {
20628 Vars.emplace_back(Args&: Item);
20629 Privates.emplace_back(Args&: Private);
20630 LHSs.emplace_back(Args&: LHS);
20631 RHSs.emplace_back(Args&: RHS);
20632 ReductionOps.emplace_back(Args&: ReductionOp);
20633 TaskgroupDescriptors.emplace_back(Args&: TaskgroupDescriptor);
20634 if (RedModifier == OMPC_REDUCTION_inscan) {
20635 InscanCopyOps.push_back(Elt: CopyOp);
20636 InscanCopyArrayTemps.push_back(Elt: CopyArrayTemp);
20637 InscanCopyArrayElems.push_back(Elt: CopyArrayElem);
20638 } else {
20639 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
20640 CopyArrayElem == nullptr &&
20641 "Copy operation must be used for inscan reductions only.");
20642 }
20643 IsPrivateVarReduction.emplace_back(Args&: IsPrivate);
20644 }
20645};
20646} // namespace
20647
20648static bool checkOMPArraySectionConstantForReduction(
20649 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
20650 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
20651 const Expr *Length = OASE->getLength();
20652 if (Length == nullptr) {
20653 // For array sections of the form [1:] or [:], we would need to analyze
20654 // the lower bound...
20655 if (OASE->getColonLocFirst().isValid())
20656 return false;
20657
20658 // This is an array subscript which has implicit length 1!
20659 SingleElement = true;
20660 ArraySizes.push_back(Elt: llvm::APSInt::get(X: 1));
20661 } else {
20662 Expr::EvalResult Result;
20663 if (!Length->EvaluateAsInt(Result, Ctx: Context))
20664 return false;
20665
20666 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
20667 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
20668 ArraySizes.push_back(Elt: ConstantLengthValue);
20669 }
20670
20671 // Get the base of this array section and walk up from there.
20672 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
20673
20674 // We require length = 1 for all array sections except the right-most to
20675 // guarantee that the memory region is contiguous and has no holes in it.
20676 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Val: Base)) {
20677 Length = TempOASE->getLength();
20678 if (Length == nullptr) {
20679 // For array sections of the form [1:] or [:], we would need to analyze
20680 // the lower bound...
20681 if (OASE->getColonLocFirst().isValid())
20682 return false;
20683
20684 // This is an array subscript which has implicit length 1!
20685 llvm::APSInt ConstantOne = llvm::APSInt::get(X: 1);
20686 ArraySizes.push_back(Elt: ConstantOne);
20687 } else {
20688 Expr::EvalResult Result;
20689 if (!Length->EvaluateAsInt(Result, Ctx: Context))
20690 return false;
20691
20692 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
20693 if (ConstantLengthValue.getSExtValue() != 1)
20694 return false;
20695
20696 ArraySizes.push_back(Elt: ConstantLengthValue);
20697 }
20698 Base = TempOASE->getBase()->IgnoreParenImpCasts();
20699 }
20700
20701 // If we have a single element, we don't need to add the implicit lengths.
20702 if (!SingleElement) {
20703 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base)) {
20704 // Has implicit length 1!
20705 llvm::APSInt ConstantOne = llvm::APSInt::get(X: 1);
20706 ArraySizes.push_back(Elt: ConstantOne);
20707 Base = TempASE->getBase()->IgnoreParenImpCasts();
20708 }
20709 }
20710
20711 // This array section can be privatized as a single value or as a constant
20712 // sized array.
20713 return true;
20714}
20715
20716static BinaryOperatorKind
20717getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
20718 if (BOK == BO_Add)
20719 return BO_AddAssign;
20720 if (BOK == BO_Mul)
20721 return BO_MulAssign;
20722 if (BOK == BO_And)
20723 return BO_AndAssign;
20724 if (BOK == BO_Or)
20725 return BO_OrAssign;
20726 if (BOK == BO_Xor)
20727 return BO_XorAssign;
20728 return BOK;
20729}
20730
20731static bool actOnOMPReductionKindClause(
20732 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
20733 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20734 SourceLocation ColonLoc, SourceLocation EndLoc,
20735 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20736 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
20737 DeclarationName DN = ReductionId.getName();
20738 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
20739 BinaryOperatorKind BOK = BO_Comma;
20740
20741 ASTContext &Context = S.Context;
20742 // OpenMP [2.14.3.6, reduction clause]
20743 // C
20744 // reduction-identifier is either an identifier or one of the following
20745 // operators: +, -, *, &, |, ^, && and ||
20746 // C++
20747 // reduction-identifier is either an id-expression or one of the following
20748 // operators: +, -, *, &, |, ^, && and ||
20749 switch (OOK) {
20750 case OO_Plus:
20751 BOK = BO_Add;
20752 break;
20753 case OO_Minus:
20754 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
20755 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
20756 // reduction identifier.
20757 if (S.LangOpts.OpenMP > 52)
20758 BOK = BO_Comma;
20759 else
20760 BOK = BO_Add;
20761 break;
20762 case OO_Star:
20763 BOK = BO_Mul;
20764 break;
20765 case OO_Amp:
20766 BOK = BO_And;
20767 break;
20768 case OO_Pipe:
20769 BOK = BO_Or;
20770 break;
20771 case OO_Caret:
20772 BOK = BO_Xor;
20773 break;
20774 case OO_AmpAmp:
20775 BOK = BO_LAnd;
20776 break;
20777 case OO_PipePipe:
20778 BOK = BO_LOr;
20779 break;
20780 case OO_New:
20781 case OO_Delete:
20782 case OO_Array_New:
20783 case OO_Array_Delete:
20784 case OO_Slash:
20785 case OO_Percent:
20786 case OO_Tilde:
20787 case OO_Exclaim:
20788 case OO_Equal:
20789 case OO_Less:
20790 case OO_Greater:
20791 case OO_LessEqual:
20792 case OO_GreaterEqual:
20793 case OO_PlusEqual:
20794 case OO_MinusEqual:
20795 case OO_StarEqual:
20796 case OO_SlashEqual:
20797 case OO_PercentEqual:
20798 case OO_CaretEqual:
20799 case OO_AmpEqual:
20800 case OO_PipeEqual:
20801 case OO_LessLess:
20802 case OO_GreaterGreater:
20803 case OO_LessLessEqual:
20804 case OO_GreaterGreaterEqual:
20805 case OO_EqualEqual:
20806 case OO_ExclaimEqual:
20807 case OO_Spaceship:
20808 case OO_PlusPlus:
20809 case OO_MinusMinus:
20810 case OO_Comma:
20811 case OO_ArrowStar:
20812 case OO_Arrow:
20813 case OO_Call:
20814 case OO_Subscript:
20815 case OO_Conditional:
20816 case OO_Coawait:
20817 case NUM_OVERLOADED_OPERATORS:
20818 llvm_unreachable("Unexpected reduction identifier");
20819 case OO_None:
20820 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
20821 if (II->isStr(Str: "max"))
20822 BOK = BO_GT;
20823 else if (II->isStr(Str: "min"))
20824 BOK = BO_LT;
20825 }
20826 break;
20827 }
20828
20829 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
20830 // A reduction clause with the minus (-) operator was deprecated
20831 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
20832 S.Diag(Loc: ReductionId.getLoc(), DiagID: diag::warn_omp_minus_in_reduction_deprecated);
20833
20834 SourceRange ReductionIdRange;
20835 if (ReductionIdScopeSpec.isValid())
20836 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
20837 else
20838 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
20839 ReductionIdRange.setEnd(ReductionId.getEndLoc());
20840
20841 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
20842 bool FirstIter = true;
20843 for (Expr *RefExpr : VarList) {
20844 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
20845 // OpenMP [2.1, C/C++]
20846 // A list item is a variable or array section, subject to the restrictions
20847 // specified in Section 2.4 on page 42 and in each of the sections
20848 // describing clauses and directives for which a list appears.
20849 // OpenMP [2.14.3.3, Restrictions, p.1]
20850 // A variable that is part of another variable (as an array or
20851 // structure element) cannot appear in a private clause.
20852 if (!FirstIter && IR != ER)
20853 ++IR;
20854 FirstIter = false;
20855 SourceLocation ELoc;
20856 SourceRange ERange;
20857 bool IsPrivate = false;
20858 Expr *SimpleRefExpr = RefExpr;
20859 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
20860 /*AllowArraySection=*/true);
20861 if (Res.second) {
20862 // Try to find 'declare reduction' corresponding construct before using
20863 // builtin/overloaded operators.
20864 QualType Type = Context.DependentTy;
20865 CXXCastPath BasePath;
20866 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20867 SemaRef&: S, Loc: ELoc, Range: ERange, S: Stack->getCurScope(), ReductionIdScopeSpec,
20868 ReductionId, Ty: Type, BasePath, UnresolvedReduction: IR == ER ? nullptr : *IR);
20869 Expr *ReductionOp = nullptr;
20870 if (S.CurContext->isDependentContext() &&
20871 (DeclareReductionRef.isUnset() ||
20872 isa<UnresolvedLookupExpr>(Val: DeclareReductionRef.get())))
20873 ReductionOp = DeclareReductionRef.get();
20874 // It will be analyzed later.
20875 RD.push(Item: RefExpr, ReductionOp);
20876 }
20877 ValueDecl *D = Res.first;
20878 if (!D)
20879 continue;
20880
20881 Expr *TaskgroupDescriptor = nullptr;
20882 QualType Type;
20883 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: RefExpr->IgnoreParens());
20884 auto *OASE = dyn_cast<ArraySectionExpr>(Val: RefExpr->IgnoreParens());
20885 if (ASE) {
20886 Type = ASE->getType().getNonReferenceType();
20887 } else if (OASE) {
20888 QualType BaseType =
20889 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
20890 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20891 Type = ATy->getElementType();
20892 else
20893 Type = BaseType->getPointeeType();
20894 Type = Type.getNonReferenceType();
20895 } else {
20896 Type = Context.getBaseElementType(QT: D->getType().getNonReferenceType());
20897 }
20898 auto *VD = dyn_cast<VarDecl>(Val: D);
20899
20900 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
20901 // A variable that appears in a private clause must not have an incomplete
20902 // type or a reference type.
20903 if (S.RequireCompleteType(Loc: ELoc, T: D->getType(),
20904 DiagID: diag::err_omp_reduction_incomplete_type))
20905 continue;
20906 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20907 // A list item that appears in a reduction clause must not be
20908 // const-qualified.
20909 if (rejectConstNotMutableType(SemaRef&: S, D, Type, CKind: ClauseKind, ELoc,
20910 /*AcceptIfMutable=*/false, ListItemNotVar: ASE || OASE))
20911 continue;
20912
20913 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
20914 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
20915 // If a list-item is a reference type then it must bind to the same object
20916 // for all threads of the team.
20917 if (!ASE && !OASE) {
20918 if (VD) {
20919 VarDecl *VDDef = VD->getDefinition();
20920 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
20921 DSARefChecker Check(Stack);
20922 if (Check.Visit(S: VDDef->getInit())) {
20923 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_ref_type_arg)
20924 << getOpenMPClauseNameForDiag(C: ClauseKind) << ERange;
20925 S.Diag(Loc: VDDef->getLocation(), DiagID: diag::note_defined_here) << VDDef;
20926 continue;
20927 }
20928 }
20929 }
20930
20931 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
20932 // in a Construct]
20933 // Variables with the predetermined data-sharing attributes may not be
20934 // listed in data-sharing attributes clauses, except for the cases
20935 // listed below. For these exceptions only, listing a predetermined
20936 // variable in a data-sharing attribute clause is allowed and overrides
20937 // the variable's predetermined data-sharing attributes.
20938 // OpenMP [2.14.3.6, Restrictions, p.3]
20939 // Any number of reduction clauses can be specified on the directive,
20940 // but a list item can appear only once in the reduction clauses for that
20941 // directive.
20942 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20943 if (DVar.CKind == OMPC_reduction) {
20944 S.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced)
20945 << getOpenMPClauseNameForDiag(C: ClauseKind);
20946 if (DVar.RefExpr)
20947 S.Diag(Loc: DVar.RefExpr->getExprLoc(), DiagID: diag::note_omp_referenced);
20948 continue;
20949 }
20950 if (DVar.CKind != OMPC_unknown) {
20951 S.Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
20952 << getOpenMPClauseNameForDiag(C: DVar.CKind)
20953 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
20954 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
20955 continue;
20956 }
20957
20958 // OpenMP [2.14.3.6, Restrictions, p.1]
20959 // A list item that appears in a reduction clause of a worksharing
20960 // construct must be shared in the parallel regions to which any of the
20961 // worksharing regions arising from the worksharing construct bind.
20962
20963 if (S.getLangOpts().OpenMP <= 52 &&
20964 isOpenMPWorksharingDirective(DKind: CurrDir) &&
20965 !isOpenMPParallelDirective(DKind: CurrDir) &&
20966 !isOpenMPTeamsDirective(DKind: CurrDir)) {
20967 DVar = Stack->getImplicitDSA(D, FromParent: true);
20968 if (DVar.CKind != OMPC_shared) {
20969 S.Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
20970 << getOpenMPClauseNameForDiag(C: OMPC_reduction)
20971 << getOpenMPClauseNameForDiag(C: OMPC_shared);
20972 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
20973 continue;
20974 }
20975 } else if (isOpenMPWorksharingDirective(DKind: CurrDir) &&
20976 !isOpenMPParallelDirective(DKind: CurrDir) &&
20977 !isOpenMPTeamsDirective(DKind: CurrDir)) {
20978 // OpenMP 6.0 [ 7.6.10 ]
20979 // Support Reduction over private variables with reduction clause.
20980 // A list item in a reduction clause can now be private in the enclosing
20981 // context. For orphaned constructs it is assumed to be shared unless
20982 // the original(private) modifier appears in the clause.
20983 DVar = Stack->getImplicitDSA(D, FromParent: true);
20984 // Determine if the variable should be considered private
20985 IsPrivate = DVar.CKind != OMPC_shared;
20986 bool IsOrphaned = false;
20987 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
20988 IsOrphaned = ParentDir == OMPD_unknown;
20989 if ((IsOrphaned &&
20990 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
20991 IsPrivate = true;
20992 }
20993 } else {
20994 // Threadprivates cannot be shared between threads, so dignose if the base
20995 // is a threadprivate variable.
20996 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20997 if (DVar.CKind == OMPC_threadprivate) {
20998 S.Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
20999 << getOpenMPClauseNameForDiag(C: DVar.CKind)
21000 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
21001 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
21002 continue;
21003 }
21004 }
21005
21006 // Try to find 'declare reduction' corresponding construct before using
21007 // builtin/overloaded operators.
21008 CXXCastPath BasePath;
21009 ExprResult DeclareReductionRef = buildDeclareReductionRef(
21010 SemaRef&: S, Loc: ELoc, Range: ERange, S: Stack->getCurScope(), ReductionIdScopeSpec,
21011 ReductionId, Ty: Type, BasePath, UnresolvedReduction: IR == ER ? nullptr : *IR);
21012 if (DeclareReductionRef.isInvalid())
21013 continue;
21014 if (S.CurContext->isDependentContext() &&
21015 (DeclareReductionRef.isUnset() ||
21016 isa<UnresolvedLookupExpr>(Val: DeclareReductionRef.get()))) {
21017 RD.push(Item: RefExpr, ReductionOp: DeclareReductionRef.get());
21018 // Handle non-dependent inscan reduction variables in dependent contexts.
21019 if (RD.RedModifier == OMPC_REDUCTION_inscan)
21020 Stack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_reduction, PrivateCopy: nullptr,
21021 Modifier: RD.RedModifier, AppliedToPointee: ASE || OASE);
21022 continue;
21023 }
21024 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
21025 // Not allowed reduction identifier is found.
21026 if (S.LangOpts.OpenMP > 52)
21027 S.Diag(Loc: ReductionId.getBeginLoc(),
21028 DiagID: diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
21029 << Type << ReductionIdRange;
21030 else
21031 S.Diag(Loc: ReductionId.getBeginLoc(),
21032 DiagID: diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
21033 << Type << ReductionIdRange;
21034 continue;
21035 }
21036
21037 // OpenMP [2.14.3.6, reduction clause, Restrictions]
21038 // The type of a list item that appears in a reduction clause must be valid
21039 // for the reduction-identifier. For a max or min reduction in C, the type
21040 // of the list item must be an allowed arithmetic data type: char, int,
21041 // float, double, or _Bool, possibly modified with long, short, signed, or
21042 // unsigned. For a max or min reduction in C++, the type of the list item
21043 // must be an allowed arithmetic data type: char, wchar_t, int, float,
21044 // double, or bool, possibly modified with long, short, signed, or unsigned.
21045 if (DeclareReductionRef.isUnset()) {
21046 if ((BOK == BO_GT || BOK == BO_LT) &&
21047 !(Type->isScalarType() ||
21048 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
21049 S.Diag(Loc: ELoc, DiagID: diag::err_omp_clause_not_arithmetic_type_arg)
21050 << getOpenMPClauseNameForDiag(C: ClauseKind)
21051 << S.getLangOpts().CPlusPlus;
21052 if (!ASE && !OASE) {
21053 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
21054 VarDecl::DeclarationOnly;
21055 S.Diag(Loc: D->getLocation(),
21056 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21057 << D;
21058 }
21059 continue;
21060 }
21061 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
21062 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
21063 S.Diag(Loc: ELoc, DiagID: diag::err_omp_clause_floating_type_arg)
21064 << getOpenMPClauseNameForDiag(C: ClauseKind);
21065 if (!ASE && !OASE) {
21066 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
21067 VarDecl::DeclarationOnly;
21068 S.Diag(Loc: D->getLocation(),
21069 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21070 << D;
21071 }
21072 continue;
21073 }
21074 }
21075
21076 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
21077 VarDecl *LHSVD = buildVarDecl(SemaRef&: S, Loc: ELoc, Type, Name: ".reduction.lhs",
21078 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
21079 VarDecl *RHSVD = buildVarDecl(SemaRef&: S, Loc: ELoc, Type, Name: D->getName(),
21080 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
21081 QualType PrivateTy = Type;
21082
21083 // Try if we can determine constant lengths for all array sections and avoid
21084 // the VLA.
21085 bool ConstantLengthOASE = false;
21086 if (OASE) {
21087 bool SingleElement;
21088 llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
21089 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
21090 Context, OASE, SingleElement, ArraySizes);
21091
21092 // If we don't have a single element, we must emit a constant array type.
21093 if (ConstantLengthOASE && !SingleElement) {
21094 for (llvm::APSInt &Size : ArraySizes)
21095 PrivateTy = Context.getConstantArrayType(EltTy: PrivateTy, ArySize: Size, SizeExpr: nullptr,
21096 ASM: ArraySizeModifier::Normal,
21097 /*IndexTypeQuals=*/0);
21098 }
21099 }
21100
21101 if ((OASE && !ConstantLengthOASE) ||
21102 (!OASE && !ASE &&
21103 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
21104 if (!Context.getTargetInfo().isVLASupported()) {
21105 if (isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective())) {
21106 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_vla_unsupported) << !!OASE;
21107 S.Diag(Loc: ELoc, DiagID: diag::note_vla_unsupported);
21108 continue;
21109 } else {
21110 S.targetDiag(Loc: ELoc, DiagID: diag::err_omp_reduction_vla_unsupported) << !!OASE;
21111 S.targetDiag(Loc: ELoc, DiagID: diag::note_vla_unsupported);
21112 }
21113 }
21114 // For arrays/array sections only:
21115 // Create pseudo array type for private copy. The size for this array will
21116 // be generated during codegen.
21117 // For array subscripts or single variables Private Ty is the same as Type
21118 // (type of the variable or single array element).
21119 PrivateTy = Context.getVariableArrayType(
21120 EltTy: Type,
21121 NumElts: new (Context)
21122 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
21123 ASM: ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
21124 } else if (!ASE && !OASE &&
21125 Context.getAsArrayType(T: D->getType().getNonReferenceType())) {
21126 PrivateTy = D->getType().getNonReferenceType();
21127 }
21128 // Private copy.
21129 VarDecl *PrivateVD =
21130 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: PrivateTy, Name: D->getName(),
21131 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
21132 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
21133 // Add initializer for private variable.
21134 Expr *Init = nullptr;
21135 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, D: LHSVD, Ty: Type, Loc: ELoc);
21136 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, D: RHSVD, Ty: Type, Loc: ELoc);
21137 if (DeclareReductionRef.isUsable()) {
21138 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
21139 auto *DRD = cast<OMPDeclareReductionDecl>(Val: DRDRef->getDecl());
21140 if (DRD->getInitializer()) {
21141 Init = DRDRef;
21142 RHSVD->setInit(DRDRef);
21143 RHSVD->setInitStyle(VarDecl::CallInit);
21144 }
21145 } else {
21146 switch (BOK) {
21147 case BO_Add:
21148 case BO_Xor:
21149 case BO_Or:
21150 case BO_LOr:
21151 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
21152 if (Type->isScalarType() || Type->isAnyComplexType())
21153 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/0).get();
21154 break;
21155 case BO_Mul:
21156 // '*' reduction op - initializer is '1'.
21157 // For C++ class types (e.g. std::complex) the OpenMP built-in
21158 // reduction identifiers are an extension: the standard only defines
21159 // identities for arithmetic (and, in Clang, _Complex) types. Without
21160 // an explicit initializer the private copy would be value-initialized,
21161 // which yields the *additive* identity (e.g. std::complex(0,0)) and is
21162 // wrong for multiplication. Initialize from the integer literal '1'
21163 // instead and let the converting constructor build the multiplicative
21164 // identity (e.g. std::complex(1) == (1,0)).
21165 if (Type->isScalarType() || Type->isAnyComplexType()) {
21166 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
21167 } else if (S.getLangOpts().CPlusPlus && Type->isRecordType()) {
21168 // Only use '1' when the type is actually copy-initializable from it.
21169 // Otherwise fall back to value-initialization (the previous behavior)
21170 // rather than rejecting the reduction, so a class that used to
21171 // compile keeps compiling. Such a class keeps its (possibly
21172 // incorrect) value-initialized identity, matching the pre-existing
21173 // behavior; BO_Add likewise relies on value-initialization for class
21174 // types.
21175 Expr *One = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
21176 InitializedEntity Entity =
21177 InitializedEntity::InitializeTemporary(Type);
21178 InitializationKind Kind = InitializationKind::CreateCopy(InitLoc: ELoc, EqualLoc: ELoc);
21179 InitializationSequence Seq(S, Entity, Kind, One);
21180 if (Seq)
21181 Init = One;
21182 }
21183 break;
21184 case BO_LAnd:
21185 if (Type->isScalarType() || Type->isAnyComplexType()) {
21186 // '&&' reduction ops - initializer is '1'.
21187 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
21188 }
21189 break;
21190 case BO_And: {
21191 // '&' reduction op - initializer is '~0'.
21192 QualType OrigType = Type;
21193 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
21194 Type = ComplexTy->getElementType();
21195 if (Type->isRealFloatingType()) {
21196 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
21197 Semantics: Context.getFloatTypeSemantics(T: Type));
21198 Init = FloatingLiteral::Create(C: Context, V: InitValue, /*isexact=*/true,
21199 Type, L: ELoc);
21200 } else if (Type->isScalarType()) {
21201 uint64_t Size = Context.getTypeSize(T: Type);
21202 QualType IntTy = Context.getIntTypeForBitwidth(DestWidth: Size, /*Signed=*/0);
21203 llvm::APInt InitValue = llvm::APInt::getAllOnes(numBits: Size);
21204 Init = IntegerLiteral::Create(C: Context, V: InitValue, type: IntTy, l: ELoc);
21205 }
21206 if (Init && OrigType->isAnyComplexType()) {
21207 // Init = 0xFFFF + 0xFFFFi;
21208 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
21209 Init = S.CreateBuiltinBinOp(OpLoc: ELoc, Opc: BO_Add, LHSExpr: Init, RHSExpr: Im).get();
21210 }
21211 Type = OrigType;
21212 break;
21213 }
21214 case BO_LT:
21215 case BO_GT: {
21216 // 'min' reduction op - initializer is 'Largest representable number in
21217 // the reduction list item type'.
21218 // 'max' reduction op - initializer is 'Least representable number in
21219 // the reduction list item type'.
21220 if (Type->isIntegerType() || Type->isPointerType()) {
21221 bool IsSigned = Type->hasSignedIntegerRepresentation();
21222 uint64_t Size = Context.getTypeSize(T: Type);
21223 QualType IntTy =
21224 Context.getIntTypeForBitwidth(DestWidth: Size, /*Signed=*/IsSigned);
21225 llvm::APInt InitValue =
21226 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(numBits: Size)
21227 : llvm::APInt::getMinValue(numBits: Size)
21228 : IsSigned ? llvm::APInt::getSignedMaxValue(numBits: Size)
21229 : llvm::APInt::getMaxValue(numBits: Size);
21230 Init = IntegerLiteral::Create(C: Context, V: InitValue, type: IntTy, l: ELoc);
21231 if (Type->isPointerType()) {
21232 // Cast to pointer type.
21233 ExprResult CastExpr = S.BuildCStyleCastExpr(
21234 LParenLoc: ELoc, Ty: Context.getTrivialTypeSourceInfo(T: Type, Loc: ELoc), RParenLoc: ELoc, Op: Init);
21235 if (CastExpr.isInvalid())
21236 continue;
21237 Init = CastExpr.get();
21238 }
21239 } else if (Type->isRealFloatingType()) {
21240 llvm::APFloat InitValue = llvm::APFloat::getLargest(
21241 Sem: Context.getFloatTypeSemantics(T: Type), Negative: BOK != BO_LT);
21242 Init = FloatingLiteral::Create(C: Context, V: InitValue, /*isexact=*/true,
21243 Type, L: ELoc);
21244 }
21245 break;
21246 }
21247 case BO_PtrMemD:
21248 case BO_PtrMemI:
21249 case BO_MulAssign:
21250 case BO_Div:
21251 case BO_Rem:
21252 case BO_Sub:
21253 case BO_Shl:
21254 case BO_Shr:
21255 case BO_LE:
21256 case BO_GE:
21257 case BO_EQ:
21258 case BO_NE:
21259 case BO_Cmp:
21260 case BO_AndAssign:
21261 case BO_XorAssign:
21262 case BO_OrAssign:
21263 case BO_Assign:
21264 case BO_AddAssign:
21265 case BO_SubAssign:
21266 case BO_DivAssign:
21267 case BO_RemAssign:
21268 case BO_ShlAssign:
21269 case BO_ShrAssign:
21270 case BO_Comma:
21271 llvm_unreachable("Unexpected reduction operation");
21272 }
21273 }
21274 if (Init && DeclareReductionRef.isUnset()) {
21275 S.AddInitializerToDecl(dcl: RHSVD, init: Init, /*DirectInit=*/false);
21276 // Store initializer for single element in private copy. Will be used
21277 // during codegen.
21278 PrivateVD->setInit(RHSVD->getInit());
21279 PrivateVD->setInitStyle(RHSVD->getInitStyle());
21280 } else if (!Init) {
21281 S.ActOnUninitializedDecl(dcl: RHSVD);
21282 // Store initializer for single element in private copy. Will be used
21283 // during codegen.
21284 PrivateVD->setInit(RHSVD->getInit());
21285 PrivateVD->setInitStyle(RHSVD->getInitStyle());
21286 }
21287 if (RHSVD->isInvalidDecl())
21288 continue;
21289 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
21290 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_id_not_compatible)
21291 << Type << ReductionIdRange;
21292 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
21293 VarDecl::DeclarationOnly;
21294 S.Diag(Loc: D->getLocation(),
21295 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21296 << D;
21297 continue;
21298 }
21299 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, D: PrivateVD, Ty: PrivateTy, Loc: ELoc);
21300 ExprResult ReductionOp;
21301 if (DeclareReductionRef.isUsable()) {
21302 QualType RedTy = DeclareReductionRef.get()->getType();
21303 QualType PtrRedTy = Context.getPointerType(T: RedTy);
21304 ExprResult LHS = S.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: LHSDRE);
21305 ExprResult RHS = S.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: RHSDRE);
21306 if (!BasePath.empty()) {
21307 LHS = S.DefaultLvalueConversion(E: LHS.get());
21308 RHS = S.DefaultLvalueConversion(E: RHS.get());
21309 LHS = ImplicitCastExpr::Create(
21310 Context, T: PtrRedTy, Kind: CK_UncheckedDerivedToBase, Operand: LHS.get(), BasePath: &BasePath,
21311 Cat: LHS.get()->getValueKind(), FPO: FPOptionsOverride());
21312 RHS = ImplicitCastExpr::Create(
21313 Context, T: PtrRedTy, Kind: CK_UncheckedDerivedToBase, Operand: RHS.get(), BasePath: &BasePath,
21314 Cat: RHS.get()->getValueKind(), FPO: FPOptionsOverride());
21315 }
21316 FunctionProtoType::ExtProtoInfo EPI;
21317 QualType Params[] = {PtrRedTy, PtrRedTy};
21318 QualType FnTy = Context.getFunctionType(ResultTy: Context.VoidTy, Args: Params, EPI);
21319 auto *OVE = new (Context) OpaqueValueExpr(
21320 ELoc, Context.getPointerType(T: FnTy), VK_PRValue, OK_Ordinary,
21321 S.DefaultLvalueConversion(E: DeclareReductionRef.get()).get());
21322 Expr *Args[] = {LHS.get(), RHS.get()};
21323 ReductionOp =
21324 CallExpr::Create(Ctx: Context, Fn: OVE, Args, Ty: Context.VoidTy, VK: VK_PRValue, RParenLoc: ELoc,
21325 FPFeatures: S.CurFPFeatureOverrides());
21326 } else {
21327 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
21328 if (Type->isRecordType() && CombBOK != BOK) {
21329 Sema::TentativeAnalysisScope Trap(S);
21330 ReductionOp =
21331 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
21332 Opc: CombBOK, LHSExpr: LHSDRE, RHSExpr: RHSDRE);
21333 }
21334 if (!ReductionOp.isUsable()) {
21335 ReductionOp =
21336 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(), Opc: BOK,
21337 LHSExpr: LHSDRE, RHSExpr: RHSDRE);
21338 if (ReductionOp.isUsable()) {
21339 if (BOK != BO_LT && BOK != BO_GT) {
21340 ReductionOp =
21341 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
21342 Opc: BO_Assign, LHSExpr: LHSDRE, RHSExpr: ReductionOp.get());
21343 } else {
21344 auto *ConditionalOp = new (Context)
21345 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
21346 RHSDRE, Type, VK_LValue, OK_Ordinary);
21347 ReductionOp =
21348 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
21349 Opc: BO_Assign, LHSExpr: LHSDRE, RHSExpr: ConditionalOp);
21350 }
21351 }
21352 }
21353 if (ReductionOp.isUsable())
21354 ReductionOp = S.ActOnFinishFullExpr(Expr: ReductionOp.get(),
21355 /*DiscardedValue=*/false);
21356 if (!ReductionOp.isUsable())
21357 continue;
21358 }
21359
21360 // Add copy operations for inscan reductions.
21361 // LHS = RHS;
21362 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
21363 if (ClauseKind == OMPC_reduction &&
21364 RD.RedModifier == OMPC_REDUCTION_inscan) {
21365 ExprResult RHS = S.DefaultLvalueConversion(E: RHSDRE);
21366 CopyOpRes = S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: LHSDRE,
21367 RHSExpr: RHS.get());
21368 if (!CopyOpRes.isUsable())
21369 continue;
21370 CopyOpRes =
21371 S.ActOnFinishFullExpr(Expr: CopyOpRes.get(), /*DiscardedValue=*/true);
21372 if (!CopyOpRes.isUsable())
21373 continue;
21374 // For simd directive and simd-based directives in simd mode no need to
21375 // construct temp array, need just a single temp element.
21376 if (Stack->getCurrentDirective() == OMPD_simd ||
21377 (S.getLangOpts().OpenMPSimd &&
21378 isOpenMPSimdDirective(DKind: Stack->getCurrentDirective()))) {
21379 VarDecl *TempArrayVD =
21380 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: PrivateTy, Name: D->getName(),
21381 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
21382 // Add a constructor to the temp decl.
21383 S.ActOnUninitializedDecl(dcl: TempArrayVD);
21384 TempArrayRes = buildDeclRefExpr(S, D: TempArrayVD, Ty: PrivateTy, Loc: ELoc);
21385 } else {
21386 // Build temp array for prefix sum.
21387 auto *Dim = new (S.Context)
21388 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
21389 QualType ArrayTy = S.Context.getVariableArrayType(
21390 EltTy: PrivateTy, NumElts: Dim, ASM: ArraySizeModifier::Normal,
21391 /*IndexTypeQuals=*/0);
21392 VarDecl *TempArrayVD =
21393 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: ArrayTy, Name: D->getName(),
21394 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
21395 // Add a constructor to the temp decl.
21396 S.ActOnUninitializedDecl(dcl: TempArrayVD);
21397 TempArrayRes = buildDeclRefExpr(S, D: TempArrayVD, Ty: ArrayTy, Loc: ELoc);
21398 TempArrayElem =
21399 S.DefaultFunctionArrayLvalueConversion(E: TempArrayRes.get());
21400 auto *Idx = new (S.Context)
21401 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
21402 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(Base: TempArrayElem.get(),
21403 LLoc: ELoc, Idx, RLoc: ELoc);
21404 }
21405 }
21406
21407 // OpenMP [2.15.4.6, Restrictions, p.2]
21408 // A list item that appears in an in_reduction clause of a task construct
21409 // must appear in a task_reduction clause of a construct associated with a
21410 // taskgroup region that includes the participating task in its taskgroup
21411 // set. The construct associated with the innermost region that meets this
21412 // condition must specify the same reduction-identifier as the in_reduction
21413 // clause.
21414 if (ClauseKind == OMPC_in_reduction) {
21415 SourceRange ParentSR;
21416 BinaryOperatorKind ParentBOK;
21417 const Expr *ParentReductionOp = nullptr;
21418 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
21419 DSAStackTy::DSAVarData ParentBOKDSA =
21420 Stack->getTopMostTaskgroupReductionData(D, SR&: ParentSR, BOK&: ParentBOK,
21421 TaskgroupDescriptor&: ParentBOKTD);
21422 DSAStackTy::DSAVarData ParentReductionOpDSA =
21423 Stack->getTopMostTaskgroupReductionData(
21424 D, SR&: ParentSR, ReductionRef&: ParentReductionOp, TaskgroupDescriptor&: ParentReductionOpTD);
21425 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
21426 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
21427 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
21428 (DeclareReductionRef.isUsable() && IsParentBOK) ||
21429 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
21430 bool EmitError = true;
21431 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
21432 llvm::FoldingSetNodeID RedId, ParentRedId;
21433 ParentReductionOp->Profile(ID&: ParentRedId, Context, /*Canonical=*/true);
21434 DeclareReductionRef.get()->Profile(ID&: RedId, Context,
21435 /*Canonical=*/true);
21436 EmitError = RedId != ParentRedId;
21437 }
21438 if (EmitError) {
21439 S.Diag(Loc: ReductionId.getBeginLoc(),
21440 DiagID: diag::err_omp_reduction_identifier_mismatch)
21441 << ReductionIdRange << RefExpr->getSourceRange();
21442 S.Diag(Loc: ParentSR.getBegin(),
21443 DiagID: diag::note_omp_previous_reduction_identifier)
21444 << ParentSR
21445 << (IsParentBOK ? ParentBOKDSA.RefExpr
21446 : ParentReductionOpDSA.RefExpr)
21447 ->getSourceRange();
21448 continue;
21449 }
21450 }
21451 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
21452 }
21453
21454 DeclRefExpr *Ref = nullptr;
21455 Expr *VarsExpr = RefExpr->IgnoreParens();
21456 if (!VD && !S.CurContext->isDependentContext()) {
21457 if (ASE || OASE) {
21458 TransformExprToCaptures RebuildToCapture(S, D);
21459 VarsExpr =
21460 RebuildToCapture.TransformExpr(E: RefExpr->IgnoreParens()).get();
21461 Ref = RebuildToCapture.getCapturedExpr();
21462 } else {
21463 VarsExpr = Ref = buildCapture(S, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
21464 }
21465 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
21466 RD.ExprCaptures.emplace_back(Args: Ref->getDecl());
21467 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
21468 ExprResult RefRes = S.DefaultLvalueConversion(E: Ref);
21469 if (!RefRes.isUsable())
21470 continue;
21471 ExprResult PostUpdateRes =
21472 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: SimpleRefExpr,
21473 RHSExpr: RefRes.get());
21474 if (!PostUpdateRes.isUsable())
21475 continue;
21476 if (isOpenMPTaskingDirective(Kind: Stack->getCurrentDirective()) ||
21477 Stack->getCurrentDirective() == OMPD_taskgroup) {
21478 S.Diag(Loc: RefExpr->getExprLoc(),
21479 DiagID: diag::err_omp_reduction_non_addressable_expression)
21480 << RefExpr->getSourceRange();
21481 continue;
21482 }
21483 RD.ExprPostUpdates.emplace_back(
21484 Args: S.IgnoredValueConversions(E: PostUpdateRes.get()).get());
21485 }
21486 }
21487 }
21488 // All reduction items are still marked as reduction (to do not increase
21489 // code base size).
21490 unsigned Modifier = RD.RedModifier;
21491 // Consider task_reductions as reductions with task modifier. Required for
21492 // correct analysis of in_reduction clauses.
21493 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
21494 Modifier = OMPC_REDUCTION_task;
21495 Stack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_reduction, PrivateCopy: Ref, Modifier,
21496 AppliedToPointee: ASE || OASE);
21497 if (Modifier == OMPC_REDUCTION_task &&
21498 (CurrDir == OMPD_taskgroup ||
21499 ((isOpenMPParallelDirective(DKind: CurrDir) ||
21500 isOpenMPWorksharingDirective(DKind: CurrDir)) &&
21501 !isOpenMPSimdDirective(DKind: CurrDir)))) {
21502 if (DeclareReductionRef.isUsable())
21503 Stack->addTaskgroupReductionData(D, SR: ReductionIdRange,
21504 ReductionRef: DeclareReductionRef.get());
21505 else
21506 Stack->addTaskgroupReductionData(D, SR: ReductionIdRange, BOK);
21507 }
21508 RD.push(Item: VarsExpr, Private: PrivateDRE, LHS: LHSDRE, RHS: RHSDRE, ReductionOp: ReductionOp.get(),
21509 TaskgroupDescriptor, CopyOp: CopyOpRes.get(), CopyArrayTemp: TempArrayRes.get(),
21510 CopyArrayElem: TempArrayElem.get(), IsPrivate);
21511 }
21512 return RD.Vars.empty();
21513}
21514
21515OMPClause *SemaOpenMP::ActOnOpenMPReductionClause(
21516 ArrayRef<Expr *> VarList,
21517 OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers,
21518 SourceLocation StartLoc, SourceLocation LParenLoc,
21519 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
21520 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
21521 ArrayRef<Expr *> UnresolvedReductions) {
21522 OpenMPReductionClauseModifier Modifier =
21523 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
21524 OpenMPOriginalSharingModifier OriginalSharingModifier =
21525 static_cast<OpenMPOriginalSharingModifier>(
21526 Modifiers.OriginalSharingModifier);
21527 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
21528 Diag(Loc: LParenLoc, DiagID: diag::err_omp_unexpected_clause_value)
21529 << getListOfPossibleValues(K: OMPC_reduction, /*First=*/0,
21530 /*Last=*/OMPC_REDUCTION_unknown)
21531 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
21532 return nullptr;
21533 }
21534 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
21535 // A reduction clause with the inscan reduction-modifier may only appear on a
21536 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
21537 // construct, a parallel worksharing-loop construct or a parallel
21538 // worksharing-loop SIMD construct.
21539 if (Modifier == OMPC_REDUCTION_inscan &&
21540 (DSAStack->getCurrentDirective() != OMPD_for &&
21541 DSAStack->getCurrentDirective() != OMPD_for_simd &&
21542 DSAStack->getCurrentDirective() != OMPD_simd &&
21543 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
21544 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
21545 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_wrong_inscan_reduction);
21546 return nullptr;
21547 }
21548 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
21549 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_reduction, VarList,
21550 StartLoc, LParenLoc, ColonLoc, EndLoc,
21551 ReductionIdScopeSpec, ReductionId,
21552 UnresolvedReductions, RD))
21553 return nullptr;
21554
21555 return OMPReductionClause::Create(
21556 C: getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
21557 Modifier, VL: RD.Vars,
21558 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
21559 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps, CopyOps: RD.InscanCopyOps,
21560 CopyArrayTemps: RD.InscanCopyArrayTemps, CopyArrayElems: RD.InscanCopyArrayElems,
21561 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
21562 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates), IsPrivateVarReduction: RD.IsPrivateVarReduction,
21563 OriginalSharingModifier);
21564}
21565
21566OMPClause *SemaOpenMP::ActOnOpenMPTaskReductionClause(
21567 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21568 SourceLocation ColonLoc, SourceLocation EndLoc,
21569 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
21570 ArrayRef<Expr *> UnresolvedReductions) {
21571 ReductionData RD(VarList.size());
21572 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_task_reduction,
21573 VarList, StartLoc, LParenLoc, ColonLoc,
21574 EndLoc, ReductionIdScopeSpec, ReductionId,
21575 UnresolvedReductions, RD))
21576 return nullptr;
21577
21578 return OMPTaskReductionClause::Create(
21579 C: getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, VL: RD.Vars,
21580 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
21581 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps,
21582 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
21583 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates));
21584}
21585
21586OMPClause *SemaOpenMP::ActOnOpenMPInReductionClause(
21587 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21588 SourceLocation ColonLoc, SourceLocation EndLoc,
21589 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
21590 ArrayRef<Expr *> UnresolvedReductions) {
21591 ReductionData RD(VarList.size());
21592 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_in_reduction, VarList,
21593 StartLoc, LParenLoc, ColonLoc, EndLoc,
21594 ReductionIdScopeSpec, ReductionId,
21595 UnresolvedReductions, RD))
21596 return nullptr;
21597
21598 return OMPInReductionClause::Create(
21599 C: getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, VL: RD.Vars,
21600 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
21601 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps, TaskgroupDescriptors: RD.TaskgroupDescriptors,
21602 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
21603 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates));
21604}
21605
21606bool SemaOpenMP::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
21607 SourceLocation LinLoc) {
21608 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
21609 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
21610 Diag(Loc: LinLoc, DiagID: diag::err_omp_wrong_linear_modifier)
21611 << getLangOpts().CPlusPlus;
21612 return true;
21613 }
21614 return false;
21615}
21616
21617bool SemaOpenMP::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
21618 OpenMPLinearClauseKind LinKind,
21619 QualType Type, bool IsDeclareSimd) {
21620 const auto *VD = dyn_cast_or_null<VarDecl>(Val: D);
21621 // A variable must not have an incomplete type or a reference type.
21622 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
21623 DiagID: diag::err_omp_linear_incomplete_type))
21624 return true;
21625 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
21626 !Type->isReferenceType()) {
21627 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_linear_modifier_non_reference)
21628 << Type << getOpenMPSimpleClauseTypeName(Kind: OMPC_linear, Type: LinKind);
21629 return true;
21630 }
21631 Type = Type.getNonReferenceType();
21632
21633 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
21634 // A variable that is privatized must not have a const-qualified type
21635 // unless it is of class type with a mutable member. This restriction does
21636 // not apply to the firstprivate clause, nor to the linear clause on
21637 // declarative directives (like declare simd).
21638 if (!IsDeclareSimd &&
21639 rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_linear, ELoc))
21640 return true;
21641
21642 // A list item must be of integral or pointer type.
21643 Type = Type.getUnqualifiedType().getCanonicalType();
21644 const auto *Ty = Type.getTypePtrOrNull();
21645 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
21646 !Ty->isIntegralType(Ctx: getASTContext()) && !Ty->isPointerType())) {
21647 Diag(Loc: ELoc, DiagID: diag::err_omp_linear_expected_int_or_ptr) << Type;
21648 if (D) {
21649 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21650 VarDecl::DeclarationOnly;
21651 Diag(Loc: D->getLocation(),
21652 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21653 << D;
21654 }
21655 return true;
21656 }
21657 return false;
21658}
21659
21660OMPClause *SemaOpenMP::ActOnOpenMPLinearClause(
21661 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
21662 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
21663 SourceLocation LinLoc, SourceLocation ColonLoc,
21664 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
21665 SmallVector<Expr *, 8> Vars;
21666 SmallVector<Expr *, 8> Privates;
21667 SmallVector<Expr *, 8> Inits;
21668 SmallVector<Decl *, 4> ExprCaptures;
21669 SmallVector<Expr *, 4> ExprPostUpdates;
21670 // OpenMP 5.2 [Section 5.4.6, linear clause]
21671 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
21672 // 'ref'
21673 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
21674 getLangOpts().OpenMP >= 52)
21675 Diag(Loc: Step->getBeginLoc(), DiagID: diag::err_omp_step_simple_modifier_exclusive);
21676 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
21677 LinKind = OMPC_LINEAR_val;
21678 for (Expr *RefExpr : VarList) {
21679 assert(RefExpr && "NULL expr in OpenMP linear clause.");
21680 SourceLocation ELoc;
21681 SourceRange ERange;
21682 Expr *SimpleRefExpr = RefExpr;
21683 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
21684 if (Res.second) {
21685 // It will be analyzed later.
21686 Vars.push_back(Elt: RefExpr);
21687 Privates.push_back(Elt: nullptr);
21688 Inits.push_back(Elt: nullptr);
21689 }
21690 ValueDecl *D = Res.first;
21691 if (!D)
21692 continue;
21693
21694 QualType Type = D->getType();
21695 auto *VD = dyn_cast<VarDecl>(Val: D);
21696
21697 // OpenMP [2.14.3.7, linear clause]
21698 // A list-item cannot appear in more than one linear clause.
21699 // A list-item that appears in a linear clause cannot appear in any
21700 // other data-sharing attribute clause.
21701 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
21702 if (DVar.RefExpr) {
21703 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
21704 << getOpenMPClauseNameForDiag(C: DVar.CKind)
21705 << getOpenMPClauseNameForDiag(C: OMPC_linear);
21706 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
21707 continue;
21708 }
21709
21710 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
21711 continue;
21712 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
21713
21714 // Build private copy of original var.
21715 VarDecl *Private =
21716 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
21717 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
21718 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
21719 DeclRefExpr *PrivateRef = buildDeclRefExpr(S&: SemaRef, D: Private, Ty: Type, Loc: ELoc);
21720 // Build var to save initial value.
21721 VarDecl *Init = buildVarDecl(SemaRef, Loc: ELoc, Type, Name: ".linear.start");
21722 Expr *InitExpr;
21723 DeclRefExpr *Ref = nullptr;
21724 if (!VD && !SemaRef.CurContext->isDependentContext()) {
21725 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
21726 if (!isOpenMPCapturedDecl(D)) {
21727 ExprCaptures.push_back(Elt: Ref->getDecl());
21728 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
21729 ExprResult RefRes = SemaRef.DefaultLvalueConversion(E: Ref);
21730 if (!RefRes.isUsable())
21731 continue;
21732 ExprResult PostUpdateRes =
21733 SemaRef.BuildBinOp(DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign,
21734 LHSExpr: SimpleRefExpr, RHSExpr: RefRes.get());
21735 if (!PostUpdateRes.isUsable())
21736 continue;
21737 ExprPostUpdates.push_back(
21738 Elt: SemaRef.IgnoredValueConversions(E: PostUpdateRes.get()).get());
21739 }
21740 }
21741 }
21742 if (LinKind == OMPC_LINEAR_uval)
21743 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
21744 else
21745 InitExpr = VD ? SimpleRefExpr : Ref;
21746 SemaRef.AddInitializerToDecl(
21747 dcl: Init, init: SemaRef.DefaultLvalueConversion(E: InitExpr).get(),
21748 /*DirectInit=*/false);
21749 DeclRefExpr *InitRef = buildDeclRefExpr(S&: SemaRef, D: Init, Ty: Type, Loc: ELoc);
21750
21751 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_linear, PrivateCopy: Ref);
21752 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
21753 ? RefExpr->IgnoreParens()
21754 : Ref);
21755 Privates.push_back(Elt: PrivateRef);
21756 Inits.push_back(Elt: InitRef);
21757 }
21758
21759 if (Vars.empty())
21760 return nullptr;
21761
21762 Expr *StepExpr = Step;
21763 Expr *CalcStepExpr = nullptr;
21764 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
21765 !Step->isInstantiationDependent() &&
21766 !Step->containsUnexpandedParameterPack()) {
21767 SourceLocation StepLoc = Step->getBeginLoc();
21768 ExprResult Val = PerformOpenMPImplicitIntegerConversion(Loc: StepLoc, Op: Step);
21769 if (Val.isInvalid())
21770 return nullptr;
21771 StepExpr = Val.get();
21772
21773 // Build var to save the step value.
21774 VarDecl *SaveVar =
21775 buildVarDecl(SemaRef, Loc: StepLoc, Type: StepExpr->getType(), Name: ".linear.step");
21776 ExprResult SaveRef =
21777 buildDeclRefExpr(S&: SemaRef, D: SaveVar, Ty: StepExpr->getType(), Loc: StepLoc);
21778 ExprResult CalcStep = SemaRef.BuildBinOp(
21779 S: SemaRef.getCurScope(), OpLoc: StepLoc, Opc: BO_Assign, LHSExpr: SaveRef.get(), RHSExpr: StepExpr);
21780 CalcStep =
21781 SemaRef.ActOnFinishFullExpr(Expr: CalcStep.get(), /*DiscardedValue=*/false);
21782
21783 // Warn about zero linear step (it would be probably better specified as
21784 // making corresponding variables 'const').
21785 if (std::optional<llvm::APSInt> Result =
21786 StepExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
21787 if (!Result->isNegative() && !Result->isStrictlyPositive())
21788 Diag(Loc: StepLoc, DiagID: diag::warn_omp_linear_step_zero)
21789 << Vars[0] << (Vars.size() > 1);
21790 } else if (CalcStep.isUsable()) {
21791 // Calculate the step beforehand instead of doing this on each iteration.
21792 // (This is not used if the number of iterations may be kfold-ed).
21793 CalcStepExpr = CalcStep.get();
21794 }
21795 }
21796
21797 return OMPLinearClause::Create(C: getASTContext(), StartLoc, LParenLoc, Modifier: LinKind,
21798 ModifierLoc: LinLoc, ColonLoc, StepModifierLoc, EndLoc,
21799 VL: Vars, PL: Privates, IL: Inits, Step: StepExpr, CalcStep: CalcStepExpr,
21800 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures),
21801 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: ExprPostUpdates));
21802}
21803
21804static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
21805 Expr *NumIterations, Sema &SemaRef,
21806 Scope *S, DSAStackTy *Stack) {
21807 // Walk the vars and build update/final expressions for the CodeGen.
21808 SmallVector<Expr *, 8> Updates;
21809 SmallVector<Expr *, 8> Finals;
21810 SmallVector<Expr *, 8> UsedExprs;
21811 Expr *Step = Clause.getStep();
21812 Expr *CalcStep = Clause.getCalcStep();
21813 // OpenMP [2.14.3.7, linear clause]
21814 // If linear-step is not specified it is assumed to be 1.
21815 if (!Step)
21816 Step = SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get();
21817 else if (CalcStep)
21818 Step = cast<BinaryOperator>(Val: CalcStep)->getLHS();
21819 bool HasErrors = false;
21820 auto CurInit = Clause.inits().begin();
21821 auto CurPrivate = Clause.privates().begin();
21822 OpenMPLinearClauseKind LinKind = Clause.getModifier();
21823 for (Expr *RefExpr : Clause.varlist()) {
21824 SourceLocation ELoc;
21825 SourceRange ERange;
21826 Expr *SimpleRefExpr = RefExpr;
21827 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
21828 ValueDecl *D = Res.first;
21829 if (Res.second || !D) {
21830 Updates.push_back(Elt: nullptr);
21831 Finals.push_back(Elt: nullptr);
21832 HasErrors = true;
21833 continue;
21834 }
21835 auto &&Info = Stack->isLoopControlVariable(D);
21836 // OpenMP [2.15.11, distribute simd Construct]
21837 // A list item may not appear in a linear clause, unless it is the loop
21838 // iteration variable.
21839 if (isOpenMPDistributeDirective(DKind: Stack->getCurrentDirective()) &&
21840 isOpenMPSimdDirective(DKind: Stack->getCurrentDirective()) && !Info.first) {
21841 SemaRef.Diag(Loc: ELoc,
21842 DiagID: diag::err_omp_linear_distribute_var_non_loop_iteration);
21843 Updates.push_back(Elt: nullptr);
21844 Finals.push_back(Elt: nullptr);
21845 HasErrors = true;
21846 continue;
21847 }
21848 Expr *InitExpr = *CurInit;
21849
21850 // Build privatized reference to the current linear var.
21851 auto *DE = cast<DeclRefExpr>(Val: SimpleRefExpr);
21852 Expr *CapturedRef;
21853 if (LinKind == OMPC_LINEAR_uval)
21854 CapturedRef = cast<VarDecl>(Val: DE->getDecl())->getInit();
21855 else
21856 CapturedRef =
21857 buildDeclRefExpr(S&: SemaRef, D: cast<VarDecl>(Val: DE->getDecl()),
21858 Ty: DE->getType().getUnqualifiedType(), Loc: DE->getExprLoc(),
21859 /*RefersToCapture=*/true);
21860
21861 // Build update: Var = InitExpr + IV * Step
21862 ExprResult Update;
21863 if (!Info.first)
21864 Update = buildCounterUpdate(
21865 SemaRef, S, Loc: RefExpr->getExprLoc(), VarRef: *CurPrivate, Start: InitExpr, Iter: IV, Step,
21866 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
21867 else
21868 Update = *CurPrivate;
21869 Update = SemaRef.ActOnFinishFullExpr(Expr: Update.get(), CC: DE->getBeginLoc(),
21870 /*DiscardedValue=*/false);
21871
21872 // Build final: Var = PrivCopy;
21873 ExprResult Final;
21874 if (!Info.first)
21875 Final = SemaRef.BuildBinOp(
21876 S, OpLoc: RefExpr->getExprLoc(), Opc: BO_Assign, LHSExpr: CapturedRef,
21877 RHSExpr: SemaRef.DefaultLvalueConversion(E: *CurPrivate).get());
21878 else
21879 Final = *CurPrivate;
21880 Final = SemaRef.ActOnFinishFullExpr(Expr: Final.get(), CC: DE->getBeginLoc(),
21881 /*DiscardedValue=*/false);
21882
21883 if (!Update.isUsable() || !Final.isUsable()) {
21884 Updates.push_back(Elt: nullptr);
21885 Finals.push_back(Elt: nullptr);
21886 UsedExprs.push_back(Elt: nullptr);
21887 HasErrors = true;
21888 } else {
21889 Updates.push_back(Elt: Update.get());
21890 Finals.push_back(Elt: Final.get());
21891 if (!Info.first)
21892 UsedExprs.push_back(Elt: SimpleRefExpr);
21893 }
21894 ++CurInit;
21895 ++CurPrivate;
21896 }
21897 if (Expr *S = Clause.getStep())
21898 UsedExprs.push_back(Elt: S);
21899 // Fill the remaining part with the nullptr.
21900 UsedExprs.append(NumInputs: Clause.varlist_size() + 1 - UsedExprs.size(), Elt: nullptr);
21901 Clause.setUpdates(Updates);
21902 Clause.setFinals(Finals);
21903 Clause.setUsedExprs(UsedExprs);
21904 return HasErrors;
21905}
21906
21907OMPClause *SemaOpenMP::ActOnOpenMPAlignedClause(
21908 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
21909 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
21910 SmallVector<Expr *, 8> Vars;
21911 for (Expr *RefExpr : VarList) {
21912 assert(RefExpr && "NULL expr in OpenMP aligned clause.");
21913 SourceLocation ELoc;
21914 SourceRange ERange;
21915 Expr *SimpleRefExpr = RefExpr;
21916 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
21917 if (Res.second) {
21918 // It will be analyzed later.
21919 Vars.push_back(Elt: RefExpr);
21920 }
21921 ValueDecl *D = Res.first;
21922 if (!D)
21923 continue;
21924
21925 QualType QType = D->getType();
21926 auto *VD = dyn_cast<VarDecl>(Val: D);
21927
21928 // OpenMP [2.8.1, simd construct, Restrictions]
21929 // The type of list items appearing in the aligned clause must be
21930 // array, pointer, reference to array, or reference to pointer.
21931 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
21932 const Type *Ty = QType.getTypePtrOrNull();
21933 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
21934 Diag(Loc: ELoc, DiagID: diag::err_omp_aligned_expected_array_or_ptr)
21935 << QType << getLangOpts().CPlusPlus << ERange;
21936 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21937 VarDecl::DeclarationOnly;
21938 Diag(Loc: D->getLocation(),
21939 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21940 << D;
21941 continue;
21942 }
21943
21944 // OpenMP [2.8.1, simd construct, Restrictions]
21945 // A list-item cannot appear in more than one aligned clause.
21946 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, NewDE: SimpleRefExpr)) {
21947 Diag(Loc: ELoc, DiagID: diag::err_omp_used_in_clause_twice)
21948 << 0 << getOpenMPClauseNameForDiag(C: OMPC_aligned) << ERange;
21949 Diag(Loc: PrevRef->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
21950 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
21951 continue;
21952 }
21953
21954 DeclRefExpr *Ref = nullptr;
21955 if (!VD && isOpenMPCapturedDecl(D))
21956 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
21957 Vars.push_back(Elt: SemaRef
21958 .DefaultFunctionArrayConversion(
21959 E: (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
21960 .get());
21961 }
21962
21963 // OpenMP [2.8.1, simd construct, Description]
21964 // The parameter of the aligned clause, alignment, must be a constant
21965 // positive integer expression.
21966 // If no optional parameter is specified, implementation-defined default
21967 // alignments for SIMD instructions on the target platforms are assumed.
21968 if (Alignment != nullptr) {
21969 ExprResult AlignResult =
21970 VerifyPositiveIntegerConstantInClause(E: Alignment, CKind: OMPC_aligned);
21971 if (AlignResult.isInvalid())
21972 return nullptr;
21973 Alignment = AlignResult.get();
21974 }
21975 if (Vars.empty())
21976 return nullptr;
21977
21978 return OMPAlignedClause::Create(C: getASTContext(), StartLoc, LParenLoc,
21979 ColonLoc, EndLoc, VL: Vars, A: Alignment);
21980}
21981
21982OMPClause *SemaOpenMP::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
21983 SourceLocation StartLoc,
21984 SourceLocation LParenLoc,
21985 SourceLocation EndLoc) {
21986 SmallVector<Expr *, 8> Vars;
21987 SmallVector<Expr *, 8> SrcExprs;
21988 SmallVector<Expr *, 8> DstExprs;
21989 SmallVector<Expr *, 8> AssignmentOps;
21990 for (Expr *RefExpr : VarList) {
21991 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
21992 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
21993 // It will be analyzed later.
21994 Vars.push_back(Elt: RefExpr);
21995 SrcExprs.push_back(Elt: nullptr);
21996 DstExprs.push_back(Elt: nullptr);
21997 AssignmentOps.push_back(Elt: nullptr);
21998 continue;
21999 }
22000
22001 SourceLocation ELoc = RefExpr->getExprLoc();
22002 // OpenMP [2.1, C/C++]
22003 // A list item is a variable name.
22004 // OpenMP [2.14.4.1, Restrictions, p.1]
22005 // A list item that appears in a copyin clause must be threadprivate.
22006 auto *DE = dyn_cast<DeclRefExpr>(Val: RefExpr);
22007 if (!DE || !isa<VarDecl>(Val: DE->getDecl())) {
22008 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_var_name_member_expr)
22009 << 0 << RefExpr->getSourceRange();
22010 continue;
22011 }
22012
22013 Decl *D = DE->getDecl();
22014 auto *VD = cast<VarDecl>(Val: D);
22015
22016 QualType Type = VD->getType();
22017 if (Type->isDependentType() || Type->isInstantiationDependentType()) {
22018 // It will be analyzed later.
22019 Vars.push_back(Elt: DE);
22020 SrcExprs.push_back(Elt: nullptr);
22021 DstExprs.push_back(Elt: nullptr);
22022 AssignmentOps.push_back(Elt: nullptr);
22023 continue;
22024 }
22025
22026 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
22027 // A list item that appears in a copyin clause must be threadprivate.
22028 if (!DSAStack->isThreadPrivate(D: VD)) {
22029 unsigned OMPVersion = getLangOpts().OpenMP;
22030 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
22031 << getOpenMPClauseNameForDiag(C: OMPC_copyin)
22032 << getOpenMPDirectiveName(D: OMPD_threadprivate, Ver: OMPVersion);
22033 continue;
22034 }
22035
22036 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
22037 // A variable of class type (or array thereof) that appears in a
22038 // copyin clause requires an accessible, unambiguous copy assignment
22039 // operator for the class type.
22040 QualType ElemType =
22041 getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
22042 VarDecl *SrcVD =
22043 buildVarDecl(SemaRef, Loc: DE->getBeginLoc(), Type: ElemType.getUnqualifiedType(),
22044 Name: ".copyin.src", Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr);
22045 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
22046 S&: SemaRef, D: SrcVD, Ty: ElemType.getUnqualifiedType(), Loc: DE->getExprLoc());
22047 VarDecl *DstVD =
22048 buildVarDecl(SemaRef, Loc: DE->getBeginLoc(), Type: ElemType, Name: ".copyin.dst",
22049 Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr);
22050 DeclRefExpr *PseudoDstExpr =
22051 buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: ElemType, Loc: DE->getExprLoc());
22052 // For arrays generate assignment operation for single element and replace
22053 // it by the original array element in CodeGen.
22054 ExprResult AssignmentOp =
22055 SemaRef.BuildBinOp(/*S=*/nullptr, OpLoc: DE->getExprLoc(), Opc: BO_Assign,
22056 LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
22057 if (AssignmentOp.isInvalid())
22058 continue;
22059 AssignmentOp =
22060 SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: DE->getExprLoc(),
22061 /*DiscardedValue=*/false);
22062 if (AssignmentOp.isInvalid())
22063 continue;
22064
22065 DSAStack->addDSA(D: VD, E: DE, A: OMPC_copyin);
22066 Vars.push_back(Elt: DE);
22067 SrcExprs.push_back(Elt: PseudoSrcExpr);
22068 DstExprs.push_back(Elt: PseudoDstExpr);
22069 AssignmentOps.push_back(Elt: AssignmentOp.get());
22070 }
22071
22072 if (Vars.empty())
22073 return nullptr;
22074
22075 return OMPCopyinClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
22076 VL: Vars, SrcExprs, DstExprs, AssignmentOps);
22077}
22078
22079OMPClause *SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
22080 SourceLocation StartLoc,
22081 SourceLocation LParenLoc,
22082 SourceLocation EndLoc) {
22083 SmallVector<Expr *, 8> Vars;
22084 SmallVector<Expr *, 8> SrcExprs;
22085 SmallVector<Expr *, 8> DstExprs;
22086 SmallVector<Expr *, 8> AssignmentOps;
22087 for (Expr *RefExpr : VarList) {
22088 assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
22089 SourceLocation ELoc;
22090 SourceRange ERange;
22091 Expr *SimpleRefExpr = RefExpr;
22092 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
22093 if (Res.second) {
22094 // It will be analyzed later.
22095 Vars.push_back(Elt: RefExpr);
22096 SrcExprs.push_back(Elt: nullptr);
22097 DstExprs.push_back(Elt: nullptr);
22098 AssignmentOps.push_back(Elt: nullptr);
22099 }
22100 ValueDecl *D = Res.first;
22101 if (!D)
22102 continue;
22103
22104 QualType Type = D->getType();
22105 auto *VD = dyn_cast<VarDecl>(Val: D);
22106
22107 // OpenMP [2.14.4.2, Restrictions, p.2]
22108 // A list item that appears in a copyprivate clause may not appear in a
22109 // private or firstprivate clause on the single construct.
22110 if (!VD || !DSAStack->isThreadPrivate(D: VD)) {
22111 DSAStackTy::DSAVarData DVar =
22112 DSAStack->getTopDSA(D, /*FromParent=*/false);
22113 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
22114 DVar.RefExpr) {
22115 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
22116 << getOpenMPClauseNameForDiag(C: DVar.CKind)
22117 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate);
22118 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
22119 continue;
22120 }
22121
22122 // OpenMP [2.11.4.2, Restrictions, p.1]
22123 // All list items that appear in a copyprivate clause must be either
22124 // threadprivate or private in the enclosing context.
22125 if (DVar.CKind == OMPC_unknown) {
22126 DVar = DSAStack->getImplicitDSA(D, FromParent: false);
22127 if (DVar.CKind == OMPC_shared) {
22128 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
22129 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate)
22130 << "threadprivate or private in the enclosing context";
22131 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
22132 continue;
22133 }
22134 }
22135 }
22136
22137 // Variably modified types are not supported.
22138 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
22139 unsigned OMPVersion = getLangOpts().OpenMP;
22140 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
22141 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate) << Type
22142 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
22143 Ver: OMPVersion);
22144 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
22145 VarDecl::DeclarationOnly;
22146 Diag(Loc: D->getLocation(),
22147 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
22148 << D;
22149 continue;
22150 }
22151
22152 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
22153 // A variable of class type (or array thereof) that appears in a
22154 // copyin clause requires an accessible, unambiguous copy assignment
22155 // operator for the class type.
22156 Type = getASTContext()
22157 .getBaseElementType(QT: Type.getNonReferenceType())
22158 .getUnqualifiedType();
22159 VarDecl *SrcVD =
22160 buildVarDecl(SemaRef, Loc: RefExpr->getBeginLoc(), Type, Name: ".copyprivate.src",
22161 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
22162 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(S&: SemaRef, D: SrcVD, Ty: Type, Loc: ELoc);
22163 VarDecl *DstVD =
22164 buildVarDecl(SemaRef, Loc: RefExpr->getBeginLoc(), Type, Name: ".copyprivate.dst",
22165 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
22166 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: Type, Loc: ELoc);
22167 ExprResult AssignmentOp = SemaRef.BuildBinOp(
22168 DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
22169 if (AssignmentOp.isInvalid())
22170 continue;
22171 AssignmentOp = SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: ELoc,
22172 /*DiscardedValue=*/false);
22173 if (AssignmentOp.isInvalid())
22174 continue;
22175
22176 // No need to mark vars as copyprivate, they are already threadprivate or
22177 // implicitly private.
22178 assert(VD || isOpenMPCapturedDecl(D));
22179 Vars.push_back(
22180 Elt: VD ? RefExpr->IgnoreParens()
22181 : buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false));
22182 SrcExprs.push_back(Elt: PseudoSrcExpr);
22183 DstExprs.push_back(Elt: PseudoDstExpr);
22184 AssignmentOps.push_back(Elt: AssignmentOp.get());
22185 }
22186
22187 if (Vars.empty())
22188 return nullptr;
22189
22190 return OMPCopyprivateClause::Create(C: getASTContext(), StartLoc, LParenLoc,
22191 EndLoc, VL: Vars, SrcExprs, DstExprs,
22192 AssignmentOps);
22193}
22194
22195OMPClause *SemaOpenMP::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
22196 SourceLocation StartLoc,
22197 SourceLocation LParenLoc,
22198 SourceLocation EndLoc) {
22199 if (VarList.empty())
22200 return nullptr;
22201
22202 return OMPFlushClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
22203 VL: VarList);
22204}
22205
22206/// Tries to find omp_depend_t. type.
22207static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
22208 bool Diagnose = true) {
22209 QualType OMPDependT = Stack->getOMPDependT();
22210 if (!OMPDependT.isNull())
22211 return true;
22212 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_depend_t");
22213 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
22214 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22215 if (Diagnose)
22216 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_depend_t";
22217 return false;
22218 }
22219 Stack->setOMPDependT(PT.get());
22220 return true;
22221}
22222
22223OMPClause *SemaOpenMP::ActOnOpenMPDepobjClause(Expr *Depobj,
22224 SourceLocation StartLoc,
22225 SourceLocation LParenLoc,
22226 SourceLocation EndLoc) {
22227 if (!Depobj)
22228 return nullptr;
22229
22230 bool OMPDependTFound = findOMPDependT(S&: SemaRef, Loc: StartLoc, DSAStack);
22231
22232 // OpenMP 5.0, 2.17.10.1 depobj Construct
22233 // depobj is an lvalue expression of type omp_depend_t.
22234 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
22235 !Depobj->isInstantiationDependent() &&
22236 !Depobj->containsUnexpandedParameterPack() &&
22237 (OMPDependTFound && !getASTContext().typesAreCompatible(
22238 DSAStack->getOMPDependT(), T2: Depobj->getType(),
22239 /*CompareUnqualified=*/true))) {
22240 Diag(Loc: Depobj->getExprLoc(), DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
22241 << 0 << Depobj->getType() << Depobj->getSourceRange();
22242 }
22243
22244 if (!Depobj->isLValue()) {
22245 Diag(Loc: Depobj->getExprLoc(), DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
22246 << 1 << Depobj->getSourceRange();
22247 }
22248
22249 return OMPDepobjClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
22250 Depobj);
22251}
22252
22253namespace {
22254// Utility struct that gathers the related info for doacross clause.
22255struct DoacrossDataInfoTy {
22256 // The list of expressions.
22257 SmallVector<Expr *, 8> Vars;
22258 // The OperatorOffset for doacross loop.
22259 DSAStackTy::OperatorOffsetTy OpsOffs;
22260 // The depended loop count.
22261 llvm::APSInt TotalDepCount;
22262};
22263} // namespace
22264static DoacrossDataInfoTy
22265ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource,
22266 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
22267 SourceLocation EndLoc) {
22268
22269 SmallVector<Expr *, 8> Vars;
22270 DSAStackTy::OperatorOffsetTy OpsOffs;
22271 llvm::APSInt DepCounter(/*BitWidth=*/32);
22272 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
22273
22274 if (const Expr *OrderedCountExpr =
22275 Stack->getParentOrderedRegionParam().first) {
22276 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Ctx: SemaRef.Context);
22277 TotalDepCount.setIsUnsigned(/*Val=*/true);
22278 }
22279
22280 for (Expr *RefExpr : VarList) {
22281 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
22282 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
22283 // It will be analyzed later.
22284 Vars.push_back(Elt: RefExpr);
22285 continue;
22286 }
22287
22288 SourceLocation ELoc = RefExpr->getExprLoc();
22289 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
22290 if (!IsSource) {
22291 if (Stack->getParentOrderedRegionParam().first &&
22292 DepCounter >= TotalDepCount) {
22293 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_unexpected_expr);
22294 continue;
22295 }
22296 ++DepCounter;
22297 // OpenMP [2.13.9, Summary]
22298 // depend(dependence-type : vec), where dependence-type is:
22299 // 'sink' and where vec is the iteration vector, which has the form:
22300 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
22301 // where n is the value specified by the ordered clause in the loop
22302 // directive, xi denotes the loop iteration variable of the i-th nested
22303 // loop associated with the loop directive, and di is a constant
22304 // non-negative integer.
22305 if (SemaRef.CurContext->isDependentContext()) {
22306 // It will be analyzed later.
22307 Vars.push_back(Elt: RefExpr);
22308 continue;
22309 }
22310 SimpleExpr = SimpleExpr->IgnoreImplicit();
22311 OverloadedOperatorKind OOK = OO_None;
22312 SourceLocation OOLoc;
22313 Expr *LHS = SimpleExpr;
22314 Expr *RHS = nullptr;
22315 if (auto *BO = dyn_cast<BinaryOperator>(Val: SimpleExpr)) {
22316 OOK = BinaryOperator::getOverloadedOperator(Opc: BO->getOpcode());
22317 OOLoc = BO->getOperatorLoc();
22318 LHS = BO->getLHS()->IgnoreParenImpCasts();
22319 RHS = BO->getRHS()->IgnoreParenImpCasts();
22320 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Val: SimpleExpr)) {
22321 OOK = OCE->getOperator();
22322 OOLoc = OCE->getOperatorLoc();
22323 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
22324 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
22325 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Val: SimpleExpr)) {
22326 OOK = MCE->getMethodDecl()
22327 ->getNameInfo()
22328 .getName()
22329 .getCXXOverloadedOperator();
22330 OOLoc = MCE->getCallee()->getExprLoc();
22331 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
22332 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
22333 }
22334 SourceLocation ELoc;
22335 SourceRange ERange;
22336 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: LHS, ELoc, ERange);
22337 if (Res.second) {
22338 // It will be analyzed later.
22339 Vars.push_back(Elt: RefExpr);
22340 }
22341 ValueDecl *D = Res.first;
22342 if (!D)
22343 continue;
22344
22345 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
22346 SemaRef.Diag(Loc: OOLoc, DiagID: diag::err_omp_depend_sink_expected_plus_minus);
22347 continue;
22348 }
22349 if (RHS) {
22350 ExprResult RHSRes =
22351 SemaRef.OpenMP().VerifyPositiveIntegerConstantInClause(
22352 E: RHS, CKind: OMPC_depend, /*StrictlyPositive=*/false);
22353 if (RHSRes.isInvalid())
22354 continue;
22355 }
22356 if (!SemaRef.CurContext->isDependentContext() &&
22357 Stack->getParentOrderedRegionParam().first &&
22358 DepCounter != Stack->isParentLoopControlVariable(D).first) {
22359 const ValueDecl *VD =
22360 Stack->getParentLoopControlVariable(I: DepCounter.getZExtValue());
22361 if (VD)
22362 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
22363 << 1 << VD;
22364 else
22365 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
22366 << 0;
22367 continue;
22368 }
22369 OpsOffs.emplace_back(Args&: RHS, Args&: OOK);
22370 }
22371 Vars.push_back(Elt: RefExpr->IgnoreParenImpCasts());
22372 }
22373 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
22374 TotalDepCount > VarList.size() &&
22375 Stack->getParentOrderedRegionParam().first &&
22376 Stack->getParentLoopControlVariable(I: VarList.size() + 1)) {
22377 SemaRef.Diag(Loc: EndLoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
22378 << 1 << Stack->getParentLoopControlVariable(I: VarList.size() + 1);
22379 }
22380 return {.Vars: Vars, .OpsOffs: OpsOffs, .TotalDepCount: TotalDepCount};
22381}
22382
22383OMPClause *SemaOpenMP::ActOnOpenMPDependClause(
22384 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
22385 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
22386 SourceLocation EndLoc) {
22387 OpenMPDependClauseKind DepKind = Data.DepKind;
22388 SourceLocation DepLoc = Data.DepLoc;
22389 if (DSAStack->getCurrentDirective() == OMPD_ordered_standalone &&
22390 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
22391 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
22392 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(C: OMPC_depend);
22393 return nullptr;
22394 }
22395 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
22396 DepKind == OMPC_DEPEND_mutexinoutset) {
22397 Diag(Loc: DepLoc, DiagID: diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
22398 return nullptr;
22399 }
22400 if ((DSAStack->getCurrentDirective() != OMPD_ordered_standalone ||
22401 DSAStack->getCurrentDirective() == OMPD_depobj) &&
22402 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
22403 DepKind == OMPC_DEPEND_sink ||
22404 ((getLangOpts().OpenMP < 50 ||
22405 DSAStack->getCurrentDirective() == OMPD_depobj) &&
22406 DepKind == OMPC_DEPEND_depobj))) {
22407 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
22408 OMPC_DEPEND_outallmemory,
22409 OMPC_DEPEND_inoutallmemory};
22410 if (getLangOpts().OpenMP < 50 ||
22411 DSAStack->getCurrentDirective() == OMPD_depobj)
22412 Except.push_back(Elt: OMPC_DEPEND_depobj);
22413 if (getLangOpts().OpenMP < 51)
22414 Except.push_back(Elt: OMPC_DEPEND_inoutset);
22415 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
22416 ? "depend modifier(iterator) or "
22417 : "";
22418 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
22419 << Expected + getListOfPossibleValues(K: OMPC_depend, /*First=*/0,
22420 /*Last=*/OMPC_DEPEND_unknown,
22421 Exclude: Except)
22422 << getOpenMPClauseNameForDiag(C: OMPC_depend);
22423 return nullptr;
22424 }
22425 if (DepModifier &&
22426 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
22427 Diag(Loc: DepModifier->getExprLoc(),
22428 DiagID: diag::err_omp_depend_sink_source_with_modifier);
22429 return nullptr;
22430 }
22431 if (DepModifier &&
22432 !DepModifier->getType()->isSpecificBuiltinType(K: BuiltinType::OMPIterator))
22433 Diag(Loc: DepModifier->getExprLoc(), DiagID: diag::err_omp_depend_modifier_not_iterator);
22434
22435 SmallVector<Expr *, 8> Vars;
22436 DSAStackTy::OperatorOffsetTy OpsOffs;
22437 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
22438
22439 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
22440 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
22441 SemaRef, IsSource: DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
22442 Vars = VarOffset.Vars;
22443 OpsOffs = VarOffset.OpsOffs;
22444 TotalDepCount = VarOffset.TotalDepCount;
22445 } else {
22446 for (Expr *RefExpr : VarList) {
22447 assert(RefExpr && "NULL expr in OpenMP depend clause.");
22448 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
22449 // It will be analyzed later.
22450 Vars.push_back(Elt: RefExpr);
22451 continue;
22452 }
22453
22454 SourceLocation ELoc = RefExpr->getExprLoc();
22455 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
22456 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
22457 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
22458 if (OMPDependTFound)
22459 OMPDependTFound = findOMPDependT(S&: SemaRef, Loc: StartLoc, DSAStack,
22460 Diagnose: DepKind == OMPC_DEPEND_depobj);
22461 if (DepKind == OMPC_DEPEND_depobj) {
22462 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
22463 // List items used in depend clauses with the depobj dependence type
22464 // must be expressions of the omp_depend_t type.
22465 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
22466 !RefExpr->isInstantiationDependent() &&
22467 !RefExpr->containsUnexpandedParameterPack() &&
22468 (OMPDependTFound &&
22469 !getASTContext().hasSameUnqualifiedType(
22470 DSAStack->getOMPDependT(), T2: RefExpr->getType()))) {
22471 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
22472 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
22473 continue;
22474 }
22475 if (!RefExpr->isLValue()) {
22476 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
22477 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
22478 continue;
22479 }
22480 } else {
22481 // OpenMP 5.0 [2.17.11, Restrictions]
22482 // List items used in depend clauses cannot be zero-length array
22483 // sections.
22484 QualType ExprTy = RefExpr->getType().getNonReferenceType();
22485 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: SimpleExpr);
22486 if (OASE) {
22487 QualType BaseType =
22488 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
22489 if (BaseType.isNull())
22490 return nullptr;
22491 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22492 ExprTy = ATy->getElementType();
22493 else
22494 ExprTy = BaseType->getPointeeType();
22495 if (BaseType.isNull() || ExprTy.isNull())
22496 return nullptr;
22497 ExprTy = ExprTy.getNonReferenceType();
22498 const Expr *Length = OASE->getLength();
22499 Expr::EvalResult Result;
22500 if (Length && !Length->isValueDependent() &&
22501 Length->EvaluateAsInt(Result, Ctx: getASTContext()) &&
22502 Result.Val.getInt().isZero()) {
22503 Diag(Loc: ELoc,
22504 DiagID: diag::err_omp_depend_zero_length_array_section_not_allowed)
22505 << SimpleExpr->getSourceRange();
22506 continue;
22507 }
22508 }
22509
22510 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
22511 // List items used in depend clauses with the in, out, inout,
22512 // inoutset, or mutexinoutset dependence types cannot be
22513 // expressions of the omp_depend_t type.
22514 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
22515 !RefExpr->isInstantiationDependent() &&
22516 !RefExpr->containsUnexpandedParameterPack() &&
22517 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
22518 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
22519 ExprTy.getTypePtr()))) {
22520 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
22521 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22522 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22523 << RefExpr->getSourceRange();
22524 continue;
22525 }
22526
22527 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: SimpleExpr);
22528 if (ASE && !ASE->getBase()->isTypeDependent() &&
22529 !ASE->getBase()
22530 ->getType()
22531 .getNonReferenceType()
22532 ->isPointerType() &&
22533 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
22534 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
22535 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22536 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22537 << RefExpr->getSourceRange();
22538 continue;
22539 }
22540
22541 ExprResult Res;
22542 {
22543 Sema::TentativeAnalysisScope Trap(SemaRef);
22544 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf,
22545 InputExpr: RefExpr->IgnoreParenImpCasts());
22546 }
22547 if (!Res.isUsable() && !isa<ArraySectionExpr>(Val: SimpleExpr) &&
22548 !isa<OMPArrayShapingExpr>(Val: SimpleExpr)) {
22549 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
22550 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22551 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22552 << RefExpr->getSourceRange();
22553 continue;
22554 }
22555 }
22556 }
22557 Vars.push_back(Elt: RefExpr->IgnoreParenImpCasts());
22558 }
22559 }
22560
22561 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
22562 DepKind != OMPC_DEPEND_outallmemory &&
22563 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
22564 return nullptr;
22565
22566 auto *C = OMPDependClause::Create(
22567 C: getASTContext(), StartLoc, LParenLoc, EndLoc,
22568 Data: {.DepKind: DepKind, .DepLoc: DepLoc, .ColonLoc: Data.ColonLoc, .OmpAllMemoryLoc: Data.OmpAllMemoryLoc}, DepModifier, VL: Vars,
22569 NumLoops: TotalDepCount.getZExtValue());
22570 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
22571 DSAStack->isParentOrderedRegion())
22572 DSAStack->addDoacrossDependClause(C, OpsOffs);
22573 return C;
22574}
22575
22576OMPClause *SemaOpenMP::ActOnOpenMPDeviceClause(
22577 OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc,
22578 SourceLocation LParenLoc, SourceLocation ModifierLoc,
22579 SourceLocation EndLoc) {
22580 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
22581 "Unexpected device modifier in OpenMP < 50.");
22582
22583 bool ErrorFound = false;
22584 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
22585 std::string Values =
22586 getListOfPossibleValues(K: OMPC_device, /*First=*/0, Last: OMPC_DEVICE_unknown);
22587 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
22588 << Values << getOpenMPClauseNameForDiag(C: OMPC_device);
22589 ErrorFound = true;
22590 }
22591
22592 Expr *ValExpr = Device;
22593 Stmt *HelperValStmt = nullptr;
22594
22595 // OpenMP 5.2 [1.3, Execution Model]: a conforming device number is either
22596 // a non-negative integer that is less than or equal to omp_get_num_devices()
22597 // or equal to omp_initial_device or omp_invalid_device. The predefined
22598 // identifiers were introduced in OpenMP 5.2; earlier versions require a
22599 // non-negative integer.
22600 if (getLangOpts().OpenMP >= 52) {
22601 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
22602 !ValExpr->isInstantiationDependent()) {
22603 SourceLocation Loc = ValExpr->getExprLoc();
22604 ExprResult Value = PerformOpenMPImplicitIntegerConversion(Loc, Op: ValExpr);
22605 if (Value.isInvalid()) {
22606 ErrorFound = true;
22607 } else {
22608 ValExpr = Value.get();
22609 if (std::optional<llvm::APSInt> Result =
22610 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
22611 if (Result->isSigned() && Result->slt(RHS: -2)) {
22612 Diag(Loc, DiagID: diag::err_omp_device_expression_invalid)
22613 << ValExpr->getSourceRange();
22614 ErrorFound = true;
22615 }
22616 }
22617 }
22618 }
22619 } else {
22620 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_device,
22621 /*StrictlyPositive=*/false) ||
22622 ErrorFound;
22623 }
22624 if (ErrorFound)
22625 return nullptr;
22626
22627 // OpenMP 5.0 [2.12.5, Restrictions]
22628 // In case of ancestor device-modifier, a requires directive with
22629 // the reverse_offload clause must be specified.
22630 if (Modifier == OMPC_DEVICE_ancestor) {
22631 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
22632 SemaRef.targetDiag(
22633 Loc: StartLoc,
22634 DiagID: diag::err_omp_device_ancestor_without_requires_reverse_offload);
22635 ErrorFound = true;
22636 }
22637 }
22638
22639 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22640 OpenMPDirectiveKind CaptureRegion =
22641 getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_device, OpenMPVersion: getLangOpts().OpenMP);
22642 if (CaptureRegion != OMPD_unknown &&
22643 !SemaRef.CurContext->isDependentContext()) {
22644 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
22645 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22646 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
22647 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
22648 }
22649
22650 return new (getASTContext())
22651 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
22652 LParenLoc, ModifierLoc, EndLoc);
22653}
22654
22655static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
22656 DSAStackTy *Stack, QualType QTy,
22657 bool FullCheck = true) {
22658 if (SemaRef.RequireCompleteType(Loc: SL, T: QTy, DiagID: diag::err_incomplete_type))
22659 return false;
22660 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
22661 !QTy.isTriviallyCopyableType(Context: SemaRef.Context))
22662 SemaRef.Diag(Loc: SL, DiagID: diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
22663 return true;
22664}
22665
22666/// Return true if it can be proven that the provided array expression
22667/// (array section or array subscript) does NOT specify the whole size of the
22668/// array whose base type is \a BaseQTy.
22669static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
22670 const Expr *E,
22671 QualType BaseQTy) {
22672 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: E);
22673
22674 // If this is an array subscript, it refers to the whole size if the size of
22675 // the dimension is constant and equals 1. Also, an array section assumes the
22676 // format of an array subscript if no colon is used.
22677 if (isa<ArraySubscriptExpr>(Val: E) ||
22678 (OASE && OASE->getColonLocFirst().isInvalid())) {
22679 if (const auto *ATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr()))
22680 return ATy->getSExtSize() != 1;
22681 // Size can't be evaluated statically.
22682 return false;
22683 }
22684
22685 assert(OASE && "Expecting array section if not an array subscript.");
22686 const Expr *LowerBound = OASE->getLowerBound();
22687 const Expr *Length = OASE->getLength();
22688
22689 // If there is a lower bound that does not evaluates to zero, we are not
22690 // covering the whole dimension.
22691 if (LowerBound) {
22692 Expr::EvalResult Result;
22693 if (!LowerBound->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
22694 return false; // Can't get the integer value as a constant.
22695
22696 llvm::APSInt ConstLowerBound = Result.Val.getInt();
22697 if (ConstLowerBound.getSExtValue())
22698 return true;
22699 }
22700
22701 // If we don't have a length we covering the whole dimension.
22702 if (!Length)
22703 return false;
22704
22705 // If the base is a pointer, we don't have a way to get the size of the
22706 // pointee.
22707 if (BaseQTy->isPointerType())
22708 return false;
22709
22710 // We can only check if the length is the same as the size of the dimension
22711 // if we have a constant array.
22712 const auto *CATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr());
22713 if (!CATy)
22714 return false;
22715
22716 Expr::EvalResult Result;
22717 if (!Length->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
22718 return false; // Can't get the integer value as a constant.
22719
22720 llvm::APSInt ConstLength = Result.Val.getInt();
22721 return CATy->getSExtSize() != ConstLength.getSExtValue();
22722}
22723
22724// Return true if it can be proven that the provided array expression (array
22725// section or array subscript) does NOT specify a single element of the array
22726// whose base type is \a BaseQTy.
22727static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
22728 const Expr *E,
22729 QualType BaseQTy) {
22730 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: E);
22731
22732 // An array subscript always refer to a single element. Also, an array section
22733 // assumes the format of an array subscript if no colon is used.
22734 if (isa<ArraySubscriptExpr>(Val: E) ||
22735 (OASE && OASE->getColonLocFirst().isInvalid()))
22736 return false;
22737
22738 assert(OASE && "Expecting array section if not an array subscript.");
22739 const Expr *Length = OASE->getLength();
22740
22741 // If we don't have a length we have to check if the array has unitary size
22742 // for this dimension. Also, we should always expect a length if the base type
22743 // is pointer.
22744 if (!Length) {
22745 if (const auto *ATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr()))
22746 return ATy->getSExtSize() != 1;
22747 // We cannot assume anything.
22748 return false;
22749 }
22750
22751 // Check if the length evaluates to 1.
22752 Expr::EvalResult Result;
22753 if (!Length->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
22754 return false; // Can't get the integer value as a constant.
22755
22756 llvm::APSInt ConstLength = Result.Val.getInt();
22757 return ConstLength.getSExtValue() != 1;
22758}
22759
22760// The base of elements of list in a map clause have to be either:
22761// - a reference to variable or field.
22762// - a member expression.
22763// - an array expression.
22764//
22765// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
22766// reference to 'r'.
22767//
22768// If we have:
22769//
22770// struct SS {
22771// Bla S;
22772// foo() {
22773// #pragma omp target map (S.Arr[:12]);
22774// }
22775// }
22776//
22777// We want to retrieve the member expression 'this->S';
22778
22779// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
22780// If a list item is an array section, it must specify contiguous storage.
22781//
22782// For this restriction it is sufficient that we make sure only references
22783// to variables or fields and array expressions, and that no array sections
22784// exist except in the rightmost expression (unless they cover the whole
22785// dimension of the array). E.g. these would be invalid:
22786//
22787// r.ArrS[3:5].Arr[6:7]
22788//
22789// r.ArrS[3:5].x
22790//
22791// but these would be valid:
22792// r.ArrS[3].Arr[6:7]
22793//
22794// r.ArrS[3].x
22795namespace {
22796class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
22797 Sema &SemaRef;
22798 OpenMPClauseKind CKind = OMPC_unknown;
22799 OpenMPDirectiveKind DKind = OMPD_unknown;
22800 OMPClauseMappableExprCommon::MappableExprComponentList &Components;
22801 bool IsNonContiguous = false;
22802 bool NoDiagnose = false;
22803 const Expr *RelevantExpr = nullptr;
22804 bool AllowUnitySizeArraySection = true;
22805 bool AllowWholeSizeArraySection = true;
22806 bool AllowAnotherPtr = true;
22807 SourceLocation ELoc;
22808 SourceRange ERange;
22809
22810 void emitErrorMsg() {
22811 // If nothing else worked, this is not a valid map clause expression.
22812 if (SemaRef.getLangOpts().OpenMP < 50) {
22813 SemaRef.Diag(Loc: ELoc,
22814 DiagID: diag::err_omp_expected_named_var_member_or_array_expression)
22815 << ERange;
22816 } else {
22817 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22818 << getOpenMPClauseNameForDiag(C: CKind) << ERange;
22819 }
22820 }
22821
22822public:
22823 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
22824 if (!isa<VarDecl>(Val: DRE->getDecl())) {
22825 emitErrorMsg();
22826 return false;
22827 }
22828 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22829 RelevantExpr = DRE;
22830 // Record the component.
22831 Components.emplace_back(Args&: DRE, Args: DRE->getDecl(), Args&: IsNonContiguous);
22832 return true;
22833 }
22834
22835 bool VisitMemberExpr(MemberExpr *ME) {
22836 Expr *E = ME;
22837 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
22838
22839 if (isa<CXXThisExpr>(Val: BaseE)) {
22840 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22841 // We found a base expression: this->Val.
22842 RelevantExpr = ME;
22843 } else {
22844 E = BaseE;
22845 }
22846
22847 if (!isa<FieldDecl>(Val: ME->getMemberDecl())) {
22848 if (!NoDiagnose) {
22849 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_access_to_data_field)
22850 << ME->getSourceRange();
22851 return false;
22852 }
22853 if (RelevantExpr)
22854 return false;
22855 return Visit(S: E);
22856 }
22857
22858 auto *FD = cast<FieldDecl>(Val: ME->getMemberDecl());
22859
22860 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
22861 // A bit-field cannot appear in a map clause.
22862 //
22863 if (FD->isBitField()) {
22864 if (!NoDiagnose) {
22865 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_bit_fields_forbidden_in_clause)
22866 << ME->getSourceRange() << getOpenMPClauseNameForDiag(C: CKind);
22867 return false;
22868 }
22869 if (RelevantExpr)
22870 return false;
22871 return Visit(S: E);
22872 }
22873
22874 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22875 // If the type of a list item is a reference to a type T then the type
22876 // will be considered to be T for all purposes of this clause.
22877 QualType CurType = BaseE->getType().getNonReferenceType();
22878
22879 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
22880 // A list item cannot be a variable that is a member of a structure with
22881 // a union type.
22882 //
22883 if (CurType->isUnionType()) {
22884 if (!NoDiagnose) {
22885 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_union_type_not_allowed)
22886 << ME->getSourceRange();
22887 return false;
22888 }
22889 return RelevantExpr || Visit(S: E);
22890 }
22891
22892 // If we got a member expression, we should not expect any array section
22893 // before that:
22894 //
22895 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
22896 // If a list item is an element of a structure, only the rightmost symbol
22897 // of the variable reference can be an array section.
22898 //
22899 AllowUnitySizeArraySection = false;
22900 AllowWholeSizeArraySection = false;
22901
22902 // Record the component.
22903 Components.emplace_back(Args&: ME, Args&: FD, Args&: IsNonContiguous);
22904 return RelevantExpr || Visit(S: E);
22905 }
22906
22907 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
22908 Expr *E = AE->getBase()->IgnoreParenImpCasts();
22909
22910 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
22911 if (!NoDiagnose) {
22912 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
22913 << 0 << AE->getSourceRange();
22914 return false;
22915 }
22916 return RelevantExpr || Visit(S: E);
22917 }
22918
22919 // If we got an array subscript that express the whole dimension we
22920 // can have any array expressions before. If it only expressing part of
22921 // the dimension, we can only have unitary-size array expressions.
22922 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, E: AE, BaseQTy: E->getType()))
22923 AllowWholeSizeArraySection = false;
22924
22925 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E->IgnoreParenCasts())) {
22926 Expr::EvalResult Result;
22927 if (!AE->getIdx()->isValueDependent() &&
22928 AE->getIdx()->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()) &&
22929 !Result.Val.getInt().isZero()) {
22930 SemaRef.Diag(Loc: AE->getIdx()->getExprLoc(),
22931 DiagID: diag::err_omp_invalid_map_this_expr);
22932 SemaRef.Diag(Loc: AE->getIdx()->getExprLoc(),
22933 DiagID: diag::note_omp_invalid_subscript_on_this_ptr_map);
22934 }
22935 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22936 RelevantExpr = TE;
22937 }
22938
22939 // Record the component - we don't have any declaration associated.
22940 Components.emplace_back(Args&: AE, Args: nullptr, Args&: IsNonContiguous);
22941
22942 return RelevantExpr || Visit(S: E);
22943 }
22944
22945 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
22946 // After OMP 5.0 Array section in reduction clause will be implicitly
22947 // mapped
22948 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
22949 "Array sections cannot be implicitly mapped.");
22950 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22951 QualType CurType =
22952 ArraySectionExpr::getBaseOriginalType(Base: E).getCanonicalType();
22953
22954 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22955 // If the type of a list item is a reference to a type T then the type
22956 // will be considered to be T for all purposes of this clause.
22957 if (CurType->isReferenceType())
22958 CurType = CurType->getPointeeType();
22959
22960 bool IsPointer = CurType->isAnyPointerType();
22961
22962 if (!IsPointer && !CurType->isArrayType()) {
22963 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
22964 << 0 << OASE->getSourceRange();
22965 return false;
22966 }
22967
22968 bool NotWhole =
22969 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, E: OASE, BaseQTy: CurType);
22970 bool NotUnity =
22971 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, E: OASE, BaseQTy: CurType);
22972
22973 if (AllowWholeSizeArraySection) {
22974 // Any array section is currently allowed. Allowing a whole size array
22975 // section implies allowing a unity array section as well.
22976 //
22977 // If this array section refers to the whole dimension we can still
22978 // accept other array sections before this one, except if the base is a
22979 // pointer. Otherwise, only unitary sections are accepted.
22980 if (NotWhole || IsPointer)
22981 AllowWholeSizeArraySection = false;
22982 } else if (DKind == OMPD_target_update &&
22983 SemaRef.getLangOpts().OpenMP >= 50) {
22984 if (IsPointer && !AllowAnotherPtr)
22985 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_section_length_undefined)
22986 << /*array of unknown bound */ 1;
22987 else
22988 IsNonContiguous = true;
22989 } else if (AllowUnitySizeArraySection && NotUnity) {
22990 // A unity or whole array section is not allowed and that is not
22991 // compatible with the properties of the current array section.
22992 if (NoDiagnose)
22993 return false;
22994 SemaRef.Diag(Loc: ELoc,
22995 DiagID: diag::err_array_section_does_not_specify_contiguous_storage)
22996 << OASE->getSourceRange();
22997 return false;
22998 }
22999
23000 if (IsPointer)
23001 AllowAnotherPtr = false;
23002
23003 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E)) {
23004 Expr::EvalResult ResultR;
23005 Expr::EvalResult ResultL;
23006 if (!OASE->getLength()->isValueDependent() &&
23007 OASE->getLength()->EvaluateAsInt(Result&: ResultR, Ctx: SemaRef.getASTContext()) &&
23008 !ResultR.Val.getInt().isOne()) {
23009 SemaRef.Diag(Loc: OASE->getLength()->getExprLoc(),
23010 DiagID: diag::err_omp_invalid_map_this_expr);
23011 SemaRef.Diag(Loc: OASE->getLength()->getExprLoc(),
23012 DiagID: diag::note_omp_invalid_length_on_this_ptr_mapping);
23013 }
23014 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
23015 OASE->getLowerBound()->EvaluateAsInt(Result&: ResultL,
23016 Ctx: SemaRef.getASTContext()) &&
23017 !ResultL.Val.getInt().isZero()) {
23018 SemaRef.Diag(Loc: OASE->getLowerBound()->getExprLoc(),
23019 DiagID: diag::err_omp_invalid_map_this_expr);
23020 SemaRef.Diag(Loc: OASE->getLowerBound()->getExprLoc(),
23021 DiagID: diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
23022 }
23023 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
23024 RelevantExpr = TE;
23025 }
23026
23027 // Record the component - we don't have any declaration associated.
23028 Components.emplace_back(Args&: OASE, Args: nullptr, /*IsNonContiguous=*/Args: false);
23029 return RelevantExpr || Visit(S: E);
23030 }
23031 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
23032 Expr *Base = E->getBase();
23033
23034 // Record the component - we don't have any declaration associated.
23035 Components.emplace_back(Args&: E, Args: nullptr, Args&: IsNonContiguous);
23036
23037 return Visit(S: Base->IgnoreParenImpCasts());
23038 }
23039
23040 bool VisitUnaryOperator(UnaryOperator *UO) {
23041 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
23042 UO->getOpcode() != UO_Deref) {
23043 emitErrorMsg();
23044 return false;
23045 }
23046 if (!RelevantExpr) {
23047 // Record the component if haven't found base decl.
23048 Components.emplace_back(Args&: UO, Args: nullptr, /*IsNonContiguous=*/Args: false);
23049 }
23050 return RelevantExpr || Visit(S: UO->getSubExpr()->IgnoreParenImpCasts());
23051 }
23052 bool VisitBinaryOperator(BinaryOperator *BO) {
23053 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
23054 emitErrorMsg();
23055 return false;
23056 }
23057
23058 // Pointer arithmetic is the only thing we expect to happen here so after we
23059 // make sure the binary operator is a pointer type, the only thing we need
23060 // to do is to visit the subtree that has the same type as root (so that we
23061 // know the other subtree is just an offset)
23062 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
23063 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
23064 Components.emplace_back(Args&: BO, Args: nullptr, Args: false);
23065 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
23066 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
23067 "Either LHS or RHS have base decl inside");
23068 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
23069 return RelevantExpr || Visit(S: LE);
23070 return RelevantExpr || Visit(S: RE);
23071 }
23072 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
23073 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
23074 RelevantExpr = CTE;
23075 Components.emplace_back(Args&: CTE, Args: nullptr, Args&: IsNonContiguous);
23076 return true;
23077 }
23078 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
23079 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
23080 Components.emplace_back(Args&: COCE, Args: nullptr, Args&: IsNonContiguous);
23081 return true;
23082 }
23083 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
23084 Expr *Source = E->getSourceExpr();
23085 if (!Source) {
23086 emitErrorMsg();
23087 return false;
23088 }
23089 return Visit(S: Source);
23090 }
23091 bool VisitStmt(Stmt *) {
23092 emitErrorMsg();
23093 return false;
23094 }
23095 const Expr *getFoundBase() const { return RelevantExpr; }
23096 explicit MapBaseChecker(
23097 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
23098 OMPClauseMappableExprCommon::MappableExprComponentList &Components,
23099 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
23100 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
23101 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
23102};
23103} // namespace
23104
23105/// Return the expression of the base of the mappable expression or null if it
23106/// cannot be determined and do all the necessary checks to see if the
23107/// expression is valid as a standalone mappable expression. In the process,
23108/// record all the components of the expression.
23109static const Expr *checkMapClauseExpressionBase(
23110 Sema &SemaRef, Expr *E,
23111 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
23112 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
23113 SourceLocation ELoc = E->getExprLoc();
23114 SourceRange ERange = E->getSourceRange();
23115 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
23116 ERange);
23117 if (Checker.Visit(S: E->IgnoreParens())) {
23118 // Check if the highest dimension array section has length specified
23119 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
23120 (CKind == OMPC_to || CKind == OMPC_from)) {
23121 auto CI = CurComponents.rbegin();
23122 auto CE = CurComponents.rend();
23123 for (; CI != CE; ++CI) {
23124 const auto *OASE =
23125 dyn_cast<ArraySectionExpr>(Val: CI->getAssociatedExpression());
23126 if (!OASE)
23127 continue;
23128 if (OASE && OASE->getLength())
23129 break;
23130 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_array_section_does_not_specify_length)
23131 << ERange;
23132 }
23133 }
23134 return Checker.getFoundBase();
23135 }
23136 return nullptr;
23137}
23138
23139// Return true if expression E associated with value VD has conflicts with other
23140// map information.
23141static bool checkMapConflicts(
23142 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
23143 bool CurrentRegionOnly,
23144 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
23145 OpenMPClauseKind CKind) {
23146 assert(VD && E);
23147 SourceLocation ELoc = E->getExprLoc();
23148 SourceRange ERange = E->getSourceRange();
23149
23150 // In order to easily check the conflicts we need to match each component of
23151 // the expression under test with the components of the expressions that are
23152 // already in the stack.
23153
23154 assert(!CurComponents.empty() && "Map clause expression with no components!");
23155 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
23156 "Map clause expression with unexpected base!");
23157
23158 // Variables to help detecting enclosing problems in data environment nests.
23159 bool IsEnclosedByDataEnvironmentExpr = false;
23160 const Expr *EnclosingExpr = nullptr;
23161
23162 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
23163 VD, CurrentRegionOnly,
23164 Check: [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
23165 ERange, CKind, &EnclosingExpr,
23166 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
23167 StackComponents,
23168 OpenMPClauseKind Kind) {
23169 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
23170 return false;
23171 assert(!StackComponents.empty() &&
23172 "Map clause expression with no components!");
23173 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
23174 "Map clause expression with unexpected base!");
23175 (void)VD;
23176
23177 // The whole expression in the stack.
23178 const Expr *RE = StackComponents.front().getAssociatedExpression();
23179
23180 // Expressions must start from the same base. Here we detect at which
23181 // point both expressions diverge from each other and see if we can
23182 // detect if the memory referred to both expressions is contiguous and
23183 // do not overlap.
23184 auto CI = CurComponents.rbegin();
23185 auto CE = CurComponents.rend();
23186 auto SI = StackComponents.rbegin();
23187 auto SE = StackComponents.rend();
23188 for (; CI != CE && SI != SE; ++CI, ++SI) {
23189
23190 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
23191 // At most one list item can be an array item derived from a given
23192 // variable in map clauses of the same construct.
23193 if (CurrentRegionOnly &&
23194 (isa<ArraySubscriptExpr>(Val: CI->getAssociatedExpression()) ||
23195 isa<ArraySectionExpr>(Val: CI->getAssociatedExpression()) ||
23196 isa<OMPArrayShapingExpr>(Val: CI->getAssociatedExpression())) &&
23197 (isa<ArraySubscriptExpr>(Val: SI->getAssociatedExpression()) ||
23198 isa<ArraySectionExpr>(Val: SI->getAssociatedExpression()) ||
23199 isa<OMPArrayShapingExpr>(Val: SI->getAssociatedExpression()))) {
23200 SemaRef.Diag(Loc: CI->getAssociatedExpression()->getExprLoc(),
23201 DiagID: diag::err_omp_multiple_array_items_in_map_clause)
23202 << CI->getAssociatedExpression()->getSourceRange();
23203 SemaRef.Diag(Loc: SI->getAssociatedExpression()->getExprLoc(),
23204 DiagID: diag::note_used_here)
23205 << SI->getAssociatedExpression()->getSourceRange();
23206 return true;
23207 }
23208
23209 // Do both expressions have the same kind?
23210 if (CI->getAssociatedExpression()->getStmtClass() !=
23211 SI->getAssociatedExpression()->getStmtClass())
23212 break;
23213
23214 // Are we dealing with different variables/fields?
23215 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
23216 break;
23217 }
23218 // Check if the extra components of the expressions in the enclosing
23219 // data environment are redundant for the current base declaration.
23220 // If they are, the maps completely overlap, which is legal.
23221 for (; SI != SE; ++SI) {
23222 QualType Type;
23223 if (const auto *ASE =
23224 dyn_cast<ArraySubscriptExpr>(Val: SI->getAssociatedExpression())) {
23225 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
23226 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
23227 Val: SI->getAssociatedExpression())) {
23228 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
23229 Type = ArraySectionExpr::getBaseOriginalType(Base: E).getCanonicalType();
23230 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
23231 Val: SI->getAssociatedExpression())) {
23232 Type = OASE->getBase()->getType()->getPointeeType();
23233 }
23234 if (Type.isNull() || Type->isAnyPointerType() ||
23235 checkArrayExpressionDoesNotReferToWholeSize(
23236 SemaRef, E: SI->getAssociatedExpression(), BaseQTy: Type))
23237 break;
23238 }
23239
23240 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
23241 // List items of map clauses in the same construct must not share
23242 // original storage.
23243 //
23244 // If the expressions are exactly the same or one is a subset of the
23245 // other, it means they are sharing storage.
23246 if (CI == CE && SI == SE) {
23247 if (CurrentRegionOnly) {
23248 if (CKind == OMPC_map) {
23249 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << ERange;
23250 } else {
23251 assert(CKind == OMPC_to || CKind == OMPC_from);
23252 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced_in_target_update)
23253 << ERange;
23254 }
23255 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
23256 << RE->getSourceRange();
23257 return true;
23258 }
23259 // If we find the same expression in the enclosing data environment,
23260 // that is legal.
23261 IsEnclosedByDataEnvironmentExpr = true;
23262 return false;
23263 }
23264
23265 QualType DerivedType =
23266 std::prev(x: CI)->getAssociatedDeclaration()->getType();
23267 SourceLocation DerivedLoc =
23268 std::prev(x: CI)->getAssociatedExpression()->getExprLoc();
23269
23270 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
23271 // If the type of a list item is a reference to a type T then the type
23272 // will be considered to be T for all purposes of this clause.
23273 DerivedType = DerivedType.getNonReferenceType();
23274
23275 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
23276 // A variable for which the type is pointer and an array section
23277 // derived from that variable must not appear as list items of map
23278 // clauses of the same construct.
23279 //
23280 // Also, cover one of the cases in:
23281 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
23282 // If any part of the original storage of a list item has corresponding
23283 // storage in the device data environment, all of the original storage
23284 // must have corresponding storage in the device data environment.
23285 //
23286 if (DerivedType->isAnyPointerType()) {
23287 if (CI == CE || SI == SE) {
23288 SemaRef.Diag(
23289 Loc: DerivedLoc,
23290 DiagID: diag::err_omp_pointer_mapped_along_with_derived_section)
23291 << DerivedLoc;
23292 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
23293 << RE->getSourceRange();
23294 return true;
23295 }
23296 if (CI->getAssociatedExpression()->getStmtClass() !=
23297 SI->getAssociatedExpression()->getStmtClass() ||
23298 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
23299 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
23300 assert(CI != CE && SI != SE);
23301 SemaRef.Diag(Loc: DerivedLoc, DiagID: diag::err_omp_same_pointer_dereferenced)
23302 << DerivedLoc;
23303 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
23304 << RE->getSourceRange();
23305 return true;
23306 }
23307 }
23308
23309 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
23310 // List items of map clauses in the same construct must not share
23311 // original storage.
23312 //
23313 // An expression is a subset of the other.
23314 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
23315 if (CKind == OMPC_map) {
23316 if (CI != CE || SI != SE) {
23317 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
23318 // a pointer.
23319 auto Begin =
23320 CI != CE ? CurComponents.begin() : StackComponents.begin();
23321 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
23322 auto It = Begin;
23323 while (It != End && !It->getAssociatedDeclaration())
23324 std::advance(i&: It, n: 1);
23325 assert(It != End &&
23326 "Expected at least one component with the declaration.");
23327 if (It != Begin && It->getAssociatedDeclaration()
23328 ->getType()
23329 .getCanonicalType()
23330 ->isAnyPointerType()) {
23331 IsEnclosedByDataEnvironmentExpr = false;
23332 EnclosingExpr = nullptr;
23333 return false;
23334 }
23335 }
23336 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << ERange;
23337 } else {
23338 assert(CKind == OMPC_to || CKind == OMPC_from);
23339 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced_in_target_update)
23340 << ERange;
23341 }
23342 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
23343 << RE->getSourceRange();
23344 return true;
23345 }
23346
23347 // The current expression uses the same base as other expression in the
23348 // data environment but does not contain it completely.
23349 if (!CurrentRegionOnly && SI != SE)
23350 EnclosingExpr = RE;
23351
23352 // The current expression is a subset of the expression in the data
23353 // environment.
23354 IsEnclosedByDataEnvironmentExpr |=
23355 (!CurrentRegionOnly && CI != CE && SI == SE);
23356
23357 return false;
23358 });
23359
23360 if (CurrentRegionOnly)
23361 return FoundError;
23362
23363 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
23364 // If any part of the original storage of a list item has corresponding
23365 // storage in the device data environment, all of the original storage must
23366 // have corresponding storage in the device data environment.
23367 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
23368 // If a list item is an element of a structure, and a different element of
23369 // the structure has a corresponding list item in the device data environment
23370 // prior to a task encountering the construct associated with the map clause,
23371 // then the list item must also have a corresponding list item in the device
23372 // data environment prior to the task encountering the construct.
23373 //
23374 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
23375 SemaRef.Diag(Loc: ELoc,
23376 DiagID: diag::err_omp_original_storage_is_shared_and_does_not_contain)
23377 << ERange;
23378 SemaRef.Diag(Loc: EnclosingExpr->getExprLoc(), DiagID: diag::note_used_here)
23379 << EnclosingExpr->getSourceRange();
23380 return true;
23381 }
23382
23383 return FoundError;
23384}
23385
23386// Look up the user-defined mapper given the mapper name and mapped type, and
23387// build a reference to it.
23388static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
23389 CXXScopeSpec &MapperIdScopeSpec,
23390 const DeclarationNameInfo &MapperId,
23391 QualType Type,
23392 Expr *UnresolvedMapper) {
23393 if (MapperIdScopeSpec.isInvalid())
23394 return ExprError();
23395 // Get the actual type for the array type.
23396 if (Type->isArrayType()) {
23397 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
23398 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
23399 }
23400 // Find all user-defined mappers with the given MapperId.
23401 SmallVector<UnresolvedSet<8>, 4> Lookups;
23402 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
23403 Lookup.suppressDiagnostics();
23404 if (S) {
23405 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &MapperIdScopeSpec,
23406 /*ObjectType=*/QualType())) {
23407 NamedDecl *D = Lookup.getRepresentativeDecl();
23408 while (S && !S->isDeclScope(D))
23409 S = S->getParent();
23410 if (S)
23411 S = S->getParent();
23412 Lookups.emplace_back();
23413 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
23414 Lookup.clear();
23415 }
23416 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(Val: UnresolvedMapper)) {
23417 // Extract the user-defined mappers with the given MapperId.
23418 Lookups.push_back(Elt: UnresolvedSet<8>());
23419 for (NamedDecl *D : ULE->decls()) {
23420 auto *DMD = cast<OMPDeclareMapperDecl>(Val: D);
23421 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
23422 Lookups.back().addDecl(D: DMD);
23423 }
23424 }
23425 // Defer the lookup for dependent types. The results will be passed through
23426 // UnresolvedMapper on instantiation.
23427 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
23428 Type->isInstantiationDependentType() ||
23429 Type->containsUnexpandedParameterPack() ||
23430 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
23431 return !D->isInvalidDecl() &&
23432 (D->getType()->isDependentType() ||
23433 D->getType()->isInstantiationDependentType() ||
23434 D->getType()->containsUnexpandedParameterPack());
23435 })) {
23436 UnresolvedSet<8> URS;
23437 for (const UnresolvedSet<8> &Set : Lookups) {
23438 if (Set.empty())
23439 continue;
23440 URS.append(I: Set.begin(), E: Set.end());
23441 }
23442 return UnresolvedLookupExpr::Create(
23443 Context: SemaRef.Context, /*NamingClass=*/nullptr,
23444 QualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: SemaRef.Context), NameInfo: MapperId,
23445 /*ADL=*/RequiresADL: false, Begin: URS.begin(), End: URS.end(), /*KnownDependent=*/false,
23446 /*KnownInstantiationDependent=*/false);
23447 }
23448 SourceLocation Loc = MapperId.getLoc();
23449 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23450 // The type must be of struct, union or class type in C and C++
23451 if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
23452 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
23453 SemaRef.Diag(Loc, DiagID: diag::err_omp_mapper_wrong_type);
23454 return ExprError();
23455 }
23456 // Perform argument dependent lookup.
23457 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
23458 argumentDependentLookup(SemaRef, Id: MapperId, Loc, Ty: Type, Lookups);
23459 // Return the first user-defined mapper with the desired type.
23460 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
23461 Lookups, Gen: [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
23462 if (!D->isInvalidDecl() &&
23463 SemaRef.Context.hasSameType(T1: D->getType(), T2: Type))
23464 return D;
23465 return nullptr;
23466 }))
23467 return SemaRef.BuildDeclRefExpr(D: VD, Ty: Type, VK: VK_LValue, Loc);
23468 // Find the first user-defined mapper with a type derived from the desired
23469 // type.
23470 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
23471 Lookups, Gen: [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
23472 if (!D->isInvalidDecl() &&
23473 SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: D->getType()) &&
23474 !Type.isMoreQualifiedThan(other: D->getType(),
23475 Ctx: SemaRef.getASTContext()))
23476 return D;
23477 return nullptr;
23478 })) {
23479 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
23480 /*DetectVirtual=*/false);
23481 if (SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: VD->getType(), Paths)) {
23482 if (!Paths.isAmbiguous(BaseType: SemaRef.Context.getCanonicalType(
23483 T: VD->getType().getUnqualifiedType()))) {
23484 if (SemaRef.CheckBaseClassAccess(
23485 AccessLoc: Loc, Base: VD->getType(), Derived: Type, Path: Paths.front(),
23486 /*DiagID=*/0) != Sema::AR_inaccessible) {
23487 return SemaRef.BuildDeclRefExpr(D: VD, Ty: Type, VK: VK_LValue, Loc);
23488 }
23489 }
23490 }
23491 }
23492 // Report error if a mapper is specified, but cannot be found.
23493 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
23494 SemaRef.Diag(Loc, DiagID: diag::err_omp_invalid_mapper)
23495 << Type << MapperId.getName();
23496 return ExprError();
23497 }
23498 return ExprEmpty();
23499}
23500
23501namespace {
23502// Utility struct that gathers all the related lists associated with a mappable
23503// expression.
23504struct MappableVarListInfo {
23505 // The list of expressions.
23506 ArrayRef<Expr *> VarList;
23507 // The list of processed expressions.
23508 SmallVector<Expr *, 16> ProcessedVarList;
23509 // The mappble components for each expression.
23510 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
23511 // The base declaration of the variable.
23512 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
23513 // The reference to the user-defined mapper associated with every expression.
23514 SmallVector<Expr *, 16> UDMapperList;
23515
23516 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
23517 // We have a list of components and base declarations for each entry in the
23518 // variable list.
23519 VarComponents.reserve(N: VarList.size());
23520 VarBaseDeclarations.reserve(N: VarList.size());
23521 }
23522};
23523} // namespace
23524
23525static DeclRefExpr *buildImplicitMap(Sema &S, QualType BaseType,
23526 DSAStackTy *Stack,
23527 SmallVectorImpl<OMPClause *> &Maps) {
23528
23529 const RecordDecl *RD = BaseType->getAsRecordDecl();
23530 SourceRange Range = RD->getSourceRange();
23531 DeclarationNameInfo ImplicitName;
23532 // Dummy variable _s for Mapper.
23533 VarDecl *VD = buildVarDecl(SemaRef&: S, Loc: Range.getEnd(), Type: BaseType, Name: "_s");
23534 DeclRefExpr *MapperVarRef =
23535 buildDeclRefExpr(S, D: VD, Ty: BaseType, Loc: SourceLocation());
23536
23537 // Create implicit map clause for mapper.
23538 SmallVector<Expr *, 4> SExprs;
23539 for (auto *FD : RD->fields()) {
23540 Expr *BE = S.BuildMemberExpr(
23541 Base: MapperVarRef, /*IsArrow=*/false, OpLoc: Range.getBegin(),
23542 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: Range.getBegin(), Member: FD,
23543 FoundDecl: DeclAccessPair::make(D: FD, AS: FD->getAccess()),
23544 /*HadMultipleCandidates=*/false,
23545 MemberNameInfo: DeclarationNameInfo(FD->getDeclName(), FD->getSourceRange().getBegin()),
23546 Ty: FD->getType(), VK: VK_LValue, OK: OK_Ordinary);
23547 SExprs.push_back(Elt: BE);
23548 }
23549 CXXScopeSpec MapperIdScopeSpec;
23550 DeclarationNameInfo MapperId;
23551 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
23552
23553 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
23554 IteratorModifier: nullptr, MapTypeModifiers: OMPC_MAP_MODIFIER_unknown, MapTypeModifiersLoc: SourceLocation(), MapperIdScopeSpec,
23555 MapperId, MapType: DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
23556 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(), VarList: SExprs,
23557 Locs: OMPVarListLocTy());
23558 Maps.push_back(Elt: MapClause);
23559 return MapperVarRef;
23560}
23561
23562static ExprResult buildImplicitMapper(Sema &S, QualType BaseType,
23563 DSAStackTy *Stack) {
23564
23565 // Build impilicit map for mapper
23566 SmallVector<OMPClause *, 4> Maps;
23567 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
23568
23569 const RecordDecl *RD = BaseType->getAsRecordDecl();
23570 // AST context is RD's ParentASTContext().
23571 ASTContext &Ctx = RD->getParentASTContext();
23572 // DeclContext is RD's DeclContext.
23573 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
23574
23575 // Create implicit default mapper for "RD".
23576 DeclarationName MapperId;
23577 auto &DeclNames = Ctx.DeclarationNames;
23578 MapperId = DeclNames.getIdentifier(ID: &Ctx.Idents.get(Name: "default"));
23579 auto *DMD = OMPDeclareMapperDecl::Create(C&: Ctx, DC: DCT, L: SourceLocation(), Name: MapperId,
23580 T: BaseType, VarName: MapperId, Clauses: Maps, PrevDeclInScope: nullptr);
23581 Scope *Scope = S.getScopeForContext(Ctx: DCT);
23582 if (Scope)
23583 S.PushOnScopeChains(D: DMD, S: Scope, /*AddToContext=*/false);
23584 DCT->addDecl(D: DMD);
23585 DMD->setAccess(clang::AS_none);
23586 auto *VD = cast<DeclRefExpr>(Val: MapperVarRef)->getDecl();
23587 VD->setDeclContext(DMD);
23588 VD->setLexicalDeclContext(DMD);
23589 DMD->addDecl(D: VD);
23590 DMD->setMapperVarRef(MapperVarRef);
23591 FieldDecl *FD = *RD->field_begin();
23592 // create mapper refence.
23593 return DeclRefExpr::Create(Context: Ctx, QualifierLoc: NestedNameSpecifierLoc{}, TemplateKWLoc: FD->getLocation(),
23594 D: DMD, RefersToEnclosingVariableOrCapture: false, NameLoc: SourceLocation(), T: BaseType, VK: VK_LValue);
23595}
23596
23597// Look up the user-defined mapper given the mapper name and mapper type,
23598// return true if found one.
23599static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
23600 CXXScopeSpec &MapperIdScopeSpec,
23601 const DeclarationNameInfo &MapperId,
23602 QualType Type) {
23603 // Find all user-defined mappers with the given MapperId.
23604 SmallVector<UnresolvedSet<8>, 4> Lookups;
23605 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
23606 Lookup.suppressDiagnostics();
23607 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &MapperIdScopeSpec,
23608 /*ObjectType=*/QualType())) {
23609 NamedDecl *D = Lookup.getRepresentativeDecl();
23610 while (S && !S->isDeclScope(D))
23611 S = S->getParent();
23612 if (S)
23613 S = S->getParent();
23614 Lookups.emplace_back();
23615 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
23616 Lookup.clear();
23617 }
23618 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
23619 Type->isInstantiationDependentType() ||
23620 Type->containsUnexpandedParameterPack() ||
23621 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
23622 return !D->isInvalidDecl() &&
23623 (D->getType()->isDependentType() ||
23624 D->getType()->isInstantiationDependentType() ||
23625 D->getType()->containsUnexpandedParameterPack());
23626 }))
23627 return false;
23628 // Perform argument dependent lookup.
23629 SourceLocation Loc = MapperId.getLoc();
23630 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
23631 argumentDependentLookup(SemaRef, Id: MapperId, Loc, Ty: Type, Lookups);
23632 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
23633 Lookups, Gen: [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
23634 if (!D->isInvalidDecl() &&
23635 SemaRef.Context.hasSameType(T1: D->getType(), T2: Type))
23636 return D;
23637 return nullptr;
23638 }))
23639 return true;
23640 // Find the first user-defined mapper with a type derived from the desired
23641 // type.
23642 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
23643 Lookups, Gen: [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
23644 if (!D->isInvalidDecl() &&
23645 SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: D->getType()) &&
23646 !Type.isMoreQualifiedThan(other: D->getType(), Ctx: SemaRef.getASTContext()))
23647 return D;
23648 return nullptr;
23649 });
23650 if (!VD)
23651 return false;
23652 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
23653 /*DetectVirtual=*/false);
23654 if (SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: VD->getType(), Paths)) {
23655 bool IsAmbiguous = !Paths.isAmbiguous(
23656 BaseType: SemaRef.Context.getCanonicalType(T: VD->getType().getUnqualifiedType()));
23657 if (IsAmbiguous)
23658 return false;
23659 if (SemaRef.CheckBaseClassAccess(AccessLoc: Loc, Base: VD->getType(), Derived: Type, Path: Paths.front(),
23660 /*DiagID=*/0) != Sema::AR_inaccessible)
23661 return true;
23662 }
23663 return false;
23664}
23665
23666static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
23667 QualType CanonType, const Expr *E) {
23668
23669 // DFS over data members in structures/classes.
23670 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(1,
23671 {CanonType, nullptr});
23672 llvm::DenseMap<const Type *, bool> Visited;
23673 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
23674 while (!Types.empty()) {
23675 auto [BaseType, CurFD] = Types.pop_back_val();
23676 while (ParentChain.back().second == 0)
23677 ParentChain.pop_back();
23678 --ParentChain.back().second;
23679 if (BaseType.isNull())
23680 continue;
23681 // Only structs/classes are allowed to have mappers.
23682 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
23683 if (!RD)
23684 continue;
23685 auto It = Visited.find(Val: BaseType.getTypePtr());
23686 if (It == Visited.end()) {
23687 // Try to find the associated user-defined mapper.
23688 CXXScopeSpec MapperIdScopeSpec;
23689 DeclarationNameInfo DefaultMapperId;
23690 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
23691 ID: &S.Context.Idents.get(Name: "default")));
23692 DefaultMapperId.setLoc(E->getExprLoc());
23693 bool HasUDMapper =
23694 hasUserDefinedMapper(SemaRef&: S, S: Stack->getCurScope(), MapperIdScopeSpec,
23695 MapperId: DefaultMapperId, Type: BaseType);
23696 It = Visited.try_emplace(Key: BaseType.getTypePtr(), Args&: HasUDMapper).first;
23697 }
23698 // Found default mapper.
23699 if (It->second)
23700 return true;
23701 // Check for the "default" mapper for data members.
23702 bool FirstIter = true;
23703 for (FieldDecl *FD : RD->fields()) {
23704 if (!FD)
23705 continue;
23706 QualType FieldTy = FD->getType();
23707 if (FieldTy.isNull() ||
23708 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
23709 continue;
23710 if (FirstIter) {
23711 FirstIter = false;
23712 ParentChain.emplace_back(Args&: CurFD, Args: 1);
23713 } else {
23714 ++ParentChain.back().second;
23715 }
23716 Types.emplace_back(Args&: FieldTy, Args&: FD);
23717 }
23718 }
23719 return false;
23720}
23721
23722// Check the validity of the provided variable list for the provided clause kind
23723// \a CKind. In the check process the valid expressions, mappable expression
23724// components, variables, and user-defined mappers are extracted and used to
23725// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
23726// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
23727// and \a MapperId are expected to be valid if the clause kind is 'map'.
23728static void checkMappableExpressionList(
23729 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
23730 MappableVarListInfo &MVLI, SourceLocation StartLoc,
23731 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
23732 ArrayRef<Expr *> UnresolvedMappers,
23733 OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
23734 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
23735 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
23736 // We only expect mappable expressions in 'to', 'from', 'map', and
23737 // 'use_device_addr' clauses.
23738 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from ||
23739 CKind == OMPC_use_device_addr) &&
23740 "Unexpected clause kind with mappable expressions!");
23741 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
23742
23743 // If the identifier of user-defined mapper is not specified, it is "default".
23744 // We do not change the actual name in this clause to distinguish whether a
23745 // mapper is specified explicitly, i.e., it is not explicitly specified when
23746 // MapperId.getName() is empty.
23747 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
23748 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
23749 MapperId.setName(DeclNames.getIdentifier(
23750 ID: &SemaRef.getASTContext().Idents.get(Name: "default")));
23751 MapperId.setLoc(StartLoc);
23752 }
23753
23754 // Iterators to find the current unresolved mapper expression.
23755 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
23756 bool UpdateUMIt = false;
23757 Expr *UnresolvedMapper = nullptr;
23758
23759 bool HasHoldModifier =
23760 llvm::is_contained(Range&: Modifiers, Element: OMPC_MAP_MODIFIER_ompx_hold);
23761
23762 // Keep track of the mappable components and base declarations in this clause.
23763 // Each entry in the list is going to have a list of components associated. We
23764 // record each set of the components so that we can build the clause later on.
23765 // In the end we should have the same amount of declarations and component
23766 // lists.
23767
23768 for (Expr *RE : MVLI.VarList) {
23769 assert(RE && "Null expr in omp to/from/map clause");
23770 SourceLocation ELoc = RE->getExprLoc();
23771
23772 // Find the current unresolved mapper expression.
23773 if (UpdateUMIt && UMIt != UMEnd) {
23774 UMIt++;
23775 assert(
23776 UMIt != UMEnd &&
23777 "Expect the size of UnresolvedMappers to match with that of VarList");
23778 }
23779 UpdateUMIt = true;
23780 if (UMIt != UMEnd)
23781 UnresolvedMapper = *UMIt;
23782
23783 const Expr *VE = RE->IgnoreParenLValueCasts();
23784
23785 if (VE->isValueDependent() || VE->isTypeDependent() ||
23786 VE->isInstantiationDependent() ||
23787 VE->containsUnexpandedParameterPack()) {
23788 // Try to find the associated user-defined mapper.
23789 ExprResult ER = buildUserDefinedMapperRef(
23790 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23791 Type: VE->getType().getCanonicalType(), UnresolvedMapper);
23792 if (ER.isInvalid())
23793 continue;
23794 MVLI.UDMapperList.push_back(Elt: ER.get());
23795 // We can only analyze this information once the missing information is
23796 // resolved.
23797 MVLI.ProcessedVarList.push_back(Elt: RE);
23798 continue;
23799 }
23800
23801 Expr *SimpleExpr = RE->IgnoreParenCasts();
23802
23803 if (!RE->isLValue()) {
23804 if (SemaRef.getLangOpts().OpenMP < 50) {
23805 SemaRef.Diag(
23806 Loc: ELoc, DiagID: diag::err_omp_expected_named_var_member_or_array_expression)
23807 << RE->getSourceRange();
23808 } else {
23809 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_non_lvalue_in_map_or_motion_clauses)
23810 << getOpenMPClauseNameForDiag(C: CKind) << RE->getSourceRange();
23811 }
23812 continue;
23813 }
23814
23815 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
23816 ValueDecl *CurDeclaration = nullptr;
23817
23818 // Obtain the array or member expression bases if required. Also, fill the
23819 // components array with all the components identified in the process.
23820 const Expr *BE =
23821 checkMapClauseExpressionBase(SemaRef, E: SimpleExpr, CurComponents, CKind,
23822 DKind: DSAS->getCurrentDirective(), NoDiagnose);
23823 if (!BE)
23824 continue;
23825
23826 assert(!CurComponents.empty() &&
23827 "Invalid mappable expression information.");
23828
23829 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: BE)) {
23830 // Add store "this" pointer to class in DSAStackTy for future checking
23831 DSAS->addMappedClassesQualTypes(QT: TE->getType());
23832 // Try to find the associated user-defined mapper.
23833 ExprResult ER = buildUserDefinedMapperRef(
23834 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23835 Type: VE->getType().getCanonicalType(), UnresolvedMapper);
23836 if (ER.isInvalid())
23837 continue;
23838 MVLI.UDMapperList.push_back(Elt: ER.get());
23839 // Skip restriction checking for variable or field declarations
23840 MVLI.ProcessedVarList.push_back(Elt: RE);
23841 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
23842 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
23843 in_end: CurComponents.end());
23844 MVLI.VarBaseDeclarations.push_back(Elt: nullptr);
23845 continue;
23846 }
23847
23848 // For the following checks, we rely on the base declaration which is
23849 // expected to be associated with the last component. The declaration is
23850 // expected to be a variable or a field (if 'this' is being mapped).
23851 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
23852 assert(CurDeclaration && "Null decl on map clause.");
23853 assert(
23854 CurDeclaration->isCanonicalDecl() &&
23855 "Expecting components to have associated only canonical declarations.");
23856
23857 auto *VD = dyn_cast<VarDecl>(Val: CurDeclaration);
23858 const auto *FD = dyn_cast<FieldDecl>(Val: CurDeclaration);
23859
23860 assert((VD || FD) && "Only variables or fields are expected here!");
23861 (void)FD;
23862
23863 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
23864 // threadprivate variables cannot appear in a map clause.
23865 // OpenMP 4.5 [2.10.5, target update Construct]
23866 // threadprivate variables cannot appear in a from clause.
23867 if (VD && DSAS->isThreadPrivate(D: VD)) {
23868 if (NoDiagnose)
23869 continue;
23870 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(D: VD, /*FromParent=*/false);
23871 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_threadprivate_in_clause)
23872 << getOpenMPClauseNameForDiag(C: CKind);
23873 reportOriginalDsa(SemaRef, Stack: DSAS, D: VD, DVar);
23874 continue;
23875 }
23876
23877 // OpenMP 6.0 [7.9.6, map Clause, Restrictions, p. 386]
23878 // A device-local variable must not appear as a list item in a map clause.
23879 if (VD && CKind == OMPC_map) {
23880 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23881 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
23882 if (*Res == OMPDeclareTargetDeclAttr::MT_Local) {
23883 if (NoDiagnose)
23884 continue;
23885 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_device_local_in_clause)
23886 << VD << getOpenMPClauseNameForDiag(C: CKind);
23887 continue;
23888 }
23889 }
23890 }
23891
23892 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23893 // A list item cannot appear in both a map clause and a data-sharing
23894 // attribute clause on the same construct.
23895
23896 // Check conflicts with other map clause expressions. We check the conflicts
23897 // with the current construct separately from the enclosing data
23898 // environment, because the restrictions are different. We only have to
23899 // check conflicts across regions for the map clauses.
23900 if (checkMapConflicts(SemaRef, DSAS, VD: CurDeclaration, E: SimpleExpr,
23901 /*CurrentRegionOnly=*/true, CurComponents, CKind))
23902 break;
23903 if (CKind == OMPC_map &&
23904 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
23905 checkMapConflicts(SemaRef, DSAS, VD: CurDeclaration, E: SimpleExpr,
23906 /*CurrentRegionOnly=*/false, CurComponents, CKind))
23907 break;
23908
23909 // OpenMP 4.5 [2.10.5, target update Construct]
23910 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
23911 // If the type of a list item is a reference to a type T then the type will
23912 // be considered to be T for all purposes of this clause.
23913 auto I = llvm::find_if(
23914 Range&: CurComponents,
23915 P: [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
23916 return MC.getAssociatedDeclaration();
23917 });
23918 assert(I != CurComponents.end() && "Null decl on map clause.");
23919 (void)I;
23920 QualType Type;
23921 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: VE->IgnoreParens());
23922 auto *OASE = dyn_cast<ArraySectionExpr>(Val: VE->IgnoreParens());
23923 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(Val: VE->IgnoreParens());
23924 if (ASE) {
23925 Type = ASE->getType().getNonReferenceType();
23926 } else if (OASE) {
23927 QualType BaseType =
23928 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
23929 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
23930 Type = ATy->getElementType();
23931 else
23932 Type = BaseType->getPointeeType();
23933 Type = Type.getNonReferenceType();
23934 } else if (OAShE) {
23935 Type = OAShE->getBase()->getType()->getPointeeType();
23936 } else {
23937 Type = VE->getType();
23938 }
23939
23940 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
23941 // A list item in a to or from clause must have a mappable type.
23942 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23943 // A list item must have a mappable type.
23944 if (!checkTypeMappable(SL: VE->getExprLoc(), SR: VE->getSourceRange(), SemaRef,
23945 Stack: DSAS, QTy: Type, /*FullCheck=*/true))
23946 continue;
23947
23948 if (CKind == OMPC_map) {
23949 // target enter data
23950 // OpenMP [2.10.2, Restrictions, p. 99]
23951 // A map-type must be specified in all map clauses and must be either
23952 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
23953 // no map type is present.
23954 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
23955 if (DKind == OMPD_target_enter_data &&
23956 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
23957 SemaRef.getLangOpts().OpenMP >= 52)) {
23958 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
23959 << (IsMapTypeImplicit ? 1 : 0)
23960 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
23961 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
23962 continue;
23963 }
23964
23965 // target exit_data
23966 // OpenMP [2.10.3, Restrictions, p. 102]
23967 // A map-type must be specified in all map clauses and must be either
23968 // from, release, or delete. Starting with OpenMP 5.2 the default map
23969 // type is `from` if no map type is present.
23970 if (DKind == OMPD_target_exit_data &&
23971 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
23972 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
23973 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
23974 << (IsMapTypeImplicit ? 1 : 0)
23975 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
23976 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
23977 continue;
23978 }
23979
23980 // The 'ompx_hold' modifier is specifically intended to be used on a
23981 // 'target' or 'target data' directive to prevent data from being unmapped
23982 // during the associated statement. It is not permitted on a 'target
23983 // enter data' or 'target exit data' directive, which have no associated
23984 // statement.
23985 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
23986 HasHoldModifier) {
23987 SemaRef.Diag(Loc: StartLoc,
23988 DiagID: diag::err_omp_invalid_map_type_modifier_for_directive)
23989 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map,
23990 Type: OMPC_MAP_MODIFIER_ompx_hold)
23991 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
23992 continue;
23993 }
23994
23995 // target, target data
23996 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
23997 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
23998 // A map-type in a map clause must be to, from, tofrom or alloc
23999 if ((DKind == OMPD_target_data ||
24000 isOpenMPTargetExecutionDirective(DKind)) &&
24001 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
24002 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
24003 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
24004 << (IsMapTypeImplicit ? 1 : 0)
24005 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
24006 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
24007 continue;
24008 }
24009
24010 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
24011 // A list item cannot appear in both a map clause and a data-sharing
24012 // attribute clause on the same construct
24013 //
24014 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
24015 // A list item cannot appear in both a map clause and a data-sharing
24016 // attribute clause on the same construct unless the construct is a
24017 // combined construct.
24018 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
24019 isOpenMPTargetExecutionDirective(DKind)) ||
24020 DKind == OMPD_target)) {
24021 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(D: VD, /*FromParent=*/false);
24022 if (isOpenMPPrivate(Kind: DVar.CKind)) {
24023 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
24024 << getOpenMPClauseNameForDiag(C: DVar.CKind)
24025 << getOpenMPClauseNameForDiag(C: OMPC_map)
24026 << getOpenMPDirectiveName(D: DSAS->getCurrentDirective(),
24027 Ver: OMPVersion);
24028 reportOriginalDsa(SemaRef, Stack: DSAS, D: CurDeclaration, DVar);
24029 continue;
24030 }
24031 }
24032 }
24033
24034 // Try to find the associated user-defined mapper.
24035 ExprResult ER = buildUserDefinedMapperRef(
24036 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
24037 Type: Type.getCanonicalType(), UnresolvedMapper);
24038 if (ER.isInvalid())
24039 continue;
24040
24041 // If no user-defined mapper is found, we need to create an implicit one for
24042 // arrays/array-sections on structs that have members that have
24043 // user-defined mappers. This is needed to ensure that the mapper for the
24044 // member is invoked when mapping each element of the array/array-section.
24045 if (!ER.get()) {
24046 QualType BaseType;
24047
24048 if (isa<ArraySectionExpr>(Val: VE)) {
24049 BaseType = VE->getType().getCanonicalType();
24050 if (BaseType->isSpecificBuiltinType(K: BuiltinType::ArraySection)) {
24051 const auto *OASE = cast<ArraySectionExpr>(Val: VE->IgnoreParenImpCasts());
24052 QualType BType =
24053 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
24054 QualType ElemType;
24055 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
24056 ElemType = ATy->getElementType();
24057 else
24058 ElemType = BType->getPointeeType();
24059 BaseType = ElemType.getCanonicalType();
24060 }
24061 } else if (VE->getType()->isArrayType()) {
24062 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
24063 const QualType ElemType = AT->getElementType();
24064 BaseType = ElemType.getCanonicalType();
24065 }
24066
24067 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
24068 isImplicitMapperNeeded(S&: SemaRef, Stack: DSAS, CanonType: BaseType, E: VE)) {
24069 ER = buildImplicitMapper(S&: SemaRef, BaseType, Stack: DSAS);
24070 }
24071 }
24072 MVLI.UDMapperList.push_back(Elt: ER.get());
24073
24074 // Save the current expression.
24075 MVLI.ProcessedVarList.push_back(Elt: RE);
24076
24077 // Store the components in the stack so that they can be used to check
24078 // against other clauses later on.
24079 DSAS->addMappableExpressionComponents(VD: CurDeclaration, Components: CurComponents,
24080 /*WhereFoundClauseKind=*/OMPC_map);
24081
24082 // Save the components and declaration to create the clause. For purposes of
24083 // the clause creation, any component list that has base 'this' uses
24084 // null as base declaration.
24085 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
24086 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
24087 in_end: CurComponents.end());
24088 MVLI.VarBaseDeclarations.push_back(Elt: isa<MemberExpr>(Val: BE) ? nullptr
24089 : CurDeclaration);
24090 }
24091}
24092
24093OMPClause *SemaOpenMP::ActOnOpenMPMapClause(
24094 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
24095 ArrayRef<SourceLocation> MapTypeModifiersLoc,
24096 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
24097 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
24098 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
24099 const OMPVarListLocTy &Locs, bool NoDiagnose,
24100 ArrayRef<Expr *> UnresolvedMappers) {
24101 OpenMPMapModifierKind Modifiers[] = {
24102 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
24103 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
24104 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
24105 OMPC_MAP_MODIFIER_unknown};
24106 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
24107
24108 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
24109 K: BuiltinType::OMPIterator))
24110 Diag(Loc: IteratorModifier->getExprLoc(),
24111 DiagID: diag::err_omp_map_modifier_not_iterator);
24112
24113 // Process map-type-modifiers, flag errors for duplicate modifiers.
24114 unsigned Count = 0;
24115 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
24116 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
24117 llvm::is_contained(Range&: Modifiers, Element: MapTypeModifiers[I])) {
24118 Diag(Loc: MapTypeModifiersLoc[I], DiagID: diag::err_omp_duplicate_map_type_modifier);
24119 continue;
24120 }
24121 assert(Count < NumberOfOMPMapClauseModifiers &&
24122 "Modifiers exceed the allowed number of map type modifiers");
24123 Modifiers[Count] = MapTypeModifiers[I];
24124 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
24125 ++Count;
24126 }
24127
24128 MappableVarListInfo MVLI(VarList);
24129 // Per OpenMP 6.0 p299 lines 3-4, a list item with the const specifier and
24130 // no mutable members is ignored for 'from' clauses. A const-qualified
24131 // variable cannot be modified on the device, so copying back to the host
24132 // is unnecessary and potentially unsafe. Strip the FROM component:
24133 // map(tofrom:) -> map(to:), map(from:) -> map(alloc:).
24134 for (auto *E : VarList) {
24135 if ((MapType == OMPC_MAP_from || MapType == OMPC_MAP_tofrom) &&
24136 hasConstQualifiedMappingType(T: E->getType()))
24137 MapType = (MapType == OMPC_MAP_tofrom) ? OMPC_MAP_to : OMPC_MAP_alloc;
24138 }
24139 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_map, MVLI, StartLoc: Locs.StartLoc,
24140 MapperIdScopeSpec, MapperId, UnresolvedMappers,
24141 MapType, Modifiers, IsMapTypeImplicit,
24142 NoDiagnose);
24143
24144 // We need to produce a map clause even if we don't have variables so that
24145 // other diagnostics related with non-existing map clauses are accurate.
24146 return OMPMapClause::Create(
24147 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
24148 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, IteratorModifier, MapModifiers: Modifiers,
24149 MapModifiersLoc: ModifiersLoc, UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()),
24150 MapperId, Type: MapType, TypeIsImplicit: IsMapTypeImplicit, TypeLoc: MapLoc);
24151}
24152
24153QualType SemaOpenMP::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
24154 TypeResult ParsedType) {
24155 assert(ParsedType.isUsable());
24156
24157 QualType ReductionType = SemaRef.GetTypeFromParser(Ty: ParsedType.get());
24158 if (ReductionType.isNull())
24159 return QualType();
24160
24161 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
24162 // A type name in a declare reduction directive cannot be a function type, an
24163 // array type, a reference type, or a type qualified with const, volatile or
24164 // restrict.
24165 if (ReductionType.hasQualifiers()) {
24166 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 0;
24167 return QualType();
24168 }
24169
24170 if (ReductionType->isFunctionType()) {
24171 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 1;
24172 return QualType();
24173 }
24174 if (ReductionType->isReferenceType()) {
24175 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 2;
24176 return QualType();
24177 }
24178 if (ReductionType->isArrayType()) {
24179 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 3;
24180 return QualType();
24181 }
24182 return ReductionType;
24183}
24184
24185SemaOpenMP::DeclGroupPtrTy
24186SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveStart(
24187 Scope *S, DeclContext *DC, DeclarationName Name,
24188 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
24189 AccessSpecifier AS, Decl *PrevDeclInScope) {
24190 SmallVector<Decl *, 8> Decls;
24191 Decls.reserve(N: ReductionTypes.size());
24192
24193 LookupResult Lookup(SemaRef, Name, SourceLocation(),
24194 Sema::LookupOMPReductionName,
24195 SemaRef.forRedeclarationInCurContext());
24196 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
24197 // A reduction-identifier may not be re-declared in the current scope for the
24198 // same type or for a type that is compatible according to the base language
24199 // rules.
24200 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
24201 OMPDeclareReductionDecl *PrevDRD = nullptr;
24202 bool InCompoundScope = true;
24203 if (S != nullptr) {
24204 // Find previous declaration with the same name not referenced in other
24205 // declarations.
24206 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
24207 InCompoundScope =
24208 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
24209 SemaRef.LookupName(R&: Lookup, S);
24210 SemaRef.FilterLookupForScope(R&: Lookup, Ctx: DC, S, /*ConsiderLinkage=*/false,
24211 /*AllowInlineNamespace=*/false);
24212 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
24213 LookupResult::Filter Filter = Lookup.makeFilter();
24214 while (Filter.hasNext()) {
24215 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Val: Filter.next());
24216 if (InCompoundScope) {
24217 UsedAsPrevious.try_emplace(Key: PrevDecl, Args: false);
24218 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
24219 UsedAsPrevious[D] = true;
24220 }
24221 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
24222 PrevDecl->getLocation();
24223 }
24224 Filter.done();
24225 if (InCompoundScope) {
24226 for (const auto &PrevData : UsedAsPrevious) {
24227 if (!PrevData.second) {
24228 PrevDRD = PrevData.first;
24229 break;
24230 }
24231 }
24232 }
24233 } else if (PrevDeclInScope != nullptr) {
24234 auto *PrevDRDInScope = PrevDRD =
24235 cast<OMPDeclareReductionDecl>(Val: PrevDeclInScope);
24236 do {
24237 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
24238 PrevDRDInScope->getLocation();
24239 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
24240 } while (PrevDRDInScope != nullptr);
24241 }
24242 for (const auto &TyData : ReductionTypes) {
24243 const auto I = PreviousRedeclTypes.find(Val: TyData.first.getCanonicalType());
24244 bool Invalid = false;
24245 if (I != PreviousRedeclTypes.end()) {
24246 Diag(Loc: TyData.second, DiagID: diag::err_omp_declare_reduction_redefinition)
24247 << TyData.first;
24248 Diag(Loc: I->second, DiagID: diag::note_previous_definition);
24249 Invalid = true;
24250 }
24251 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
24252 auto *DRD = OMPDeclareReductionDecl::Create(
24253 C&: getASTContext(), DC, L: TyData.second, Name, T: TyData.first, PrevDeclInScope: PrevDRD);
24254 DC->addDecl(D: DRD);
24255 DRD->setAccess(AS);
24256 Decls.push_back(Elt: DRD);
24257 if (Invalid)
24258 DRD->setInvalidDecl();
24259 else
24260 PrevDRD = DRD;
24261 }
24262
24263 return DeclGroupPtrTy::make(
24264 P: DeclGroupRef::Create(C&: getASTContext(), Decls: Decls.begin(), NumDecls: Decls.size()));
24265}
24266
24267void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
24268 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
24269
24270 // Enter new function scope.
24271 SemaRef.PushFunctionScope();
24272 SemaRef.setFunctionHasBranchProtectedScope();
24273 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
24274
24275 if (S != nullptr)
24276 SemaRef.PushDeclContext(S, DC: DRD);
24277 else
24278 SemaRef.CurContext = DRD;
24279
24280 SemaRef.PushExpressionEvaluationContext(
24281 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
24282
24283 QualType ReductionType = DRD->getType();
24284 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
24285 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
24286 // uses semantics of argument handles by value, but it should be passed by
24287 // reference. C lang does not support references, so pass all parameters as
24288 // pointers.
24289 // Create 'T omp_in;' variable.
24290 VarDecl *OmpInParm =
24291 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_in");
24292 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
24293 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
24294 // uses semantics of argument handles by value, but it should be passed by
24295 // reference. C lang does not support references, so pass all parameters as
24296 // pointers.
24297 // Create 'T omp_out;' variable.
24298 VarDecl *OmpOutParm =
24299 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_out");
24300 if (S != nullptr) {
24301 SemaRef.PushOnScopeChains(D: OmpInParm, S);
24302 SemaRef.PushOnScopeChains(D: OmpOutParm, S);
24303 } else {
24304 DRD->addDecl(D: OmpInParm);
24305 DRD->addDecl(D: OmpOutParm);
24306 }
24307 Expr *InE =
24308 ::buildDeclRefExpr(S&: SemaRef, D: OmpInParm, Ty: ReductionType, Loc: D->getLocation());
24309 Expr *OutE =
24310 ::buildDeclRefExpr(S&: SemaRef, D: OmpOutParm, Ty: ReductionType, Loc: D->getLocation());
24311 DRD->setCombinerData(InE, OutE);
24312}
24313
24314void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D,
24315 Expr *Combiner) {
24316 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
24317 SemaRef.DiscardCleanupsInEvaluationContext();
24318 SemaRef.PopExpressionEvaluationContext();
24319
24320 SemaRef.PopDeclContext();
24321 SemaRef.PopFunctionScopeInfo();
24322
24323 if (Combiner != nullptr)
24324 DRD->setCombiner(Combiner);
24325 else
24326 DRD->setInvalidDecl();
24327}
24328
24329VarDecl *SemaOpenMP::ActOnOpenMPDeclareReductionInitializerStart(Scope *S,
24330 Decl *D) {
24331 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
24332
24333 // Enter new function scope.
24334 SemaRef.PushFunctionScope();
24335 SemaRef.setFunctionHasBranchProtectedScope();
24336
24337 if (S != nullptr)
24338 SemaRef.PushDeclContext(S, DC: DRD);
24339 else
24340 SemaRef.CurContext = DRD;
24341
24342 SemaRef.PushExpressionEvaluationContext(
24343 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
24344
24345 QualType ReductionType = DRD->getType();
24346 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
24347 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
24348 // uses semantics of argument handles by value, but it should be passed by
24349 // reference. C lang does not support references, so pass all parameters as
24350 // pointers.
24351 // Create 'T omp_priv;' variable.
24352 VarDecl *OmpPrivParm =
24353 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_priv");
24354 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
24355 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
24356 // uses semantics of argument handles by value, but it should be passed by
24357 // reference. C lang does not support references, so pass all parameters as
24358 // pointers.
24359 // Create 'T omp_orig;' variable.
24360 VarDecl *OmpOrigParm =
24361 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_orig");
24362 if (S != nullptr) {
24363 SemaRef.PushOnScopeChains(D: OmpPrivParm, S);
24364 SemaRef.PushOnScopeChains(D: OmpOrigParm, S);
24365 } else {
24366 DRD->addDecl(D: OmpPrivParm);
24367 DRD->addDecl(D: OmpOrigParm);
24368 }
24369 Expr *OrigE =
24370 ::buildDeclRefExpr(S&: SemaRef, D: OmpOrigParm, Ty: ReductionType, Loc: D->getLocation());
24371 Expr *PrivE =
24372 ::buildDeclRefExpr(S&: SemaRef, D: OmpPrivParm, Ty: ReductionType, Loc: D->getLocation());
24373 DRD->setInitializerData(OrigE, PrivE);
24374 return OmpPrivParm;
24375}
24376
24377void SemaOpenMP::ActOnOpenMPDeclareReductionInitializerEnd(
24378 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
24379 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
24380 SemaRef.DiscardCleanupsInEvaluationContext();
24381 SemaRef.PopExpressionEvaluationContext();
24382
24383 SemaRef.PopDeclContext();
24384 SemaRef.PopFunctionScopeInfo();
24385
24386 if (Initializer != nullptr) {
24387 DRD->setInitializer(E: Initializer, IK: OMPDeclareReductionInitKind::Call);
24388 } else if (OmpPrivParm->hasInit()) {
24389 DRD->setInitializer(E: OmpPrivParm->getInit(),
24390 IK: OmpPrivParm->isDirectInit()
24391 ? OMPDeclareReductionInitKind::Direct
24392 : OMPDeclareReductionInitKind::Copy);
24393 } else {
24394 DRD->setInvalidDecl();
24395 }
24396}
24397
24398SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveEnd(
24399 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
24400 for (Decl *D : DeclReductions.get()) {
24401 if (IsValid) {
24402 if (S)
24403 SemaRef.PushOnScopeChains(D: cast<OMPDeclareReductionDecl>(Val: D), S,
24404 /*AddToContext=*/false);
24405 } else {
24406 D->setInvalidDecl();
24407 }
24408 }
24409 return DeclReductions;
24410}
24411
24412TypeResult SemaOpenMP::ActOnOpenMPDeclareMapperVarDecl(Scope *S,
24413 Declarator &D) {
24414 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
24415 QualType T = TInfo->getType();
24416 if (D.isInvalidType())
24417 return true;
24418
24419 if (getLangOpts().CPlusPlus) {
24420 // Check that there are no default arguments (C++ only).
24421 SemaRef.CheckExtraCXXDefaultArguments(D);
24422 }
24423
24424 return SemaRef.CreateParsedType(T, TInfo);
24425}
24426
24427QualType SemaOpenMP::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
24428 TypeResult ParsedType) {
24429 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
24430
24431 QualType MapperType = SemaRef.GetTypeFromParser(Ty: ParsedType.get());
24432 assert(!MapperType.isNull() && "Expect valid mapper type");
24433
24434 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
24435 // The type must be of struct, union or class type in C and C++
24436 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
24437 Diag(Loc: TyLoc, DiagID: diag::err_omp_mapper_wrong_type);
24438 return QualType();
24439 }
24440 return MapperType;
24441}
24442
24443SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareMapperDirective(
24444 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
24445 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
24446 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
24447 LookupResult Lookup(SemaRef, Name, SourceLocation(),
24448 Sema::LookupOMPMapperName,
24449 SemaRef.forRedeclarationInCurContext());
24450 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
24451 // A mapper-identifier may not be redeclared in the current scope for the
24452 // same type or for a type that is compatible according to the base language
24453 // rules.
24454 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
24455 OMPDeclareMapperDecl *PrevDMD = nullptr;
24456 bool InCompoundScope = true;
24457 if (S != nullptr) {
24458 // Find previous declaration with the same name not referenced in other
24459 // declarations.
24460 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
24461 InCompoundScope =
24462 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
24463 SemaRef.LookupName(R&: Lookup, S);
24464 SemaRef.FilterLookupForScope(R&: Lookup, Ctx: DC, S, /*ConsiderLinkage=*/false,
24465 /*AllowInlineNamespace=*/false);
24466 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
24467 LookupResult::Filter Filter = Lookup.makeFilter();
24468 while (Filter.hasNext()) {
24469 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Val: Filter.next());
24470 if (InCompoundScope) {
24471 UsedAsPrevious.try_emplace(Key: PrevDecl, Args: false);
24472 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
24473 UsedAsPrevious[D] = true;
24474 }
24475 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
24476 PrevDecl->getLocation();
24477 }
24478 Filter.done();
24479 if (InCompoundScope) {
24480 for (const auto &PrevData : UsedAsPrevious) {
24481 if (!PrevData.second) {
24482 PrevDMD = PrevData.first;
24483 break;
24484 }
24485 }
24486 }
24487 } else if (PrevDeclInScope) {
24488 auto *PrevDMDInScope = PrevDMD =
24489 cast<OMPDeclareMapperDecl>(Val: PrevDeclInScope);
24490 do {
24491 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
24492 PrevDMDInScope->getLocation();
24493 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
24494 } while (PrevDMDInScope != nullptr);
24495 }
24496 const auto I = PreviousRedeclTypes.find(Val: MapperType.getCanonicalType());
24497 bool Invalid = false;
24498 if (I != PreviousRedeclTypes.end()) {
24499 Diag(Loc: StartLoc, DiagID: diag::err_omp_declare_mapper_redefinition)
24500 << MapperType << Name;
24501 Diag(Loc: I->second, DiagID: diag::note_previous_definition);
24502 Invalid = true;
24503 }
24504 // Build expressions for implicit maps of data members with 'default'
24505 // mappers.
24506 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
24507 if (getLangOpts().OpenMP >= 50)
24508 processImplicitMapsWithDefaultMappers(S&: SemaRef, DSAStack,
24509 Clauses&: ClausesWithImplicit);
24510 auto *DMD = OMPDeclareMapperDecl::Create(C&: getASTContext(), DC, L: StartLoc, Name,
24511 T: MapperType, VarName: VN, Clauses: ClausesWithImplicit,
24512 PrevDeclInScope: PrevDMD);
24513 if (S)
24514 SemaRef.PushOnScopeChains(D: DMD, S);
24515 else
24516 DC->addDecl(D: DMD);
24517 DMD->setAccess(AS);
24518 if (Invalid)
24519 DMD->setInvalidDecl();
24520
24521 auto *VD = cast<DeclRefExpr>(Val: MapperVarRef)->getDecl();
24522 VD->setDeclContext(DMD);
24523 VD->setLexicalDeclContext(DMD);
24524 DMD->addDecl(D: VD);
24525 DMD->setMapperVarRef(MapperVarRef);
24526
24527 return DeclGroupPtrTy::make(P: DeclGroupRef(DMD));
24528}
24529
24530ExprResult SemaOpenMP::ActOnOpenMPDeclareMapperDirectiveVarDecl(
24531 Scope *S, QualType MapperType, SourceLocation StartLoc,
24532 DeclarationName VN) {
24533 TypeSourceInfo *TInfo =
24534 getASTContext().getTrivialTypeSourceInfo(T: MapperType, Loc: StartLoc);
24535 auto *VD = VarDecl::Create(
24536 C&: getASTContext(), DC: getASTContext().getTranslationUnitDecl(), StartLoc,
24537 IdLoc: StartLoc, Id: VN.getAsIdentifierInfo(), T: MapperType, TInfo, S: SC_None);
24538 if (S)
24539 SemaRef.PushOnScopeChains(D: VD, S, /*AddToContext=*/false);
24540 Expr *E = buildDeclRefExpr(S&: SemaRef, D: VD, Ty: MapperType, Loc: StartLoc);
24541 DSAStack->addDeclareMapperVarRef(Ref: E);
24542 return E;
24543}
24544
24545void SemaOpenMP::ActOnOpenMPIteratorVarDecl(VarDecl *VD) {
24546 bool IsGlobalVar =
24547 !VD->isLocalVarDecl() && VD->getDeclContext()->isTranslationUnit();
24548 if (DSAStack->getDeclareMapperVarRef()) {
24549 if (IsGlobalVar)
24550 SemaRef.Consumer.HandleTopLevelDecl(D: DeclGroupRef(VD));
24551 DSAStack->addIteratorVarDecl(VD);
24552 } else {
24553 // Currently, only declare mapper handles global-scope iterator vars.
24554 assert(!IsGlobalVar && "Only declare mapper handles TU-scope iterators.");
24555 }
24556}
24557
24558bool SemaOpenMP::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
24559 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
24560 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
24561 if (const auto *DRE = cast_or_null<DeclRefExpr>(Val: Ref)) {
24562 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
24563 return true;
24564 if (VD->isUsableInConstantExpressions(C: getASTContext()))
24565 return true;
24566 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
24567 return true;
24568 return false;
24569 }
24570 return true;
24571}
24572
24573const ValueDecl *SemaOpenMP::getOpenMPDeclareMapperVarName() const {
24574 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
24575 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
24576}
24577
24578ExprResult SemaOpenMP::ActOnOpenMPDimsModifier(OpenMPClauseKind ClauseKind,
24579 int Modifier, Expr *ModifierExpr,
24580 SourceLocation ModifierLoc,
24581 ArrayRef<Expr *> VarList,
24582 SourceLocation VarListEndLoc) {
24583 assert(ModifierExpr && "Unexpected modifier expression.");
24584
24585 if (getLangOpts().OpenMP < 61) {
24586 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_modifier_requires_version)
24587 << getOpenMPSimpleClauseTypeName(Kind: ClauseKind, Type: Modifier)
24588 << getOpenMPClauseName(C: ClauseKind) << "6.1";
24589 return ExprError();
24590 }
24591
24592 ExprResult DimsRes = VerifyPositiveIntegerConstantInClause(
24593 E: ModifierExpr, CKind: ClauseKind, /*StrictlyPositive=*/true,
24594 /*SuppressExprDiags=*/false);
24595 if (DimsRes.isInvalid())
24596 return ExprError();
24597
24598 ModifierExpr = DimsRes.get();
24599 if (ModifierExpr->isInstantiationDependent())
24600 return DimsRes;
24601
24602 uint64_t NumDims =
24603 ModifierExpr->EvaluateKnownConstInt(Ctx: getASTContext()).getExtValue();
24604 if (NumDims == VarList.size())
24605 return DimsRes;
24606
24607 Diag(Loc: VarListEndLoc, DiagID: diag::err_omp_unexpected_num_exprs)
24608 << getOpenMPClauseName(C: ClauseKind) << NumDims << VarList.size();
24609 return ExprError();
24610}
24611
24612OMPClause *SemaOpenMP::ActOnOpenMPNumTeamsClause(
24613 ArrayRef<Expr *> VarList, OpenMPNumTeamsClauseModifier Modifier,
24614 Expr *ModifierExpr, SourceLocation ModifierLoc,
24615 OpenMPNumTeamsClauseModifier ModifierExtra, Expr *,
24616 SourceLocation ModifierExtraLoc, SourceLocation StartLoc,
24617 SourceLocation LParenLoc, SourceLocation EndLoc) {
24618 if (VarList.empty())
24619 return nullptr;
24620
24621 for (Expr *ValExpr : VarList) {
24622 // OpenMP [teams Construct, Restrictions]
24623 // The num_teams expression must evaluate to a positive integer value.
24624 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_num_teams,
24625 /*StrictlyPositive=*/true))
24626 return nullptr;
24627 }
24628
24629 // OpenMP [teams Construct, Restrictions]
24630 // The lower-bound modifier cannot be specified if the dims modifier is
24631 // specified.
24632 if (Modifier != OMPC_NUMTEAMS_unknown &&
24633 ModifierExtra != OMPC_NUMTEAMS_unknown) {
24634 Diag(Loc: ModifierExtraLoc, DiagID: diag::err_omp_incompatible_modifiers)
24635 << getOpenMPSimpleClauseTypeName(Kind: llvm::omp::OMPC_num_teams,
24636 Type: ModifierExtra)
24637 << getOpenMPSimpleClauseTypeName(Kind: llvm::omp::OMPC_num_teams, Type: Modifier)
24638 << getOpenMPClauseName(C: llvm::omp::OMPC_num_teams);
24639 ModifierExtra = OMPC_NUMTEAMS_unknown;
24640 ModifierExtraLoc = SourceLocation();
24641 }
24642
24643 if (Modifier == OMPC_NUMTEAMS_dims) {
24644 ExprResult Res = ActOnOpenMPDimsModifier(
24645 ClauseKind: OMPC_num_teams, Modifier, ModifierExpr, ModifierLoc, VarList, VarListEndLoc: EndLoc);
24646 if (Res.isInvalid())
24647 return nullptr;
24648 ModifierExpr = Res.get();
24649 } else if (Modifier == OMPC_NUMTEAMS_lower_bound) {
24650 assert(ModifierExpr && "Unexpected modifier expression.");
24651
24652 if (getLangOpts().OpenMP < 51) {
24653 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_modifier_requires_version)
24654 << getOpenMPSimpleClauseTypeName(Kind: llvm::omp::OMPC_num_teams, Type: Modifier)
24655 << getOpenMPClauseName(C: llvm::omp::OMPC_num_teams) << "5.1";
24656 return nullptr;
24657 }
24658
24659 // OpenMP [teams Construct, Restrictions]
24660 // The lower-bound expression in num_teams must evaluate to a positive
24661 // integer value.
24662 if (!isNonNegativeIntegerValue(ValExpr&: ModifierExpr, SemaRef, CKind: OMPC_num_teams,
24663 /*StrictlyPositive=*/true))
24664 return nullptr;
24665
24666 // OpenMP 5.2: Validate lower-bound is less than or equal to upper-bound.
24667 Expr *LowerBound = ModifierExpr;
24668 Expr *UpperBound = VarList[0];
24669
24670 // Check if both are compile-time constants for validation.
24671 if (!LowerBound->isValueDependent() && !UpperBound->isValueDependent() &&
24672 LowerBound->isIntegerConstantExpr(Ctx: getASTContext()) &&
24673 UpperBound->isIntegerConstantExpr(Ctx: getASTContext())) {
24674
24675 // Get the actual constant values.
24676 llvm::APSInt LowerVal =
24677 LowerBound->EvaluateKnownConstInt(Ctx: getASTContext());
24678 llvm::APSInt UpperVal =
24679 UpperBound->EvaluateKnownConstInt(Ctx: getASTContext());
24680
24681 if (LowerVal > UpperVal) {
24682 Diag(Loc: LowerBound->getExprLoc(),
24683 DiagID: diag::err_omp_num_teams_lower_bound_larger)
24684 << LowerBound->getSourceRange() << UpperBound->getSourceRange();
24685 return nullptr;
24686 }
24687 }
24688 }
24689
24690 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24691 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
24692 DKind, CKind: OMPC_num_teams, OpenMPVersion: getLangOpts().OpenMP);
24693 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
24694 return OMPNumTeamsClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
24695 LParenLoc, EndLoc, VL: VarList, Modifier,
24696 ModifierExpr, ModifierLoc,
24697 /*PreInit=*/nullptr);
24698
24699 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24700 SmallVector<Expr *, 3> Vars;
24701 for (Expr *ValExpr : VarList) {
24702 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
24703 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
24704 Vars.push_back(Elt: ValExpr);
24705 }
24706
24707 if (ModifierExpr) {
24708 ModifierExpr = SemaRef.MakeFullExpr(Arg: ModifierExpr).get();
24709 ModifierExpr = tryBuildCapture(SemaRef, Capture: ModifierExpr, Captures).get();
24710 }
24711
24712 Stmt *PreInit = buildPreInits(Context&: getASTContext(), Captures);
24713 return OMPNumTeamsClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
24714 LParenLoc, EndLoc, VL: Vars, Modifier,
24715 ModifierExpr, ModifierLoc, PreInit);
24716}
24717
24718OMPClause *SemaOpenMP::ActOnOpenMPThreadLimitClause(
24719 ArrayRef<Expr *> VarList, OpenMPThreadLimitClauseModifier Modifier,
24720 Expr *ModifierExpr, SourceLocation ModifierLoc, SourceLocation StartLoc,
24721 SourceLocation LParenLoc, SourceLocation EndLoc) {
24722 if (VarList.empty())
24723 return nullptr;
24724
24725 for (Expr *ValExpr : VarList) {
24726 // OpenMP [teams Constrcut, Restrictions]
24727 // The thread_limit expression must evaluate to a positive integer value.
24728 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_thread_limit,
24729 /*StrictlyPositive=*/true))
24730 return nullptr;
24731 }
24732
24733 if (Modifier == OMPC_THREADLIMIT_dims) {
24734 ExprResult Res =
24735 ActOnOpenMPDimsModifier(ClauseKind: OMPC_thread_limit, Modifier, ModifierExpr,
24736 ModifierLoc, VarList, VarListEndLoc: EndLoc);
24737 if (Res.isInvalid())
24738 return nullptr;
24739 ModifierExpr = Res.get();
24740 }
24741
24742 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24743 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
24744 DKind, CKind: OMPC_thread_limit, OpenMPVersion: getLangOpts().OpenMP);
24745 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
24746 return OMPThreadLimitClause::Create(C: getASTContext(), CaptureRegion,
24747 StartLoc, LParenLoc, EndLoc, VL: VarList,
24748 Modifier, ModifierExpr, ModifierLoc,
24749 /*PreInit=*/nullptr);
24750
24751 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24752 SmallVector<Expr *, 3> Vars;
24753 for (Expr *ValExpr : VarList) {
24754 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
24755 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
24756 Vars.push_back(Elt: ValExpr);
24757 }
24758
24759 if (ModifierExpr) {
24760 ModifierExpr = SemaRef.MakeFullExpr(Arg: ModifierExpr).get();
24761 ModifierExpr = tryBuildCapture(SemaRef, Capture: ModifierExpr, Captures).get();
24762 }
24763
24764 Stmt *PreInit = buildPreInits(Context&: getASTContext(), Captures);
24765 return OMPThreadLimitClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
24766 LParenLoc, EndLoc, VL: Vars, Modifier,
24767 ModifierExpr, ModifierLoc, PreInit);
24768}
24769
24770OMPClause *SemaOpenMP::ActOnOpenMPPriorityClause(Expr *Priority,
24771 SourceLocation StartLoc,
24772 SourceLocation LParenLoc,
24773 SourceLocation EndLoc) {
24774 Expr *ValExpr = Priority;
24775 Stmt *HelperValStmt = nullptr;
24776 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24777
24778 // OpenMP [2.9.1, task Constrcut]
24779 // The priority-value is a non-negative numerical scalar expression.
24780 if (!isNonNegativeIntegerValue(
24781 ValExpr, SemaRef, CKind: OMPC_priority,
24782 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
24783 DSAStack->getCurrentDirective(), CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
24784 return nullptr;
24785
24786 return new (getASTContext()) OMPPriorityClause(
24787 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24788}
24789
24790OMPClause *SemaOpenMP::ActOnOpenMPGrainsizeClause(
24791 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
24792 SourceLocation StartLoc, SourceLocation LParenLoc,
24793 SourceLocation ModifierLoc, SourceLocation EndLoc) {
24794 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
24795 "Unexpected grainsize modifier in OpenMP < 51.");
24796
24797 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
24798 std::string Values = getListOfPossibleValues(K: OMPC_grainsize, /*First=*/0,
24799 Last: OMPC_GRAINSIZE_unknown);
24800 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
24801 << Values << getOpenMPClauseNameForDiag(C: OMPC_grainsize);
24802 return nullptr;
24803 }
24804
24805 Expr *ValExpr = Grainsize;
24806 Stmt *HelperValStmt = nullptr;
24807 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24808
24809 // OpenMP [2.9.2, taskloop Constrcut]
24810 // The parameter of the grainsize clause must be a positive integer
24811 // expression.
24812 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_grainsize,
24813 /*StrictlyPositive=*/true,
24814 /*BuildCapture=*/true,
24815 DSAStack->getCurrentDirective(),
24816 CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
24817 return nullptr;
24818
24819 return new (getASTContext())
24820 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
24821 StartLoc, LParenLoc, ModifierLoc, EndLoc);
24822}
24823
24824OMPClause *SemaOpenMP::ActOnOpenMPNumTasksClause(
24825 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
24826 SourceLocation StartLoc, SourceLocation LParenLoc,
24827 SourceLocation ModifierLoc, SourceLocation EndLoc) {
24828 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
24829 "Unexpected num_tasks modifier in OpenMP < 51.");
24830
24831 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
24832 std::string Values = getListOfPossibleValues(K: OMPC_num_tasks, /*First=*/0,
24833 Last: OMPC_NUMTASKS_unknown);
24834 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
24835 << Values << getOpenMPClauseNameForDiag(C: OMPC_num_tasks);
24836 return nullptr;
24837 }
24838
24839 Expr *ValExpr = NumTasks;
24840 Stmt *HelperValStmt = nullptr;
24841 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24842
24843 // OpenMP [2.9.2, taskloop Constrcut]
24844 // The parameter of the num_tasks clause must be a positive integer
24845 // expression.
24846 if (!isNonNegativeIntegerValue(
24847 ValExpr, SemaRef, CKind: OMPC_num_tasks,
24848 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
24849 DSAStack->getCurrentDirective(), CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
24850 return nullptr;
24851
24852 return new (getASTContext())
24853 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
24854 StartLoc, LParenLoc, ModifierLoc, EndLoc);
24855}
24856
24857OMPClause *SemaOpenMP::ActOnOpenMPHintClause(Expr *Hint,
24858 SourceLocation StartLoc,
24859 SourceLocation LParenLoc,
24860 SourceLocation EndLoc) {
24861 // OpenMP [2.13.2, critical construct, Description]
24862 // ... where hint-expression is an integer constant expression that evaluates
24863 // to a valid lock hint.
24864 ExprResult HintExpr =
24865 VerifyPositiveIntegerConstantInClause(E: Hint, CKind: OMPC_hint, StrictlyPositive: false);
24866 if (HintExpr.isInvalid())
24867 return nullptr;
24868 return new (getASTContext())
24869 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
24870}
24871
24872/// Tries to find omp_event_handle_t type.
24873static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
24874 DSAStackTy *Stack) {
24875 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
24876 if (!OMPEventHandleT.isNull())
24877 return true;
24878 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_event_handle_t");
24879 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
24880 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
24881 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
24882 return false;
24883 }
24884 Stack->setOMPEventHandleT(PT.get());
24885 return true;
24886}
24887
24888OMPClause *SemaOpenMP::ActOnOpenMPDetachClause(Expr *Evt,
24889 SourceLocation StartLoc,
24890 SourceLocation LParenLoc,
24891 SourceLocation EndLoc) {
24892 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
24893 !Evt->isInstantiationDependent() &&
24894 !Evt->containsUnexpandedParameterPack()) {
24895 if (!findOMPEventHandleT(S&: SemaRef, Loc: Evt->getExprLoc(), DSAStack))
24896 return nullptr;
24897 // OpenMP 5.0, 2.10.1 task Construct.
24898 // event-handle is a variable of the omp_event_handle_t type.
24899 auto *Ref = dyn_cast<DeclRefExpr>(Val: Evt->IgnoreParenImpCasts());
24900 if (!Ref) {
24901 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
24902 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
24903 return nullptr;
24904 }
24905 auto *VD = dyn_cast_or_null<VarDecl>(Val: Ref->getDecl());
24906 if (!VD) {
24907 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
24908 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
24909 return nullptr;
24910 }
24911 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
24912 T2: VD->getType()) ||
24913 VD->getType().isConstant(Ctx: getASTContext())) {
24914 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
24915 << "omp_event_handle_t" << 1 << VD->getType()
24916 << Evt->getSourceRange();
24917 return nullptr;
24918 }
24919 // OpenMP 5.0, 2.10.1 task Construct
24920 // [detach clause]... The event-handle will be considered as if it was
24921 // specified on a firstprivate clause.
24922 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
24923 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
24924 DVar.RefExpr) {
24925 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
24926 << getOpenMPClauseNameForDiag(C: DVar.CKind)
24927 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
24928 reportOriginalDsa(SemaRef, DSAStack, D: VD, DVar);
24929 return nullptr;
24930 }
24931 }
24932
24933 return new (getASTContext())
24934 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
24935}
24936
24937OMPClause *SemaOpenMP::ActOnOpenMPDistScheduleClause(
24938 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
24939 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
24940 SourceLocation EndLoc) {
24941 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
24942 std::string Values;
24943 Values += "'";
24944 Values += getOpenMPSimpleClauseTypeName(Kind: OMPC_dist_schedule, Type: 0);
24945 Values += "'";
24946 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
24947 << Values << getOpenMPClauseNameForDiag(C: OMPC_dist_schedule);
24948 return nullptr;
24949 }
24950 Expr *ValExpr = ChunkSize;
24951 Stmt *HelperValStmt = nullptr;
24952 if (ChunkSize) {
24953 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
24954 !ChunkSize->isInstantiationDependent() &&
24955 !ChunkSize->containsUnexpandedParameterPack()) {
24956 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
24957 ExprResult Val =
24958 PerformOpenMPImplicitIntegerConversion(Loc: ChunkSizeLoc, Op: ChunkSize);
24959 if (Val.isInvalid())
24960 return nullptr;
24961
24962 ValExpr = Val.get();
24963
24964 // OpenMP [2.7.1, Restrictions]
24965 // chunk_size must be a loop invariant integer expression with a positive
24966 // value.
24967 if (std::optional<llvm::APSInt> Result =
24968 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
24969 if (Result->isSigned() && !Result->isStrictlyPositive()) {
24970 Diag(Loc: ChunkSizeLoc, DiagID: diag::err_omp_negative_expression_in_clause)
24971 << "dist_schedule" << /*strictly positive*/ 1
24972 << ChunkSize->getSourceRange();
24973 return nullptr;
24974 }
24975 } else if (getOpenMPCaptureRegionForClause(
24976 DSAStack->getCurrentDirective(), CKind: OMPC_dist_schedule,
24977 OpenMPVersion: getLangOpts().OpenMP) != OMPD_unknown &&
24978 !SemaRef.CurContext->isDependentContext()) {
24979 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
24980 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24981 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
24982 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
24983 }
24984 }
24985 }
24986
24987 return new (getASTContext())
24988 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
24989 Kind, ValExpr, HelperValStmt);
24990}
24991
24992OMPClause *SemaOpenMP::ActOnOpenMPDefaultmapClause(
24993 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
24994 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
24995 SourceLocation KindLoc, SourceLocation EndLoc) {
24996 if (getLangOpts().OpenMP < 50) {
24997 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
24998 Kind != OMPC_DEFAULTMAP_scalar) {
24999 std::string Value;
25000 SourceLocation Loc;
25001 Value += "'";
25002 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
25003 Value += getOpenMPSimpleClauseTypeName(Kind: OMPC_defaultmap,
25004 Type: OMPC_DEFAULTMAP_MODIFIER_tofrom);
25005 Loc = MLoc;
25006 } else {
25007 Value += getOpenMPSimpleClauseTypeName(Kind: OMPC_defaultmap,
25008 Type: OMPC_DEFAULTMAP_scalar);
25009 Loc = KindLoc;
25010 }
25011 Value += "'";
25012 Diag(Loc, DiagID: diag::err_omp_unexpected_clause_value)
25013 << Value << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25014 return nullptr;
25015 }
25016 } else {
25017 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
25018 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
25019 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
25020 if (!isDefaultmapKind || !isDefaultmapModifier) {
25021 StringRef KindValue = getLangOpts().OpenMP < 52
25022 ? "'scalar', 'aggregate', 'pointer'"
25023 : "'scalar', 'aggregate', 'pointer', 'all'";
25024 if (getLangOpts().OpenMP == 50) {
25025 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
25026 "'firstprivate', 'none', 'default'";
25027 if (!isDefaultmapKind && isDefaultmapModifier) {
25028 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
25029 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25030 } else if (isDefaultmapKind && !isDefaultmapModifier) {
25031 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
25032 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25033 } else {
25034 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
25035 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25036 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
25037 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25038 }
25039 } else {
25040 StringRef ModifierValue =
25041 getLangOpts().OpenMP < 60
25042 ? "'alloc', 'from', 'to', 'tofrom', "
25043 "'firstprivate', 'none', 'default', 'present'"
25044 : "'storage', 'from', 'to', 'tofrom', "
25045 "'firstprivate', 'private', 'none', 'default', 'present'";
25046 if (!isDefaultmapKind && isDefaultmapModifier) {
25047 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
25048 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25049 } else if (isDefaultmapKind && !isDefaultmapModifier) {
25050 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
25051 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25052 } else {
25053 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
25054 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25055 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
25056 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
25057 }
25058 }
25059 return nullptr;
25060 }
25061
25062 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
25063 // At most one defaultmap clause for each category can appear on the
25064 // directive.
25065 if (DSAStack->checkDefaultmapCategory(VariableCategory: Kind)) {
25066 Diag(Loc: StartLoc, DiagID: diag::err_omp_one_defaultmap_each_category);
25067 return nullptr;
25068 }
25069 }
25070 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
25071 // Variable category is not specified - mark all categories.
25072 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_aggregate, Loc: StartLoc);
25073 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_scalar, Loc: StartLoc);
25074 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_pointer, Loc: StartLoc);
25075 } else {
25076 DSAStack->setDefaultDMAAttr(M, Kind, Loc: StartLoc);
25077 }
25078
25079 return new (getASTContext())
25080 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
25081}
25082
25083bool SemaOpenMP::ActOnStartOpenMPDeclareTargetContext(
25084 DeclareTargetContextInfo &DTCI) {
25085 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
25086 if (!CurLexicalContext->isFileContext() &&
25087 !CurLexicalContext->isExternCContext() &&
25088 !CurLexicalContext->isExternCXXContext() &&
25089 !isa<CXXRecordDecl>(Val: CurLexicalContext) &&
25090 !isa<ClassTemplateDecl>(Val: CurLexicalContext) &&
25091 !isa<ClassTemplatePartialSpecializationDecl>(Val: CurLexicalContext) &&
25092 !isa<ClassTemplateSpecializationDecl>(Val: CurLexicalContext)) {
25093 Diag(Loc: DTCI.Loc, DiagID: diag::err_omp_region_not_file_context);
25094 return false;
25095 }
25096
25097 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
25098 if (getLangOpts().HIP)
25099 Diag(Loc: DTCI.Loc, DiagID: diag::warn_hip_omp_target_directives);
25100
25101 DeclareTargetNesting.push_back(Elt: DTCI);
25102 return true;
25103}
25104
25105const SemaOpenMP::DeclareTargetContextInfo
25106SemaOpenMP::ActOnOpenMPEndDeclareTargetDirective() {
25107 assert(!DeclareTargetNesting.empty() &&
25108 "check isInOpenMPDeclareTargetContext() first!");
25109 return DeclareTargetNesting.pop_back_val();
25110}
25111
25112void SemaOpenMP::ActOnFinishedOpenMPDeclareTargetContext(
25113 DeclareTargetContextInfo &DTCI) {
25114 for (auto &It : DTCI.ExplicitlyMapped)
25115 ActOnOpenMPDeclareTargetName(ND: It.first, Loc: It.second.Loc, MT: It.second.MT, DTCI);
25116}
25117
25118void SemaOpenMP::DiagnoseUnterminatedOpenMPDeclareTarget() {
25119 if (DeclareTargetNesting.empty())
25120 return;
25121 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
25122 unsigned OMPVersion = getLangOpts().OpenMP;
25123 Diag(Loc: DTCI.Loc, DiagID: diag::warn_omp_unterminated_declare_target)
25124 << getOpenMPDirectiveName(D: DTCI.Kind, Ver: OMPVersion);
25125}
25126
25127NamedDecl *SemaOpenMP::lookupOpenMPDeclareTargetName(
25128 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
25129 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
25130 SemaRef.LookupParsedName(R&: Lookup, S: CurScope, SS: &ScopeSpec,
25131 /*ObjectType=*/QualType(),
25132 /*AllowBuiltinCreation=*/true);
25133
25134 if (Lookup.isAmbiguous())
25135 return nullptr;
25136 Lookup.suppressDiagnostics();
25137
25138 if (!Lookup.isSingleResult()) {
25139 VarOrFuncDeclFilterCCC CCC(SemaRef);
25140 if (TypoCorrection Corrected =
25141 SemaRef.CorrectTypo(Typo: Id, LookupKind: Sema::LookupOrdinaryName, S: CurScope, SS: nullptr,
25142 CCC, Mode: CorrectTypoKind::ErrorRecovery)) {
25143 SemaRef.diagnoseTypo(Correction: Corrected,
25144 TypoDiag: SemaRef.PDiag(DiagID: diag::err_undeclared_var_use_suggest)
25145 << Id.getName());
25146 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: Corrected.getCorrectionDecl());
25147 return nullptr;
25148 }
25149
25150 Diag(Loc: Id.getLoc(), DiagID: diag::err_undeclared_var_use) << Id.getName();
25151 return nullptr;
25152 }
25153
25154 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
25155 if (!isa<VarDecl>(Val: ND) && !isa<FunctionDecl>(Val: ND) &&
25156 !isa<FunctionTemplateDecl>(Val: ND)) {
25157 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_invalid_target_decl) << Id.getName();
25158 return nullptr;
25159 }
25160 return ND;
25161}
25162
25163void SemaOpenMP::ActOnOpenMPDeclareTargetName(
25164 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
25165 DeclareTargetContextInfo &DTCI) {
25166 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
25167 isa<FunctionTemplateDecl>(ND)) &&
25168 "Expected variable, function or function template.");
25169
25170 if (auto *VD = dyn_cast<VarDecl>(Val: ND)) {
25171 // Only global variables can be marked as declare target.
25172 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
25173 !VD->isStaticDataMember()) {
25174 Diag(Loc, DiagID: diag::err_omp_declare_target_has_local_vars)
25175 << VD->getNameAsString();
25176 return;
25177 }
25178 }
25179 // Diagnose marking after use as it may lead to incorrect diagnosis and
25180 // codegen.
25181 if (getLangOpts().OpenMP >= 50 &&
25182 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
25183 Diag(Loc, DiagID: diag::warn_omp_declare_target_after_first_use);
25184
25185 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
25186 if (getLangOpts().HIP)
25187 Diag(Loc, DiagID: diag::warn_hip_omp_target_directives);
25188
25189 // 'local' is incompatible with 'device_type(host)' because 'local'
25190 // variables exist only on the device.
25191 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
25192 DTCI.DT == OMPDeclareTargetDeclAttr::DT_Host) {
25193 Diag(Loc, DiagID: diag::err_omp_declare_target_local_host_only);
25194 return;
25195 }
25196
25197 // Explicit declare target lists have precedence.
25198 const unsigned Level = -1;
25199
25200 auto *VD = cast<ValueDecl>(Val: ND);
25201 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
25202 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
25203 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
25204 (*ActiveAttr)->getLevel() == Level) {
25205 Diag(Loc, DiagID: diag::err_omp_device_type_mismatch)
25206 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(Val: DTCI.DT)
25207 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
25208 Val: (*ActiveAttr)->getDevType());
25209 return;
25210 }
25211 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
25212 (*ActiveAttr)->getLevel() == Level) {
25213 Diag(Loc, DiagID: diag::err_omp_declare_target_var_in_both_clauses)
25214 << ND
25215 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(
25216 Val: (*ActiveAttr)->getMapType())
25217 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(Val: MT);
25218 return;
25219 }
25220
25221 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
25222 return;
25223
25224 Expr *IndirectE = nullptr;
25225 bool IsIndirect = false;
25226 if (DTCI.Indirect) {
25227 IndirectE = *DTCI.Indirect;
25228 if (!IndirectE)
25229 IsIndirect = true;
25230 }
25231 // FIXME: 'local' with 'device_type(nohost)' is not yet fully supported
25232 // in codegen. Treat as 'device_type(any)' for now. The variable will
25233 // exist on both host and device, but the host copy is unused.
25234 auto DT = DTCI.DT;
25235 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
25236 DT == OMPDeclareTargetDeclAttr::DT_NoHost) {
25237 Diag(Loc, DiagID: diag::warn_omp_declare_target_local_nohost);
25238 DT = OMPDeclareTargetDeclAttr::DT_Any;
25239 }
25240
25241 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
25242 Ctx&: getASTContext(), MapType: MT, DevType: DT, IndirectExpr: IndirectE, Indirect: IsIndirect, Level,
25243 Range: SourceRange(Loc, Loc));
25244 ND->addAttr(A);
25245 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
25246 ML->DeclarationMarkedOpenMPDeclareTarget(D: ND, Attr: A);
25247 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: ND, IdLoc: Loc);
25248 if (auto *VD = dyn_cast<VarDecl>(Val: ND);
25249 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
25250 VD->hasGlobalStorage())
25251 ActOnOpenMPDeclareTargetInitializer(D: ND);
25252}
25253
25254static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
25255 Sema &SemaRef, Decl *D) {
25256 if (!D || !isa<VarDecl>(Val: D))
25257 return;
25258 auto *VD = cast<VarDecl>(Val: D);
25259 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
25260 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
25261 if (SemaRef.LangOpts.OpenMP >= 50 &&
25262 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
25263 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
25264 VD->hasGlobalStorage()) {
25265 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
25266 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter &&
25267 *MapTy != OMPDeclareTargetDeclAttr::MT_Local)) {
25268 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
25269 // If a lambda declaration and definition appears between a
25270 // declare target directive and the matching end declare target
25271 // directive, all variables that are captured by the lambda
25272 // expression must also appear in a to clause.
25273 SemaRef.Diag(Loc: VD->getLocation(),
25274 DiagID: diag::err_omp_lambda_capture_in_declare_target_not_to);
25275 SemaRef.Diag(Loc: SL, DiagID: diag::note_var_explicitly_captured_here)
25276 << VD << 0 << SR;
25277 return;
25278 }
25279 }
25280 if (MapTy)
25281 return;
25282 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::warn_omp_not_in_target_context);
25283 SemaRef.Diag(Loc: SL, DiagID: diag::note_used_here) << SR;
25284}
25285
25286static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
25287 Sema &SemaRef, DSAStackTy *Stack,
25288 ValueDecl *VD) {
25289 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
25290 checkTypeMappable(SL, SR, SemaRef, Stack, QTy: VD->getType(),
25291 /*FullCheck=*/false);
25292}
25293
25294void SemaOpenMP::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
25295 SourceLocation IdLoc) {
25296 if (!D || D->isInvalidDecl())
25297 return;
25298 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
25299 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
25300 if (auto *VD = dyn_cast<VarDecl>(Val: D)) {
25301 // Only global variables can be marked as declare target.
25302 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
25303 !VD->isStaticDataMember())
25304 return;
25305 // 2.10.6: threadprivate variable cannot appear in a declare target
25306 // directive.
25307 if (DSAStack->isThreadPrivate(D: VD)) {
25308 Diag(Loc: SL, DiagID: diag::err_omp_threadprivate_in_target);
25309 reportOriginalDsa(SemaRef, DSAStack, D: VD, DSAStack->getTopDSA(D: VD, FromParent: false));
25310 return;
25311 }
25312 }
25313 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: D))
25314 D = FTD->getTemplatedDecl();
25315 if (auto *FD = dyn_cast<FunctionDecl>(Val: D)) {
25316 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
25317 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD: FD);
25318 if (IdLoc.isValid() && Res &&
25319 (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
25320 *Res == OMPDeclareTargetDeclAttr::MT_Local)) {
25321 Diag(Loc: IdLoc, DiagID: diag::err_omp_function_in_target_clause_list)
25322 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(Val: *Res);
25323 Diag(Loc: FD->getLocation(), DiagID: diag::note_defined_here) << FD;
25324 return;
25325 }
25326 }
25327 if (auto *VD = dyn_cast<ValueDecl>(Val: D)) {
25328 // Problem if any with var declared with incomplete type will be reported
25329 // as normal, so no need to check it here.
25330 if ((E || !VD->getType()->isIncompleteType()) &&
25331 !checkValueDeclInTarget(SL, SR, SemaRef, DSAStack, VD))
25332 return;
25333 if (!E && isInOpenMPDeclareTargetContext()) {
25334 // Checking declaration inside declare target region.
25335 if (isa<VarDecl>(Val: D) || isa<FunctionDecl>(Val: D) ||
25336 isa<FunctionTemplateDecl>(Val: D)) {
25337 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
25338 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
25339 unsigned Level = DeclareTargetNesting.size();
25340 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
25341 return;
25342 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
25343 Expr *IndirectE = nullptr;
25344 bool IsIndirect = false;
25345 if (DTCI.Indirect) {
25346 IndirectE = *DTCI.Indirect;
25347 if (!IndirectE)
25348 IsIndirect = true;
25349 }
25350 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
25351 Ctx&: getASTContext(),
25352 MapType: getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
25353 : OMPDeclareTargetDeclAttr::MT_To,
25354 DevType: DTCI.DT, IndirectExpr: IndirectE, Indirect: IsIndirect, Level,
25355 Range: SourceRange(DTCI.Loc, DTCI.Loc));
25356 D->addAttr(A);
25357 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
25358 ML->DeclarationMarkedOpenMPDeclareTarget(D, Attr: A);
25359 }
25360 return;
25361 }
25362 }
25363 if (!E)
25364 return;
25365 checkDeclInTargetContext(SL: E->getExprLoc(), SR: E->getSourceRange(), SemaRef, D);
25366}
25367
25368/// This class visits every VarDecl that the initializer references and adds
25369/// OMPDeclareTargetDeclAttr to each of them.
25370class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
25371 SmallVector<VarDecl *> DeclVector;
25372 Attr *A;
25373
25374public:
25375 /// A StmtVisitor class function that visits all DeclRefExpr and adds
25376 /// OMPDeclareTargetDeclAttr to them.
25377 void VisitDeclRefExpr(DeclRefExpr *Node) {
25378 if (auto *VD = dyn_cast<VarDecl>(Val: Node->getDecl())) {
25379 VD->addAttr(A);
25380 DeclVector.push_back(Elt: VD);
25381 }
25382 }
25383 /// A function that iterates across each of the Expr's children.
25384 void VisitExpr(Expr *Ex) {
25385 for (auto *Child : Ex->children()) {
25386 Visit(S: Child);
25387 }
25388 }
25389 /// A function that keeps a record of all the Decls that are variables, has
25390 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
25391 /// each Decl one at a time and use the inherited 'visit' functions to look
25392 /// for DeclRefExpr.
25393 void declareTargetInitializer(Decl *TD) {
25394 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
25395 DeclVector.push_back(Elt: cast<VarDecl>(Val: TD));
25396 llvm::SmallDenseSet<Decl *> Visited;
25397 while (!DeclVector.empty()) {
25398 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
25399 if (!Visited.insert(V: TargetVarDecl).second)
25400 continue;
25401
25402 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
25403 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
25404 if (Expr *Ex = TargetVarDecl->getInit())
25405 Visit(S: Ex);
25406 }
25407 }
25408 }
25409};
25410
25411/// Adding OMPDeclareTargetDeclAttr to variables with static storage
25412/// duration that are referenced in the initializer expression list of
25413/// variables with static storage duration in declare target directive.
25414void SemaOpenMP::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) {
25415 GlobalDeclRefChecker Checker;
25416 if (isa<VarDecl>(Val: TargetDecl))
25417 Checker.declareTargetInitializer(TD: TargetDecl);
25418}
25419
25420OMPClause *SemaOpenMP::ActOnOpenMPToClause(
25421 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
25422 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
25423 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
25424 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
25425 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
25426 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
25427 OMPC_MOTION_MODIFIER_unknown,
25428 OMPC_MOTION_MODIFIER_unknown};
25429 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
25430
25431 // Process motion-modifiers, flag errors for duplicate modifiers.
25432 unsigned Count = 0;
25433 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
25434 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
25435 llvm::is_contained(Range&: Modifiers, Element: MotionModifiers[I])) {
25436 Diag(Loc: MotionModifiersLoc[I], DiagID: diag::err_omp_duplicate_motion_modifier);
25437 continue;
25438 }
25439 assert(Count < NumberOfOMPMotionModifiers &&
25440 "Modifiers exceed the allowed number of motion modifiers");
25441 Modifiers[Count] = MotionModifiers[I];
25442 ModifiersLoc[Count] = MotionModifiersLoc[I];
25443 ++Count;
25444 }
25445
25446 MappableVarListInfo MVLI(VarList);
25447 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_to, MVLI, StartLoc: Locs.StartLoc,
25448 MapperIdScopeSpec, MapperId, UnresolvedMappers);
25449 if (MVLI.ProcessedVarList.empty())
25450 return nullptr;
25451 if (IteratorExpr)
25452 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: IteratorExpr))
25453 if (auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
25454 DSAStack->addIteratorVarDecl(VD);
25455 return OMPToClause::Create(
25456 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25457 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, IteratorModifier: IteratorExpr, MotionModifiers: Modifiers,
25458 MotionModifiersLoc: ModifiersLoc, UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()),
25459 MapperId);
25460}
25461
25462OMPClause *SemaOpenMP::ActOnOpenMPFromClause(
25463 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
25464 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
25465 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
25466 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
25467 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
25468 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
25469 OMPC_MOTION_MODIFIER_unknown,
25470 OMPC_MOTION_MODIFIER_unknown};
25471 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
25472
25473 // Process motion-modifiers, flag errors for duplicate modifiers.
25474 unsigned Count = 0;
25475 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
25476 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
25477 llvm::is_contained(Range&: Modifiers, Element: MotionModifiers[I])) {
25478 Diag(Loc: MotionModifiersLoc[I], DiagID: diag::err_omp_duplicate_motion_modifier);
25479 continue;
25480 }
25481 assert(Count < NumberOfOMPMotionModifiers &&
25482 "Modifiers exceed the allowed number of motion modifiers");
25483 Modifiers[Count] = MotionModifiers[I];
25484 ModifiersLoc[Count] = MotionModifiersLoc[I];
25485 ++Count;
25486 }
25487
25488 MappableVarListInfo MVLI(VarList);
25489 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_from, MVLI, StartLoc: Locs.StartLoc,
25490 MapperIdScopeSpec, MapperId, UnresolvedMappers);
25491 if (MVLI.ProcessedVarList.empty())
25492 return nullptr;
25493 if (IteratorExpr)
25494 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: IteratorExpr))
25495 if (auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
25496 DSAStack->addIteratorVarDecl(VD);
25497 return OMPFromClause::Create(
25498 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25499 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, IteratorExpr, MotionModifiers: Modifiers,
25500 MotionModifiersLoc: ModifiersLoc, UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()),
25501 MapperId);
25502}
25503
25504OMPClause *SemaOpenMP::ActOnOpenMPUseDevicePtrClause(
25505 ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs,
25506 OpenMPUseDevicePtrFallbackModifier FallbackModifier,
25507 SourceLocation FallbackModifierLoc) {
25508 MappableVarListInfo MVLI(VarList);
25509 SmallVector<Expr *, 8> PrivateCopies;
25510 SmallVector<Expr *, 8> Inits;
25511
25512 for (Expr *RefExpr : VarList) {
25513 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
25514 SourceLocation ELoc;
25515 SourceRange ERange;
25516 Expr *SimpleRefExpr = RefExpr;
25517 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
25518 if (Res.second) {
25519 // It will be analyzed later.
25520 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
25521 PrivateCopies.push_back(Elt: nullptr);
25522 Inits.push_back(Elt: nullptr);
25523 }
25524 ValueDecl *D = Res.first;
25525 if (!D)
25526 continue;
25527
25528 QualType Type = D->getType();
25529 Type = Type.getNonReferenceType().getUnqualifiedType();
25530
25531 auto *VD = dyn_cast<VarDecl>(Val: D);
25532
25533 // Item should be a pointer or reference to pointer.
25534 if (!Type->isPointerType()) {
25535 Diag(Loc: ELoc, DiagID: diag::err_omp_usedeviceptr_not_a_pointer)
25536 << 0 << RefExpr->getSourceRange();
25537 continue;
25538 }
25539
25540 // Build the private variable and the expression that refers to it.
25541 auto VDPrivate =
25542 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
25543 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
25544 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
25545 if (VDPrivate->isInvalidDecl())
25546 continue;
25547
25548 SemaRef.CurContext->addDecl(D: VDPrivate);
25549 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
25550 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(), Loc: ELoc);
25551
25552 // Add temporary variable to initialize the private copy of the pointer.
25553 VarDecl *VDInit =
25554 buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type, Name: ".devptr.temp");
25555 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
25556 S&: SemaRef, D: VDInit, Ty: RefExpr->getType(), Loc: RefExpr->getExprLoc());
25557 SemaRef.AddInitializerToDecl(
25558 dcl: VDPrivate, init: SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get(),
25559 /*DirectInit=*/false);
25560
25561 // If required, build a capture to implement the privatization initialized
25562 // with the current list item value.
25563 DeclRefExpr *Ref = nullptr;
25564 if (!VD)
25565 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
25566 MVLI.ProcessedVarList.push_back(Elt: VD ? RefExpr->IgnoreParens() : Ref);
25567 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
25568 Inits.push_back(Elt: VDInitRefExpr);
25569
25570 // We need to add a data sharing attribute for this variable to make sure it
25571 // is correctly captured. A variable that shows up in a use_device_ptr has
25572 // similar properties of a first private variable.
25573 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
25574
25575 // Create a mappable component for the list item. List items in this clause
25576 // only need a component.
25577 MVLI.VarBaseDeclarations.push_back(Elt: D);
25578 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
25579 MVLI.VarComponents.back().emplace_back(Args&: SimpleRefExpr, Args&: D,
25580 /*IsNonContiguous=*/Args: false);
25581 }
25582
25583 if (MVLI.ProcessedVarList.empty())
25584 return nullptr;
25585
25586 return OMPUseDevicePtrClause::Create(
25587 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, PrivateVars: PrivateCopies, Inits,
25588 Declarations: MVLI.VarBaseDeclarations, ComponentLists: MVLI.VarComponents, FallbackModifier,
25589 FallbackModifierLoc);
25590}
25591
25592OMPClause *
25593SemaOpenMP::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
25594 const OMPVarListLocTy &Locs) {
25595 MappableVarListInfo MVLI(VarList);
25596
25597 for (Expr *RefExpr : VarList) {
25598 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
25599 SourceLocation ELoc;
25600 SourceRange ERange;
25601 Expr *SimpleRefExpr = RefExpr;
25602 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
25603 /*AllowArraySection=*/true,
25604 /*AllowAssumedSizeArray=*/true);
25605 if (Res.second) {
25606 // It will be analyzed later.
25607 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
25608 }
25609 ValueDecl *D = Res.first;
25610 if (!D)
25611 continue;
25612 auto *VD = dyn_cast<VarDecl>(Val: D);
25613
25614 // If required, build a capture to implement the privatization initialized
25615 // with the current list item value.
25616 DeclRefExpr *Ref = nullptr;
25617 if (!VD)
25618 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
25619 MVLI.ProcessedVarList.push_back(Elt: VD ? RefExpr->IgnoreParens() : Ref);
25620
25621 // We need to add a data sharing attribute for this variable to make sure it
25622 // is correctly captured. A variable that shows up in a use_device_addr has
25623 // similar properties of a first private variable.
25624 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
25625
25626 // Use the map-like approach to fully populate VarComponents
25627 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
25628
25629 const Expr *BE = checkMapClauseExpressionBase(
25630 SemaRef, E: RefExpr, CurComponents, CKind: OMPC_use_device_addr,
25631 DSAStack->getCurrentDirective(),
25632 /*NoDiagnose=*/false);
25633
25634 if (!BE)
25635 continue;
25636
25637 assert(!CurComponents.empty() &&
25638 "use_device_addr clause expression with no components!");
25639
25640 // OpenMP use_device_addr: If a list item is an array section, the array
25641 // base must be a base language identifier. We caught the cases where
25642 // the array-section has a base-variable in getPrivateItem. e.g.
25643 // struct S {
25644 // int a[10];
25645 // }; S s1;
25646 // ... use_device_addr(s1.a[0]) // not ok, caught already
25647 //
25648 // But we still neeed to verify that the base-pointer is also a
25649 // base-language identifier, and catch cases like:
25650 // int *pa[10]; *p;
25651 // ... use_device_addr(pa[1][2]) // not ok, base-pointer is pa[1]
25652 // ... use_device_addr(p[1]) // ok
25653 // ... use_device_addr(this->p[1]) // ok
25654 auto AttachPtrResult = OMPClauseMappableExprCommon::findAttachPtrExpr(
25655 Components: CurComponents, DSAStack->getCurrentDirective());
25656 const Expr *AttachPtrExpr = AttachPtrResult.first;
25657
25658 if (AttachPtrExpr) {
25659 const Expr *BaseExpr = AttachPtrExpr->IgnoreParenImpCasts();
25660 bool IsValidBase = false;
25661
25662 if (isa<DeclRefExpr>(Val: BaseExpr))
25663 IsValidBase = true;
25664 else if (const auto *ME = dyn_cast<MemberExpr>(Val: BaseExpr);
25665 ME && isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
25666 IsValidBase = true;
25667
25668 if (!IsValidBase) {
25669 SemaRef.Diag(Loc: ELoc,
25670 DiagID: diag::err_omp_expected_base_pointer_var_name_member_expr)
25671 << (SemaRef.getCurrentThisType().isNull() ? 0 : 1)
25672 << AttachPtrExpr->getSourceRange();
25673 continue;
25674 }
25675 }
25676
25677 // Get the declaration from the components
25678 ValueDecl *CurDeclaration = CurComponents.back().getAssociatedDeclaration();
25679 assert((isa<CXXThisExpr>(BE) || CurDeclaration) &&
25680 "Unexpected null decl for use_device_addr clause.");
25681
25682 MVLI.VarBaseDeclarations.push_back(Elt: CurDeclaration);
25683 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
25684 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
25685 in_end: CurComponents.end());
25686 }
25687
25688 if (MVLI.ProcessedVarList.empty())
25689 return nullptr;
25690
25691 return OMPUseDeviceAddrClause::Create(
25692 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25693 ComponentLists: MVLI.VarComponents);
25694}
25695
25696OMPClause *
25697SemaOpenMP::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
25698 const OMPVarListLocTy &Locs) {
25699 MappableVarListInfo MVLI(VarList);
25700 for (Expr *RefExpr : VarList) {
25701 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
25702 SourceLocation ELoc;
25703 SourceRange ERange;
25704 Expr *SimpleRefExpr = RefExpr;
25705 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
25706 if (Res.second) {
25707 // It will be analyzed later.
25708 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
25709 }
25710 ValueDecl *D = Res.first;
25711 if (!D)
25712 continue;
25713
25714 QualType Type = D->getType();
25715 // item should be a pointer or array or reference to pointer or array
25716 if (!Type.getNonReferenceType()->isPointerType() &&
25717 !Type.getNonReferenceType()->isArrayType()) {
25718 Diag(Loc: ELoc, DiagID: diag::err_omp_argument_type_isdeviceptr)
25719 << 0 << RefExpr->getSourceRange();
25720 continue;
25721 }
25722
25723 // Check if the declaration in the clause does not show up in any data
25724 // sharing attribute.
25725 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
25726 if (isOpenMPPrivate(Kind: DVar.CKind)) {
25727 unsigned OMPVersion = getLangOpts().OpenMP;
25728 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
25729 << getOpenMPClauseNameForDiag(C: DVar.CKind)
25730 << getOpenMPClauseNameForDiag(C: OMPC_is_device_ptr)
25731 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
25732 Ver: OMPVersion);
25733 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
25734 continue;
25735 }
25736
25737 const Expr *ConflictExpr;
25738 if (DSAStack->checkMappableExprComponentListsForDecl(
25739 VD: D, /*CurrentRegionOnly=*/true,
25740 Check: [&ConflictExpr](
25741 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
25742 OpenMPClauseKind) -> bool {
25743 ConflictExpr = R.front().getAssociatedExpression();
25744 return true;
25745 })) {
25746 Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
25747 Diag(Loc: ConflictExpr->getExprLoc(), DiagID: diag::note_used_here)
25748 << ConflictExpr->getSourceRange();
25749 continue;
25750 }
25751
25752 // Store the components in the stack so that they can be used to check
25753 // against other clauses later on.
25754 OMPClauseMappableExprCommon::MappableComponent MC(
25755 SimpleRefExpr, D, /*IsNonContiguous=*/false);
25756 DSAStack->addMappableExpressionComponents(
25757 VD: D, Components: MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
25758
25759 // Record the expression we've just processed.
25760 MVLI.ProcessedVarList.push_back(Elt: SimpleRefExpr);
25761
25762 // Create a mappable component for the list item. List items in this clause
25763 // only need a component. We use a null declaration to signal fields in
25764 // 'this'.
25765 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
25766 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
25767 "Unexpected device pointer expression!");
25768 MVLI.VarBaseDeclarations.push_back(
25769 Elt: isa<DeclRefExpr>(Val: SimpleRefExpr) ? D : nullptr);
25770 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
25771 MVLI.VarComponents.back().push_back(Elt: MC);
25772 }
25773
25774 if (MVLI.ProcessedVarList.empty())
25775 return nullptr;
25776
25777 return OMPIsDevicePtrClause::Create(
25778 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25779 ComponentLists: MVLI.VarComponents);
25780}
25781
25782OMPClause *
25783SemaOpenMP::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
25784 const OMPVarListLocTy &Locs) {
25785 MappableVarListInfo MVLI(VarList);
25786 for (Expr *RefExpr : VarList) {
25787 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
25788 SourceLocation ELoc;
25789 SourceRange ERange;
25790 Expr *SimpleRefExpr = RefExpr;
25791 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
25792 /*AllowArraySection=*/true);
25793 if (Res.second) {
25794 // It will be analyzed later.
25795 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
25796 }
25797 ValueDecl *D = Res.first;
25798 if (!D)
25799 continue;
25800
25801 // Check if the declaration in the clause does not show up in any data
25802 // sharing attribute.
25803 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
25804 if (isOpenMPPrivate(Kind: DVar.CKind)) {
25805 unsigned OMPVersion = getLangOpts().OpenMP;
25806 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
25807 << getOpenMPClauseNameForDiag(C: DVar.CKind)
25808 << getOpenMPClauseNameForDiag(C: OMPC_has_device_addr)
25809 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
25810 Ver: OMPVersion);
25811 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
25812 continue;
25813 }
25814
25815 const Expr *ConflictExpr;
25816 if (DSAStack->checkMappableExprComponentListsForDecl(
25817 VD: D, /*CurrentRegionOnly=*/true,
25818 Check: [&ConflictExpr](
25819 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
25820 OpenMPClauseKind) -> bool {
25821 ConflictExpr = R.front().getAssociatedExpression();
25822 return true;
25823 })) {
25824 Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
25825 Diag(Loc: ConflictExpr->getExprLoc(), DiagID: diag::note_used_here)
25826 << ConflictExpr->getSourceRange();
25827 continue;
25828 }
25829
25830 // Store the components in the stack so that they can be used to check
25831 // against other clauses later on.
25832 Expr *Component = SimpleRefExpr;
25833 auto *VD = dyn_cast<VarDecl>(Val: D);
25834 if (VD && (isa<ArraySectionExpr>(Val: RefExpr->IgnoreParenImpCasts()) ||
25835 isa<ArraySubscriptExpr>(Val: RefExpr->IgnoreParenImpCasts())))
25836 Component =
25837 SemaRef.DefaultFunctionArrayLvalueConversion(E: SimpleRefExpr).get();
25838 OMPClauseMappableExprCommon::MappableComponent MC(
25839 Component, D, /*IsNonContiguous=*/false);
25840 DSAStack->addMappableExpressionComponents(
25841 VD: D, Components: MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
25842
25843 // Record the expression we've just processed.
25844 if (!VD && !SemaRef.CurContext->isDependentContext()) {
25845 DeclRefExpr *Ref =
25846 buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
25847 assert(Ref && "has_device_addr capture failed");
25848 MVLI.ProcessedVarList.push_back(Elt: Ref);
25849 } else
25850 MVLI.ProcessedVarList.push_back(Elt: RefExpr->IgnoreParens());
25851
25852 // Create a mappable component for the list item. List items in this clause
25853 // only need a component. We use a null declaration to signal fields in
25854 // 'this'.
25855 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
25856 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
25857 "Unexpected device pointer expression!");
25858 MVLI.VarBaseDeclarations.push_back(
25859 Elt: isa<DeclRefExpr>(Val: SimpleRefExpr) ? D : nullptr);
25860 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
25861 MVLI.VarComponents.back().push_back(Elt: MC);
25862 }
25863
25864 if (MVLI.ProcessedVarList.empty())
25865 return nullptr;
25866
25867 return OMPHasDeviceAddrClause::Create(
25868 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
25869 ComponentLists: MVLI.VarComponents);
25870}
25871
25872OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause(
25873 Expr *Allocator, Expr *Alignment,
25874 OpenMPAllocateClauseModifier FirstAllocateModifier,
25875 SourceLocation FirstAllocateModifierLoc,
25876 OpenMPAllocateClauseModifier SecondAllocateModifier,
25877 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
25878 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
25879 SourceLocation EndLoc) {
25880 if (Allocator) {
25881 // Allocator expression is dependent - skip it for now and build the
25882 // allocator when instantiated.
25883 bool AllocDependent =
25884 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
25885 Allocator->isInstantiationDependent() ||
25886 Allocator->containsUnexpandedParameterPack());
25887 if (!AllocDependent) {
25888 // OpenMP [2.11.4 allocate Clause, Description]
25889 // allocator is an expression of omp_allocator_handle_t type.
25890 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: Allocator->getExprLoc(), DSAStack))
25891 return nullptr;
25892
25893 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(E: Allocator);
25894 if (AllocatorRes.isInvalid())
25895 return nullptr;
25896 AllocatorRes = SemaRef.PerformImplicitConversion(
25897 From: AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
25898 Action: AssignmentAction::Initializing,
25899 /*AllowExplicit=*/true);
25900 if (AllocatorRes.isInvalid())
25901 return nullptr;
25902 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
25903 }
25904 } else {
25905 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
25906 // allocate clauses that appear on a target construct or on constructs in a
25907 // target region must specify an allocator expression unless a requires
25908 // directive with the dynamic_allocators clause is present in the same
25909 // compilation unit.
25910 if (getLangOpts().OpenMPIsTargetDevice &&
25911 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
25912 SemaRef.targetDiag(Loc: StartLoc, DiagID: diag::err_expected_allocator_expression);
25913 }
25914 if (Alignment) {
25915 bool AlignmentDependent = Alignment->isTypeDependent() ||
25916 Alignment->isValueDependent() ||
25917 Alignment->isInstantiationDependent() ||
25918 Alignment->containsUnexpandedParameterPack();
25919 if (!AlignmentDependent) {
25920 ExprResult AlignResult =
25921 VerifyPositiveIntegerConstantInClause(E: Alignment, CKind: OMPC_allocate);
25922 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
25923 }
25924 }
25925 // Analyze and build list of variables.
25926 SmallVector<Expr *, 8> Vars;
25927 for (Expr *RefExpr : VarList) {
25928 assert(RefExpr && "NULL expr in OpenMP allocate clause.");
25929 SourceLocation ELoc;
25930 SourceRange ERange;
25931 Expr *SimpleRefExpr = RefExpr;
25932 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
25933 if (Res.second) {
25934 // It will be analyzed later.
25935 Vars.push_back(Elt: RefExpr);
25936 }
25937 ValueDecl *D = Res.first;
25938 if (!D)
25939 continue;
25940
25941 auto *VD = dyn_cast<VarDecl>(Val: D);
25942 DeclRefExpr *Ref = nullptr;
25943 if (!VD && !SemaRef.CurContext->isDependentContext())
25944 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
25945 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
25946 ? RefExpr->IgnoreParens()
25947 : Ref);
25948 }
25949
25950 if (Vars.empty())
25951 return nullptr;
25952
25953 if (Allocator)
25954 DSAStack->addInnerAllocatorExpr(E: Allocator);
25955
25956 return OMPAllocateClause::Create(
25957 C: getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
25958 Modifier1: FirstAllocateModifier, Modifier1Loc: FirstAllocateModifierLoc, Modifier2: SecondAllocateModifier,
25959 Modifier2Loc: SecondAllocateModifierLoc, EndLoc, VL: Vars);
25960}
25961
25962OMPClause *SemaOpenMP::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
25963 SourceLocation StartLoc,
25964 SourceLocation LParenLoc,
25965 SourceLocation EndLoc) {
25966 SmallVector<Expr *, 8> Vars;
25967 for (Expr *RefExpr : VarList) {
25968 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
25969 SourceLocation ELoc;
25970 SourceRange ERange;
25971 Expr *SimpleRefExpr = RefExpr;
25972 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
25973 if (Res.second)
25974 // It will be analyzed later.
25975 Vars.push_back(Elt: RefExpr);
25976 ValueDecl *D = Res.first;
25977 if (!D)
25978 continue;
25979
25980 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
25981 // A list-item cannot appear in more than one nontemporal clause.
25982 if (const Expr *PrevRef =
25983 DSAStack->addUniqueNontemporal(D, NewDE: SimpleRefExpr)) {
25984 Diag(Loc: ELoc, DiagID: diag::err_omp_used_in_clause_twice)
25985 << 0 << getOpenMPClauseNameForDiag(C: OMPC_nontemporal) << ERange;
25986 Diag(Loc: PrevRef->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
25987 << getOpenMPClauseNameForDiag(C: OMPC_nontemporal);
25988 continue;
25989 }
25990
25991 Vars.push_back(Elt: RefExpr);
25992 }
25993
25994 if (Vars.empty())
25995 return nullptr;
25996
25997 return OMPNontemporalClause::Create(C: getASTContext(), StartLoc, LParenLoc,
25998 EndLoc, VL: Vars);
25999}
26000
26001StmtResult SemaOpenMP::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
26002 Stmt *AStmt,
26003 SourceLocation StartLoc,
26004 SourceLocation EndLoc) {
26005 if (!AStmt)
26006 return StmtError();
26007
26008 SemaRef.setFunctionHasBranchProtectedScope();
26009
26010 return OMPScopeDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
26011 AssociatedStmt: AStmt);
26012}
26013
26014OMPClause *SemaOpenMP::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
26015 SourceLocation StartLoc,
26016 SourceLocation LParenLoc,
26017 SourceLocation EndLoc) {
26018 SmallVector<Expr *, 8> Vars;
26019 for (Expr *RefExpr : VarList) {
26020 assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
26021 SourceLocation ELoc;
26022 SourceRange ERange;
26023 Expr *SimpleRefExpr = RefExpr;
26024 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
26025 /*AllowArraySection=*/true);
26026 if (Res.second)
26027 // It will be analyzed later.
26028 Vars.push_back(Elt: RefExpr);
26029 ValueDecl *D = Res.first;
26030 if (!D)
26031 continue;
26032
26033 const DSAStackTy::DSAVarData DVar =
26034 DSAStack->getTopDSA(D, /*FromParent=*/true);
26035 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
26036 // A list item that appears in the inclusive or exclusive clause must appear
26037 // in a reduction clause with the inscan modifier on the enclosing
26038 // worksharing-loop, worksharing-loop SIMD, or simd construct.
26039 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
26040 Diag(Loc: ELoc, DiagID: diag::err_omp_inclusive_exclusive_not_reduction)
26041 << RefExpr->getSourceRange();
26042
26043 if (DSAStack->getParentDirective() != OMPD_unknown)
26044 DSAStack->markDeclAsUsedInScanDirective(D);
26045 Vars.push_back(Elt: RefExpr);
26046 }
26047
26048 if (Vars.empty())
26049 return nullptr;
26050
26051 return OMPInclusiveClause::Create(C: getASTContext(), StartLoc, LParenLoc,
26052 EndLoc, VL: Vars);
26053}
26054
26055OMPClause *SemaOpenMP::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
26056 SourceLocation StartLoc,
26057 SourceLocation LParenLoc,
26058 SourceLocation EndLoc) {
26059 SmallVector<Expr *, 8> Vars;
26060 for (Expr *RefExpr : VarList) {
26061 assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
26062 SourceLocation ELoc;
26063 SourceRange ERange;
26064 Expr *SimpleRefExpr = RefExpr;
26065 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
26066 /*AllowArraySection=*/true);
26067 if (Res.second)
26068 // It will be analyzed later.
26069 Vars.push_back(Elt: RefExpr);
26070 ValueDecl *D = Res.first;
26071 if (!D)
26072 continue;
26073
26074 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
26075 DSAStackTy::DSAVarData DVar;
26076 if (ParentDirective != OMPD_unknown)
26077 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
26078 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
26079 // A list item that appears in the inclusive or exclusive clause must appear
26080 // in a reduction clause with the inscan modifier on the enclosing
26081 // worksharing-loop, worksharing-loop SIMD, or simd construct.
26082 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
26083 DVar.Modifier != OMPC_REDUCTION_inscan) {
26084 Diag(Loc: ELoc, DiagID: diag::err_omp_inclusive_exclusive_not_reduction)
26085 << RefExpr->getSourceRange();
26086 } else {
26087 DSAStack->markDeclAsUsedInScanDirective(D);
26088 }
26089 Vars.push_back(Elt: RefExpr);
26090 }
26091
26092 if (Vars.empty())
26093 return nullptr;
26094
26095 return OMPExclusiveClause::Create(C: getASTContext(), StartLoc, LParenLoc,
26096 EndLoc, VL: Vars);
26097}
26098
26099/// Tries to find omp_alloctrait_t type.
26100static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
26101 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
26102 if (!OMPAlloctraitT.isNull())
26103 return true;
26104 IdentifierInfo &II = S.PP.getIdentifierTable().get(Name: "omp_alloctrait_t");
26105 ParsedType PT = S.getTypeName(II, NameLoc: Loc, S: S.getCurScope());
26106 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
26107 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
26108 return false;
26109 }
26110 Stack->setOMPAlloctraitT(PT.get());
26111 return true;
26112}
26113
26114OMPClause *SemaOpenMP::ActOnOpenMPUsesAllocatorClause(
26115 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
26116 ArrayRef<UsesAllocatorsData> Data) {
26117 ASTContext &Context = getASTContext();
26118 // OpenMP [2.12.5, target Construct]
26119 // allocator is an identifier of omp_allocator_handle_t type.
26120 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: StartLoc, DSAStack))
26121 return nullptr;
26122 // OpenMP [2.12.5, target Construct]
26123 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
26124 if (llvm::any_of(
26125 Range&: Data,
26126 P: [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
26127 !findOMPAlloctraitT(S&: SemaRef, Loc: StartLoc, DSAStack))
26128 return nullptr;
26129 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
26130 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
26131 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
26132 StringRef Allocator =
26133 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(Val: AllocatorKind);
26134 DeclarationName AllocatorName = &Context.Idents.get(Name: Allocator);
26135 PredefinedAllocators.insert(Ptr: SemaRef.LookupSingleName(
26136 S: SemaRef.TUScope, Name: AllocatorName, Loc: StartLoc, NameKind: Sema::LookupAnyName));
26137 }
26138
26139 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
26140 for (const UsesAllocatorsData &D : Data) {
26141 Expr *AllocatorExpr = nullptr;
26142 // Check allocator expression.
26143 if (D.Allocator->isTypeDependent()) {
26144 AllocatorExpr = D.Allocator;
26145 } else {
26146 // Traits were specified - need to assign new allocator to the specified
26147 // allocator, so it must be an lvalue.
26148 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
26149 auto *DRE = dyn_cast<DeclRefExpr>(Val: AllocatorExpr);
26150 bool IsPredefinedAllocator = false;
26151 if (DRE) {
26152 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
26153 getAllocatorKind(S&: SemaRef, DSAStack, Allocator: AllocatorExpr);
26154 IsPredefinedAllocator =
26155 AllocatorTy !=
26156 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
26157 }
26158 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
26159 QualType AllocatorExprType = AllocatorExpr->getType();
26160 bool IsTypeCompatible = IsPredefinedAllocator;
26161 IsTypeCompatible = IsTypeCompatible ||
26162 Context.hasSameUnqualifiedType(T1: AllocatorExprType,
26163 T2: OMPAllocatorHandleT);
26164 IsTypeCompatible =
26165 IsTypeCompatible ||
26166 Context.typesAreCompatible(T1: AllocatorExprType, T2: OMPAllocatorHandleT);
26167 bool IsNonConstantLValue =
26168 !AllocatorExprType.isConstant(Ctx: Context) && AllocatorExpr->isLValue();
26169 if (!DRE || !IsTypeCompatible ||
26170 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
26171 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::err_omp_var_expected)
26172 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
26173 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
26174 continue;
26175 }
26176 // OpenMP [2.12.5, target Construct]
26177 // Predefined allocators appearing in a uses_allocators clause cannot have
26178 // traits specified.
26179 if (IsPredefinedAllocator && D.AllocatorTraits) {
26180 Diag(Loc: D.AllocatorTraits->getExprLoc(),
26181 DiagID: diag::err_omp_predefined_allocator_with_traits)
26182 << D.AllocatorTraits->getSourceRange();
26183 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::note_omp_predefined_allocator)
26184 << cast<NamedDecl>(Val: DRE->getDecl())->getName()
26185 << D.Allocator->getSourceRange();
26186 continue;
26187 }
26188 // OpenMP [2.12.5, target Construct]
26189 // Non-predefined allocators appearing in a uses_allocators clause must
26190 // have traits specified.
26191 if (getLangOpts().OpenMP < 52) {
26192 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
26193 Diag(Loc: D.Allocator->getExprLoc(),
26194 DiagID: diag::err_omp_nonpredefined_allocator_without_traits);
26195 continue;
26196 }
26197 }
26198 // No allocator traits - just convert it to rvalue.
26199 if (!D.AllocatorTraits)
26200 AllocatorExpr = SemaRef.DefaultLvalueConversion(E: AllocatorExpr).get();
26201 DSAStack->addUsesAllocatorsDecl(
26202 D: DRE->getDecl(),
26203 Kind: IsPredefinedAllocator
26204 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
26205 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
26206 }
26207 Expr *AllocatorTraitsExpr = nullptr;
26208 if (D.AllocatorTraits) {
26209 if (D.AllocatorTraits->isTypeDependent()) {
26210 AllocatorTraitsExpr = D.AllocatorTraits;
26211 } else {
26212 // OpenMP [2.12.5, target Construct]
26213 // Arrays that contain allocator traits that appear in a uses_allocators
26214 // clause must be constant arrays, have constant values and be defined
26215 // in the same scope as the construct in which the clause appears.
26216 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
26217 // Check that traits expr is a constant array.
26218 QualType TraitTy;
26219 if (const ArrayType *Ty =
26220 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
26221 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Val: Ty))
26222 TraitTy = ConstArrayTy->getElementType();
26223 if (TraitTy.isNull() ||
26224 !(Context.hasSameUnqualifiedType(T1: TraitTy,
26225 DSAStack->getOMPAlloctraitT()) ||
26226 Context.typesAreCompatible(T1: TraitTy, DSAStack->getOMPAlloctraitT(),
26227 /*CompareUnqualified=*/true))) {
26228 Diag(Loc: D.AllocatorTraits->getExprLoc(),
26229 DiagID: diag::err_omp_expected_array_alloctraits)
26230 << AllocatorTraitsExpr->getType();
26231 continue;
26232 }
26233 // Do not map by default allocator traits if it is a standalone
26234 // variable.
26235 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: AllocatorTraitsExpr))
26236 DSAStack->addUsesAllocatorsDecl(
26237 D: DRE->getDecl(),
26238 Kind: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
26239 }
26240 }
26241 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
26242 NewD.Allocator = AllocatorExpr;
26243 NewD.AllocatorTraits = AllocatorTraitsExpr;
26244 NewD.LParenLoc = D.LParenLoc;
26245 NewD.RParenLoc = D.RParenLoc;
26246 }
26247 return OMPUsesAllocatorsClause::Create(C: getASTContext(), StartLoc, LParenLoc,
26248 EndLoc, Data: NewData);
26249}
26250
26251OMPClause *SemaOpenMP::ActOnOpenMPAffinityClause(
26252 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
26253 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
26254 SmallVector<Expr *, 8> Vars;
26255 for (Expr *RefExpr : Locators) {
26256 assert(RefExpr && "NULL expr in OpenMP affinity clause.");
26257 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr) || RefExpr->isTypeDependent()) {
26258 // It will be analyzed later.
26259 Vars.push_back(Elt: RefExpr);
26260 continue;
26261 }
26262
26263 SourceLocation ELoc = RefExpr->getExprLoc();
26264 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
26265
26266 if (!SimpleExpr->isLValue()) {
26267 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
26268 << 1 << 0 << RefExpr->getSourceRange();
26269 continue;
26270 }
26271
26272 ExprResult Res;
26273 {
26274 Sema::TentativeAnalysisScope Trap(SemaRef);
26275 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: SimpleExpr);
26276 }
26277 if (!Res.isUsable() && !isa<ArraySectionExpr>(Val: SimpleExpr) &&
26278 !isa<OMPArrayShapingExpr>(Val: SimpleExpr)) {
26279 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
26280 << 1 << 0 << RefExpr->getSourceRange();
26281 continue;
26282 }
26283 Vars.push_back(Elt: SimpleExpr);
26284 }
26285
26286 return OMPAffinityClause::Create(C: getASTContext(), StartLoc, LParenLoc,
26287 ColonLoc, EndLoc, Modifier, Locators: Vars);
26288}
26289
26290OMPClause *SemaOpenMP::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
26291 SourceLocation KindLoc,
26292 SourceLocation StartLoc,
26293 SourceLocation LParenLoc,
26294 SourceLocation EndLoc) {
26295 if (Kind == OMPC_BIND_unknown) {
26296 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
26297 << getListOfPossibleValues(K: OMPC_bind, /*First=*/0,
26298 /*Last=*/unsigned(OMPC_BIND_unknown))
26299 << getOpenMPClauseNameForDiag(C: OMPC_bind);
26300 return nullptr;
26301 }
26302
26303 return OMPBindClause::Create(C: getASTContext(), K: Kind, KLoc: KindLoc, StartLoc,
26304 LParenLoc, EndLoc);
26305}
26306
26307OMPClause *SemaOpenMP::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
26308 SourceLocation StartLoc,
26309 SourceLocation LParenLoc,
26310 SourceLocation EndLoc) {
26311 Expr *ValExpr = Size;
26312 Stmt *HelperValStmt = nullptr;
26313
26314 // OpenMP [2.5, Restrictions]
26315 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
26316 // value.
26317 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_ompx_dyn_cgroup_mem,
26318 /*StrictlyPositive=*/false))
26319 return nullptr;
26320
26321 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
26322 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
26323 DKind, CKind: OMPC_ompx_dyn_cgroup_mem, OpenMPVersion: getLangOpts().OpenMP);
26324 if (CaptureRegion != OMPD_unknown &&
26325 !SemaRef.CurContext->isDependentContext()) {
26326 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
26327 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26328 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
26329 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
26330 }
26331
26332 return new (getASTContext()) OMPXDynCGroupMemClause(
26333 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
26334}
26335
26336OMPClause *SemaOpenMP::ActOnOpenMPDynGroupprivateClause(
26337 OpenMPDynGroupprivateClauseModifier M1,
26338 OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size,
26339 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
26340 SourceLocation M2Loc, SourceLocation EndLoc) {
26341
26342 if ((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ||
26343 (M2Loc.isValid() && M2 == OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown)) {
26344 std::string Values = getListOfPossibleValues(
26345 K: OMPC_dyn_groupprivate, /*First=*/0, Last: OMPC_DYN_GROUPPRIVATE_unknown);
26346 Diag(Loc: (M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ? M1Loc
26347 : M2Loc,
26348 DiagID: diag::err_omp_unexpected_clause_value)
26349 << Values << getOpenMPClauseName(C: OMPC_dyn_groupprivate);
26350 return nullptr;
26351 }
26352
26353 Expr *ValExpr = Size;
26354 Stmt *HelperValStmt = nullptr;
26355
26356 // OpenMP [2.5, Restrictions]
26357 // The dyn_groupprivate expression must evaluate to a positive integer
26358 // value.
26359 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_dyn_groupprivate,
26360 /*StrictlyPositive=*/false))
26361 return nullptr;
26362
26363 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
26364 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
26365 DKind, CKind: OMPC_dyn_groupprivate, OpenMPVersion: getLangOpts().OpenMP);
26366 if (CaptureRegion != OMPD_unknown &&
26367 !SemaRef.CurContext->isDependentContext()) {
26368 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
26369 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26370 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
26371 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
26372 }
26373
26374 return new (getASTContext()) OMPDynGroupprivateClause(
26375 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
26376 M1Loc, M2, M2Loc);
26377}
26378
26379OMPClause *SemaOpenMP::ActOnOpenMPDoacrossClause(
26380 OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
26381 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
26382 SourceLocation LParenLoc, SourceLocation EndLoc) {
26383
26384 if (DSAStack->getCurrentDirective() == OMPD_ordered_standalone &&
26385 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
26386 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
26387 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
26388 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
26389 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(C: OMPC_doacross);
26390 return nullptr;
26391 }
26392
26393 SmallVector<Expr *, 8> Vars;
26394 DSAStackTy::OperatorOffsetTy OpsOffs;
26395 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
26396 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
26397 SemaRef,
26398 IsSource: DepType == OMPC_DOACROSS_source ||
26399 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
26400 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
26401 VarList, DSAStack, EndLoc);
26402 Vars = VarOffset.Vars;
26403 OpsOffs = VarOffset.OpsOffs;
26404 TotalDepCount = VarOffset.TotalDepCount;
26405 auto *C = OMPDoacrossClause::Create(C: getASTContext(), StartLoc, LParenLoc,
26406 EndLoc, DepType, DepLoc, ColonLoc, VL: Vars,
26407 NumLoops: TotalDepCount.getZExtValue());
26408 if (DSAStack->isParentOrderedRegion())
26409 DSAStack->addDoacrossDependClause(C, OpsOffs);
26410 return C;
26411}
26412
26413OMPClause *SemaOpenMP::ActOnOpenMPXAttributeClause(ArrayRef<const Attr *> Attrs,
26414 SourceLocation StartLoc,
26415 SourceLocation LParenLoc,
26416 SourceLocation EndLoc) {
26417 return new (getASTContext())
26418 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
26419}
26420
26421OMPClause *SemaOpenMP::ActOnOpenMPXBareClause(SourceLocation StartLoc,
26422 SourceLocation EndLoc) {
26423 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
26424}
26425
26426OMPClause *SemaOpenMP::ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc,
26427 SourceLocation LParenLoc,
26428 SourceLocation EndLoc) {
26429 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
26430}
26431
26432OMPClause *SemaOpenMP::ActOnOpenMPDirectivePresenceClause(
26433 OpenMPClauseKind CK, llvm::ArrayRef<OpenMPDirectiveKind> DKVec,
26434 SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc) {
26435 switch (CK) {
26436 case OMPC_absent:
26437 return OMPAbsentClause::Create(C: getASTContext(), DKVec, Loc, LLoc, RLoc);
26438 case OMPC_contains:
26439 return OMPContainsClause::Create(C: getASTContext(), DKVec, Loc, LLoc, RLoc);
26440 default:
26441 llvm_unreachable("Unexpected OpenMP clause");
26442 }
26443}
26444
26445OMPClause *SemaOpenMP::ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK,
26446 SourceLocation Loc,
26447 SourceLocation RLoc) {
26448 switch (CK) {
26449 case OMPC_no_openmp:
26450 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
26451 case OMPC_no_openmp_routines:
26452 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
26453 case OMPC_no_parallelism:
26454 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
26455 case OMPC_no_openmp_constructs:
26456 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
26457 default:
26458 llvm_unreachable("Unexpected OpenMP clause");
26459 }
26460}
26461
26462ExprResult SemaOpenMP::ActOnOMPArraySectionExpr(
26463 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
26464 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
26465 Expr *Stride, SourceLocation RBLoc) {
26466 ASTContext &Context = getASTContext();
26467 if (Base->hasPlaceholderType() &&
26468 !Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
26469 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base);
26470 if (Result.isInvalid())
26471 return ExprError();
26472 Base = Result.get();
26473 }
26474 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
26475 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: LowerBound);
26476 if (Result.isInvalid())
26477 return ExprError();
26478 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26479 if (Result.isInvalid())
26480 return ExprError();
26481 LowerBound = Result.get();
26482 }
26483 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
26484 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Length);
26485 if (Result.isInvalid())
26486 return ExprError();
26487 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26488 if (Result.isInvalid())
26489 return ExprError();
26490 Length = Result.get();
26491 }
26492 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
26493 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Stride);
26494 if (Result.isInvalid())
26495 return ExprError();
26496 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26497 if (Result.isInvalid())
26498 return ExprError();
26499 Stride = Result.get();
26500 }
26501
26502 // Build an unanalyzed expression if either operand is type-dependent.
26503 if (Base->isTypeDependent() ||
26504 (LowerBound &&
26505 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
26506 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
26507 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
26508 return new (Context) ArraySectionExpr(
26509 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
26510 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
26511 }
26512
26513 // Perform default conversions.
26514 QualType OriginalTy = ArraySectionExpr::getBaseOriginalType(Base);
26515 QualType ResultTy;
26516 if (OriginalTy->isAnyPointerType()) {
26517 ResultTy = OriginalTy->getPointeeType();
26518 } else if (OriginalTy->isArrayType()) {
26519 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
26520 } else {
26521 return ExprError(
26522 Diag(Loc: Base->getExprLoc(), DiagID: diag::err_omp_typecheck_section_value)
26523 << Base->getSourceRange());
26524 }
26525 // C99 6.5.2.1p1
26526 if (LowerBound) {
26527 auto Res = PerformOpenMPImplicitIntegerConversion(Loc: LowerBound->getExprLoc(),
26528 Op: LowerBound);
26529 if (Res.isInvalid())
26530 return ExprError(Diag(Loc: LowerBound->getExprLoc(),
26531 DiagID: diag::err_omp_typecheck_section_not_integer)
26532 << 0 << LowerBound->getSourceRange());
26533 LowerBound = Res.get();
26534
26535 if (LowerBound->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
26536 LowerBound->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
26537 Diag(Loc: LowerBound->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
26538 << 0 << LowerBound->getSourceRange();
26539 }
26540 if (Length) {
26541 auto Res =
26542 PerformOpenMPImplicitIntegerConversion(Loc: Length->getExprLoc(), Op: Length);
26543 if (Res.isInvalid())
26544 return ExprError(Diag(Loc: Length->getExprLoc(),
26545 DiagID: diag::err_omp_typecheck_section_not_integer)
26546 << 1 << Length->getSourceRange());
26547 Length = Res.get();
26548
26549 if (Length->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
26550 Length->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
26551 Diag(Loc: Length->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
26552 << 1 << Length->getSourceRange();
26553 }
26554 if (Stride) {
26555 ExprResult Res =
26556 PerformOpenMPImplicitIntegerConversion(Loc: Stride->getExprLoc(), Op: Stride);
26557 if (Res.isInvalid())
26558 return ExprError(Diag(Loc: Stride->getExprLoc(),
26559 DiagID: diag::err_omp_typecheck_section_not_integer)
26560 << 1 << Stride->getSourceRange());
26561 Stride = Res.get();
26562
26563 if (Stride->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
26564 Stride->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
26565 Diag(Loc: Stride->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
26566 << 1 << Stride->getSourceRange();
26567 }
26568
26569 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
26570 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
26571 // type. Note that functions are not objects, and that (in C99 parlance)
26572 // incomplete types are not object types.
26573 if (ResultTy->isFunctionType()) {
26574 Diag(Loc: Base->getExprLoc(), DiagID: diag::err_omp_section_function_type)
26575 << ResultTy << Base->getSourceRange();
26576 return ExprError();
26577 }
26578
26579 if (SemaRef.RequireCompleteType(Loc: Base->getExprLoc(), T: ResultTy,
26580 DiagID: diag::err_omp_section_incomplete_type, Args: Base))
26581 return ExprError();
26582
26583 if (LowerBound && !OriginalTy->isAnyPointerType()) {
26584 Expr::EvalResult Result;
26585 if (LowerBound->EvaluateAsInt(Result, Ctx: Context)) {
26586 // OpenMP 5.0, [2.1.5 Array Sections]
26587 // The array section must be a subset of the original array.
26588 llvm::APSInt LowerBoundValue = Result.Val.getInt();
26589 if (LowerBoundValue.isNegative()) {
26590 Diag(Loc: LowerBound->getExprLoc(),
26591 DiagID: diag::err_omp_section_not_subset_of_array)
26592 << LowerBound->getSourceRange();
26593 return ExprError();
26594 }
26595 }
26596 }
26597
26598 if (Length) {
26599 Expr::EvalResult Result;
26600 if (Length->EvaluateAsInt(Result, Ctx: Context)) {
26601 // OpenMP 5.0, [2.1.5 Array Sections]
26602 // The length must evaluate to non-negative integers.
26603 llvm::APSInt LengthValue = Result.Val.getInt();
26604 if (LengthValue.isNegative()) {
26605 Diag(Loc: Length->getExprLoc(), DiagID: diag::err_omp_section_length_negative)
26606 << toString(I: LengthValue, /*Radix=*/10, /*Signed=*/true)
26607 << Length->getSourceRange();
26608 return ExprError();
26609 }
26610 }
26611 } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
26612 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
26613 !OriginalTy->isVariableArrayType()))) {
26614 // OpenMP 5.0, [2.1.5 Array Sections]
26615 // When the size of the array dimension is not known, the length must be
26616 // specified explicitly.
26617 Diag(Loc: ColonLocFirst, DiagID: diag::err_omp_section_length_undefined)
26618 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
26619 return ExprError();
26620 }
26621
26622 if (Stride) {
26623 Expr::EvalResult Result;
26624 if (Stride->EvaluateAsInt(Result, Ctx: Context)) {
26625 // OpenMP 5.0, [2.1.5 Array Sections]
26626 // The stride must evaluate to a positive integer.
26627 llvm::APSInt StrideValue = Result.Val.getInt();
26628 if (!StrideValue.isStrictlyPositive()) {
26629 Diag(Loc: Stride->getExprLoc(), DiagID: diag::err_omp_section_stride_non_positive)
26630 << toString(I: StrideValue, /*Radix=*/10, /*Signed=*/true)
26631 << Stride->getSourceRange();
26632 return ExprError();
26633 }
26634 }
26635 }
26636
26637 if (!Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
26638 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(E: Base);
26639 if (Result.isInvalid())
26640 return ExprError();
26641 Base = Result.get();
26642 }
26643 return new (Context) ArraySectionExpr(
26644 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
26645 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
26646}
26647
26648ExprResult SemaOpenMP::ActOnOMPArrayShapingExpr(
26649 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
26650 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
26651 ASTContext &Context = getASTContext();
26652 if (Base->hasPlaceholderType()) {
26653 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base);
26654 if (Result.isInvalid())
26655 return ExprError();
26656 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26657 if (Result.isInvalid())
26658 return ExprError();
26659 Base = Result.get();
26660 }
26661 QualType BaseTy = Base->getType();
26662 // Delay analysis of the types/expressions if instantiation/specialization is
26663 // required.
26664 if (!BaseTy->isPointerType() && Base->isTypeDependent())
26665 return OMPArrayShapingExpr::Create(Context, T: Context.DependentTy, Op: Base,
26666 L: LParenLoc, R: RParenLoc, Dims, BracketRanges: Brackets);
26667 if (!BaseTy->isPointerType() ||
26668 (!Base->isTypeDependent() &&
26669 BaseTy->getPointeeType()->isIncompleteType()))
26670 return ExprError(Diag(Loc: Base->getExprLoc(),
26671 DiagID: diag::err_omp_non_pointer_type_array_shaping_base)
26672 << Base->getSourceRange());
26673
26674 SmallVector<Expr *, 4> NewDims;
26675 bool ErrorFound = false;
26676 for (Expr *Dim : Dims) {
26677 if (Dim->hasPlaceholderType()) {
26678 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Dim);
26679 if (Result.isInvalid()) {
26680 ErrorFound = true;
26681 continue;
26682 }
26683 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
26684 if (Result.isInvalid()) {
26685 ErrorFound = true;
26686 continue;
26687 }
26688 Dim = Result.get();
26689 }
26690 if (!Dim->isTypeDependent()) {
26691 ExprResult Result =
26692 PerformOpenMPImplicitIntegerConversion(Loc: Dim->getExprLoc(), Op: Dim);
26693 if (Result.isInvalid()) {
26694 ErrorFound = true;
26695 Diag(Loc: Dim->getExprLoc(), DiagID: diag::err_omp_typecheck_shaping_not_integer)
26696 << Dim->getSourceRange();
26697 continue;
26698 }
26699 Dim = Result.get();
26700 Expr::EvalResult EvResult;
26701 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(Result&: EvResult, Ctx: Context)) {
26702 // OpenMP 5.0, [2.1.4 Array Shaping]
26703 // Each si is an integral type expression that must evaluate to a
26704 // positive integer.
26705 llvm::APSInt Value = EvResult.Val.getInt();
26706 if (!Value.isStrictlyPositive()) {
26707 Diag(Loc: Dim->getExprLoc(), DiagID: diag::err_omp_shaping_dimension_not_positive)
26708 << toString(I: Value, /*Radix=*/10, /*Signed=*/true)
26709 << Dim->getSourceRange();
26710 ErrorFound = true;
26711 continue;
26712 }
26713 }
26714 }
26715 NewDims.push_back(Elt: Dim);
26716 }
26717 if (ErrorFound)
26718 return ExprError();
26719 return OMPArrayShapingExpr::Create(Context, T: Context.OMPArrayShapingTy, Op: Base,
26720 L: LParenLoc, R: RParenLoc, Dims: NewDims, BracketRanges: Brackets);
26721}
26722
26723ExprResult SemaOpenMP::ActOnOMPIteratorExpr(Scope *S,
26724 SourceLocation IteratorKwLoc,
26725 SourceLocation LLoc,
26726 SourceLocation RLoc,
26727 ArrayRef<OMPIteratorData> Data) {
26728 ASTContext &Context = getASTContext();
26729 SmallVector<OMPIteratorExpr::IteratorDefinition, 4> ID;
26730 bool IsCorrect = true;
26731 for (const OMPIteratorData &D : Data) {
26732 TypeSourceInfo *TInfo = nullptr;
26733 SourceLocation StartLoc;
26734 QualType DeclTy;
26735 if (!D.Type.getAsOpaquePtr()) {
26736 // OpenMP 5.0, 2.1.6 Iterators
26737 // In an iterator-specifier, if the iterator-type is not specified then
26738 // the type of that iterator is of int type.
26739 DeclTy = Context.IntTy;
26740 StartLoc = D.DeclIdentLoc;
26741 } else {
26742 DeclTy = Sema::GetTypeFromParser(Ty: D.Type, TInfo: &TInfo);
26743 StartLoc = TInfo->getTypeLoc().getBeginLoc();
26744 }
26745
26746 bool IsDeclTyDependent = DeclTy->isDependentType() ||
26747 DeclTy->containsUnexpandedParameterPack() ||
26748 DeclTy->isInstantiationDependentType();
26749 if (!IsDeclTyDependent) {
26750 if (!DeclTy->isIntegralType(Ctx: Context) && !DeclTy->isAnyPointerType()) {
26751 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
26752 // The iterator-type must be an integral or pointer type.
26753 Diag(Loc: StartLoc, DiagID: diag::err_omp_iterator_not_integral_or_pointer)
26754 << DeclTy;
26755 IsCorrect = false;
26756 continue;
26757 }
26758 if (DeclTy.isConstant(Ctx: Context)) {
26759 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
26760 // The iterator-type must not be const qualified.
26761 Diag(Loc: StartLoc, DiagID: diag::err_omp_iterator_not_integral_or_pointer)
26762 << DeclTy;
26763 IsCorrect = false;
26764 continue;
26765 }
26766 }
26767
26768 // Iterator declaration.
26769 assert(D.DeclIdent && "Identifier expected.");
26770 // Always try to create iterator declarator to avoid extra error messages
26771 // about unknown declarations use.
26772 auto *VD =
26773 VarDecl::Create(C&: Context, DC: SemaRef.CurContext, StartLoc, IdLoc: D.DeclIdentLoc,
26774 Id: D.DeclIdent, T: DeclTy, TInfo, S: SC_None);
26775 VD->setImplicit();
26776 if (S) {
26777 // Check for conflicting previous declaration.
26778 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
26779 LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
26780 RedeclarationKind::ForVisibleRedeclaration);
26781 Previous.suppressDiagnostics();
26782 SemaRef.LookupName(R&: Previous, S);
26783
26784 SemaRef.FilterLookupForScope(R&: Previous, Ctx: SemaRef.CurContext, S,
26785 /*ConsiderLinkage=*/false,
26786 /*AllowInlineNamespace=*/false);
26787 if (!Previous.empty()) {
26788 NamedDecl *Old = Previous.getRepresentativeDecl();
26789 Diag(Loc: D.DeclIdentLoc, DiagID: diag::err_redefinition) << VD->getDeclName();
26790 Diag(Loc: Old->getLocation(), DiagID: diag::note_previous_definition);
26791 } else {
26792 SemaRef.PushOnScopeChains(D: VD, S);
26793 }
26794 } else {
26795 SemaRef.CurContext->addDecl(D: VD);
26796 }
26797
26798 /// Act on the iterator variable declaration.
26799 ActOnOpenMPIteratorVarDecl(VD);
26800
26801 Expr *Begin = D.Range.Begin;
26802 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
26803 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
26804 From: Begin, ToType: DeclTy, Action: AssignmentAction::Converting);
26805 Begin = BeginRes.get();
26806 }
26807 Expr *End = D.Range.End;
26808 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
26809 ExprResult EndRes = SemaRef.PerformImplicitConversion(
26810 From: End, ToType: DeclTy, Action: AssignmentAction::Converting);
26811 End = EndRes.get();
26812 }
26813 Expr *Step = D.Range.Step;
26814 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
26815 if (!Step->getType()->isIntegralType(Ctx: Context)) {
26816 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_iterator_step_not_integral)
26817 << Step << Step->getSourceRange();
26818 IsCorrect = false;
26819 continue;
26820 }
26821 std::optional<llvm::APSInt> Result =
26822 Step->getIntegerConstantExpr(Ctx: Context);
26823 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
26824 // If the step expression of a range-specification equals zero, the
26825 // behavior is unspecified.
26826 if (Result && Result->isZero()) {
26827 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_iterator_step_constant_zero)
26828 << Step << Step->getSourceRange();
26829 IsCorrect = false;
26830 continue;
26831 }
26832 }
26833 if (!Begin || !End || !IsCorrect) {
26834 IsCorrect = false;
26835 continue;
26836 }
26837 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
26838 IDElem.IteratorDecl = VD;
26839 IDElem.AssignmentLoc = D.AssignLoc;
26840 IDElem.Range.Begin = Begin;
26841 IDElem.Range.End = End;
26842 IDElem.Range.Step = Step;
26843 IDElem.ColonLoc = D.ColonLoc;
26844 IDElem.SecondColonLoc = D.SecColonLoc;
26845 }
26846 if (!IsCorrect) {
26847 // Invalidate all created iterator declarations if error is found.
26848 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
26849 if (Decl *ID = D.IteratorDecl)
26850 ID->setInvalidDecl();
26851 }
26852 return ExprError();
26853 }
26854 SmallVector<OMPIteratorHelperData, 4> Helpers;
26855 if (!SemaRef.CurContext->isDependentContext()) {
26856 // Build number of ityeration for each iteration range.
26857 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
26858 // ((Begini-Stepi-1-Endi) / -Stepi);
26859 for (OMPIteratorExpr::IteratorDefinition &D : ID) {
26860 // (Endi - Begini)
26861 ExprResult Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Sub,
26862 LHSExpr: D.Range.End, RHSExpr: D.Range.Begin);
26863 if (!Res.isUsable()) {
26864 IsCorrect = false;
26865 continue;
26866 }
26867 ExprResult St, St1;
26868 if (D.Range.Step) {
26869 St = D.Range.Step;
26870 // (Endi - Begini) + Stepi
26871 Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add, LHSExpr: Res.get(),
26872 RHSExpr: St.get());
26873 if (!Res.isUsable()) {
26874 IsCorrect = false;
26875 continue;
26876 }
26877 // (Endi - Begini) + Stepi - 1
26878 Res = SemaRef.CreateBuiltinBinOp(
26879 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: Res.get(),
26880 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 1).get());
26881 if (!Res.isUsable()) {
26882 IsCorrect = false;
26883 continue;
26884 }
26885 // ((Endi - Begini) + Stepi - 1) / Stepi
26886 Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Div, LHSExpr: Res.get(),
26887 RHSExpr: St.get());
26888 if (!Res.isUsable()) {
26889 IsCorrect = false;
26890 continue;
26891 }
26892 St1 = SemaRef.CreateBuiltinUnaryOp(OpLoc: D.AssignmentLoc, Opc: UO_Minus,
26893 InputExpr: D.Range.Step);
26894 // (Begini - Endi)
26895 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
26896 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: D.Range.Begin, RHSExpr: D.Range.End);
26897 if (!Res1.isUsable()) {
26898 IsCorrect = false;
26899 continue;
26900 }
26901 // (Begini - Endi) - Stepi
26902 Res1 = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add, LHSExpr: Res1.get(),
26903 RHSExpr: St1.get());
26904 if (!Res1.isUsable()) {
26905 IsCorrect = false;
26906 continue;
26907 }
26908 // (Begini - Endi) - Stepi - 1
26909 Res1 = SemaRef.CreateBuiltinBinOp(
26910 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: Res1.get(),
26911 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 1).get());
26912 if (!Res1.isUsable()) {
26913 IsCorrect = false;
26914 continue;
26915 }
26916 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
26917 Res1 = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Div, LHSExpr: Res1.get(),
26918 RHSExpr: St1.get());
26919 if (!Res1.isUsable()) {
26920 IsCorrect = false;
26921 continue;
26922 }
26923 // Stepi > 0.
26924 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
26925 OpLoc: D.AssignmentLoc, Opc: BO_GT, LHSExpr: D.Range.Step,
26926 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 0).get());
26927 if (!CmpRes.isUsable()) {
26928 IsCorrect = false;
26929 continue;
26930 }
26931 Res = SemaRef.ActOnConditionalOp(QuestionLoc: D.AssignmentLoc, ColonLoc: D.AssignmentLoc,
26932 CondExpr: CmpRes.get(), LHSExpr: Res.get(), RHSExpr: Res1.get());
26933 if (!Res.isUsable()) {
26934 IsCorrect = false;
26935 continue;
26936 }
26937 }
26938 Res = SemaRef.ActOnFinishFullExpr(Expr: Res.get(), /*DiscardedValue=*/false);
26939 if (!Res.isUsable()) {
26940 IsCorrect = false;
26941 continue;
26942 }
26943
26944 // Build counter update.
26945 // Build counter.
26946 auto *CounterVD = VarDecl::Create(C&: Context, DC: SemaRef.CurContext,
26947 StartLoc: D.IteratorDecl->getBeginLoc(),
26948 IdLoc: D.IteratorDecl->getBeginLoc(), Id: nullptr,
26949 T: Res.get()->getType(), TInfo: nullptr, S: SC_None);
26950 CounterVD->setImplicit();
26951 ExprResult RefRes =
26952 SemaRef.BuildDeclRefExpr(D: CounterVD, Ty: CounterVD->getType(), VK: VK_LValue,
26953 Loc: D.IteratorDecl->getBeginLoc());
26954 // Build counter update.
26955 // I = Begini + counter * Stepi;
26956 ExprResult UpdateRes;
26957 if (D.Range.Step) {
26958 UpdateRes = SemaRef.CreateBuiltinBinOp(
26959 OpLoc: D.AssignmentLoc, Opc: BO_Mul,
26960 LHSExpr: SemaRef.DefaultLvalueConversion(E: RefRes.get()).get(), RHSExpr: St.get());
26961 } else {
26962 UpdateRes = SemaRef.DefaultLvalueConversion(E: RefRes.get());
26963 }
26964 if (!UpdateRes.isUsable()) {
26965 IsCorrect = false;
26966 continue;
26967 }
26968 UpdateRes = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add,
26969 LHSExpr: D.Range.Begin, RHSExpr: UpdateRes.get());
26970 if (!UpdateRes.isUsable()) {
26971 IsCorrect = false;
26972 continue;
26973 }
26974 ExprResult VDRes =
26975 SemaRef.BuildDeclRefExpr(D: cast<VarDecl>(Val: D.IteratorDecl),
26976 Ty: cast<VarDecl>(Val: D.IteratorDecl)->getType(),
26977 VK: VK_LValue, Loc: D.IteratorDecl->getBeginLoc());
26978 UpdateRes = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Assign,
26979 LHSExpr: VDRes.get(), RHSExpr: UpdateRes.get());
26980 if (!UpdateRes.isUsable()) {
26981 IsCorrect = false;
26982 continue;
26983 }
26984 UpdateRes =
26985 SemaRef.ActOnFinishFullExpr(Expr: UpdateRes.get(), /*DiscardedValue=*/true);
26986 if (!UpdateRes.isUsable()) {
26987 IsCorrect = false;
26988 continue;
26989 }
26990 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
26991 OpLoc: D.AssignmentLoc, Opc: UO_PreInc, InputExpr: RefRes.get());
26992 if (!CounterUpdateRes.isUsable()) {
26993 IsCorrect = false;
26994 continue;
26995 }
26996 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(Expr: CounterUpdateRes.get(),
26997 /*DiscardedValue=*/true);
26998 if (!CounterUpdateRes.isUsable()) {
26999 IsCorrect = false;
27000 continue;
27001 }
27002 OMPIteratorHelperData &HD = Helpers.emplace_back();
27003 HD.CounterVD = CounterVD;
27004 HD.Upper = Res.get();
27005 HD.Update = UpdateRes.get();
27006 HD.CounterUpdate = CounterUpdateRes.get();
27007 }
27008 } else {
27009 Helpers.assign(NumElts: ID.size(), Elt: {});
27010 }
27011 if (!IsCorrect) {
27012 // Invalidate all created iterator declarations if error is found.
27013 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
27014 if (Decl *ID = D.IteratorDecl)
27015 ID->setInvalidDecl();
27016 }
27017 return ExprError();
27018 }
27019 return OMPIteratorExpr::Create(Context, T: Context.OMPIteratorTy, IteratorKwLoc,
27020 L: LLoc, R: RLoc, Data: ID, Helpers);
27021}
27022
27023/// Check if \p AssumptionStr is a known assumption and warn if not.
27024static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc,
27025 StringRef AssumptionStr) {
27026 if (llvm::getKnownAssumptionStrings().count(Key: AssumptionStr))
27027 return;
27028
27029 unsigned BestEditDistance = 3;
27030 StringRef Suggestion;
27031 for (const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
27032 unsigned EditDistance =
27033 AssumptionStr.edit_distance(Other: KnownAssumptionIt.getKey());
27034 if (EditDistance < BestEditDistance) {
27035 Suggestion = KnownAssumptionIt.getKey();
27036 BestEditDistance = EditDistance;
27037 }
27038 }
27039
27040 if (!Suggestion.empty())
27041 S.Diag(Loc, DiagID: diag::warn_omp_assume_attribute_string_unknown_suggested)
27042 << AssumptionStr << Suggestion;
27043 else
27044 S.Diag(Loc, DiagID: diag::warn_omp_assume_attribute_string_unknown)
27045 << AssumptionStr;
27046}
27047
27048void SemaOpenMP::handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL) {
27049 // Handle the case where the attribute has a text message.
27050 StringRef Str;
27051 SourceLocation AttrStrLoc;
27052 if (!SemaRef.checkStringLiteralArgumentAttr(Attr: AL, ArgNum: 0, Str, ArgLocation: &AttrStrLoc))
27053 return;
27054
27055 checkOMPAssumeAttr(S&: SemaRef, Loc: AttrStrLoc, AssumptionStr: Str);
27056
27057 D->addAttr(A: ::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
27058}
27059
27060SemaOpenMP::SemaOpenMP(Sema &S)
27061 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
27062