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
16#include "TreeTransform.h"
17#include "clang/AST/ASTContext.h"
18#include "clang/AST/ASTMutationListener.h"
19#include "clang/AST/CXXInheritance.h"
20#include "clang/AST/Decl.h"
21#include "clang/AST/DeclCXX.h"
22#include "clang/AST/DeclOpenMP.h"
23#include "clang/AST/DynamicRecursiveASTVisitor.h"
24#include "clang/AST/OpenMPClause.h"
25#include "clang/AST/StmtCXX.h"
26#include "clang/AST/StmtOpenMP.h"
27#include "clang/AST/StmtVisitor.h"
28#include "clang/Basic/DiagnosticSema.h"
29#include "clang/Basic/OpenMPKinds.h"
30#include "clang/Basic/PartialDiagnostic.h"
31#include "clang/Basic/TargetInfo.h"
32#include "clang/Sema/EnterExpressionEvaluationContext.h"
33#include "clang/Sema/Initialization.h"
34#include "clang/Sema/Lookup.h"
35#include "clang/Sema/ParsedAttr.h"
36#include "clang/Sema/Scope.h"
37#include "clang/Sema/ScopeInfo.h"
38#include "clang/Sema/Sema.h"
39#include "llvm/ADT/IndexedMap.h"
40#include "llvm/ADT/PointerEmbeddedInt.h"
41#include "llvm/ADT/STLExtras.h"
42#include "llvm/ADT/Sequence.h"
43#include "llvm/ADT/SetVector.h"
44#include "llvm/ADT/SmallSet.h"
45#include "llvm/ADT/StringExtras.h"
46#include "llvm/Frontend/OpenMP/OMPAssume.h"
47#include "llvm/Frontend/OpenMP/OMPConstants.h"
48#include "llvm/IR/Assumptions.h"
49#include <optional>
50
51using namespace clang;
52using namespace llvm::omp;
53
54//===----------------------------------------------------------------------===//
55// Stack of data-sharing attributes for variables
56//===----------------------------------------------------------------------===//
57
58static const Expr *checkMapClauseExpressionBase(
59 Sema &SemaRef, Expr *E,
60 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
61 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
62
63static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C);
64
65namespace {
66/// Default data sharing attributes, which can be applied to directive.
67enum DefaultDataSharingAttributes {
68 DSA_unspecified = 0, /// Data sharing attribute not specified.
69 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
70 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
71 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
72 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
73};
74
75/// Stack for tracking declarations used in OpenMP directives and
76/// clauses and their data-sharing attributes.
77class DSAStackTy {
78public:
79 struct DSAVarData {
80 OpenMPDirectiveKind DKind = OMPD_unknown;
81 OpenMPClauseKind CKind = OMPC_unknown;
82 unsigned Modifier = 0;
83 const Expr *RefExpr = nullptr;
84 DeclRefExpr *PrivateCopy = nullptr;
85 SourceLocation ImplicitDSALoc;
86 bool AppliedToPointee = false;
87 DSAVarData() = default;
88 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
89 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
90 SourceLocation ImplicitDSALoc, unsigned Modifier,
91 bool AppliedToPointee)
92 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
93 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
94 AppliedToPointee(AppliedToPointee) {}
95 };
96 using OperatorOffsetTy =
97 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
98 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
99 /// Kind of the declaration used in the uses_allocators clauses.
100 enum class UsesAllocatorsDeclKind {
101 /// Predefined allocator
102 PredefinedAllocator,
103 /// User-defined allocator
104 UserDefinedAllocator,
105 /// The declaration that represent allocator trait
106 AllocatorTrait,
107 };
108
109private:
110 struct DSAInfo {
111 OpenMPClauseKind Attributes = OMPC_unknown;
112 unsigned Modifier = 0;
113 /// Pointer to a reference expression and a flag which shows that the
114 /// variable is marked as lastprivate(true) or not (false).
115 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
116 DeclRefExpr *PrivateCopy = nullptr;
117 /// true if the attribute is applied to the pointee, not the variable
118 /// itself.
119 bool AppliedToPointee = false;
120 };
121 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
122 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
123 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
124 using LoopControlVariablesMapTy =
125 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
126 /// Struct that associates a component with the clause kind where they are
127 /// found.
128 struct MappedExprComponentTy {
129 OMPClauseMappableExprCommon::MappableExprComponentLists Components;
130 OpenMPClauseKind Kind = OMPC_unknown;
131 };
132 using MappedExprComponentsTy =
133 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
134 using CriticalsWithHintsTy =
135 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
136 struct ReductionData {
137 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
138 SourceRange ReductionRange;
139 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
140 ReductionData() = default;
141 void set(BinaryOperatorKind BO, SourceRange RR) {
142 ReductionRange = RR;
143 ReductionOp = BO;
144 }
145 void set(const Expr *RefExpr, SourceRange RR) {
146 ReductionRange = RR;
147 ReductionOp = RefExpr;
148 }
149 };
150 using DeclReductionMapTy =
151 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
152 struct DefaultmapInfo {
153 OpenMPDefaultmapClauseModifier ImplicitBehavior =
154 OMPC_DEFAULTMAP_MODIFIER_unknown;
155 SourceLocation SLoc;
156 DefaultmapInfo() = default;
157 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
158 : ImplicitBehavior(M), SLoc(Loc) {}
159 };
160
161 struct SharingMapTy {
162 DeclSAMapTy SharingMap;
163 DeclReductionMapTy ReductionMap;
164 UsedRefMapTy AlignedMap;
165 UsedRefMapTy NontemporalMap;
166 MappedExprComponentsTy MappedExprComponents;
167 LoopControlVariablesMapTy LCVMap;
168 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
169 SourceLocation DefaultAttrLoc;
170 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
171 OpenMPDirectiveKind Directive = OMPD_unknown;
172 DeclarationNameInfo DirectiveName;
173 Scope *CurScope = nullptr;
174 DeclContext *Context = nullptr;
175 SourceLocation ConstructLoc;
176 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
177 /// get the data (loop counters etc.) about enclosing loop-based construct.
178 /// This data is required during codegen.
179 DoacrossClauseMapTy DoacrossDepends;
180 /// First argument (Expr *) contains optional argument of the
181 /// 'ordered' clause, the second one is true if the regions has 'ordered'
182 /// clause, false otherwise.
183 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
184 bool RegionHasOrderConcurrent = false;
185 unsigned AssociatedLoops = 1;
186 bool HasMutipleLoops = false;
187 const Decl *PossiblyLoopCounter = nullptr;
188 bool NowaitRegion = false;
189 bool UntiedRegion = false;
190 bool CancelRegion = false;
191 bool LoopStart = false;
192 bool BodyComplete = false;
193 SourceLocation PrevScanLocation;
194 SourceLocation PrevOrderedLocation;
195 SourceLocation InnerTeamsRegionLoc;
196 /// Reference to the taskgroup task_reduction reference expression.
197 Expr *TaskgroupReductionRef = nullptr;
198 llvm::DenseSet<QualType> MappedClassesQualTypes;
199 SmallVector<Expr *, 4> InnerUsedAllocators;
200 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
201 /// List of globals marked as declare target link in this target region
202 /// (isOpenMPTargetExecutionDirective(Directive) == true).
203 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
204 /// List of decls used in inclusive/exclusive clauses of the scan directive.
205 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
206 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
207 UsesAllocatorsDecls;
208 /// Data is required on creating capture fields for implicit
209 /// default first|private clause.
210 struct ImplicitDefaultFDInfoTy {
211 /// Field decl.
212 const FieldDecl *FD = nullptr;
213 /// Nesting stack level
214 size_t StackLevel = 0;
215 /// Capture variable decl.
216 VarDecl *VD = nullptr;
217 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
218 VarDecl *VD)
219 : FD(FD), StackLevel(StackLevel), VD(VD) {}
220 };
221 /// List of captured fields
222 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
223 ImplicitDefaultFirstprivateFDs;
224 Expr *DeclareMapperVar = nullptr;
225 SmallVector<VarDecl *, 16> IteratorVarDecls;
226 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
227 Scope *CurScope, SourceLocation Loc)
228 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
229 ConstructLoc(Loc) {}
230 SharingMapTy() = default;
231 };
232
233 using StackTy = SmallVector<SharingMapTy, 4>;
234
235 /// Stack of used declaration and their data-sharing attributes.
236 DeclSAMapTy Threadprivates;
237 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
238 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
239 /// true, if check for DSA must be from parent directive, false, if
240 /// from current directive.
241 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
242 Sema &SemaRef;
243 bool ForceCapturing = false;
244 /// true if all the variables in the target executable directives must be
245 /// captured by reference.
246 bool ForceCaptureByReferenceInTargetExecutable = false;
247 CriticalsWithHintsTy Criticals;
248 unsigned IgnoredStackElements = 0;
249
250 /// Iterators over the stack iterate in order from innermost to outermost
251 /// directive.
252 using const_iterator = StackTy::const_reverse_iterator;
253 const_iterator begin() const {
254 return Stack.empty() ? const_iterator()
255 : Stack.back().first.rbegin() + IgnoredStackElements;
256 }
257 const_iterator end() const {
258 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
259 }
260 using iterator = StackTy::reverse_iterator;
261 iterator begin() {
262 return Stack.empty() ? iterator()
263 : Stack.back().first.rbegin() + IgnoredStackElements;
264 }
265 iterator end() {
266 return Stack.empty() ? iterator() : Stack.back().first.rend();
267 }
268
269 // Convenience operations to get at the elements of the stack.
270
271 bool isStackEmpty() const {
272 return Stack.empty() ||
273 Stack.back().second != CurrentNonCapturingFunctionScope ||
274 Stack.back().first.size() <= IgnoredStackElements;
275 }
276 size_t getStackSize() const {
277 return isStackEmpty() ? 0
278 : Stack.back().first.size() - IgnoredStackElements;
279 }
280
281 SharingMapTy *getTopOfStackOrNull() {
282 size_t Size = getStackSize();
283 if (Size == 0)
284 return nullptr;
285 return &Stack.back().first[Size - 1];
286 }
287 const SharingMapTy *getTopOfStackOrNull() const {
288 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
289 }
290 SharingMapTy &getTopOfStack() {
291 assert(!isStackEmpty() && "no current directive");
292 return *getTopOfStackOrNull();
293 }
294 const SharingMapTy &getTopOfStack() const {
295 return const_cast<DSAStackTy &>(*this).getTopOfStack();
296 }
297
298 SharingMapTy *getSecondOnStackOrNull() {
299 size_t Size = getStackSize();
300 if (Size <= 1)
301 return nullptr;
302 return &Stack.back().first[Size - 2];
303 }
304 const SharingMapTy *getSecondOnStackOrNull() const {
305 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
306 }
307
308 /// Get the stack element at a certain level (previously returned by
309 /// \c getNestingLevel).
310 ///
311 /// Note that nesting levels count from outermost to innermost, and this is
312 /// the reverse of our iteration order where new inner levels are pushed at
313 /// the front of the stack.
314 SharingMapTy &getStackElemAtLevel(unsigned Level) {
315 assert(Level < getStackSize() && "no such stack element");
316 return Stack.back().first[Level];
317 }
318 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
319 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
320 }
321
322 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
323
324 /// Checks if the variable is a local for OpenMP region.
325 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
326
327 /// Vector of previously declared requires directives
328 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
329 /// omp_allocator_handle_t type.
330 QualType OMPAllocatorHandleT;
331 /// omp_depend_t type.
332 QualType OMPDependT;
333 /// omp_event_handle_t type.
334 QualType OMPEventHandleT;
335 /// omp_alloctrait_t type.
336 QualType OMPAlloctraitT;
337 /// Expression for the predefined allocators.
338 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
339 nullptr};
340 /// Vector of previously encountered target directives
341 SmallVector<SourceLocation, 2> TargetLocations;
342 SourceLocation AtomicLocation;
343 /// Vector of declare variant construct traits.
344 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
345
346public:
347 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
348
349 /// Sets omp_allocator_handle_t type.
350 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
351 /// Gets omp_allocator_handle_t type.
352 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
353 /// Sets omp_alloctrait_t type.
354 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
355 /// Gets omp_alloctrait_t type.
356 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
357 /// Sets the given default allocator.
358 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
359 Expr *Allocator) {
360 OMPPredefinedAllocators[AllocatorKind] = Allocator;
361 }
362 /// Returns the specified default allocator.
363 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
364 return OMPPredefinedAllocators[AllocatorKind];
365 }
366 /// Sets omp_depend_t type.
367 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
368 /// Gets omp_depend_t type.
369 QualType getOMPDependT() const { return OMPDependT; }
370
371 /// Sets omp_event_handle_t type.
372 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
373 /// Gets omp_event_handle_t type.
374 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
375
376 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
377 OpenMPClauseKind getClauseParsingMode() const {
378 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
379 return ClauseKindMode;
380 }
381 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
382
383 bool isBodyComplete() const {
384 const SharingMapTy *Top = getTopOfStackOrNull();
385 return Top && Top->BodyComplete;
386 }
387 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
388
389 bool isForceVarCapturing() const { return ForceCapturing; }
390 void setForceVarCapturing(bool V) { ForceCapturing = V; }
391
392 void setForceCaptureByReferenceInTargetExecutable(bool V) {
393 ForceCaptureByReferenceInTargetExecutable = V;
394 }
395 bool isForceCaptureByReferenceInTargetExecutable() const {
396 return ForceCaptureByReferenceInTargetExecutable;
397 }
398
399 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
400 Scope *CurScope, SourceLocation Loc) {
401 assert(!IgnoredStackElements &&
402 "cannot change stack while ignoring elements");
403 if (Stack.empty() ||
404 Stack.back().second != CurrentNonCapturingFunctionScope)
405 Stack.emplace_back(Args: StackTy(), Args&: CurrentNonCapturingFunctionScope);
406 Stack.back().first.emplace_back(Args&: DKind, Args: DirName, Args&: CurScope, Args&: Loc);
407 Stack.back().first.back().DefaultAttrLoc = Loc;
408 }
409
410 void pop() {
411 assert(!IgnoredStackElements &&
412 "cannot change stack while ignoring elements");
413 assert(!Stack.back().first.empty() &&
414 "Data-sharing attributes stack is empty!");
415 Stack.back().first.pop_back();
416 }
417
418 /// RAII object to temporarily leave the scope of a directive when we want to
419 /// logically operate in its parent.
420 class ParentDirectiveScope {
421 DSAStackTy &Self;
422 bool Active;
423
424 public:
425 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
426 : Self(Self), Active(false) {
427 if (Activate)
428 enable();
429 }
430 ~ParentDirectiveScope() { disable(); }
431 void disable() {
432 if (Active) {
433 --Self.IgnoredStackElements;
434 Active = false;
435 }
436 }
437 void enable() {
438 if (!Active) {
439 ++Self.IgnoredStackElements;
440 Active = true;
441 }
442 }
443 };
444
445 /// Marks that we're started loop parsing.
446 void loopInit() {
447 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
448 "Expected loop-based directive.");
449 getTopOfStack().LoopStart = true;
450 }
451 /// Start capturing of the variables in the loop context.
452 void loopStart() {
453 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
454 "Expected loop-based directive.");
455 getTopOfStack().LoopStart = false;
456 }
457 /// true, if variables are captured, false otherwise.
458 bool isLoopStarted() const {
459 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
460 "Expected loop-based directive.");
461 return !getTopOfStack().LoopStart;
462 }
463 /// Marks (or clears) declaration as possibly loop counter.
464 void resetPossibleLoopCounter(const Decl *D = nullptr) {
465 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
466 }
467 /// Gets the possible loop counter decl.
468 const Decl *getPossiblyLoopCounter() const {
469 return getTopOfStack().PossiblyLoopCounter;
470 }
471 /// Start new OpenMP region stack in new non-capturing function.
472 void pushFunction() {
473 assert(!IgnoredStackElements &&
474 "cannot change stack while ignoring elements");
475 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
476 assert(!isa<CapturingScopeInfo>(CurFnScope));
477 CurrentNonCapturingFunctionScope = CurFnScope;
478 }
479 /// Pop region stack for non-capturing function.
480 void popFunction(const FunctionScopeInfo *OldFSI) {
481 assert(!IgnoredStackElements &&
482 "cannot change stack while ignoring elements");
483 if (!Stack.empty() && Stack.back().second == OldFSI) {
484 assert(Stack.back().first.empty());
485 Stack.pop_back();
486 }
487 CurrentNonCapturingFunctionScope = nullptr;
488 for (const FunctionScopeInfo *FSI : llvm::reverse(C&: SemaRef.FunctionScopes)) {
489 if (!isa<CapturingScopeInfo>(Val: FSI)) {
490 CurrentNonCapturingFunctionScope = FSI;
491 break;
492 }
493 }
494 }
495
496 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
497 Criticals.try_emplace(Key: D->getDirectiveName().getAsString(), Args&: D, Args&: Hint);
498 }
499 std::pair<const OMPCriticalDirective *, llvm::APSInt>
500 getCriticalWithHint(const DeclarationNameInfo &Name) const {
501 auto I = Criticals.find(Key: Name.getAsString());
502 if (I != Criticals.end())
503 return I->second;
504 return std::make_pair(x: nullptr, y: llvm::APSInt());
505 }
506 /// If 'aligned' declaration for given variable \a D was not seen yet,
507 /// add it and return NULL; otherwise return previous occurrence's expression
508 /// for diagnostics.
509 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
510 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
511 /// add it and return NULL; otherwise return previous occurrence's expression
512 /// for diagnostics.
513 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
514
515 /// Register specified variable as loop control variable.
516 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
517 /// Check if the specified variable is a loop control variable for
518 /// current region.
519 /// \return The index of the loop control variable in the list of associated
520 /// for-loops (from outer to inner).
521 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
522 /// Check if the specified variable is a loop control variable for
523 /// parent region.
524 /// \return The index of the loop control variable in the list of associated
525 /// for-loops (from outer to inner).
526 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
527 /// Check if the specified variable is a loop control variable for
528 /// current region.
529 /// \return The index of the loop control variable in the list of associated
530 /// for-loops (from outer to inner).
531 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
532 unsigned Level) const;
533 /// Get the loop control variable for the I-th loop (or nullptr) in
534 /// parent directive.
535 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
536
537 /// Marks the specified decl \p D as used in scan directive.
538 void markDeclAsUsedInScanDirective(ValueDecl *D) {
539 if (SharingMapTy *Stack = getSecondOnStackOrNull())
540 Stack->UsedInScanDirective.insert(V: D);
541 }
542
543 /// Checks if the specified declaration was used in the inner scan directive.
544 bool isUsedInScanDirective(ValueDecl *D) const {
545 if (const SharingMapTy *Stack = getTopOfStackOrNull())
546 return Stack->UsedInScanDirective.contains(V: D);
547 return false;
548 }
549
550 /// Adds explicit data sharing attribute to the specified declaration.
551 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
552 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
553 bool AppliedToPointee = false);
554
555 /// Adds additional information for the reduction items with the reduction id
556 /// represented as an operator.
557 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
558 BinaryOperatorKind BOK);
559 /// Adds additional information for the reduction items with the reduction id
560 /// represented as reduction identifier.
561 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
562 const Expr *ReductionRef);
563 /// Returns the location and reduction operation from the innermost parent
564 /// region for the given \p D.
565 const DSAVarData
566 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
567 BinaryOperatorKind &BOK,
568 Expr *&TaskgroupDescriptor) const;
569 /// Returns the location and reduction operation from the innermost parent
570 /// region for the given \p D.
571 const DSAVarData
572 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
573 const Expr *&ReductionRef,
574 Expr *&TaskgroupDescriptor) const;
575 /// Return reduction reference expression for the current taskgroup or
576 /// parallel/worksharing directives with task reductions.
577 Expr *getTaskgroupReductionRef() const {
578 assert((getTopOfStack().Directive == OMPD_taskgroup ||
579 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
580 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
581 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
582 "taskgroup reference expression requested for non taskgroup or "
583 "parallel/worksharing directive.");
584 return getTopOfStack().TaskgroupReductionRef;
585 }
586 /// Checks if the given \p VD declaration is actually a taskgroup reduction
587 /// descriptor variable at the \p Level of OpenMP regions.
588 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
589 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
590 cast<DeclRefExpr>(Val: getStackElemAtLevel(Level).TaskgroupReductionRef)
591 ->getDecl() == VD;
592 }
593
594 /// Returns data sharing attributes from top of the stack for the
595 /// specified declaration.
596 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
597 /// Returns data-sharing attributes for the specified declaration.
598 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
599 /// Returns data-sharing attributes for the specified declaration.
600 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
601 /// Checks if the specified variables has data-sharing attributes which
602 /// match specified \a CPred predicate in any directive which matches \a DPred
603 /// predicate.
604 const DSAVarData
605 hasDSA(ValueDecl *D,
606 const llvm::function_ref<bool(OpenMPClauseKind, bool,
607 DefaultDataSharingAttributes)>
608 CPred,
609 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
610 bool FromParent) const;
611 /// Checks if the specified variables has data-sharing attributes which
612 /// match specified \a CPred predicate in any innermost directive which
613 /// matches \a DPred predicate.
614 const DSAVarData
615 hasInnermostDSA(ValueDecl *D,
616 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
617 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
618 bool FromParent) const;
619 /// Checks if the specified variables has explicit data-sharing
620 /// attributes which match specified \a CPred predicate at the specified
621 /// OpenMP region.
622 bool
623 hasExplicitDSA(const ValueDecl *D,
624 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
625 unsigned Level, bool NotLastprivate = false) const;
626
627 /// Returns true if the directive at level \Level matches in the
628 /// specified \a DPred predicate.
629 bool hasExplicitDirective(
630 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
631 unsigned Level) const;
632
633 /// Finds a directive which matches specified \a DPred predicate.
634 bool hasDirective(
635 const llvm::function_ref<bool(
636 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
637 DPred,
638 bool FromParent) const;
639
640 /// Returns currently analyzed directive.
641 OpenMPDirectiveKind getCurrentDirective() const {
642 const SharingMapTy *Top = getTopOfStackOrNull();
643 return Top ? Top->Directive : OMPD_unknown;
644 }
645 /// Returns directive kind at specified level.
646 OpenMPDirectiveKind getDirective(unsigned Level) const {
647 assert(!isStackEmpty() && "No directive at specified level.");
648 return getStackElemAtLevel(Level).Directive;
649 }
650 /// Returns the capture region at the specified level.
651 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
652 unsigned OpenMPCaptureLevel) const {
653 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
654 getOpenMPCaptureRegions(CaptureRegions, DKind: getDirective(Level));
655 return CaptureRegions[OpenMPCaptureLevel];
656 }
657 /// Returns parent directive.
658 OpenMPDirectiveKind getParentDirective() const {
659 const SharingMapTy *Parent = getSecondOnStackOrNull();
660 return Parent ? Parent->Directive : OMPD_unknown;
661 }
662
663 /// Add requires decl to internal vector
664 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(Elt: RD); }
665
666 /// Checks if the defined 'requires' directive has specified type of clause.
667 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
668 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
669 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
670 return isa<ClauseType>(C);
671 });
672 });
673 }
674
675 /// Checks for a duplicate clause amongst previously declared requires
676 /// directives
677 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
678 bool IsDuplicate = false;
679 for (OMPClause *CNew : ClauseList) {
680 for (const OMPRequiresDecl *D : RequiresDecls) {
681 for (const OMPClause *CPrev : D->clauselists()) {
682 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
683 SemaRef.Diag(Loc: CNew->getBeginLoc(),
684 DiagID: diag::err_omp_requires_clause_redeclaration)
685 << getOpenMPClauseNameForDiag(C: CNew->getClauseKind());
686 SemaRef.Diag(Loc: CPrev->getBeginLoc(),
687 DiagID: diag::note_omp_requires_previous_clause)
688 << getOpenMPClauseNameForDiag(C: CPrev->getClauseKind());
689 IsDuplicate = true;
690 }
691 }
692 }
693 }
694 return IsDuplicate;
695 }
696
697 /// Add location of previously encountered target to internal vector
698 void addTargetDirLocation(SourceLocation LocStart) {
699 TargetLocations.push_back(Elt: LocStart);
700 }
701
702 /// Add location for the first encountered atomic directive.
703 void addAtomicDirectiveLoc(SourceLocation Loc) {
704 if (AtomicLocation.isInvalid())
705 AtomicLocation = Loc;
706 }
707
708 /// Returns the location of the first encountered atomic directive in the
709 /// module.
710 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
711
712 // Return previously encountered target region locations.
713 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
714 return TargetLocations;
715 }
716
717 /// Set default data sharing attribute to none.
718 void setDefaultDSANone(SourceLocation Loc) {
719 getTopOfStack().DefaultAttr = DSA_none;
720 getTopOfStack().DefaultAttrLoc = Loc;
721 }
722 /// Set default data sharing attribute to shared.
723 void setDefaultDSAShared(SourceLocation Loc) {
724 getTopOfStack().DefaultAttr = DSA_shared;
725 getTopOfStack().DefaultAttrLoc = Loc;
726 }
727 /// Set default data sharing attribute to private.
728 void setDefaultDSAPrivate(SourceLocation Loc) {
729 getTopOfStack().DefaultAttr = DSA_private;
730 getTopOfStack().DefaultAttrLoc = Loc;
731 }
732 /// Set default data sharing attribute to firstprivate.
733 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
734 getTopOfStack().DefaultAttr = DSA_firstprivate;
735 getTopOfStack().DefaultAttrLoc = Loc;
736 }
737 /// Set default data mapping attribute to Modifier:Kind
738 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
739 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
740 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
741 DMI.ImplicitBehavior = M;
742 DMI.SLoc = Loc;
743 }
744 /// Check whether the implicit-behavior has been set in defaultmap
745 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
746 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
747 return getTopOfStack()
748 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
749 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
750 getTopOfStack()
751 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
752 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
753 getTopOfStack()
754 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
755 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
756 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
757 OMPC_DEFAULTMAP_MODIFIER_unknown;
758 }
759
760 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
761 return ConstructTraits;
762 }
763 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
764 bool ScopeEntry) {
765 if (ScopeEntry)
766 ConstructTraits.append(in_start: Traits.begin(), in_end: Traits.end());
767 else
768 for (llvm::omp::TraitProperty Trait : llvm::reverse(C&: Traits)) {
769 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
770 assert(Top == Trait && "Something left a trait on the stack!");
771 (void)Trait;
772 (void)Top;
773 }
774 }
775
776 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
777 return getStackSize() <= Level ? DSA_unspecified
778 : getStackElemAtLevel(Level).DefaultAttr;
779 }
780 DefaultDataSharingAttributes getDefaultDSA() const {
781 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
782 }
783 SourceLocation getDefaultDSALocation() const {
784 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
785 }
786 OpenMPDefaultmapClauseModifier
787 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
788 return isStackEmpty()
789 ? OMPC_DEFAULTMAP_MODIFIER_unknown
790 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
791 }
792 OpenMPDefaultmapClauseModifier
793 getDefaultmapModifierAtLevel(unsigned Level,
794 OpenMPDefaultmapClauseKind Kind) const {
795 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
796 }
797 bool isDefaultmapCapturedByRef(unsigned Level,
798 OpenMPDefaultmapClauseKind Kind) const {
799 OpenMPDefaultmapClauseModifier M =
800 getDefaultmapModifierAtLevel(Level, Kind);
801 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
802 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
803 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
804 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
805 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
806 (M == OMPC_DEFAULTMAP_MODIFIER_present);
807 }
808 return true;
809 }
810 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
811 OpenMPDefaultmapClauseKind Kind) {
812 switch (Kind) {
813 case OMPC_DEFAULTMAP_scalar:
814 case OMPC_DEFAULTMAP_pointer:
815 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
816 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
817 (M == OMPC_DEFAULTMAP_MODIFIER_default);
818 case OMPC_DEFAULTMAP_aggregate:
819 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
820 default:
821 break;
822 }
823 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
824 }
825 bool mustBeFirstprivateAtLevel(unsigned Level,
826 OpenMPDefaultmapClauseKind Kind) const {
827 OpenMPDefaultmapClauseModifier M =
828 getDefaultmapModifierAtLevel(Level, Kind);
829 return mustBeFirstprivateBase(M, Kind);
830 }
831 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
832 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
833 return mustBeFirstprivateBase(M, Kind);
834 }
835
836 /// Checks if the specified variable is a threadprivate.
837 bool isThreadPrivate(VarDecl *D) {
838 const DSAVarData DVar = getTopDSA(D, FromParent: false);
839 return isOpenMPThreadPrivate(Kind: DVar.CKind);
840 }
841
842 /// Marks current region as ordered (it has an 'ordered' clause).
843 void setOrderedRegion(bool IsOrdered, const Expr *Param,
844 OMPOrderedClause *Clause) {
845 if (IsOrdered)
846 getTopOfStack().OrderedRegion.emplace(args&: Param, args&: Clause);
847 else
848 getTopOfStack().OrderedRegion.reset();
849 }
850 /// Returns true, if region is ordered (has associated 'ordered' clause),
851 /// false - otherwise.
852 bool isOrderedRegion() const {
853 if (const SharingMapTy *Top = getTopOfStackOrNull())
854 return Top->OrderedRegion.has_value();
855 return false;
856 }
857 /// Returns optional parameter for the ordered region.
858 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
859 if (const SharingMapTy *Top = getTopOfStackOrNull())
860 if (Top->OrderedRegion)
861 return *Top->OrderedRegion;
862 return std::make_pair(x: nullptr, y: nullptr);
863 }
864 /// Returns true, if parent region is ordered (has associated
865 /// 'ordered' clause), false - otherwise.
866 bool isParentOrderedRegion() const {
867 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
868 return Parent->OrderedRegion.has_value();
869 return false;
870 }
871 /// Returns optional parameter for the ordered region.
872 std::pair<const Expr *, OMPOrderedClause *>
873 getParentOrderedRegionParam() const {
874 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
875 if (Parent->OrderedRegion)
876 return *Parent->OrderedRegion;
877 return std::make_pair(x: nullptr, y: nullptr);
878 }
879 /// Marks current region as having an 'order' clause.
880 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
881 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
882 }
883 /// Returns true, if parent region is order (has associated
884 /// 'order' clause), false - otherwise.
885 bool isParentOrderConcurrent() const {
886 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
887 return Parent->RegionHasOrderConcurrent;
888 return false;
889 }
890 /// Marks current region as nowait (it has a 'nowait' clause).
891 void setNowaitRegion(bool IsNowait = true) {
892 getTopOfStack().NowaitRegion = IsNowait;
893 }
894 /// Returns true, if parent region is nowait (has associated
895 /// 'nowait' clause), false - otherwise.
896 bool isParentNowaitRegion() const {
897 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
898 return Parent->NowaitRegion;
899 return false;
900 }
901 /// Marks current region as untied (it has a 'untied' clause).
902 void setUntiedRegion(bool IsUntied = true) {
903 getTopOfStack().UntiedRegion = IsUntied;
904 }
905 /// Return true if current region is untied.
906 bool isUntiedRegion() const {
907 const SharingMapTy *Top = getTopOfStackOrNull();
908 return Top ? Top->UntiedRegion : false;
909 }
910 /// Marks parent region as cancel region.
911 void setParentCancelRegion(bool Cancel = true) {
912 if (SharingMapTy *Parent = getSecondOnStackOrNull())
913 Parent->CancelRegion |= Cancel;
914 }
915 /// Return true if current region has inner cancel construct.
916 bool isCancelRegion() const {
917 const SharingMapTy *Top = getTopOfStackOrNull();
918 return Top ? Top->CancelRegion : false;
919 }
920
921 /// Mark that parent region already has scan directive.
922 void setParentHasScanDirective(SourceLocation Loc) {
923 if (SharingMapTy *Parent = getSecondOnStackOrNull())
924 Parent->PrevScanLocation = Loc;
925 }
926 /// Return true if current region has inner cancel construct.
927 bool doesParentHasScanDirective() const {
928 const SharingMapTy *Top = getSecondOnStackOrNull();
929 return Top ? Top->PrevScanLocation.isValid() : false;
930 }
931 /// Return true if current region has inner cancel construct.
932 SourceLocation getParentScanDirectiveLoc() const {
933 const SharingMapTy *Top = getSecondOnStackOrNull();
934 return Top ? Top->PrevScanLocation : SourceLocation();
935 }
936 /// Mark that parent region already has ordered directive.
937 void setParentHasOrderedDirective(SourceLocation Loc) {
938 if (SharingMapTy *Parent = getSecondOnStackOrNull())
939 Parent->PrevOrderedLocation = Loc;
940 }
941 /// Return true if current region has inner ordered construct.
942 bool doesParentHasOrderedDirective() const {
943 const SharingMapTy *Top = getSecondOnStackOrNull();
944 return Top ? Top->PrevOrderedLocation.isValid() : false;
945 }
946 /// Returns the location of the previously specified ordered directive.
947 SourceLocation getParentOrderedDirectiveLoc() const {
948 const SharingMapTy *Top = getSecondOnStackOrNull();
949 return Top ? Top->PrevOrderedLocation : SourceLocation();
950 }
951
952 /// Set collapse value for the region.
953 void setAssociatedLoops(unsigned Val) {
954 getTopOfStack().AssociatedLoops = Val;
955 if (Val > 1)
956 getTopOfStack().HasMutipleLoops = true;
957 }
958 /// Return collapse value for region.
959 unsigned getAssociatedLoops() const {
960 const SharingMapTy *Top = getTopOfStackOrNull();
961 return Top ? Top->AssociatedLoops : 0;
962 }
963 /// Returns true if the construct is associated with multiple loops.
964 bool hasMutipleLoops() const {
965 const SharingMapTy *Top = getTopOfStackOrNull();
966 return Top ? Top->HasMutipleLoops : false;
967 }
968
969 /// Marks current target region as one with closely nested teams
970 /// region.
971 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
972 if (SharingMapTy *Parent = getSecondOnStackOrNull())
973 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
974 }
975 /// Returns true, if current region has closely nested teams region.
976 bool hasInnerTeamsRegion() const {
977 return getInnerTeamsRegionLoc().isValid();
978 }
979 /// Returns location of the nested teams region (if any).
980 SourceLocation getInnerTeamsRegionLoc() const {
981 const SharingMapTy *Top = getTopOfStackOrNull();
982 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
983 }
984
985 Scope *getCurScope() const {
986 const SharingMapTy *Top = getTopOfStackOrNull();
987 return Top ? Top->CurScope : nullptr;
988 }
989 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
990 SourceLocation getConstructLoc() const {
991 const SharingMapTy *Top = getTopOfStackOrNull();
992 return Top ? Top->ConstructLoc : SourceLocation();
993 }
994
995 /// Do the check specified in \a Check to all component lists and return true
996 /// if any issue is found.
997 bool checkMappableExprComponentListsForDecl(
998 const ValueDecl *VD, bool CurrentRegionOnly,
999 const llvm::function_ref<
1000 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1001 OpenMPClauseKind)>
1002 Check) const {
1003 if (isStackEmpty())
1004 return false;
1005 auto SI = begin();
1006 auto SE = end();
1007
1008 if (SI == SE)
1009 return false;
1010
1011 if (CurrentRegionOnly)
1012 SE = std::next(x: SI);
1013 else
1014 std::advance(i&: SI, n: 1);
1015
1016 for (; SI != SE; ++SI) {
1017 auto MI = SI->MappedExprComponents.find(Val: VD);
1018 if (MI != SI->MappedExprComponents.end())
1019 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1020 MI->second.Components)
1021 if (Check(L, MI->second.Kind))
1022 return true;
1023 }
1024 return false;
1025 }
1026
1027 /// Do the check specified in \a Check to all component lists at a given level
1028 /// and return true if any issue is found.
1029 bool checkMappableExprComponentListsForDeclAtLevel(
1030 const ValueDecl *VD, unsigned Level,
1031 const llvm::function_ref<
1032 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1033 OpenMPClauseKind)>
1034 Check) const {
1035 if (getStackSize() <= Level)
1036 return false;
1037
1038 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1039 auto MI = StackElem.MappedExprComponents.find(Val: VD);
1040 if (MI != StackElem.MappedExprComponents.end())
1041 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1042 MI->second.Components)
1043 if (Check(L, MI->second.Kind))
1044 return true;
1045 return false;
1046 }
1047
1048 /// Create a new mappable expression component list associated with a given
1049 /// declaration and initialize it with the provided list of components.
1050 void addMappableExpressionComponents(
1051 const ValueDecl *VD,
1052 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
1053 OpenMPClauseKind WhereFoundClauseKind) {
1054 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1055 // Create new entry and append the new components there.
1056 MEC.Components.resize(N: MEC.Components.size() + 1);
1057 MEC.Components.back().append(in_start: Components.begin(), in_end: Components.end());
1058 MEC.Kind = WhereFoundClauseKind;
1059 }
1060
1061 unsigned getNestingLevel() const {
1062 assert(!isStackEmpty());
1063 return getStackSize() - 1;
1064 }
1065 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1066 SharingMapTy *Parent = getSecondOnStackOrNull();
1067 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1068 Parent->DoacrossDepends.try_emplace(Key: C, Args: OpsOffs);
1069 }
1070 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1071 getDoacrossDependClauses() const {
1072 const SharingMapTy &StackElem = getTopOfStack();
1073 if (isOpenMPWorksharingDirective(DKind: StackElem.Directive)) {
1074 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1075 return llvm::make_range(x: Ref.begin(), y: Ref.end());
1076 }
1077 return llvm::make_range(x: StackElem.DoacrossDepends.end(),
1078 y: StackElem.DoacrossDepends.end());
1079 }
1080
1081 // Store types of classes which have been explicitly mapped
1082 void addMappedClassesQualTypes(QualType QT) {
1083 SharingMapTy &StackElem = getTopOfStack();
1084 StackElem.MappedClassesQualTypes.insert(V: QT);
1085 }
1086
1087 // Return set of mapped classes types
1088 bool isClassPreviouslyMapped(QualType QT) const {
1089 const SharingMapTy &StackElem = getTopOfStack();
1090 return StackElem.MappedClassesQualTypes.contains(V: QT);
1091 }
1092
1093 /// Adds global declare target to the parent target region.
1094 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1095 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1096 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1097 "Expected declare target link global.");
1098 for (auto &Elem : *this) {
1099 if (isOpenMPTargetExecutionDirective(DKind: Elem.Directive)) {
1100 Elem.DeclareTargetLinkVarDecls.push_back(Elt: E);
1101 return;
1102 }
1103 }
1104 }
1105
1106 /// Returns the list of globals with declare target link if current directive
1107 /// is target.
1108 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1109 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1110 "Expected target executable directive.");
1111 return getTopOfStack().DeclareTargetLinkVarDecls;
1112 }
1113
1114 /// Adds list of allocators expressions.
1115 void addInnerAllocatorExpr(Expr *E) {
1116 getTopOfStack().InnerUsedAllocators.push_back(Elt: E);
1117 }
1118 /// Return list of used allocators.
1119 ArrayRef<Expr *> getInnerAllocators() const {
1120 return getTopOfStack().InnerUsedAllocators;
1121 }
1122 /// Marks the declaration as implicitly firstprivate nin the task-based
1123 /// regions.
1124 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1125 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(V: D);
1126 }
1127 /// Checks if the decl is implicitly firstprivate in the task-based region.
1128 bool isImplicitTaskFirstprivate(Decl *D) const {
1129 return getTopOfStack().ImplicitTaskFirstprivates.contains(V: D);
1130 }
1131
1132 /// Marks decl as used in uses_allocators clause as the allocator.
1133 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1134 getTopOfStack().UsesAllocatorsDecls.try_emplace(Key: D, Args&: Kind);
1135 }
1136 /// Checks if specified decl is used in uses allocator clause as the
1137 /// allocator.
1138 std::optional<UsesAllocatorsDeclKind>
1139 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1140 const SharingMapTy &StackElem = getTopOfStack();
1141 auto I = StackElem.UsesAllocatorsDecls.find(Val: D);
1142 if (I == StackElem.UsesAllocatorsDecls.end())
1143 return std::nullopt;
1144 return I->getSecond();
1145 }
1146 std::optional<UsesAllocatorsDeclKind>
1147 isUsesAllocatorsDecl(const Decl *D) const {
1148 const SharingMapTy &StackElem = getTopOfStack();
1149 auto I = StackElem.UsesAllocatorsDecls.find(Val: D);
1150 if (I == StackElem.UsesAllocatorsDecls.end())
1151 return std::nullopt;
1152 return I->getSecond();
1153 }
1154
1155 void addDeclareMapperVarRef(Expr *Ref) {
1156 SharingMapTy &StackElem = getTopOfStack();
1157 StackElem.DeclareMapperVar = Ref;
1158 }
1159 const Expr *getDeclareMapperVarRef() const {
1160 const SharingMapTy *Top = getTopOfStackOrNull();
1161 return Top ? Top->DeclareMapperVar : nullptr;
1162 }
1163
1164 /// Add a new iterator variable.
1165 void addIteratorVarDecl(VarDecl *VD) {
1166 SharingMapTy &StackElem = getTopOfStack();
1167 StackElem.IteratorVarDecls.push_back(Elt: VD->getCanonicalDecl());
1168 }
1169 /// Check if variable declaration is an iterator VarDecl.
1170 bool isIteratorVarDecl(const VarDecl *VD) const {
1171 const SharingMapTy *Top = getTopOfStackOrNull();
1172 if (!Top)
1173 return false;
1174
1175 return llvm::is_contained(Range: Top->IteratorVarDecls, Element: VD->getCanonicalDecl());
1176 }
1177 /// get captured field from ImplicitDefaultFirstprivateFDs
1178 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1179 const_iterator I = begin();
1180 const_iterator EndI = end();
1181 size_t StackLevel = getStackSize();
1182 for (; I != EndI; ++I) {
1183 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1184 break;
1185 StackLevel--;
1186 }
1187 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1188 if (I == EndI)
1189 return nullptr;
1190 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1191 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1192 return IFD.VD;
1193 return nullptr;
1194 }
1195 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1196 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1197 const_iterator I = begin();
1198 const_iterator EndI = end();
1199 for (; I != EndI; ++I)
1200 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1201 break;
1202 if (I == EndI)
1203 return false;
1204 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1205 if (IFD.VD == VD)
1206 return true;
1207 return false;
1208 }
1209 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1210 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1211 iterator I = begin();
1212 const_iterator EndI = end();
1213 size_t StackLevel = getStackSize();
1214 for (; I != EndI; ++I) {
1215 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1216 I->ImplicitDefaultFirstprivateFDs.emplace_back(Args&: FD, Args&: StackLevel, Args&: VD);
1217 break;
1218 }
1219 StackLevel--;
1220 }
1221 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1222 }
1223};
1224
1225bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1226 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1227}
1228
1229bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1230 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(Kind: DKind) ||
1231 DKind == OMPD_unknown;
1232}
1233
1234} // namespace
1235
1236static const Expr *getExprAsWritten(const Expr *E) {
1237 if (const auto *FE = dyn_cast<FullExpr>(Val: E))
1238 E = FE->getSubExpr();
1239
1240 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Val: E))
1241 E = MTE->getSubExpr();
1242
1243 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(Val: E))
1244 E = Binder->getSubExpr();
1245
1246 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(Val: E))
1247 E = ICE->getSubExprAsWritten();
1248 return E->IgnoreParens();
1249}
1250
1251static Expr *getExprAsWritten(Expr *E) {
1252 return const_cast<Expr *>(getExprAsWritten(E: const_cast<const Expr *>(E)));
1253}
1254
1255static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1256 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: D))
1257 if (const auto *ME = dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit())))
1258 D = ME->getMemberDecl();
1259
1260 D = cast<ValueDecl>(Val: D->getCanonicalDecl());
1261 return D;
1262}
1263
1264static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1265 return const_cast<ValueDecl *>(
1266 getCanonicalDecl(D: const_cast<const ValueDecl *>(D)));
1267}
1268
1269static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C) {
1270 if (C == OMPC_threadprivate)
1271 return getOpenMPClauseName(C).str() + " or thread local";
1272 return getOpenMPClauseName(C).str();
1273}
1274
1275DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1276 ValueDecl *D) const {
1277 D = getCanonicalDecl(D);
1278 auto *VD = dyn_cast<VarDecl>(Val: D);
1279 const auto *FD = dyn_cast<FieldDecl>(Val: D);
1280 DSAVarData DVar;
1281 if (Iter == end()) {
1282 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1283 // in a region but not in construct]
1284 // File-scope or namespace-scope variables referenced in called routines
1285 // in the region are shared unless they appear in a threadprivate
1286 // directive.
1287 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(Val: VD))
1288 DVar.CKind = OMPC_shared;
1289
1290 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1291 // in a region but not in construct]
1292 // Variables with static storage duration that are declared in called
1293 // routines in the region are shared.
1294 if (VD && VD->hasGlobalStorage())
1295 DVar.CKind = OMPC_shared;
1296
1297 // Non-static data members are shared by default.
1298 if (FD)
1299 DVar.CKind = OMPC_shared;
1300
1301 return DVar;
1302 }
1303
1304 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1305 // in a Construct, C/C++, predetermined, p.1]
1306 // Variables with automatic storage duration that are declared in a scope
1307 // inside the construct are private.
1308 if (VD && isOpenMPLocal(D: VD, Iter) && VD->isLocalVarDecl() &&
1309 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1310 DVar.CKind = OMPC_private;
1311 return DVar;
1312 }
1313
1314 DVar.DKind = Iter->Directive;
1315 // Explicitly specified attributes and local variables with predetermined
1316 // attributes.
1317 if (Iter->SharingMap.count(Val: D)) {
1318 const DSAInfo &Data = Iter->SharingMap.lookup(Val: D);
1319 DVar.RefExpr = Data.RefExpr.getPointer();
1320 DVar.PrivateCopy = Data.PrivateCopy;
1321 DVar.CKind = Data.Attributes;
1322 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1323 DVar.Modifier = Data.Modifier;
1324 DVar.AppliedToPointee = Data.AppliedToPointee;
1325 return DVar;
1326 }
1327
1328 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1329 // in a Construct, C/C++, implicitly determined, p.1]
1330 // In a parallel or task construct, the data-sharing attributes of these
1331 // variables are determined by the default clause, if present.
1332 switch (Iter->DefaultAttr) {
1333 case DSA_shared:
1334 DVar.CKind = OMPC_shared;
1335 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1336 return DVar;
1337 case DSA_none:
1338 return DVar;
1339 case DSA_firstprivate:
1340 if (VD && VD->getStorageDuration() == SD_Static &&
1341 VD->getDeclContext()->isFileContext()) {
1342 DVar.CKind = OMPC_unknown;
1343 } else {
1344 DVar.CKind = OMPC_firstprivate;
1345 }
1346 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1347 return DVar;
1348 case DSA_private:
1349 // each variable with static storage duration that is declared
1350 // in a namespace or global scope and referenced in the construct,
1351 // and that does not have a predetermined data-sharing attribute
1352 if (VD && VD->getStorageDuration() == SD_Static &&
1353 VD->getDeclContext()->isFileContext()) {
1354 DVar.CKind = OMPC_unknown;
1355 } else {
1356 DVar.CKind = OMPC_private;
1357 }
1358 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1359 return DVar;
1360 case DSA_unspecified:
1361 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1362 // in a Construct, implicitly determined, p.2]
1363 // In a parallel construct, if no default clause is present, these
1364 // variables are shared.
1365 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1366 if ((isOpenMPParallelDirective(DKind: DVar.DKind) &&
1367 !isOpenMPTaskLoopDirective(DKind: DVar.DKind)) ||
1368 isOpenMPTeamsDirective(DKind: DVar.DKind)) {
1369 DVar.CKind = OMPC_shared;
1370 return DVar;
1371 }
1372
1373 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1374 // in a Construct, implicitly determined, p.4]
1375 // In a task construct, if no default clause is present, a variable that in
1376 // the enclosing context is determined to be shared by all implicit tasks
1377 // bound to the current team is shared.
1378 if (isOpenMPTaskingDirective(Kind: DVar.DKind)) {
1379 DSAVarData DVarTemp;
1380 const_iterator I = Iter, E = end();
1381 do {
1382 ++I;
1383 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1384 // Referenced in a Construct, implicitly determined, p.6]
1385 // In a task construct, if no default clause is present, a variable
1386 // whose data-sharing attribute is not determined by the rules above is
1387 // firstprivate.
1388 DVarTemp = getDSA(Iter&: I, D);
1389 if (DVarTemp.CKind != OMPC_shared) {
1390 DVar.RefExpr = nullptr;
1391 DVar.CKind = OMPC_firstprivate;
1392 return DVar;
1393 }
1394 } while (I != E && !isImplicitTaskingRegion(DKind: I->Directive));
1395 DVar.CKind =
1396 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1397 return DVar;
1398 }
1399 }
1400 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1401 // in a Construct, implicitly determined, p.3]
1402 // For constructs other than task, if no default clause is present, these
1403 // variables inherit their data-sharing attributes from the enclosing
1404 // context.
1405 return getDSA(Iter&: ++Iter, D);
1406}
1407
1408const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1409 const Expr *NewDE) {
1410 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1411 D = getCanonicalDecl(D);
1412 SharingMapTy &StackElem = getTopOfStack();
1413 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(Key: D, Args&: NewDE);
1414 if (Inserted) {
1415 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1416 return nullptr;
1417 }
1418 assert(It->second && "Unexpected nullptr expr in the aligned map");
1419 return It->second;
1420}
1421
1422const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1423 const Expr *NewDE) {
1424 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1425 D = getCanonicalDecl(D);
1426 SharingMapTy &StackElem = getTopOfStack();
1427 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(Key: D, Args&: NewDE);
1428 if (Inserted) {
1429 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1430 return nullptr;
1431 }
1432 assert(It->second && "Unexpected nullptr expr in the aligned map");
1433 return It->second;
1434}
1435
1436void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1437 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1438 D = getCanonicalDecl(D);
1439 SharingMapTy &StackElem = getTopOfStack();
1440 StackElem.LCVMap.try_emplace(
1441 Key: D, Args: LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1442}
1443
1444const DSAStackTy::LCDeclInfo
1445DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1446 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1447 D = getCanonicalDecl(D);
1448 const SharingMapTy &StackElem = getTopOfStack();
1449 auto It = StackElem.LCVMap.find(Val: D);
1450 if (It != StackElem.LCVMap.end())
1451 return It->second;
1452 return {0, nullptr};
1453}
1454
1455const DSAStackTy::LCDeclInfo
1456DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1457 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1458 D = getCanonicalDecl(D);
1459 for (unsigned I = Level + 1; I > 0; --I) {
1460 const SharingMapTy &StackElem = getStackElemAtLevel(Level: I - 1);
1461 auto It = StackElem.LCVMap.find(Val: D);
1462 if (It != StackElem.LCVMap.end())
1463 return It->second;
1464 }
1465 return {0, nullptr};
1466}
1467
1468const DSAStackTy::LCDeclInfo
1469DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1470 const SharingMapTy *Parent = getSecondOnStackOrNull();
1471 assert(Parent && "Data-sharing attributes stack is empty");
1472 D = getCanonicalDecl(D);
1473 auto It = Parent->LCVMap.find(Val: D);
1474 if (It != Parent->LCVMap.end())
1475 return It->second;
1476 return {0, nullptr};
1477}
1478
1479const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1480 const SharingMapTy *Parent = getSecondOnStackOrNull();
1481 assert(Parent && "Data-sharing attributes stack is empty");
1482 if (Parent->LCVMap.size() < I)
1483 return nullptr;
1484 for (const auto &Pair : Parent->LCVMap)
1485 if (Pair.second.first == I)
1486 return Pair.first;
1487 return nullptr;
1488}
1489
1490void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1491 DeclRefExpr *PrivateCopy, unsigned Modifier,
1492 bool AppliedToPointee) {
1493 D = getCanonicalDecl(D);
1494 if (A == OMPC_threadprivate) {
1495 DSAInfo &Data = Threadprivates[D];
1496 Data.Attributes = A;
1497 Data.RefExpr.setPointer(E);
1498 Data.PrivateCopy = nullptr;
1499 Data.Modifier = Modifier;
1500 } else {
1501 DSAInfo &Data = getTopOfStack().SharingMap[D];
1502 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1503 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1504 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1505 (isLoopControlVariable(D).first && A == OMPC_private));
1506 Data.Modifier = Modifier;
1507 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1508 Data.RefExpr.setInt(/*IntVal=*/true);
1509 return;
1510 }
1511 const bool IsLastprivate =
1512 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1513 Data.Attributes = A;
1514 Data.RefExpr.setPointerAndInt(PtrVal: E, IntVal: IsLastprivate);
1515 Data.PrivateCopy = PrivateCopy;
1516 Data.AppliedToPointee = AppliedToPointee;
1517 if (PrivateCopy) {
1518 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1519 Data.Modifier = Modifier;
1520 Data.Attributes = A;
1521 Data.RefExpr.setPointerAndInt(PtrVal: PrivateCopy, IntVal: IsLastprivate);
1522 Data.PrivateCopy = nullptr;
1523 Data.AppliedToPointee = AppliedToPointee;
1524 }
1525 }
1526}
1527
1528/// Build a variable declaration for OpenMP loop iteration variable.
1529static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
1530 StringRef Name, const AttrVec *Attrs = nullptr,
1531 DeclRefExpr *OrigRef = nullptr) {
1532 DeclContext *DC = SemaRef.CurContext;
1533 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1534 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(T: Type, Loc);
1535 auto *Decl =
1536 VarDecl::Create(C&: SemaRef.Context, DC, StartLoc: Loc, IdLoc: Loc, Id: II, T: Type, TInfo, S: SC_None);
1537 if (Attrs) {
1538 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1539 I != E; ++I)
1540 Decl->addAttr(A: *I);
1541 }
1542 Decl->setImplicit();
1543 if (OrigRef) {
1544 Decl->addAttr(
1545 A: OMPReferencedVarAttr::CreateImplicit(Ctx&: SemaRef.Context, Ref: OrigRef));
1546 }
1547 return Decl;
1548}
1549
1550static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
1551 SourceLocation Loc,
1552 bool RefersToCapture = false) {
1553 D->setReferenced();
1554 D->markUsed(C&: S.Context);
1555 return DeclRefExpr::Create(Context: S.getASTContext(), QualifierLoc: NestedNameSpecifierLoc(),
1556 TemplateKWLoc: SourceLocation(), D, RefersToEnclosingVariableOrCapture: RefersToCapture, NameLoc: Loc, T: Ty,
1557 VK: VK_LValue);
1558}
1559
1560void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1561 BinaryOperatorKind BOK) {
1562 D = getCanonicalDecl(D);
1563 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1564 assert(
1565 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1566 "Additional reduction info may be specified only for reduction items.");
1567 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1568 assert(ReductionData.ReductionRange.isInvalid() &&
1569 (getTopOfStack().Directive == OMPD_taskgroup ||
1570 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1571 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1572 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1573 "Additional reduction info may be specified only once for reduction "
1574 "items.");
1575 ReductionData.set(BO: BOK, RR: SR);
1576 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1577 if (!TaskgroupReductionRef) {
1578 VarDecl *VD = buildVarDecl(SemaRef, Loc: SR.getBegin(),
1579 Type: SemaRef.Context.VoidPtrTy, Name: ".task_red.");
1580 TaskgroupReductionRef =
1581 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: SemaRef.Context.VoidPtrTy, Loc: SR.getBegin());
1582 }
1583}
1584
1585void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1586 const Expr *ReductionRef) {
1587 D = getCanonicalDecl(D);
1588 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1589 assert(
1590 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1591 "Additional reduction info may be specified only for reduction items.");
1592 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1593 assert(ReductionData.ReductionRange.isInvalid() &&
1594 (getTopOfStack().Directive == OMPD_taskgroup ||
1595 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1596 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1597 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1598 "Additional reduction info may be specified only once for reduction "
1599 "items.");
1600 ReductionData.set(RefExpr: ReductionRef, RR: SR);
1601 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1602 if (!TaskgroupReductionRef) {
1603 VarDecl *VD = buildVarDecl(SemaRef, Loc: SR.getBegin(),
1604 Type: SemaRef.Context.VoidPtrTy, Name: ".task_red.");
1605 TaskgroupReductionRef =
1606 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: SemaRef.Context.VoidPtrTy, Loc: SR.getBegin());
1607 }
1608}
1609
1610const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1611 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1612 Expr *&TaskgroupDescriptor) const {
1613 D = getCanonicalDecl(D);
1614 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1615 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1616 const DSAInfo &Data = I->SharingMap.lookup(Val: D);
1617 if (Data.Attributes != OMPC_reduction ||
1618 Data.Modifier != OMPC_REDUCTION_task)
1619 continue;
1620 const ReductionData &ReductionData = I->ReductionMap.lookup(Val: D);
1621 if (!ReductionData.ReductionOp ||
1622 isa<const Expr *>(Val: ReductionData.ReductionOp))
1623 return DSAVarData();
1624 SR = ReductionData.ReductionRange;
1625 BOK = cast<ReductionData::BOKPtrType>(Val: ReductionData.ReductionOp);
1626 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1627 "expression for the descriptor is not "
1628 "set.");
1629 TaskgroupDescriptor = I->TaskgroupReductionRef;
1630 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1631 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1632 /*AppliedToPointee=*/false);
1633 }
1634 return DSAVarData();
1635}
1636
1637const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1638 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1639 Expr *&TaskgroupDescriptor) const {
1640 D = getCanonicalDecl(D);
1641 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1642 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1643 const DSAInfo &Data = I->SharingMap.lookup(Val: D);
1644 if (Data.Attributes != OMPC_reduction ||
1645 Data.Modifier != OMPC_REDUCTION_task)
1646 continue;
1647 const ReductionData &ReductionData = I->ReductionMap.lookup(Val: D);
1648 if (!ReductionData.ReductionOp ||
1649 !isa<const Expr *>(Val: ReductionData.ReductionOp))
1650 return DSAVarData();
1651 SR = ReductionData.ReductionRange;
1652 ReductionRef = cast<const Expr *>(Val: ReductionData.ReductionOp);
1653 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1654 "expression for the descriptor is not "
1655 "set.");
1656 TaskgroupDescriptor = I->TaskgroupReductionRef;
1657 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1658 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1659 /*AppliedToPointee=*/false);
1660 }
1661 return DSAVarData();
1662}
1663
1664bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1665 D = D->getCanonicalDecl();
1666 for (const_iterator E = end(); I != E; ++I) {
1667 if (isImplicitOrExplicitTaskingRegion(DKind: I->Directive) ||
1668 isOpenMPTargetExecutionDirective(DKind: I->Directive)) {
1669 if (I->CurScope) {
1670 Scope *TopScope = I->CurScope->getParent();
1671 Scope *CurScope = getCurScope();
1672 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1673 CurScope = CurScope->getParent();
1674 return CurScope != TopScope;
1675 }
1676 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1677 if (I->Context == DC)
1678 return true;
1679 return false;
1680 }
1681 }
1682 return false;
1683}
1684
1685static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
1686 bool AcceptIfMutable = true,
1687 bool *IsClassType = nullptr) {
1688 ASTContext &Context = SemaRef.getASTContext();
1689 Type = Type.getNonReferenceType().getCanonicalType();
1690 bool IsConstant = Type.isConstant(Ctx: Context);
1691 Type = Context.getBaseElementType(QT: Type);
1692 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1693 ? Type->getAsCXXRecordDecl()
1694 : nullptr;
1695 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(Val: RD))
1696 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1697 RD = CTD->getTemplatedDecl();
1698 if (IsClassType)
1699 *IsClassType = RD;
1700 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1701 RD->hasDefinition() && RD->hasMutableFields());
1702}
1703
1704static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1705 QualType Type, OpenMPClauseKind CKind,
1706 SourceLocation ELoc,
1707 bool AcceptIfMutable = true,
1708 bool ListItemNotVar = false) {
1709 ASTContext &Context = SemaRef.getASTContext();
1710 bool IsClassType;
1711 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, IsClassType: &IsClassType)) {
1712 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1713 : IsClassType ? diag::err_omp_const_not_mutable_variable
1714 : diag::err_omp_const_variable;
1715 SemaRef.Diag(Loc: ELoc, DiagID: Diag) << getOpenMPClauseNameForDiag(C: CKind);
1716 if (!ListItemNotVar && D) {
1717 const VarDecl *VD = dyn_cast<VarDecl>(Val: D);
1718 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1719 VarDecl::DeclarationOnly;
1720 SemaRef.Diag(Loc: D->getLocation(),
1721 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1722 << D;
1723 }
1724 return true;
1725 }
1726 return false;
1727}
1728
1729const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1730 bool FromParent) {
1731 D = getCanonicalDecl(D);
1732 DSAVarData DVar;
1733
1734 auto *VD = dyn_cast<VarDecl>(Val: D);
1735 auto TI = Threadprivates.find(Val: D);
1736 if (TI != Threadprivates.end()) {
1737 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1738 DVar.CKind = OMPC_threadprivate;
1739 DVar.Modifier = TI->getSecond().Modifier;
1740 return DVar;
1741 }
1742 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1743 DVar.RefExpr = buildDeclRefExpr(
1744 S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1745 Loc: VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1746 DVar.CKind = OMPC_threadprivate;
1747 addDSA(D, E: DVar.RefExpr, A: OMPC_threadprivate);
1748 return DVar;
1749 }
1750 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1751 // in a Construct, C/C++, predetermined, p.1]
1752 // Variables appearing in threadprivate directives are threadprivate.
1753 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1754 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1755 SemaRef.getLangOpts().OpenMPUseTLS &&
1756 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1757 (VD && VD->getStorageClass() == SC_Register &&
1758 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1759 DVar.RefExpr = buildDeclRefExpr(
1760 S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(), Loc: D->getLocation());
1761 DVar.CKind = OMPC_threadprivate;
1762 addDSA(D, E: DVar.RefExpr, A: OMPC_threadprivate);
1763 return DVar;
1764 }
1765 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1766 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1767 !isLoopControlVariable(D).first) {
1768 const_iterator IterTarget =
1769 std::find_if(first: begin(), last: end(), pred: [](const SharingMapTy &Data) {
1770 return isOpenMPTargetExecutionDirective(DKind: Data.Directive);
1771 });
1772 if (IterTarget != end()) {
1773 const_iterator ParentIterTarget = IterTarget + 1;
1774 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1775 if (isOpenMPLocal(D: VD, I: Iter)) {
1776 DVar.RefExpr =
1777 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1778 Loc: D->getLocation());
1779 DVar.CKind = OMPC_threadprivate;
1780 return DVar;
1781 }
1782 }
1783 if (!isClauseParsingMode() || IterTarget != begin()) {
1784 auto DSAIter = IterTarget->SharingMap.find(Val: D);
1785 if (DSAIter != IterTarget->SharingMap.end() &&
1786 isOpenMPPrivate(Kind: DSAIter->getSecond().Attributes)) {
1787 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1788 DVar.CKind = OMPC_threadprivate;
1789 return DVar;
1790 }
1791 const_iterator End = end();
1792 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1793 D, Level: std::distance(first: ParentIterTarget, last: End),
1794 /*OpenMPCaptureLevel=*/0)) {
1795 DVar.RefExpr =
1796 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1797 Loc: IterTarget->ConstructLoc);
1798 DVar.CKind = OMPC_threadprivate;
1799 return DVar;
1800 }
1801 }
1802 }
1803 }
1804
1805 if (isStackEmpty())
1806 // Not in OpenMP execution region and top scope was already checked.
1807 return DVar;
1808
1809 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1810 // in a Construct, C/C++, predetermined, p.4]
1811 // Static data members are shared.
1812 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1813 // in a Construct, C/C++, predetermined, p.7]
1814 // Variables with static storage duration that are declared in a scope
1815 // inside the construct are shared.
1816 if (VD && VD->isStaticDataMember()) {
1817 // Check for explicitly specified attributes.
1818 const_iterator I = begin();
1819 const_iterator EndI = end();
1820 if (FromParent && I != EndI)
1821 ++I;
1822 if (I != EndI) {
1823 auto It = I->SharingMap.find(Val: D);
1824 if (It != I->SharingMap.end()) {
1825 const DSAInfo &Data = It->getSecond();
1826 DVar.RefExpr = Data.RefExpr.getPointer();
1827 DVar.PrivateCopy = Data.PrivateCopy;
1828 DVar.CKind = Data.Attributes;
1829 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1830 DVar.DKind = I->Directive;
1831 DVar.Modifier = Data.Modifier;
1832 DVar.AppliedToPointee = Data.AppliedToPointee;
1833 return DVar;
1834 }
1835 }
1836
1837 DVar.CKind = OMPC_shared;
1838 return DVar;
1839 }
1840
1841 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1842 // The predetermined shared attribute for const-qualified types having no
1843 // mutable members was removed after OpenMP 3.1.
1844 if (SemaRef.LangOpts.OpenMP <= 31) {
1845 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1846 // in a Construct, C/C++, predetermined, p.6]
1847 // Variables with const qualified type having no mutable member are
1848 // shared.
1849 if (isConstNotMutableType(SemaRef, Type: D->getType())) {
1850 // Variables with const-qualified type having no mutable member may be
1851 // listed in a firstprivate clause, even if they are static data members.
1852 DSAVarData DVarTemp = hasInnermostDSA(
1853 D,
1854 CPred: [](OpenMPClauseKind C, bool) {
1855 return C == OMPC_firstprivate || C == OMPC_shared;
1856 },
1857 DPred: MatchesAlways, FromParent);
1858 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1859 return DVarTemp;
1860
1861 DVar.CKind = OMPC_shared;
1862 return DVar;
1863 }
1864 }
1865
1866 // Explicitly specified attributes and local variables with predetermined
1867 // attributes.
1868 const_iterator I = begin();
1869 const_iterator EndI = end();
1870 if (FromParent && I != EndI)
1871 ++I;
1872 if (I == EndI)
1873 return DVar;
1874 auto It = I->SharingMap.find(Val: D);
1875 if (It != I->SharingMap.end()) {
1876 const DSAInfo &Data = It->getSecond();
1877 DVar.RefExpr = Data.RefExpr.getPointer();
1878 DVar.PrivateCopy = Data.PrivateCopy;
1879 DVar.CKind = Data.Attributes;
1880 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1881 DVar.DKind = I->Directive;
1882 DVar.Modifier = Data.Modifier;
1883 DVar.AppliedToPointee = Data.AppliedToPointee;
1884 }
1885
1886 return DVar;
1887}
1888
1889const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1890 bool FromParent) const {
1891 if (isStackEmpty()) {
1892 const_iterator I;
1893 return getDSA(Iter&: I, D);
1894 }
1895 D = getCanonicalDecl(D);
1896 const_iterator StartI = begin();
1897 const_iterator EndI = end();
1898 if (FromParent && StartI != EndI)
1899 ++StartI;
1900 return getDSA(Iter&: StartI, D);
1901}
1902
1903const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1904 unsigned Level) const {
1905 if (getStackSize() <= Level)
1906 return DSAVarData();
1907 D = getCanonicalDecl(D);
1908 const_iterator StartI = std::next(x: begin(), n: getStackSize() - 1 - Level);
1909 return getDSA(Iter&: StartI, D);
1910}
1911
1912const DSAStackTy::DSAVarData
1913DSAStackTy::hasDSA(ValueDecl *D,
1914 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1915 DefaultDataSharingAttributes)>
1916 CPred,
1917 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1918 bool FromParent) const {
1919 if (isStackEmpty())
1920 return {};
1921 D = getCanonicalDecl(D);
1922 const_iterator I = begin();
1923 const_iterator EndI = end();
1924 if (FromParent && I != EndI)
1925 ++I;
1926 for (; I != EndI; ++I) {
1927 if (!DPred(I->Directive) &&
1928 !isImplicitOrExplicitTaskingRegion(DKind: I->Directive))
1929 continue;
1930 const_iterator NewI = I;
1931 DSAVarData DVar = getDSA(Iter&: NewI, D);
1932 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1933 return DVar;
1934 }
1935 return {};
1936}
1937
1938const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1939 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1940 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1941 bool FromParent) const {
1942 if (isStackEmpty())
1943 return {};
1944 D = getCanonicalDecl(D);
1945 const_iterator StartI = begin();
1946 const_iterator EndI = end();
1947 if (FromParent && StartI != EndI)
1948 ++StartI;
1949 if (StartI == EndI || !DPred(StartI->Directive))
1950 return {};
1951 const_iterator NewI = StartI;
1952 DSAVarData DVar = getDSA(Iter&: NewI, D);
1953 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1954 ? DVar
1955 : DSAVarData();
1956}
1957
1958bool DSAStackTy::hasExplicitDSA(
1959 const ValueDecl *D,
1960 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1961 unsigned Level, bool NotLastprivate) const {
1962 if (getStackSize() <= Level)
1963 return false;
1964 D = getCanonicalDecl(D);
1965 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1966 auto I = StackElem.SharingMap.find(Val: D);
1967 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1968 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1969 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1970 return true;
1971 // Check predetermined rules for the loop control variables.
1972 auto LI = StackElem.LCVMap.find(Val: D);
1973 if (LI != StackElem.LCVMap.end())
1974 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1975 return false;
1976}
1977
1978bool DSAStackTy::hasExplicitDirective(
1979 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1980 unsigned Level) const {
1981 if (getStackSize() <= Level)
1982 return false;
1983 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1984 return DPred(StackElem.Directive);
1985}
1986
1987bool DSAStackTy::hasDirective(
1988 const llvm::function_ref<bool(OpenMPDirectiveKind,
1989 const DeclarationNameInfo &, SourceLocation)>
1990 DPred,
1991 bool FromParent) const {
1992 // We look only in the enclosing region.
1993 size_t Skip = FromParent ? 2 : 1;
1994 for (const_iterator I = begin() + std::min(a: Skip, b: getStackSize()), E = end();
1995 I != E; ++I) {
1996 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
1997 return true;
1998 }
1999 return false;
2000}
2001
2002void SemaOpenMP::InitDataSharingAttributesStack() {
2003 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2004}
2005
2006#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2007
2008void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2009
2010void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2011 DSAStack->popFunction(OldFSI);
2012}
2013
2014static bool isOpenMPDeviceDelayedContext(Sema &S) {
2015 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2016 "Expected OpenMP device compilation.");
2017 return !S.OpenMP().isInOpenMPTargetExecutionDirective();
2018}
2019
2020namespace {
2021/// Status of the function emission on the host/device.
2022enum class FunctionEmissionStatus {
2023 Emitted,
2024 Discarded,
2025 Unknown,
2026};
2027} // anonymous namespace
2028
2029SemaBase::SemaDiagnosticBuilder
2030SemaOpenMP::diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID,
2031 const FunctionDecl *FD) {
2032 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2033 "Expected OpenMP device compilation.");
2034
2035 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2036 if (FD) {
2037 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(Decl: FD);
2038 switch (FES) {
2039 case Sema::FunctionEmissionStatus::Emitted:
2040 Kind = SemaDiagnosticBuilder::K_Immediate;
2041 break;
2042 case Sema::FunctionEmissionStatus::Unknown:
2043 // TODO: We should always delay diagnostics here in case a target
2044 // region is in a function we do not emit. However, as the
2045 // current diagnostics are associated with the function containing
2046 // the target region and we do not emit that one, we would miss out
2047 // on diagnostics for the target region itself. We need to anchor
2048 // the diagnostics with the new generated function *or* ensure we
2049 // emit diagnostics associated with the surrounding function.
2050 Kind = isOpenMPDeviceDelayedContext(S&: SemaRef)
2051 ? SemaDiagnosticBuilder::K_Deferred
2052 : SemaDiagnosticBuilder::K_Immediate;
2053 break;
2054 case Sema::FunctionEmissionStatus::TemplateDiscarded:
2055 case Sema::FunctionEmissionStatus::OMPDiscarded:
2056 Kind = SemaDiagnosticBuilder::K_Nop;
2057 break;
2058 case Sema::FunctionEmissionStatus::CUDADiscarded:
2059 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2060 break;
2061 }
2062 }
2063
2064 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2065}
2066
2067SemaBase::SemaDiagnosticBuilder
2068SemaOpenMP::diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID,
2069 const FunctionDecl *FD) {
2070 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2071 "Expected OpenMP host compilation.");
2072
2073 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2074 if (FD) {
2075 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(Decl: FD);
2076 switch (FES) {
2077 case Sema::FunctionEmissionStatus::Emitted:
2078 Kind = SemaDiagnosticBuilder::K_Immediate;
2079 break;
2080 case Sema::FunctionEmissionStatus::Unknown:
2081 Kind = SemaDiagnosticBuilder::K_Deferred;
2082 break;
2083 case Sema::FunctionEmissionStatus::TemplateDiscarded:
2084 case Sema::FunctionEmissionStatus::OMPDiscarded:
2085 case Sema::FunctionEmissionStatus::CUDADiscarded:
2086 Kind = SemaDiagnosticBuilder::K_Nop;
2087 break;
2088 }
2089 }
2090
2091 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2092}
2093
2094static OpenMPDefaultmapClauseKind
2095getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) {
2096 if (LO.OpenMP <= 45) {
2097 if (VD->getType().getNonReferenceType()->isScalarType())
2098 return OMPC_DEFAULTMAP_scalar;
2099 return OMPC_DEFAULTMAP_aggregate;
2100 }
2101 if (VD->getType().getNonReferenceType()->isAnyPointerType())
2102 return OMPC_DEFAULTMAP_pointer;
2103 if (VD->getType().getNonReferenceType()->isScalarType())
2104 return OMPC_DEFAULTMAP_scalar;
2105 return OMPC_DEFAULTMAP_aggregate;
2106}
2107
2108bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2109 unsigned OpenMPCaptureLevel) const {
2110 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2111
2112 ASTContext &Ctx = getASTContext();
2113 bool IsByRef = true;
2114
2115 // Find the directive that is associated with the provided scope.
2116 D = cast<ValueDecl>(Val: D->getCanonicalDecl());
2117 QualType Ty = D->getType();
2118
2119 bool IsVariableUsedInMapClause = false;
2120 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective, Level)) {
2121 // This table summarizes how a given variable should be passed to the device
2122 // given its type and the clauses where it appears. This table is based on
2123 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2124 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2125 //
2126 // =========================================================================
2127 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2128 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2129 // =========================================================================
2130 // | scl | | | | - | | bycopy|
2131 // | scl | | - | x | - | - | bycopy|
2132 // | scl | | x | - | - | - | null |
2133 // | scl | x | | | - | | byref |
2134 // | scl | x | - | x | - | - | bycopy|
2135 // | scl | x | x | - | - | - | null |
2136 // | scl | | - | - | - | x | byref |
2137 // | scl | x | - | - | - | x | byref |
2138 //
2139 // | agg | n.a. | | | - | | byref |
2140 // | agg | n.a. | - | x | - | - | byref |
2141 // | agg | n.a. | x | - | - | - | null |
2142 // | agg | n.a. | - | - | - | x | byref |
2143 // | agg | n.a. | - | - | - | x[] | byref |
2144 //
2145 // | ptr | n.a. | | | - | | bycopy|
2146 // | ptr | n.a. | - | x | - | - | bycopy|
2147 // | ptr | n.a. | x | - | - | - | null |
2148 // | ptr | n.a. | - | - | - | x | byref |
2149 // | ptr | n.a. | - | - | - | x[] | bycopy|
2150 // | ptr | n.a. | - | - | x | | bycopy|
2151 // | ptr | n.a. | - | - | x | x | bycopy|
2152 // | ptr | n.a. | - | - | x | x[] | bycopy|
2153 // =========================================================================
2154 // Legend:
2155 // scl - scalar
2156 // ptr - pointer
2157 // agg - aggregate
2158 // x - applies
2159 // - - invalid in this combination
2160 // [] - mapped with an array section
2161 // byref - should be mapped by reference
2162 // byval - should be mapped by value
2163 // null - initialize a local variable to null on the device
2164 //
2165 // Observations:
2166 // - All scalar declarations that show up in a map clause have to be passed
2167 // by reference, because they may have been mapped in the enclosing data
2168 // environment.
2169 // - If the scalar value does not fit the size of uintptr, it has to be
2170 // passed by reference, regardless the result in the table above.
2171 // - For pointers mapped by value that have either an implicit map or an
2172 // array section, the runtime library may pass the NULL value to the
2173 // device instead of the value passed to it by the compiler.
2174
2175 if (Ty->isReferenceType())
2176 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2177
2178 // Locate map clauses and see if the variable being captured is referred to
2179 // in any of those clauses. Here we only care about variables, not fields,
2180 // because fields are part of aggregates.
2181 bool IsVariableAssociatedWithSection = false;
2182
2183 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2184 VD: D, Level,
2185 Check: [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2186 D](OMPClauseMappableExprCommon::MappableExprComponentListRef
2187 MapExprComponents,
2188 OpenMPClauseKind WhereFoundClauseKind) {
2189 // Both map and has_device_addr clauses information influences how a
2190 // variable is captured. E.g. is_device_ptr does not require changing
2191 // the default behavior.
2192 if (WhereFoundClauseKind != OMPC_map &&
2193 WhereFoundClauseKind != OMPC_has_device_addr)
2194 return false;
2195
2196 auto EI = MapExprComponents.rbegin();
2197 auto EE = MapExprComponents.rend();
2198
2199 assert(EI != EE && "Invalid map expression!");
2200
2201 if (isa<DeclRefExpr>(Val: EI->getAssociatedExpression()))
2202 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2203
2204 ++EI;
2205 if (EI == EE)
2206 return false;
2207 auto Last = std::prev(x: EE);
2208 const auto *UO =
2209 dyn_cast<UnaryOperator>(Val: Last->getAssociatedExpression());
2210 if ((UO && UO->getOpcode() == UO_Deref) ||
2211 isa<ArraySubscriptExpr>(Val: Last->getAssociatedExpression()) ||
2212 isa<ArraySectionExpr>(Val: Last->getAssociatedExpression()) ||
2213 isa<MemberExpr>(Val: EI->getAssociatedExpression()) ||
2214 isa<OMPArrayShapingExpr>(Val: Last->getAssociatedExpression())) {
2215 IsVariableAssociatedWithSection = true;
2216 // There is nothing more we need to know about this variable.
2217 return true;
2218 }
2219
2220 // Keep looking for more map info.
2221 return false;
2222 });
2223
2224 if (IsVariableUsedInMapClause) {
2225 // If variable is identified in a map clause it is always captured by
2226 // reference except if it is a pointer that is dereferenced somehow.
2227 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2228 } else {
2229 // By default, all the data that has a scalar type is mapped by copy
2230 // (except for reduction variables).
2231 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2232 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2233 !Ty->isAnyPointerType()) ||
2234 !Ty->isScalarType() ||
2235 DSAStack->isDefaultmapCapturedByRef(
2236 Level, Kind: getVariableCategoryFromDecl(LO: getLangOpts(), VD: D)) ||
2237 DSAStack->hasExplicitDSA(
2238 D,
2239 CPred: [](OpenMPClauseKind K, bool AppliedToPointee) {
2240 return K == OMPC_reduction && !AppliedToPointee;
2241 },
2242 Level);
2243 }
2244 }
2245
2246 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2247 IsByRef =
2248 ((IsVariableUsedInMapClause &&
2249 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2250 OMPD_target) ||
2251 !(DSAStack->hasExplicitDSA(
2252 D,
2253 CPred: [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2254 return K == OMPC_firstprivate ||
2255 (K == OMPC_reduction && AppliedToPointee);
2256 },
2257 Level, /*NotLastprivate=*/true) ||
2258 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2259 // If the variable is artificial and must be captured by value - try to
2260 // capture by value.
2261 !(isa<OMPCapturedExprDecl>(Val: D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2262 !cast<OMPCapturedExprDecl>(Val: D)->getInit()->isGLValue()) &&
2263 // If the variable is implicitly firstprivate and scalar - capture by
2264 // copy
2265 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2266 DSAStack->getDefaultDSA() == DSA_private) &&
2267 !DSAStack->hasExplicitDSA(
2268 D, CPred: [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2269 Level) &&
2270 !DSAStack->isLoopControlVariable(D, Level).first);
2271 }
2272
2273 // When passing data by copy, we need to make sure it fits the uintptr size
2274 // and alignment, because the runtime library only deals with uintptr types.
2275 // If it does not fit the uintptr size, we need to pass the data by reference
2276 // instead.
2277 if (!IsByRef && (Ctx.getTypeSizeInChars(T: Ty) >
2278 Ctx.getTypeSizeInChars(T: Ctx.getUIntPtrType()) ||
2279 Ctx.getAlignOfGlobalVarInChars(T: Ty, VD: dyn_cast<VarDecl>(Val: D)) >
2280 Ctx.getTypeAlignInChars(T: Ctx.getUIntPtrType()))) {
2281 IsByRef = true;
2282 }
2283
2284 return IsByRef;
2285}
2286
2287unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2288 assert(getLangOpts().OpenMP);
2289 return DSAStack->getNestingLevel();
2290}
2291
2292bool SemaOpenMP::isInOpenMPTaskUntiedContext() const {
2293 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2294 DSAStack->isUntiedRegion();
2295}
2296
2297bool SemaOpenMP::isInOpenMPTargetExecutionDirective() const {
2298 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2299 !DSAStack->isClauseParsingMode()) ||
2300 DSAStack->hasDirective(
2301 DPred: [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2302 SourceLocation) -> bool {
2303 return isOpenMPTargetExecutionDirective(DKind: K);
2304 },
2305 FromParent: false);
2306}
2307
2308bool SemaOpenMP::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2309 // Only rebuild for Field.
2310 if (!isa<FieldDecl>(Val: D))
2311 return false;
2312 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2313 D,
2314 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2315 DefaultDataSharingAttributes DefaultAttr) {
2316 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2317 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2318 },
2319 DPred: [](OpenMPDirectiveKind) { return true; },
2320 DSAStack->isClauseParsingMode());
2321 if (DVarPrivate.CKind != OMPC_unknown)
2322 return true;
2323 return false;
2324}
2325
2326static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
2327 Expr *CaptureExpr, bool WithInit,
2328 DeclContext *CurContext,
2329 bool AsExpression);
2330
2331VarDecl *SemaOpenMP::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2332 unsigned StopAt) {
2333 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2334 D = getCanonicalDecl(D);
2335
2336 auto *VD = dyn_cast<VarDecl>(Val: D);
2337 // Do not capture constexpr variables.
2338 if (VD && VD->isConstexpr())
2339 return nullptr;
2340
2341 // If we want to determine whether the variable should be captured from the
2342 // perspective of the current capturing scope, and we've already left all the
2343 // capturing scopes of the top directive on the stack, check from the
2344 // perspective of its parent directive (if any) instead.
2345 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2346 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2347
2348 // If we are attempting to capture a global variable in a directive with
2349 // 'target' we return true so that this global is also mapped to the device.
2350 //
2351 if (VD && !VD->hasLocalStorage() &&
2352 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2353 SemaRef.getCurLambda())) {
2354 if (isInOpenMPTargetExecutionDirective()) {
2355 DSAStackTy::DSAVarData DVarTop =
2356 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2357 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2358 return VD;
2359 // If the declaration is enclosed in a 'declare target' directive,
2360 // then it should not be captured.
2361 //
2362 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2363 return nullptr;
2364 CapturedRegionScopeInfo *CSI = nullptr;
2365 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2366 RangeOrContainer: llvm::reverse(C&: SemaRef.FunctionScopes),
2367 N: CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2368 : 0)) {
2369 if (!isa<CapturingScopeInfo>(Val: FSI))
2370 return nullptr;
2371 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(Val: FSI))
2372 if (RSI->CapRegionKind == CR_OpenMP) {
2373 CSI = RSI;
2374 break;
2375 }
2376 }
2377 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2378 SmallVector<OpenMPDirectiveKind, 4> Regions;
2379 getOpenMPCaptureRegions(CaptureRegions&: Regions,
2380 DSAStack->getDirective(Level: CSI->OpenMPLevel));
2381 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2382 return VD;
2383 }
2384 if (isInOpenMPDeclareTargetContext()) {
2385 // Try to mark variable as declare target if it is used in capturing
2386 // regions.
2387 if (getLangOpts().OpenMP <= 45 &&
2388 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2389 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: VD);
2390 return nullptr;
2391 }
2392 }
2393
2394 if (CheckScopeInfo) {
2395 bool OpenMPFound = false;
2396 for (unsigned I = StopAt + 1; I > 0; --I) {
2397 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2398 if (!isa<CapturingScopeInfo>(Val: FSI))
2399 return nullptr;
2400 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(Val: FSI))
2401 if (RSI->CapRegionKind == CR_OpenMP) {
2402 OpenMPFound = true;
2403 break;
2404 }
2405 }
2406 if (!OpenMPFound)
2407 return nullptr;
2408 }
2409
2410 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2411 (!DSAStack->isClauseParsingMode() ||
2412 DSAStack->getParentDirective() != OMPD_unknown)) {
2413 auto &&Info = DSAStack->isLoopControlVariable(D);
2414 if (Info.first ||
2415 (VD && VD->hasLocalStorage() &&
2416 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2417 (VD && DSAStack->isForceVarCapturing()))
2418 return VD ? VD : Info.second;
2419 DSAStackTy::DSAVarData DVarTop =
2420 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2421 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(Kind: DVarTop.CKind) &&
2422 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2423 return VD ? VD : cast<VarDecl>(Val: DVarTop.PrivateCopy->getDecl());
2424 // Threadprivate variables must not be captured.
2425 if (isOpenMPThreadPrivate(Kind: DVarTop.CKind))
2426 return nullptr;
2427 // The variable is not private or it is the variable in the directive with
2428 // default(none) clause and not used in any clause.
2429 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2430 D,
2431 CPred: [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2432 return isOpenMPPrivate(Kind: C) && !AppliedToPointee;
2433 },
2434 DPred: [](OpenMPDirectiveKind) { return true; },
2435 DSAStack->isClauseParsingMode());
2436 // Global shared must not be captured.
2437 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2438 ((DSAStack->getDefaultDSA() != DSA_none &&
2439 DSAStack->getDefaultDSA() != DSA_private &&
2440 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2441 DVarTop.CKind == OMPC_shared))
2442 return nullptr;
2443 auto *FD = dyn_cast<FieldDecl>(Val: D);
2444 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2445 !DVarPrivate.PrivateCopy) {
2446 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2447 D,
2448 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2449 DefaultDataSharingAttributes DefaultAttr) {
2450 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2451 (DefaultAttr == DSA_firstprivate ||
2452 DefaultAttr == DSA_private);
2453 },
2454 DPred: [](OpenMPDirectiveKind) { return true; },
2455 DSAStack->isClauseParsingMode());
2456 if (DVarPrivate.CKind == OMPC_unknown)
2457 return nullptr;
2458
2459 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2460 if (VD)
2461 return VD;
2462 if (SemaRef.getCurrentThisType().isNull())
2463 return nullptr;
2464 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(Loc: SourceLocation(),
2465 Type: SemaRef.getCurrentThisType(),
2466 /*IsImplicit=*/true);
2467 const CXXScopeSpec CS = CXXScopeSpec();
2468 Expr *ME = SemaRef.BuildMemberExpr(
2469 Base: ThisExpr, /*IsArrow=*/true, OpLoc: SourceLocation(),
2470 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: FD,
2471 FoundDecl: DeclAccessPair::make(D: FD, AS: FD->getAccess()),
2472 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(), Ty: FD->getType(),
2473 VK: VK_LValue, OK: OK_Ordinary);
2474 OMPCapturedExprDecl *CD = buildCaptureDecl(
2475 S&: SemaRef, Id: FD->getIdentifier(), CaptureExpr: ME, WithInit: DVarPrivate.CKind != OMPC_private,
2476 CurContext: SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2477 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2478 S&: SemaRef, D: CD, Ty: CD->getType().getNonReferenceType(), Loc: SourceLocation());
2479 VD = cast<VarDecl>(Val: VDPrivateRefExpr->getDecl());
2480 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2481 return VD;
2482 }
2483 if (DVarPrivate.CKind != OMPC_unknown ||
2484 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2485 DSAStack->getDefaultDSA() == DSA_private ||
2486 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2487 return VD ? VD : cast<VarDecl>(Val: DVarPrivate.PrivateCopy->getDecl());
2488 }
2489 return nullptr;
2490}
2491
2492void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2493 unsigned Level) const {
2494 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2495}
2496
2497void SemaOpenMP::startOpenMPLoop() {
2498 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2499 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2500 DSAStack->loopInit();
2501}
2502
2503void SemaOpenMP::startOpenMPCXXRangeFor() {
2504 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2505 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2506 DSAStack->resetPossibleLoopCounter();
2507 DSAStack->loopStart();
2508 }
2509}
2510
2511OpenMPClauseKind SemaOpenMP::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2512 unsigned CapLevel) const {
2513 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2514 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2515 (!DSAStack->isClauseParsingMode() ||
2516 DSAStack->getParentDirective() != OMPD_unknown)) {
2517 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2518 D,
2519 CPred: [](OpenMPClauseKind C, bool AppliedToPointee,
2520 DefaultDataSharingAttributes DefaultAttr) {
2521 return isOpenMPPrivate(Kind: C) && !AppliedToPointee &&
2522 DefaultAttr == DSA_private;
2523 },
2524 DPred: [](OpenMPDirectiveKind) { return true; },
2525 DSAStack->isClauseParsingMode());
2526 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(Val: D) &&
2527 DSAStack->isImplicitDefaultFirstprivateFD(VD: cast<VarDecl>(Val: D)) &&
2528 !DSAStack->isLoopControlVariable(D).first)
2529 return OMPC_private;
2530 }
2531 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTaskingDirective, Level)) {
2532 bool IsTriviallyCopyable =
2533 D->getType().getNonReferenceType().isTriviallyCopyableType(
2534 Context: getASTContext()) &&
2535 !D->getType()
2536 .getNonReferenceType()
2537 .getCanonicalType()
2538 ->getAsCXXRecordDecl();
2539 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2540 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2541 getOpenMPCaptureRegions(CaptureRegions, DKind);
2542 if (isOpenMPTaskingDirective(Kind: CaptureRegions[CapLevel]) &&
2543 (IsTriviallyCopyable ||
2544 !isOpenMPTaskLoopDirective(DKind: CaptureRegions[CapLevel]))) {
2545 if (DSAStack->hasExplicitDSA(
2546 D,
2547 CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2548 Level, /*NotLastprivate=*/true))
2549 return OMPC_firstprivate;
2550 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2551 if (DVar.CKind != OMPC_shared &&
2552 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2553 DSAStack->addImplicitTaskFirstprivate(Level, D);
2554 return OMPC_firstprivate;
2555 }
2556 }
2557 }
2558 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2559 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2560 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2561 DSAStack->resetPossibleLoopCounter(D);
2562 DSAStack->loopStart();
2563 return OMPC_private;
2564 }
2565 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2566 DSAStack->isLoopControlVariable(D).first) &&
2567 !DSAStack->hasExplicitDSA(
2568 D, CPred: [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2569 Level) &&
2570 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2571 return OMPC_private;
2572 }
2573 if (const auto *VD = dyn_cast<VarDecl>(Val: D)) {
2574 if (DSAStack->isThreadPrivate(D: const_cast<VarDecl *>(VD)) &&
2575 DSAStack->isForceVarCapturing() &&
2576 !DSAStack->hasExplicitDSA(
2577 D, CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2578 Level))
2579 return OMPC_private;
2580 }
2581 // User-defined allocators are private since they must be defined in the
2582 // context of target region.
2583 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective, Level) &&
2584 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2585 u: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2586 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2587 return OMPC_private;
2588 return (DSAStack->hasExplicitDSA(
2589 D, CPred: [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2590 Level) ||
2591 (DSAStack->isClauseParsingMode() &&
2592 DSAStack->getClauseParsingMode() == OMPC_private) ||
2593 // Consider taskgroup reduction descriptor variable a private
2594 // to avoid possible capture in the region.
2595 (DSAStack->hasExplicitDirective(
2596 DPred: [](OpenMPDirectiveKind K) {
2597 return K == OMPD_taskgroup ||
2598 ((isOpenMPParallelDirective(DKind: K) ||
2599 isOpenMPWorksharingDirective(DKind: K)) &&
2600 !isOpenMPSimdDirective(DKind: K));
2601 },
2602 Level) &&
2603 DSAStack->isTaskgroupReductionRef(VD: D, Level)))
2604 ? OMPC_private
2605 : OMPC_unknown;
2606}
2607
2608void SemaOpenMP::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2609 unsigned Level) {
2610 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2611 D = getCanonicalDecl(D);
2612 OpenMPClauseKind OMPC = OMPC_unknown;
2613 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2614 const unsigned NewLevel = I - 1;
2615 if (DSAStack->hasExplicitDSA(
2616 D,
2617 CPred: [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2618 if (isOpenMPPrivate(Kind: K) && !AppliedToPointee) {
2619 OMPC = K;
2620 return true;
2621 }
2622 return false;
2623 },
2624 Level: NewLevel))
2625 break;
2626 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2627 VD: D, Level: NewLevel,
2628 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2629 OpenMPClauseKind) { return true; })) {
2630 OMPC = OMPC_map;
2631 break;
2632 }
2633 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective,
2634 Level: NewLevel)) {
2635 OMPC = OMPC_map;
2636 if (DSAStack->mustBeFirstprivateAtLevel(
2637 Level: NewLevel, Kind: getVariableCategoryFromDecl(LO: getLangOpts(), VD: D)))
2638 OMPC = OMPC_firstprivate;
2639 break;
2640 }
2641 }
2642 if (OMPC != OMPC_unknown)
2643 FD->addAttr(
2644 A: OMPCaptureKindAttr::CreateImplicit(Ctx&: getASTContext(), CaptureKindVal: unsigned(OMPC)));
2645}
2646
2647bool SemaOpenMP::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2648 unsigned CaptureLevel) const {
2649 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2650 // Return true if the current level is no longer enclosed in a target region.
2651
2652 SmallVector<OpenMPDirectiveKind, 4> Regions;
2653 getOpenMPCaptureRegions(CaptureRegions&: Regions, DSAStack->getDirective(Level));
2654 const auto *VD = dyn_cast<VarDecl>(Val: D);
2655 return VD && !VD->hasLocalStorage() &&
2656 DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective,
2657 Level) &&
2658 Regions[CaptureLevel] != OMPD_task;
2659}
2660
2661bool SemaOpenMP::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2662 unsigned CaptureLevel) const {
2663 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2664 // Return true if the current level is no longer enclosed in a target region.
2665
2666 if (const auto *VD = dyn_cast<VarDecl>(Val: D)) {
2667 if (!VD->hasLocalStorage()) {
2668 if (isInOpenMPTargetExecutionDirective())
2669 return true;
2670 DSAStackTy::DSAVarData TopDVar =
2671 DSAStack->getTopDSA(D, /*FromParent=*/false);
2672 unsigned NumLevels =
2673 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2674 if (Level == 0)
2675 // non-file scope static variable with default(firstprivate)
2676 // should be global captured.
2677 return (NumLevels == CaptureLevel + 1 &&
2678 (TopDVar.CKind != OMPC_shared ||
2679 DSAStack->getDefaultDSA() == DSA_firstprivate));
2680 do {
2681 --Level;
2682 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2683 if (DVar.CKind != OMPC_shared)
2684 return true;
2685 } while (Level > 0);
2686 }
2687 }
2688 return true;
2689}
2690
2691void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2692
2693void SemaOpenMP::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2694 OMPTraitInfo &TI) {
2695 OMPDeclareVariantScopes.push_back(Elt: OMPDeclareVariantScope(TI));
2696}
2697
2698void SemaOpenMP::ActOnOpenMPEndDeclareVariant() {
2699 assert(isInOpenMPDeclareVariantScope() &&
2700 "Not in OpenMP declare variant scope!");
2701
2702 OMPDeclareVariantScopes.pop_back();
2703}
2704
2705void SemaOpenMP::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2706 const FunctionDecl *Callee,
2707 SourceLocation Loc) {
2708 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2709 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2710 OMPDeclareTargetDeclAttr::getDeviceType(VD: Caller->getMostRecentDecl());
2711 // Ignore host functions during device analysis.
2712 if (getLangOpts().OpenMPIsTargetDevice &&
2713 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2714 return;
2715 // Ignore nohost functions during host analysis.
2716 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2717 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2718 return;
2719 const FunctionDecl *FD = Callee->getMostRecentDecl();
2720 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(VD: FD);
2721 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2722 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2723 // Diagnose host function called during device codegen.
2724 StringRef HostDevTy =
2725 getOpenMPSimpleClauseTypeName(Kind: OMPC_device_type, Type: OMPC_DEVICE_TYPE_host);
2726 Diag(Loc, DiagID: diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2727 Diag(Loc: *OMPDeclareTargetDeclAttr::getLocation(VD: FD),
2728 DiagID: diag::note_omp_marked_device_type_here)
2729 << HostDevTy;
2730 return;
2731 }
2732 if (!getLangOpts().OpenMPIsTargetDevice &&
2733 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2734 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2735 // In OpenMP 5.2 or later, if the function has a host variant then allow
2736 // that to be called instead
2737 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2738 for (OMPDeclareVariantAttr *A :
2739 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2740 auto *DeclRefVariant = cast<DeclRefExpr>(Val: A->getVariantFuncRef());
2741 auto *VariantFD = cast<FunctionDecl>(Val: DeclRefVariant->getDecl());
2742 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2743 OMPDeclareTargetDeclAttr::getDeviceType(
2744 VD: VariantFD->getMostRecentDecl());
2745 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2746 return true;
2747 }
2748 return false;
2749 };
2750 if (getLangOpts().OpenMP >= 52 &&
2751 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2752 return;
2753 // Diagnose nohost function called during host codegen.
2754 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2755 Kind: OMPC_device_type, Type: OMPC_DEVICE_TYPE_nohost);
2756 Diag(Loc, DiagID: diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2757 Diag(Loc: *OMPDeclareTargetDeclAttr::getLocation(VD: FD),
2758 DiagID: diag::note_omp_marked_device_type_here)
2759 << NoHostDevTy;
2760 }
2761}
2762
2763void SemaOpenMP::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2764 const DeclarationNameInfo &DirName,
2765 Scope *CurScope, SourceLocation Loc) {
2766 DSAStack->push(DKind, DirName, CurScope, Loc);
2767 SemaRef.PushExpressionEvaluationContext(
2768 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
2769}
2770
2771void SemaOpenMP::StartOpenMPClause(OpenMPClauseKind K) {
2772 DSAStack->setClauseParsingMode(K);
2773}
2774
2775void SemaOpenMP::EndOpenMPClause() {
2776 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2777 SemaRef.CleanupVarDeclMarking();
2778}
2779
2780static std::pair<ValueDecl *, bool>
2781getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2782 SourceRange &ERange, bool AllowArraySection = false,
2783 StringRef DiagType = "");
2784
2785/// Check consistency of the reduction clauses.
2786static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2787 ArrayRef<OMPClause *> Clauses) {
2788 bool InscanFound = false;
2789 SourceLocation InscanLoc;
2790 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2791 // A reduction clause without the inscan reduction-modifier may not appear on
2792 // a construct on which a reduction clause with the inscan reduction-modifier
2793 // appears.
2794 for (OMPClause *C : Clauses) {
2795 if (C->getClauseKind() != OMPC_reduction)
2796 continue;
2797 auto *RC = cast<OMPReductionClause>(Val: C);
2798 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2799 InscanFound = true;
2800 InscanLoc = RC->getModifierLoc();
2801 continue;
2802 }
2803 if (RC->getModifier() == OMPC_REDUCTION_task) {
2804 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2805 // A reduction clause with the task reduction-modifier may only appear on
2806 // a parallel construct, a worksharing construct or a combined or
2807 // composite construct for which any of the aforementioned constructs is a
2808 // constituent construct and simd or loop are not constituent constructs.
2809 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2810 if (!(isOpenMPParallelDirective(DKind: CurDir) ||
2811 isOpenMPWorksharingDirective(DKind: CurDir)) ||
2812 isOpenMPSimdDirective(DKind: CurDir))
2813 S.Diag(Loc: RC->getModifierLoc(),
2814 DiagID: diag::err_omp_reduction_task_not_parallel_or_worksharing);
2815 continue;
2816 }
2817 }
2818 if (InscanFound) {
2819 for (OMPClause *C : Clauses) {
2820 if (C->getClauseKind() != OMPC_reduction)
2821 continue;
2822 auto *RC = cast<OMPReductionClause>(Val: C);
2823 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2824 S.Diag(Loc: RC->getModifier() == OMPC_REDUCTION_unknown
2825 ? RC->getBeginLoc()
2826 : RC->getModifierLoc(),
2827 DiagID: diag::err_omp_inscan_reduction_expected);
2828 S.Diag(Loc: InscanLoc, DiagID: diag::note_omp_previous_inscan_reduction);
2829 continue;
2830 }
2831 for (Expr *Ref : RC->varlist()) {
2832 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2833 SourceLocation ELoc;
2834 SourceRange ERange;
2835 Expr *SimpleRefExpr = Ref;
2836 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
2837 /*AllowArraySection=*/true);
2838 ValueDecl *D = Res.first;
2839 if (!D)
2840 continue;
2841 if (!Stack->isUsedInScanDirective(D: getCanonicalDecl(D))) {
2842 S.Diag(Loc: Ref->getExprLoc(),
2843 DiagID: diag::err_omp_reduction_not_inclusive_exclusive)
2844 << Ref->getSourceRange();
2845 }
2846 }
2847 }
2848 }
2849}
2850
2851static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2852 ArrayRef<OMPClause *> Clauses);
2853static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2854 bool WithInit);
2855
2856static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2857 const ValueDecl *D,
2858 const DSAStackTy::DSAVarData &DVar,
2859 bool IsLoopIterVar = false);
2860
2861void SemaOpenMP::EndOpenMPDSABlock(Stmt *CurDirective) {
2862 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2863 // A variable of class type (or array thereof) that appears in a lastprivate
2864 // clause requires an accessible, unambiguous default constructor for the
2865 // class type, unless the list item is also specified in a firstprivate
2866 // clause.
2867
2868 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2869 SmallVector<Expr *, 8> PrivateCopies;
2870 for (Expr *DE : Clause->varlist()) {
2871 if (DE->isValueDependent() || DE->isTypeDependent()) {
2872 PrivateCopies.push_back(Elt: nullptr);
2873 continue;
2874 }
2875 auto *DRE = cast<DeclRefExpr>(Val: DE->IgnoreParens());
2876 auto *VD = cast<VarDecl>(Val: DRE->getDecl());
2877 QualType Type = VD->getType().getNonReferenceType();
2878 const DSAStackTy::DSAVarData DVar =
2879 DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
2880 if (DVar.CKind != OMPC_lastprivate) {
2881 // The variable is also a firstprivate, so initialization sequence
2882 // for private copy is generated already.
2883 PrivateCopies.push_back(Elt: nullptr);
2884 continue;
2885 }
2886 // Generate helper private variable and initialize it with the
2887 // default value. The address of the original variable is replaced
2888 // by the address of the new private variable in CodeGen. This new
2889 // variable is not added to IdResolver, so the code in the OpenMP
2890 // region uses original variable for proper diagnostics.
2891 VarDecl *VDPrivate = buildVarDecl(
2892 SemaRef, Loc: DE->getExprLoc(), Type: Type.getUnqualifiedType(), Name: VD->getName(),
2893 Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr, OrigRef: DRE);
2894 SemaRef.ActOnUninitializedDecl(dcl: VDPrivate);
2895 if (VDPrivate->isInvalidDecl()) {
2896 PrivateCopies.push_back(Elt: nullptr);
2897 continue;
2898 }
2899 PrivateCopies.push_back(Elt: buildDeclRefExpr(
2900 S&: SemaRef, D: VDPrivate, Ty: DE->getType(), Loc: DE->getExprLoc()));
2901 }
2902 Clause->setPrivateCopies(PrivateCopies);
2903 };
2904
2905 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
2906 // Finalize nontemporal clause by handling private copies, if any.
2907 SmallVector<Expr *, 8> PrivateRefs;
2908 for (Expr *RefExpr : Clause->varlist()) {
2909 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2910 SourceLocation ELoc;
2911 SourceRange ERange;
2912 Expr *SimpleRefExpr = RefExpr;
2913 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
2914 if (Res.second)
2915 // It will be analyzed later.
2916 PrivateRefs.push_back(Elt: RefExpr);
2917 ValueDecl *D = Res.first;
2918 if (!D)
2919 continue;
2920
2921 const DSAStackTy::DSAVarData DVar =
2922 DSAStack->getTopDSA(D, /*FromParent=*/false);
2923 PrivateRefs.push_back(Elt: DVar.PrivateCopy ? DVar.PrivateCopy
2924 : SimpleRefExpr);
2925 }
2926 Clause->setPrivateRefs(PrivateRefs);
2927 };
2928
2929 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
2930 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2931 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2932 auto *DRE = dyn_cast<DeclRefExpr>(Val: D.Allocator->IgnoreParenImpCasts());
2933 if (!DRE)
2934 continue;
2935 ValueDecl *VD = DRE->getDecl();
2936 if (!VD || !isa<VarDecl>(Val: VD))
2937 continue;
2938 DSAStackTy::DSAVarData DVar =
2939 DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
2940 // OpenMP [2.12.5, target Construct]
2941 // Memory allocators that appear in a uses_allocators clause cannot
2942 // appear in other data-sharing attribute clauses or data-mapping
2943 // attribute clauses in the same construct.
2944 Expr *MapExpr = nullptr;
2945 if (DVar.RefExpr ||
2946 DSAStack->checkMappableExprComponentListsForDecl(
2947 VD, /*CurrentRegionOnly=*/true,
2948 Check: [VD, &MapExpr](
2949 OMPClauseMappableExprCommon::MappableExprComponentListRef
2950 MapExprComponents,
2951 OpenMPClauseKind C) {
2952 auto MI = MapExprComponents.rbegin();
2953 auto ME = MapExprComponents.rend();
2954 if (MI != ME &&
2955 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2956 VD->getCanonicalDecl()) {
2957 MapExpr = MI->getAssociatedExpression();
2958 return true;
2959 }
2960 return false;
2961 })) {
2962 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::err_omp_allocator_used_in_clauses)
2963 << D.Allocator->getSourceRange();
2964 if (DVar.RefExpr)
2965 reportOriginalDsa(SemaRef, DSAStack, D: VD, DVar);
2966 else
2967 Diag(Loc: MapExpr->getExprLoc(), DiagID: diag::note_used_here)
2968 << MapExpr->getSourceRange();
2969 }
2970 }
2971 };
2972
2973 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(Val: CurDirective)) {
2974 for (OMPClause *C : D->clauses()) {
2975 if (auto *Clause = dyn_cast<OMPLastprivateClause>(Val: C)) {
2976 FinalizeLastprivate(Clause);
2977 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(Val: C)) {
2978 FinalizeNontemporal(Clause);
2979 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(Val: C)) {
2980 FinalizeAllocators(Clause);
2981 }
2982 }
2983 // Check allocate clauses.
2984 if (!SemaRef.CurContext->isDependentContext())
2985 checkAllocateClauses(S&: SemaRef, DSAStack, Clauses: D->clauses());
2986 checkReductionClauses(S&: SemaRef, DSAStack, Clauses: D->clauses());
2987 }
2988
2989 DSAStack->pop();
2990 SemaRef.DiscardCleanupsInEvaluationContext();
2991 SemaRef.PopExpressionEvaluationContext();
2992}
2993
2994static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
2995 Expr *NumIterations, Sema &SemaRef,
2996 Scope *S, DSAStackTy *Stack);
2997
2998static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
2999 OMPLoopBasedDirective::HelperExprs &B,
3000 DSAStackTy *Stack) {
3001 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3002 "loop exprs were not built");
3003
3004 if (SemaRef.CurContext->isDependentContext())
3005 return false;
3006
3007 // Finalize the clauses that need pre-built expressions for CodeGen.
3008 for (OMPClause *C : Clauses) {
3009 auto *LC = dyn_cast<OMPLinearClause>(Val: C);
3010 if (!LC)
3011 continue;
3012 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
3013 NumIterations: B.NumIterations, SemaRef,
3014 S: SemaRef.getCurScope(), Stack))
3015 return true;
3016 }
3017
3018 return false;
3019}
3020
3021namespace {
3022
3023class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3024private:
3025 Sema &SemaRef;
3026
3027public:
3028 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3029 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3030 NamedDecl *ND = Candidate.getCorrectionDecl();
3031 if (const auto *VD = dyn_cast_or_null<VarDecl>(Val: ND)) {
3032 return VD->hasGlobalStorage() &&
3033 SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(),
3034 S: SemaRef.getCurScope());
3035 }
3036 return false;
3037 }
3038
3039 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3040 return std::make_unique<VarDeclFilterCCC>(args&: *this);
3041 }
3042};
3043
3044class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3045private:
3046 Sema &SemaRef;
3047
3048public:
3049 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3050 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3051 NamedDecl *ND = Candidate.getCorrectionDecl();
3052 if (ND && ((isa<VarDecl>(Val: ND) && ND->getKind() == Decl::Var) ||
3053 isa<FunctionDecl>(Val: ND))) {
3054 return SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(),
3055 S: SemaRef.getCurScope());
3056 }
3057 return false;
3058 }
3059
3060 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3061 return std::make_unique<VarOrFuncDeclFilterCCC>(args&: *this);
3062 }
3063};
3064
3065} // namespace
3066
3067ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope,
3068 CXXScopeSpec &ScopeSpec,
3069 const DeclarationNameInfo &Id,
3070 OpenMPDirectiveKind Kind) {
3071 ASTContext &Context = getASTContext();
3072 unsigned OMPVersion = getLangOpts().OpenMP;
3073 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
3074 SemaRef.LookupParsedName(R&: Lookup, S: CurScope, SS: &ScopeSpec,
3075 /*ObjectType=*/QualType(),
3076 /*AllowBuiltinCreation=*/true);
3077
3078 if (Lookup.isAmbiguous())
3079 return ExprError();
3080
3081 VarDecl *VD;
3082 if (!Lookup.isSingleResult()) {
3083 VarDeclFilterCCC CCC(SemaRef);
3084 if (TypoCorrection Corrected =
3085 SemaRef.CorrectTypo(Typo: Id, LookupKind: Sema::LookupOrdinaryName, S: CurScope, SS: nullptr,
3086 CCC, Mode: CorrectTypoKind::ErrorRecovery)) {
3087 SemaRef.diagnoseTypo(
3088 Correction: Corrected,
3089 TypoDiag: SemaRef.PDiag(DiagID: Lookup.empty() ? diag::err_undeclared_var_use_suggest
3090 : diag::err_omp_expected_var_arg_suggest)
3091 << Id.getName());
3092 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3093 } else {
3094 Diag(Loc: Id.getLoc(), DiagID: Lookup.empty() ? diag::err_undeclared_var_use
3095 : diag::err_omp_expected_var_arg)
3096 << Id.getName();
3097 return ExprError();
3098 }
3099 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3100 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_expected_var_arg) << Id.getName();
3101 Diag(Loc: Lookup.getFoundDecl()->getLocation(), DiagID: diag::note_declared_at);
3102 return ExprError();
3103 }
3104 Lookup.suppressDiagnostics();
3105
3106 // OpenMP [2.9.2, Syntax, C/C++]
3107 // Variables must be file-scope, namespace-scope, or static block-scope.
3108 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3109 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_global_var_arg)
3110 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << !VD->isStaticLocal();
3111 bool IsDecl =
3112 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3113 Diag(Loc: VD->getLocation(),
3114 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3115 << VD;
3116 return ExprError();
3117 }
3118
3119 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3120 NamedDecl *ND = CanonicalVD;
3121 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3122 // A threadprivate directive for file-scope variables must appear outside
3123 // any definition or declaration.
3124 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3125 !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3126 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3127 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3128 bool IsDecl =
3129 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3130 Diag(Loc: VD->getLocation(),
3131 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3132 << VD;
3133 return ExprError();
3134 }
3135 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3136 // A threadprivate directive for static class member variables must appear
3137 // in the class definition, in the same scope in which the member
3138 // variables are declared.
3139 if (CanonicalVD->isStaticDataMember() &&
3140 !CanonicalVD->getDeclContext()->Equals(DC: SemaRef.getCurLexicalContext())) {
3141 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3142 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3143 bool IsDecl =
3144 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3145 Diag(Loc: VD->getLocation(),
3146 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3147 << VD;
3148 return ExprError();
3149 }
3150 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3151 // A threadprivate directive for namespace-scope variables must appear
3152 // outside any definition or declaration other than the namespace
3153 // definition itself.
3154 if (CanonicalVD->getDeclContext()->isNamespace() &&
3155 (!SemaRef.getCurLexicalContext()->isFileContext() ||
3156 !SemaRef.getCurLexicalContext()->Encloses(
3157 DC: CanonicalVD->getDeclContext()))) {
3158 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3159 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3160 bool IsDecl =
3161 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3162 Diag(Loc: VD->getLocation(),
3163 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3164 << VD;
3165 return ExprError();
3166 }
3167 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3168 // A threadprivate directive for static block-scope variables must appear
3169 // in the scope of the variable and not in a nested scope.
3170 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3171 !SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(), S: CurScope)) {
3172 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_scope)
3173 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3174 bool IsDecl =
3175 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3176 Diag(Loc: VD->getLocation(),
3177 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3178 << VD;
3179 return ExprError();
3180 }
3181
3182 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3183 // A threadprivate directive must lexically precede all references to any
3184 // of the variables in its list.
3185 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3186 !DSAStack->isThreadPrivate(D: VD)) {
3187 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_var_used)
3188 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion) << VD;
3189 return ExprError();
3190 }
3191
3192 QualType ExprType = VD->getType().getNonReferenceType();
3193 return DeclRefExpr::Create(Context, QualifierLoc: NestedNameSpecifierLoc(),
3194 TemplateKWLoc: SourceLocation(), D: VD,
3195 /*RefersToEnclosingVariableOrCapture=*/false,
3196 NameLoc: Id.getLoc(), T: ExprType, VK: VK_LValue);
3197}
3198
3199SemaOpenMP::DeclGroupPtrTy
3200SemaOpenMP::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3201 ArrayRef<Expr *> VarList) {
3202 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3203 SemaRef.CurContext->addDecl(D);
3204 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3205 }
3206 return nullptr;
3207}
3208
3209namespace {
3210class LocalVarRefChecker final
3211 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3212 Sema &SemaRef;
3213
3214public:
3215 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3216 if (const auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
3217 if (VD->hasLocalStorage()) {
3218 SemaRef.Diag(Loc: E->getBeginLoc(),
3219 DiagID: diag::err_omp_local_var_in_threadprivate_init)
3220 << E->getSourceRange();
3221 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::note_defined_here)
3222 << VD << VD->getSourceRange();
3223 return true;
3224 }
3225 }
3226 return false;
3227 }
3228 bool VisitStmt(const Stmt *S) {
3229 for (const Stmt *Child : S->children()) {
3230 if (Child && Visit(S: Child))
3231 return true;
3232 }
3233 return false;
3234 }
3235 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3236};
3237} // namespace
3238
3239OMPThreadPrivateDecl *
3240SemaOpenMP::CheckOMPThreadPrivateDecl(SourceLocation Loc,
3241 ArrayRef<Expr *> VarList) {
3242 ASTContext &Context = getASTContext();
3243 SmallVector<Expr *, 8> Vars;
3244 for (Expr *RefExpr : VarList) {
3245 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3246 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3247 SourceLocation ILoc = DE->getExprLoc();
3248
3249 // Mark variable as used.
3250 VD->setReferenced();
3251 VD->markUsed(C&: Context);
3252
3253 QualType QType = VD->getType();
3254 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3255 // It will be analyzed later.
3256 Vars.push_back(Elt: DE);
3257 continue;
3258 }
3259
3260 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3261 // A threadprivate variable must not have an incomplete type.
3262 if (SemaRef.RequireCompleteType(
3263 Loc: ILoc, T: VD->getType(), DiagID: diag::err_omp_threadprivate_incomplete_type)) {
3264 continue;
3265 }
3266
3267 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3268 // A threadprivate variable must not have a reference type.
3269 if (VD->getType()->isReferenceType()) {
3270 unsigned OMPVersion = getLangOpts().OpenMP;
3271 Diag(Loc: ILoc, DiagID: diag::err_omp_ref_type_arg)
3272 << getOpenMPDirectiveName(D: OMPD_threadprivate, Ver: OMPVersion)
3273 << VD->getType();
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 continue;
3280 }
3281
3282 // Check if this is a TLS variable. If TLS is not being supported, produce
3283 // the corresponding diagnostic.
3284 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3285 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3286 getLangOpts().OpenMPUseTLS &&
3287 getASTContext().getTargetInfo().isTLSSupported())) ||
3288 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3289 !VD->isLocalVarDecl())) {
3290 Diag(Loc: ILoc, DiagID: diag::err_omp_var_thread_local)
3291 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3292 bool IsDecl =
3293 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3294 Diag(Loc: VD->getLocation(),
3295 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3296 << VD;
3297 continue;
3298 }
3299
3300 // Check if initial value of threadprivate variable reference variable with
3301 // local storage (it is not supported by runtime).
3302 if (const Expr *Init = VD->getAnyInitializer()) {
3303 LocalVarRefChecker Checker(SemaRef);
3304 if (Checker.Visit(S: Init))
3305 continue;
3306 }
3307
3308 Vars.push_back(Elt: RefExpr);
3309 DSAStack->addDSA(D: VD, E: DE, A: OMPC_threadprivate);
3310 VD->addAttr(A: OMPThreadPrivateDeclAttr::CreateImplicit(
3311 Ctx&: Context, Range: SourceRange(Loc, Loc)));
3312 if (ASTMutationListener *ML = Context.getASTMutationListener())
3313 ML->DeclarationMarkedOpenMPThreadPrivate(D: VD);
3314 }
3315 OMPThreadPrivateDecl *D = nullptr;
3316 if (!Vars.empty()) {
3317 D = OMPThreadPrivateDecl::Create(C&: Context, DC: SemaRef.getCurLexicalContext(),
3318 L: Loc, VL: Vars);
3319 D->setAccess(AS_public);
3320 }
3321 return D;
3322}
3323
3324static OMPAllocateDeclAttr::AllocatorTypeTy
3325getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3326 if (!Allocator)
3327 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3328 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3329 Allocator->isInstantiationDependent() ||
3330 Allocator->containsUnexpandedParameterPack())
3331 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3332 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3333 llvm::FoldingSetNodeID AEId;
3334 const Expr *AE = Allocator->IgnoreParenImpCasts();
3335 AE->IgnoreImpCasts()->Profile(ID&: AEId, Context: S.getASTContext(), /*Canonical=*/true);
3336 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3337 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3338 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3339 llvm::FoldingSetNodeID DAEId;
3340 DefAllocator->IgnoreImpCasts()->Profile(ID&: DAEId, Context: S.getASTContext(),
3341 /*Canonical=*/true);
3342 if (AEId == DAEId) {
3343 AllocatorKindRes = AllocatorKind;
3344 break;
3345 }
3346 }
3347 return AllocatorKindRes;
3348}
3349
3350static bool checkPreviousOMPAllocateAttribute(
3351 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3352 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3353 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3354 return false;
3355 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3356 Expr *PrevAllocator = A->getAllocator();
3357 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3358 getAllocatorKind(S, Stack, Allocator: PrevAllocator);
3359 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3360 if (AllocatorsMatch &&
3361 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3362 Allocator && PrevAllocator) {
3363 const Expr *AE = Allocator->IgnoreParenImpCasts();
3364 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3365 llvm::FoldingSetNodeID AEId, PAEId;
3366 AE->Profile(ID&: AEId, Context: S.Context, /*Canonical=*/true);
3367 PAE->Profile(ID&: PAEId, Context: S.Context, /*Canonical=*/true);
3368 AllocatorsMatch = AEId == PAEId;
3369 }
3370 if (!AllocatorsMatch) {
3371 SmallString<256> AllocatorBuffer;
3372 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3373 if (Allocator)
3374 Allocator->printPretty(OS&: AllocatorStream, Helper: nullptr, Policy: S.getPrintingPolicy());
3375 SmallString<256> PrevAllocatorBuffer;
3376 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3377 if (PrevAllocator)
3378 PrevAllocator->printPretty(OS&: PrevAllocatorStream, Helper: nullptr,
3379 Policy: S.getPrintingPolicy());
3380
3381 SourceLocation AllocatorLoc =
3382 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3383 SourceRange AllocatorRange =
3384 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3385 SourceLocation PrevAllocatorLoc =
3386 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3387 SourceRange PrevAllocatorRange =
3388 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3389 S.Diag(Loc: AllocatorLoc, DiagID: diag::warn_omp_used_different_allocator)
3390 << (Allocator ? 1 : 0) << AllocatorStream.str()
3391 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3392 << AllocatorRange;
3393 S.Diag(Loc: PrevAllocatorLoc, DiagID: diag::note_omp_previous_allocator)
3394 << PrevAllocatorRange;
3395 return true;
3396 }
3397 return false;
3398}
3399
3400static void
3401applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3402 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3403 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3404 if (VD->hasAttr<OMPAllocateDeclAttr>())
3405 return;
3406 if (Alignment &&
3407 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3408 Alignment->isInstantiationDependent() ||
3409 Alignment->containsUnexpandedParameterPack()))
3410 // Apply later when we have a usable value.
3411 return;
3412 if (Allocator &&
3413 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3414 Allocator->isInstantiationDependent() ||
3415 Allocator->containsUnexpandedParameterPack()))
3416 return;
3417 auto *A = OMPAllocateDeclAttr::CreateImplicit(Ctx&: S.Context, AllocatorType: AllocatorKind,
3418 Allocator, Alignment, Range: SR);
3419 VD->addAttr(A);
3420 if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3421 ML->DeclarationMarkedOpenMPAllocate(D: VD, A);
3422}
3423
3424SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPAllocateDirective(
3425 SourceLocation Loc, ArrayRef<Expr *> VarList, ArrayRef<OMPClause *> Clauses,
3426 DeclContext *Owner) {
3427 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3428 Expr *Alignment = nullptr;
3429 Expr *Allocator = nullptr;
3430 if (Clauses.empty()) {
3431 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3432 // allocate directives that appear in a target region must specify an
3433 // allocator clause unless a requires directive with the dynamic_allocators
3434 // clause is present in the same compilation unit.
3435 if (getLangOpts().OpenMPIsTargetDevice &&
3436 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3437 SemaRef.targetDiag(Loc, DiagID: diag::err_expected_allocator_clause);
3438 } else {
3439 for (const OMPClause *C : Clauses)
3440 if (const auto *AC = dyn_cast<OMPAllocatorClause>(Val: C))
3441 Allocator = AC->getAllocator();
3442 else if (const auto *AC = dyn_cast<OMPAlignClause>(Val: C))
3443 Alignment = AC->getAlignment();
3444 else
3445 llvm_unreachable("Unexpected clause on allocate directive");
3446 }
3447 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3448 getAllocatorKind(S&: SemaRef, DSAStack, Allocator);
3449 SmallVector<Expr *, 8> Vars;
3450 for (Expr *RefExpr : VarList) {
3451 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3452 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3453
3454 // Check if this is a TLS variable or global register.
3455 if (VD->getTLSKind() != VarDecl::TLS_None ||
3456 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3457 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3458 !VD->isLocalVarDecl()))
3459 continue;
3460
3461 // If the used several times in the allocate directive, the same allocator
3462 // must be used.
3463 if (checkPreviousOMPAllocateAttribute(S&: SemaRef, DSAStack, RefExpr, VD,
3464 AllocatorKind, Allocator))
3465 continue;
3466
3467 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3468 // If a list item has a static storage type, the allocator expression in the
3469 // allocator clause must be a constant expression that evaluates to one of
3470 // the predefined memory allocator values.
3471 if (Allocator && VD->hasGlobalStorage()) {
3472 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3473 Diag(Loc: Allocator->getExprLoc(),
3474 DiagID: diag::err_omp_expected_predefined_allocator)
3475 << Allocator->getSourceRange();
3476 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3477 VarDecl::DeclarationOnly;
3478 Diag(Loc: VD->getLocation(),
3479 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3480 << VD;
3481 continue;
3482 }
3483 }
3484
3485 Vars.push_back(Elt: RefExpr);
3486 applyOMPAllocateAttribute(S&: SemaRef, VD, AllocatorKind, Allocator, Alignment,
3487 SR: DE->getSourceRange());
3488 }
3489 if (Vars.empty())
3490 return nullptr;
3491 if (!Owner)
3492 Owner = SemaRef.getCurLexicalContext();
3493 auto *D = OMPAllocateDecl::Create(C&: getASTContext(), DC: Owner, L: Loc, VL: Vars, CL: Clauses);
3494 D->setAccess(AS_public);
3495 Owner->addDecl(D);
3496 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3497}
3498
3499SemaOpenMP::DeclGroupPtrTy
3500SemaOpenMP::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3501 ArrayRef<OMPClause *> ClauseList) {
3502 OMPRequiresDecl *D = nullptr;
3503 if (!SemaRef.CurContext->isFileContext()) {
3504 Diag(Loc, DiagID: diag::err_omp_invalid_scope) << "requires";
3505 } else {
3506 D = CheckOMPRequiresDecl(Loc, Clauses: ClauseList);
3507 if (D) {
3508 SemaRef.CurContext->addDecl(D);
3509 DSAStack->addRequiresDecl(RD: D);
3510 }
3511 }
3512 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3513}
3514
3515void SemaOpenMP::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3516 OpenMPDirectiveKind DKind,
3517 ArrayRef<std::string> Assumptions,
3518 bool SkippedClauses) {
3519 if (!SkippedClauses && Assumptions.empty()) {
3520 unsigned OMPVersion = getLangOpts().OpenMP;
3521 Diag(Loc, DiagID: diag::err_omp_no_clause_for_directive)
3522 << llvm::omp::getAllAssumeClauseOptions()
3523 << llvm::omp::getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
3524 }
3525
3526 auto *AA =
3527 OMPAssumeAttr::Create(Ctx&: getASTContext(), Assumption: llvm::join(R&: Assumptions, Separator: ","), Range: Loc);
3528 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3529 OMPAssumeScoped.push_back(Elt: AA);
3530 return;
3531 }
3532
3533 // Global assumes without assumption clauses are ignored.
3534 if (Assumptions.empty())
3535 return;
3536
3537 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3538 "Unexpected omp assumption directive!");
3539 OMPAssumeGlobal.push_back(Elt: AA);
3540
3541 // The OMPAssumeGlobal scope above will take care of new declarations but
3542 // we also want to apply the assumption to existing ones, e.g., to
3543 // declarations in included headers. To this end, we traverse all existing
3544 // declaration contexts and annotate function declarations here.
3545 SmallVector<DeclContext *, 8> DeclContexts;
3546 auto *Ctx = SemaRef.CurContext;
3547 while (Ctx->getLexicalParent())
3548 Ctx = Ctx->getLexicalParent();
3549 DeclContexts.push_back(Elt: Ctx);
3550 while (!DeclContexts.empty()) {
3551 DeclContext *DC = DeclContexts.pop_back_val();
3552 for (auto *SubDC : DC->decls()) {
3553 if (SubDC->isInvalidDecl())
3554 continue;
3555 if (auto *CTD = dyn_cast<ClassTemplateDecl>(Val: SubDC)) {
3556 DeclContexts.push_back(Elt: CTD->getTemplatedDecl());
3557 llvm::append_range(C&: DeclContexts, R: CTD->specializations());
3558 continue;
3559 }
3560 if (auto *DC = dyn_cast<DeclContext>(Val: SubDC))
3561 DeclContexts.push_back(Elt: DC);
3562 if (auto *F = dyn_cast<FunctionDecl>(Val: SubDC)) {
3563 F->addAttr(A: AA);
3564 continue;
3565 }
3566 }
3567 }
3568}
3569
3570void SemaOpenMP::ActOnOpenMPEndAssumesDirective() {
3571 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3572 OMPAssumeScoped.pop_back();
3573}
3574
3575StmtResult SemaOpenMP::ActOnOpenMPAssumeDirective(ArrayRef<OMPClause *> Clauses,
3576 Stmt *AStmt,
3577 SourceLocation StartLoc,
3578 SourceLocation EndLoc) {
3579 if (!AStmt)
3580 return StmtError();
3581
3582 return OMPAssumeDirective::Create(Ctx: getASTContext(), StartLoc, EndLoc, Clauses,
3583 AStmt);
3584}
3585
3586OMPRequiresDecl *
3587SemaOpenMP::CheckOMPRequiresDecl(SourceLocation Loc,
3588 ArrayRef<OMPClause *> ClauseList) {
3589 /// For target specific clauses, the requires directive cannot be
3590 /// specified after the handling of any of the target regions in the
3591 /// current compilation unit.
3592 ArrayRef<SourceLocation> TargetLocations =
3593 DSAStack->getEncounteredTargetLocs();
3594 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3595 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3596 for (const OMPClause *CNew : ClauseList) {
3597 // Check if any of the requires clauses affect target regions.
3598 if (isa<OMPUnifiedSharedMemoryClause>(Val: CNew) ||
3599 isa<OMPUnifiedAddressClause>(Val: CNew) ||
3600 isa<OMPReverseOffloadClause>(Val: CNew) ||
3601 isa<OMPDynamicAllocatorsClause>(Val: CNew)) {
3602 Diag(Loc, DiagID: diag::err_omp_directive_before_requires)
3603 << "target" << getOpenMPClauseNameForDiag(C: CNew->getClauseKind());
3604 for (SourceLocation TargetLoc : TargetLocations) {
3605 Diag(Loc: TargetLoc, DiagID: diag::note_omp_requires_encountered_directive)
3606 << "target";
3607 }
3608 } else if (!AtomicLoc.isInvalid() &&
3609 isa<OMPAtomicDefaultMemOrderClause>(Val: CNew)) {
3610 Diag(Loc, DiagID: diag::err_omp_directive_before_requires)
3611 << "atomic" << getOpenMPClauseNameForDiag(C: CNew->getClauseKind());
3612 Diag(Loc: AtomicLoc, DiagID: diag::note_omp_requires_encountered_directive)
3613 << "atomic";
3614 }
3615 }
3616 }
3617
3618 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3619 return OMPRequiresDecl::Create(
3620 C&: getASTContext(), DC: SemaRef.getCurLexicalContext(), L: Loc, CL: ClauseList);
3621 return nullptr;
3622}
3623
3624static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3625 const ValueDecl *D,
3626 const DSAStackTy::DSAVarData &DVar,
3627 bool IsLoopIterVar) {
3628 if (DVar.RefExpr) {
3629 SemaRef.Diag(Loc: DVar.RefExpr->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
3630 << getOpenMPClauseNameForDiag(C: DVar.CKind);
3631 return;
3632 }
3633 enum {
3634 PDSA_StaticMemberShared,
3635 PDSA_StaticLocalVarShared,
3636 PDSA_LoopIterVarPrivate,
3637 PDSA_LoopIterVarLinear,
3638 PDSA_LoopIterVarLastprivate,
3639 PDSA_ConstVarShared,
3640 PDSA_GlobalVarShared,
3641 PDSA_TaskVarFirstprivate,
3642 PDSA_LocalVarPrivate,
3643 PDSA_Implicit
3644 } Reason = PDSA_Implicit;
3645 bool ReportHint = false;
3646 auto ReportLoc = D->getLocation();
3647 auto *VD = dyn_cast<VarDecl>(Val: D);
3648 if (IsLoopIterVar) {
3649 if (DVar.CKind == OMPC_private)
3650 Reason = PDSA_LoopIterVarPrivate;
3651 else if (DVar.CKind == OMPC_lastprivate)
3652 Reason = PDSA_LoopIterVarLastprivate;
3653 else
3654 Reason = PDSA_LoopIterVarLinear;
3655 } else if (isOpenMPTaskingDirective(Kind: DVar.DKind) &&
3656 DVar.CKind == OMPC_firstprivate) {
3657 Reason = PDSA_TaskVarFirstprivate;
3658 ReportLoc = DVar.ImplicitDSALoc;
3659 } else if (VD && VD->isStaticLocal())
3660 Reason = PDSA_StaticLocalVarShared;
3661 else if (VD && VD->isStaticDataMember())
3662 Reason = PDSA_StaticMemberShared;
3663 else if (VD && VD->isFileVarDecl())
3664 Reason = PDSA_GlobalVarShared;
3665 else if (D->getType().isConstant(Ctx: SemaRef.getASTContext()))
3666 Reason = PDSA_ConstVarShared;
3667 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3668 ReportHint = true;
3669 Reason = PDSA_LocalVarPrivate;
3670 }
3671 if (Reason != PDSA_Implicit) {
3672 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
3673 SemaRef.Diag(Loc: ReportLoc, DiagID: diag::note_omp_predetermined_dsa)
3674 << Reason << ReportHint
3675 << getOpenMPDirectiveName(D: Stack->getCurrentDirective(), Ver: OMPVersion);
3676 } else if (DVar.ImplicitDSALoc.isValid()) {
3677 SemaRef.Diag(Loc: DVar.ImplicitDSALoc, DiagID: diag::note_omp_implicit_dsa)
3678 << getOpenMPClauseNameForDiag(C: DVar.CKind);
3679 }
3680}
3681
3682static OpenMPMapClauseKind
3683getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
3684 bool IsAggregateOrDeclareTarget) {
3685 OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
3686 switch (M) {
3687 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3688 Kind = OMPC_MAP_alloc;
3689 break;
3690 case OMPC_DEFAULTMAP_MODIFIER_to:
3691 Kind = OMPC_MAP_to;
3692 break;
3693 case OMPC_DEFAULTMAP_MODIFIER_from:
3694 Kind = OMPC_MAP_from;
3695 break;
3696 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3697 Kind = OMPC_MAP_tofrom;
3698 break;
3699 case OMPC_DEFAULTMAP_MODIFIER_present:
3700 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3701 // If implicit-behavior is present, each variable referenced in the
3702 // construct in the category specified by variable-category is treated as if
3703 // it had been listed in a map clause with the map-type of alloc and
3704 // map-type-modifier of present.
3705 Kind = OMPC_MAP_alloc;
3706 break;
3707 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3708 case OMPC_DEFAULTMAP_MODIFIER_last:
3709 llvm_unreachable("Unexpected defaultmap implicit behavior");
3710 case OMPC_DEFAULTMAP_MODIFIER_none:
3711 case OMPC_DEFAULTMAP_MODIFIER_default:
3712 case OMPC_DEFAULTMAP_MODIFIER_unknown:
3713 // IsAggregateOrDeclareTarget could be true if:
3714 // 1. the implicit behavior for aggregate is tofrom
3715 // 2. it's a declare target link
3716 if (IsAggregateOrDeclareTarget) {
3717 Kind = OMPC_MAP_tofrom;
3718 break;
3719 }
3720 llvm_unreachable("Unexpected defaultmap implicit behavior");
3721 }
3722 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3723 return Kind;
3724}
3725
3726namespace {
3727struct VariableImplicitInfo {
3728 static const unsigned MapKindNum = OMPC_MAP_unknown;
3729 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3730
3731 llvm::SetVector<Expr *> Privates;
3732 llvm::SetVector<Expr *> Firstprivates;
3733 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3734 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3735 MapModifiers[DefaultmapKindNum];
3736};
3737
3738class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3739 DSAStackTy *Stack;
3740 Sema &SemaRef;
3741 OpenMPDirectiveKind DKind = OMPD_unknown;
3742 bool ErrorFound = false;
3743 bool TryCaptureCXXThisMembers = false;
3744 CapturedStmt *CS = nullptr;
3745
3746 VariableImplicitInfo ImpInfo;
3747 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3748 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3749
3750 void VisitSubCaptures(OMPExecutableDirective *S) {
3751 // Check implicitly captured variables.
3752 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3753 return;
3754 if (S->getDirectiveKind() == OMPD_atomic ||
3755 S->getDirectiveKind() == OMPD_critical ||
3756 S->getDirectiveKind() == OMPD_section ||
3757 S->getDirectiveKind() == OMPD_master ||
3758 S->getDirectiveKind() == OMPD_masked ||
3759 S->getDirectiveKind() == OMPD_scope ||
3760 S->getDirectiveKind() == OMPD_assume ||
3761 isOpenMPLoopTransformationDirective(DKind: S->getDirectiveKind())) {
3762 Visit(S: S->getAssociatedStmt());
3763 return;
3764 }
3765 visitSubCaptures(S: S->getInnermostCapturedStmt());
3766 // Try to capture inner this->member references to generate correct mappings
3767 // and diagnostics.
3768 if (TryCaptureCXXThisMembers ||
3769 (isOpenMPTargetExecutionDirective(DKind) &&
3770 llvm::any_of(Range: S->getInnermostCapturedStmt()->captures(),
3771 P: [](const CapturedStmt::Capture &C) {
3772 return C.capturesThis();
3773 }))) {
3774 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3775 TryCaptureCXXThisMembers = true;
3776 Visit(S: S->getInnermostCapturedStmt()->getCapturedStmt());
3777 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3778 }
3779 // In tasks firstprivates are not captured anymore, need to analyze them
3780 // explicitly.
3781 if (isOpenMPTaskingDirective(Kind: S->getDirectiveKind()) &&
3782 !isOpenMPTaskLoopDirective(DKind: S->getDirectiveKind())) {
3783 for (OMPClause *C : S->clauses())
3784 if (auto *FC = dyn_cast<OMPFirstprivateClause>(Val: C)) {
3785 for (Expr *Ref : FC->varlist())
3786 Visit(S: Ref);
3787 }
3788 }
3789 }
3790
3791public:
3792 void VisitDeclRefExpr(DeclRefExpr *E) {
3793 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3794 E->isValueDependent() || E->containsUnexpandedParameterPack() ||
3795 E->isInstantiationDependent() ||
3796 E->isNonOdrUse() == clang::NOUR_Unevaluated)
3797 return;
3798 if (auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
3799 // Check the datasharing rules for the expressions in the clauses.
3800 if (!CS || (isa<OMPCapturedExprDecl>(Val: VD) && !CS->capturesVariable(Var: VD) &&
3801 !Stack->getTopDSA(D: VD, /*FromParent=*/false).RefExpr &&
3802 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3803 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: VD))
3804 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3805 Visit(S: CED->getInit());
3806 return;
3807 }
3808 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(Val: VD))
3809 // Do not analyze internal variables and do not enclose them into
3810 // implicit clauses.
3811 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3812 return;
3813 VD = VD->getCanonicalDecl();
3814 // Skip internally declared variables.
3815 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(Var: VD) &&
3816 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3817 !Stack->isImplicitTaskFirstprivate(D: VD))
3818 return;
3819 // Skip allocators in uses_allocators clauses.
3820 if (Stack->isUsesAllocatorsDecl(D: VD))
3821 return;
3822
3823 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D: VD, /*FromParent=*/false);
3824 // Check if the variable has explicit DSA set and stop analysis if it so.
3825 if (DVar.RefExpr || !ImplicitDeclarations.insert(V: VD).second)
3826 return;
3827
3828 // Skip internally declared static variables.
3829 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3830 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3831 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(Var: VD) &&
3832 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3833 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3834 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3835 !Stack->isImplicitTaskFirstprivate(D: VD))
3836 return;
3837
3838 SourceLocation ELoc = E->getExprLoc();
3839 // The default(none) clause requires that each variable that is referenced
3840 // in the construct, and does not have a predetermined data-sharing
3841 // attribute, must have its data-sharing attribute explicitly determined
3842 // by being listed in a data-sharing attribute clause.
3843 if (DVar.CKind == OMPC_unknown &&
3844 (Stack->getDefaultDSA() == DSA_none ||
3845 Stack->getDefaultDSA() == DSA_private ||
3846 Stack->getDefaultDSA() == DSA_firstprivate) &&
3847 isImplicitOrExplicitTaskingRegion(DKind) &&
3848 VarsWithInheritedDSA.count(Val: VD) == 0) {
3849 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3850 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3851 Stack->getDefaultDSA() == DSA_private)) {
3852 DSAStackTy::DSAVarData DVar =
3853 Stack->getImplicitDSA(D: VD, /*FromParent=*/false);
3854 InheritedDSA = DVar.CKind == OMPC_unknown;
3855 }
3856 if (InheritedDSA)
3857 VarsWithInheritedDSA[VD] = E;
3858 if (Stack->getDefaultDSA() == DSA_none)
3859 return;
3860 }
3861
3862 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3863 // If implicit-behavior is none, each variable referenced in the
3864 // construct that does not have a predetermined data-sharing attribute
3865 // and does not appear in a to or link clause on a declare target
3866 // directive must be listed in a data-mapping attribute clause, a
3867 // data-sharing attribute clause (including a data-sharing attribute
3868 // clause on a combined construct where target. is one of the
3869 // constituent constructs), or an is_device_ptr clause.
3870 OpenMPDefaultmapClauseKind ClauseKind =
3871 getVariableCategoryFromDecl(LO: SemaRef.getLangOpts(), VD);
3872 if (SemaRef.getLangOpts().OpenMP >= 50) {
3873 bool IsModifierNone = Stack->getDefaultmapModifier(Kind: ClauseKind) ==
3874 OMPC_DEFAULTMAP_MODIFIER_none;
3875 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3876 VarsWithInheritedDSA.count(Val: VD) == 0 && !Res) {
3877 // Only check for data-mapping attribute and is_device_ptr here
3878 // since we have already make sure that the declaration does not
3879 // have a data-sharing attribute above
3880 if (!Stack->checkMappableExprComponentListsForDecl(
3881 VD, /*CurrentRegionOnly=*/true,
3882 Check: [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
3883 MapExprComponents,
3884 OpenMPClauseKind) {
3885 auto MI = MapExprComponents.rbegin();
3886 auto ME = MapExprComponents.rend();
3887 return MI != ME && MI->getAssociatedDeclaration() == VD;
3888 })) {
3889 VarsWithInheritedDSA[VD] = E;
3890 return;
3891 }
3892 }
3893 }
3894 if (SemaRef.getLangOpts().OpenMP > 50) {
3895 bool IsModifierPresent = Stack->getDefaultmapModifier(Kind: ClauseKind) ==
3896 OMPC_DEFAULTMAP_MODIFIER_present;
3897 if (IsModifierPresent) {
3898 if (!llvm::is_contained(Range&: ImpInfo.MapModifiers[ClauseKind],
3899 Element: OMPC_MAP_MODIFIER_present)) {
3900 ImpInfo.MapModifiers[ClauseKind].push_back(
3901 Elt: OMPC_MAP_MODIFIER_present);
3902 }
3903 }
3904 }
3905
3906 if (isOpenMPTargetExecutionDirective(DKind) &&
3907 !Stack->isLoopControlVariable(D: VD).first) {
3908 if (!Stack->checkMappableExprComponentListsForDecl(
3909 VD, /*CurrentRegionOnly=*/true,
3910 Check: [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
3911 StackComponents,
3912 OpenMPClauseKind) {
3913 if (SemaRef.LangOpts.OpenMP >= 50)
3914 return !StackComponents.empty();
3915 // Variable is used if it has been marked as an array, array
3916 // section, array shaping or the variable itself.
3917 return StackComponents.size() == 1 ||
3918 llvm::all_of(
3919 Range: llvm::drop_begin(RangeOrContainer: llvm::reverse(C&: StackComponents)),
3920 P: [](const OMPClauseMappableExprCommon::
3921 MappableComponent &MC) {
3922 return MC.getAssociatedDeclaration() ==
3923 nullptr &&
3924 (isa<ArraySectionExpr>(
3925 Val: MC.getAssociatedExpression()) ||
3926 isa<OMPArrayShapingExpr>(
3927 Val: MC.getAssociatedExpression()) ||
3928 isa<ArraySubscriptExpr>(
3929 Val: MC.getAssociatedExpression()));
3930 });
3931 })) {
3932 bool IsFirstprivate = false;
3933 // By default lambdas are captured as firstprivates.
3934 if (const auto *RD =
3935 VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
3936 IsFirstprivate = RD->isLambda();
3937 IsFirstprivate =
3938 IsFirstprivate || (Stack->mustBeFirstprivate(Kind: ClauseKind) && !Res);
3939 if (IsFirstprivate) {
3940 ImpInfo.Firstprivates.insert(X: E);
3941 } else {
3942 OpenMPDefaultmapClauseModifier M =
3943 Stack->getDefaultmapModifier(Kind: ClauseKind);
3944 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3945 M, IsAggregateOrDeclareTarget: ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3946 ImpInfo.Mappings[ClauseKind][Kind].insert(X: E);
3947 }
3948 return;
3949 }
3950 }
3951
3952 // OpenMP [2.9.3.6, Restrictions, p.2]
3953 // A list item that appears in a reduction clause of the innermost
3954 // enclosing worksharing or parallel construct may not be accessed in an
3955 // explicit task.
3956 DVar = Stack->hasInnermostDSA(
3957 D: VD,
3958 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
3959 return C == OMPC_reduction && !AppliedToPointee;
3960 },
3961 DPred: [](OpenMPDirectiveKind K) {
3962 return isOpenMPParallelDirective(DKind: K) ||
3963 isOpenMPWorksharingDirective(DKind: K) || isOpenMPTeamsDirective(DKind: K);
3964 },
3965 /*FromParent=*/true);
3966 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind == OMPC_reduction) {
3967 ErrorFound = true;
3968 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_in_task);
3969 reportOriginalDsa(SemaRef, Stack, D: VD, DVar);
3970 return;
3971 }
3972
3973 // Define implicit data-sharing attributes for task.
3974 DVar = Stack->getImplicitDSA(D: VD, /*FromParent=*/false);
3975 if (((isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind != OMPC_shared) ||
3976 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3977 DVar.CKind == OMPC_firstprivate) ||
3978 (Stack->getDefaultDSA() == DSA_private &&
3979 DVar.CKind == OMPC_private)) &&
3980 !DVar.RefExpr)) &&
3981 !Stack->isLoopControlVariable(D: VD).first) {
3982 if (Stack->getDefaultDSA() == DSA_private)
3983 ImpInfo.Privates.insert(X: E);
3984 else
3985 ImpInfo.Firstprivates.insert(X: E);
3986 return;
3987 }
3988
3989 // Store implicitly used globals with declare target link for parent
3990 // target.
3991 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3992 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3993 Stack->addToParentTargetRegionLinkGlobals(E);
3994 return;
3995 }
3996 }
3997 }
3998 void VisitMemberExpr(MemberExpr *E) {
3999 if (E->isTypeDependent() || E->isValueDependent() ||
4000 E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
4001 return;
4002 auto *FD = dyn_cast<FieldDecl>(Val: E->getMemberDecl());
4003 if (auto *TE = dyn_cast<CXXThisExpr>(Val: E->getBase()->IgnoreParenCasts())) {
4004 if (!FD)
4005 return;
4006 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D: FD, /*FromParent=*/false);
4007 // Check if the variable has explicit DSA set and stop analysis if it
4008 // so.
4009 if (DVar.RefExpr || !ImplicitDeclarations.insert(V: FD).second)
4010 return;
4011
4012 if (isOpenMPTargetExecutionDirective(DKind) &&
4013 !Stack->isLoopControlVariable(D: FD).first &&
4014 !Stack->checkMappableExprComponentListsForDecl(
4015 VD: FD, /*CurrentRegionOnly=*/true,
4016 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef
4017 StackComponents,
4018 OpenMPClauseKind) {
4019 return isa<CXXThisExpr>(
4020 Val: cast<MemberExpr>(
4021 Val: StackComponents.back().getAssociatedExpression())
4022 ->getBase()
4023 ->IgnoreParens());
4024 })) {
4025 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4026 // A bit-field cannot appear in a map clause.
4027 //
4028 if (FD->isBitField())
4029 return;
4030
4031 // Check to see if the member expression is referencing a class that
4032 // has already been explicitly mapped
4033 if (Stack->isClassPreviouslyMapped(QT: TE->getType()))
4034 return;
4035
4036 OpenMPDefaultmapClauseModifier Modifier =
4037 Stack->getDefaultmapModifier(Kind: OMPC_DEFAULTMAP_aggregate);
4038 OpenMPDefaultmapClauseKind ClauseKind =
4039 getVariableCategoryFromDecl(LO: SemaRef.getLangOpts(), VD: FD);
4040 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
4041 M: Modifier, /*IsAggregateOrDeclareTarget=*/true);
4042 ImpInfo.Mappings[ClauseKind][Kind].insert(X: E);
4043 return;
4044 }
4045
4046 SourceLocation ELoc = E->getExprLoc();
4047 // OpenMP [2.9.3.6, Restrictions, p.2]
4048 // A list item that appears in a reduction clause of the innermost
4049 // enclosing worksharing or parallel construct may not be accessed in
4050 // an explicit task.
4051 DVar = Stack->hasInnermostDSA(
4052 D: FD,
4053 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
4054 return C == OMPC_reduction && !AppliedToPointee;
4055 },
4056 DPred: [](OpenMPDirectiveKind K) {
4057 return isOpenMPParallelDirective(DKind: K) ||
4058 isOpenMPWorksharingDirective(DKind: K) || isOpenMPTeamsDirective(DKind: K);
4059 },
4060 /*FromParent=*/true);
4061 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind == OMPC_reduction) {
4062 ErrorFound = true;
4063 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_in_task);
4064 reportOriginalDsa(SemaRef, Stack, D: FD, DVar);
4065 return;
4066 }
4067
4068 // Define implicit data-sharing attributes for task.
4069 DVar = Stack->getImplicitDSA(D: FD, /*FromParent=*/false);
4070 if (isOpenMPTaskingDirective(Kind: DKind) && DVar.CKind != OMPC_shared &&
4071 !Stack->isLoopControlVariable(D: FD).first) {
4072 // Check if there is a captured expression for the current field in the
4073 // region. Do not mark it as firstprivate unless there is no captured
4074 // expression.
4075 // TODO: try to make it firstprivate.
4076 if (DVar.CKind != OMPC_unknown)
4077 ImpInfo.Firstprivates.insert(X: E);
4078 }
4079 return;
4080 }
4081 if (isOpenMPTargetExecutionDirective(DKind)) {
4082 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
4083 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, CKind: OMPC_map,
4084 DKind, /*NoDiagnose=*/true))
4085 return;
4086 const auto *VD = cast<ValueDecl>(
4087 Val: CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4088 if (!Stack->checkMappableExprComponentListsForDecl(
4089 VD, /*CurrentRegionOnly=*/true,
4090 Check: [&CurComponents](
4091 OMPClauseMappableExprCommon::MappableExprComponentListRef
4092 StackComponents,
4093 OpenMPClauseKind) {
4094 auto CCI = CurComponents.rbegin();
4095 auto CCE = CurComponents.rend();
4096 for (const auto &SC : llvm::reverse(C&: StackComponents)) {
4097 // Do both expressions have the same kind?
4098 if (CCI->getAssociatedExpression()->getStmtClass() !=
4099 SC.getAssociatedExpression()->getStmtClass())
4100 if (!((isa<ArraySectionExpr>(
4101 Val: SC.getAssociatedExpression()) ||
4102 isa<OMPArrayShapingExpr>(
4103 Val: SC.getAssociatedExpression())) &&
4104 isa<ArraySubscriptExpr>(
4105 Val: CCI->getAssociatedExpression())))
4106 return false;
4107
4108 const Decl *CCD = CCI->getAssociatedDeclaration();
4109 const Decl *SCD = SC.getAssociatedDeclaration();
4110 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4111 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4112 if (SCD != CCD)
4113 return false;
4114 std::advance(i&: CCI, n: 1);
4115 if (CCI == CCE)
4116 break;
4117 }
4118 return true;
4119 })) {
4120 Visit(S: E->getBase());
4121 }
4122 } else if (!TryCaptureCXXThisMembers) {
4123 Visit(S: E->getBase());
4124 }
4125 }
4126 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4127 for (OMPClause *C : S->clauses()) {
4128 // Skip analysis of arguments of private clauses for task|target
4129 // directives.
4130 if (isa_and_nonnull<OMPPrivateClause>(Val: C))
4131 continue;
4132 // Skip analysis of arguments of implicitly defined firstprivate clause
4133 // for task|target directives.
4134 // Skip analysis of arguments of implicitly defined map clause for target
4135 // directives.
4136 if (C && !((isa<OMPFirstprivateClause>(Val: C) || isa<OMPMapClause>(Val: C)) &&
4137 C->isImplicit() && !isOpenMPTaskingDirective(Kind: DKind))) {
4138 for (Stmt *CC : C->children()) {
4139 if (CC)
4140 Visit(S: CC);
4141 }
4142 }
4143 }
4144 // Check implicitly captured variables.
4145 VisitSubCaptures(S);
4146 }
4147
4148 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4149 // Loop transformation directives do not introduce data sharing
4150 VisitStmt(S);
4151 }
4152
4153 void VisitCallExpr(CallExpr *S) {
4154 for (Stmt *C : S->arguments()) {
4155 if (C) {
4156 // Check implicitly captured variables in the task-based directives to
4157 // check if they must be firstprivatized.
4158 Visit(S: C);
4159 }
4160 }
4161 if (Expr *Callee = S->getCallee()) {
4162 auto *CI = Callee->IgnoreParenImpCasts();
4163 if (auto *CE = dyn_cast<MemberExpr>(Val: CI))
4164 Visit(S: CE->getBase());
4165 else if (auto *CE = dyn_cast<DeclRefExpr>(Val: CI))
4166 Visit(S: CE);
4167 }
4168 }
4169 void VisitStmt(Stmt *S) {
4170 for (Stmt *C : S->children()) {
4171 if (C) {
4172 // Check implicitly captured variables in the task-based directives to
4173 // check if they must be firstprivatized.
4174 Visit(S: C);
4175 }
4176 }
4177 }
4178
4179 void visitSubCaptures(CapturedStmt *S) {
4180 for (const CapturedStmt::Capture &Cap : S->captures()) {
4181 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4182 continue;
4183 VarDecl *VD = Cap.getCapturedVar();
4184 // Do not try to map the variable if it or its sub-component was mapped
4185 // already.
4186 if (isOpenMPTargetExecutionDirective(DKind) &&
4187 Stack->checkMappableExprComponentListsForDecl(
4188 VD, /*CurrentRegionOnly=*/true,
4189 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4190 OpenMPClauseKind) { return true; }))
4191 continue;
4192 DeclRefExpr *DRE = buildDeclRefExpr(
4193 S&: SemaRef, D: VD, Ty: VD->getType().getNonLValueExprType(Context: SemaRef.Context),
4194 Loc: Cap.getLocation(), /*RefersToCapture=*/true);
4195 Visit(S: DRE);
4196 }
4197 }
4198 bool isErrorFound() const { return ErrorFound; }
4199 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4200 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4201 return VarsWithInheritedDSA;
4202 }
4203
4204 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4205 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4206 DKind = S->getCurrentDirective();
4207 // Process declare target link variables for the target directives.
4208 if (isOpenMPTargetExecutionDirective(DKind)) {
4209 for (DeclRefExpr *E : Stack->getLinkGlobals())
4210 Visit(S: E);
4211 }
4212 }
4213};
4214} // namespace
4215
4216static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4217 OpenMPDirectiveKind DKind,
4218 bool ScopeEntry) {
4219 SmallVector<llvm::omp::TraitProperty, 8> Traits;
4220 if (isOpenMPTargetExecutionDirective(DKind))
4221 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_target_target);
4222 if (isOpenMPTeamsDirective(DKind))
4223 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_teams_teams);
4224 if (isOpenMPParallelDirective(DKind))
4225 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_parallel_parallel);
4226 if (isOpenMPWorksharingDirective(DKind))
4227 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_for_for);
4228 if (isOpenMPSimdDirective(DKind))
4229 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_simd_simd);
4230 Stack->handleConstructTrait(Traits, ScopeEntry);
4231}
4232
4233static SmallVector<SemaOpenMP::CapturedParamNameType>
4234getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4235 ASTContext &Context = SemaRef.getASTContext();
4236 QualType KmpInt32Ty =
4237 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4238 QualType KmpInt32PtrTy =
4239 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4240 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4241 std::make_pair(x: ".global_tid.", y&: KmpInt32PtrTy),
4242 std::make_pair(x: ".bound_tid.", y&: KmpInt32PtrTy),
4243 };
4244 if (LoopBoundSharing) {
4245 QualType KmpSizeTy = Context.getSizeType().withConst();
4246 Params.push_back(Elt: std::make_pair(x: ".previous.lb.", y&: KmpSizeTy));
4247 Params.push_back(Elt: std::make_pair(x: ".previous.ub.", y&: KmpSizeTy));
4248 }
4249
4250 // __context with shared vars
4251 Params.push_back(Elt: std::make_pair(x: StringRef(), y: QualType()));
4252 return Params;
4253}
4254
4255static SmallVector<SemaOpenMP::CapturedParamNameType>
4256getTeamsRegionParams(Sema &SemaRef) {
4257 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4258}
4259
4260static SmallVector<SemaOpenMP::CapturedParamNameType>
4261getTaskRegionParams(Sema &SemaRef) {
4262 ASTContext &Context = SemaRef.getASTContext();
4263 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(DestWidth: 32, Signed: 1).withConst();
4264 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4265 QualType KmpInt32PtrTy =
4266 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4267 QualType Args[] = {VoidPtrTy};
4268 FunctionProtoType::ExtProtoInfo EPI;
4269 EPI.Variadic = true;
4270 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4271 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4272 std::make_pair(x: ".global_tid.", y&: KmpInt32Ty),
4273 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4274 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4275 std::make_pair(
4276 x: ".copy_fn.",
4277 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4278 std::make_pair(x: ".task_t.", y: Context.VoidPtrTy.withConst()),
4279 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4280 };
4281 return Params;
4282}
4283
4284static SmallVector<SemaOpenMP::CapturedParamNameType>
4285getTargetRegionParams(Sema &SemaRef) {
4286 ASTContext &Context = SemaRef.getASTContext();
4287 SmallVector<SemaOpenMP::CapturedParamNameType> Params;
4288 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4289 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4290 Params.push_back(Elt: std::make_pair(x: StringRef("dyn_ptr"), y&: VoidPtrTy));
4291 }
4292 // __context with shared vars
4293 Params.push_back(Elt: std::make_pair(x: StringRef(), y: QualType()));
4294 return Params;
4295}
4296
4297static SmallVector<SemaOpenMP::CapturedParamNameType>
4298getUnknownRegionParams(Sema &SemaRef) {
4299 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4300 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4301 };
4302 return Params;
4303}
4304
4305static SmallVector<SemaOpenMP::CapturedParamNameType>
4306getTaskloopRegionParams(Sema &SemaRef) {
4307 ASTContext &Context = SemaRef.getASTContext();
4308 QualType KmpInt32Ty =
4309 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4310 QualType KmpUInt64Ty =
4311 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4312 QualType KmpInt64Ty =
4313 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4314 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4315 QualType KmpInt32PtrTy =
4316 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4317 QualType Args[] = {VoidPtrTy};
4318 FunctionProtoType::ExtProtoInfo EPI;
4319 EPI.Variadic = true;
4320 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4321 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4322 std::make_pair(x: ".global_tid.", y&: KmpInt32Ty),
4323 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4324 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4325 std::make_pair(
4326 x: ".copy_fn.",
4327 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4328 std::make_pair(x: ".task_t.", y: Context.VoidPtrTy.withConst()),
4329 std::make_pair(x: ".lb.", y&: KmpUInt64Ty),
4330 std::make_pair(x: ".ub.", y&: KmpUInt64Ty),
4331 std::make_pair(x: ".st.", y&: KmpInt64Ty),
4332 std::make_pair(x: ".liter.", y&: KmpInt32Ty),
4333 std::make_pair(x: ".reductions.", y&: VoidPtrTy),
4334 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4335 };
4336 return Params;
4337}
4338
4339static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind,
4340 Scope *CurScope, SourceLocation Loc) {
4341 SmallVector<OpenMPDirectiveKind> Regions;
4342 getOpenMPCaptureRegions(CaptureRegions&: Regions, DKind);
4343
4344 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(Kind: DKind);
4345
4346 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4347 CSI->TheCapturedDecl->addAttr(A: AlwaysInlineAttr::CreateImplicit(
4348 Ctx&: SemaRef.getASTContext(), Range: {}, S: AlwaysInlineAttr::Keyword_forceinline));
4349 };
4350
4351 for (auto [Level, RKind] : llvm::enumerate(First&: Regions)) {
4352 switch (RKind) {
4353 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4354 // are listed here.
4355 case OMPD_parallel:
4356 SemaRef.ActOnCapturedRegionStart(
4357 Loc, CurScope, Kind: CR_OpenMP,
4358 Params: getParallelRegionParams(SemaRef, LoopBoundSharing), OpenMPCaptureLevel: Level);
4359 break;
4360 case OMPD_teams:
4361 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4362 Params: getTeamsRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4363 break;
4364 case OMPD_task:
4365 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4366 Params: getTaskRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4367 // Mark this captured region as inlined, because we don't use outlined
4368 // function directly.
4369 MarkAsInlined(SemaRef.getCurCapturedRegion());
4370 break;
4371 case OMPD_taskloop:
4372 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4373 Params: getTaskloopRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4374 // Mark this captured region as inlined, because we don't use outlined
4375 // function directly.
4376 MarkAsInlined(SemaRef.getCurCapturedRegion());
4377 break;
4378 case OMPD_target:
4379 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4380 Params: getTargetRegionParams(SemaRef), OpenMPCaptureLevel: Level);
4381 break;
4382 case OMPD_unknown:
4383 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, Kind: CR_OpenMP,
4384 Params: getUnknownRegionParams(SemaRef));
4385 break;
4386 case OMPD_metadirective:
4387 case OMPD_nothing:
4388 default:
4389 llvm_unreachable("Unexpected capture region");
4390 }
4391 }
4392}
4393
4394void SemaOpenMP::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,
4395 Scope *CurScope) {
4396 switch (DKind) {
4397 case OMPD_atomic:
4398 case OMPD_critical:
4399 case OMPD_masked:
4400 case OMPD_master:
4401 case OMPD_section:
4402 case OMPD_tile:
4403 case OMPD_stripe:
4404 case OMPD_unroll:
4405 case OMPD_reverse:
4406 case OMPD_interchange:
4407 case OMPD_assume:
4408 break;
4409 default:
4410 processCapturedRegions(SemaRef, DKind, CurScope,
4411 DSAStack->getConstructLoc());
4412 break;
4413 }
4414
4415 DSAStack->setContext(SemaRef.CurContext);
4416 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4417}
4418
4419int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4420 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4421}
4422
4423int SemaOpenMP::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4424 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4425 getOpenMPCaptureRegions(CaptureRegions, DKind);
4426 return CaptureRegions.size();
4427}
4428
4429static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
4430 Expr *CaptureExpr, bool WithInit,
4431 DeclContext *CurContext,
4432 bool AsExpression) {
4433 assert(CaptureExpr);
4434 ASTContext &C = S.getASTContext();
4435 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4436 QualType Ty = Init->getType();
4437 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4438 if (S.getLangOpts().CPlusPlus) {
4439 Ty = C.getLValueReferenceType(T: Ty);
4440 } else {
4441 Ty = C.getPointerType(T: Ty);
4442 ExprResult Res =
4443 S.CreateBuiltinUnaryOp(OpLoc: CaptureExpr->getExprLoc(), Opc: UO_AddrOf, InputExpr: Init);
4444 if (!Res.isUsable())
4445 return nullptr;
4446 Init = Res.get();
4447 }
4448 WithInit = true;
4449 }
4450 auto *CED = OMPCapturedExprDecl::Create(C, DC: CurContext, Id, T: Ty,
4451 StartLoc: CaptureExpr->getBeginLoc());
4452 if (!WithInit)
4453 CED->addAttr(A: OMPCaptureNoInitAttr::CreateImplicit(Ctx&: C));
4454 CurContext->addHiddenDecl(D: CED);
4455 Sema::TentativeAnalysisScope Trap(S);
4456 S.AddInitializerToDecl(dcl: CED, init: Init, /*DirectInit=*/false);
4457 return CED;
4458}
4459
4460static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4461 bool WithInit) {
4462 OMPCapturedExprDecl *CD;
4463 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4464 CD = cast<OMPCapturedExprDecl>(Val: VD);
4465 else
4466 CD = buildCaptureDecl(S, Id: D->getIdentifier(), CaptureExpr, WithInit,
4467 CurContext: S.CurContext,
4468 /*AsExpression=*/false);
4469 return buildDeclRefExpr(S, D: CD, Ty: CD->getType().getNonReferenceType(),
4470 Loc: CaptureExpr->getExprLoc());
4471}
4472
4473static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4474 StringRef Name) {
4475 CaptureExpr = S.DefaultLvalueConversion(E: CaptureExpr).get();
4476 if (!Ref) {
4477 OMPCapturedExprDecl *CD = buildCaptureDecl(
4478 S, Id: &S.getASTContext().Idents.get(Name), CaptureExpr,
4479 /*WithInit=*/true, CurContext: S.CurContext, /*AsExpression=*/true);
4480 Ref = buildDeclRefExpr(S, D: CD, Ty: CD->getType().getNonReferenceType(),
4481 Loc: CaptureExpr->getExprLoc());
4482 }
4483 ExprResult Res = Ref;
4484 if (!S.getLangOpts().CPlusPlus &&
4485 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4486 Ref->getType()->isPointerType()) {
4487 Res = S.CreateBuiltinUnaryOp(OpLoc: CaptureExpr->getExprLoc(), Opc: UO_Deref, InputExpr: Ref);
4488 if (!Res.isUsable())
4489 return ExprError();
4490 }
4491 return S.DefaultLvalueConversion(E: Res.get());
4492}
4493
4494namespace {
4495// OpenMP directives parsed in this section are represented as a
4496// CapturedStatement with an associated statement. If a syntax error
4497// is detected during the parsing of the associated statement, the
4498// compiler must abort processing and close the CapturedStatement.
4499//
4500// Combined directives such as 'target parallel' have more than one
4501// nested CapturedStatements. This RAII ensures that we unwind out
4502// of all the nested CapturedStatements when an error is found.
4503class CaptureRegionUnwinderRAII {
4504private:
4505 Sema &S;
4506 bool &ErrorFound;
4507 OpenMPDirectiveKind DKind = OMPD_unknown;
4508
4509public:
4510 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4511 OpenMPDirectiveKind DKind)
4512 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4513 ~CaptureRegionUnwinderRAII() {
4514 if (ErrorFound) {
4515 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4516 while (--ThisCaptureLevel >= 0)
4517 S.ActOnCapturedRegionError();
4518 }
4519 }
4520};
4521} // namespace
4522
4523void SemaOpenMP::tryCaptureOpenMPLambdas(ValueDecl *V) {
4524 // Capture variables captured by reference in lambdas for target-based
4525 // directives.
4526 if (!SemaRef.CurContext->isDependentContext() &&
4527 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4528 isOpenMPTargetDataManagementDirective(
4529 DSAStack->getCurrentDirective()))) {
4530 QualType Type = V->getType();
4531 if (const auto *RD = Type.getCanonicalType()
4532 .getNonReferenceType()
4533 ->getAsCXXRecordDecl()) {
4534 bool SavedForceCaptureByReferenceInTargetExecutable =
4535 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4536 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4537 /*V=*/true);
4538 if (RD->isLambda()) {
4539 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4540 FieldDecl *ThisCapture;
4541 RD->getCaptureFields(Captures, ThisCapture);
4542 for (const LambdaCapture &LC : RD->captures()) {
4543 if (LC.getCaptureKind() == LCK_ByRef) {
4544 VarDecl *VD = cast<VarDecl>(Val: LC.getCapturedVar());
4545 DeclContext *VDC = VD->getDeclContext();
4546 if (!VDC->Encloses(DC: SemaRef.CurContext))
4547 continue;
4548 SemaRef.MarkVariableReferenced(Loc: LC.getLocation(), Var: VD);
4549 } else if (LC.getCaptureKind() == LCK_This) {
4550 QualType ThisTy = SemaRef.getCurrentThisType();
4551 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4552 T1: ThisTy, T2: ThisCapture->getType()))
4553 SemaRef.CheckCXXThisCapture(Loc: LC.getLocation());
4554 }
4555 }
4556 }
4557 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4558 SavedForceCaptureByReferenceInTargetExecutable);
4559 }
4560 }
4561}
4562
4563static bool checkOrderedOrderSpecified(Sema &S,
4564 const ArrayRef<OMPClause *> Clauses) {
4565 const OMPOrderedClause *Ordered = nullptr;
4566 const OMPOrderClause *Order = nullptr;
4567
4568 for (const OMPClause *Clause : Clauses) {
4569 if (Clause->getClauseKind() == OMPC_ordered)
4570 Ordered = cast<OMPOrderedClause>(Val: Clause);
4571 else if (Clause->getClauseKind() == OMPC_order) {
4572 Order = cast<OMPOrderClause>(Val: Clause);
4573 if (Order->getKind() != OMPC_ORDER_concurrent)
4574 Order = nullptr;
4575 }
4576 if (Ordered && Order)
4577 break;
4578 }
4579
4580 if (Ordered && Order) {
4581 S.Diag(Loc: Order->getKindKwLoc(),
4582 DiagID: diag::err_omp_simple_clause_incompatible_with_ordered)
4583 << getOpenMPClauseNameForDiag(C: OMPC_order)
4584 << getOpenMPSimpleClauseTypeName(Kind: OMPC_order, Type: OMPC_ORDER_concurrent)
4585 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4586 S.Diag(Loc: Ordered->getBeginLoc(), DiagID: diag::note_omp_ordered_param)
4587 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4588 return true;
4589 }
4590 return false;
4591}
4592
4593StmtResult SemaOpenMP::ActOnOpenMPRegionEnd(StmtResult S,
4594 ArrayRef<OMPClause *> Clauses) {
4595 handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(),
4596 /*ScopeEntry=*/false);
4597 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4598 return S;
4599
4600 bool ErrorFound = false;
4601 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4602 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4603 if (!S.isUsable()) {
4604 ErrorFound = true;
4605 return StmtError();
4606 }
4607
4608 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4609 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4610 OMPOrderedClause *OC = nullptr;
4611 OMPScheduleClause *SC = nullptr;
4612 SmallVector<const OMPLinearClause *, 4> LCs;
4613 SmallVector<const OMPClauseWithPreInit *, 4> PICs;
4614 // This is required for proper codegen.
4615 for (OMPClause *Clause : Clauses) {
4616 if (!getLangOpts().OpenMPSimd &&
4617 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4618 DSAStack->getCurrentDirective() == OMPD_target) &&
4619 Clause->getClauseKind() == OMPC_in_reduction) {
4620 // Capture taskgroup task_reduction descriptors inside the tasking regions
4621 // with the corresponding in_reduction items.
4622 auto *IRC = cast<OMPInReductionClause>(Val: Clause);
4623 for (Expr *E : IRC->taskgroup_descriptors())
4624 if (E)
4625 SemaRef.MarkDeclarationsReferencedInExpr(E);
4626 }
4627 if (isOpenMPPrivate(Kind: Clause->getClauseKind()) ||
4628 Clause->getClauseKind() == OMPC_copyprivate ||
4629 (getLangOpts().OpenMPUseTLS &&
4630 getASTContext().getTargetInfo().isTLSSupported() &&
4631 Clause->getClauseKind() == OMPC_copyin)) {
4632 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4633 // Mark all variables in private list clauses as used in inner region.
4634 for (Stmt *VarRef : Clause->children()) {
4635 if (auto *E = cast_or_null<Expr>(Val: VarRef)) {
4636 SemaRef.MarkDeclarationsReferencedInExpr(E);
4637 }
4638 }
4639 DSAStack->setForceVarCapturing(/*V=*/false);
4640 } else if (CaptureRegions.size() > 1 ||
4641 CaptureRegions.back() != OMPD_unknown) {
4642 if (auto *C = OMPClauseWithPreInit::get(C: Clause))
4643 PICs.push_back(Elt: C);
4644 if (auto *C = OMPClauseWithPostUpdate::get(C: Clause)) {
4645 if (Expr *E = C->getPostUpdateExpr())
4646 SemaRef.MarkDeclarationsReferencedInExpr(E);
4647 }
4648 }
4649 if (Clause->getClauseKind() == OMPC_schedule)
4650 SC = cast<OMPScheduleClause>(Val: Clause);
4651 else if (Clause->getClauseKind() == OMPC_ordered)
4652 OC = cast<OMPOrderedClause>(Val: Clause);
4653 else if (Clause->getClauseKind() == OMPC_linear)
4654 LCs.push_back(Elt: cast<OMPLinearClause>(Val: Clause));
4655 }
4656 // Capture allocator expressions if used.
4657 for (Expr *E : DSAStack->getInnerAllocators())
4658 SemaRef.MarkDeclarationsReferencedInExpr(E);
4659 // OpenMP, 2.7.1 Loop Construct, Restrictions
4660 // The nonmonotonic modifier cannot be specified if an ordered clause is
4661 // specified.
4662 if (SC &&
4663 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4664 SC->getSecondScheduleModifier() ==
4665 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4666 OC) {
4667 Diag(Loc: SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4668 ? SC->getFirstScheduleModifierLoc()
4669 : SC->getSecondScheduleModifierLoc(),
4670 DiagID: diag::err_omp_simple_clause_incompatible_with_ordered)
4671 << getOpenMPClauseNameForDiag(C: OMPC_schedule)
4672 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule,
4673 Type: OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4674 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4675 ErrorFound = true;
4676 }
4677 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4678 // If an order(concurrent) clause is present, an ordered clause may not appear
4679 // on the same directive.
4680 if (checkOrderedOrderSpecified(S&: SemaRef, Clauses))
4681 ErrorFound = true;
4682 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4683 for (const OMPLinearClause *C : LCs) {
4684 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_linear_ordered)
4685 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4686 }
4687 ErrorFound = true;
4688 }
4689 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4690 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4691 OC->getNumForLoops()) {
4692 unsigned OMPVersion = getLangOpts().OpenMP;
4693 Diag(Loc: OC->getBeginLoc(), DiagID: diag::err_omp_ordered_simd)
4694 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), Ver: OMPVersion);
4695 ErrorFound = true;
4696 }
4697 if (ErrorFound) {
4698 return StmtError();
4699 }
4700 StmtResult SR = S;
4701 unsigned CompletedRegions = 0;
4702 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(C&: CaptureRegions)) {
4703 // Mark all variables in private list clauses as used in inner region.
4704 // Required for proper codegen of combined directives.
4705 // TODO: add processing for other clauses.
4706 if (ThisCaptureRegion != OMPD_unknown) {
4707 for (const clang::OMPClauseWithPreInit *C : PICs) {
4708 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4709 // Find the particular capture region for the clause if the
4710 // directive is a combined one with multiple capture regions.
4711 // If the directive is not a combined one, the capture region
4712 // associated with the clause is OMPD_unknown and is generated
4713 // only once.
4714 if (CaptureRegion == ThisCaptureRegion ||
4715 CaptureRegion == OMPD_unknown) {
4716 if (auto *DS = cast_or_null<DeclStmt>(Val: C->getPreInitStmt())) {
4717 for (Decl *D : DS->decls())
4718 SemaRef.MarkVariableReferenced(Loc: D->getLocation(),
4719 Var: cast<VarDecl>(Val: D));
4720 }
4721 }
4722 }
4723 }
4724 if (ThisCaptureRegion == OMPD_target) {
4725 // Capture allocator traits in the target region. They are used implicitly
4726 // and, thus, are not captured by default.
4727 for (OMPClause *C : Clauses) {
4728 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(Val: C)) {
4729 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4730 ++I) {
4731 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4732 if (Expr *E = D.AllocatorTraits)
4733 SemaRef.MarkDeclarationsReferencedInExpr(E);
4734 }
4735 continue;
4736 }
4737 }
4738 }
4739 if (ThisCaptureRegion == OMPD_parallel) {
4740 // Capture temp arrays for inscan reductions and locals in aligned
4741 // clauses.
4742 for (OMPClause *C : Clauses) {
4743 if (auto *RC = dyn_cast<OMPReductionClause>(Val: C)) {
4744 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4745 continue;
4746 for (Expr *E : RC->copy_array_temps())
4747 if (E)
4748 SemaRef.MarkDeclarationsReferencedInExpr(E);
4749 }
4750 if (auto *AC = dyn_cast<OMPAlignedClause>(Val: C)) {
4751 for (Expr *E : AC->varlist())
4752 SemaRef.MarkDeclarationsReferencedInExpr(E);
4753 }
4754 }
4755 }
4756 if (++CompletedRegions == CaptureRegions.size())
4757 DSAStack->setBodyComplete();
4758 SR = SemaRef.ActOnCapturedRegionEnd(S: SR.get());
4759 }
4760 return SR;
4761}
4762
4763static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4764 OpenMPDirectiveKind CancelRegion,
4765 SourceLocation StartLoc) {
4766 // CancelRegion is only needed for cancel and cancellation_point.
4767 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4768 return false;
4769
4770 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4771 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4772 return false;
4773
4774 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4775 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_wrong_cancel_region)
4776 << getOpenMPDirectiveName(D: CancelRegion, Ver: OMPVersion);
4777 return true;
4778}
4779
4780static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4781 OpenMPDirectiveKind CurrentRegion,
4782 const DeclarationNameInfo &CurrentName,
4783 OpenMPDirectiveKind CancelRegion,
4784 OpenMPBindClauseKind BindKind,
4785 SourceLocation StartLoc) {
4786 if (!Stack->getCurScope())
4787 return false;
4788
4789 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4790 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4791 bool NestingProhibited = false;
4792 bool CloseNesting = true;
4793 bool OrphanSeen = false;
4794 enum {
4795 NoRecommend,
4796 ShouldBeInParallelRegion,
4797 ShouldBeInOrderedRegion,
4798 ShouldBeInTargetRegion,
4799 ShouldBeInTeamsRegion,
4800 ShouldBeInLoopSimdRegion,
4801 } Recommend = NoRecommend;
4802
4803 SmallVector<OpenMPDirectiveKind, 4> LeafOrComposite;
4804 ArrayRef<OpenMPDirectiveKind> ParentLOC =
4805 getLeafOrCompositeConstructs(D: ParentRegion, Output&: LeafOrComposite);
4806 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4807 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4808
4809 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
4810 !isOpenMPOrderConcurrentNestableDirective(DKind: CurrentRegion,
4811 LangOpts: SemaRef.LangOpts)) {
4812 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_order)
4813 << getOpenMPDirectiveName(D: CurrentRegion, Ver: OMPVersion);
4814 return true;
4815 }
4816 if (isOpenMPSimdDirective(DKind: ParentRegion) &&
4817 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
4818 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
4819 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4820 CurrentRegion != OMPD_scan))) {
4821 // OpenMP [2.16, Nesting of Regions]
4822 // OpenMP constructs may not be nested inside a simd region.
4823 // OpenMP [2.8.1,simd Construct, Restrictions]
4824 // An ordered construct with the simd clause is the only OpenMP
4825 // construct that can appear in the simd region.
4826 // Allowing a SIMD construct nested in another SIMD construct is an
4827 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4828 // message.
4829 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4830 // The only OpenMP constructs that can be encountered during execution of
4831 // a simd region are the atomic construct, the loop construct, the simd
4832 // construct and the ordered construct with the simd clause.
4833 SemaRef.Diag(Loc: StartLoc, DiagID: (CurrentRegion != OMPD_simd)
4834 ? diag::err_omp_prohibited_region_simd
4835 : diag::warn_omp_nesting_simd)
4836 << (OMPVersion >= 50 ? 1 : 0);
4837 return CurrentRegion != OMPD_simd;
4838 }
4839 if (EnclosingConstruct == OMPD_atomic) {
4840 // OpenMP [2.16, Nesting of Regions]
4841 // OpenMP constructs may not be nested inside an atomic region.
4842 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_atomic);
4843 return true;
4844 }
4845 if (CurrentRegion == OMPD_section) {
4846 // OpenMP [2.7.2, sections Construct, Restrictions]
4847 // Orphaned section directives are prohibited. That is, the section
4848 // directives must appear within the sections construct and must not be
4849 // encountered elsewhere in the sections region.
4850 if (EnclosingConstruct != OMPD_sections) {
4851 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_section_directive)
4852 << (ParentRegion != OMPD_unknown)
4853 << getOpenMPDirectiveName(D: ParentRegion, Ver: OMPVersion);
4854 return true;
4855 }
4856 return false;
4857 }
4858 // Allow some constructs (except teams and cancellation constructs) to be
4859 // orphaned (they could be used in functions, called from OpenMP regions
4860 // with the required preconditions).
4861 if (ParentRegion == OMPD_unknown &&
4862 !isOpenMPNestingTeamsDirective(DKind: CurrentRegion) &&
4863 CurrentRegion != OMPD_cancellation_point &&
4864 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4865 return false;
4866 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
4867 // for a detailed explanation
4868 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
4869 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4870 (isOpenMPWorksharingDirective(DKind: ParentRegion) ||
4871 EnclosingConstruct == OMPD_loop)) {
4872 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4873 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region)
4874 << true << getOpenMPDirectiveName(D: ParentRegion, Ver: OMPVersion)
4875 << ErrorMsgNumber << getOpenMPDirectiveName(D: CurrentRegion, Ver: OMPVersion);
4876 return true;
4877 }
4878 if (CurrentRegion == OMPD_cancellation_point ||
4879 CurrentRegion == OMPD_cancel) {
4880 // OpenMP [2.16, Nesting of Regions]
4881 // A cancellation point construct for which construct-type-clause is
4882 // taskgroup must be nested inside a task construct. A cancellation
4883 // point construct for which construct-type-clause is not taskgroup must
4884 // be closely nested inside an OpenMP construct that matches the type
4885 // specified in construct-type-clause.
4886 // A cancel construct for which construct-type-clause is taskgroup must be
4887 // nested inside a task construct. A cancel construct for which
4888 // construct-type-clause is not taskgroup must be closely nested inside an
4889 // OpenMP construct that matches the type specified in
4890 // construct-type-clause.
4891 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(D: ParentRegion);
4892 if (CancelRegion == OMPD_taskgroup) {
4893 NestingProhibited =
4894 EnclosingConstruct != OMPD_task &&
4895 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
4896 } else if (CancelRegion == OMPD_sections) {
4897 NestingProhibited = EnclosingConstruct != OMPD_section &&
4898 EnclosingConstruct != OMPD_sections;
4899 } else {
4900 NestingProhibited = CancelRegion != Leafs.back();
4901 }
4902 OrphanSeen = ParentRegion == OMPD_unknown;
4903 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4904 // OpenMP 5.1 [2.22, Nesting of Regions]
4905 // A masked region may not be closely nested inside a worksharing, loop,
4906 // atomic, task, or taskloop region.
4907 NestingProhibited = isOpenMPWorksharingDirective(DKind: ParentRegion) ||
4908 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
4909 isOpenMPTaskingDirective(Kind: ParentRegion);
4910 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
4911 // OpenMP [2.16, Nesting of Regions]
4912 // A critical region may not be nested (closely or otherwise) inside a
4913 // critical region with the same name. Note that this restriction is not
4914 // sufficient to prevent deadlock.
4915 SourceLocation PreviousCriticalLoc;
4916 bool DeadLock = Stack->hasDirective(
4917 DPred: [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
4918 const DeclarationNameInfo &DNI,
4919 SourceLocation Loc) {
4920 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
4921 PreviousCriticalLoc = Loc;
4922 return true;
4923 }
4924 return false;
4925 },
4926 FromParent: false /* skip top directive */);
4927 if (DeadLock) {
4928 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_critical_same_name)
4929 << CurrentName.getName();
4930 if (PreviousCriticalLoc.isValid())
4931 SemaRef.Diag(Loc: PreviousCriticalLoc,
4932 DiagID: diag::note_omp_previous_critical_region);
4933 return true;
4934 }
4935 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4936 // OpenMP 5.1 [2.22, Nesting of Regions]
4937 // A scope region may not be closely nested inside a worksharing, loop,
4938 // task, taskloop, critical, ordered, atomic, or masked region.
4939 // OpenMP 5.1 [2.22, Nesting of Regions]
4940 // A barrier region may not be closely nested inside a worksharing, loop,
4941 // task, taskloop, critical, ordered, atomic, or masked region.
4942 NestingProhibited = isOpenMPWorksharingDirective(DKind: ParentRegion) ||
4943 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
4944 isOpenMPTaskingDirective(Kind: ParentRegion) ||
4945 llvm::is_contained(Set: {OMPD_masked, OMPD_master,
4946 OMPD_critical, OMPD_ordered},
4947 Element: EnclosingConstruct);
4948 } else if (isOpenMPWorksharingDirective(DKind: CurrentRegion) &&
4949 !isOpenMPParallelDirective(DKind: CurrentRegion) &&
4950 !isOpenMPTeamsDirective(DKind: CurrentRegion)) {
4951 // OpenMP 5.1 [2.22, Nesting of Regions]
4952 // A loop region that binds to a parallel region or a worksharing region
4953 // may not be closely nested inside a worksharing, loop, task, taskloop,
4954 // critical, ordered, atomic, or masked region.
4955 NestingProhibited = isOpenMPWorksharingDirective(DKind: ParentRegion) ||
4956 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
4957 isOpenMPTaskingDirective(Kind: ParentRegion) ||
4958 llvm::is_contained(Set: {OMPD_masked, OMPD_master,
4959 OMPD_critical, OMPD_ordered},
4960 Element: EnclosingConstruct);
4961 Recommend = ShouldBeInParallelRegion;
4962 } else if (CurrentRegion == OMPD_ordered) {
4963 // OpenMP [2.16, Nesting of Regions]
4964 // An ordered region may not be closely nested inside a critical,
4965 // atomic, or explicit task region.
4966 // An ordered region must be closely nested inside a loop region (or
4967 // parallel loop region) with an ordered clause.
4968 // OpenMP [2.8.1,simd Construct, Restrictions]
4969 // An ordered construct with the simd clause is the only OpenMP construct
4970 // that can appear in the simd region.
4971 NestingProhibited = EnclosingConstruct == OMPD_critical ||
4972 isOpenMPTaskingDirective(Kind: ParentRegion) ||
4973 !(isOpenMPSimdDirective(DKind: ParentRegion) ||
4974 Stack->isParentOrderedRegion());
4975 Recommend = ShouldBeInOrderedRegion;
4976 } else if (isOpenMPNestingTeamsDirective(DKind: CurrentRegion)) {
4977 // OpenMP [2.16, Nesting of Regions]
4978 // If specified, a teams construct must be contained within a target
4979 // construct.
4980 NestingProhibited =
4981 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
4982 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
4983 EnclosingConstruct != OMPD_target);
4984 OrphanSeen = ParentRegion == OMPD_unknown;
4985 Recommend = ShouldBeInTargetRegion;
4986 } else if (CurrentRegion == OMPD_scan) {
4987 if (OMPVersion >= 50) {
4988 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
4989 // simd, or for simd. This has to take into account combined directives.
4990 // In 5.2 this seems to be implied by the fact that the specified
4991 // separated constructs are do, for, and simd.
4992 NestingProhibited = !llvm::is_contained(
4993 Set: {OMPD_for, OMPD_simd, OMPD_for_simd}, Element: EnclosingConstruct);
4994 } else {
4995 NestingProhibited = true;
4996 }
4997 OrphanSeen = ParentRegion == OMPD_unknown;
4998 Recommend = ShouldBeInLoopSimdRegion;
4999 }
5000 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(DKind: CurrentRegion) &&
5001 !isOpenMPTargetDataManagementDirective(DKind: CurrentRegion) &&
5002 EnclosingConstruct == OMPD_teams) {
5003 // OpenMP [5.1, 2.22, Nesting of Regions]
5004 // distribute, distribute simd, distribute parallel worksharing-loop,
5005 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5006 // including any parallel regions arising from combined constructs,
5007 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5008 // only OpenMP regions that may be strictly nested inside the teams
5009 // region.
5010 //
5011 // As an extension, we permit atomic within teams as well.
5012 NestingProhibited = !isOpenMPParallelDirective(DKind: CurrentRegion) &&
5013 !isOpenMPDistributeDirective(DKind: CurrentRegion) &&
5014 CurrentRegion != OMPD_loop &&
5015 !(SemaRef.getLangOpts().OpenMPExtensions &&
5016 CurrentRegion == OMPD_atomic);
5017 Recommend = ShouldBeInParallelRegion;
5018 }
5019 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5020 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5021 // If the bind clause is present on the loop construct and binding is
5022 // teams then the corresponding loop region must be strictly nested inside
5023 // a teams region.
5024 NestingProhibited =
5025 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5026 Recommend = ShouldBeInTeamsRegion;
5027 }
5028 if (!NestingProhibited && isOpenMPNestingDistributeDirective(DKind: CurrentRegion)) {
5029 // OpenMP 4.5 [2.17 Nesting of Regions]
5030 // The region associated with the distribute construct must be strictly
5031 // nested inside a teams region
5032 NestingProhibited = EnclosingConstruct != OMPD_teams;
5033 Recommend = ShouldBeInTeamsRegion;
5034 }
5035 if (!NestingProhibited &&
5036 (isOpenMPTargetExecutionDirective(DKind: CurrentRegion) ||
5037 isOpenMPTargetDataManagementDirective(DKind: CurrentRegion))) {
5038 // OpenMP 4.5 [2.17 Nesting of Regions]
5039 // If a target, target update, target data, target enter data, or
5040 // target exit data construct is encountered during execution of a
5041 // target region, the behavior is unspecified.
5042 NestingProhibited = Stack->hasDirective(
5043 DPred: [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5044 SourceLocation) {
5045 if (isOpenMPTargetExecutionDirective(DKind: K)) {
5046 OffendingRegion = K;
5047 return true;
5048 }
5049 return false;
5050 },
5051 FromParent: false /* don't skip top directive */);
5052 CloseNesting = false;
5053 }
5054 if (NestingProhibited) {
5055 if (OrphanSeen) {
5056 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_device_directive)
5057 << getOpenMPDirectiveName(D: CurrentRegion, Ver: OMPVersion) << Recommend;
5058 } else {
5059 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region)
5060 << CloseNesting << getOpenMPDirectiveName(D: OffendingRegion, Ver: OMPVersion)
5061 << Recommend << getOpenMPDirectiveName(D: CurrentRegion, Ver: OMPVersion);
5062 }
5063 return true;
5064 }
5065 return false;
5066}
5067
5068struct Kind2Unsigned {
5069 using argument_type = OpenMPDirectiveKind;
5070 unsigned operator()(argument_type DK) { return unsigned(DK); }
5071};
5072static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5073 ArrayRef<OMPClause *> Clauses,
5074 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5075 bool ErrorFound = false;
5076 unsigned NamedModifiersNumber = 0;
5077 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5078 FoundNameModifiers.resize(s: llvm::omp::Directive_enumSize + 1);
5079 SmallVector<SourceLocation, 4> NameModifierLoc;
5080 unsigned OMPVersion = S.getLangOpts().OpenMP;
5081 for (const OMPClause *C : Clauses) {
5082 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(Val: C)) {
5083 // At most one if clause without a directive-name-modifier can appear on
5084 // the directive.
5085 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5086 auto &FNM = FoundNameModifiers[CurNM];
5087 if (FNM) {
5088 S.Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_more_one_clause)
5089 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion)
5090 << getOpenMPClauseNameForDiag(C: OMPC_if) << (CurNM != OMPD_unknown)
5091 << getOpenMPDirectiveName(D: CurNM, Ver: OMPVersion);
5092 ErrorFound = true;
5093 } else if (CurNM != OMPD_unknown) {
5094 NameModifierLoc.push_back(Elt: IC->getNameModifierLoc());
5095 ++NamedModifiersNumber;
5096 }
5097 FNM = IC;
5098 if (CurNM == OMPD_unknown)
5099 continue;
5100 // Check if the specified name modifier is allowed for the current
5101 // directive.
5102 // At most one if clause with the particular directive-name-modifier can
5103 // appear on the directive.
5104 if (!llvm::is_contained(Range&: AllowedNameModifiers, Element: CurNM)) {
5105 S.Diag(Loc: IC->getNameModifierLoc(),
5106 DiagID: diag::err_omp_wrong_if_directive_name_modifier)
5107 << getOpenMPDirectiveName(D: CurNM, Ver: OMPVersion)
5108 << getOpenMPDirectiveName(D: Kind, Ver: OMPVersion);
5109 ErrorFound = true;
5110 }
5111 }
5112 }
5113 // If any if clause on the directive includes a directive-name-modifier then
5114 // all if clauses on the directive must include a directive-name-modifier.
5115 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5116 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5117 S.Diag(Loc: FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5118 DiagID: diag::err_omp_no_more_if_clause);
5119 } else {
5120 std::string Values;
5121 std::string Sep(", ");
5122 unsigned AllowedCnt = 0;
5123 unsigned TotalAllowedNum =
5124 AllowedNameModifiers.size() - NamedModifiersNumber;
5125 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5126 ++Cnt) {
5127 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5128 if (!FoundNameModifiers[NM]) {
5129 Values += "'";
5130 Values += getOpenMPDirectiveName(D: NM, Ver: OMPVersion);
5131 Values += "'";
5132 if (AllowedCnt + 2 == TotalAllowedNum)
5133 Values += " or ";
5134 else if (AllowedCnt + 1 != TotalAllowedNum)
5135 Values += Sep;
5136 ++AllowedCnt;
5137 }
5138 }
5139 S.Diag(Loc: FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5140 DiagID: diag::err_omp_unnamed_if_clause)
5141 << (TotalAllowedNum > 1) << Values;
5142 }
5143 for (SourceLocation Loc : NameModifierLoc) {
5144 S.Diag(Loc, DiagID: diag::note_omp_previous_named_if_clause);
5145 }
5146 ErrorFound = true;
5147 }
5148 return ErrorFound;
5149}
5150
5151static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5152 SourceLocation &ELoc,
5153 SourceRange &ERange,
5154 bool AllowArraySection,
5155 StringRef DiagType) {
5156 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5157 RefExpr->containsUnexpandedParameterPack())
5158 return std::make_pair(x: nullptr, y: true);
5159
5160 // OpenMP [3.1, C/C++]
5161 // A list item is a variable name.
5162 // OpenMP [2.9.3.3, Restrictions, p.1]
5163 // A variable that is part of another variable (as an array or
5164 // structure element) cannot appear in a private clause.
5165 RefExpr = RefExpr->IgnoreParens();
5166 enum {
5167 NoArrayExpr = -1,
5168 ArraySubscript = 0,
5169 OMPArraySection = 1
5170 } IsArrayExpr = NoArrayExpr;
5171 if (AllowArraySection) {
5172 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(Val: RefExpr)) {
5173 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5174 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base))
5175 Base = TempASE->getBase()->IgnoreParenImpCasts();
5176 RefExpr = Base;
5177 IsArrayExpr = ArraySubscript;
5178 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(Val: RefExpr)) {
5179 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5180 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Val: Base))
5181 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5182 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base))
5183 Base = TempASE->getBase()->IgnoreParenImpCasts();
5184 RefExpr = Base;
5185 IsArrayExpr = OMPArraySection;
5186 }
5187 }
5188 ELoc = RefExpr->getExprLoc();
5189 ERange = RefExpr->getSourceRange();
5190 RefExpr = RefExpr->IgnoreParenImpCasts();
5191 auto *DE = dyn_cast_or_null<DeclRefExpr>(Val: RefExpr);
5192 auto *ME = dyn_cast_or_null<MemberExpr>(Val: RefExpr);
5193 if ((!DE || !isa<VarDecl>(Val: DE->getDecl())) &&
5194 (S.getCurrentThisType().isNull() || !ME ||
5195 !isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()) ||
5196 !isa<FieldDecl>(Val: ME->getMemberDecl()))) {
5197 if (IsArrayExpr != NoArrayExpr) {
5198 S.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
5199 << IsArrayExpr << ERange;
5200 } else if (!DiagType.empty()) {
5201 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5202 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5203 : 0;
5204 S.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_var_name_member_expr_with_type)
5205 << DiagSelect << DiagType << ERange;
5206 } else {
5207 S.Diag(Loc: ELoc,
5208 DiagID: AllowArraySection
5209 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5210 : diag::err_omp_expected_var_name_member_expr)
5211 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5212 }
5213 return std::make_pair(x: nullptr, y: false);
5214 }
5215 return std::make_pair(
5216 x: getCanonicalDecl(D: DE ? DE->getDecl() : ME->getMemberDecl()), y: false);
5217}
5218
5219namespace {
5220/// Checks if the allocator is used in uses_allocators clause to be allowed in
5221/// target regions.
5222class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5223 DSAStackTy *S = nullptr;
5224
5225public:
5226 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5227 return S->isUsesAllocatorsDecl(D: E->getDecl())
5228 .value_or(u: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5229 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5230 }
5231 bool VisitStmt(const Stmt *S) {
5232 for (const Stmt *Child : S->children()) {
5233 if (Child && Visit(S: Child))
5234 return true;
5235 }
5236 return false;
5237 }
5238 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5239};
5240} // namespace
5241
5242static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5243 ArrayRef<OMPClause *> Clauses) {
5244 assert(!S.CurContext->isDependentContext() &&
5245 "Expected non-dependent context.");
5246 auto AllocateRange =
5247 llvm::make_filter_range(Range&: Clauses, Pred: OMPAllocateClause::classof);
5248 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5249 auto PrivateRange = llvm::make_filter_range(Range&: Clauses, Pred: [](const OMPClause *C) {
5250 return isOpenMPPrivate(Kind: C->getClauseKind());
5251 });
5252 for (OMPClause *Cl : PrivateRange) {
5253 MutableArrayRef<Expr *>::iterator I, It, Et;
5254 if (Cl->getClauseKind() == OMPC_private) {
5255 auto *PC = cast<OMPPrivateClause>(Val: Cl);
5256 I = PC->private_copies().begin();
5257 It = PC->varlist_begin();
5258 Et = PC->varlist_end();
5259 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5260 auto *PC = cast<OMPFirstprivateClause>(Val: Cl);
5261 I = PC->private_copies().begin();
5262 It = PC->varlist_begin();
5263 Et = PC->varlist_end();
5264 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5265 auto *PC = cast<OMPLastprivateClause>(Val: Cl);
5266 I = PC->private_copies().begin();
5267 It = PC->varlist_begin();
5268 Et = PC->varlist_end();
5269 } else if (Cl->getClauseKind() == OMPC_linear) {
5270 auto *PC = cast<OMPLinearClause>(Val: Cl);
5271 I = PC->privates().begin();
5272 It = PC->varlist_begin();
5273 Et = PC->varlist_end();
5274 } else if (Cl->getClauseKind() == OMPC_reduction) {
5275 auto *PC = cast<OMPReductionClause>(Val: Cl);
5276 I = PC->privates().begin();
5277 It = PC->varlist_begin();
5278 Et = PC->varlist_end();
5279 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5280 auto *PC = cast<OMPTaskReductionClause>(Val: Cl);
5281 I = PC->privates().begin();
5282 It = PC->varlist_begin();
5283 Et = PC->varlist_end();
5284 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5285 auto *PC = cast<OMPInReductionClause>(Val: Cl);
5286 I = PC->privates().begin();
5287 It = PC->varlist_begin();
5288 Et = PC->varlist_end();
5289 } else {
5290 llvm_unreachable("Expected private clause.");
5291 }
5292 for (Expr *E : llvm::make_range(x: It, y: Et)) {
5293 if (!*I) {
5294 ++I;
5295 continue;
5296 }
5297 SourceLocation ELoc;
5298 SourceRange ERange;
5299 Expr *SimpleRefExpr = E;
5300 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
5301 /*AllowArraySection=*/true);
5302 DeclToCopy.try_emplace(Key: Res.first,
5303 Args: cast<VarDecl>(Val: cast<DeclRefExpr>(Val: *I)->getDecl()));
5304 ++I;
5305 }
5306 }
5307 for (OMPClause *C : AllocateRange) {
5308 auto *AC = cast<OMPAllocateClause>(Val: C);
5309 if (S.getLangOpts().OpenMP >= 50 &&
5310 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5311 isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective()) &&
5312 AC->getAllocator()) {
5313 Expr *Allocator = AC->getAllocator();
5314 // OpenMP, 2.12.5 target Construct
5315 // Memory allocators that do not appear in a uses_allocators clause cannot
5316 // appear as an allocator in an allocate clause or be used in the target
5317 // region unless a requires directive with the dynamic_allocators clause
5318 // is present in the same compilation unit.
5319 AllocatorChecker Checker(Stack);
5320 if (Checker.Visit(S: Allocator))
5321 S.Diag(Loc: Allocator->getExprLoc(),
5322 DiagID: diag::err_omp_allocator_not_in_uses_allocators)
5323 << Allocator->getSourceRange();
5324 }
5325 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5326 getAllocatorKind(S, Stack, Allocator: AC->getAllocator());
5327 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5328 // For task, taskloop or target directives, allocation requests to memory
5329 // allocators with the trait access set to thread result in unspecified
5330 // behavior.
5331 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5332 (isOpenMPTaskingDirective(Kind: Stack->getCurrentDirective()) ||
5333 isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective()))) {
5334 unsigned OMPVersion = S.getLangOpts().OpenMP;
5335 S.Diag(Loc: AC->getAllocator()->getExprLoc(),
5336 DiagID: diag::warn_omp_allocate_thread_on_task_target_directive)
5337 << getOpenMPDirectiveName(D: Stack->getCurrentDirective(), Ver: OMPVersion);
5338 }
5339 for (Expr *E : AC->varlist()) {
5340 SourceLocation ELoc;
5341 SourceRange ERange;
5342 Expr *SimpleRefExpr = E;
5343 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange);
5344 ValueDecl *VD = Res.first;
5345 if (!VD)
5346 continue;
5347 DSAStackTy::DSAVarData Data = Stack->getTopDSA(D: VD, /*FromParent=*/false);
5348 if (!isOpenMPPrivate(Kind: Data.CKind)) {
5349 S.Diag(Loc: E->getExprLoc(),
5350 DiagID: diag::err_omp_expected_private_copy_for_allocate);
5351 continue;
5352 }
5353 VarDecl *PrivateVD = DeclToCopy[VD];
5354 if (checkPreviousOMPAllocateAttribute(S, Stack, RefExpr: E, VD: PrivateVD,
5355 AllocatorKind, Allocator: AC->getAllocator()))
5356 continue;
5357 applyOMPAllocateAttribute(S, VD: PrivateVD, AllocatorKind, Allocator: AC->getAllocator(),
5358 Alignment: AC->getAlignment(), SR: E->getSourceRange());
5359 }
5360 }
5361}
5362
5363namespace {
5364/// Rewrite statements and expressions for Sema \p Actions CurContext.
5365///
5366/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5367/// context. DeclRefExpr used inside the new context are changed to refer to the
5368/// captured variable instead.
5369class CaptureVars : public TreeTransform<CaptureVars> {
5370 using BaseTransform = TreeTransform<CaptureVars>;
5371
5372public:
5373 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5374
5375 bool AlwaysRebuild() { return true; }
5376};
5377} // namespace
5378
5379static VarDecl *precomputeExpr(Sema &Actions,
5380 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5381 StringRef Name) {
5382 Expr *NewE = AssertSuccess(R: CaptureVars(Actions).TransformExpr(E));
5383 VarDecl *NewVar = buildVarDecl(SemaRef&: Actions, Loc: {}, Type: NewE->getType(), Name, Attrs: nullptr,
5384 OrigRef: dyn_cast<DeclRefExpr>(Val: E->IgnoreImplicit()));
5385 auto *NewDeclStmt = cast<DeclStmt>(Val: AssertSuccess(
5386 R: Actions.ActOnDeclStmt(Decl: Actions.ConvertDeclToDeclGroup(Ptr: NewVar), StartLoc: {}, EndLoc: {})));
5387 Actions.AddInitializerToDecl(dcl: NewDeclStmt->getSingleDecl(), init: NewE, DirectInit: false);
5388 BodyStmts.push_back(Elt: NewDeclStmt);
5389 return NewVar;
5390}
5391
5392/// Create a closure that computes the number of iterations of a loop.
5393///
5394/// \param Actions The Sema object.
5395/// \param LogicalTy Type for the logical iteration number.
5396/// \param Rel Comparison operator of the loop condition.
5397/// \param StartExpr Value of the loop counter at the first iteration.
5398/// \param StopExpr Expression the loop counter is compared against in the loop
5399/// condition. \param StepExpr Amount of increment after each iteration.
5400///
5401/// \return Closure (CapturedStmt) of the distance calculation.
5402static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5403 BinaryOperator::Opcode Rel,
5404 Expr *StartExpr, Expr *StopExpr,
5405 Expr *StepExpr) {
5406 ASTContext &Ctx = Actions.getASTContext();
5407 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(T: LogicalTy);
5408
5409 // Captured regions currently don't support return values, we use an
5410 // out-parameter instead. All inputs are implicit captures.
5411 // TODO: Instead of capturing each DeclRefExpr occurring in
5412 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5413 QualType ResultTy = Ctx.getLValueReferenceType(T: LogicalTy);
5414 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5415 {StringRef(), QualType()}};
5416 Actions.ActOnCapturedRegionStart(Loc: {}, CurScope: nullptr, Kind: CR_Default, Params);
5417
5418 Stmt *Body;
5419 {
5420 Sema::CompoundScopeRAII CompoundScope(Actions);
5421 CapturedDecl *CS = cast<CapturedDecl>(Val: Actions.CurContext);
5422
5423 // Get the LValue expression for the result.
5424 ImplicitParamDecl *DistParam = CS->getParam(i: 0);
5425 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5426 D: DistParam, Ty: LogicalTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
5427
5428 SmallVector<Stmt *, 4> BodyStmts;
5429
5430 // Capture all referenced variable references.
5431 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5432 // CapturedStmt, we could compute them before and capture the result, to be
5433 // used jointly with the LoopVar function.
5434 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, E: StartExpr, Name: ".start");
5435 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, E: StopExpr, Name: ".stop");
5436 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, E: StepExpr, Name: ".step");
5437 auto BuildVarRef = [&](VarDecl *VD) {
5438 return buildDeclRefExpr(S&: Actions, D: VD, Ty: VD->getType(), Loc: {});
5439 };
5440
5441 IntegerLiteral *Zero = IntegerLiteral::Create(
5442 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 0), type: LogicalTy, l: {});
5443 IntegerLiteral *One = IntegerLiteral::Create(
5444 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 1), type: LogicalTy, l: {});
5445 Expr *Dist;
5446 if (Rel == BO_NE) {
5447 // When using a != comparison, the increment can be +1 or -1. This can be
5448 // dynamic at runtime, so we need to check for the direction.
5449 Expr *IsNegStep = AssertSuccess(
5450 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_LT, LHSExpr: BuildVarRef(NewStep), RHSExpr: Zero));
5451
5452 // Positive increment.
5453 Expr *ForwardRange = AssertSuccess(R: Actions.BuildBinOp(
5454 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStop), RHSExpr: BuildVarRef(NewStart)));
5455 ForwardRange = AssertSuccess(
5456 R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: ForwardRange));
5457 Expr *ForwardDist = AssertSuccess(R: Actions.BuildBinOp(
5458 S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: ForwardRange, RHSExpr: BuildVarRef(NewStep)));
5459
5460 // Negative increment.
5461 Expr *BackwardRange = AssertSuccess(R: Actions.BuildBinOp(
5462 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5463 BackwardRange = AssertSuccess(
5464 R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: BackwardRange));
5465 Expr *NegIncAmount = AssertSuccess(
5466 R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: BuildVarRef(NewStep)));
5467 Expr *BackwardDist = AssertSuccess(
5468 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: BackwardRange, RHSExpr: NegIncAmount));
5469
5470 // Use the appropriate case.
5471 Dist = AssertSuccess(R: Actions.ActOnConditionalOp(
5472 QuestionLoc: {}, ColonLoc: {}, CondExpr: IsNegStep, LHSExpr: BackwardDist, RHSExpr: ForwardDist));
5473 } else {
5474 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5475 "Expected one of these relational operators");
5476
5477 // We can derive the direction from any other comparison operator. It is
5478 // non well-formed OpenMP if Step increments/decrements in the other
5479 // directions. Whether at least the first iteration passes the loop
5480 // condition.
5481 Expr *HasAnyIteration = AssertSuccess(R: Actions.BuildBinOp(
5482 S: nullptr, OpLoc: {}, Opc: Rel, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5483
5484 // Compute the range between first and last counter value.
5485 Expr *Range;
5486 if (Rel == BO_GE || Rel == BO_GT)
5487 Range = AssertSuccess(R: Actions.BuildBinOp(
5488 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5489 else
5490 Range = AssertSuccess(R: Actions.BuildBinOp(
5491 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStop), RHSExpr: BuildVarRef(NewStart)));
5492
5493 // Ensure unsigned range space.
5494 Range =
5495 AssertSuccess(R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: Range));
5496
5497 if (Rel == BO_LE || Rel == BO_GE) {
5498 // Add one to the range if the relational operator is inclusive.
5499 Range =
5500 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: Range, RHSExpr: One));
5501 }
5502
5503 // Divide by the absolute step amount. If the range is not a multiple of
5504 // the step size, rounding-up the effective upper bound ensures that the
5505 // last iteration is included.
5506 // Note that the rounding-up may cause an overflow in a temporary that
5507 // could be avoided, but would have occurred in a C-style for-loop as
5508 // well.
5509 Expr *Divisor = BuildVarRef(NewStep);
5510 if (Rel == BO_GE || Rel == BO_GT)
5511 Divisor =
5512 AssertSuccess(R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: Divisor));
5513 Expr *DivisorMinusOne =
5514 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: Divisor, RHSExpr: One));
5515 Expr *RangeRoundUp = AssertSuccess(
5516 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: Range, RHSExpr: DivisorMinusOne));
5517 Dist = AssertSuccess(
5518 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: RangeRoundUp, RHSExpr: Divisor));
5519
5520 // If there is not at least one iteration, the range contains garbage. Fix
5521 // to zero in this case.
5522 Dist = AssertSuccess(
5523 R: Actions.ActOnConditionalOp(QuestionLoc: {}, ColonLoc: {}, CondExpr: HasAnyIteration, LHSExpr: Dist, RHSExpr: Zero));
5524 }
5525
5526 // Assign the result to the out-parameter.
5527 Stmt *ResultAssign = AssertSuccess(R: Actions.BuildBinOp(
5528 S: Actions.getCurScope(), OpLoc: {}, Opc: BO_Assign, LHSExpr: DistRef, RHSExpr: Dist));
5529 BodyStmts.push_back(Elt: ResultAssign);
5530
5531 Body = AssertSuccess(R: Actions.ActOnCompoundStmt(L: {}, R: {}, Elts: BodyStmts, isStmtExpr: false));
5532 }
5533
5534 return cast<CapturedStmt>(
5535 Val: AssertSuccess(R: Actions.ActOnCapturedRegionEnd(S: Body)));
5536}
5537
5538/// Create a closure that computes the loop variable from the logical iteration
5539/// number.
5540///
5541/// \param Actions The Sema object.
5542/// \param LoopVarTy Type for the loop variable used for result value.
5543/// \param LogicalTy Type for the logical iteration number.
5544/// \param StartExpr Value of the loop counter at the first iteration.
5545/// \param Step Amount of increment after each iteration.
5546/// \param Deref Whether the loop variable is a dereference of the loop
5547/// counter variable.
5548///
5549/// \return Closure (CapturedStmt) of the loop value calculation.
5550static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5551 QualType LogicalTy,
5552 DeclRefExpr *StartExpr, Expr *Step,
5553 bool Deref) {
5554 ASTContext &Ctx = Actions.getASTContext();
5555
5556 // Pass the result as an out-parameter. Passing as return value would require
5557 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5558 // invoke a copy constructor.
5559 QualType TargetParamTy = Ctx.getLValueReferenceType(T: LoopVarTy);
5560 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5561 {"Logical", LogicalTy},
5562 {StringRef(), QualType()}};
5563 Actions.ActOnCapturedRegionStart(Loc: {}, CurScope: nullptr, Kind: CR_Default, Params);
5564
5565 // Capture the initial iterator which represents the LoopVar value at the
5566 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5567 // it in every iteration, capture it by value before it is modified.
5568 VarDecl *StartVar = cast<VarDecl>(Val: StartExpr->getDecl());
5569 bool Invalid = Actions.tryCaptureVariable(Var: StartVar, Loc: {},
5570 Kind: TryCaptureKind::ExplicitByVal, EllipsisLoc: {});
5571 (void)Invalid;
5572 assert(!Invalid && "Expecting capture-by-value to work.");
5573
5574 Expr *Body;
5575 {
5576 Sema::CompoundScopeRAII CompoundScope(Actions);
5577 auto *CS = cast<CapturedDecl>(Val: Actions.CurContext);
5578
5579 ImplicitParamDecl *TargetParam = CS->getParam(i: 0);
5580 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5581 D: TargetParam, Ty: LoopVarTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
5582 ImplicitParamDecl *IndvarParam = CS->getParam(i: 1);
5583 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5584 D: IndvarParam, Ty: LogicalTy, VK: VK_LValue, NameInfo: {}, SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
5585
5586 // Capture the Start expression.
5587 CaptureVars Recap(Actions);
5588 Expr *NewStart = AssertSuccess(R: Recap.TransformExpr(E: StartExpr));
5589 Expr *NewStep = AssertSuccess(R: Recap.TransformExpr(E: Step));
5590
5591 Expr *Skip = AssertSuccess(
5592 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Mul, LHSExpr: NewStep, RHSExpr: LogicalRef));
5593 // TODO: Explicitly cast to the iterator's difference_type instead of
5594 // relying on implicit conversion.
5595 Expr *Advanced =
5596 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: NewStart, RHSExpr: Skip));
5597
5598 if (Deref) {
5599 // For range-based for-loops convert the loop counter value to a concrete
5600 // loop variable value by dereferencing the iterator.
5601 Advanced =
5602 AssertSuccess(R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Deref, Input: Advanced));
5603 }
5604
5605 // Assign the result to the output parameter.
5606 Body = AssertSuccess(R: Actions.BuildBinOp(S: Actions.getCurScope(), OpLoc: {},
5607 Opc: BO_Assign, LHSExpr: TargetRef, RHSExpr: Advanced));
5608 }
5609 return cast<CapturedStmt>(
5610 Val: AssertSuccess(R: Actions.ActOnCapturedRegionEnd(S: Body)));
5611}
5612
5613StmtResult SemaOpenMP::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
5614 ASTContext &Ctx = getASTContext();
5615
5616 // Extract the common elements of ForStmt and CXXForRangeStmt:
5617 // Loop variable, repeat condition, increment
5618 Expr *Cond, *Inc;
5619 VarDecl *LIVDecl, *LUVDecl;
5620 if (auto *For = dyn_cast<ForStmt>(Val: AStmt)) {
5621 Stmt *Init = For->getInit();
5622 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Val: Init)) {
5623 // For statement declares loop variable.
5624 LIVDecl = cast<VarDecl>(Val: LCVarDeclStmt->getSingleDecl());
5625 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Val: Init)) {
5626 // For statement reuses variable.
5627 assert(LCAssign->getOpcode() == BO_Assign &&
5628 "init part must be a loop variable assignment");
5629 auto *CounterRef = cast<DeclRefExpr>(Val: LCAssign->getLHS());
5630 LIVDecl = cast<VarDecl>(Val: CounterRef->getDecl());
5631 } else
5632 llvm_unreachable("Cannot determine loop variable");
5633 LUVDecl = LIVDecl;
5634
5635 Cond = For->getCond();
5636 Inc = For->getInc();
5637 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(Val: AStmt)) {
5638 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5639 LIVDecl = cast<VarDecl>(Val: BeginStmt->getSingleDecl());
5640 LUVDecl = RangeFor->getLoopVariable();
5641
5642 Cond = RangeFor->getCond();
5643 Inc = RangeFor->getInc();
5644 } else
5645 llvm_unreachable("unhandled kind of loop");
5646
5647 QualType CounterTy = LIVDecl->getType();
5648 QualType LVTy = LUVDecl->getType();
5649
5650 // Analyze the loop condition.
5651 Expr *LHS, *RHS;
5652 BinaryOperator::Opcode CondRel;
5653 Cond = Cond->IgnoreImplicit();
5654 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Val: Cond)) {
5655 LHS = CondBinExpr->getLHS();
5656 RHS = CondBinExpr->getRHS();
5657 CondRel = CondBinExpr->getOpcode();
5658 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Val: Cond)) {
5659 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5660 LHS = CondCXXOp->getArg(Arg: 0);
5661 RHS = CondCXXOp->getArg(Arg: 1);
5662 switch (CondCXXOp->getOperator()) {
5663 case OO_ExclaimEqual:
5664 CondRel = BO_NE;
5665 break;
5666 case OO_Less:
5667 CondRel = BO_LT;
5668 break;
5669 case OO_LessEqual:
5670 CondRel = BO_LE;
5671 break;
5672 case OO_Greater:
5673 CondRel = BO_GT;
5674 break;
5675 case OO_GreaterEqual:
5676 CondRel = BO_GE;
5677 break;
5678 default:
5679 llvm_unreachable("unexpected iterator operator");
5680 }
5681 } else
5682 llvm_unreachable("unexpected loop condition");
5683
5684 // Normalize such that the loop counter is on the LHS.
5685 if (!isa<DeclRefExpr>(Val: LHS->IgnoreImplicit()) ||
5686 cast<DeclRefExpr>(Val: LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5687 std::swap(a&: LHS, b&: RHS);
5688 CondRel = BinaryOperator::reverseComparisonOp(Opc: CondRel);
5689 }
5690 auto *CounterRef = cast<DeclRefExpr>(Val: LHS->IgnoreImplicit());
5691
5692 // Decide the bit width for the logical iteration counter. By default use the
5693 // unsigned ptrdiff_t integer size (for iterators and pointers).
5694 // TODO: For iterators, use iterator::difference_type,
5695 // std::iterator_traits<>::difference_type or decltype(it - end).
5696 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5697 if (CounterTy->isIntegerType()) {
5698 unsigned BitWidth = Ctx.getIntWidth(T: CounterTy);
5699 LogicalTy = Ctx.getIntTypeForBitwidth(DestWidth: BitWidth, Signed: false);
5700 }
5701
5702 // Analyze the loop increment.
5703 Expr *Step;
5704 if (auto *IncUn = dyn_cast<UnaryOperator>(Val: Inc)) {
5705 int Direction;
5706 switch (IncUn->getOpcode()) {
5707 case UO_PreInc:
5708 case UO_PostInc:
5709 Direction = 1;
5710 break;
5711 case UO_PreDec:
5712 case UO_PostDec:
5713 Direction = -1;
5714 break;
5715 default:
5716 llvm_unreachable("unhandled unary increment operator");
5717 }
5718 Step = IntegerLiteral::Create(
5719 C: Ctx,
5720 V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), Direction, /*isSigned=*/true),
5721 type: LogicalTy, l: {});
5722 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Val: Inc)) {
5723 if (IncBin->getOpcode() == BO_AddAssign) {
5724 Step = IncBin->getRHS();
5725 } else if (IncBin->getOpcode() == BO_SubAssign) {
5726 Step = AssertSuccess(
5727 R: SemaRef.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: IncBin->getRHS()));
5728 } else
5729 llvm_unreachable("unhandled binary increment operator");
5730 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Val: Inc)) {
5731 switch (CondCXXOp->getOperator()) {
5732 case OO_PlusPlus:
5733 Step = IntegerLiteral::Create(
5734 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 1), type: LogicalTy, l: {});
5735 break;
5736 case OO_MinusMinus:
5737 Step = IntegerLiteral::Create(
5738 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), -1), type: LogicalTy, l: {});
5739 break;
5740 case OO_PlusEqual:
5741 Step = CondCXXOp->getArg(Arg: 1);
5742 break;
5743 case OO_MinusEqual:
5744 Step = AssertSuccess(
5745 R: SemaRef.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: CondCXXOp->getArg(Arg: 1)));
5746 break;
5747 default:
5748 llvm_unreachable("unhandled overloaded increment operator");
5749 }
5750 } else
5751 llvm_unreachable("unknown increment expression");
5752
5753 CapturedStmt *DistanceFunc =
5754 buildDistanceFunc(Actions&: SemaRef, LogicalTy, Rel: CondRel, StartExpr: LHS, StopExpr: RHS, StepExpr: Step);
5755 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5756 Actions&: SemaRef, LoopVarTy: LVTy, LogicalTy, StartExpr: CounterRef, Step, Deref: isa<CXXForRangeStmt>(Val: AStmt));
5757 DeclRefExpr *LVRef =
5758 SemaRef.BuildDeclRefExpr(D: LUVDecl, Ty: LUVDecl->getType(), VK: VK_LValue, NameInfo: {},
5759 SS: nullptr, FoundD: nullptr, TemplateKWLoc: {}, TemplateArgs: nullptr);
5760 return OMPCanonicalLoop::create(Ctx: getASTContext(), LoopStmt: AStmt, DistanceFunc,
5761 LoopVarFunc, LoopVarRef: LVRef);
5762}
5763
5764StmtResult SemaOpenMP::ActOnOpenMPLoopnest(Stmt *AStmt) {
5765 // Handle a literal loop.
5766 if (isa<ForStmt>(Val: AStmt) || isa<CXXForRangeStmt>(Val: AStmt))
5767 return ActOnOpenMPCanonicalLoop(AStmt);
5768
5769 // If not a literal loop, it must be the result of a loop transformation.
5770 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(Val: AStmt);
5771 assert(
5772 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5773 "Loop transformation directive expected");
5774 return LoopTransform;
5775}
5776
5777static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
5778 CXXScopeSpec &MapperIdScopeSpec,
5779 const DeclarationNameInfo &MapperId,
5780 QualType Type,
5781 Expr *UnresolvedMapper);
5782
5783/// Perform DFS through the structure/class data members trying to find
5784/// member(s) with user-defined 'default' mapper and generate implicit map
5785/// clauses for such members with the found 'default' mapper.
5786static void
5787processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
5788 SmallVectorImpl<OMPClause *> &Clauses) {
5789 // Check for the default mapper for data members.
5790 if (S.getLangOpts().OpenMP < 50)
5791 return;
5792 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5793 auto *C = dyn_cast<OMPMapClause>(Val: Clauses[Cnt]);
5794 if (!C)
5795 continue;
5796 SmallVector<Expr *, 4> SubExprs;
5797 auto *MI = C->mapperlist_begin();
5798 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5799 ++I, ++MI) {
5800 // Expression is mapped using mapper - skip it.
5801 if (*MI)
5802 continue;
5803 Expr *E = *I;
5804 // Expression is dependent - skip it, build the mapper when it gets
5805 // instantiated.
5806 if (E->isTypeDependent() || E->isValueDependent() ||
5807 E->containsUnexpandedParameterPack())
5808 continue;
5809 // Array section - need to check for the mapping of the array section
5810 // element.
5811 QualType CanonType = E->getType().getCanonicalType();
5812 if (CanonType->isSpecificBuiltinType(K: BuiltinType::ArraySection)) {
5813 const auto *OASE = cast<ArraySectionExpr>(Val: E->IgnoreParenImpCasts());
5814 QualType BaseType =
5815 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
5816 QualType ElemType;
5817 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
5818 ElemType = ATy->getElementType();
5819 else
5820 ElemType = BaseType->getPointeeType();
5821 CanonType = ElemType;
5822 }
5823
5824 // DFS over data members in structures/classes.
5825 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
5826 1, {CanonType, nullptr});
5827 llvm::DenseMap<const Type *, Expr *> Visited;
5828 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
5829 1, {nullptr, 1});
5830 while (!Types.empty()) {
5831 QualType BaseType;
5832 FieldDecl *CurFD;
5833 std::tie(args&: BaseType, args&: CurFD) = Types.pop_back_val();
5834 while (ParentChain.back().second == 0)
5835 ParentChain.pop_back();
5836 --ParentChain.back().second;
5837 if (BaseType.isNull())
5838 continue;
5839 // Only structs/classes are allowed to have mappers.
5840 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
5841 if (!RD)
5842 continue;
5843 auto It = Visited.find(Val: BaseType.getTypePtr());
5844 if (It == Visited.end()) {
5845 // Try to find the associated user-defined mapper.
5846 CXXScopeSpec MapperIdScopeSpec;
5847 DeclarationNameInfo DefaultMapperId;
5848 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
5849 ID: &S.Context.Idents.get(Name: "default")));
5850 DefaultMapperId.setLoc(E->getExprLoc());
5851 ExprResult ER = buildUserDefinedMapperRef(
5852 SemaRef&: S, S: Stack->getCurScope(), MapperIdScopeSpec, MapperId: DefaultMapperId,
5853 Type: BaseType, /*UnresolvedMapper=*/nullptr);
5854 if (ER.isInvalid())
5855 continue;
5856 It = Visited.try_emplace(Key: BaseType.getTypePtr(), Args: ER.get()).first;
5857 }
5858 // Found default mapper.
5859 if (It->second) {
5860 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
5861 VK_LValue, OK_Ordinary, E);
5862 OE->setIsUnique(/*V=*/true);
5863 Expr *BaseExpr = OE;
5864 for (const auto &P : ParentChain) {
5865 if (P.first) {
5866 BaseExpr = S.BuildMemberExpr(
5867 Base: BaseExpr, /*IsArrow=*/false, OpLoc: E->getExprLoc(),
5868 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: P.first,
5869 FoundDecl: DeclAccessPair::make(D: P.first, AS: P.first->getAccess()),
5870 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(),
5871 Ty: P.first->getType(), VK: VK_LValue, OK: OK_Ordinary);
5872 BaseExpr = S.DefaultLvalueConversion(E: BaseExpr).get();
5873 }
5874 }
5875 if (CurFD)
5876 BaseExpr = S.BuildMemberExpr(
5877 Base: BaseExpr, /*IsArrow=*/false, OpLoc: E->getExprLoc(),
5878 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: CurFD,
5879 FoundDecl: DeclAccessPair::make(D: CurFD, AS: CurFD->getAccess()),
5880 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(),
5881 Ty: CurFD->getType(), VK: VK_LValue, OK: OK_Ordinary);
5882 SubExprs.push_back(Elt: BaseExpr);
5883 continue;
5884 }
5885 // Check for the "default" mapper for data members.
5886 bool FirstIter = true;
5887 for (FieldDecl *FD : RD->fields()) {
5888 if (!FD)
5889 continue;
5890 QualType FieldTy = FD->getType();
5891 if (FieldTy.isNull() ||
5892 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
5893 continue;
5894 if (FirstIter) {
5895 FirstIter = false;
5896 ParentChain.emplace_back(Args&: CurFD, Args: 1);
5897 } else {
5898 ++ParentChain.back().second;
5899 }
5900 Types.emplace_back(Args&: FieldTy, Args&: FD);
5901 }
5902 }
5903 }
5904 if (SubExprs.empty())
5905 continue;
5906 CXXScopeSpec MapperIdScopeSpec;
5907 DeclarationNameInfo MapperId;
5908 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
5909 IteratorModifier: nullptr, MapTypeModifiers: C->getMapTypeModifiers(), MapTypeModifiersLoc: C->getMapTypeModifiersLoc(),
5910 MapperIdScopeSpec, MapperId, MapType: C->getMapType(),
5911 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(),
5912 VarList: SubExprs, Locs: OMPVarListLocTy()))
5913 Clauses.push_back(Elt: NewClause);
5914 }
5915}
5916
5917namespace {
5918/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
5919/// call in the associated loop-nest cannot be a 'parallel for'.
5920class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
5921 Sema &SemaRef;
5922
5923public:
5924 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
5925
5926 // Is there a nested OpenMP loop bind(parallel)
5927 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
5928 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5929 if (const auto *C = D->getSingleClause<OMPBindClause>())
5930 if (C->getBindKind() == OMPC_BIND_parallel) {
5931 TeamsLoopCanBeParallelFor = false;
5932 // No need to continue visiting any more
5933 return;
5934 }
5935 }
5936 for (const Stmt *Child : D->children())
5937 if (Child)
5938 Visit(S: Child);
5939 }
5940
5941 void VisitCallExpr(const CallExpr *C) {
5942 // Function calls inhibit parallel loop translation of 'target teams loop'
5943 // unless the assume-no-nested-parallelism flag has been specified.
5944 // OpenMP API runtime library calls do not inhibit parallel loop
5945 // translation, regardless of the assume-no-nested-parallelism.
5946 bool IsOpenMPAPI = false;
5947 auto *FD = dyn_cast_or_null<FunctionDecl>(Val: C->getCalleeDecl());
5948 if (FD) {
5949 std::string Name = FD->getNameInfo().getAsString();
5950 IsOpenMPAPI = Name.find(s: "omp_") == 0;
5951 }
5952 TeamsLoopCanBeParallelFor =
5953 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5954 if (!TeamsLoopCanBeParallelFor)
5955 return;
5956
5957 for (const Stmt *Child : C->children())
5958 if (Child)
5959 Visit(S: Child);
5960 }
5961
5962 void VisitCapturedStmt(const CapturedStmt *S) {
5963 if (!S)
5964 return;
5965 Visit(S: S->getCapturedDecl()->getBody());
5966 }
5967
5968 void VisitStmt(const Stmt *S) {
5969 if (!S)
5970 return;
5971 for (const Stmt *Child : S->children())
5972 if (Child)
5973 Visit(S: Child);
5974 }
5975 explicit TeamsLoopChecker(Sema &SemaRef)
5976 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
5977
5978private:
5979 bool TeamsLoopCanBeParallelFor;
5980};
5981} // namespace
5982
5983static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
5984 TeamsLoopChecker Checker(SemaRef);
5985 Checker.Visit(S: AStmt);
5986 return Checker.teamsLoopCanBeParallelFor();
5987}
5988
5989StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective(
5990 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
5991 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
5992 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
5993 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
5994
5995 StmtResult Res = StmtError();
5996 OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
5997 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
5998
5999 if (const OMPBindClause *BC =
6000 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6001 BindKind = BC->getBindKind();
6002
6003 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6004 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6005
6006 // Setting the enclosing teams or parallel construct for the loop
6007 // directive without bind clause.
6008 // [5.0:129:25-28] If the bind clause is not present on the construct and
6009 // the loop construct is closely nested inside a teams or parallel
6010 // construct, the binding region is the corresponding teams or parallel
6011 // region. If none of those conditions hold, the binding region is not
6012 // defined.
6013 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6014 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6015 getLeafConstructsOrSelf(D: ParentDirective);
6016
6017 if (ParentDirective == OMPD_unknown) {
6018 Diag(DSAStack->getDefaultDSALocation(),
6019 DiagID: diag::err_omp_bind_required_on_loop);
6020 } else if (ParentLeafs.back() == OMPD_parallel) {
6021 BindKind = OMPC_BIND_parallel;
6022 } else if (ParentLeafs.back() == OMPD_teams) {
6023 BindKind = OMPC_BIND_teams;
6024 }
6025
6026 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6027
6028 OMPClause *C =
6029 ActOnOpenMPBindClause(Kind: BindKind, KindLoc: SourceLocation(), StartLoc: SourceLocation(),
6030 LParenLoc: SourceLocation(), EndLoc: SourceLocation());
6031 ClausesWithImplicit.push_back(Elt: C);
6032 }
6033
6034 // Diagnose "loop bind(teams)" with "reduction".
6035 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6036 for (OMPClause *C : Clauses) {
6037 if (C->getClauseKind() == OMPC_reduction)
6038 Diag(DSAStack->getDefaultDSALocation(),
6039 DiagID: diag::err_omp_loop_reduction_clause);
6040 }
6041 }
6042
6043 // First check CancelRegion which is then used in checkNestingOfRegions.
6044 if (checkCancelRegion(SemaRef, CurrentRegion: Kind, CancelRegion, StartLoc) ||
6045 checkNestingOfRegions(SemaRef, DSAStack, CurrentRegion: Kind, CurrentName: DirName, CancelRegion,
6046 BindKind, StartLoc)) {
6047 return StmtError();
6048 }
6049
6050 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6051 if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(DKind: Kind) ||
6052 isOpenMPTargetDataManagementDirective(DKind: Kind)))
6053 Diag(Loc: StartLoc, DiagID: diag::warn_hip_omp_target_directives);
6054
6055 VarsWithInheritedDSAType VarsWithInheritedDSA;
6056 bool ErrorFound = false;
6057 ClausesWithImplicit.append(in_start: Clauses.begin(), in_end: Clauses.end());
6058
6059 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6060 isOpenMPCapturingDirective(DKind: Kind)) {
6061 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6062
6063 // Check default data sharing attributes for referenced variables.
6064 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(Val: AStmt));
6065 int ThisCaptureLevel = getOpenMPCaptureLevels(DKind: Kind);
6066 Stmt *S = AStmt;
6067 while (--ThisCaptureLevel >= 0)
6068 S = cast<CapturedStmt>(Val: S)->getCapturedStmt();
6069 DSAChecker.Visit(S);
6070 if (!isOpenMPTargetDataManagementDirective(DKind: Kind) &&
6071 !isOpenMPTaskingDirective(Kind)) {
6072 // Visit subcaptures to generate implicit clauses for captured vars.
6073 auto *CS = cast<CapturedStmt>(Val: AStmt);
6074 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
6075 getOpenMPCaptureRegions(CaptureRegions, DKind: Kind);
6076 // Ignore outer tasking regions for target directives.
6077 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6078 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
6079 DSAChecker.visitSubCaptures(S: CS);
6080 }
6081 if (DSAChecker.isErrorFound())
6082 return StmtError();
6083 // Generate list of implicitly defined firstprivate variables.
6084 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6085 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6086
6087 SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
6088 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6089 // Get the original location of present modifier from Defaultmap clause.
6090 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6091 for (OMPClause *C : Clauses) {
6092 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(Val: C))
6093 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6094 PresentModifierLocs[DMC->getDefaultmapKind()] =
6095 DMC->getDefaultmapModifierLoc();
6096 }
6097
6098 for (OpenMPDefaultmapClauseKind K :
6099 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6100 Begin: OpenMPDefaultmapClauseKind(), End: OMPC_DEFAULTMAP_unknown)) {
6101 std::fill_n(first: std::back_inserter(x&: ImplicitMapModifiersLoc[K]),
6102 n: ImpInfo.MapModifiers[K].size(), value: PresentModifierLocs[K]);
6103 }
6104 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6105 for (OMPClause *C : Clauses) {
6106 if (auto *IRC = dyn_cast<OMPInReductionClause>(Val: C)) {
6107 for (Expr *E : IRC->taskgroup_descriptors())
6108 if (E)
6109 ImpInfo.Firstprivates.insert(X: E);
6110 }
6111 // OpenMP 5.0, 2.10.1 task Construct
6112 // [detach clause]... The event-handle will be considered as if it was
6113 // specified on a firstprivate clause.
6114 if (auto *DC = dyn_cast<OMPDetachClause>(Val: C))
6115 ImpInfo.Firstprivates.insert(X: DC->getEventHandler());
6116 }
6117 if (!ImpInfo.Firstprivates.empty()) {
6118 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6119 VarList: ImpInfo.Firstprivates.getArrayRef(), StartLoc: SourceLocation(),
6120 LParenLoc: SourceLocation(), EndLoc: SourceLocation())) {
6121 ClausesWithImplicit.push_back(Elt: Implicit);
6122 ErrorFound = cast<OMPFirstprivateClause>(Val: Implicit)->varlist_size() !=
6123 ImpInfo.Firstprivates.size();
6124 } else {
6125 ErrorFound = true;
6126 }
6127 }
6128 if (!ImpInfo.Privates.empty()) {
6129 if (OMPClause *Implicit = ActOnOpenMPPrivateClause(
6130 VarList: ImpInfo.Privates.getArrayRef(), StartLoc: SourceLocation(),
6131 LParenLoc: SourceLocation(), EndLoc: SourceLocation())) {
6132 ClausesWithImplicit.push_back(Elt: Implicit);
6133 ErrorFound = cast<OMPPrivateClause>(Val: Implicit)->varlist_size() !=
6134 ImpInfo.Privates.size();
6135 } else {
6136 ErrorFound = true;
6137 }
6138 }
6139 // OpenMP 5.0 [2.19.7]
6140 // If a list item appears in a reduction, lastprivate or linear
6141 // clause on a combined target construct then it is treated as
6142 // if it also appears in a map clause with a map-type of tofrom
6143 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6144 isOpenMPTargetExecutionDirective(DKind: Kind)) {
6145 SmallVector<Expr *, 4> ImplicitExprs;
6146 for (OMPClause *C : Clauses) {
6147 if (auto *RC = dyn_cast<OMPReductionClause>(Val: C))
6148 for (Expr *E : RC->varlist())
6149 if (!isa<DeclRefExpr>(Val: E->IgnoreParenImpCasts()))
6150 ImplicitExprs.emplace_back(Args&: E);
6151 }
6152 if (!ImplicitExprs.empty()) {
6153 ArrayRef<Expr *> Exprs = ImplicitExprs;
6154 CXXScopeSpec MapperIdScopeSpec;
6155 DeclarationNameInfo MapperId;
6156 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6157 IteratorModifier: nullptr, MapTypeModifiers: OMPC_MAP_MODIFIER_unknown, MapTypeModifiersLoc: SourceLocation(),
6158 MapperIdScopeSpec, MapperId, MapType: OMPC_MAP_tofrom,
6159 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(),
6160 VarList: Exprs, Locs: OMPVarListLocTy(), /*NoDiagnose=*/true))
6161 ClausesWithImplicit.emplace_back(Args&: Implicit);
6162 }
6163 }
6164 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6165 int ClauseKindCnt = -1;
6166 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6167 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6168 ++ClauseKindCnt;
6169 if (ImplicitMap.empty())
6170 continue;
6171 CXXScopeSpec MapperIdScopeSpec;
6172 DeclarationNameInfo MapperId;
6173 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6174 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6175 IteratorModifier: nullptr, MapTypeModifiers: ImpInfo.MapModifiers[I], MapTypeModifiersLoc: ImplicitMapModifiersLoc[I],
6176 MapperIdScopeSpec, MapperId, MapType: K, /*IsMapTypeImplicit=*/true,
6177 MapLoc: SourceLocation(), ColonLoc: SourceLocation(), VarList: ImplicitMap,
6178 Locs: OMPVarListLocTy())) {
6179 ClausesWithImplicit.emplace_back(Args&: Implicit);
6180 ErrorFound |= cast<OMPMapClause>(Val: Implicit)->varlist_size() !=
6181 ImplicitMap.size();
6182 } else {
6183 ErrorFound = true;
6184 }
6185 }
6186 }
6187 // Build expressions for implicit maps of data members with 'default'
6188 // mappers.
6189 if (getLangOpts().OpenMP >= 50)
6190 processImplicitMapsWithDefaultMappers(S&: SemaRef, DSAStack,
6191 Clauses&: ClausesWithImplicit);
6192 }
6193
6194 switch (Kind) {
6195 case OMPD_parallel:
6196 Res = ActOnOpenMPParallelDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6197 EndLoc);
6198 break;
6199 case OMPD_simd:
6200 Res = ActOnOpenMPSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6201 VarsWithImplicitDSA&: VarsWithInheritedDSA);
6202 break;
6203 case OMPD_tile:
6204 Res =
6205 ActOnOpenMPTileDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6206 break;
6207 case OMPD_stripe:
6208 Res = ActOnOpenMPStripeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6209 EndLoc);
6210 break;
6211 case OMPD_unroll:
6212 Res = ActOnOpenMPUnrollDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6213 EndLoc);
6214 break;
6215 case OMPD_reverse:
6216 assert(ClausesWithImplicit.empty() &&
6217 "reverse directive does not support any clauses");
6218 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6219 break;
6220 case OMPD_interchange:
6221 Res = ActOnOpenMPInterchangeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6222 EndLoc);
6223 break;
6224 case OMPD_for:
6225 Res = ActOnOpenMPForDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6226 VarsWithImplicitDSA&: VarsWithInheritedDSA);
6227 break;
6228 case OMPD_for_simd:
6229 Res = ActOnOpenMPForSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6230 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6231 break;
6232 case OMPD_sections:
6233 Res = ActOnOpenMPSectionsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6234 EndLoc);
6235 break;
6236 case OMPD_section:
6237 assert(ClausesWithImplicit.empty() &&
6238 "No clauses are allowed for 'omp section' directive");
6239 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6240 break;
6241 case OMPD_single:
6242 Res = ActOnOpenMPSingleDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6243 EndLoc);
6244 break;
6245 case OMPD_master:
6246 assert(ClausesWithImplicit.empty() &&
6247 "No clauses are allowed for 'omp master' directive");
6248 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6249 break;
6250 case OMPD_masked:
6251 Res = ActOnOpenMPMaskedDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6252 EndLoc);
6253 break;
6254 case OMPD_critical:
6255 Res = ActOnOpenMPCriticalDirective(DirName, Clauses: ClausesWithImplicit, AStmt,
6256 StartLoc, EndLoc);
6257 break;
6258 case OMPD_parallel_for:
6259 Res = ActOnOpenMPParallelForDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6260 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6261 break;
6262 case OMPD_parallel_for_simd:
6263 Res = ActOnOpenMPParallelForSimdDirective(
6264 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6265 break;
6266 case OMPD_scope:
6267 Res =
6268 ActOnOpenMPScopeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6269 break;
6270 case OMPD_parallel_master:
6271 Res = ActOnOpenMPParallelMasterDirective(Clauses: ClausesWithImplicit, AStmt,
6272 StartLoc, EndLoc);
6273 break;
6274 case OMPD_parallel_masked:
6275 Res = ActOnOpenMPParallelMaskedDirective(Clauses: ClausesWithImplicit, AStmt,
6276 StartLoc, EndLoc);
6277 break;
6278 case OMPD_parallel_sections:
6279 Res = ActOnOpenMPParallelSectionsDirective(Clauses: ClausesWithImplicit, AStmt,
6280 StartLoc, EndLoc);
6281 break;
6282 case OMPD_task:
6283 Res =
6284 ActOnOpenMPTaskDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6285 break;
6286 case OMPD_taskyield:
6287 assert(ClausesWithImplicit.empty() &&
6288 "No clauses are allowed for 'omp taskyield' directive");
6289 assert(AStmt == nullptr &&
6290 "No associated statement allowed for 'omp taskyield' directive");
6291 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6292 break;
6293 case OMPD_error:
6294 assert(AStmt == nullptr &&
6295 "No associated statement allowed for 'omp error' directive");
6296 Res = ActOnOpenMPErrorDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6297 break;
6298 case OMPD_barrier:
6299 assert(ClausesWithImplicit.empty() &&
6300 "No clauses are allowed for 'omp barrier' directive");
6301 assert(AStmt == nullptr &&
6302 "No associated statement allowed for 'omp barrier' directive");
6303 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6304 break;
6305 case OMPD_taskwait:
6306 assert(AStmt == nullptr &&
6307 "No associated statement allowed for 'omp taskwait' directive");
6308 Res = ActOnOpenMPTaskwaitDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6309 break;
6310 case OMPD_taskgroup:
6311 Res = ActOnOpenMPTaskgroupDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6312 EndLoc);
6313 break;
6314 case OMPD_flush:
6315 assert(AStmt == nullptr &&
6316 "No associated statement allowed for 'omp flush' directive");
6317 Res = ActOnOpenMPFlushDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6318 break;
6319 case OMPD_depobj:
6320 assert(AStmt == nullptr &&
6321 "No associated statement allowed for 'omp depobj' directive");
6322 Res = ActOnOpenMPDepobjDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6323 break;
6324 case OMPD_scan:
6325 assert(AStmt == nullptr &&
6326 "No associated statement allowed for 'omp scan' directive");
6327 Res = ActOnOpenMPScanDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6328 break;
6329 case OMPD_ordered:
6330 Res = ActOnOpenMPOrderedDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6331 EndLoc);
6332 break;
6333 case OMPD_atomic:
6334 Res = ActOnOpenMPAtomicDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6335 EndLoc);
6336 break;
6337 case OMPD_teams:
6338 Res =
6339 ActOnOpenMPTeamsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6340 break;
6341 case OMPD_target:
6342 Res = ActOnOpenMPTargetDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6343 EndLoc);
6344 break;
6345 case OMPD_target_parallel:
6346 Res = ActOnOpenMPTargetParallelDirective(Clauses: ClausesWithImplicit, AStmt,
6347 StartLoc, EndLoc);
6348 break;
6349 case OMPD_target_parallel_for:
6350 Res = ActOnOpenMPTargetParallelForDirective(
6351 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6352 break;
6353 case OMPD_cancellation_point:
6354 assert(ClausesWithImplicit.empty() &&
6355 "No clauses are allowed for 'omp cancellation point' directive");
6356 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6357 "cancellation point' directive");
6358 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6359 break;
6360 case OMPD_cancel:
6361 assert(AStmt == nullptr &&
6362 "No associated statement allowed for 'omp cancel' directive");
6363 Res = ActOnOpenMPCancelDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc,
6364 CancelRegion);
6365 break;
6366 case OMPD_target_data:
6367 Res = ActOnOpenMPTargetDataDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6368 EndLoc);
6369 break;
6370 case OMPD_target_enter_data:
6371 Res = ActOnOpenMPTargetEnterDataDirective(Clauses: ClausesWithImplicit, StartLoc,
6372 EndLoc, AStmt);
6373 break;
6374 case OMPD_target_exit_data:
6375 Res = ActOnOpenMPTargetExitDataDirective(Clauses: ClausesWithImplicit, StartLoc,
6376 EndLoc, AStmt);
6377 break;
6378 case OMPD_taskloop:
6379 Res = ActOnOpenMPTaskLoopDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6380 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6381 break;
6382 case OMPD_taskloop_simd:
6383 Res = ActOnOpenMPTaskLoopSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6384 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6385 break;
6386 case OMPD_master_taskloop:
6387 Res = ActOnOpenMPMasterTaskLoopDirective(
6388 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6389 break;
6390 case OMPD_masked_taskloop:
6391 Res = ActOnOpenMPMaskedTaskLoopDirective(
6392 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6393 break;
6394 case OMPD_master_taskloop_simd:
6395 Res = ActOnOpenMPMasterTaskLoopSimdDirective(
6396 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6397 break;
6398 case OMPD_masked_taskloop_simd:
6399 Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
6400 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6401 break;
6402 case OMPD_parallel_master_taskloop:
6403 Res = ActOnOpenMPParallelMasterTaskLoopDirective(
6404 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6405 break;
6406 case OMPD_parallel_masked_taskloop:
6407 Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
6408 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6409 break;
6410 case OMPD_parallel_master_taskloop_simd:
6411 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6412 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6413 break;
6414 case OMPD_parallel_masked_taskloop_simd:
6415 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6416 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6417 break;
6418 case OMPD_distribute:
6419 Res = ActOnOpenMPDistributeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6420 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6421 break;
6422 case OMPD_target_update:
6423 Res = ActOnOpenMPTargetUpdateDirective(Clauses: ClausesWithImplicit, StartLoc,
6424 EndLoc, AStmt);
6425 break;
6426 case OMPD_distribute_parallel_for:
6427 Res = ActOnOpenMPDistributeParallelForDirective(
6428 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6429 break;
6430 case OMPD_distribute_parallel_for_simd:
6431 Res = ActOnOpenMPDistributeParallelForSimdDirective(
6432 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6433 break;
6434 case OMPD_distribute_simd:
6435 Res = ActOnOpenMPDistributeSimdDirective(
6436 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6437 break;
6438 case OMPD_target_parallel_for_simd:
6439 Res = ActOnOpenMPTargetParallelForSimdDirective(
6440 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6441 break;
6442 case OMPD_target_simd:
6443 Res = ActOnOpenMPTargetSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6444 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6445 break;
6446 case OMPD_teams_distribute:
6447 Res = ActOnOpenMPTeamsDistributeDirective(
6448 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6449 break;
6450 case OMPD_teams_distribute_simd:
6451 Res = ActOnOpenMPTeamsDistributeSimdDirective(
6452 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6453 break;
6454 case OMPD_teams_distribute_parallel_for_simd:
6455 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6456 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6457 break;
6458 case OMPD_teams_distribute_parallel_for:
6459 Res = ActOnOpenMPTeamsDistributeParallelForDirective(
6460 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6461 break;
6462 case OMPD_target_teams:
6463 Res = ActOnOpenMPTargetTeamsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6464 EndLoc);
6465 break;
6466 case OMPD_target_teams_distribute:
6467 Res = ActOnOpenMPTargetTeamsDistributeDirective(
6468 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6469 break;
6470 case OMPD_target_teams_distribute_parallel_for:
6471 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6472 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6473 break;
6474 case OMPD_target_teams_distribute_parallel_for_simd:
6475 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6476 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6477 break;
6478 case OMPD_target_teams_distribute_simd:
6479 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
6480 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6481 break;
6482 case OMPD_interop:
6483 assert(AStmt == nullptr &&
6484 "No associated statement allowed for 'omp interop' directive");
6485 Res = ActOnOpenMPInteropDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6486 break;
6487 case OMPD_dispatch:
6488 Res = ActOnOpenMPDispatchDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6489 EndLoc);
6490 break;
6491 case OMPD_loop:
6492 Res = ActOnOpenMPGenericLoopDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6493 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6494 break;
6495 case OMPD_teams_loop:
6496 Res = ActOnOpenMPTeamsGenericLoopDirective(
6497 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6498 break;
6499 case OMPD_target_teams_loop:
6500 Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
6501 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6502 break;
6503 case OMPD_parallel_loop:
6504 Res = ActOnOpenMPParallelGenericLoopDirective(
6505 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6506 break;
6507 case OMPD_target_parallel_loop:
6508 Res = ActOnOpenMPTargetParallelGenericLoopDirective(
6509 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6510 break;
6511 case OMPD_declare_target:
6512 case OMPD_end_declare_target:
6513 case OMPD_threadprivate:
6514 case OMPD_allocate:
6515 case OMPD_declare_reduction:
6516 case OMPD_declare_mapper:
6517 case OMPD_declare_simd:
6518 case OMPD_requires:
6519 case OMPD_declare_variant:
6520 case OMPD_begin_declare_variant:
6521 case OMPD_end_declare_variant:
6522 llvm_unreachable("OpenMP Directive is not allowed");
6523 case OMPD_unknown:
6524 default:
6525 llvm_unreachable("Unknown OpenMP directive");
6526 }
6527
6528 ErrorFound = Res.isInvalid() || ErrorFound;
6529
6530 // Check variables in the clauses if default(none) or
6531 // default(firstprivate) was specified.
6532 if (DSAStack->getDefaultDSA() == DSA_none ||
6533 DSAStack->getDefaultDSA() == DSA_private ||
6534 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6535 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6536 for (OMPClause *C : Clauses) {
6537 switch (C->getClauseKind()) {
6538 case OMPC_num_threads:
6539 case OMPC_dist_schedule:
6540 // Do not analyze if no parent teams directive.
6541 if (isOpenMPTeamsDirective(DKind: Kind))
6542 break;
6543 continue;
6544 case OMPC_if:
6545 if (isOpenMPTeamsDirective(DKind: Kind) &&
6546 cast<OMPIfClause>(Val: C)->getNameModifier() != OMPD_target)
6547 break;
6548 if (isOpenMPParallelDirective(DKind: Kind) &&
6549 isOpenMPTaskLoopDirective(DKind: Kind) &&
6550 cast<OMPIfClause>(Val: C)->getNameModifier() != OMPD_parallel)
6551 break;
6552 continue;
6553 case OMPC_schedule:
6554 case OMPC_detach:
6555 break;
6556 case OMPC_grainsize:
6557 case OMPC_num_tasks:
6558 case OMPC_final:
6559 case OMPC_priority:
6560 case OMPC_novariants:
6561 case OMPC_nocontext:
6562 // Do not analyze if no parent parallel directive.
6563 if (isOpenMPParallelDirective(DKind: Kind))
6564 break;
6565 continue;
6566 case OMPC_ordered:
6567 case OMPC_device:
6568 case OMPC_num_teams:
6569 case OMPC_thread_limit:
6570 case OMPC_hint:
6571 case OMPC_collapse:
6572 case OMPC_safelen:
6573 case OMPC_simdlen:
6574 case OMPC_sizes:
6575 case OMPC_default:
6576 case OMPC_proc_bind:
6577 case OMPC_private:
6578 case OMPC_firstprivate:
6579 case OMPC_lastprivate:
6580 case OMPC_shared:
6581 case OMPC_reduction:
6582 case OMPC_task_reduction:
6583 case OMPC_in_reduction:
6584 case OMPC_linear:
6585 case OMPC_aligned:
6586 case OMPC_copyin:
6587 case OMPC_copyprivate:
6588 case OMPC_nowait:
6589 case OMPC_untied:
6590 case OMPC_mergeable:
6591 case OMPC_allocate:
6592 case OMPC_read:
6593 case OMPC_write:
6594 case OMPC_update:
6595 case OMPC_capture:
6596 case OMPC_compare:
6597 case OMPC_seq_cst:
6598 case OMPC_acq_rel:
6599 case OMPC_acquire:
6600 case OMPC_release:
6601 case OMPC_relaxed:
6602 case OMPC_depend:
6603 case OMPC_threads:
6604 case OMPC_simd:
6605 case OMPC_map:
6606 case OMPC_nogroup:
6607 case OMPC_defaultmap:
6608 case OMPC_to:
6609 case OMPC_from:
6610 case OMPC_use_device_ptr:
6611 case OMPC_use_device_addr:
6612 case OMPC_is_device_ptr:
6613 case OMPC_has_device_addr:
6614 case OMPC_nontemporal:
6615 case OMPC_order:
6616 case OMPC_destroy:
6617 case OMPC_inclusive:
6618 case OMPC_exclusive:
6619 case OMPC_uses_allocators:
6620 case OMPC_affinity:
6621 case OMPC_bind:
6622 case OMPC_filter:
6623 continue;
6624 case OMPC_allocator:
6625 case OMPC_flush:
6626 case OMPC_depobj:
6627 case OMPC_threadprivate:
6628 case OMPC_uniform:
6629 case OMPC_unknown:
6630 case OMPC_unified_address:
6631 case OMPC_unified_shared_memory:
6632 case OMPC_reverse_offload:
6633 case OMPC_dynamic_allocators:
6634 case OMPC_atomic_default_mem_order:
6635 case OMPC_self_maps:
6636 case OMPC_device_type:
6637 case OMPC_match:
6638 case OMPC_when:
6639 case OMPC_at:
6640 case OMPC_severity:
6641 case OMPC_message:
6642 default:
6643 llvm_unreachable("Unexpected clause");
6644 }
6645 for (Stmt *CC : C->children()) {
6646 if (CC)
6647 DSAChecker.Visit(S: CC);
6648 }
6649 }
6650 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6651 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6652 }
6653 for (const auto &P : VarsWithInheritedDSA) {
6654 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(Val: P.getFirst()))
6655 continue;
6656 ErrorFound = true;
6657 if (DSAStack->getDefaultDSA() == DSA_none ||
6658 DSAStack->getDefaultDSA() == DSA_private ||
6659 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6660 Diag(Loc: P.second->getExprLoc(), DiagID: diag::err_omp_no_dsa_for_variable)
6661 << P.first << P.second->getSourceRange();
6662 Diag(DSAStack->getDefaultDSALocation(), DiagID: diag::note_omp_default_dsa_none);
6663 } else if (getLangOpts().OpenMP >= 50) {
6664 Diag(Loc: P.second->getExprLoc(),
6665 DiagID: diag::err_omp_defaultmap_no_attr_for_variable)
6666 << P.first << P.second->getSourceRange();
6667 Diag(DSAStack->getDefaultDSALocation(),
6668 DiagID: diag::note_omp_defaultmap_attr_none);
6669 }
6670 }
6671
6672 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6673 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(D: Kind)) {
6674 if (isAllowedClauseForDirective(D, C: OMPC_if, Version: getLangOpts().OpenMP))
6675 AllowedNameModifiers.push_back(Elt: D);
6676 }
6677 if (!AllowedNameModifiers.empty())
6678 ErrorFound = checkIfClauses(S&: SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6679 ErrorFound;
6680
6681 if (ErrorFound)
6682 return StmtError();
6683
6684 if (!SemaRef.CurContext->isDependentContext() &&
6685 isOpenMPTargetExecutionDirective(DKind: Kind) &&
6686 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6687 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6688 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6689 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6690 // Register target to DSA Stack.
6691 DSAStack->addTargetDirLocation(LocStart: StartLoc);
6692 }
6693
6694 return Res;
6695}
6696
6697SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareSimdDirective(
6698 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6699 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6700 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6701 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6702 assert(Aligneds.size() == Alignments.size());
6703 assert(Linears.size() == LinModifiers.size());
6704 assert(Linears.size() == Steps.size());
6705 if (!DG || DG.get().isNull())
6706 return DeclGroupPtrTy();
6707
6708 const int SimdId = 0;
6709 if (!DG.get().isSingleDecl()) {
6710 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_single_decl_in_declare_simd_variant)
6711 << SimdId;
6712 return DG;
6713 }
6714 Decl *ADecl = DG.get().getSingleDecl();
6715 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: ADecl))
6716 ADecl = FTD->getTemplatedDecl();
6717
6718 auto *FD = dyn_cast<FunctionDecl>(Val: ADecl);
6719 if (!FD) {
6720 Diag(Loc: ADecl->getLocation(), DiagID: diag::err_omp_function_expected) << SimdId;
6721 return DeclGroupPtrTy();
6722 }
6723
6724 // OpenMP [2.8.2, declare simd construct, Description]
6725 // The parameter of the simdlen clause must be a constant positive integer
6726 // expression.
6727 ExprResult SL;
6728 if (Simdlen)
6729 SL = VerifyPositiveIntegerConstantInClause(Op: Simdlen, CKind: OMPC_simdlen);
6730 // OpenMP [2.8.2, declare simd construct, Description]
6731 // The special this pointer can be used as if was one of the arguments to the
6732 // function in any of the linear, aligned, or uniform clauses.
6733 // The uniform clause declares one or more arguments to have an invariant
6734 // value for all concurrent invocations of the function in the execution of a
6735 // single SIMD loop.
6736 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6737 const Expr *UniformedLinearThis = nullptr;
6738 for (const Expr *E : Uniforms) {
6739 E = E->IgnoreParenImpCasts();
6740 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
6741 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl()))
6742 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6743 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
6744 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6745 UniformedArgs.try_emplace(Key: PVD->getCanonicalDecl(), Args&: E);
6746 continue;
6747 }
6748 if (isa<CXXThisExpr>(Val: E)) {
6749 UniformedLinearThis = E;
6750 continue;
6751 }
6752 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
6753 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
6754 }
6755 // OpenMP [2.8.2, declare simd construct, Description]
6756 // The aligned clause declares that the object to which each list item points
6757 // is aligned to the number of bytes expressed in the optional parameter of
6758 // the aligned clause.
6759 // The special this pointer can be used as if was one of the arguments to the
6760 // function in any of the linear, aligned, or uniform clauses.
6761 // The type of list items appearing in the aligned clause must be array,
6762 // pointer, reference to array, or reference to pointer.
6763 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6764 const Expr *AlignedThis = nullptr;
6765 for (const Expr *E : Aligneds) {
6766 E = E->IgnoreParenImpCasts();
6767 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
6768 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
6769 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6770 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6771 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
6772 ->getCanonicalDecl() == CanonPVD) {
6773 // OpenMP [2.8.1, simd construct, Restrictions]
6774 // A list-item cannot appear in more than one aligned clause.
6775 auto [It, Inserted] = AlignedArgs.try_emplace(Key: CanonPVD, Args&: E);
6776 if (!Inserted) {
6777 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_used_in_clause_twice)
6778 << 1 << getOpenMPClauseNameForDiag(C: OMPC_aligned)
6779 << E->getSourceRange();
6780 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
6781 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
6782 continue;
6783 }
6784 QualType QTy = PVD->getType()
6785 .getNonReferenceType()
6786 .getUnqualifiedType()
6787 .getCanonicalType();
6788 const Type *Ty = QTy.getTypePtrOrNull();
6789 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6790 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_aligned_expected_array_or_ptr)
6791 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6792 Diag(Loc: PVD->getLocation(), DiagID: diag::note_previous_decl) << PVD;
6793 }
6794 continue;
6795 }
6796 }
6797 if (isa<CXXThisExpr>(Val: E)) {
6798 if (AlignedThis) {
6799 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_used_in_clause_twice)
6800 << 2 << getOpenMPClauseNameForDiag(C: OMPC_aligned)
6801 << E->getSourceRange();
6802 Diag(Loc: AlignedThis->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
6803 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
6804 }
6805 AlignedThis = E;
6806 continue;
6807 }
6808 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
6809 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
6810 }
6811 // The optional parameter of the aligned clause, alignment, must be a constant
6812 // positive integer expression. If no optional parameter is specified,
6813 // implementation-defined default alignments for SIMD instructions on the
6814 // target platforms are assumed.
6815 SmallVector<const Expr *, 4> NewAligns;
6816 for (Expr *E : Alignments) {
6817 ExprResult Align;
6818 if (E)
6819 Align = VerifyPositiveIntegerConstantInClause(Op: E, CKind: OMPC_aligned);
6820 NewAligns.push_back(Elt: Align.get());
6821 }
6822 // OpenMP [2.8.2, declare simd construct, Description]
6823 // The linear clause declares one or more list items to be private to a SIMD
6824 // lane and to have a linear relationship with respect to the iteration space
6825 // of a loop.
6826 // The special this pointer can be used as if was one of the arguments to the
6827 // function in any of the linear, aligned, or uniform clauses.
6828 // When a linear-step expression is specified in a linear clause it must be
6829 // either a constant integer expression or an integer-typed parameter that is
6830 // specified in a uniform clause on the directive.
6831 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6832 const bool IsUniformedThis = UniformedLinearThis != nullptr;
6833 auto MI = LinModifiers.begin();
6834 for (const Expr *E : Linears) {
6835 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
6836 ++MI;
6837 E = E->IgnoreParenImpCasts();
6838 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
6839 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
6840 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6841 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6842 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
6843 ->getCanonicalDecl() == CanonPVD) {
6844 // OpenMP [2.15.3.7, linear Clause, Restrictions]
6845 // A list-item cannot appear in more than one linear clause.
6846 if (auto It = LinearArgs.find(Val: CanonPVD); It != LinearArgs.end()) {
6847 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
6848 << getOpenMPClauseNameForDiag(C: OMPC_linear)
6849 << getOpenMPClauseNameForDiag(C: OMPC_linear)
6850 << E->getSourceRange();
6851 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
6852 << getOpenMPClauseNameForDiag(C: OMPC_linear);
6853 continue;
6854 }
6855 // Each argument can appear in at most one uniform or linear clause.
6856 if (auto It = UniformedArgs.find(Val: CanonPVD);
6857 It != UniformedArgs.end()) {
6858 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
6859 << getOpenMPClauseNameForDiag(C: OMPC_linear)
6860 << getOpenMPClauseNameForDiag(C: OMPC_uniform)
6861 << E->getSourceRange();
6862 Diag(Loc: It->second->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
6863 << getOpenMPClauseNameForDiag(C: OMPC_uniform);
6864 continue;
6865 }
6866 LinearArgs[CanonPVD] = E;
6867 if (E->isValueDependent() || E->isTypeDependent() ||
6868 E->isInstantiationDependent() ||
6869 E->containsUnexpandedParameterPack())
6870 continue;
6871 (void)CheckOpenMPLinearDecl(D: CanonPVD, ELoc: E->getExprLoc(), LinKind,
6872 Type: PVD->getOriginalType(),
6873 /*IsDeclareSimd=*/true);
6874 continue;
6875 }
6876 }
6877 if (isa<CXXThisExpr>(Val: E)) {
6878 if (UniformedLinearThis) {
6879 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
6880 << getOpenMPClauseNameForDiag(C: OMPC_linear)
6881 << getOpenMPClauseNameForDiag(C: IsUniformedThis ? OMPC_uniform
6882 : OMPC_linear)
6883 << E->getSourceRange();
6884 Diag(Loc: UniformedLinearThis->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
6885 << getOpenMPClauseNameForDiag(C: IsUniformedThis ? OMPC_uniform
6886 : OMPC_linear);
6887 continue;
6888 }
6889 UniformedLinearThis = E;
6890 if (E->isValueDependent() || E->isTypeDependent() ||
6891 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
6892 continue;
6893 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, ELoc: E->getExprLoc(), LinKind,
6894 Type: E->getType(), /*IsDeclareSimd=*/true);
6895 continue;
6896 }
6897 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause)
6898 << FD->getDeclName() << (isa<CXXMethodDecl>(Val: ADecl) ? 1 : 0);
6899 }
6900 Expr *Step = nullptr;
6901 Expr *NewStep = nullptr;
6902 SmallVector<Expr *, 4> NewSteps;
6903 for (Expr *E : Steps) {
6904 // Skip the same step expression, it was checked already.
6905 if (Step == E || !E) {
6906 NewSteps.push_back(Elt: E ? NewStep : nullptr);
6907 continue;
6908 }
6909 Step = E;
6910 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: Step))
6911 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
6912 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6913 if (UniformedArgs.count(Val: CanonPVD) == 0) {
6914 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_expected_uniform_param)
6915 << Step->getSourceRange();
6916 } else if (E->isValueDependent() || E->isTypeDependent() ||
6917 E->isInstantiationDependent() ||
6918 E->containsUnexpandedParameterPack() ||
6919 CanonPVD->getType()->hasIntegerRepresentation()) {
6920 NewSteps.push_back(Elt: Step);
6921 } else {
6922 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_expected_int_param)
6923 << Step->getSourceRange();
6924 }
6925 continue;
6926 }
6927 NewStep = Step;
6928 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
6929 !Step->isInstantiationDependent() &&
6930 !Step->containsUnexpandedParameterPack()) {
6931 NewStep = PerformOpenMPImplicitIntegerConversion(OpLoc: Step->getExprLoc(), Op: Step)
6932 .get();
6933 if (NewStep)
6934 NewStep = SemaRef
6935 .VerifyIntegerConstantExpression(
6936 E: NewStep, /*FIXME*/ CanFold: AllowFoldKind::Allow)
6937 .get();
6938 }
6939 NewSteps.push_back(Elt: NewStep);
6940 }
6941 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
6942 Ctx&: getASTContext(), BranchState: BS, Simdlen: SL.get(), Uniforms: const_cast<Expr **>(Uniforms.data()),
6943 UniformsSize: Uniforms.size(), Aligneds: const_cast<Expr **>(Aligneds.data()), AlignedsSize: Aligneds.size(),
6944 Alignments: const_cast<Expr **>(NewAligns.data()), AlignmentsSize: NewAligns.size(),
6945 Linears: const_cast<Expr **>(Linears.data()), LinearsSize: Linears.size(),
6946 Modifiers: const_cast<unsigned *>(LinModifiers.data()), ModifiersSize: LinModifiers.size(),
6947 Steps: NewSteps.data(), StepsSize: NewSteps.size(), Range: SR);
6948 ADecl->addAttr(A: NewAttr);
6949 return DG;
6950}
6951
6952StmtResult SemaOpenMP::ActOnOpenMPInformationalDirective(
6953 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6954 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
6955 SourceLocation EndLoc) {
6956 assert(isOpenMPInformationalDirective(Kind) &&
6957 "Unexpected directive category");
6958
6959 StmtResult Res = StmtError();
6960
6961 switch (Kind) {
6962 case OMPD_assume:
6963 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
6964 break;
6965 default:
6966 llvm_unreachable("Unknown OpenMP directive");
6967 }
6968
6969 return Res;
6970}
6971
6972static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
6973 QualType NewType) {
6974 assert(NewType->isFunctionProtoType() &&
6975 "Expected function type with prototype.");
6976 assert(FD->getType()->isFunctionNoProtoType() &&
6977 "Expected function with type with no prototype.");
6978 assert(FDWithProto->getType()->isFunctionProtoType() &&
6979 "Expected function with prototype.");
6980 // Synthesize parameters with the same types.
6981 FD->setType(NewType);
6982 SmallVector<ParmVarDecl *, 16> Params;
6983 for (const ParmVarDecl *P : FDWithProto->parameters()) {
6984 auto *Param = ParmVarDecl::Create(C&: S.getASTContext(), DC: FD, StartLoc: SourceLocation(),
6985 IdLoc: SourceLocation(), Id: nullptr, T: P->getType(),
6986 /*TInfo=*/nullptr, S: SC_None, DefArg: nullptr);
6987 Param->setScopeInfo(scopeDepth: 0, parameterIndex: Params.size());
6988 Param->setImplicit();
6989 Params.push_back(Elt: Param);
6990 }
6991
6992 FD->setParams(Params);
6993}
6994
6995void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
6996 if (D->isInvalidDecl())
6997 return;
6998 FunctionDecl *FD = nullptr;
6999 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(Val: D))
7000 FD = UTemplDecl->getTemplatedDecl();
7001 else
7002 FD = cast<FunctionDecl>(Val: D);
7003 assert(FD && "Expected a function declaration!");
7004
7005 // If we are instantiating templates we do *not* apply scoped assumptions but
7006 // only global ones. We apply scoped assumption to the template definition
7007 // though.
7008 if (!SemaRef.inTemplateInstantiation()) {
7009 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7010 FD->addAttr(A: AA);
7011 }
7012 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7013 FD->addAttr(A: AA);
7014}
7015
7016SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7017 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7018
7019void SemaOpenMP::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7020 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7021 SmallVectorImpl<FunctionDecl *> &Bases) {
7022 if (!D.getIdentifier())
7023 return;
7024
7025 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7026
7027 // Template specialization is an extension, check if we do it.
7028 bool IsTemplated = !TemplateParamLists.empty();
7029 if (IsTemplated &&
7030 !DVScope.TI->isExtensionActive(
7031 TP: llvm::omp::TraitProperty::implementation_extension_allow_templates))
7032 return;
7033
7034 const IdentifierInfo *BaseII = D.getIdentifier();
7035 LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(),
7036 Sema::LookupOrdinaryName);
7037 SemaRef.LookupParsedName(R&: Lookup, S, SS: &D.getCXXScopeSpec(),
7038 /*ObjectType=*/QualType());
7039
7040 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7041 QualType FType = TInfo->getType();
7042
7043 bool IsConstexpr =
7044 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7045 bool IsConsteval =
7046 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7047
7048 for (auto *Candidate : Lookup) {
7049 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7050 FunctionDecl *UDecl = nullptr;
7051 if (IsTemplated && isa<FunctionTemplateDecl>(Val: CandidateDecl)) {
7052 auto *FTD = cast<FunctionTemplateDecl>(Val: CandidateDecl);
7053 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7054 UDecl = FTD->getTemplatedDecl();
7055 } else if (!IsTemplated)
7056 UDecl = dyn_cast<FunctionDecl>(Val: CandidateDecl);
7057 if (!UDecl)
7058 continue;
7059
7060 // Don't specialize constexpr/consteval functions with
7061 // non-constexpr/consteval functions.
7062 if (UDecl->isConstexpr() && !IsConstexpr)
7063 continue;
7064 if (UDecl->isConsteval() && !IsConsteval)
7065 continue;
7066
7067 QualType UDeclTy = UDecl->getType();
7068 if (!UDeclTy->isDependentType()) {
7069 QualType NewType = getASTContext().mergeFunctionTypes(
7070 FType, UDeclTy, /*OfBlockPointer=*/false,
7071 /*Unqualified=*/false, /*AllowCXX=*/true);
7072 if (NewType.isNull())
7073 continue;
7074 }
7075
7076 // Found a base!
7077 Bases.push_back(Elt: UDecl);
7078 }
7079
7080 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7081 TP: llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7082 // If no base was found we create a declaration that we use as base.
7083 if (Bases.empty() && UseImplicitBase) {
7084 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7085 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParameterLists: TemplateParamLists);
7086 BaseD->setImplicit(true);
7087 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(Val: BaseD))
7088 Bases.push_back(Elt: BaseTemplD->getTemplatedDecl());
7089 else
7090 Bases.push_back(Elt: cast<FunctionDecl>(Val: BaseD));
7091 }
7092
7093 std::string MangledName;
7094 MangledName += D.getIdentifier()->getName();
7095 MangledName += getOpenMPVariantManglingSeparatorStr();
7096 MangledName += DVScope.NameSuffix;
7097 IdentifierInfo &VariantII = getASTContext().Idents.get(Name: MangledName);
7098
7099 VariantII.setMangledOpenMPVariantName(true);
7100 D.SetIdentifier(Id: &VariantII, IdLoc: D.getBeginLoc());
7101}
7102
7103void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7104 Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
7105 // Do not mark function as is used to prevent its emission if this is the
7106 // only place where it is used.
7107 EnterExpressionEvaluationContext Unevaluated(
7108 SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);
7109
7110 FunctionDecl *FD = nullptr;
7111 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(Val: D))
7112 FD = UTemplDecl->getTemplatedDecl();
7113 else
7114 FD = cast<FunctionDecl>(Val: D);
7115 auto *VariantFuncRef = DeclRefExpr::Create(
7116 Context: getASTContext(), QualifierLoc: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), D: FD,
7117 /*RefersToEnclosingVariableOrCapture=*/false,
7118 /*NameLoc=*/FD->getLocation(), T: FD->getType(), VK: ExprValueKind::VK_PRValue);
7119
7120 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7121 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7122 Ctx&: getASTContext(), VariantFuncRef, TraitInfos: DVScope.TI,
7123 /*NothingArgs=*/AdjustArgsNothing: nullptr, /*NothingArgsSize=*/AdjustArgsNothingSize: 0,
7124 /*NeedDevicePtrArgs=*/AdjustArgsNeedDevicePtr: nullptr, /*NeedDevicePtrArgsSize=*/AdjustArgsNeedDevicePtrSize: 0,
7125 /*NeedDeviceAddrArgs=*/AdjustArgsNeedDeviceAddr: nullptr, /*NeedDeviceAddrArgsSize=*/AdjustArgsNeedDeviceAddrSize: 0,
7126 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7127 for (FunctionDecl *BaseFD : Bases)
7128 BaseFD->addAttr(A: OMPDeclareVariantA);
7129}
7130
7131ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
7132 SourceLocation LParenLoc,
7133 MultiExprArg ArgExprs,
7134 SourceLocation RParenLoc,
7135 Expr *ExecConfig) {
7136 // The common case is a regular call we do not want to specialize at all. Try
7137 // to make that case fast by bailing early.
7138 CallExpr *CE = dyn_cast<CallExpr>(Val: Call.get());
7139 if (!CE)
7140 return Call;
7141
7142 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7143 if (!CalleeFnDecl)
7144 return Call;
7145
7146 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7147 CalleeFnDecl->getIdentifier() &&
7148 CalleeFnDecl->getName().starts_with_insensitive(Prefix: "omp_")) {
7149 // checking for any calls inside an Order region
7150 if (Scope && Scope->isOpenMPOrderClauseScope())
7151 Diag(Loc: LParenLoc, DiagID: diag::err_omp_unexpected_call_to_omp_runtime_api);
7152 }
7153
7154 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7155 return Call;
7156
7157 ASTContext &Context = getASTContext();
7158 std::function<void(StringRef)> DiagUnknownTrait = [this,
7159 CE](StringRef ISATrait) {
7160 // TODO Track the selector locations in a way that is accessible here to
7161 // improve the diagnostic location.
7162 Diag(Loc: CE->getBeginLoc(), DiagID: diag::warn_unknown_declare_variant_isa_trait)
7163 << ISATrait;
7164 };
7165 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7166 SemaRef.getCurFunctionDecl(),
7167 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7168
7169 QualType CalleeFnType = CalleeFnDecl->getType();
7170
7171 SmallVector<Expr *, 4> Exprs;
7172 SmallVector<VariantMatchInfo, 4> VMIs;
7173 while (CalleeFnDecl) {
7174 for (OMPDeclareVariantAttr *A :
7175 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7176 Expr *VariantRef = A->getVariantFuncRef();
7177
7178 VariantMatchInfo VMI;
7179 OMPTraitInfo &TI = A->getTraitInfo();
7180 TI.getAsVariantMatchInfo(ASTCtx&: Context, VMI);
7181 if (!isVariantApplicableInContext(VMI, Ctx: OMPCtx,
7182 /*DeviceSetOnly=*/DeviceOrImplementationSetOnly: false))
7183 continue;
7184
7185 VMIs.push_back(Elt: VMI);
7186 Exprs.push_back(Elt: VariantRef);
7187 }
7188
7189 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7190 }
7191
7192 ExprResult NewCall;
7193 do {
7194 int BestIdx = getBestVariantMatchForContext(VMIs, Ctx: OMPCtx);
7195 if (BestIdx < 0)
7196 return Call;
7197 Expr *BestExpr = cast<DeclRefExpr>(Val: Exprs[BestIdx]);
7198 Decl *BestDecl = cast<DeclRefExpr>(Val: BestExpr)->getDecl();
7199
7200 {
7201 // Try to build a (member) call expression for the current best applicable
7202 // variant expression. We allow this to fail in which case we continue
7203 // with the next best variant expression. The fail case is part of the
7204 // implementation defined behavior in the OpenMP standard when it talks
7205 // about what differences in the function prototypes: "Any differences
7206 // that the specific OpenMP context requires in the prototype of the
7207 // variant from the base function prototype are implementation defined."
7208 // This wording is there to allow the specialized variant to have a
7209 // different type than the base function. This is intended and OK but if
7210 // we cannot create a call the difference is not in the "implementation
7211 // defined range" we allow.
7212 Sema::TentativeAnalysisScope Trap(SemaRef);
7213
7214 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(Val: BestDecl)) {
7215 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(Val: CE);
7216 BestExpr = MemberExpr::CreateImplicit(
7217 C: Context, Base: MemberCall->getImplicitObjectArgument(),
7218 /*IsArrow=*/false, MemberDecl: SpecializedMethod, T: Context.BoundMemberTy,
7219 VK: MemberCall->getValueKind(), OK: MemberCall->getObjectKind());
7220 }
7221 NewCall = SemaRef.BuildCallExpr(S: Scope, Fn: BestExpr, LParenLoc, ArgExprs,
7222 RParenLoc, ExecConfig);
7223 if (NewCall.isUsable()) {
7224 if (CallExpr *NCE = dyn_cast<CallExpr>(Val: NewCall.get())) {
7225 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7226 QualType NewType = getASTContext().mergeFunctionTypes(
7227 CalleeFnType, NewCalleeFnDecl->getType(),
7228 /*OfBlockPointer=*/false,
7229 /*Unqualified=*/false, /*AllowCXX=*/true);
7230 if (!NewType.isNull())
7231 break;
7232 // Don't use the call if the function type was not compatible.
7233 NewCall = nullptr;
7234 }
7235 }
7236 }
7237
7238 VMIs.erase(CI: VMIs.begin() + BestIdx);
7239 Exprs.erase(CI: Exprs.begin() + BestIdx);
7240 } while (!VMIs.empty());
7241
7242 if (!NewCall.isUsable())
7243 return Call;
7244 return PseudoObjectExpr::Create(Context: getASTContext(), syntactic: CE, semantic: {NewCall.get()}, resultIndex: 0);
7245}
7246
7247std::optional<std::pair<FunctionDecl *, Expr *>>
7248SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG,
7249 Expr *VariantRef,
7250 OMPTraitInfo &TI,
7251 unsigned NumAppendArgs,
7252 SourceRange SR) {
7253 ASTContext &Context = getASTContext();
7254 if (!DG || DG.get().isNull())
7255 return std::nullopt;
7256
7257 const int VariantId = 1;
7258 // Must be applied only to single decl.
7259 if (!DG.get().isSingleDecl()) {
7260 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_single_decl_in_declare_simd_variant)
7261 << VariantId << SR;
7262 return std::nullopt;
7263 }
7264 Decl *ADecl = DG.get().getSingleDecl();
7265 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: ADecl))
7266 ADecl = FTD->getTemplatedDecl();
7267
7268 // Decl must be a function.
7269 auto *FD = dyn_cast<FunctionDecl>(Val: ADecl);
7270 if (!FD) {
7271 Diag(Loc: ADecl->getLocation(), DiagID: diag::err_omp_function_expected)
7272 << VariantId << SR;
7273 return std::nullopt;
7274 }
7275
7276 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7277 // The 'target' attribute needs to be separately checked because it does
7278 // not always signify a multiversion function declaration.
7279 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7280 };
7281 // OpenMP is not compatible with multiversion function attributes.
7282 if (HasMultiVersionAttributes(FD)) {
7283 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_incompat_attributes)
7284 << SR;
7285 return std::nullopt;
7286 }
7287
7288 // Allow #pragma omp declare variant only if the function is not used.
7289 if (FD->isUsed(CheckUsedAttr: false))
7290 Diag(Loc: SR.getBegin(), DiagID: diag::warn_omp_declare_variant_after_used)
7291 << FD->getLocation();
7292
7293 // Check if the function was emitted already.
7294 const FunctionDecl *Definition;
7295 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7296 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(D: Definition)))
7297 Diag(Loc: SR.getBegin(), DiagID: diag::warn_omp_declare_variant_after_emitted)
7298 << FD->getLocation();
7299
7300 // The VariantRef must point to function.
7301 if (!VariantRef) {
7302 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_function_expected) << VariantId;
7303 return std::nullopt;
7304 }
7305
7306 auto ShouldDelayChecks = [](Expr *&E, bool) {
7307 return E && (E->isTypeDependent() || E->isValueDependent() ||
7308 E->containsUnexpandedParameterPack() ||
7309 E->isInstantiationDependent());
7310 };
7311 // Do not check templates, wait until instantiation.
7312 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7313 TI.anyScoreOrCondition(Cond: ShouldDelayChecks))
7314 return std::make_pair(x&: FD, y&: VariantRef);
7315
7316 // Deal with non-constant score and user condition expressions.
7317 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7318 bool IsScore) -> bool {
7319 if (!E || E->isIntegerConstantExpr(Ctx: getASTContext()))
7320 return false;
7321
7322 if (IsScore) {
7323 // We warn on non-constant scores and pretend they were not present.
7324 Diag(Loc: E->getExprLoc(), DiagID: diag::warn_omp_declare_variant_score_not_constant)
7325 << E;
7326 E = nullptr;
7327 } else {
7328 // We could replace a non-constant user condition with "false" but we
7329 // will soon need to handle these anyway for the dynamic version of
7330 // OpenMP context selectors.
7331 Diag(Loc: E->getExprLoc(),
7332 DiagID: diag::err_omp_declare_variant_user_condition_not_constant)
7333 << E;
7334 }
7335 return true;
7336 };
7337 if (TI.anyScoreOrCondition(Cond: HandleNonConstantScoresAndConditions))
7338 return std::nullopt;
7339
7340 QualType AdjustedFnType = FD->getType();
7341 if (NumAppendArgs) {
7342 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7343 if (!PTy) {
7344 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_prototype_required)
7345 << SR;
7346 return std::nullopt;
7347 }
7348 // Adjust the function type to account for an extra omp_interop_t for each
7349 // specified in the append_args clause.
7350 const TypeDecl *TD = nullptr;
7351 LookupResult Result(SemaRef, &Context.Idents.get(Name: "omp_interop_t"),
7352 SR.getBegin(), Sema::LookupOrdinaryName);
7353 if (SemaRef.LookupName(R&: Result, S: SemaRef.getCurScope())) {
7354 NamedDecl *ND = Result.getFoundDecl();
7355 TD = dyn_cast_or_null<TypeDecl>(Val: ND);
7356 }
7357 if (!TD) {
7358 Diag(Loc: SR.getBegin(), DiagID: diag::err_omp_interop_type_not_found) << SR;
7359 return std::nullopt;
7360 }
7361 QualType InteropType = Context.getTypeDeclType(Decl: TD);
7362 if (PTy->isVariadic()) {
7363 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_append_args_with_varargs) << SR;
7364 return std::nullopt;
7365 }
7366 llvm::SmallVector<QualType, 8> Params;
7367 Params.append(in_start: PTy->param_type_begin(), in_end: PTy->param_type_end());
7368 Params.insert(I: Params.end(), NumToInsert: NumAppendArgs, Elt: InteropType);
7369 AdjustedFnType = Context.getFunctionType(ResultTy: PTy->getReturnType(), Args: Params,
7370 EPI: PTy->getExtProtoInfo());
7371 }
7372
7373 // Convert VariantRef expression to the type of the original function to
7374 // resolve possible conflicts.
7375 ExprResult VariantRefCast = VariantRef;
7376 if (getLangOpts().CPlusPlus) {
7377 QualType FnPtrType;
7378 auto *Method = dyn_cast<CXXMethodDecl>(Val: FD);
7379 if (Method && !Method->isStatic()) {
7380 FnPtrType = Context.getMemberPointerType(
7381 T: AdjustedFnType, /*Qualifier=*/nullptr, Cls: Method->getParent());
7382 ExprResult ER;
7383 {
7384 // Build addr_of unary op to correctly handle type checks for member
7385 // functions.
7386 Sema::TentativeAnalysisScope Trap(SemaRef);
7387 ER = SemaRef.CreateBuiltinUnaryOp(OpLoc: VariantRef->getBeginLoc(), Opc: UO_AddrOf,
7388 InputExpr: VariantRef);
7389 }
7390 if (!ER.isUsable()) {
7391 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7392 << VariantId << VariantRef->getSourceRange();
7393 return std::nullopt;
7394 }
7395 VariantRef = ER.get();
7396 } else {
7397 FnPtrType = Context.getPointerType(T: AdjustedFnType);
7398 }
7399 QualType VarianPtrType = Context.getPointerType(T: VariantRef->getType());
7400 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7401 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7402 From: VariantRef, ToType: FnPtrType.getUnqualifiedType(),
7403 /*SuppressUserConversions=*/false, AllowExplicit: Sema::AllowedExplicit::None,
7404 /*InOverloadResolution=*/false,
7405 /*CStyle=*/false,
7406 /*AllowObjCWritebackConversion=*/false);
7407 if (ICS.isFailure()) {
7408 Diag(Loc: VariantRef->getExprLoc(),
7409 DiagID: diag::err_omp_declare_variant_incompat_types)
7410 << VariantRef->getType()
7411 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7412 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7413 return std::nullopt;
7414 }
7415 VariantRefCast = SemaRef.PerformImplicitConversion(
7416 From: VariantRef, ToType: FnPtrType.getUnqualifiedType(),
7417 Action: AssignmentAction::Converting);
7418 if (!VariantRefCast.isUsable())
7419 return std::nullopt;
7420 }
7421 // Drop previously built artificial addr_of unary op for member functions.
7422 if (Method && !Method->isStatic()) {
7423 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7424 if (auto *UO = dyn_cast<UnaryOperator>(
7425 Val: PossibleAddrOfVariantRef->IgnoreImplicit()))
7426 VariantRefCast = UO->getSubExpr();
7427 }
7428 }
7429
7430 ExprResult ER = SemaRef.CheckPlaceholderExpr(E: VariantRefCast.get());
7431 if (!ER.isUsable() ||
7432 !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7433 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7434 << VariantId << VariantRef->getSourceRange();
7435 return std::nullopt;
7436 }
7437
7438 // The VariantRef must point to function.
7439 auto *DRE = dyn_cast<DeclRefExpr>(Val: ER.get()->IgnoreParenImpCasts());
7440 if (!DRE) {
7441 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7442 << VariantId << VariantRef->getSourceRange();
7443 return std::nullopt;
7444 }
7445 auto *NewFD = dyn_cast_or_null<FunctionDecl>(Val: DRE->getDecl());
7446 if (!NewFD) {
7447 Diag(Loc: VariantRef->getExprLoc(), DiagID: diag::err_omp_function_expected)
7448 << VariantId << VariantRef->getSourceRange();
7449 return std::nullopt;
7450 }
7451
7452 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7453 Diag(Loc: VariantRef->getExprLoc(),
7454 DiagID: diag::err_omp_declare_variant_same_base_function)
7455 << VariantRef->getSourceRange();
7456 return std::nullopt;
7457 }
7458
7459 // Check if function types are compatible in C.
7460 if (!getLangOpts().CPlusPlus) {
7461 QualType NewType =
7462 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7463 if (NewType.isNull()) {
7464 Diag(Loc: VariantRef->getExprLoc(),
7465 DiagID: diag::err_omp_declare_variant_incompat_types)
7466 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7467 << VariantRef->getSourceRange();
7468 return std::nullopt;
7469 }
7470 if (NewType->isFunctionProtoType()) {
7471 if (FD->getType()->isFunctionNoProtoType())
7472 setPrototype(S&: SemaRef, FD, FDWithProto: NewFD, NewType);
7473 else if (NewFD->getType()->isFunctionNoProtoType())
7474 setPrototype(S&: SemaRef, FD: NewFD, FDWithProto: FD, NewType);
7475 }
7476 }
7477
7478 // Check if variant function is not marked with declare variant directive.
7479 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7480 Diag(Loc: VariantRef->getExprLoc(),
7481 DiagID: diag::warn_omp_declare_variant_marked_as_declare_variant)
7482 << VariantRef->getSourceRange();
7483 SourceRange SR =
7484 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7485 Diag(Loc: SR.getBegin(), DiagID: diag::note_omp_marked_declare_variant_here) << SR;
7486 return std::nullopt;
7487 }
7488
7489 enum DoesntSupport {
7490 VirtFuncs = 1,
7491 Constructors = 3,
7492 Destructors = 4,
7493 DeletedFuncs = 5,
7494 DefaultedFuncs = 6,
7495 ConstexprFuncs = 7,
7496 ConstevalFuncs = 8,
7497 };
7498 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(Val: FD)) {
7499 if (CXXFD->isVirtual()) {
7500 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7501 << VirtFuncs;
7502 return std::nullopt;
7503 }
7504
7505 if (isa<CXXConstructorDecl>(Val: FD)) {
7506 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7507 << Constructors;
7508 return std::nullopt;
7509 }
7510
7511 if (isa<CXXDestructorDecl>(Val: FD)) {
7512 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7513 << Destructors;
7514 return std::nullopt;
7515 }
7516 }
7517
7518 if (FD->isDeleted()) {
7519 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7520 << DeletedFuncs;
7521 return std::nullopt;
7522 }
7523
7524 if (FD->isDefaulted()) {
7525 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7526 << DefaultedFuncs;
7527 return std::nullopt;
7528 }
7529
7530 if (FD->isConstexpr()) {
7531 Diag(Loc: FD->getLocation(), DiagID: diag::err_omp_declare_variant_doesnt_support)
7532 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7533 return std::nullopt;
7534 }
7535
7536 // Check general compatibility.
7537 if (SemaRef.areMultiversionVariantFunctionsCompatible(
7538 OldFD: FD, NewFD, NoProtoDiagID: PartialDiagnostic::NullDiagnostic(),
7539 NoteCausedDiagIDAt: PartialDiagnosticAt(SourceLocation(),
7540 PartialDiagnostic::NullDiagnostic()),
7541 NoSupportDiagIDAt: PartialDiagnosticAt(
7542 VariantRef->getExprLoc(),
7543 SemaRef.PDiag(DiagID: diag::err_omp_declare_variant_doesnt_support)),
7544 DiffDiagIDAt: PartialDiagnosticAt(VariantRef->getExprLoc(),
7545 SemaRef.PDiag(DiagID: diag::err_omp_declare_variant_diff)
7546 << FD->getLocation()),
7547 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7548 /*CLinkageMayDiffer=*/true))
7549 return std::nullopt;
7550 return std::make_pair(x&: FD, y: cast<Expr>(Val: DRE));
7551}
7552
7553void SemaOpenMP::ActOnOpenMPDeclareVariantDirective(
7554 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7555 ArrayRef<Expr *> AdjustArgsNothing,
7556 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7557 ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
7558 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7559 SourceLocation AppendArgsLoc, SourceRange SR) {
7560
7561 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7562 // An adjust_args clause or append_args clause can only be specified if the
7563 // dispatch selector of the construct selector set appears in the match
7564 // clause.
7565
7566 SmallVector<Expr *, 8> AllAdjustArgs;
7567 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNothing);
7568 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNeedDevicePtr);
7569 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNeedDeviceAddr);
7570
7571 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7572 VariantMatchInfo VMI;
7573 TI.getAsVariantMatchInfo(ASTCtx&: getASTContext(), VMI);
7574 if (!llvm::is_contained(
7575 Range&: VMI.ConstructTraits,
7576 Element: llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7577 if (!AllAdjustArgs.empty())
7578 Diag(Loc: AdjustArgsLoc, DiagID: diag::err_omp_clause_requires_dispatch_construct)
7579 << getOpenMPClauseNameForDiag(C: OMPC_adjust_args);
7580 if (!AppendArgs.empty())
7581 Diag(Loc: AppendArgsLoc, DiagID: diag::err_omp_clause_requires_dispatch_construct)
7582 << getOpenMPClauseNameForDiag(C: OMPC_append_args);
7583 return;
7584 }
7585 }
7586
7587 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7588 // Each argument can only appear in a single adjust_args clause for each
7589 // declare variant directive.
7590 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
7591
7592 for (Expr *E : AllAdjustArgs) {
7593 E = E->IgnoreParenImpCasts();
7594 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E)) {
7595 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7596 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7597 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7598 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7599 ->getCanonicalDecl() == CanonPVD) {
7600 // It's a parameter of the function, check duplicates.
7601 if (!AdjustVars.insert(Ptr: CanonPVD).second) {
7602 Diag(Loc: DRE->getLocation(), DiagID: diag::err_omp_adjust_arg_multiple_clauses)
7603 << PVD;
7604 return;
7605 }
7606 continue;
7607 }
7608 }
7609 }
7610 // Anything that is not a function parameter is an error.
7611 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_param_or_this_in_clause) << FD << 0;
7612 return;
7613 }
7614
7615 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7616 Ctx&: getASTContext(), VariantFuncRef: VariantRef, TraitInfos: &TI,
7617 AdjustArgsNothing: const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothingSize: AdjustArgsNothing.size(),
7618 AdjustArgsNeedDevicePtr: const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7619 AdjustArgsNeedDevicePtrSize: AdjustArgsNeedDevicePtr.size(),
7620 AdjustArgsNeedDeviceAddr: const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
7621 AdjustArgsNeedDeviceAddrSize: AdjustArgsNeedDeviceAddr.size(),
7622 AppendArgs: const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgsSize: AppendArgs.size(), Range: SR);
7623 FD->addAttr(A: NewAttr);
7624}
7625
7626static CapturedStmt *
7627setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt) {
7628 auto *CS = dyn_cast<CapturedStmt>(Val: AStmt);
7629 assert(CS && "Captured statement expected");
7630 // 1.2.2 OpenMP Language Terminology
7631 // Structured block - An executable statement with a single entry at the
7632 // top and a single exit at the bottom.
7633 // The point of exit cannot be a branch out of the structured block.
7634 // longjmp() and throw() must not violate the entry/exit criteria.
7635 CS->getCapturedDecl()->setNothrow();
7636
7637 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7638 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7639 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
7640 // 1.2.2 OpenMP Language Terminology
7641 // Structured block - An executable statement with a single entry at the
7642 // top and a single exit at the bottom.
7643 // The point of exit cannot be a branch out of the structured block.
7644 // longjmp() and throw() must not violate the entry/exit criteria.
7645 CS->getCapturedDecl()->setNothrow();
7646 }
7647 SemaRef.setFunctionHasBranchProtectedScope();
7648 return CS;
7649}
7650
7651StmtResult
7652SemaOpenMP::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
7653 Stmt *AStmt, SourceLocation StartLoc,
7654 SourceLocation EndLoc) {
7655 if (!AStmt)
7656 return StmtError();
7657
7658 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel, AStmt);
7659
7660 return OMPParallelDirective::Create(
7661 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
7662 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7663}
7664
7665namespace {
7666/// Iteration space of a single for loop.
7667struct LoopIterationSpace final {
7668 /// True if the condition operator is the strict compare operator (<, > or
7669 /// !=).
7670 bool IsStrictCompare = false;
7671 /// Condition of the loop.
7672 Expr *PreCond = nullptr;
7673 /// This expression calculates the number of iterations in the loop.
7674 /// It is always possible to calculate it before starting the loop.
7675 Expr *NumIterations = nullptr;
7676 /// The loop counter variable.
7677 Expr *CounterVar = nullptr;
7678 /// Private loop counter variable.
7679 Expr *PrivateCounterVar = nullptr;
7680 /// This is initializer for the initial value of #CounterVar.
7681 Expr *CounterInit = nullptr;
7682 /// This is step for the #CounterVar used to generate its update:
7683 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7684 Expr *CounterStep = nullptr;
7685 /// Should step be subtracted?
7686 bool Subtract = false;
7687 /// Source range of the loop init.
7688 SourceRange InitSrcRange;
7689 /// Source range of the loop condition.
7690 SourceRange CondSrcRange;
7691 /// Source range of the loop increment.
7692 SourceRange IncSrcRange;
7693 /// Minimum value that can have the loop control variable. Used to support
7694 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7695 /// since only such variables can be used in non-loop invariant expressions.
7696 Expr *MinValue = nullptr;
7697 /// Maximum value that can have the loop control variable. Used to support
7698 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7699 /// since only such variables can be used in non-loop invariant expressions.
7700 Expr *MaxValue = nullptr;
7701 /// true, if the lower bound depends on the outer loop control var.
7702 bool IsNonRectangularLB = false;
7703 /// true, if the upper bound depends on the outer loop control var.
7704 bool IsNonRectangularUB = false;
7705 /// Index of the loop this loop depends on and forms non-rectangular loop
7706 /// nest.
7707 unsigned LoopDependentIdx = 0;
7708 /// Final condition for the non-rectangular loop nest support. It is used to
7709 /// check that the number of iterations for this particular counter must be
7710 /// finished.
7711 Expr *FinalCondition = nullptr;
7712};
7713
7714/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
7715/// set are referenced. Used for verifying loop nest structure before
7716/// performing a loop collapse operation.
7717class ForSubExprChecker : public DynamicRecursiveASTVisitor {
7718 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7719 VarDecl *ForbiddenVar = nullptr;
7720 SourceRange ErrLoc;
7721
7722public:
7723 explicit ForSubExprChecker(
7724 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7725 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7726 // We want to visit implicit code, i.e. synthetic initialisation statements
7727 // created during range-for lowering.
7728 ShouldVisitImplicitCode = true;
7729 }
7730
7731 bool VisitDeclRefExpr(DeclRefExpr *E) override {
7732 ValueDecl *VD = E->getDecl();
7733 if (!isa<VarDecl, BindingDecl>(Val: VD))
7734 return true;
7735 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
7736 if (V->getType()->isReferenceType()) {
7737 VarDecl *VD = V->getDefinition();
7738 if (VD->hasInit()) {
7739 Expr *I = VD->getInit();
7740 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Val: I);
7741 if (!DRE)
7742 return true;
7743 V = DRE->getDecl()->getPotentiallyDecomposedVarDecl();
7744 }
7745 }
7746 Decl *Canon = V->getCanonicalDecl();
7747 if (CollapsedLoopVarDecls.contains(Ptr: Canon)) {
7748 ForbiddenVar = V;
7749 ErrLoc = E->getSourceRange();
7750 return false;
7751 }
7752
7753 return true;
7754 }
7755
7756 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
7757 SourceRange getErrRange() const { return ErrLoc; }
7758};
7759
7760/// Helper class for checking canonical form of the OpenMP loops and
7761/// extracting iteration space of each loop in the loop nest, that will be used
7762/// for IR generation.
7763class OpenMPIterationSpaceChecker {
7764 /// Reference to Sema.
7765 Sema &SemaRef;
7766 /// Does the loop associated directive support non-rectangular loops?
7767 bool SupportsNonRectangular;
7768 /// Data-sharing stack.
7769 DSAStackTy &Stack;
7770 /// A location for diagnostics (when there is no some better location).
7771 SourceLocation DefaultLoc;
7772 /// A location for diagnostics (when increment is not compatible).
7773 SourceLocation ConditionLoc;
7774 /// The set of variables declared within the (to be collapsed) loop nest.
7775 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7776 /// A source location for referring to loop init later.
7777 SourceRange InitSrcRange;
7778 /// A source location for referring to condition later.
7779 SourceRange ConditionSrcRange;
7780 /// A source location for referring to increment later.
7781 SourceRange IncrementSrcRange;
7782 /// Loop variable.
7783 ValueDecl *LCDecl = nullptr;
7784 /// Reference to loop variable.
7785 Expr *LCRef = nullptr;
7786 /// Lower bound (initializer for the var).
7787 Expr *LB = nullptr;
7788 /// Upper bound.
7789 Expr *UB = nullptr;
7790 /// Loop step (increment).
7791 Expr *Step = nullptr;
7792 /// This flag is true when condition is one of:
7793 /// Var < UB
7794 /// Var <= UB
7795 /// UB > Var
7796 /// UB >= Var
7797 /// This will have no value when the condition is !=
7798 std::optional<bool> TestIsLessOp;
7799 /// This flag is true when condition is strict ( < or > ).
7800 bool TestIsStrictOp = false;
7801 /// This flag is true when step is subtracted on each iteration.
7802 bool SubtractStep = false;
7803 /// The outer loop counter this loop depends on (if any).
7804 const ValueDecl *DepDecl = nullptr;
7805 /// Contains number of loop (starts from 1) on which loop counter init
7806 /// expression of this loop depends on.
7807 std::optional<unsigned> InitDependOnLC;
7808 /// Contains number of loop (starts from 1) on which loop counter condition
7809 /// expression of this loop depends on.
7810 std::optional<unsigned> CondDependOnLC;
7811 /// Checks if the provide statement depends on the loop counter.
7812 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
7813 bool IsInitializer);
7814 /// Original condition required for checking of the exit condition for
7815 /// non-rectangular loop.
7816 Expr *Condition = nullptr;
7817
7818public:
7819 OpenMPIterationSpaceChecker(
7820 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
7821 SourceLocation DefaultLoc,
7822 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
7823 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7824 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
7825 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
7826 /// Check init-expr for canonical loop form and save loop counter
7827 /// variable - #Var and its initialization value - #LB.
7828 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7829 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7830 /// for less/greater and for strict/non-strict comparison.
7831 bool checkAndSetCond(Expr *S);
7832 /// Check incr-expr for canonical loop form and return true if it
7833 /// does not conform, otherwise save loop step (#Step).
7834 bool checkAndSetInc(Expr *S);
7835 /// Return the loop counter variable.
7836 ValueDecl *getLoopDecl() const { return LCDecl; }
7837 /// Return the reference expression to loop counter variable.
7838 Expr *getLoopDeclRefExpr() const { return LCRef; }
7839 /// Source range of the loop init.
7840 SourceRange getInitSrcRange() const { return InitSrcRange; }
7841 /// Source range of the loop condition.
7842 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7843 /// Source range of the loop increment.
7844 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
7845 /// True if the step should be subtracted.
7846 bool shouldSubtractStep() const { return SubtractStep; }
7847 /// True, if the compare operator is strict (<, > or !=).
7848 bool isStrictTestOp() const { return TestIsStrictOp; }
7849 /// Build the expression to calculate the number of iterations.
7850 Expr *buildNumIterations(
7851 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
7852 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7853 /// Build the precondition expression for the loops.
7854 Expr *
7855 buildPreCond(Scope *S, Expr *Cond,
7856 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7857 /// Build reference expression to the counter be used for codegen.
7858 DeclRefExpr *
7859 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7860 DSAStackTy &DSA) const;
7861 /// Build reference expression to the private counter be used for
7862 /// codegen.
7863 Expr *buildPrivateCounterVar() const;
7864 /// Build initialization of the counter be used for codegen.
7865 Expr *buildCounterInit() const;
7866 /// Build step of the counter be used for codegen.
7867 Expr *buildCounterStep() const;
7868 /// Build loop data with counter value for depend clauses in ordered
7869 /// directives.
7870 Expr *
7871 buildOrderedLoopData(Scope *S, Expr *Counter,
7872 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7873 SourceLocation Loc, Expr *Inc = nullptr,
7874 OverloadedOperatorKind OOK = OO_Amp);
7875 /// Builds the minimum value for the loop counter.
7876 std::pair<Expr *, Expr *> buildMinMaxValues(
7877 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7878 /// Builds final condition for the non-rectangular loops.
7879 Expr *buildFinalCondition(Scope *S) const;
7880 /// Return true if any expression is dependent.
7881 bool dependent() const;
7882 /// Returns true if the initializer forms non-rectangular loop.
7883 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
7884 /// Returns true if the condition forms non-rectangular loop.
7885 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
7886 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
7887 unsigned getLoopDependentIdx() const {
7888 return InitDependOnLC.value_or(u: CondDependOnLC.value_or(u: 0));
7889 }
7890
7891private:
7892 /// Check the right-hand side of an assignment in the increment
7893 /// expression.
7894 bool checkAndSetIncRHS(Expr *RHS);
7895 /// Helper to set loop counter variable and its initializer.
7896 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
7897 bool EmitDiags);
7898 /// Helper to set upper bound.
7899 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
7900 SourceRange SR, SourceLocation SL);
7901 /// Helper to set loop increment.
7902 bool setStep(Expr *NewStep, bool Subtract);
7903};
7904
7905bool OpenMPIterationSpaceChecker::dependent() const {
7906 if (!LCDecl) {
7907 assert(!LB && !UB && !Step);
7908 return false;
7909 }
7910 return LCDecl->getType()->isDependentType() ||
7911 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
7912 (Step && Step->isValueDependent());
7913}
7914
7915bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
7916 Expr *NewLCRefExpr,
7917 Expr *NewLB, bool EmitDiags) {
7918 // State consistency checking to ensure correct usage.
7919 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
7920 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7921 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
7922 return true;
7923 LCDecl = getCanonicalDecl(D: NewLCDecl);
7924 LCRef = NewLCRefExpr;
7925 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(Val: NewLB))
7926 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
7927 if ((Ctor->isCopyOrMoveConstructor() ||
7928 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
7929 CE->getNumArgs() > 0 && CE->getArg(Arg: 0) != nullptr)
7930 NewLB = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
7931 LB = NewLB;
7932 if (EmitDiags)
7933 InitDependOnLC = doesDependOnLoopCounter(S: LB, /*IsInitializer=*/true);
7934 return false;
7935}
7936
7937bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
7938 bool StrictOp, SourceRange SR,
7939 SourceLocation SL) {
7940 // State consistency checking to ensure correct usage.
7941 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
7942 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7943 if (!NewUB || NewUB->containsErrors())
7944 return true;
7945 UB = NewUB;
7946 if (LessOp)
7947 TestIsLessOp = LessOp;
7948 TestIsStrictOp = StrictOp;
7949 ConditionSrcRange = SR;
7950 ConditionLoc = SL;
7951 CondDependOnLC = doesDependOnLoopCounter(S: UB, /*IsInitializer=*/false);
7952 return false;
7953}
7954
7955bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
7956 // State consistency checking to ensure correct usage.
7957 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
7958 if (!NewStep || NewStep->containsErrors())
7959 return true;
7960 if (!NewStep->isValueDependent()) {
7961 // Check that the step is integer expression.
7962 SourceLocation StepLoc = NewStep->getBeginLoc();
7963 ExprResult Val = SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(
7964 OpLoc: StepLoc, Op: getExprAsWritten(E: NewStep));
7965 if (Val.isInvalid())
7966 return true;
7967 NewStep = Val.get();
7968
7969 // OpenMP [2.6, Canonical Loop Form, Restrictions]
7970 // If test-expr is of form var relational-op b and relational-op is < or
7971 // <= then incr-expr must cause var to increase on each iteration of the
7972 // loop. If test-expr is of form var relational-op b and relational-op is
7973 // > or >= then incr-expr must cause var to decrease on each iteration of
7974 // the loop.
7975 // If test-expr is of form b relational-op var and relational-op is < or
7976 // <= then incr-expr must cause var to decrease on each iteration of the
7977 // loop. If test-expr is of form b relational-op var and relational-op is
7978 // > or >= then incr-expr must cause var to increase on each iteration of
7979 // the loop.
7980 std::optional<llvm::APSInt> Result =
7981 NewStep->getIntegerConstantExpr(Ctx: SemaRef.Context);
7982 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
7983 bool IsConstNeg =
7984 Result && Result->isSigned() && (Subtract != Result->isNegative());
7985 bool IsConstPos =
7986 Result && Result->isSigned() && (Subtract == Result->isNegative());
7987 bool IsConstZero = Result && !Result->getBoolValue();
7988
7989 // != with increment is treated as <; != with decrement is treated as >
7990 if (!TestIsLessOp)
7991 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7992 if (UB && (IsConstZero ||
7993 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
7994 : (IsConstPos || (IsUnsigned && !Subtract))))) {
7995 SemaRef.Diag(Loc: NewStep->getExprLoc(),
7996 DiagID: diag::err_omp_loop_incr_not_compatible)
7997 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
7998 SemaRef.Diag(Loc: ConditionLoc,
7999 DiagID: diag::note_omp_loop_cond_requires_compatible_incr)
8000 << *TestIsLessOp << ConditionSrcRange;
8001 return true;
8002 }
8003 if (*TestIsLessOp == Subtract) {
8004 NewStep =
8005 SemaRef.CreateBuiltinUnaryOp(OpLoc: NewStep->getExprLoc(), Opc: UO_Minus, InputExpr: NewStep)
8006 .get();
8007 Subtract = !Subtract;
8008 }
8009 }
8010
8011 Step = NewStep;
8012 SubtractStep = Subtract;
8013 return false;
8014}
8015
8016namespace {
8017/// Checker for the non-rectangular loops. Checks if the initializer or
8018/// condition expression references loop counter variable.
8019class LoopCounterRefChecker final
8020 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8021 Sema &SemaRef;
8022 DSAStackTy &Stack;
8023 const ValueDecl *CurLCDecl = nullptr;
8024 const ValueDecl *DepDecl = nullptr;
8025 const ValueDecl *PrevDepDecl = nullptr;
8026 bool IsInitializer = true;
8027 bool SupportsNonRectangular;
8028 unsigned BaseLoopId = 0;
8029 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8030 if (getCanonicalDecl(D: VD) == getCanonicalDecl(D: CurLCDecl)) {
8031 SemaRef.Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_stmt_depends_on_loop_counter)
8032 << (IsInitializer ? 0 : 1);
8033 return false;
8034 }
8035 const auto &&Data = Stack.isLoopControlVariable(D: VD);
8036 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8037 // The type of the loop iterator on which we depend may not have a random
8038 // access iterator type.
8039 if (Data.first && VD->getType()->isRecordType()) {
8040 SmallString<128> Name;
8041 llvm::raw_svector_ostream OS(Name);
8042 VD->getNameForDiagnostic(OS, Policy: SemaRef.getPrintingPolicy(),
8043 /*Qualified=*/true);
8044 SemaRef.Diag(Loc: E->getExprLoc(),
8045 DiagID: diag::err_omp_wrong_dependency_iterator_type)
8046 << OS.str();
8047 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::note_previous_decl) << VD;
8048 return false;
8049 }
8050 if (Data.first && !SupportsNonRectangular) {
8051 SemaRef.Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_invariant_dependency);
8052 return false;
8053 }
8054 if (Data.first &&
8055 (DepDecl || (PrevDepDecl &&
8056 getCanonicalDecl(D: VD) != getCanonicalDecl(D: PrevDepDecl)))) {
8057 if (!DepDecl && PrevDepDecl)
8058 DepDecl = PrevDepDecl;
8059 SmallString<128> Name;
8060 llvm::raw_svector_ostream OS(Name);
8061 DepDecl->getNameForDiagnostic(OS, Policy: SemaRef.getPrintingPolicy(),
8062 /*Qualified=*/true);
8063 SemaRef.Diag(Loc: E->getExprLoc(),
8064 DiagID: diag::err_omp_invariant_or_linear_dependency)
8065 << OS.str();
8066 return false;
8067 }
8068 if (Data.first) {
8069 DepDecl = VD;
8070 BaseLoopId = Data.first;
8071 }
8072 return Data.first;
8073 }
8074
8075public:
8076 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8077 const ValueDecl *VD = E->getDecl();
8078 if (isa<VarDecl>(Val: VD))
8079 return checkDecl(E, VD);
8080 return false;
8081 }
8082 bool VisitMemberExpr(const MemberExpr *E) {
8083 if (isa<CXXThisExpr>(Val: E->getBase()->IgnoreParens())) {
8084 const ValueDecl *VD = E->getMemberDecl();
8085 if (isa<VarDecl>(Val: VD) || isa<FieldDecl>(Val: VD))
8086 return checkDecl(E, VD);
8087 }
8088 return false;
8089 }
8090 bool VisitStmt(const Stmt *S) {
8091 bool Res = false;
8092 for (const Stmt *Child : S->children())
8093 Res = (Child && Visit(S: Child)) || Res;
8094 return Res;
8095 }
8096 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8097 const ValueDecl *CurLCDecl, bool IsInitializer,
8098 const ValueDecl *PrevDepDecl = nullptr,
8099 bool SupportsNonRectangular = true)
8100 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8101 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8102 SupportsNonRectangular(SupportsNonRectangular) {}
8103 unsigned getBaseLoopId() const {
8104 assert(CurLCDecl && "Expected loop dependency.");
8105 return BaseLoopId;
8106 }
8107 const ValueDecl *getDepDecl() const {
8108 assert(CurLCDecl && "Expected loop dependency.");
8109 return DepDecl;
8110 }
8111};
8112} // namespace
8113
8114std::optional<unsigned>
8115OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8116 bool IsInitializer) {
8117 // Check for the non-rectangular loops.
8118 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8119 DepDecl, SupportsNonRectangular);
8120 if (LoopStmtChecker.Visit(S)) {
8121 DepDecl = LoopStmtChecker.getDepDecl();
8122 return LoopStmtChecker.getBaseLoopId();
8123 }
8124 return std::nullopt;
8125}
8126
8127bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8128 // Check init-expr for canonical loop form and save loop counter
8129 // variable - #Var and its initialization value - #LB.
8130 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8131 // var = lb
8132 // integer-type var = lb
8133 // random-access-iterator-type var = lb
8134 // pointer-type var = lb
8135 //
8136 if (!S) {
8137 if (EmitDiags) {
8138 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_init);
8139 }
8140 return true;
8141 }
8142 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: S))
8143 if (!ExprTemp->cleanupsHaveSideEffects())
8144 S = ExprTemp->getSubExpr();
8145
8146 if (!CollapsedLoopVarDecls.empty()) {
8147 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8148 if (!FSEC.TraverseStmt(S)) {
8149 SourceRange Range = FSEC.getErrRange();
8150 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
8151 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8152 return true;
8153 }
8154 }
8155
8156 InitSrcRange = S->getSourceRange();
8157 if (Expr *E = dyn_cast<Expr>(Val: S))
8158 S = E->IgnoreParens();
8159 if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8160 if (BO->getOpcode() == BO_Assign) {
8161 Expr *LHS = BO->getLHS()->IgnoreParens();
8162 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS)) {
8163 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: DRE->getDecl()))
8164 if (auto *ME = dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit())))
8165 return setLCDeclAndLB(NewLCDecl: ME->getMemberDecl(), NewLCRefExpr: ME, NewLB: BO->getRHS(),
8166 EmitDiags);
8167 return setLCDeclAndLB(NewLCDecl: DRE->getDecl(), NewLCRefExpr: DRE, NewLB: BO->getRHS(), EmitDiags);
8168 }
8169 if (auto *ME = dyn_cast<MemberExpr>(Val: LHS)) {
8170 if (ME->isArrow() &&
8171 isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
8172 return setLCDeclAndLB(NewLCDecl: ME->getMemberDecl(), NewLCRefExpr: ME, NewLB: BO->getRHS(),
8173 EmitDiags);
8174 }
8175 }
8176 } else if (auto *DS = dyn_cast<DeclStmt>(Val: S)) {
8177 if (DS->isSingleDecl()) {
8178 if (auto *Var = dyn_cast_or_null<VarDecl>(Val: DS->getSingleDecl())) {
8179 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8180 // Accept non-canonical init form here but emit ext. warning.
8181 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8182 SemaRef.Diag(Loc: S->getBeginLoc(),
8183 DiagID: diag::ext_omp_loop_not_canonical_init)
8184 << S->getSourceRange();
8185 return setLCDeclAndLB(
8186 NewLCDecl: Var,
8187 NewLCRefExpr: buildDeclRefExpr(S&: SemaRef, D: Var,
8188 Ty: Var->getType().getNonReferenceType(),
8189 Loc: DS->getBeginLoc()),
8190 NewLB: Var->getInit(), EmitDiags);
8191 }
8192 }
8193 }
8194 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8195 if (CE->getOperator() == OO_Equal) {
8196 Expr *LHS = CE->getArg(Arg: 0);
8197 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS)) {
8198 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: DRE->getDecl()))
8199 if (auto *ME = dyn_cast<MemberExpr>(Val: getExprAsWritten(E: CED->getInit())))
8200 return setLCDeclAndLB(NewLCDecl: ME->getMemberDecl(), NewLCRefExpr: ME, NewLB: BO->getRHS(),
8201 EmitDiags);
8202 return setLCDeclAndLB(NewLCDecl: DRE->getDecl(), NewLCRefExpr: DRE, NewLB: CE->getArg(Arg: 1), EmitDiags);
8203 }
8204 if (auto *ME = dyn_cast<MemberExpr>(Val: LHS)) {
8205 if (ME->isArrow() &&
8206 isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
8207 return setLCDeclAndLB(NewLCDecl: ME->getMemberDecl(), NewLCRefExpr: ME, NewLB: BO->getRHS(),
8208 EmitDiags);
8209 }
8210 }
8211 }
8212
8213 if (dependent() || SemaRef.CurContext->isDependentContext())
8214 return false;
8215 if (EmitDiags) {
8216 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_init)
8217 << S->getSourceRange();
8218 }
8219 return true;
8220}
8221
8222/// Ignore parenthesizes, implicit casts, copy constructor and return the
8223/// variable (which may be the loop variable) if possible.
8224static const ValueDecl *getInitLCDecl(const Expr *E) {
8225 if (!E)
8226 return nullptr;
8227 E = getExprAsWritten(E);
8228 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(Val: E))
8229 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8230 if ((Ctor->isCopyOrMoveConstructor() ||
8231 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8232 CE->getNumArgs() > 0 && CE->getArg(Arg: 0) != nullptr)
8233 E = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
8234 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(Val: E)) {
8235 if (const auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
8236 return getCanonicalDecl(D: VD);
8237 }
8238 if (const auto *ME = dyn_cast_or_null<MemberExpr>(Val: E))
8239 if (ME->isArrow() && isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
8240 return getCanonicalDecl(D: ME->getMemberDecl());
8241 return nullptr;
8242}
8243
8244bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8245 // Check test-expr for canonical form, save upper-bound UB, flags for
8246 // less/greater and for strict/non-strict comparison.
8247 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8248 // var relational-op b
8249 // b relational-op var
8250 //
8251 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8252 if (!S) {
8253 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_cond)
8254 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8255 return true;
8256 }
8257 Condition = S;
8258 S = getExprAsWritten(E: S);
8259
8260 if (!CollapsedLoopVarDecls.empty()) {
8261 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8262 if (!FSEC.TraverseStmt(S)) {
8263 SourceRange Range = FSEC.getErrRange();
8264 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
8265 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8266 return true;
8267 }
8268 }
8269
8270 SourceLocation CondLoc = S->getBeginLoc();
8271 auto &&CheckAndSetCond =
8272 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8273 const Expr *RHS, SourceRange SR,
8274 SourceLocation OpLoc) -> std::optional<bool> {
8275 if (BinaryOperator::isRelationalOp(Opc: Opcode)) {
8276 if (getInitLCDecl(E: LHS) == LCDecl)
8277 return setUB(NewUB: const_cast<Expr *>(RHS),
8278 LessOp: (Opcode == BO_LT || Opcode == BO_LE),
8279 StrictOp: (Opcode == BO_LT || Opcode == BO_GT), SR, SL: OpLoc);
8280 if (getInitLCDecl(E: RHS) == LCDecl)
8281 return setUB(NewUB: const_cast<Expr *>(LHS),
8282 LessOp: (Opcode == BO_GT || Opcode == BO_GE),
8283 StrictOp: (Opcode == BO_LT || Opcode == BO_GT), SR, SL: OpLoc);
8284 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8285 return setUB(NewUB: const_cast<Expr *>(getInitLCDecl(E: LHS) == LCDecl ? RHS : LHS),
8286 /*LessOp=*/std::nullopt,
8287 /*StrictOp=*/true, SR, SL: OpLoc);
8288 }
8289 return std::nullopt;
8290 };
8291 std::optional<bool> Res;
8292 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(Val: S)) {
8293 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8294 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8295 RBO->getOperatorLoc());
8296 } else if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8297 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8298 BO->getSourceRange(), BO->getOperatorLoc());
8299 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8300 if (CE->getNumArgs() == 2) {
8301 Res = CheckAndSetCond(
8302 BinaryOperator::getOverloadedOpcode(OO: CE->getOperator()), CE->getArg(Arg: 0),
8303 CE->getArg(Arg: 1), CE->getSourceRange(), CE->getOperatorLoc());
8304 }
8305 }
8306 if (Res)
8307 return *Res;
8308 if (dependent() || SemaRef.CurContext->isDependentContext())
8309 return false;
8310 SemaRef.Diag(Loc: CondLoc, DiagID: diag::err_omp_loop_not_canonical_cond)
8311 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8312 return true;
8313}
8314
8315bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8316 // RHS of canonical loop form increment can be:
8317 // var + incr
8318 // incr + var
8319 // var - incr
8320 //
8321 RHS = RHS->IgnoreParenImpCasts();
8322 if (auto *BO = dyn_cast<BinaryOperator>(Val: RHS)) {
8323 if (BO->isAdditiveOp()) {
8324 bool IsAdd = BO->getOpcode() == BO_Add;
8325 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8326 return setStep(NewStep: BO->getRHS(), Subtract: !IsAdd);
8327 if (IsAdd && getInitLCDecl(E: BO->getRHS()) == LCDecl)
8328 return setStep(NewStep: BO->getLHS(), /*Subtract=*/false);
8329 }
8330 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: RHS)) {
8331 bool IsAdd = CE->getOperator() == OO_Plus;
8332 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8333 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8334 return setStep(NewStep: CE->getArg(Arg: 1), Subtract: !IsAdd);
8335 if (IsAdd && getInitLCDecl(E: CE->getArg(Arg: 1)) == LCDecl)
8336 return setStep(NewStep: CE->getArg(Arg: 0), /*Subtract=*/false);
8337 }
8338 }
8339 if (dependent() || SemaRef.CurContext->isDependentContext())
8340 return false;
8341 SemaRef.Diag(Loc: RHS->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_incr)
8342 << RHS->getSourceRange() << LCDecl;
8343 return true;
8344}
8345
8346bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8347 // Check incr-expr for canonical loop form and return true if it
8348 // does not conform.
8349 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8350 // ++var
8351 // var++
8352 // --var
8353 // var--
8354 // var += incr
8355 // var -= incr
8356 // var = var + incr
8357 // var = incr + var
8358 // var = var - incr
8359 //
8360 if (!S) {
8361 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::err_omp_loop_not_canonical_incr) << LCDecl;
8362 return true;
8363 }
8364 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: S))
8365 if (!ExprTemp->cleanupsHaveSideEffects())
8366 S = ExprTemp->getSubExpr();
8367
8368 if (!CollapsedLoopVarDecls.empty()) {
8369 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8370 if (!FSEC.TraverseStmt(S)) {
8371 SourceRange Range = FSEC.getErrRange();
8372 SemaRef.Diag(Loc: Range.getBegin(), DiagID: diag::err_omp_loop_bad_collapse_var)
8373 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8374 return true;
8375 }
8376 }
8377
8378 IncrementSrcRange = S->getSourceRange();
8379 S = S->IgnoreParens();
8380 if (auto *UO = dyn_cast<UnaryOperator>(Val: S)) {
8381 if (UO->isIncrementDecrementOp() &&
8382 getInitLCDecl(E: UO->getSubExpr()) == LCDecl)
8383 return setStep(NewStep: SemaRef
8384 .ActOnIntegerConstant(Loc: UO->getBeginLoc(),
8385 Val: (UO->isDecrementOp() ? -1 : 1))
8386 .get(),
8387 /*Subtract=*/false);
8388 } else if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8389 switch (BO->getOpcode()) {
8390 case BO_AddAssign:
8391 case BO_SubAssign:
8392 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8393 return setStep(NewStep: BO->getRHS(), Subtract: BO->getOpcode() == BO_SubAssign);
8394 break;
8395 case BO_Assign:
8396 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8397 return checkAndSetIncRHS(RHS: BO->getRHS());
8398 break;
8399 default:
8400 break;
8401 }
8402 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8403 switch (CE->getOperator()) {
8404 case OO_PlusPlus:
8405 case OO_MinusMinus:
8406 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8407 return setStep(NewStep: SemaRef
8408 .ActOnIntegerConstant(
8409 Loc: CE->getBeginLoc(),
8410 Val: ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8411 .get(),
8412 /*Subtract=*/false);
8413 break;
8414 case OO_PlusEqual:
8415 case OO_MinusEqual:
8416 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8417 return setStep(NewStep: CE->getArg(Arg: 1), Subtract: CE->getOperator() == OO_MinusEqual);
8418 break;
8419 case OO_Equal:
8420 if (getInitLCDecl(E: CE->getArg(Arg: 0)) == LCDecl)
8421 return checkAndSetIncRHS(RHS: CE->getArg(Arg: 1));
8422 break;
8423 default:
8424 break;
8425 }
8426 }
8427 if (dependent() || SemaRef.CurContext->isDependentContext())
8428 return false;
8429 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_loop_not_canonical_incr)
8430 << S->getSourceRange() << LCDecl;
8431 return true;
8432}
8433
8434static ExprResult
8435tryBuildCapture(Sema &SemaRef, Expr *Capture,
8436 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8437 StringRef Name = ".capture_expr.") {
8438 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8439 return Capture;
8440 if (Capture->isEvaluatable(Ctx: SemaRef.Context, AllowSideEffects: Expr::SE_AllowSideEffects))
8441 return SemaRef.PerformImplicitConversion(From: Capture->IgnoreImpCasts(),
8442 ToType: Capture->getType(),
8443 Action: AssignmentAction::Converting,
8444 /*AllowExplicit=*/true);
8445 auto I = Captures.find(Key: Capture);
8446 if (I != Captures.end())
8447 return buildCapture(S&: SemaRef, CaptureExpr: Capture, Ref&: I->second, Name);
8448 DeclRefExpr *Ref = nullptr;
8449 ExprResult Res = buildCapture(S&: SemaRef, CaptureExpr: Capture, Ref, Name);
8450 Captures[Capture] = Ref;
8451 return Res;
8452}
8453
8454/// Calculate number of iterations, transforming to unsigned, if number of
8455/// iterations may be larger than the original type.
8456static Expr *
8457calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8458 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8459 bool TestIsStrictOp, bool RoundToStep,
8460 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8461 ExprResult NewStep = tryBuildCapture(SemaRef, Capture: Step, Captures, Name: ".new_step");
8462 if (!NewStep.isUsable())
8463 return nullptr;
8464 llvm::APSInt LRes, SRes;
8465 bool IsLowerConst = false, IsStepConst = false;
8466 if (std::optional<llvm::APSInt> Res =
8467 Lower->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8468 LRes = *Res;
8469 IsLowerConst = true;
8470 }
8471 if (std::optional<llvm::APSInt> Res =
8472 Step->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8473 SRes = *Res;
8474 IsStepConst = true;
8475 }
8476 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8477 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8478 (TestIsStrictOp && LRes.isStrictlyPositive()));
8479 bool NeedToReorganize = false;
8480 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8481 if (!NoNeedToConvert && IsLowerConst &&
8482 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8483 NoNeedToConvert = true;
8484 if (RoundToStep) {
8485 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8486 ? LRes.getBitWidth()
8487 : SRes.getBitWidth();
8488 LRes = LRes.extend(width: BW + 1);
8489 LRes.setIsSigned(true);
8490 SRes = SRes.extend(width: BW + 1);
8491 SRes.setIsSigned(true);
8492 LRes -= SRes;
8493 NoNeedToConvert = LRes.trunc(width: BW).extend(width: BW + 1) == LRes;
8494 LRes = LRes.trunc(width: BW);
8495 }
8496 if (TestIsStrictOp) {
8497 unsigned BW = LRes.getBitWidth();
8498 LRes = LRes.extend(width: BW + 1);
8499 LRes.setIsSigned(true);
8500 ++LRes;
8501 NoNeedToConvert =
8502 NoNeedToConvert && LRes.trunc(width: BW).extend(width: BW + 1) == LRes;
8503 // truncate to the original bitwidth.
8504 LRes = LRes.trunc(width: BW);
8505 }
8506 NeedToReorganize = NoNeedToConvert;
8507 }
8508 llvm::APSInt URes;
8509 bool IsUpperConst = false;
8510 if (std::optional<llvm::APSInt> Res =
8511 Upper->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8512 URes = *Res;
8513 IsUpperConst = true;
8514 }
8515 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8516 (!RoundToStep || IsStepConst)) {
8517 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8518 : URes.getBitWidth();
8519 LRes = LRes.extend(width: BW + 1);
8520 LRes.setIsSigned(true);
8521 URes = URes.extend(width: BW + 1);
8522 URes.setIsSigned(true);
8523 URes -= LRes;
8524 NoNeedToConvert = URes.trunc(width: BW).extend(width: BW + 1) == URes;
8525 NeedToReorganize = NoNeedToConvert;
8526 }
8527 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8528 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8529 // unsigned.
8530 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8531 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8532 QualType LowerTy = Lower->getType();
8533 QualType UpperTy = Upper->getType();
8534 uint64_t LowerSize = SemaRef.Context.getTypeSize(T: LowerTy);
8535 uint64_t UpperSize = SemaRef.Context.getTypeSize(T: UpperTy);
8536 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8537 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8538 QualType CastType = SemaRef.Context.getIntTypeForBitwidth(
8539 DestWidth: LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8540 Upper =
8541 SemaRef
8542 .PerformImplicitConversion(
8543 From: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Upper).get(),
8544 ToType: CastType, Action: AssignmentAction::Converting)
8545 .get();
8546 Lower = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Lower).get();
8547 NewStep = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: NewStep.get());
8548 }
8549 }
8550 if (!Lower || !Upper || NewStep.isInvalid())
8551 return nullptr;
8552
8553 ExprResult Diff;
8554 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8555 // 1]).
8556 if (NeedToReorganize) {
8557 Diff = Lower;
8558
8559 if (RoundToStep) {
8560 // Lower - Step
8561 Diff =
8562 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8563 if (!Diff.isUsable())
8564 return nullptr;
8565 }
8566
8567 // Lower - Step [+ 1]
8568 if (TestIsStrictOp)
8569 Diff = SemaRef.BuildBinOp(
8570 S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(),
8571 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
8572 if (!Diff.isUsable())
8573 return nullptr;
8574
8575 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
8576 if (!Diff.isUsable())
8577 return nullptr;
8578
8579 // Upper - (Lower - Step [+ 1]).
8580 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Diff.get());
8581 if (!Diff.isUsable())
8582 return nullptr;
8583 } else {
8584 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Lower);
8585
8586 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8587 // BuildBinOp already emitted error, this one is to point user to upper
8588 // and lower bound, and to tell what is passed to 'operator-'.
8589 SemaRef.Diag(Loc: Upper->getBeginLoc(), DiagID: diag::err_omp_loop_diff_cxx)
8590 << Upper->getSourceRange() << Lower->getSourceRange();
8591 return nullptr;
8592 }
8593
8594 if (!Diff.isUsable())
8595 return nullptr;
8596
8597 // Upper - Lower [- 1]
8598 if (TestIsStrictOp)
8599 Diff = SemaRef.BuildBinOp(
8600 S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Diff.get(),
8601 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
8602 if (!Diff.isUsable())
8603 return nullptr;
8604
8605 if (RoundToStep) {
8606 // Upper - Lower [- 1] + Step
8607 Diff =
8608 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8609 if (!Diff.isUsable())
8610 return nullptr;
8611 }
8612 }
8613
8614 // Parentheses (for dumping/debugging purposes only).
8615 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
8616 if (!Diff.isUsable())
8617 return nullptr;
8618
8619 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8620 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Div, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8621 if (!Diff.isUsable())
8622 return nullptr;
8623
8624 return Diff.get();
8625}
8626
8627/// Build the expression to calculate the number of iterations.
8628Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8629 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8630 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8631 QualType VarType = LCDecl->getType().getNonReferenceType();
8632 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8633 !SemaRef.getLangOpts().CPlusPlus)
8634 return nullptr;
8635 Expr *LBVal = LB;
8636 Expr *UBVal = UB;
8637 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8638 // max(LB(MinVal), LB(MaxVal)))
8639 if (InitDependOnLC) {
8640 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8641 if (!IS.MinValue || !IS.MaxValue)
8642 return nullptr;
8643 // OuterVar = Min
8644 ExprResult MinValue =
8645 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MinValue);
8646 if (!MinValue.isUsable())
8647 return nullptr;
8648
8649 ExprResult LBMinVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
8650 LHSExpr: IS.CounterVar, RHSExpr: MinValue.get());
8651 if (!LBMinVal.isUsable())
8652 return nullptr;
8653 // OuterVar = Min, LBVal
8654 LBMinVal =
8655 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: LBMinVal.get(), RHSExpr: LBVal);
8656 if (!LBMinVal.isUsable())
8657 return nullptr;
8658 // (OuterVar = Min, LBVal)
8659 LBMinVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: LBMinVal.get());
8660 if (!LBMinVal.isUsable())
8661 return nullptr;
8662
8663 // OuterVar = Max
8664 ExprResult MaxValue =
8665 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MaxValue);
8666 if (!MaxValue.isUsable())
8667 return nullptr;
8668
8669 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
8670 LHSExpr: IS.CounterVar, RHSExpr: MaxValue.get());
8671 if (!LBMaxVal.isUsable())
8672 return nullptr;
8673 // OuterVar = Max, LBVal
8674 LBMaxVal =
8675 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: LBMaxVal.get(), RHSExpr: LBVal);
8676 if (!LBMaxVal.isUsable())
8677 return nullptr;
8678 // (OuterVar = Max, LBVal)
8679 LBMaxVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: LBMaxVal.get());
8680 if (!LBMaxVal.isUsable())
8681 return nullptr;
8682
8683 Expr *LBMin =
8684 tryBuildCapture(SemaRef, Capture: LBMinVal.get(), Captures, Name: ".lb_min").get();
8685 Expr *LBMax =
8686 tryBuildCapture(SemaRef, Capture: LBMaxVal.get(), Captures, Name: ".lb_max").get();
8687 if (!LBMin || !LBMax)
8688 return nullptr;
8689 // LB(MinVal) < LB(MaxVal)
8690 ExprResult MinLessMaxRes =
8691 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_LT, LHSExpr: LBMin, RHSExpr: LBMax);
8692 if (!MinLessMaxRes.isUsable())
8693 return nullptr;
8694 Expr *MinLessMax =
8695 tryBuildCapture(SemaRef, Capture: MinLessMaxRes.get(), Captures, Name: ".min_less_max")
8696 .get();
8697 if (!MinLessMax)
8698 return nullptr;
8699 if (*TestIsLessOp) {
8700 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8701 // LB(MaxVal))
8702 ExprResult MinLB = SemaRef.ActOnConditionalOp(QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc,
8703 CondExpr: MinLessMax, LHSExpr: LBMin, RHSExpr: LBMax);
8704 if (!MinLB.isUsable())
8705 return nullptr;
8706 LBVal = MinLB.get();
8707 } else {
8708 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8709 // LB(MaxVal))
8710 ExprResult MaxLB = SemaRef.ActOnConditionalOp(QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc,
8711 CondExpr: MinLessMax, LHSExpr: LBMax, RHSExpr: LBMin);
8712 if (!MaxLB.isUsable())
8713 return nullptr;
8714 LBVal = MaxLB.get();
8715 }
8716 // OuterVar = LB
8717 LBMinVal =
8718 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign, LHSExpr: IS.CounterVar, RHSExpr: LBVal);
8719 if (!LBMinVal.isUsable())
8720 return nullptr;
8721 LBVal = LBMinVal.get();
8722 }
8723 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8724 // min(UB(MinVal), UB(MaxVal))
8725 if (CondDependOnLC) {
8726 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8727 if (!IS.MinValue || !IS.MaxValue)
8728 return nullptr;
8729 // OuterVar = Min
8730 ExprResult MinValue =
8731 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MinValue);
8732 if (!MinValue.isUsable())
8733 return nullptr;
8734
8735 ExprResult UBMinVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
8736 LHSExpr: IS.CounterVar, RHSExpr: MinValue.get());
8737 if (!UBMinVal.isUsable())
8738 return nullptr;
8739 // OuterVar = Min, UBVal
8740 UBMinVal =
8741 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: UBMinVal.get(), RHSExpr: UBVal);
8742 if (!UBMinVal.isUsable())
8743 return nullptr;
8744 // (OuterVar = Min, UBVal)
8745 UBMinVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: UBMinVal.get());
8746 if (!UBMinVal.isUsable())
8747 return nullptr;
8748
8749 // OuterVar = Max
8750 ExprResult MaxValue =
8751 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MaxValue);
8752 if (!MaxValue.isUsable())
8753 return nullptr;
8754
8755 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
8756 LHSExpr: IS.CounterVar, RHSExpr: MaxValue.get());
8757 if (!UBMaxVal.isUsable())
8758 return nullptr;
8759 // OuterVar = Max, UBVal
8760 UBMaxVal =
8761 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: UBMaxVal.get(), RHSExpr: UBVal);
8762 if (!UBMaxVal.isUsable())
8763 return nullptr;
8764 // (OuterVar = Max, UBVal)
8765 UBMaxVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: UBMaxVal.get());
8766 if (!UBMaxVal.isUsable())
8767 return nullptr;
8768
8769 Expr *UBMin =
8770 tryBuildCapture(SemaRef, Capture: UBMinVal.get(), Captures, Name: ".ub_min").get();
8771 Expr *UBMax =
8772 tryBuildCapture(SemaRef, Capture: UBMaxVal.get(), Captures, Name: ".ub_max").get();
8773 if (!UBMin || !UBMax)
8774 return nullptr;
8775 // UB(MinVal) > UB(MaxVal)
8776 ExprResult MinGreaterMaxRes =
8777 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_GT, LHSExpr: UBMin, RHSExpr: UBMax);
8778 if (!MinGreaterMaxRes.isUsable())
8779 return nullptr;
8780 Expr *MinGreaterMax = tryBuildCapture(SemaRef, Capture: MinGreaterMaxRes.get(),
8781 Captures, Name: ".min_greater_max")
8782 .get();
8783 if (!MinGreaterMax)
8784 return nullptr;
8785 if (*TestIsLessOp) {
8786 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8787 // UB(MaxVal))
8788 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8789 QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc, CondExpr: MinGreaterMax, LHSExpr: UBMin, RHSExpr: UBMax);
8790 if (!MaxUB.isUsable())
8791 return nullptr;
8792 UBVal = MaxUB.get();
8793 } else {
8794 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8795 // UB(MaxVal))
8796 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8797 QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc, CondExpr: MinGreaterMax, LHSExpr: UBMax, RHSExpr: UBMin);
8798 if (!MinUB.isUsable())
8799 return nullptr;
8800 UBVal = MinUB.get();
8801 }
8802 }
8803 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8804 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8805 Expr *Upper = tryBuildCapture(SemaRef, Capture: UBExpr, Captures, Name: ".upper").get();
8806 Expr *Lower = tryBuildCapture(SemaRef, Capture: LBExpr, Captures, Name: ".lower").get();
8807 if (!Upper || !Lower)
8808 return nullptr;
8809
8810 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8811 Step, LCTy: VarType, TestIsStrictOp,
8812 /*RoundToStep=*/true, Captures);
8813 if (!Diff.isUsable())
8814 return nullptr;
8815
8816 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8817 QualType Type = Diff.get()->getType();
8818 ASTContext &C = SemaRef.Context;
8819 bool UseVarType = VarType->hasIntegerRepresentation() &&
8820 C.getTypeSize(T: Type) > C.getTypeSize(T: VarType);
8821 if (!Type->isIntegerType() || UseVarType) {
8822 unsigned NewSize =
8823 UseVarType ? C.getTypeSize(T: VarType) : C.getTypeSize(T: Type);
8824 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8825 : Type->hasSignedIntegerRepresentation();
8826 Type = C.getIntTypeForBitwidth(DestWidth: NewSize, Signed: IsSigned);
8827 if (!SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: Type)) {
8828 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: Type,
8829 Action: AssignmentAction::Converting,
8830 /*AllowExplicit=*/true);
8831 if (!Diff.isUsable())
8832 return nullptr;
8833 }
8834 }
8835 if (LimitedType) {
8836 unsigned NewSize = (C.getTypeSize(T: Type) > 32) ? 64 : 32;
8837 if (NewSize != C.getTypeSize(T: Type)) {
8838 if (NewSize < C.getTypeSize(T: Type)) {
8839 assert(NewSize == 64 && "incorrect loop var size");
8840 SemaRef.Diag(Loc: DefaultLoc, DiagID: diag::warn_omp_loop_64_bit_var)
8841 << InitSrcRange << ConditionSrcRange;
8842 }
8843 QualType NewType = C.getIntTypeForBitwidth(
8844 DestWidth: NewSize, Signed: Type->hasSignedIntegerRepresentation() ||
8845 C.getTypeSize(T: Type) < NewSize);
8846 if (!SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: NewType)) {
8847 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: NewType,
8848 Action: AssignmentAction::Converting,
8849 /*AllowExplicit=*/true);
8850 if (!Diff.isUsable())
8851 return nullptr;
8852 }
8853 }
8854 }
8855
8856 return Diff.get();
8857}
8858
8859std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8860 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8861 // Do not build for iterators, they cannot be used in non-rectangular loop
8862 // nests.
8863 if (LCDecl->getType()->isRecordType())
8864 return std::make_pair(x: nullptr, y: nullptr);
8865 // If we subtract, the min is in the condition, otherwise the min is in the
8866 // init value.
8867 Expr *MinExpr = nullptr;
8868 Expr *MaxExpr = nullptr;
8869 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8870 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8871 bool LBNonRect =
8872 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8873 bool UBNonRect =
8874 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8875 Expr *Lower =
8876 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, Capture: LBExpr, Captures).get();
8877 Expr *Upper =
8878 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, Capture: UBExpr, Captures).get();
8879 if (!Upper || !Lower)
8880 return std::make_pair(x: nullptr, y: nullptr);
8881
8882 if (*TestIsLessOp)
8883 MinExpr = Lower;
8884 else
8885 MaxExpr = Upper;
8886
8887 // Build minimum/maximum value based on number of iterations.
8888 QualType VarType = LCDecl->getType().getNonReferenceType();
8889
8890 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8891 Step, LCTy: VarType, TestIsStrictOp,
8892 /*RoundToStep=*/false, Captures);
8893 if (!Diff.isUsable())
8894 return std::make_pair(x: nullptr, y: nullptr);
8895
8896 // ((Upper - Lower [- 1]) / Step) * Step
8897 // Parentheses (for dumping/debugging purposes only).
8898 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
8899 if (!Diff.isUsable())
8900 return std::make_pair(x: nullptr, y: nullptr);
8901
8902 ExprResult NewStep = tryBuildCapture(SemaRef, Capture: Step, Captures, Name: ".new_step");
8903 if (!NewStep.isUsable())
8904 return std::make_pair(x: nullptr, y: nullptr);
8905 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Mul, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8906 if (!Diff.isUsable())
8907 return std::make_pair(x: nullptr, y: nullptr);
8908
8909 // Parentheses (for dumping/debugging purposes only).
8910 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
8911 if (!Diff.isUsable())
8912 return std::make_pair(x: nullptr, y: nullptr);
8913
8914 // Convert to the ptrdiff_t, if original type is pointer.
8915 if (VarType->isAnyPointerType() &&
8916 !SemaRef.Context.hasSameType(
8917 T1: Diff.get()->getType(),
8918 T2: SemaRef.Context.getUnsignedPointerDiffType())) {
8919 Diff = SemaRef.PerformImplicitConversion(
8920 From: Diff.get(), ToType: SemaRef.Context.getUnsignedPointerDiffType(),
8921 Action: AssignmentAction::Converting, /*AllowExplicit=*/true);
8922 }
8923 if (!Diff.isUsable())
8924 return std::make_pair(x: nullptr, y: nullptr);
8925
8926 if (*TestIsLessOp) {
8927 // MinExpr = Lower;
8928 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
8929 Diff = SemaRef.BuildBinOp(
8930 S, OpLoc: DefaultLoc, Opc: BO_Add,
8931 LHSExpr: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Lower).get(),
8932 RHSExpr: Diff.get());
8933 if (!Diff.isUsable())
8934 return std::make_pair(x: nullptr, y: nullptr);
8935 } else {
8936 // MaxExpr = Upper;
8937 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
8938 Diff = SemaRef.BuildBinOp(
8939 S, OpLoc: DefaultLoc, Opc: BO_Sub,
8940 LHSExpr: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Upper).get(),
8941 RHSExpr: Diff.get());
8942 if (!Diff.isUsable())
8943 return std::make_pair(x: nullptr, y: nullptr);
8944 }
8945
8946 // Convert to the original type.
8947 if (SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: VarType))
8948 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: VarType,
8949 Action: AssignmentAction::Converting,
8950 /*AllowExplicit=*/true);
8951 if (!Diff.isUsable())
8952 return std::make_pair(x: nullptr, y: nullptr);
8953
8954 Sema::TentativeAnalysisScope Trap(SemaRef);
8955 Diff = SemaRef.ActOnFinishFullExpr(Expr: Diff.get(), /*DiscardedValue=*/false);
8956 if (!Diff.isUsable())
8957 return std::make_pair(x: nullptr, y: nullptr);
8958
8959 if (*TestIsLessOp)
8960 MaxExpr = Diff.get();
8961 else
8962 MinExpr = Diff.get();
8963
8964 return std::make_pair(x&: MinExpr, y&: MaxExpr);
8965}
8966
8967Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
8968 if (InitDependOnLC || CondDependOnLC)
8969 return Condition;
8970 return nullptr;
8971}
8972
8973Expr *OpenMPIterationSpaceChecker::buildPreCond(
8974 Scope *S, Expr *Cond,
8975 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8976 // Do not build a precondition when the condition/initialization is dependent
8977 // to prevent pessimistic early loop exit.
8978 // TODO: this can be improved by calculating min/max values but not sure that
8979 // it will be very effective.
8980 if (CondDependOnLC || InitDependOnLC)
8981 return SemaRef
8982 .PerformImplicitConversion(
8983 From: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get(),
8984 ToType: SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
8985 /*AllowExplicit=*/true)
8986 .get();
8987
8988 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
8989 Sema::TentativeAnalysisScope Trap(SemaRef);
8990
8991 ExprResult NewLB = tryBuildCapture(SemaRef, Capture: LB, Captures);
8992 ExprResult NewUB = tryBuildCapture(SemaRef, Capture: UB, Captures);
8993 if (!NewLB.isUsable() || !NewUB.isUsable())
8994 return nullptr;
8995
8996 ExprResult CondExpr =
8997 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc,
8998 Opc: *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
8999 : (TestIsStrictOp ? BO_GT : BO_GE),
9000 LHSExpr: NewLB.get(), RHSExpr: NewUB.get());
9001 if (CondExpr.isUsable()) {
9002 if (!SemaRef.Context.hasSameUnqualifiedType(T1: CondExpr.get()->getType(),
9003 T2: SemaRef.Context.BoolTy))
9004 CondExpr = SemaRef.PerformImplicitConversion(
9005 From: CondExpr.get(), ToType: SemaRef.Context.BoolTy,
9006 /*Action=*/AssignmentAction::Casting,
9007 /*AllowExplicit=*/true);
9008 }
9009
9010 // Otherwise use original loop condition and evaluate it in runtime.
9011 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9012}
9013
9014/// Build reference expression to the counter be used for codegen.
9015DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9016 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9017 DSAStackTy &DSA) const {
9018 auto *VD = dyn_cast<VarDecl>(Val: LCDecl);
9019 if (!VD) {
9020 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(D: LCDecl);
9021 DeclRefExpr *Ref = buildDeclRefExpr(
9022 S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(), Loc: DefaultLoc);
9023 const DSAStackTy::DSAVarData Data =
9024 DSA.getTopDSA(D: LCDecl, /*FromParent=*/false);
9025 // If the loop control decl is explicitly marked as private, do not mark it
9026 // as captured again.
9027 if (!isOpenMPPrivate(Kind: Data.CKind) || !Data.RefExpr)
9028 Captures.insert(KV: std::make_pair(x: LCRef, y&: Ref));
9029 return Ref;
9030 }
9031 return cast<DeclRefExpr>(Val: LCRef);
9032}
9033
9034Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9035 if (LCDecl && !LCDecl->isInvalidDecl()) {
9036 QualType Type = LCDecl->getType().getNonReferenceType();
9037 VarDecl *PrivateVar = buildVarDecl(
9038 SemaRef, Loc: DefaultLoc, Type, Name: LCDecl->getName(),
9039 Attrs: LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9040 OrigRef: isa<VarDecl>(Val: LCDecl)
9041 ? buildDeclRefExpr(S&: SemaRef, D: cast<VarDecl>(Val: LCDecl), Ty: Type, Loc: DefaultLoc)
9042 : nullptr);
9043 if (PrivateVar->isInvalidDecl())
9044 return nullptr;
9045 return buildDeclRefExpr(S&: SemaRef, D: PrivateVar, Ty: Type, Loc: DefaultLoc);
9046 }
9047 return nullptr;
9048}
9049
9050/// Build initialization of the counter to be used for codegen.
9051Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9052
9053/// Build step of the counter be used for codegen.
9054Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9055
9056Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9057 Scope *S, Expr *Counter,
9058 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9059 Expr *Inc, OverloadedOperatorKind OOK) {
9060 Expr *Cnt = SemaRef.DefaultLvalueConversion(E: Counter).get();
9061 if (!Cnt)
9062 return nullptr;
9063 if (Inc) {
9064 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9065 "Expected only + or - operations for depend clauses.");
9066 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9067 Cnt = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BOK, LHSExpr: Cnt, RHSExpr: Inc).get();
9068 if (!Cnt)
9069 return nullptr;
9070 }
9071 QualType VarType = LCDecl->getType().getNonReferenceType();
9072 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9073 !SemaRef.getLangOpts().CPlusPlus)
9074 return nullptr;
9075 // Upper - Lower
9076 Expr *Upper =
9077 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, Capture: LB, Captures).get();
9078 Expr *Lower =
9079 *TestIsLessOp ? tryBuildCapture(SemaRef, Capture: LB, Captures).get() : Cnt;
9080 if (!Upper || !Lower)
9081 return nullptr;
9082
9083 ExprResult Diff = calculateNumIters(
9084 SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType,
9085 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9086 if (!Diff.isUsable())
9087 return nullptr;
9088
9089 return Diff.get();
9090}
9091} // namespace
9092
9093void SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc,
9094 Stmt *Init) {
9095 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9096 assert(Init && "Expected loop in canonical form.");
9097 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9098 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9099 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9100 return;
9101
9102 DSAStack->loopStart();
9103 llvm::SmallPtrSet<const Decl *, 1> EmptyDeclSet;
9104 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9105 *DSAStack, ForLoc, EmptyDeclSet);
9106 if (!ISC.checkAndSetInit(S: Init, /*EmitDiags=*/false)) {
9107 if (ValueDecl *D = ISC.getLoopDecl()) {
9108 auto *VD = dyn_cast<VarDecl>(Val: D);
9109 DeclRefExpr *PrivateRef = nullptr;
9110 if (!VD) {
9111 if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9112 VD = Private;
9113 } else {
9114 PrivateRef = buildCapture(S&: SemaRef, D, CaptureExpr: ISC.getLoopDeclRefExpr(),
9115 /*WithInit=*/false);
9116 VD = cast<VarDecl>(Val: PrivateRef->getDecl());
9117 }
9118 }
9119 DSAStack->addLoopControlVariable(D, Capture: VD);
9120 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9121 if (LD != D->getCanonicalDecl()) {
9122 DSAStack->resetPossibleLoopCounter();
9123 if (auto *Var = dyn_cast_or_null<VarDecl>(Val: LD))
9124 SemaRef.MarkDeclarationsReferencedInExpr(E: buildDeclRefExpr(
9125 S&: SemaRef, D: const_cast<VarDecl *>(Var),
9126 Ty: Var->getType().getNonLValueExprType(Context: getASTContext()), Loc: ForLoc,
9127 /*RefersToCapture=*/true));
9128 }
9129 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9130 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9131 // associated for-loop of a simd construct with just one associated
9132 // for-loop may be listed in a linear clause with a constant-linear-step
9133 // that is the increment of the associated for-loop. The loop iteration
9134 // variable(s) in the associated for-loop(s) of a for or parallel for
9135 // construct may be listed in a private or lastprivate clause.
9136 DSAStackTy::DSAVarData DVar =
9137 DSAStack->getTopDSA(D, /*FromParent=*/false);
9138 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9139 // is declared in the loop and it is predetermined as a private.
9140 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9141 OpenMPClauseKind PredeterminedCKind =
9142 isOpenMPSimdDirective(DKind)
9143 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9144 : OMPC_private;
9145 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9146 return getLeafConstructsOrSelf(D: DK).back() == OMPD_taskloop;
9147 };
9148 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9149 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9150 (getLangOpts().OpenMP <= 45 ||
9151 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9152 ((isOpenMPWorksharingDirective(DKind) ||
9153 IsOpenMPTaskloopDirective(DKind) ||
9154 isOpenMPDistributeDirective(DKind)) &&
9155 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9156 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9157 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9158 unsigned OMPVersion = getLangOpts().OpenMP;
9159 Diag(Loc: Init->getBeginLoc(), DiagID: diag::err_omp_loop_var_dsa)
9160 << getOpenMPClauseNameForDiag(C: DVar.CKind)
9161 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion)
9162 << getOpenMPClauseNameForDiag(C: PredeterminedCKind);
9163 if (DVar.RefExpr == nullptr)
9164 DVar.CKind = PredeterminedCKind;
9165 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9166 } else if (LoopDeclRefExpr) {
9167 // Make the loop iteration variable private (for worksharing
9168 // constructs), linear (for simd directives with the only one
9169 // associated loop) or lastprivate (for simd directives with several
9170 // collapsed or ordered loops).
9171 if (DVar.CKind == OMPC_unknown)
9172 DSAStack->addDSA(D, E: LoopDeclRefExpr, A: PredeterminedCKind, PrivateCopy: PrivateRef);
9173 }
9174 }
9175 }
9176 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9177}
9178
9179namespace {
9180// Utility for OpenMP doacross clause kind
9181class OMPDoacrossKind {
9182public:
9183 bool isSource(const OMPDoacrossClause *C) {
9184 return C->getDependenceType() == OMPC_DOACROSS_source ||
9185 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9186 }
9187 bool isSink(const OMPDoacrossClause *C) {
9188 return C->getDependenceType() == OMPC_DOACROSS_sink;
9189 }
9190 bool isSinkIter(const OMPDoacrossClause *C) {
9191 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9192 }
9193};
9194} // namespace
9195/// Called on a for stmt to check and extract its iteration space
9196/// for further processing (such as collapsing).
9197static bool checkOpenMPIterationSpace(
9198 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9199 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9200 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9201 Expr *OrderedLoopCountExpr,
9202 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9203 llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
9204 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9205 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9206 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9207 // OpenMP [2.9.1, Canonical Loop Form]
9208 // for (init-expr; test-expr; incr-expr) structured-block
9209 // for (range-decl: range-expr) structured-block
9210 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(Val: S))
9211 S = CanonLoop->getLoopStmt();
9212 auto *For = dyn_cast_or_null<ForStmt>(Val: S);
9213 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(Val: S);
9214 // Ranged for is supported only in OpenMP 5.0.
9215 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9216 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
9217 SemaRef.Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_not_for)
9218 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9219 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion) << TotalNestedLoopCount
9220 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9221 if (TotalNestedLoopCount > 1) {
9222 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9223 SemaRef.Diag(Loc: DSA.getConstructLoc(),
9224 DiagID: diag::note_omp_collapse_ordered_expr)
9225 << 2 << CollapseLoopCountExpr->getSourceRange()
9226 << OrderedLoopCountExpr->getSourceRange();
9227 else if (CollapseLoopCountExpr)
9228 SemaRef.Diag(Loc: CollapseLoopCountExpr->getExprLoc(),
9229 DiagID: diag::note_omp_collapse_ordered_expr)
9230 << 0 << CollapseLoopCountExpr->getSourceRange();
9231 else if (OrderedLoopCountExpr)
9232 SemaRef.Diag(Loc: OrderedLoopCountExpr->getExprLoc(),
9233 DiagID: diag::note_omp_collapse_ordered_expr)
9234 << 1 << OrderedLoopCountExpr->getSourceRange();
9235 }
9236 return true;
9237 }
9238 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9239 "No loop body.");
9240 // Postpone analysis in dependent contexts for ranged for loops.
9241 if (CXXFor && SemaRef.CurContext->isDependentContext())
9242 return false;
9243
9244 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9245 For ? For->getForLoc() : CXXFor->getForLoc(),
9246 CollapsedLoopVarDecls);
9247
9248 // Check init.
9249 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9250 if (ISC.checkAndSetInit(S: Init))
9251 return true;
9252
9253 bool HasErrors = false;
9254
9255 // Check loop variable's type.
9256 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9257 // OpenMP [2.6, Canonical Loop Form]
9258 // Var is one of the following:
9259 // A variable of signed or unsigned integer type.
9260 // For C++, a variable of a random access iterator type.
9261 // For C, a variable of a pointer type.
9262 QualType VarType = LCDecl->getType().getNonReferenceType();
9263 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9264 !VarType->isPointerType() &&
9265 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9266 SemaRef.Diag(Loc: Init->getBeginLoc(), DiagID: diag::err_omp_loop_variable_type)
9267 << SemaRef.getLangOpts().CPlusPlus;
9268 HasErrors = true;
9269 }
9270
9271 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9272 // a Construct
9273 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9274 // parallel for construct is (are) private.
9275 // The loop iteration variable in the associated for-loop of a simd
9276 // construct with just one associated for-loop is linear with a
9277 // constant-linear-step that is the increment of the associated for-loop.
9278 // Exclude loop var from the list of variables with implicitly defined data
9279 // sharing attributes.
9280 VarsWithImplicitDSA.erase(Val: LCDecl);
9281
9282 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9283
9284 // Check test-expr.
9285 HasErrors |= ISC.checkAndSetCond(S: For ? For->getCond() : CXXFor->getCond());
9286
9287 // Check incr-expr.
9288 HasErrors |= ISC.checkAndSetInc(S: For ? For->getInc() : CXXFor->getInc());
9289 }
9290
9291 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9292 return HasErrors;
9293
9294 // Build the loop's iteration space representation.
9295 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9296 S: DSA.getCurScope(), Cond: For ? For->getCond() : CXXFor->getCond(), Captures);
9297 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9298 ISC.buildNumIterations(S: DSA.getCurScope(), ResultIterSpaces,
9299 LimitedType: (isOpenMPWorksharingDirective(DKind) ||
9300 isOpenMPGenericLoopDirective(DKind) ||
9301 isOpenMPTaskLoopDirective(DKind) ||
9302 isOpenMPDistributeDirective(DKind) ||
9303 isOpenMPLoopTransformationDirective(DKind)),
9304 Captures);
9305 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9306 ISC.buildCounterVar(Captures, DSA);
9307 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9308 ISC.buildPrivateCounterVar();
9309 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9310 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9311 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9312 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9313 ISC.getConditionSrcRange();
9314 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9315 ISC.getIncrementSrcRange();
9316 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9317 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9318 ISC.isStrictTestOp();
9319 std::tie(args&: ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9320 args&: ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9321 ISC.buildMinMaxValues(S: DSA.getCurScope(), Captures);
9322 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9323 ISC.buildFinalCondition(S: DSA.getCurScope());
9324 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9325 ISC.doesInitDependOnLC();
9326 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9327 ISC.doesCondDependOnLC();
9328 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9329 ISC.getLoopDependentIdx();
9330
9331 HasErrors |=
9332 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9333 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9334 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9335 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9336 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9337 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9338 if (!HasErrors && DSA.isOrderedRegion()) {
9339 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9340 if (CurrentNestedLoopCount <
9341 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9342 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9343 NumLoop: CurrentNestedLoopCount,
9344 NumIterations: ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9345 DSA.getOrderedRegionParam().second->setLoopCounter(
9346 NumLoop: CurrentNestedLoopCount,
9347 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9348 }
9349 }
9350 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9351 auto *DependC = dyn_cast<OMPDependClause>(Val: Pair.first);
9352 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Val: Pair.first);
9353 unsigned NumLoops =
9354 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9355 if (CurrentNestedLoopCount >= NumLoops) {
9356 // Erroneous case - clause has some problems.
9357 continue;
9358 }
9359 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9360 Pair.second.size() <= CurrentNestedLoopCount) {
9361 // Erroneous case - clause has some problems.
9362 DependC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: nullptr);
9363 continue;
9364 }
9365 OMPDoacrossKind ODK;
9366 if (DoacrossC && ODK.isSink(C: DoacrossC) &&
9367 Pair.second.size() <= CurrentNestedLoopCount) {
9368 // Erroneous case - clause has some problems.
9369 DoacrossC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: nullptr);
9370 continue;
9371 }
9372 Expr *CntValue;
9373 SourceLocation DepLoc =
9374 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9375 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9376 (DoacrossC && ODK.isSource(C: DoacrossC)))
9377 CntValue = ISC.buildOrderedLoopData(
9378 S: DSA.getCurScope(),
9379 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9380 Loc: DepLoc);
9381 else if (DoacrossC && ODK.isSinkIter(C: DoacrossC)) {
9382 Expr *Cnt = SemaRef
9383 .DefaultLvalueConversion(
9384 E: ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9385 .get();
9386 if (!Cnt)
9387 continue;
9388 // build CounterVar - 1
9389 Expr *Inc =
9390 SemaRef.ActOnIntegerConstant(Loc: DoacrossC->getColonLoc(), /*Val=*/1)
9391 .get();
9392 CntValue = ISC.buildOrderedLoopData(
9393 S: DSA.getCurScope(),
9394 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9395 Loc: DepLoc, Inc, OOK: clang::OO_Minus);
9396 } else
9397 CntValue = ISC.buildOrderedLoopData(
9398 S: DSA.getCurScope(),
9399 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9400 Loc: DepLoc, Inc: Pair.second[CurrentNestedLoopCount].first,
9401 OOK: Pair.second[CurrentNestedLoopCount].second);
9402 if (DependC)
9403 DependC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: CntValue);
9404 else
9405 DoacrossC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: CntValue);
9406 }
9407 }
9408
9409 return HasErrors;
9410}
9411
9412/// Build 'VarRef = Start.
9413static ExprResult
9414buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9415 ExprResult Start, bool IsNonRectangularLB,
9416 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9417 // Build 'VarRef = Start.
9418 ExprResult NewStart = IsNonRectangularLB
9419 ? Start.get()
9420 : tryBuildCapture(SemaRef, Capture: Start.get(), Captures);
9421 if (!NewStart.isUsable())
9422 return ExprError();
9423 if (!SemaRef.Context.hasSameType(T1: NewStart.get()->getType(),
9424 T2: VarRef.get()->getType())) {
9425 NewStart = SemaRef.PerformImplicitConversion(
9426 From: NewStart.get(), ToType: VarRef.get()->getType(), Action: AssignmentAction::Converting,
9427 /*AllowExplicit=*/true);
9428 if (!NewStart.isUsable())
9429 return ExprError();
9430 }
9431
9432 ExprResult Init =
9433 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: NewStart.get());
9434 return Init;
9435}
9436
9437/// Build 'VarRef = Start + Iter * Step'.
9438static ExprResult buildCounterUpdate(
9439 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9440 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9441 bool IsNonRectangularLB,
9442 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9443 // Add parentheses (for debugging purposes only).
9444 Iter = SemaRef.ActOnParenExpr(L: Loc, R: Loc, E: Iter.get());
9445 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9446 !Step.isUsable())
9447 return ExprError();
9448
9449 ExprResult NewStep = Step;
9450 if (Captures)
9451 NewStep = tryBuildCapture(SemaRef, Capture: Step.get(), Captures&: *Captures);
9452 if (NewStep.isInvalid())
9453 return ExprError();
9454 ExprResult Update =
9455 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Mul, LHSExpr: Iter.get(), RHSExpr: NewStep.get());
9456 if (!Update.isUsable())
9457 return ExprError();
9458
9459 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9460 // 'VarRef = Start (+|-) Iter * Step'.
9461 if (!Start.isUsable())
9462 return ExprError();
9463 ExprResult NewStart = SemaRef.ActOnParenExpr(L: Loc, R: Loc, E: Start.get());
9464 if (!NewStart.isUsable())
9465 return ExprError();
9466 if (Captures && !IsNonRectangularLB)
9467 NewStart = tryBuildCapture(SemaRef, Capture: Start.get(), Captures&: *Captures);
9468 if (NewStart.isInvalid())
9469 return ExprError();
9470
9471 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9472 ExprResult SavedUpdate = Update;
9473 ExprResult UpdateVal;
9474 if (VarRef.get()->getType()->isOverloadableType() ||
9475 NewStart.get()->getType()->isOverloadableType() ||
9476 Update.get()->getType()->isOverloadableType()) {
9477 Sema::TentativeAnalysisScope Trap(SemaRef);
9478
9479 Update =
9480 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: NewStart.get());
9481 if (Update.isUsable()) {
9482 UpdateVal =
9483 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: Subtract ? BO_SubAssign : BO_AddAssign,
9484 LHSExpr: VarRef.get(), RHSExpr: SavedUpdate.get());
9485 if (UpdateVal.isUsable()) {
9486 Update = SemaRef.CreateBuiltinBinOp(OpLoc: Loc, Opc: BO_Comma, LHSExpr: Update.get(),
9487 RHSExpr: UpdateVal.get());
9488 }
9489 }
9490 }
9491
9492 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9493 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9494 Update = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: Subtract ? BO_Sub : BO_Add,
9495 LHSExpr: NewStart.get(), RHSExpr: SavedUpdate.get());
9496 if (!Update.isUsable())
9497 return ExprError();
9498
9499 if (!SemaRef.Context.hasSameType(T1: Update.get()->getType(),
9500 T2: VarRef.get()->getType())) {
9501 Update = SemaRef.PerformImplicitConversion(
9502 From: Update.get(), ToType: VarRef.get()->getType(), Action: AssignmentAction::Converting,
9503 /*AllowExplicit=*/true);
9504 if (!Update.isUsable())
9505 return ExprError();
9506 }
9507
9508 Update = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: Update.get());
9509 }
9510 return Update;
9511}
9512
9513/// Convert integer expression \a E to make it have at least \a Bits
9514/// bits.
9515static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9516 if (E == nullptr)
9517 return ExprError();
9518 ASTContext &C = SemaRef.Context;
9519 QualType OldType = E->getType();
9520 unsigned HasBits = C.getTypeSize(T: OldType);
9521 if (HasBits >= Bits)
9522 return ExprResult(E);
9523 // OK to convert to signed, because new type has more bits than old.
9524 QualType NewType = C.getIntTypeForBitwidth(DestWidth: Bits, /*Signed=*/true);
9525 return SemaRef.PerformImplicitConversion(
9526 From: E, ToType: NewType, Action: AssignmentAction::Converting, /*AllowExplicit=*/true);
9527}
9528
9529/// Check if the given expression \a E is a constant integer that fits
9530/// into \a Bits bits.
9531static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9532 if (E == nullptr)
9533 return false;
9534 if (std::optional<llvm::APSInt> Result =
9535 E->getIntegerConstantExpr(Ctx: SemaRef.Context))
9536 return Signed ? Result->isSignedIntN(N: Bits) : Result->isIntN(N: Bits);
9537 return false;
9538}
9539
9540/// Build preinits statement for the given declarations.
9541static Stmt *buildPreInits(ASTContext &Context,
9542 MutableArrayRef<Decl *> PreInits) {
9543 if (!PreInits.empty()) {
9544 return new (Context) DeclStmt(
9545 DeclGroupRef::Create(C&: Context, Decls: PreInits.begin(), NumDecls: PreInits.size()),
9546 SourceLocation(), SourceLocation());
9547 }
9548 return nullptr;
9549}
9550
9551/// Append the \p Item or the content of a CompoundStmt to the list \p
9552/// TargetList.
9553///
9554/// A CompoundStmt is used as container in case multiple statements need to be
9555/// stored in lieu of using an explicit list. Flattening is necessary because
9556/// contained DeclStmts need to be visible after the execution of the list. Used
9557/// for OpenMP pre-init declarations/statements.
9558static void appendFlattenedStmtList(SmallVectorImpl<Stmt *> &TargetList,
9559 Stmt *Item) {
9560 // nullptr represents an empty list.
9561 if (!Item)
9562 return;
9563
9564 if (auto *CS = dyn_cast<CompoundStmt>(Val: Item))
9565 llvm::append_range(C&: TargetList, R: CS->body());
9566 else
9567 TargetList.push_back(Elt: Item);
9568}
9569
9570/// Build preinits statement for the given declarations.
9571static Stmt *
9572buildPreInits(ASTContext &Context,
9573 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9574 if (!Captures.empty()) {
9575 SmallVector<Decl *, 16> PreInits;
9576 for (const auto &Pair : Captures)
9577 PreInits.push_back(Elt: Pair.second->getDecl());
9578 return buildPreInits(Context, PreInits);
9579 }
9580 return nullptr;
9581}
9582
9583/// Build pre-init statement for the given statements.
9584static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9585 if (PreInits.empty())
9586 return nullptr;
9587
9588 SmallVector<Stmt *> Stmts;
9589 for (Stmt *S : PreInits)
9590 appendFlattenedStmtList(TargetList&: Stmts, Item: S);
9591 return CompoundStmt::Create(C: Context, Stmts: PreInits, FPFeatures: FPOptionsOverride(), LB: {}, RB: {});
9592}
9593
9594/// Build postupdate expression for the given list of postupdates expressions.
9595static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9596 Expr *PostUpdate = nullptr;
9597 if (!PostUpdates.empty()) {
9598 for (Expr *E : PostUpdates) {
9599 Expr *ConvE = S.BuildCStyleCastExpr(
9600 LParenLoc: E->getExprLoc(),
9601 Ty: S.Context.getTrivialTypeSourceInfo(T: S.Context.VoidTy),
9602 RParenLoc: E->getExprLoc(), Op: E)
9603 .get();
9604 PostUpdate = PostUpdate
9605 ? S.CreateBuiltinBinOp(OpLoc: ConvE->getExprLoc(), Opc: BO_Comma,
9606 LHSExpr: PostUpdate, RHSExpr: ConvE)
9607 .get()
9608 : ConvE;
9609 }
9610 }
9611 return PostUpdate;
9612}
9613
9614/// Look for variables declared in the body parts of a for-loop nest. Used
9615/// for verifying loop nest structure before performing a loop collapse
9616/// operation.
9617class ForVarDeclFinder : public DynamicRecursiveASTVisitor {
9618 int NestingDepth = 0;
9619 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9620
9621public:
9622 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
9623 : VarDecls(VD) {}
9624
9625 bool VisitForStmt(ForStmt *F) override {
9626 ++NestingDepth;
9627 TraverseStmt(S: F->getBody());
9628 --NestingDepth;
9629 return false;
9630 }
9631
9632 bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override {
9633 ++NestingDepth;
9634 TraverseStmt(S: RF->getBody());
9635 --NestingDepth;
9636 return false;
9637 }
9638
9639 bool VisitVarDecl(VarDecl *D) override {
9640 Decl *C = D->getCanonicalDecl();
9641 if (NestingDepth > 0)
9642 VarDecls.insert(Ptr: C);
9643 return true;
9644 }
9645};
9646
9647/// Called on a for stmt to check itself and nested loops (if any).
9648/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9649/// number of collapsed loops otherwise.
9650static unsigned
9651checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9652 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9653 DSAStackTy &DSA,
9654 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9655 OMPLoopBasedDirective::HelperExprs &Built) {
9656 // If either of the loop expressions exist and contain errors, we bail out
9657 // early because diagnostics have already been emitted and we can't reliably
9658 // check more about the loop.
9659 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
9660 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
9661 return 0;
9662
9663 unsigned NestedLoopCount = 1;
9664 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9665 !isOpenMPLoopTransformationDirective(DKind);
9666 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
9667
9668 if (CollapseLoopCountExpr) {
9669 // Found 'collapse' clause - calculate collapse number.
9670 Expr::EvalResult Result;
9671 if (!CollapseLoopCountExpr->isValueDependent() &&
9672 CollapseLoopCountExpr->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext())) {
9673 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9674
9675 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9676 FVDF.TraverseStmt(S: AStmt);
9677 } else {
9678 Built.clear(/*Size=*/1);
9679 return 1;
9680 }
9681 }
9682 unsigned OrderedLoopCount = 1;
9683 if (OrderedLoopCountExpr) {
9684 // Found 'ordered' clause - calculate collapse number.
9685 Expr::EvalResult EVResult;
9686 if (!OrderedLoopCountExpr->isValueDependent() &&
9687 OrderedLoopCountExpr->EvaluateAsInt(Result&: EVResult,
9688 Ctx: SemaRef.getASTContext())) {
9689 llvm::APSInt Result = EVResult.Val.getInt();
9690 if (Result.getLimitedValue() < NestedLoopCount) {
9691 SemaRef.Diag(Loc: OrderedLoopCountExpr->getExprLoc(),
9692 DiagID: diag::err_omp_wrong_ordered_loop_count)
9693 << OrderedLoopCountExpr->getSourceRange();
9694 SemaRef.Diag(Loc: CollapseLoopCountExpr->getExprLoc(),
9695 DiagID: diag::note_collapse_loop_count)
9696 << CollapseLoopCountExpr->getSourceRange();
9697 }
9698 OrderedLoopCount = Result.getLimitedValue();
9699 } else {
9700 Built.clear(/*Size=*/1);
9701 return 1;
9702 }
9703 }
9704 // This is helper routine for loop directives (e.g., 'for', 'simd',
9705 // 'for simd', etc.).
9706 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9707 unsigned NumLoops = std::max(a: OrderedLoopCount, b: NestedLoopCount);
9708 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9709 if (!OMPLoopBasedDirective::doForAllLoops(
9710 CurStmt: AStmt->IgnoreContainers(IgnoreCaptured: !isOpenMPLoopTransformationDirective(DKind)),
9711 TryImperfectlyNestedLoops: SupportsNonPerfectlyNested, NumLoops,
9712 Callback: [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9713 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9714 &IterSpaces, &Captures,
9715 &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
9716 if (checkOpenMPIterationSpace(
9717 DKind, S: CurStmt, SemaRef, DSA, CurrentNestedLoopCount: Cnt, NestedLoopCount,
9718 TotalNestedLoopCount: NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9719 VarsWithImplicitDSA, ResultIterSpaces: IterSpaces, Captures,
9720 CollapsedLoopVarDecls))
9721 return true;
9722 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9723 IterSpaces[Cnt].CounterVar) {
9724 // Handle initialization of captured loop iterator variables.
9725 auto *DRE = cast<DeclRefExpr>(Val: IterSpaces[Cnt].CounterVar);
9726 if (isa<OMPCapturedExprDecl>(Val: DRE->getDecl())) {
9727 Captures[DRE] = DRE;
9728 }
9729 }
9730 return false;
9731 },
9732 OnTransformationCallback: [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9733 Stmt *DependentPreInits = Transform->getPreInits();
9734 if (!DependentPreInits)
9735 return;
9736
9737 // Search for pre-init declared variables that need to be captured
9738 // to be referenceable inside the directive.
9739 SmallVector<Stmt *> Constituents;
9740 appendFlattenedStmtList(TargetList&: Constituents, Item: DependentPreInits);
9741 for (Stmt *S : Constituents) {
9742 if (auto *DC = dyn_cast<DeclStmt>(Val: S)) {
9743 for (Decl *C : DC->decls()) {
9744 auto *D = cast<VarDecl>(Val: C);
9745 DeclRefExpr *Ref = buildDeclRefExpr(
9746 S&: SemaRef, D, Ty: D->getType().getNonReferenceType(),
9747 Loc: Transform->getBeginLoc());
9748 Captures[Ref] = Ref;
9749 }
9750 }
9751 }
9752 }))
9753 return 0;
9754
9755 Built.clear(/*size=*/Size: NestedLoopCount);
9756
9757 if (SemaRef.CurContext->isDependentContext())
9758 return NestedLoopCount;
9759
9760 // An example of what is generated for the following code:
9761 //
9762 // #pragma omp simd collapse(2) ordered(2)
9763 // for (i = 0; i < NI; ++i)
9764 // for (k = 0; k < NK; ++k)
9765 // for (j = J0; j < NJ; j+=2) {
9766 // <loop body>
9767 // }
9768 //
9769 // We generate the code below.
9770 // Note: the loop body may be outlined in CodeGen.
9771 // Note: some counters may be C++ classes, operator- is used to find number of
9772 // iterations and operator+= to calculate counter value.
9773 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9774 // or i64 is currently supported).
9775 //
9776 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9777 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9778 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9779 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9780 // // similar updates for vars in clauses (e.g. 'linear')
9781 // <loop body (using local i and j)>
9782 // }
9783 // i = NI; // assign final values of counters
9784 // j = NJ;
9785 //
9786
9787 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9788 // the iteration counts of the collapsed for loops.
9789 // Precondition tests if there is at least one iteration (all conditions are
9790 // true).
9791 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9792 Expr *N0 = IterSpaces[0].NumIterations;
9793 ExprResult LastIteration32 = widenIterationCount(
9794 /*Bits=*/32,
9795 E: SemaRef
9796 .PerformImplicitConversion(From: N0->IgnoreImpCasts(), ToType: N0->getType(),
9797 Action: AssignmentAction::Converting,
9798 /*AllowExplicit=*/true)
9799 .get(),
9800 SemaRef);
9801 ExprResult LastIteration64 = widenIterationCount(
9802 /*Bits=*/64,
9803 E: SemaRef
9804 .PerformImplicitConversion(From: N0->IgnoreImpCasts(), ToType: N0->getType(),
9805 Action: AssignmentAction::Converting,
9806 /*AllowExplicit=*/true)
9807 .get(),
9808 SemaRef);
9809
9810 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9811 return NestedLoopCount;
9812
9813 ASTContext &C = SemaRef.Context;
9814 bool AllCountsNeedLessThan32Bits = C.getTypeSize(T: N0->getType()) < 32;
9815
9816 Scope *CurScope = DSA.getCurScope();
9817 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9818 if (PreCond.isUsable()) {
9819 PreCond =
9820 SemaRef.BuildBinOp(S: CurScope, OpLoc: PreCond.get()->getExprLoc(), Opc: BO_LAnd,
9821 LHSExpr: PreCond.get(), RHSExpr: IterSpaces[Cnt].PreCond);
9822 }
9823 Expr *N = IterSpaces[Cnt].NumIterations;
9824 SourceLocation Loc = N->getExprLoc();
9825 AllCountsNeedLessThan32Bits &= C.getTypeSize(T: N->getType()) < 32;
9826 if (LastIteration32.isUsable())
9827 LastIteration32 = SemaRef.BuildBinOp(
9828 S: CurScope, OpLoc: Loc, Opc: BO_Mul, LHSExpr: LastIteration32.get(),
9829 RHSExpr: SemaRef
9830 .PerformImplicitConversion(From: N->IgnoreImpCasts(), ToType: N->getType(),
9831 Action: AssignmentAction::Converting,
9832 /*AllowExplicit=*/true)
9833 .get());
9834 if (LastIteration64.isUsable())
9835 LastIteration64 = SemaRef.BuildBinOp(
9836 S: CurScope, OpLoc: Loc, Opc: BO_Mul, LHSExpr: LastIteration64.get(),
9837 RHSExpr: SemaRef
9838 .PerformImplicitConversion(From: N->IgnoreImpCasts(), ToType: N->getType(),
9839 Action: AssignmentAction::Converting,
9840 /*AllowExplicit=*/true)
9841 .get());
9842 }
9843
9844 // Choose either the 32-bit or 64-bit version.
9845 ExprResult LastIteration = LastIteration64;
9846 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9847 (LastIteration32.isUsable() &&
9848 C.getTypeSize(T: LastIteration32.get()->getType()) == 32 &&
9849 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9850 fitsInto(
9851 /*Bits=*/32,
9852 Signed: LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9853 E: LastIteration64.get(), SemaRef))))
9854 LastIteration = LastIteration32;
9855 QualType VType = LastIteration.get()->getType();
9856 QualType RealVType = VType;
9857 QualType StrideVType = VType;
9858 if (isOpenMPTaskLoopDirective(DKind)) {
9859 VType =
9860 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9861 StrideVType =
9862 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9863 }
9864
9865 if (!LastIteration.isUsable())
9866 return 0;
9867
9868 // Save the number of iterations.
9869 ExprResult NumIterations = LastIteration;
9870 {
9871 LastIteration = SemaRef.BuildBinOp(
9872 S: CurScope, OpLoc: LastIteration.get()->getExprLoc(), Opc: BO_Sub,
9873 LHSExpr: LastIteration.get(),
9874 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
9875 if (!LastIteration.isUsable())
9876 return 0;
9877 }
9878
9879 // Calculate the last iteration number beforehand instead of doing this on
9880 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9881 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(Ctx: SemaRef.Context);
9882 ExprResult CalcLastIteration;
9883 if (!IsConstant) {
9884 ExprResult SaveRef =
9885 tryBuildCapture(SemaRef, Capture: LastIteration.get(), Captures);
9886 LastIteration = SaveRef;
9887
9888 // Prepare SaveRef + 1.
9889 NumIterations = SemaRef.BuildBinOp(
9890 S: CurScope, OpLoc: SaveRef.get()->getExprLoc(), Opc: BO_Add, LHSExpr: SaveRef.get(),
9891 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
9892 if (!NumIterations.isUsable())
9893 return 0;
9894 }
9895
9896 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9897
9898 // Build variables passed into runtime, necessary for worksharing directives.
9899 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9900 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
9901 isOpenMPDistributeDirective(DKind) ||
9902 isOpenMPGenericLoopDirective(DKind) ||
9903 isOpenMPLoopTransformationDirective(DKind)) {
9904 // Lower bound variable, initialized with zero.
9905 VarDecl *LBDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.lb");
9906 LB = buildDeclRefExpr(S&: SemaRef, D: LBDecl, Ty: VType, Loc: InitLoc);
9907 SemaRef.AddInitializerToDecl(dcl: LBDecl,
9908 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
9909 /*DirectInit=*/false);
9910
9911 // Upper bound variable, initialized with last iteration number.
9912 VarDecl *UBDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.ub");
9913 UB = buildDeclRefExpr(S&: SemaRef, D: UBDecl, Ty: VType, Loc: InitLoc);
9914 SemaRef.AddInitializerToDecl(dcl: UBDecl, init: LastIteration.get(),
9915 /*DirectInit=*/false);
9916
9917 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9918 // This will be used to implement clause 'lastprivate'.
9919 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(DestWidth: 32, Signed: true);
9920 VarDecl *ILDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: Int32Ty, Name: ".omp.is_last");
9921 IL = buildDeclRefExpr(S&: SemaRef, D: ILDecl, Ty: Int32Ty, Loc: InitLoc);
9922 SemaRef.AddInitializerToDecl(dcl: ILDecl,
9923 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
9924 /*DirectInit=*/false);
9925
9926 // Stride variable returned by runtime (we initialize it to 1 by default).
9927 VarDecl *STDecl =
9928 buildVarDecl(SemaRef, Loc: InitLoc, Type: StrideVType, Name: ".omp.stride");
9929 ST = buildDeclRefExpr(S&: SemaRef, D: STDecl, Ty: StrideVType, Loc: InitLoc);
9930 SemaRef.AddInitializerToDecl(dcl: STDecl,
9931 init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 1).get(),
9932 /*DirectInit=*/false);
9933
9934 // Build expression: UB = min(UB, LastIteration)
9935 // It is necessary for CodeGen of directives with static scheduling.
9936 ExprResult IsUBGreater = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_GT,
9937 LHSExpr: UB.get(), RHSExpr: LastIteration.get());
9938 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9939 QuestionLoc: LastIteration.get()->getExprLoc(), ColonLoc: InitLoc, CondExpr: IsUBGreater.get(),
9940 LHSExpr: LastIteration.get(), RHSExpr: UB.get());
9941 EUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: UB.get(),
9942 RHSExpr: CondOp.get());
9943 EUB = SemaRef.ActOnFinishFullExpr(Expr: EUB.get(), /*DiscardedValue=*/false);
9944
9945 // If we have a combined directive that combines 'distribute', 'for' or
9946 // 'simd' we need to be able to access the bounds of the schedule of the
9947 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9948 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9949 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
9950 // Lower bound variable, initialized with zero.
9951 VarDecl *CombLBDecl =
9952 buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.comb.lb");
9953 CombLB = buildDeclRefExpr(S&: SemaRef, D: CombLBDecl, Ty: VType, Loc: InitLoc);
9954 SemaRef.AddInitializerToDecl(
9955 dcl: CombLBDecl, init: SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
9956 /*DirectInit=*/false);
9957
9958 // Upper bound variable, initialized with last iteration number.
9959 VarDecl *CombUBDecl =
9960 buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.comb.ub");
9961 CombUB = buildDeclRefExpr(S&: SemaRef, D: CombUBDecl, Ty: VType, Loc: InitLoc);
9962 SemaRef.AddInitializerToDecl(dcl: CombUBDecl, init: LastIteration.get(),
9963 /*DirectInit=*/false);
9964
9965 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9966 S: CurScope, OpLoc: InitLoc, Opc: BO_GT, LHSExpr: CombUB.get(), RHSExpr: LastIteration.get());
9967 ExprResult CombCondOp =
9968 SemaRef.ActOnConditionalOp(QuestionLoc: InitLoc, ColonLoc: InitLoc, CondExpr: CombIsUBGreater.get(),
9969 LHSExpr: LastIteration.get(), RHSExpr: CombUB.get());
9970 CombEUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: CombUB.get(),
9971 RHSExpr: CombCondOp.get());
9972 CombEUB =
9973 SemaRef.ActOnFinishFullExpr(Expr: CombEUB.get(), /*DiscardedValue=*/false);
9974
9975 const CapturedDecl *CD = cast<CapturedStmt>(Val: AStmt)->getCapturedDecl();
9976 // We expect to have at least 2 more parameters than the 'parallel'
9977 // directive does - the lower and upper bounds of the previous schedule.
9978 assert(CD->getNumParams() >= 4 &&
9979 "Unexpected number of parameters in loop combined directive");
9980
9981 // Set the proper type for the bounds given what we learned from the
9982 // enclosed loops.
9983 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/i: 2);
9984 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/i: 3);
9985
9986 // Previous lower and upper bounds are obtained from the region
9987 // parameters.
9988 PrevLB =
9989 buildDeclRefExpr(S&: SemaRef, D: PrevLBDecl, Ty: PrevLBDecl->getType(), Loc: InitLoc);
9990 PrevUB =
9991 buildDeclRefExpr(S&: SemaRef, D: PrevUBDecl, Ty: PrevUBDecl->getType(), Loc: InitLoc);
9992 }
9993 }
9994
9995 // Build the iteration variable and its initialization before loop.
9996 ExprResult IV;
9997 ExprResult Init, CombInit;
9998 {
9999 VarDecl *IVDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: RealVType, Name: ".omp.iv");
10000 IV = buildDeclRefExpr(S&: SemaRef, D: IVDecl, Ty: RealVType, Loc: InitLoc);
10001 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10002 isOpenMPGenericLoopDirective(DKind) ||
10003 isOpenMPTaskLoopDirective(DKind) ||
10004 isOpenMPDistributeDirective(DKind) ||
10005 isOpenMPLoopTransformationDirective(DKind))
10006 ? LB.get()
10007 : SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 0).get();
10008 Init = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: RHS);
10009 Init = SemaRef.ActOnFinishFullExpr(Expr: Init.get(), /*DiscardedValue=*/false);
10010
10011 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10012 Expr *CombRHS =
10013 (isOpenMPWorksharingDirective(DKind) ||
10014 isOpenMPGenericLoopDirective(DKind) ||
10015 isOpenMPTaskLoopDirective(DKind) ||
10016 isOpenMPDistributeDirective(DKind))
10017 ? CombLB.get()
10018 : SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 0).get();
10019 CombInit =
10020 SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: CombRHS);
10021 CombInit =
10022 SemaRef.ActOnFinishFullExpr(Expr: CombInit.get(), /*DiscardedValue=*/false);
10023 }
10024 }
10025
10026 bool UseStrictCompare =
10027 RealVType->hasUnsignedIntegerRepresentation() &&
10028 llvm::all_of(Range&: IterSpaces, P: [](const LoopIterationSpace &LIS) {
10029 return LIS.IsStrictCompare;
10030 });
10031 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10032 // unsigned IV)) for worksharing loops.
10033 SourceLocation CondLoc = AStmt->getBeginLoc();
10034 Expr *BoundUB = UB.get();
10035 if (UseStrictCompare) {
10036 BoundUB =
10037 SemaRef
10038 .BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundUB,
10039 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10040 .get();
10041 BoundUB =
10042 SemaRef.ActOnFinishFullExpr(Expr: BoundUB, /*DiscardedValue=*/false).get();
10043 }
10044 ExprResult Cond =
10045 (isOpenMPWorksharingDirective(DKind) ||
10046 isOpenMPGenericLoopDirective(DKind) ||
10047 isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
10048 isOpenMPLoopTransformationDirective(DKind))
10049 ? SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc,
10050 Opc: UseStrictCompare ? BO_LT : BO_LE, LHSExpr: IV.get(),
10051 RHSExpr: BoundUB)
10052 : SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LT, LHSExpr: IV.get(),
10053 RHSExpr: NumIterations.get());
10054 ExprResult CombDistCond;
10055 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10056 CombDistCond = SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LT, LHSExpr: IV.get(),
10057 RHSExpr: NumIterations.get());
10058 }
10059
10060 ExprResult CombCond;
10061 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10062 Expr *BoundCombUB = CombUB.get();
10063 if (UseStrictCompare) {
10064 BoundCombUB =
10065 SemaRef
10066 .BuildBinOp(
10067 S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundCombUB,
10068 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10069 .get();
10070 BoundCombUB =
10071 SemaRef.ActOnFinishFullExpr(Expr: BoundCombUB, /*DiscardedValue=*/false)
10072 .get();
10073 }
10074 CombCond =
10075 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE,
10076 LHSExpr: IV.get(), RHSExpr: BoundCombUB);
10077 }
10078 // Loop increment (IV = IV + 1)
10079 SourceLocation IncLoc = AStmt->getBeginLoc();
10080 ExprResult Inc =
10081 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: IV.get(),
10082 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: IncLoc, Val: 1).get());
10083 if (!Inc.isUsable())
10084 return 0;
10085 Inc = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: Inc.get());
10086 Inc = SemaRef.ActOnFinishFullExpr(Expr: Inc.get(), /*DiscardedValue=*/false);
10087 if (!Inc.isUsable())
10088 return 0;
10089
10090 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10091 // Used for directives with static scheduling.
10092 // In combined construct, add combined version that use CombLB and CombUB
10093 // base variables for the update
10094 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10095 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
10096 isOpenMPGenericLoopDirective(DKind) ||
10097 isOpenMPDistributeDirective(DKind) ||
10098 isOpenMPLoopTransformationDirective(DKind)) {
10099 // LB + ST
10100 NextLB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: LB.get(), RHSExpr: ST.get());
10101 if (!NextLB.isUsable())
10102 return 0;
10103 // LB = LB + ST
10104 NextLB =
10105 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: LB.get(), RHSExpr: NextLB.get());
10106 NextLB =
10107 SemaRef.ActOnFinishFullExpr(Expr: NextLB.get(), /*DiscardedValue=*/false);
10108 if (!NextLB.isUsable())
10109 return 0;
10110 // UB + ST
10111 NextUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: UB.get(), RHSExpr: ST.get());
10112 if (!NextUB.isUsable())
10113 return 0;
10114 // UB = UB + ST
10115 NextUB =
10116 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: UB.get(), RHSExpr: NextUB.get());
10117 NextUB =
10118 SemaRef.ActOnFinishFullExpr(Expr: NextUB.get(), /*DiscardedValue=*/false);
10119 if (!NextUB.isUsable())
10120 return 0;
10121 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10122 CombNextLB =
10123 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: CombLB.get(), RHSExpr: ST.get());
10124 if (!NextLB.isUsable())
10125 return 0;
10126 // LB = LB + ST
10127 CombNextLB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: CombLB.get(),
10128 RHSExpr: CombNextLB.get());
10129 CombNextLB = SemaRef.ActOnFinishFullExpr(Expr: CombNextLB.get(),
10130 /*DiscardedValue=*/false);
10131 if (!CombNextLB.isUsable())
10132 return 0;
10133 // UB + ST
10134 CombNextUB =
10135 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: CombUB.get(), RHSExpr: ST.get());
10136 if (!CombNextUB.isUsable())
10137 return 0;
10138 // UB = UB + ST
10139 CombNextUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: CombUB.get(),
10140 RHSExpr: CombNextUB.get());
10141 CombNextUB = SemaRef.ActOnFinishFullExpr(Expr: CombNextUB.get(),
10142 /*DiscardedValue=*/false);
10143 if (!CombNextUB.isUsable())
10144 return 0;
10145 }
10146 }
10147
10148 // Create increment expression for distribute loop when combined in a same
10149 // directive with for as IV = IV + ST; ensure upper bound expression based
10150 // on PrevUB instead of NumIterations - used to implement 'for' when found
10151 // in combination with 'distribute', like in 'distribute parallel for'
10152 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10153 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10154 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10155 DistCond = SemaRef.BuildBinOp(
10156 S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE, LHSExpr: IV.get(), RHSExpr: BoundUB);
10157 assert(DistCond.isUsable() && "distribute cond expr was not built");
10158
10159 DistInc =
10160 SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Add, LHSExpr: IV.get(), RHSExpr: ST.get());
10161 assert(DistInc.isUsable() && "distribute inc expr was not built");
10162 DistInc = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Assign, LHSExpr: IV.get(),
10163 RHSExpr: DistInc.get());
10164 DistInc =
10165 SemaRef.ActOnFinishFullExpr(Expr: DistInc.get(), /*DiscardedValue=*/false);
10166 assert(DistInc.isUsable() && "distribute inc expr was not built");
10167
10168 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10169 // construct
10170 ExprResult NewPrevUB = PrevUB;
10171 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10172 if (!SemaRef.Context.hasSameType(T1: UB.get()->getType(),
10173 T2: PrevUB.get()->getType())) {
10174 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10175 LParenLoc: DistEUBLoc,
10176 Ty: SemaRef.Context.getTrivialTypeSourceInfo(T: UB.get()->getType()),
10177 RParenLoc: DistEUBLoc, Op: NewPrevUB.get());
10178 if (!NewPrevUB.isUsable())
10179 return 0;
10180 }
10181 ExprResult IsUBGreater = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistEUBLoc, Opc: BO_GT,
10182 LHSExpr: UB.get(), RHSExpr: NewPrevUB.get());
10183 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10184 QuestionLoc: DistEUBLoc, ColonLoc: DistEUBLoc, CondExpr: IsUBGreater.get(), LHSExpr: NewPrevUB.get(), RHSExpr: UB.get());
10185 PrevEUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Assign, LHSExpr: UB.get(),
10186 RHSExpr: CondOp.get());
10187 PrevEUB =
10188 SemaRef.ActOnFinishFullExpr(Expr: PrevEUB.get(), /*DiscardedValue=*/false);
10189
10190 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10191 // parallel for is in combination with a distribute directive with
10192 // schedule(static, 1)
10193 Expr *BoundPrevUB = PrevUB.get();
10194 if (UseStrictCompare) {
10195 BoundPrevUB =
10196 SemaRef
10197 .BuildBinOp(
10198 S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundPrevUB,
10199 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10200 .get();
10201 BoundPrevUB =
10202 SemaRef.ActOnFinishFullExpr(Expr: BoundPrevUB, /*DiscardedValue=*/false)
10203 .get();
10204 }
10205 ParForInDistCond =
10206 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE,
10207 LHSExpr: IV.get(), RHSExpr: BoundPrevUB);
10208 }
10209
10210 // Build updates and final values of the loop counters.
10211 bool HasErrors = false;
10212 Built.Counters.resize(N: NestedLoopCount);
10213 Built.Inits.resize(N: NestedLoopCount);
10214 Built.Updates.resize(N: NestedLoopCount);
10215 Built.Finals.resize(N: NestedLoopCount);
10216 Built.DependentCounters.resize(N: NestedLoopCount);
10217 Built.DependentInits.resize(N: NestedLoopCount);
10218 Built.FinalsConditions.resize(N: NestedLoopCount);
10219 {
10220 // We implement the following algorithm for obtaining the
10221 // original loop iteration variable values based on the
10222 // value of the collapsed loop iteration variable IV.
10223 //
10224 // Let n+1 be the number of collapsed loops in the nest.
10225 // Iteration variables (I0, I1, .... In)
10226 // Iteration counts (N0, N1, ... Nn)
10227 //
10228 // Acc = IV;
10229 //
10230 // To compute Ik for loop k, 0 <= k <= n, generate:
10231 // Prod = N(k+1) * N(k+2) * ... * Nn;
10232 // Ik = Acc / Prod;
10233 // Acc -= Ik * Prod;
10234 //
10235 ExprResult Acc = IV;
10236 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10237 LoopIterationSpace &IS = IterSpaces[Cnt];
10238 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10239 ExprResult Iter;
10240
10241 // Compute prod
10242 ExprResult Prod = SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get();
10243 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10244 Prod = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Mul, LHSExpr: Prod.get(),
10245 RHSExpr: IterSpaces[K].NumIterations);
10246
10247 // Iter = Acc / Prod
10248 // If there is at least one more inner loop to avoid
10249 // multiplication by 1.
10250 if (Cnt + 1 < NestedLoopCount)
10251 Iter =
10252 SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Div, LHSExpr: Acc.get(), RHSExpr: Prod.get());
10253 else
10254 Iter = Acc;
10255 if (!Iter.isUsable()) {
10256 HasErrors = true;
10257 break;
10258 }
10259
10260 // Update Acc:
10261 // Acc -= Iter * Prod
10262 // Check if there is at least one more inner loop to avoid
10263 // multiplication by 1.
10264 if (Cnt + 1 < NestedLoopCount)
10265 Prod = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Mul, LHSExpr: Iter.get(),
10266 RHSExpr: Prod.get());
10267 else
10268 Prod = Iter;
10269 Acc = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Sub, LHSExpr: Acc.get(), RHSExpr: Prod.get());
10270
10271 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10272 auto *VD = cast<VarDecl>(Val: cast<DeclRefExpr>(Val: IS.CounterVar)->getDecl());
10273 DeclRefExpr *CounterVar = buildDeclRefExpr(
10274 S&: SemaRef, D: VD, Ty: IS.CounterVar->getType(), Loc: IS.CounterVar->getExprLoc(),
10275 /*RefersToCapture=*/true);
10276 ExprResult Init =
10277 buildCounterInit(SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar,
10278 Start: IS.CounterInit, IsNonRectangularLB: IS.IsNonRectangularLB, Captures);
10279 if (!Init.isUsable()) {
10280 HasErrors = true;
10281 break;
10282 }
10283 ExprResult Update = buildCounterUpdate(
10284 SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar, Start: IS.CounterInit, Iter,
10285 Step: IS.CounterStep, Subtract: IS.Subtract, IsNonRectangularLB: IS.IsNonRectangularLB, Captures: &Captures);
10286 if (!Update.isUsable()) {
10287 HasErrors = true;
10288 break;
10289 }
10290
10291 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10292 ExprResult Final =
10293 buildCounterUpdate(SemaRef, S: CurScope, Loc: UpdLoc, VarRef: CounterVar,
10294 Start: IS.CounterInit, Iter: IS.NumIterations, Step: IS.CounterStep,
10295 Subtract: IS.Subtract, IsNonRectangularLB: IS.IsNonRectangularLB, Captures: &Captures);
10296 if (!Final.isUsable()) {
10297 HasErrors = true;
10298 break;
10299 }
10300
10301 if (!Update.isUsable() || !Final.isUsable()) {
10302 HasErrors = true;
10303 break;
10304 }
10305 // Save results
10306 Built.Counters[Cnt] = IS.CounterVar;
10307 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10308 Built.Inits[Cnt] = Init.get();
10309 Built.Updates[Cnt] = Update.get();
10310 Built.Finals[Cnt] = Final.get();
10311 Built.DependentCounters[Cnt] = nullptr;
10312 Built.DependentInits[Cnt] = nullptr;
10313 Built.FinalsConditions[Cnt] = nullptr;
10314 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10315 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10316 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10317 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10318 }
10319 }
10320 }
10321
10322 if (HasErrors)
10323 return 0;
10324
10325 // Save results
10326 Built.IterationVarRef = IV.get();
10327 Built.LastIteration = LastIteration.get();
10328 Built.NumIterations = NumIterations.get();
10329 Built.CalcLastIteration = SemaRef
10330 .ActOnFinishFullExpr(Expr: CalcLastIteration.get(),
10331 /*DiscardedValue=*/false)
10332 .get();
10333 Built.PreCond = PreCond.get();
10334 Built.PreInits = buildPreInits(Context&: C, Captures);
10335 Built.Cond = Cond.get();
10336 Built.Init = Init.get();
10337 Built.Inc = Inc.get();
10338 Built.LB = LB.get();
10339 Built.UB = UB.get();
10340 Built.IL = IL.get();
10341 Built.ST = ST.get();
10342 Built.EUB = EUB.get();
10343 Built.NLB = NextLB.get();
10344 Built.NUB = NextUB.get();
10345 Built.PrevLB = PrevLB.get();
10346 Built.PrevUB = PrevUB.get();
10347 Built.DistInc = DistInc.get();
10348 Built.PrevEUB = PrevEUB.get();
10349 Built.DistCombinedFields.LB = CombLB.get();
10350 Built.DistCombinedFields.UB = CombUB.get();
10351 Built.DistCombinedFields.EUB = CombEUB.get();
10352 Built.DistCombinedFields.Init = CombInit.get();
10353 Built.DistCombinedFields.Cond = CombCond.get();
10354 Built.DistCombinedFields.NLB = CombNextLB.get();
10355 Built.DistCombinedFields.NUB = CombNextUB.get();
10356 Built.DistCombinedFields.DistCond = CombDistCond.get();
10357 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10358
10359 return NestedLoopCount;
10360}
10361
10362static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
10363 auto CollapseClauses =
10364 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10365 if (CollapseClauses.begin() != CollapseClauses.end())
10366 return (*CollapseClauses.begin())->getNumForLoops();
10367 return nullptr;
10368}
10369
10370static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
10371 auto OrderedClauses =
10372 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10373 if (OrderedClauses.begin() != OrderedClauses.end())
10374 return (*OrderedClauses.begin())->getNumForLoops();
10375 return nullptr;
10376}
10377
10378static bool checkSimdlenSafelenSpecified(Sema &S,
10379 const ArrayRef<OMPClause *> Clauses) {
10380 const OMPSafelenClause *Safelen = nullptr;
10381 const OMPSimdlenClause *Simdlen = nullptr;
10382
10383 for (const OMPClause *Clause : Clauses) {
10384 if (Clause->getClauseKind() == OMPC_safelen)
10385 Safelen = cast<OMPSafelenClause>(Val: Clause);
10386 else if (Clause->getClauseKind() == OMPC_simdlen)
10387 Simdlen = cast<OMPSimdlenClause>(Val: Clause);
10388 if (Safelen && Simdlen)
10389 break;
10390 }
10391
10392 if (Simdlen && Safelen) {
10393 const Expr *SimdlenLength = Simdlen->getSimdlen();
10394 const Expr *SafelenLength = Safelen->getSafelen();
10395 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10396 SimdlenLength->isInstantiationDependent() ||
10397 SimdlenLength->containsUnexpandedParameterPack())
10398 return false;
10399 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10400 SafelenLength->isInstantiationDependent() ||
10401 SafelenLength->containsUnexpandedParameterPack())
10402 return false;
10403 Expr::EvalResult SimdlenResult, SafelenResult;
10404 SimdlenLength->EvaluateAsInt(Result&: SimdlenResult, Ctx: S.Context);
10405 SafelenLength->EvaluateAsInt(Result&: SafelenResult, Ctx: S.Context);
10406 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10407 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10408 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10409 // If both simdlen and safelen clauses are specified, the value of the
10410 // simdlen parameter must be less than or equal to the value of the safelen
10411 // parameter.
10412 if (SimdlenRes > SafelenRes) {
10413 S.Diag(Loc: SimdlenLength->getExprLoc(),
10414 DiagID: diag::err_omp_wrong_simdlen_safelen_values)
10415 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10416 return true;
10417 }
10418 }
10419 return false;
10420}
10421
10422StmtResult SemaOpenMP::ActOnOpenMPSimdDirective(
10423 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10424 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10425 if (!AStmt)
10426 return StmtError();
10427
10428 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_simd, AStmt);
10429
10430 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10431 OMPLoopBasedDirective::HelperExprs B;
10432 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10433 // define the nested loops number.
10434 unsigned NestedLoopCount = checkOpenMPLoop(
10435 DKind: OMPD_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
10436 AStmt: CS, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
10437 if (NestedLoopCount == 0)
10438 return StmtError();
10439
10440 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10441 return StmtError();
10442
10443 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
10444 return StmtError();
10445
10446 auto *SimdDirective = OMPSimdDirective::Create(
10447 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10448 return SimdDirective;
10449}
10450
10451StmtResult SemaOpenMP::ActOnOpenMPForDirective(
10452 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10453 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10454 if (!AStmt)
10455 return StmtError();
10456
10457 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10458 OMPLoopBasedDirective::HelperExprs B;
10459 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10460 // define the nested loops number.
10461 unsigned NestedLoopCount = checkOpenMPLoop(
10462 DKind: OMPD_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
10463 AStmt, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
10464 if (NestedLoopCount == 0)
10465 return StmtError();
10466
10467 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10468 return StmtError();
10469
10470 auto *ForDirective = OMPForDirective::Create(
10471 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
10472 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10473 return ForDirective;
10474}
10475
10476StmtResult SemaOpenMP::ActOnOpenMPForSimdDirective(
10477 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10478 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10479 if (!AStmt)
10480 return StmtError();
10481
10482 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_for_simd, AStmt);
10483
10484 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10485 OMPLoopBasedDirective::HelperExprs B;
10486 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10487 // define the nested loops number.
10488 unsigned NestedLoopCount =
10489 checkOpenMPLoop(DKind: OMPD_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
10490 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
10491 VarsWithImplicitDSA, Built&: B);
10492 if (NestedLoopCount == 0)
10493 return StmtError();
10494
10495 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10496 return StmtError();
10497
10498 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
10499 return StmtError();
10500
10501 return OMPForSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
10502 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10503}
10504
10505static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind,
10506 Stmt *AStmt, DSAStackTy *Stack) {
10507 if (!AStmt)
10508 return true;
10509
10510 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10511 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
10512 auto BaseStmt = AStmt;
10513 while (auto *CS = dyn_cast_or_null<CapturedStmt>(Val: BaseStmt))
10514 BaseStmt = CS->getCapturedStmt();
10515 if (auto *C = dyn_cast_or_null<CompoundStmt>(Val: BaseStmt)) {
10516 auto S = C->children();
10517 if (S.begin() == S.end())
10518 return true;
10519 // All associated statements must be '#pragma omp section' except for
10520 // the first one.
10521 for (Stmt *SectionStmt : llvm::drop_begin(RangeOrContainer&: S)) {
10522 if (!SectionStmt || !isa<OMPSectionDirective>(Val: SectionStmt)) {
10523 if (SectionStmt)
10524 SemaRef.Diag(Loc: SectionStmt->getBeginLoc(),
10525 DiagID: diag::err_omp_sections_substmt_not_section)
10526 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
10527 return true;
10528 }
10529 cast<OMPSectionDirective>(Val: SectionStmt)
10530 ->setHasCancel(Stack->isCancelRegion());
10531 }
10532 } else {
10533 SemaRef.Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_sections_not_compound_stmt)
10534 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
10535 return true;
10536 }
10537 return false;
10538}
10539
10540StmtResult
10541SemaOpenMP::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
10542 Stmt *AStmt, SourceLocation StartLoc,
10543 SourceLocation EndLoc) {
10544 if (checkSectionsDirective(SemaRef, DKind: OMPD_sections, AStmt, DSAStack))
10545 return StmtError();
10546
10547 SemaRef.setFunctionHasBranchProtectedScope();
10548
10549 return OMPSectionsDirective::Create(
10550 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
10551 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10552}
10553
10554StmtResult SemaOpenMP::ActOnOpenMPSectionDirective(Stmt *AStmt,
10555 SourceLocation StartLoc,
10556 SourceLocation EndLoc) {
10557 if (!AStmt)
10558 return StmtError();
10559
10560 SemaRef.setFunctionHasBranchProtectedScope();
10561 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10562
10563 return OMPSectionDirective::Create(C: getASTContext(), StartLoc, EndLoc, AssociatedStmt: AStmt,
10564 DSAStack->isCancelRegion());
10565}
10566
10567static Expr *getDirectCallExpr(Expr *E) {
10568 E = E->IgnoreParenCasts()->IgnoreImplicit();
10569 if (auto *CE = dyn_cast<CallExpr>(Val: E))
10570 if (CE->getDirectCallee())
10571 return E;
10572 return nullptr;
10573}
10574
10575StmtResult
10576SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
10577 Stmt *AStmt, SourceLocation StartLoc,
10578 SourceLocation EndLoc) {
10579 if (!AStmt)
10580 return StmtError();
10581
10582 Stmt *S = cast<CapturedStmt>(Val: AStmt)->getCapturedStmt();
10583
10584 // 5.1 OpenMP
10585 // expression-stmt : an expression statement with one of the following forms:
10586 // expression = target-call ( [expression-list] );
10587 // target-call ( [expression-list] );
10588
10589 SourceLocation TargetCallLoc;
10590
10591 if (!SemaRef.CurContext->isDependentContext()) {
10592 Expr *TargetCall = nullptr;
10593
10594 auto *E = dyn_cast<Expr>(Val: S);
10595 if (!E) {
10596 Diag(Loc: S->getBeginLoc(), DiagID: diag::err_omp_dispatch_statement_call);
10597 return StmtError();
10598 }
10599
10600 E = E->IgnoreParenCasts()->IgnoreImplicit();
10601
10602 if (auto *BO = dyn_cast<BinaryOperator>(Val: E)) {
10603 if (BO->getOpcode() == BO_Assign)
10604 TargetCall = getDirectCallExpr(E: BO->getRHS());
10605 } else {
10606 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(Val: E))
10607 if (COCE->getOperator() == OO_Equal)
10608 TargetCall = getDirectCallExpr(E: COCE->getArg(Arg: 1));
10609 if (!TargetCall)
10610 TargetCall = getDirectCallExpr(E);
10611 }
10612 if (!TargetCall) {
10613 Diag(Loc: E->getBeginLoc(), DiagID: diag::err_omp_dispatch_statement_call);
10614 return StmtError();
10615 }
10616 TargetCallLoc = TargetCall->getExprLoc();
10617 }
10618
10619 SemaRef.setFunctionHasBranchProtectedScope();
10620
10621 return OMPDispatchDirective::Create(C: getASTContext(), StartLoc, EndLoc,
10622 Clauses, AssociatedStmt: AStmt, TargetCallLoc);
10623}
10624
10625static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
10626 OpenMPDirectiveKind K,
10627 DSAStackTy *Stack) {
10628 bool ErrorFound = false;
10629 for (OMPClause *C : Clauses) {
10630 if (auto *LPC = dyn_cast<OMPLastprivateClause>(Val: C)) {
10631 for (Expr *RefExpr : LPC->varlist()) {
10632 SourceLocation ELoc;
10633 SourceRange ERange;
10634 Expr *SimpleRefExpr = RefExpr;
10635 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange);
10636 if (ValueDecl *D = Res.first) {
10637 auto &&Info = Stack->isLoopControlVariable(D);
10638 if (!Info.first) {
10639 unsigned OMPVersion = S.getLangOpts().OpenMP;
10640 S.Diag(Loc: ELoc, DiagID: diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10641 << getOpenMPDirectiveName(D: K, Ver: OMPVersion);
10642 ErrorFound = true;
10643 }
10644 }
10645 }
10646 }
10647 }
10648 return ErrorFound;
10649}
10650
10651StmtResult SemaOpenMP::ActOnOpenMPGenericLoopDirective(
10652 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10653 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10654 if (!AStmt)
10655 return StmtError();
10656
10657 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10658 // A list item may not appear in a lastprivate clause unless it is the
10659 // loop iteration variable of a loop that is associated with the construct.
10660 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_loop, DSAStack))
10661 return StmtError();
10662
10663 setBranchProtectedScope(SemaRef, DKind: OMPD_loop, AStmt);
10664
10665 OMPLoopDirective::HelperExprs B;
10666 // In presence of clause 'collapse', it will define the nested loops number.
10667 unsigned NestedLoopCount = checkOpenMPLoop(
10668 DKind: OMPD_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses), OrderedLoopCountExpr: getOrderedNumberExpr(Clauses),
10669 AStmt, SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
10670 if (NestedLoopCount == 0)
10671 return StmtError();
10672
10673 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10674 "omp loop exprs were not built");
10675
10676 return OMPGenericLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
10677 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10678}
10679
10680StmtResult SemaOpenMP::ActOnOpenMPTeamsGenericLoopDirective(
10681 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10682 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10683 if (!AStmt)
10684 return StmtError();
10685
10686 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10687 // A list item may not appear in a lastprivate clause unless it is the
10688 // loop iteration variable of a loop that is associated with the construct.
10689 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_teams_loop, DSAStack))
10690 return StmtError();
10691
10692 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_teams_loop, AStmt);
10693
10694 OMPLoopDirective::HelperExprs B;
10695 // In presence of clause 'collapse', it will define the nested loops number.
10696 unsigned NestedLoopCount =
10697 checkOpenMPLoop(DKind: OMPD_teams_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
10698 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
10699 VarsWithImplicitDSA, Built&: B);
10700 if (NestedLoopCount == 0)
10701 return StmtError();
10702
10703 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10704 "omp loop exprs were not built");
10705
10706 DSAStack->setParentTeamsRegionLoc(StartLoc);
10707
10708 return OMPTeamsGenericLoopDirective::Create(
10709 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10710}
10711
10712StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsGenericLoopDirective(
10713 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10714 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10715 if (!AStmt)
10716 return StmtError();
10717
10718 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10719 // A list item may not appear in a lastprivate clause unless it is the
10720 // loop iteration variable of a loop that is associated with the construct.
10721 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_target_teams_loop,
10722 DSAStack))
10723 return StmtError();
10724
10725 CapturedStmt *CS =
10726 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams_loop, AStmt);
10727
10728 OMPLoopDirective::HelperExprs B;
10729 // In presence of clause 'collapse', it will define the nested loops number.
10730 unsigned NestedLoopCount =
10731 checkOpenMPLoop(DKind: OMPD_target_teams_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
10732 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
10733 VarsWithImplicitDSA, Built&: B);
10734 if (NestedLoopCount == 0)
10735 return StmtError();
10736
10737 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10738 "omp loop exprs were not built");
10739
10740 return OMPTargetTeamsGenericLoopDirective::Create(
10741 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
10742 CanBeParallelFor: teamsLoopCanBeParallelFor(AStmt, SemaRef));
10743}
10744
10745StmtResult SemaOpenMP::ActOnOpenMPParallelGenericLoopDirective(
10746 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10747 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10748 if (!AStmt)
10749 return StmtError();
10750
10751 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10752 // A list item may not appear in a lastprivate clause unless it is the
10753 // loop iteration variable of a loop that is associated with the construct.
10754 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_parallel_loop,
10755 DSAStack))
10756 return StmtError();
10757
10758 CapturedStmt *CS =
10759 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_loop, AStmt);
10760
10761 OMPLoopDirective::HelperExprs B;
10762 // In presence of clause 'collapse', it will define the nested loops number.
10763 unsigned NestedLoopCount =
10764 checkOpenMPLoop(DKind: OMPD_parallel_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
10765 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
10766 VarsWithImplicitDSA, Built&: B);
10767 if (NestedLoopCount == 0)
10768 return StmtError();
10769
10770 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10771 "omp loop exprs were not built");
10772
10773 return OMPParallelGenericLoopDirective::Create(
10774 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10775}
10776
10777StmtResult SemaOpenMP::ActOnOpenMPTargetParallelGenericLoopDirective(
10778 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10779 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10780 if (!AStmt)
10781 return StmtError();
10782
10783 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10784 // A list item may not appear in a lastprivate clause unless it is the
10785 // loop iteration variable of a loop that is associated with the construct.
10786 if (checkGenericLoopLastprivate(S&: SemaRef, Clauses, K: OMPD_target_parallel_loop,
10787 DSAStack))
10788 return StmtError();
10789
10790 CapturedStmt *CS =
10791 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_loop, AStmt);
10792
10793 OMPLoopDirective::HelperExprs B;
10794 // In presence of clause 'collapse', it will define the nested loops number.
10795 unsigned NestedLoopCount =
10796 checkOpenMPLoop(DKind: OMPD_target_parallel_loop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
10797 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
10798 VarsWithImplicitDSA, Built&: B);
10799 if (NestedLoopCount == 0)
10800 return StmtError();
10801
10802 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10803 "omp loop exprs were not built");
10804
10805 return OMPTargetParallelGenericLoopDirective::Create(
10806 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10807}
10808
10809StmtResult SemaOpenMP::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
10810 Stmt *AStmt,
10811 SourceLocation StartLoc,
10812 SourceLocation EndLoc) {
10813 if (!AStmt)
10814 return StmtError();
10815
10816 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10817
10818 SemaRef.setFunctionHasBranchProtectedScope();
10819
10820 // OpenMP [2.7.3, single Construct, Restrictions]
10821 // The copyprivate clause must not be used with the nowait clause.
10822 const OMPClause *Nowait = nullptr;
10823 const OMPClause *Copyprivate = nullptr;
10824 for (const OMPClause *Clause : Clauses) {
10825 if (Clause->getClauseKind() == OMPC_nowait)
10826 Nowait = Clause;
10827 else if (Clause->getClauseKind() == OMPC_copyprivate)
10828 Copyprivate = Clause;
10829 if (Copyprivate && Nowait) {
10830 Diag(Loc: Copyprivate->getBeginLoc(),
10831 DiagID: diag::err_omp_single_copyprivate_with_nowait);
10832 Diag(Loc: Nowait->getBeginLoc(), DiagID: diag::note_omp_nowait_clause_here);
10833 return StmtError();
10834 }
10835 }
10836
10837 return OMPSingleDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
10838 AssociatedStmt: AStmt);
10839}
10840
10841StmtResult SemaOpenMP::ActOnOpenMPMasterDirective(Stmt *AStmt,
10842 SourceLocation StartLoc,
10843 SourceLocation EndLoc) {
10844 if (!AStmt)
10845 return StmtError();
10846
10847 SemaRef.setFunctionHasBranchProtectedScope();
10848
10849 return OMPMasterDirective::Create(C: getASTContext(), StartLoc, EndLoc, AssociatedStmt: AStmt);
10850}
10851
10852StmtResult SemaOpenMP::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
10853 Stmt *AStmt,
10854 SourceLocation StartLoc,
10855 SourceLocation EndLoc) {
10856 if (!AStmt)
10857 return StmtError();
10858
10859 SemaRef.setFunctionHasBranchProtectedScope();
10860
10861 return OMPMaskedDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
10862 AssociatedStmt: AStmt);
10863}
10864
10865StmtResult SemaOpenMP::ActOnOpenMPCriticalDirective(
10866 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
10867 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
10868 if (!AStmt)
10869 return StmtError();
10870
10871 bool ErrorFound = false;
10872 llvm::APSInt Hint;
10873 SourceLocation HintLoc;
10874 bool DependentHint = false;
10875 for (const OMPClause *C : Clauses) {
10876 if (C->getClauseKind() == OMPC_hint) {
10877 if (!DirName.getName()) {
10878 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_hint_clause_no_name);
10879 ErrorFound = true;
10880 }
10881 Expr *E = cast<OMPHintClause>(Val: C)->getHint();
10882 if (E->isTypeDependent() || E->isValueDependent() ||
10883 E->isInstantiationDependent()) {
10884 DependentHint = true;
10885 } else {
10886 Hint = E->EvaluateKnownConstInt(Ctx: getASTContext());
10887 HintLoc = C->getBeginLoc();
10888 }
10889 }
10890 }
10891 if (ErrorFound)
10892 return StmtError();
10893 const auto Pair = DSAStack->getCriticalWithHint(Name: DirName);
10894 if (Pair.first && DirName.getName() && !DependentHint) {
10895 if (llvm::APSInt::compareValues(I1: Hint, I2: Pair.second) != 0) {
10896 Diag(Loc: StartLoc, DiagID: diag::err_omp_critical_with_hint);
10897 if (HintLoc.isValid())
10898 Diag(Loc: HintLoc, DiagID: diag::note_omp_critical_hint_here)
10899 << 0 << toString(I: Hint, /*Radix=*/10, /*Signed=*/false);
10900 else
10901 Diag(Loc: StartLoc, DiagID: diag::note_omp_critical_no_hint) << 0;
10902 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
10903 Diag(Loc: C->getBeginLoc(), DiagID: diag::note_omp_critical_hint_here)
10904 << 1
10905 << toString(I: C->getHint()->EvaluateKnownConstInt(Ctx: getASTContext()),
10906 /*Radix=*/10, /*Signed=*/false);
10907 } else {
10908 Diag(Loc: Pair.first->getBeginLoc(), DiagID: diag::note_omp_critical_no_hint) << 1;
10909 }
10910 }
10911 }
10912
10913 SemaRef.setFunctionHasBranchProtectedScope();
10914
10915 auto *Dir = OMPCriticalDirective::Create(C: getASTContext(), Name: DirName, StartLoc,
10916 EndLoc, Clauses, AssociatedStmt: AStmt);
10917 if (!Pair.first && DirName.getName() && !DependentHint)
10918 DSAStack->addCriticalWithHint(D: Dir, Hint);
10919 return Dir;
10920}
10921
10922StmtResult SemaOpenMP::ActOnOpenMPParallelForDirective(
10923 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10924 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10925 if (!AStmt)
10926 return StmtError();
10927
10928 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_for, AStmt);
10929
10930 OMPLoopBasedDirective::HelperExprs B;
10931 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10932 // define the nested loops number.
10933 unsigned NestedLoopCount =
10934 checkOpenMPLoop(DKind: OMPD_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
10935 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt, SemaRef, DSA&: *DSAStack,
10936 VarsWithImplicitDSA, Built&: B);
10937 if (NestedLoopCount == 0)
10938 return StmtError();
10939
10940 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10941 return StmtError();
10942
10943 return OMPParallelForDirective::Create(
10944 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
10945 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10946}
10947
10948StmtResult SemaOpenMP::ActOnOpenMPParallelForSimdDirective(
10949 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10950 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10951 if (!AStmt)
10952 return StmtError();
10953
10954 CapturedStmt *CS =
10955 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_for_simd, AStmt);
10956
10957 OMPLoopBasedDirective::HelperExprs B;
10958 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10959 // define the nested loops number.
10960 unsigned NestedLoopCount =
10961 checkOpenMPLoop(DKind: OMPD_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
10962 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
10963 VarsWithImplicitDSA, Built&: B);
10964 if (NestedLoopCount == 0)
10965 return StmtError();
10966
10967 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10968 return StmtError();
10969
10970 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
10971 return StmtError();
10972
10973 return OMPParallelForSimdDirective::Create(
10974 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10975}
10976
10977StmtResult SemaOpenMP::ActOnOpenMPParallelMasterDirective(
10978 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10979 SourceLocation EndLoc) {
10980 if (!AStmt)
10981 return StmtError();
10982
10983 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_master, AStmt);
10984
10985 return OMPParallelMasterDirective::Create(
10986 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
10987 DSAStack->getTaskgroupReductionRef());
10988}
10989
10990StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedDirective(
10991 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10992 SourceLocation EndLoc) {
10993 if (!AStmt)
10994 return StmtError();
10995
10996 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_masked, AStmt);
10997
10998 return OMPParallelMaskedDirective::Create(
10999 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11000 DSAStack->getTaskgroupReductionRef());
11001}
11002
11003StmtResult SemaOpenMP::ActOnOpenMPParallelSectionsDirective(
11004 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11005 SourceLocation EndLoc) {
11006 if (checkSectionsDirective(SemaRef, DKind: OMPD_parallel_sections, AStmt, DSAStack))
11007 return StmtError();
11008
11009 SemaRef.setFunctionHasBranchProtectedScope();
11010
11011 return OMPParallelSectionsDirective::Create(
11012 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11013 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11014}
11015
11016/// Find and diagnose mutually exclusive clause kinds.
11017static bool checkMutuallyExclusiveClauses(
11018 Sema &S, ArrayRef<OMPClause *> Clauses,
11019 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11020 const OMPClause *PrevClause = nullptr;
11021 bool ErrorFound = false;
11022 for (const OMPClause *C : Clauses) {
11023 if (llvm::is_contained(Range&: MutuallyExclusiveClauses, Element: C->getClauseKind())) {
11024 if (!PrevClause) {
11025 PrevClause = C;
11026 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11027 S.Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_clauses_mutually_exclusive)
11028 << getOpenMPClauseNameForDiag(C: C->getClauseKind())
11029 << getOpenMPClauseNameForDiag(C: PrevClause->getClauseKind());
11030 S.Diag(Loc: PrevClause->getBeginLoc(), DiagID: diag::note_omp_previous_clause)
11031 << getOpenMPClauseNameForDiag(C: PrevClause->getClauseKind());
11032 ErrorFound = true;
11033 }
11034 }
11035 }
11036 return ErrorFound;
11037}
11038
11039StmtResult SemaOpenMP::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
11040 Stmt *AStmt,
11041 SourceLocation StartLoc,
11042 SourceLocation EndLoc) {
11043 if (!AStmt)
11044 return StmtError();
11045
11046 // OpenMP 5.0, 2.10.1 task Construct
11047 // If a detach clause appears on the directive, then a mergeable clause cannot
11048 // appear on the same directive.
11049 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
11050 MutuallyExclusiveClauses: {OMPC_detach, OMPC_mergeable}))
11051 return StmtError();
11052
11053 setBranchProtectedScope(SemaRef, DKind: OMPD_task, AStmt);
11054
11055 return OMPTaskDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11056 AssociatedStmt: AStmt, DSAStack->isCancelRegion());
11057}
11058
11059StmtResult SemaOpenMP::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
11060 SourceLocation EndLoc) {
11061 return OMPTaskyieldDirective::Create(C: getASTContext(), StartLoc, EndLoc);
11062}
11063
11064StmtResult SemaOpenMP::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
11065 SourceLocation EndLoc) {
11066 return OMPBarrierDirective::Create(C: getASTContext(), StartLoc, EndLoc);
11067}
11068
11069StmtResult SemaOpenMP::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
11070 SourceLocation StartLoc,
11071 SourceLocation EndLoc,
11072 bool InExContext) {
11073 const OMPAtClause *AtC =
11074 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11075
11076 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11077 Diag(Loc: AtC->getAtKindKwLoc(), DiagID: diag::err_omp_unexpected_execution_modifier);
11078 return StmtError();
11079 }
11080
11081 const OMPSeverityClause *SeverityC =
11082 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11083 const OMPMessageClause *MessageC =
11084 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11085 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11086
11087 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11088 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11089 Diag(Loc: SeverityC->getSeverityKindKwLoc(), DiagID: diag::warn_diagnose_if_succeeded)
11090 << (ME ? cast<StringLiteral>(Val: ME)->getString() : "WARNING");
11091 else
11092 Diag(Loc: StartLoc, DiagID: diag::err_diagnose_if_succeeded)
11093 << (ME ? cast<StringLiteral>(Val: ME)->getString() : "ERROR");
11094 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11095 return StmtError();
11096 }
11097 return OMPErrorDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11098}
11099
11100StmtResult
11101SemaOpenMP::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
11102 SourceLocation StartLoc,
11103 SourceLocation EndLoc) {
11104 const OMPNowaitClause *NowaitC =
11105 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11106 bool HasDependC =
11107 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11108 .empty();
11109 if (NowaitC && !HasDependC) {
11110 Diag(Loc: StartLoc, DiagID: diag::err_omp_nowait_clause_without_depend);
11111 return StmtError();
11112 }
11113
11114 return OMPTaskwaitDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11115 Clauses);
11116}
11117
11118StmtResult
11119SemaOpenMP::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
11120 Stmt *AStmt, SourceLocation StartLoc,
11121 SourceLocation EndLoc) {
11122 if (!AStmt)
11123 return StmtError();
11124
11125 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11126
11127 SemaRef.setFunctionHasBranchProtectedScope();
11128
11129 return OMPTaskgroupDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11130 Clauses, AssociatedStmt: AStmt,
11131 DSAStack->getTaskgroupReductionRef());
11132}
11133
11134StmtResult SemaOpenMP::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
11135 SourceLocation StartLoc,
11136 SourceLocation EndLoc) {
11137 OMPFlushClause *FC = nullptr;
11138 OMPClause *OrderClause = nullptr;
11139 for (OMPClause *C : Clauses) {
11140 if (C->getClauseKind() == OMPC_flush)
11141 FC = cast<OMPFlushClause>(Val: C);
11142 else
11143 OrderClause = C;
11144 }
11145 unsigned OMPVersion = getLangOpts().OpenMP;
11146 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11147 SourceLocation MemOrderLoc;
11148 for (const OMPClause *C : Clauses) {
11149 if (C->getClauseKind() == OMPC_acq_rel ||
11150 C->getClauseKind() == OMPC_acquire ||
11151 C->getClauseKind() == OMPC_release ||
11152 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11153 if (MemOrderKind != OMPC_unknown) {
11154 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_several_mem_order_clauses)
11155 << getOpenMPDirectiveName(D: OMPD_flush, Ver: OMPVersion) << 1
11156 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11157 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
11158 << getOpenMPClauseNameForDiag(C: MemOrderKind);
11159 } else {
11160 MemOrderKind = C->getClauseKind();
11161 MemOrderLoc = C->getBeginLoc();
11162 }
11163 }
11164 }
11165 if (FC && OrderClause) {
11166 Diag(Loc: FC->getLParenLoc(), DiagID: diag::err_omp_flush_order_clause_and_list)
11167 << getOpenMPClauseNameForDiag(C: OrderClause->getClauseKind());
11168 Diag(Loc: OrderClause->getBeginLoc(), DiagID: diag::note_omp_flush_order_clause_here)
11169 << getOpenMPClauseNameForDiag(C: OrderClause->getClauseKind());
11170 return StmtError();
11171 }
11172 return OMPFlushDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11173}
11174
11175StmtResult SemaOpenMP::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
11176 SourceLocation StartLoc,
11177 SourceLocation EndLoc) {
11178 if (Clauses.empty()) {
11179 Diag(Loc: StartLoc, DiagID: diag::err_omp_depobj_expected);
11180 return StmtError();
11181 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11182 Diag(Loc: Clauses[0]->getBeginLoc(), DiagID: diag::err_omp_depobj_expected);
11183 return StmtError();
11184 }
11185 // Only depobj expression and another single clause is allowed.
11186 if (Clauses.size() > 2) {
11187 Diag(Loc: Clauses[2]->getBeginLoc(),
11188 DiagID: diag::err_omp_depobj_single_clause_expected);
11189 return StmtError();
11190 } else if (Clauses.size() < 1) {
11191 Diag(Loc: Clauses[0]->getEndLoc(), DiagID: diag::err_omp_depobj_single_clause_expected);
11192 return StmtError();
11193 }
11194 return OMPDepobjDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11195}
11196
11197StmtResult SemaOpenMP::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
11198 SourceLocation StartLoc,
11199 SourceLocation EndLoc) {
11200 // Check that exactly one clause is specified.
11201 if (Clauses.size() != 1) {
11202 Diag(Loc: Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11203 DiagID: diag::err_omp_scan_single_clause_expected);
11204 return StmtError();
11205 }
11206 // Check that scan directive is used in the scope of the OpenMP loop body.
11207 if (Scope *S = DSAStack->getCurScope()) {
11208 Scope *ParentS = S->getParent();
11209 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11210 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11211 unsigned OMPVersion = getLangOpts().OpenMP;
11212 return StmtError(Diag(Loc: StartLoc, DiagID: diag::err_omp_orphaned_device_directive)
11213 << getOpenMPDirectiveName(D: OMPD_scan, Ver: OMPVersion) << 5);
11214 }
11215 }
11216 // Check that only one instance of scan directives is used in the same outer
11217 // region.
11218 if (DSAStack->doesParentHasScanDirective()) {
11219 Diag(Loc: StartLoc, DiagID: diag::err_omp_several_directives_in_region) << "scan";
11220 Diag(DSAStack->getParentScanDirectiveLoc(),
11221 DiagID: diag::note_omp_previous_directive)
11222 << "scan";
11223 return StmtError();
11224 }
11225 DSAStack->setParentHasScanDirective(StartLoc);
11226 return OMPScanDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11227}
11228
11229StmtResult
11230SemaOpenMP::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
11231 Stmt *AStmt, SourceLocation StartLoc,
11232 SourceLocation EndLoc) {
11233 const OMPClause *DependFound = nullptr;
11234 const OMPClause *DependSourceClause = nullptr;
11235 const OMPClause *DependSinkClause = nullptr;
11236 const OMPClause *DoacrossFound = nullptr;
11237 const OMPClause *DoacrossSourceClause = nullptr;
11238 const OMPClause *DoacrossSinkClause = nullptr;
11239 bool ErrorFound = false;
11240 const OMPThreadsClause *TC = nullptr;
11241 const OMPSIMDClause *SC = nullptr;
11242 for (const OMPClause *C : Clauses) {
11243 auto DOC = dyn_cast<OMPDoacrossClause>(Val: C);
11244 auto DC = dyn_cast<OMPDependClause>(Val: C);
11245 if (DC || DOC) {
11246 DependFound = DC ? C : nullptr;
11247 DoacrossFound = DOC ? C : nullptr;
11248 OMPDoacrossKind ODK;
11249 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11250 (DOC && (ODK.isSource(C: DOC)))) {
11251 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11252 unsigned OMPVersion = getLangOpts().OpenMP;
11253 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_more_one_clause)
11254 << getOpenMPDirectiveName(D: OMPD_ordered, Ver: OMPVersion)
11255 << getOpenMPClauseNameForDiag(C: DC ? OMPC_depend : OMPC_doacross)
11256 << 2;
11257 ErrorFound = true;
11258 } else {
11259 if (DC)
11260 DependSourceClause = C;
11261 else
11262 DoacrossSourceClause = C;
11263 }
11264 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11265 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_sink_and_source_not_allowed)
11266 << (DC ? "depend" : "doacross") << 0;
11267 ErrorFound = true;
11268 }
11269 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11270 (DOC && (ODK.isSink(C: DOC) || ODK.isSinkIter(C: DOC)))) {
11271 if (DependSourceClause || DoacrossSourceClause) {
11272 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_sink_and_source_not_allowed)
11273 << (DC ? "depend" : "doacross") << 1;
11274 ErrorFound = true;
11275 }
11276 if (DC)
11277 DependSinkClause = C;
11278 else
11279 DoacrossSinkClause = C;
11280 }
11281 } else if (C->getClauseKind() == OMPC_threads) {
11282 TC = cast<OMPThreadsClause>(Val: C);
11283 } else if (C->getClauseKind() == OMPC_simd) {
11284 SC = cast<OMPSIMDClause>(Val: C);
11285 }
11286 }
11287 if (!ErrorFound && !SC &&
11288 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11289 // OpenMP [2.8.1,simd Construct, Restrictions]
11290 // An ordered construct with the simd clause is the only OpenMP construct
11291 // that can appear in the simd region.
11292 Diag(Loc: StartLoc, DiagID: diag::err_omp_prohibited_region_simd)
11293 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11294 ErrorFound = true;
11295 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11296 SourceLocation Loc =
11297 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11298 Diag(Loc, DiagID: diag::err_omp_depend_clause_thread_simd)
11299 << getOpenMPClauseNameForDiag(C: DependFound ? OMPC_depend : OMPC_doacross)
11300 << getOpenMPClauseNameForDiag(C: TC ? TC->getClauseKind()
11301 : SC->getClauseKind());
11302 ErrorFound = true;
11303 } else if ((DependFound || DoacrossFound) &&
11304 !DSAStack->getParentOrderedRegionParam().first) {
11305 SourceLocation Loc =
11306 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11307 Diag(Loc, DiagID: diag::err_omp_ordered_directive_without_param)
11308 << getOpenMPClauseNameForDiag(C: DependFound ? OMPC_depend
11309 : OMPC_doacross);
11310 ErrorFound = true;
11311 } else if (TC || Clauses.empty()) {
11312 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11313 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11314 Diag(Loc: ErrLoc, DiagID: diag::err_omp_ordered_directive_with_param)
11315 << (TC != nullptr);
11316 Diag(Loc: Param->getBeginLoc(), DiagID: diag::note_omp_ordered_param) << 1;
11317 ErrorFound = true;
11318 }
11319 }
11320 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11321 return StmtError();
11322
11323 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11324 // During execution of an iteration of a worksharing-loop or a loop nest
11325 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11326 // must not execute more than one ordered region corresponding to an ordered
11327 // construct without a depend clause.
11328 if (!DependFound && !DoacrossFound) {
11329 if (DSAStack->doesParentHasOrderedDirective()) {
11330 Diag(Loc: StartLoc, DiagID: diag::err_omp_several_directives_in_region) << "ordered";
11331 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11332 DiagID: diag::note_omp_previous_directive)
11333 << "ordered";
11334 return StmtError();
11335 }
11336 DSAStack->setParentHasOrderedDirective(StartLoc);
11337 }
11338
11339 if (AStmt) {
11340 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11341
11342 SemaRef.setFunctionHasBranchProtectedScope();
11343 }
11344
11345 return OMPOrderedDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11346 AssociatedStmt: AStmt);
11347}
11348
11349namespace {
11350/// Helper class for checking expression in 'omp atomic [update]'
11351/// construct.
11352class OpenMPAtomicUpdateChecker {
11353 /// Error results for atomic update expressions.
11354 enum ExprAnalysisErrorCode {
11355 /// A statement is not an expression statement.
11356 NotAnExpression,
11357 /// Expression is not builtin binary or unary operation.
11358 NotABinaryOrUnaryExpression,
11359 /// Unary operation is not post-/pre- increment/decrement operation.
11360 NotAnUnaryIncDecExpression,
11361 /// An expression is not of scalar type.
11362 NotAScalarType,
11363 /// A binary operation is not an assignment operation.
11364 NotAnAssignmentOp,
11365 /// RHS part of the binary operation is not a binary expression.
11366 NotABinaryExpression,
11367 /// RHS part is not additive/multiplicative/shift/bitwise binary
11368 /// expression.
11369 NotABinaryOperator,
11370 /// RHS binary operation does not have reference to the updated LHS
11371 /// part.
11372 NotAnUpdateExpression,
11373 /// An expression contains semantical error not related to
11374 /// 'omp atomic [update]'
11375 NotAValidExpression,
11376 /// No errors is found.
11377 NoError
11378 };
11379 /// Reference to Sema.
11380 Sema &SemaRef;
11381 /// A location for note diagnostics (when error is found).
11382 SourceLocation NoteLoc;
11383 /// 'x' lvalue part of the source atomic expression.
11384 Expr *X;
11385 /// 'expr' rvalue part of the source atomic expression.
11386 Expr *E;
11387 /// Helper expression of the form
11388 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11389 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11390 Expr *UpdateExpr;
11391 /// Is 'x' a LHS in a RHS part of full update expression. It is
11392 /// important for non-associative operations.
11393 bool IsXLHSInRHSPart;
11394 BinaryOperatorKind Op;
11395 SourceLocation OpLoc;
11396 /// true if the source expression is a postfix unary operation, false
11397 /// if it is a prefix unary operation.
11398 bool IsPostfixUpdate;
11399
11400public:
11401 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11402 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11403 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11404 /// Check specified statement that it is suitable for 'atomic update'
11405 /// constructs and extract 'x', 'expr' and Operation from the original
11406 /// expression. If DiagId and NoteId == 0, then only check is performed
11407 /// without error notification.
11408 /// \param DiagId Diagnostic which should be emitted if error is found.
11409 /// \param NoteId Diagnostic note for the main error message.
11410 /// \return true if statement is not an update expression, false otherwise.
11411 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11412 /// Return the 'x' lvalue part of the source atomic expression.
11413 Expr *getX() const { return X; }
11414 /// Return the 'expr' rvalue part of the source atomic expression.
11415 Expr *getExpr() const { return E; }
11416 /// Return the update expression used in calculation of the updated
11417 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11418 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11419 Expr *getUpdateExpr() const { return UpdateExpr; }
11420 /// Return true if 'x' is LHS in RHS part of full update expression,
11421 /// false otherwise.
11422 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11423
11424 /// true if the source expression is a postfix unary operation, false
11425 /// if it is a prefix unary operation.
11426 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11427
11428private:
11429 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11430 unsigned NoteId = 0);
11431};
11432
11433bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11434 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11435 ExprAnalysisErrorCode ErrorFound = NoError;
11436 SourceLocation ErrorLoc, NoteLoc;
11437 SourceRange ErrorRange, NoteRange;
11438 // Allowed constructs are:
11439 // x = x binop expr;
11440 // x = expr binop x;
11441 if (AtomicBinOp->getOpcode() == BO_Assign) {
11442 X = AtomicBinOp->getLHS();
11443 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11444 Val: AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11445 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11446 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11447 AtomicInnerBinOp->isBitwiseOp()) {
11448 Op = AtomicInnerBinOp->getOpcode();
11449 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11450 Expr *LHS = AtomicInnerBinOp->getLHS();
11451 Expr *RHS = AtomicInnerBinOp->getRHS();
11452 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11453 X->IgnoreParenImpCasts()->Profile(ID&: XId, Context: SemaRef.getASTContext(),
11454 /*Canonical=*/true);
11455 LHS->IgnoreParenImpCasts()->Profile(ID&: LHSId, Context: SemaRef.getASTContext(),
11456 /*Canonical=*/true);
11457 RHS->IgnoreParenImpCasts()->Profile(ID&: RHSId, Context: SemaRef.getASTContext(),
11458 /*Canonical=*/true);
11459 if (XId == LHSId) {
11460 E = RHS;
11461 IsXLHSInRHSPart = true;
11462 } else if (XId == RHSId) {
11463 E = LHS;
11464 IsXLHSInRHSPart = false;
11465 } else {
11466 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11467 ErrorRange = AtomicInnerBinOp->getSourceRange();
11468 NoteLoc = X->getExprLoc();
11469 NoteRange = X->getSourceRange();
11470 ErrorFound = NotAnUpdateExpression;
11471 }
11472 } else {
11473 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11474 ErrorRange = AtomicInnerBinOp->getSourceRange();
11475 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11476 NoteRange = SourceRange(NoteLoc, NoteLoc);
11477 ErrorFound = NotABinaryOperator;
11478 }
11479 } else {
11480 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11481 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11482 ErrorFound = NotABinaryExpression;
11483 }
11484 } else {
11485 ErrorLoc = AtomicBinOp->getExprLoc();
11486 ErrorRange = AtomicBinOp->getSourceRange();
11487 NoteLoc = AtomicBinOp->getOperatorLoc();
11488 NoteRange = SourceRange(NoteLoc, NoteLoc);
11489 ErrorFound = NotAnAssignmentOp;
11490 }
11491 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11492 SemaRef.Diag(Loc: ErrorLoc, DiagID: DiagId) << ErrorRange;
11493 SemaRef.Diag(Loc: NoteLoc, DiagID: NoteId) << ErrorFound << NoteRange;
11494 return true;
11495 }
11496 if (SemaRef.CurContext->isDependentContext())
11497 E = X = UpdateExpr = nullptr;
11498 return ErrorFound != NoError;
11499}
11500
11501bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11502 unsigned NoteId) {
11503 ExprAnalysisErrorCode ErrorFound = NoError;
11504 SourceLocation ErrorLoc, NoteLoc;
11505 SourceRange ErrorRange, NoteRange;
11506 // Allowed constructs are:
11507 // x++;
11508 // x--;
11509 // ++x;
11510 // --x;
11511 // x binop= expr;
11512 // x = x binop expr;
11513 // x = expr binop x;
11514 if (auto *AtomicBody = dyn_cast<Expr>(Val: S)) {
11515 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11516 if (AtomicBody->getType()->isScalarType() ||
11517 AtomicBody->isInstantiationDependent()) {
11518 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11519 Val: AtomicBody->IgnoreParenImpCasts())) {
11520 // Check for Compound Assignment Operation
11521 Op = BinaryOperator::getOpForCompoundAssignment(
11522 Opc: AtomicCompAssignOp->getOpcode());
11523 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11524 E = AtomicCompAssignOp->getRHS();
11525 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11526 IsXLHSInRHSPart = true;
11527 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11528 Val: AtomicBody->IgnoreParenImpCasts())) {
11529 // Check for Binary Operation
11530 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11531 return true;
11532 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11533 Val: AtomicBody->IgnoreParenImpCasts())) {
11534 // Check for Unary Operation
11535 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11536 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11537 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11538 OpLoc = AtomicUnaryOp->getOperatorLoc();
11539 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11540 E = SemaRef.ActOnIntegerConstant(Loc: OpLoc, /*uint64_t Val=*/Val: 1).get();
11541 IsXLHSInRHSPart = true;
11542 } else {
11543 ErrorFound = NotAnUnaryIncDecExpression;
11544 ErrorLoc = AtomicUnaryOp->getExprLoc();
11545 ErrorRange = AtomicUnaryOp->getSourceRange();
11546 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11547 NoteRange = SourceRange(NoteLoc, NoteLoc);
11548 }
11549 } else if (!AtomicBody->isInstantiationDependent()) {
11550 ErrorFound = NotABinaryOrUnaryExpression;
11551 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11552 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11553 } else if (AtomicBody->containsErrors()) {
11554 ErrorFound = NotAValidExpression;
11555 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11556 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11557 }
11558 } else {
11559 ErrorFound = NotAScalarType;
11560 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11561 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11562 }
11563 } else {
11564 ErrorFound = NotAnExpression;
11565 NoteLoc = ErrorLoc = S->getBeginLoc();
11566 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11567 }
11568 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11569 SemaRef.Diag(Loc: ErrorLoc, DiagID: DiagId) << ErrorRange;
11570 SemaRef.Diag(Loc: NoteLoc, DiagID: NoteId) << ErrorFound << NoteRange;
11571 return true;
11572 }
11573 if (SemaRef.CurContext->isDependentContext())
11574 E = X = UpdateExpr = nullptr;
11575 if (ErrorFound == NoError && E && X) {
11576 // Build an update expression of form 'OpaqueValueExpr(x) binop
11577 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11578 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11579 auto *OVEX = new (SemaRef.getASTContext())
11580 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11581 auto *OVEExpr = new (SemaRef.getASTContext())
11582 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
11583 ExprResult Update =
11584 SemaRef.CreateBuiltinBinOp(OpLoc, Opc: Op, LHSExpr: IsXLHSInRHSPart ? OVEX : OVEExpr,
11585 RHSExpr: IsXLHSInRHSPart ? OVEExpr : OVEX);
11586 if (Update.isInvalid())
11587 return true;
11588 Update = SemaRef.PerformImplicitConversion(From: Update.get(), ToType: X->getType(),
11589 Action: AssignmentAction::Casting);
11590 if (Update.isInvalid())
11591 return true;
11592 UpdateExpr = Update.get();
11593 }
11594 return ErrorFound != NoError;
11595}
11596
11597/// Get the node id of the fixed point of an expression \a S.
11598llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11599 llvm::FoldingSetNodeID Id;
11600 S->IgnoreParenImpCasts()->Profile(ID&: Id, Context, Canonical: true);
11601 return Id;
11602}
11603
11604/// Check if two expressions are same.
11605bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11606 const Expr *RHS) {
11607 return getNodeId(Context, S: LHS) == getNodeId(Context, S: RHS);
11608}
11609
11610class OpenMPAtomicCompareChecker {
11611public:
11612 /// All kinds of errors that can occur in `atomic compare`
11613 enum ErrorTy {
11614 /// Empty compound statement.
11615 NoStmt = 0,
11616 /// More than one statement in a compound statement.
11617 MoreThanOneStmt,
11618 /// Not an assignment binary operator.
11619 NotAnAssignment,
11620 /// Not a conditional operator.
11621 NotCondOp,
11622 /// Wrong false expr. According to the spec, 'x' should be at the false
11623 /// expression of a conditional expression.
11624 WrongFalseExpr,
11625 /// The condition of a conditional expression is not a binary operator.
11626 NotABinaryOp,
11627 /// Invalid binary operator (not <, >, or ==).
11628 InvalidBinaryOp,
11629 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11630 InvalidComparison,
11631 /// X is not a lvalue.
11632 XNotLValue,
11633 /// Not a scalar.
11634 NotScalar,
11635 /// Not an integer.
11636 NotInteger,
11637 /// 'else' statement is not expected.
11638 UnexpectedElse,
11639 /// Not an equality operator.
11640 NotEQ,
11641 /// Invalid assignment (not v == x).
11642 InvalidAssignment,
11643 /// Not if statement
11644 NotIfStmt,
11645 /// More than two statements in a compound statement.
11646 MoreThanTwoStmts,
11647 /// Not a compound statement.
11648 NotCompoundStmt,
11649 /// No else statement.
11650 NoElse,
11651 /// Not 'if (r)'.
11652 InvalidCondition,
11653 /// No error.
11654 NoError,
11655 };
11656
11657 struct ErrorInfoTy {
11658 ErrorTy Error;
11659 SourceLocation ErrorLoc;
11660 SourceRange ErrorRange;
11661 SourceLocation NoteLoc;
11662 SourceRange NoteRange;
11663 };
11664
11665 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11666
11667 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11668 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11669
11670 Expr *getX() const { return X; }
11671 Expr *getE() const { return E; }
11672 Expr *getD() const { return D; }
11673 Expr *getCond() const { return C; }
11674 bool isXBinopExpr() const { return IsXBinopExpr; }
11675
11676protected:
11677 /// Reference to ASTContext
11678 ASTContext &ContextRef;
11679 /// 'x' lvalue part of the source atomic expression.
11680 Expr *X = nullptr;
11681 /// 'expr' or 'e' rvalue part of the source atomic expression.
11682 Expr *E = nullptr;
11683 /// 'd' rvalue part of the source atomic expression.
11684 Expr *D = nullptr;
11685 /// 'cond' part of the source atomic expression. It is in one of the following
11686 /// forms:
11687 /// expr ordop x
11688 /// x ordop expr
11689 /// x == e
11690 /// e == x
11691 Expr *C = nullptr;
11692 /// True if the cond expr is in the form of 'x ordop expr'.
11693 bool IsXBinopExpr = true;
11694
11695 /// Check if it is a valid conditional update statement (cond-update-stmt).
11696 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11697
11698 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11699 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11700
11701 /// Check if all captured values have right type.
11702 bool checkType(ErrorInfoTy &ErrorInfo) const;
11703
11704 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11705 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11706 if (E->isInstantiationDependent())
11707 return true;
11708
11709 if (ShouldBeLValue && !E->isLValue()) {
11710 ErrorInfo.Error = ErrorTy::XNotLValue;
11711 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11712 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11713 return false;
11714 }
11715
11716 QualType QTy = E->getType();
11717 if (!QTy->isScalarType()) {
11718 ErrorInfo.Error = ErrorTy::NotScalar;
11719 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11720 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11721 return false;
11722 }
11723 if (ShouldBeInteger && !QTy->isIntegerType()) {
11724 ErrorInfo.Error = ErrorTy::NotInteger;
11725 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11726 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11727 return false;
11728 }
11729
11730 return true;
11731 }
11732};
11733
11734bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11735 ErrorInfoTy &ErrorInfo) {
11736 auto *Then = S->getThen();
11737 if (auto *CS = dyn_cast<CompoundStmt>(Val: Then)) {
11738 if (CS->body_empty()) {
11739 ErrorInfo.Error = ErrorTy::NoStmt;
11740 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11741 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11742 return false;
11743 }
11744 if (CS->size() > 1) {
11745 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11746 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11747 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11748 return false;
11749 }
11750 Then = CS->body_front();
11751 }
11752
11753 auto *BO = dyn_cast<BinaryOperator>(Val: Then);
11754 if (!BO) {
11755 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11756 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11757 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11758 return false;
11759 }
11760 if (BO->getOpcode() != BO_Assign) {
11761 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11762 ErrorInfo.ErrorLoc = BO->getExprLoc();
11763 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11764 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11765 return false;
11766 }
11767
11768 X = BO->getLHS();
11769
11770 auto *Cond = dyn_cast<BinaryOperator>(Val: S->getCond());
11771 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: S->getCond());
11772 Expr *LHS = nullptr;
11773 Expr *RHS = nullptr;
11774 if (Cond) {
11775 LHS = Cond->getLHS();
11776 RHS = Cond->getRHS();
11777 } else if (Call) {
11778 LHS = Call->getArg(Arg: 0);
11779 RHS = Call->getArg(Arg: 1);
11780 } else {
11781 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11782 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11783 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11784 return false;
11785 }
11786
11787 if ((Cond && Cond->getOpcode() == BO_EQ) ||
11788 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
11789 C = S->getCond();
11790 D = BO->getRHS();
11791 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
11792 E = RHS;
11793 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
11794 E = LHS;
11795 } else {
11796 ErrorInfo.Error = ErrorTy::InvalidComparison;
11797 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11798 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11799 S->getCond()->getSourceRange();
11800 return false;
11801 }
11802 } else if ((Cond &&
11803 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
11804 (Call &&
11805 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
11806 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
11807 E = BO->getRHS();
11808 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS) &&
11809 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS)) {
11810 C = S->getCond();
11811 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: LHS) &&
11812 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
11813 C = S->getCond();
11814 IsXBinopExpr = false;
11815 } else {
11816 ErrorInfo.Error = ErrorTy::InvalidComparison;
11817 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11818 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11819 S->getCond()->getSourceRange();
11820 return false;
11821 }
11822 } else {
11823 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11824 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11825 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11826 return false;
11827 }
11828
11829 if (S->getElse()) {
11830 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11831 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11832 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11833 return false;
11834 }
11835
11836 return true;
11837}
11838
11839bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
11840 ErrorInfoTy &ErrorInfo) {
11841 auto *BO = dyn_cast<BinaryOperator>(Val: S);
11842 if (!BO) {
11843 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11844 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11845 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11846 return false;
11847 }
11848 if (BO->getOpcode() != BO_Assign) {
11849 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11850 ErrorInfo.ErrorLoc = BO->getExprLoc();
11851 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11852 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11853 return false;
11854 }
11855
11856 X = BO->getLHS();
11857
11858 auto *CO = dyn_cast<ConditionalOperator>(Val: BO->getRHS()->IgnoreParenImpCasts());
11859 if (!CO) {
11860 ErrorInfo.Error = ErrorTy::NotCondOp;
11861 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11862 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11863 return false;
11864 }
11865
11866 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: CO->getFalseExpr())) {
11867 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11868 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11869 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11870 CO->getFalseExpr()->getSourceRange();
11871 return false;
11872 }
11873
11874 auto *Cond = dyn_cast<BinaryOperator>(Val: CO->getCond());
11875 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: CO->getCond());
11876 Expr *LHS = nullptr;
11877 Expr *RHS = nullptr;
11878 if (Cond) {
11879 LHS = Cond->getLHS();
11880 RHS = Cond->getRHS();
11881 } else if (Call) {
11882 LHS = Call->getArg(Arg: 0);
11883 RHS = Call->getArg(Arg: 1);
11884 } else {
11885 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11886 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11887 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11888 CO->getCond()->getSourceRange();
11889 return false;
11890 }
11891
11892 if ((Cond && Cond->getOpcode() == BO_EQ) ||
11893 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
11894 C = CO->getCond();
11895 D = CO->getTrueExpr();
11896 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
11897 E = RHS;
11898 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
11899 E = LHS;
11900 } else {
11901 ErrorInfo.Error = ErrorTy::InvalidComparison;
11902 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11903 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11904 CO->getCond()->getSourceRange();
11905 return false;
11906 }
11907 } else if ((Cond &&
11908 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
11909 (Call &&
11910 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
11911 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
11912
11913 E = CO->getTrueExpr();
11914 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS) &&
11915 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS)) {
11916 C = CO->getCond();
11917 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: LHS) &&
11918 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
11919 C = CO->getCond();
11920 IsXBinopExpr = false;
11921 } else {
11922 ErrorInfo.Error = ErrorTy::InvalidComparison;
11923 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11924 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11925 CO->getCond()->getSourceRange();
11926 return false;
11927 }
11928 } else {
11929 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11930 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11931 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11932 CO->getCond()->getSourceRange();
11933 return false;
11934 }
11935
11936 return true;
11937}
11938
11939bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
11940 // 'x' and 'e' cannot be nullptr
11941 assert(X && E && "X and E cannot be nullptr");
11942
11943 if (!CheckValue(E: X, ErrorInfo, ShouldBeLValue: true))
11944 return false;
11945
11946 if (!CheckValue(E, ErrorInfo, ShouldBeLValue: false))
11947 return false;
11948
11949 if (D && !CheckValue(E: D, ErrorInfo, ShouldBeLValue: false))
11950 return false;
11951
11952 return true;
11953}
11954
11955bool OpenMPAtomicCompareChecker::checkStmt(
11956 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11957 auto *CS = dyn_cast<CompoundStmt>(Val: S);
11958 if (CS) {
11959 if (CS->body_empty()) {
11960 ErrorInfo.Error = ErrorTy::NoStmt;
11961 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11962 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11963 return false;
11964 }
11965
11966 if (CS->size() != 1) {
11967 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11968 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11969 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11970 return false;
11971 }
11972 S = CS->body_front();
11973 }
11974
11975 auto Res = false;
11976
11977 if (auto *IS = dyn_cast<IfStmt>(Val: S)) {
11978 // Check if the statement is in one of the following forms
11979 // (cond-update-stmt):
11980 // if (expr ordop x) { x = expr; }
11981 // if (x ordop expr) { x = expr; }
11982 // if (x == e) { x = d; }
11983 Res = checkCondUpdateStmt(S: IS, ErrorInfo);
11984 } else {
11985 // Check if the statement is in one of the following forms (cond-expr-stmt):
11986 // x = expr ordop x ? expr : x;
11987 // x = x ordop expr ? expr : x;
11988 // x = x == e ? d : x;
11989 Res = checkCondExprStmt(S, ErrorInfo);
11990 }
11991
11992 if (!Res)
11993 return false;
11994
11995 return checkType(ErrorInfo);
11996}
11997
11998class OpenMPAtomicCompareCaptureChecker final
11999 : public OpenMPAtomicCompareChecker {
12000public:
12001 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12002
12003 Expr *getV() const { return V; }
12004 Expr *getR() const { return R; }
12005 bool isFailOnly() const { return IsFailOnly; }
12006 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12007
12008 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12009 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12010
12011private:
12012 bool checkType(ErrorInfoTy &ErrorInfo);
12013
12014 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12015 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12016 // spec p.p. 82:
12017 // (1) { v = x; cond-update-stmt }
12018 // (2) { cond-update-stmt v = x; }
12019 // (3) if(x == e) { x = d; } else { v = x; }
12020 // (4) { r = x == e; if(r) { x = d; } }
12021 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12022
12023 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12024 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12025
12026 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12027 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12028 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12029
12030 /// 'v' lvalue part of the source atomic expression.
12031 Expr *V = nullptr;
12032 /// 'r' lvalue part of the source atomic expression.
12033 Expr *R = nullptr;
12034 /// If 'v' is only updated when the comparison fails.
12035 bool IsFailOnly = false;
12036 /// If original value of 'x' must be stored in 'v', not an updated one.
12037 bool IsPostfixUpdate = false;
12038};
12039
12040bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12041 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12042 return false;
12043
12044 if (V && !CheckValue(E: V, ErrorInfo, ShouldBeLValue: true))
12045 return false;
12046
12047 if (R && !CheckValue(E: R, ErrorInfo, ShouldBeLValue: true, ShouldBeInteger: true))
12048 return false;
12049
12050 return true;
12051}
12052
12053bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12054 ErrorInfoTy &ErrorInfo) {
12055 IsFailOnly = true;
12056
12057 auto *Then = S->getThen();
12058 if (auto *CS = dyn_cast<CompoundStmt>(Val: Then)) {
12059 if (CS->body_empty()) {
12060 ErrorInfo.Error = ErrorTy::NoStmt;
12061 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12062 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12063 return false;
12064 }
12065 if (CS->size() > 1) {
12066 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12067 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12068 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12069 return false;
12070 }
12071 Then = CS->body_front();
12072 }
12073
12074 auto *BO = dyn_cast<BinaryOperator>(Val: Then);
12075 if (!BO) {
12076 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12077 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12078 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12079 return false;
12080 }
12081 if (BO->getOpcode() != BO_Assign) {
12082 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12083 ErrorInfo.ErrorLoc = BO->getExprLoc();
12084 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12085 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12086 return false;
12087 }
12088
12089 X = BO->getLHS();
12090 D = BO->getRHS();
12091
12092 auto *Cond = dyn_cast<BinaryOperator>(Val: S->getCond());
12093 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: S->getCond());
12094 Expr *LHS = nullptr;
12095 Expr *RHS = nullptr;
12096 if (Cond) {
12097 LHS = Cond->getLHS();
12098 RHS = Cond->getRHS();
12099 } else if (Call) {
12100 LHS = Call->getArg(Arg: 0);
12101 RHS = Call->getArg(Arg: 1);
12102 } else {
12103 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12104 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12105 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12106 return false;
12107 }
12108 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12109 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12110 ErrorInfo.Error = ErrorTy::NotEQ;
12111 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12112 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12113 return false;
12114 }
12115
12116 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
12117 E = RHS;
12118 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12119 E = LHS;
12120 } else {
12121 ErrorInfo.Error = ErrorTy::InvalidComparison;
12122 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12123 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12124 return false;
12125 }
12126
12127 C = S->getCond();
12128
12129 if (!S->getElse()) {
12130 ErrorInfo.Error = ErrorTy::NoElse;
12131 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12132 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12133 return false;
12134 }
12135
12136 auto *Else = S->getElse();
12137 if (auto *CS = dyn_cast<CompoundStmt>(Val: Else)) {
12138 if (CS->body_empty()) {
12139 ErrorInfo.Error = ErrorTy::NoStmt;
12140 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12141 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12142 return false;
12143 }
12144 if (CS->size() > 1) {
12145 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12146 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12147 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12148 return false;
12149 }
12150 Else = CS->body_front();
12151 }
12152
12153 auto *ElseBO = dyn_cast<BinaryOperator>(Val: Else);
12154 if (!ElseBO) {
12155 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12156 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12157 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12158 return false;
12159 }
12160 if (ElseBO->getOpcode() != BO_Assign) {
12161 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12162 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12163 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12164 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12165 return false;
12166 }
12167
12168 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: ElseBO->getRHS())) {
12169 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12170 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12171 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12172 ElseBO->getRHS()->getSourceRange();
12173 return false;
12174 }
12175
12176 V = ElseBO->getLHS();
12177
12178 return checkType(ErrorInfo);
12179}
12180
12181bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12182 ErrorInfoTy &ErrorInfo) {
12183 // We don't check here as they should be already done before call this
12184 // function.
12185 auto *CS = cast<CompoundStmt>(Val: S);
12186 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12187 auto *S1 = cast<BinaryOperator>(Val: CS->body_front());
12188 auto *S2 = cast<IfStmt>(Val: CS->body_back());
12189 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12190
12191 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: S1->getLHS(), RHS: S2->getCond())) {
12192 ErrorInfo.Error = ErrorTy::InvalidCondition;
12193 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12194 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12195 return false;
12196 }
12197
12198 R = S1->getLHS();
12199
12200 auto *Then = S2->getThen();
12201 if (auto *ThenCS = dyn_cast<CompoundStmt>(Val: Then)) {
12202 if (ThenCS->body_empty()) {
12203 ErrorInfo.Error = ErrorTy::NoStmt;
12204 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12205 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12206 return false;
12207 }
12208 if (ThenCS->size() > 1) {
12209 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12210 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12211 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12212 return false;
12213 }
12214 Then = ThenCS->body_front();
12215 }
12216
12217 auto *ThenBO = dyn_cast<BinaryOperator>(Val: Then);
12218 if (!ThenBO) {
12219 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12220 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12221 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12222 return false;
12223 }
12224 if (ThenBO->getOpcode() != BO_Assign) {
12225 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12226 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12227 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12228 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12229 return false;
12230 }
12231
12232 X = ThenBO->getLHS();
12233 D = ThenBO->getRHS();
12234
12235 auto *BO = cast<BinaryOperator>(Val: S1->getRHS()->IgnoreImpCasts());
12236 if (BO->getOpcode() != BO_EQ) {
12237 ErrorInfo.Error = ErrorTy::NotEQ;
12238 ErrorInfo.ErrorLoc = BO->getExprLoc();
12239 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12240 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12241 return false;
12242 }
12243
12244 C = BO;
12245
12246 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: BO->getLHS())) {
12247 E = BO->getRHS();
12248 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: BO->getRHS())) {
12249 E = BO->getLHS();
12250 } else {
12251 ErrorInfo.Error = ErrorTy::InvalidComparison;
12252 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12253 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12254 return false;
12255 }
12256
12257 if (S2->getElse()) {
12258 IsFailOnly = true;
12259
12260 auto *Else = S2->getElse();
12261 if (auto *ElseCS = dyn_cast<CompoundStmt>(Val: Else)) {
12262 if (ElseCS->body_empty()) {
12263 ErrorInfo.Error = ErrorTy::NoStmt;
12264 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12265 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12266 return false;
12267 }
12268 if (ElseCS->size() > 1) {
12269 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12270 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12271 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12272 return false;
12273 }
12274 Else = ElseCS->body_front();
12275 }
12276
12277 auto *ElseBO = dyn_cast<BinaryOperator>(Val: Else);
12278 if (!ElseBO) {
12279 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12280 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12281 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12282 return false;
12283 }
12284 if (ElseBO->getOpcode() != BO_Assign) {
12285 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12286 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12287 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12288 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12289 return false;
12290 }
12291 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: ElseBO->getRHS())) {
12292 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12293 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12294 ErrorInfo.NoteLoc = X->getExprLoc();
12295 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12296 ErrorInfo.NoteRange = X->getSourceRange();
12297 return false;
12298 }
12299
12300 V = ElseBO->getLHS();
12301 }
12302
12303 return checkType(ErrorInfo);
12304}
12305
12306bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12307 ErrorInfoTy &ErrorInfo) {
12308 // if(x == e) { x = d; } else { v = x; }
12309 if (auto *IS = dyn_cast<IfStmt>(Val: S))
12310 return checkForm3(S: IS, ErrorInfo);
12311
12312 auto *CS = dyn_cast<CompoundStmt>(Val: S);
12313 if (!CS) {
12314 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12315 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12316 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12317 return false;
12318 }
12319 if (CS->body_empty()) {
12320 ErrorInfo.Error = ErrorTy::NoStmt;
12321 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12322 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12323 return false;
12324 }
12325
12326 // { if(x == e) { x = d; } else { v = x; } }
12327 if (CS->size() == 1) {
12328 auto *IS = dyn_cast<IfStmt>(Val: CS->body_front());
12329 if (!IS) {
12330 ErrorInfo.Error = ErrorTy::NotIfStmt;
12331 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12332 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12333 CS->body_front()->getSourceRange();
12334 return false;
12335 }
12336
12337 return checkForm3(S: IS, ErrorInfo);
12338 } else if (CS->size() == 2) {
12339 auto *S1 = CS->body_front();
12340 auto *S2 = CS->body_back();
12341
12342 Stmt *UpdateStmt = nullptr;
12343 Stmt *CondUpdateStmt = nullptr;
12344 Stmt *CondExprStmt = nullptr;
12345
12346 if (auto *BO = dyn_cast<BinaryOperator>(Val: S1)) {
12347 // It could be one of the following cases:
12348 // { v = x; cond-update-stmt }
12349 // { v = x; cond-expr-stmt }
12350 // { cond-expr-stmt; v = x; }
12351 // form 45
12352 if (isa<BinaryOperator>(Val: BO->getRHS()->IgnoreImpCasts()) ||
12353 isa<ConditionalOperator>(Val: BO->getRHS()->IgnoreImpCasts())) {
12354 // check if form 45
12355 if (isa<IfStmt>(Val: S2))
12356 return checkForm45(S: CS, ErrorInfo);
12357 // { cond-expr-stmt; v = x; }
12358 CondExprStmt = S1;
12359 UpdateStmt = S2;
12360 } else {
12361 IsPostfixUpdate = true;
12362 UpdateStmt = S1;
12363 if (isa<IfStmt>(Val: S2)) {
12364 // { v = x; cond-update-stmt }
12365 CondUpdateStmt = S2;
12366 } else {
12367 // { v = x; cond-expr-stmt }
12368 CondExprStmt = S2;
12369 }
12370 }
12371 } else {
12372 // { cond-update-stmt v = x; }
12373 UpdateStmt = S2;
12374 CondUpdateStmt = S1;
12375 }
12376
12377 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12378 auto *IS = dyn_cast<IfStmt>(Val: CUS);
12379 if (!IS) {
12380 ErrorInfo.Error = ErrorTy::NotIfStmt;
12381 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12382 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12383 return false;
12384 }
12385
12386 return checkCondUpdateStmt(S: IS, ErrorInfo);
12387 };
12388
12389 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12390 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12391 auto *BO = dyn_cast<BinaryOperator>(Val: US);
12392 if (!BO) {
12393 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12394 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12395 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12396 return false;
12397 }
12398 if (BO->getOpcode() != BO_Assign) {
12399 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12400 ErrorInfo.ErrorLoc = BO->getExprLoc();
12401 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12402 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12403 return false;
12404 }
12405 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: this->X, RHS: BO->getRHS())) {
12406 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12407 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12408 ErrorInfo.NoteLoc = this->X->getExprLoc();
12409 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12410 ErrorInfo.NoteRange = this->X->getSourceRange();
12411 return false;
12412 }
12413
12414 this->V = BO->getLHS();
12415
12416 return true;
12417 };
12418
12419 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12420 return false;
12421 if (CondExprStmt && !checkCondExprStmt(S: CondExprStmt, ErrorInfo))
12422 return false;
12423 if (!CheckUpdateStmt(UpdateStmt))
12424 return false;
12425 } else {
12426 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12427 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12428 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12429 return false;
12430 }
12431
12432 return checkType(ErrorInfo);
12433}
12434} // namespace
12435
12436StmtResult SemaOpenMP::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
12437 Stmt *AStmt,
12438 SourceLocation StartLoc,
12439 SourceLocation EndLoc) {
12440 ASTContext &Context = getASTContext();
12441 unsigned OMPVersion = getLangOpts().OpenMP;
12442 // Register location of the first atomic directive.
12443 DSAStack->addAtomicDirectiveLoc(Loc: StartLoc);
12444 if (!AStmt)
12445 return StmtError();
12446
12447 // 1.2.2 OpenMP Language Terminology
12448 // Structured block - An executable statement with a single entry at the
12449 // top and a single exit at the bottom.
12450 // The point of exit cannot be a branch out of the structured block.
12451 // longjmp() and throw() must not violate the entry/exit criteria.
12452 OpenMPClauseKind AtomicKind = OMPC_unknown;
12453 SourceLocation AtomicKindLoc;
12454 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12455 SourceLocation MemOrderLoc;
12456 bool MutexClauseEncountered = false;
12457 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12458 for (const OMPClause *C : Clauses) {
12459 switch (C->getClauseKind()) {
12460 case OMPC_read:
12461 case OMPC_write:
12462 case OMPC_update:
12463 MutexClauseEncountered = true;
12464 [[fallthrough]];
12465 case OMPC_capture:
12466 case OMPC_compare: {
12467 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12468 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_several_clauses)
12469 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12470 Diag(Loc: AtomicKindLoc, DiagID: diag::note_omp_previous_mem_order_clause)
12471 << getOpenMPClauseNameForDiag(C: AtomicKind);
12472 } else {
12473 AtomicKind = C->getClauseKind();
12474 AtomicKindLoc = C->getBeginLoc();
12475 if (!EncounteredAtomicKinds.insert(V: C->getClauseKind()).second) {
12476 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_several_clauses)
12477 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12478 Diag(Loc: AtomicKindLoc, DiagID: diag::note_omp_previous_mem_order_clause)
12479 << getOpenMPClauseNameForDiag(C: AtomicKind);
12480 }
12481 }
12482 break;
12483 }
12484 case OMPC_weak:
12485 case OMPC_fail: {
12486 if (!EncounteredAtomicKinds.contains(V: OMPC_compare)) {
12487 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_atomic_no_compare)
12488 << getOpenMPClauseNameForDiag(C: C->getClauseKind())
12489 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12490 return StmtError();
12491 }
12492 break;
12493 }
12494 case OMPC_seq_cst:
12495 case OMPC_acq_rel:
12496 case OMPC_acquire:
12497 case OMPC_release:
12498 case OMPC_relaxed: {
12499 if (MemOrderKind != OMPC_unknown) {
12500 Diag(Loc: C->getBeginLoc(), DiagID: diag::err_omp_several_mem_order_clauses)
12501 << getOpenMPDirectiveName(D: OMPD_atomic, Ver: OMPVersion) << 0
12502 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12503 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
12504 << getOpenMPClauseNameForDiag(C: MemOrderKind);
12505 } else {
12506 MemOrderKind = C->getClauseKind();
12507 MemOrderLoc = C->getBeginLoc();
12508 }
12509 break;
12510 }
12511 // The following clauses are allowed, but we don't need to do anything here.
12512 case OMPC_hint:
12513 break;
12514 default:
12515 llvm_unreachable("unknown clause is encountered");
12516 }
12517 }
12518 bool IsCompareCapture = false;
12519 if (EncounteredAtomicKinds.contains(V: OMPC_compare) &&
12520 EncounteredAtomicKinds.contains(V: OMPC_capture)) {
12521 IsCompareCapture = true;
12522 AtomicKind = OMPC_compare;
12523 }
12524 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12525 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12526 // release.
12527 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12528 // acquire.
12529 // If atomic-clause is update or not present then memory-order-clause must not
12530 // be acq_rel or acquire.
12531 if ((AtomicKind == OMPC_read &&
12532 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12533 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12534 AtomicKind == OMPC_unknown) &&
12535 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12536 SourceLocation Loc = AtomicKindLoc;
12537 if (AtomicKind == OMPC_unknown)
12538 Loc = StartLoc;
12539 Diag(Loc, DiagID: diag::err_omp_atomic_incompatible_mem_order_clause)
12540 << getOpenMPClauseNameForDiag(C: AtomicKind)
12541 << (AtomicKind == OMPC_unknown ? 1 : 0)
12542 << getOpenMPClauseNameForDiag(C: MemOrderKind);
12543 Diag(Loc: MemOrderLoc, DiagID: diag::note_omp_previous_mem_order_clause)
12544 << getOpenMPClauseNameForDiag(C: MemOrderKind);
12545 }
12546
12547 Stmt *Body = AStmt;
12548 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: Body))
12549 Body = EWC->getSubExpr();
12550
12551 Expr *X = nullptr;
12552 Expr *V = nullptr;
12553 Expr *E = nullptr;
12554 Expr *UE = nullptr;
12555 Expr *D = nullptr;
12556 Expr *CE = nullptr;
12557 Expr *R = nullptr;
12558 bool IsXLHSInRHSPart = false;
12559 bool IsPostfixUpdate = false;
12560 bool IsFailOnly = false;
12561 // OpenMP [2.12.6, atomic Construct]
12562 // In the next expressions:
12563 // * x and v (as applicable) are both l-value expressions with scalar type.
12564 // * During the execution of an atomic region, multiple syntactic
12565 // occurrences of x must designate the same storage location.
12566 // * Neither of v and expr (as applicable) may access the storage location
12567 // designated by x.
12568 // * Neither of x and expr (as applicable) may access the storage location
12569 // designated by v.
12570 // * expr is an expression with scalar type.
12571 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12572 // * binop, binop=, ++, and -- are not overloaded operators.
12573 // * The expression x binop expr must be numerically equivalent to x binop
12574 // (expr). This requirement is satisfied if the operators in expr have
12575 // precedence greater than binop, or by using parentheses around expr or
12576 // subexpressions of expr.
12577 // * The expression expr binop x must be numerically equivalent to (expr)
12578 // binop x. This requirement is satisfied if the operators in expr have
12579 // precedence equal to or greater than binop, or by using parentheses around
12580 // expr or subexpressions of expr.
12581 // * For forms that allow multiple occurrences of x, the number of times
12582 // that x is evaluated is unspecified.
12583 if (AtomicKind == OMPC_read) {
12584 enum {
12585 NotAnExpression,
12586 NotAnAssignmentOp,
12587 NotAScalarType,
12588 NotAnLValue,
12589 NoError
12590 } ErrorFound = NoError;
12591 SourceLocation ErrorLoc, NoteLoc;
12592 SourceRange ErrorRange, NoteRange;
12593 // If clause is read:
12594 // v = x;
12595 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
12596 const auto *AtomicBinOp =
12597 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
12598 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12599 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12600 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12601 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12602 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12603 if (!X->isLValue() || !V->isLValue()) {
12604 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12605 ErrorFound = NotAnLValue;
12606 ErrorLoc = AtomicBinOp->getExprLoc();
12607 ErrorRange = AtomicBinOp->getSourceRange();
12608 NoteLoc = NotLValueExpr->getExprLoc();
12609 NoteRange = NotLValueExpr->getSourceRange();
12610 }
12611 } else if (!X->isInstantiationDependent() ||
12612 !V->isInstantiationDependent()) {
12613 const Expr *NotScalarExpr =
12614 (X->isInstantiationDependent() || X->getType()->isScalarType())
12615 ? V
12616 : X;
12617 ErrorFound = NotAScalarType;
12618 ErrorLoc = AtomicBinOp->getExprLoc();
12619 ErrorRange = AtomicBinOp->getSourceRange();
12620 NoteLoc = NotScalarExpr->getExprLoc();
12621 NoteRange = NotScalarExpr->getSourceRange();
12622 }
12623 } else if (!AtomicBody->isInstantiationDependent()) {
12624 ErrorFound = NotAnAssignmentOp;
12625 ErrorLoc = AtomicBody->getExprLoc();
12626 ErrorRange = AtomicBody->getSourceRange();
12627 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12628 : AtomicBody->getExprLoc();
12629 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12630 : AtomicBody->getSourceRange();
12631 }
12632 } else {
12633 ErrorFound = NotAnExpression;
12634 NoteLoc = ErrorLoc = Body->getBeginLoc();
12635 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12636 }
12637 if (ErrorFound != NoError) {
12638 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_read_not_expression_statement)
12639 << ErrorRange;
12640 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_read_write)
12641 << ErrorFound << NoteRange;
12642 return StmtError();
12643 }
12644 if (SemaRef.CurContext->isDependentContext())
12645 V = X = nullptr;
12646 } else if (AtomicKind == OMPC_write) {
12647 enum {
12648 NotAnExpression,
12649 NotAnAssignmentOp,
12650 NotAScalarType,
12651 NotAnLValue,
12652 NoError
12653 } ErrorFound = NoError;
12654 SourceLocation ErrorLoc, NoteLoc;
12655 SourceRange ErrorRange, NoteRange;
12656 // If clause is write:
12657 // x = expr;
12658 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
12659 const auto *AtomicBinOp =
12660 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
12661 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12662 X = AtomicBinOp->getLHS();
12663 E = AtomicBinOp->getRHS();
12664 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12665 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12666 if (!X->isLValue()) {
12667 ErrorFound = NotAnLValue;
12668 ErrorLoc = AtomicBinOp->getExprLoc();
12669 ErrorRange = AtomicBinOp->getSourceRange();
12670 NoteLoc = X->getExprLoc();
12671 NoteRange = X->getSourceRange();
12672 }
12673 } else if (!X->isInstantiationDependent() ||
12674 !E->isInstantiationDependent()) {
12675 const Expr *NotScalarExpr =
12676 (X->isInstantiationDependent() || X->getType()->isScalarType())
12677 ? E
12678 : X;
12679 ErrorFound = NotAScalarType;
12680 ErrorLoc = AtomicBinOp->getExprLoc();
12681 ErrorRange = AtomicBinOp->getSourceRange();
12682 NoteLoc = NotScalarExpr->getExprLoc();
12683 NoteRange = NotScalarExpr->getSourceRange();
12684 }
12685 } else if (!AtomicBody->isInstantiationDependent()) {
12686 ErrorFound = NotAnAssignmentOp;
12687 ErrorLoc = AtomicBody->getExprLoc();
12688 ErrorRange = AtomicBody->getSourceRange();
12689 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12690 : AtomicBody->getExprLoc();
12691 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12692 : AtomicBody->getSourceRange();
12693 }
12694 } else {
12695 ErrorFound = NotAnExpression;
12696 NoteLoc = ErrorLoc = Body->getBeginLoc();
12697 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12698 }
12699 if (ErrorFound != NoError) {
12700 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_write_not_expression_statement)
12701 << ErrorRange;
12702 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_read_write)
12703 << ErrorFound << NoteRange;
12704 return StmtError();
12705 }
12706 if (SemaRef.CurContext->isDependentContext())
12707 E = X = nullptr;
12708 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12709 // If clause is update:
12710 // x++;
12711 // x--;
12712 // ++x;
12713 // --x;
12714 // x binop= expr;
12715 // x = x binop expr;
12716 // x = expr binop x;
12717 OpenMPAtomicUpdateChecker Checker(SemaRef);
12718 if (Checker.checkStatement(
12719 S: Body,
12720 DiagId: (AtomicKind == OMPC_update)
12721 ? diag::err_omp_atomic_update_not_expression_statement
12722 : diag::err_omp_atomic_not_expression_statement,
12723 NoteId: diag::note_omp_atomic_update))
12724 return StmtError();
12725 if (!SemaRef.CurContext->isDependentContext()) {
12726 E = Checker.getExpr();
12727 X = Checker.getX();
12728 UE = Checker.getUpdateExpr();
12729 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12730 }
12731 } else if (AtomicKind == OMPC_capture) {
12732 enum {
12733 NotAnAssignmentOp,
12734 NotACompoundStatement,
12735 NotTwoSubstatements,
12736 NotASpecificExpression,
12737 NoError
12738 } ErrorFound = NoError;
12739 SourceLocation ErrorLoc, NoteLoc;
12740 SourceRange ErrorRange, NoteRange;
12741 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
12742 // If clause is a capture:
12743 // v = x++;
12744 // v = x--;
12745 // v = ++x;
12746 // v = --x;
12747 // v = x binop= expr;
12748 // v = x = x binop expr;
12749 // v = x = expr binop x;
12750 const auto *AtomicBinOp =
12751 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
12752 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12753 V = AtomicBinOp->getLHS();
12754 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12755 OpenMPAtomicUpdateChecker Checker(SemaRef);
12756 if (Checker.checkStatement(
12757 S: Body, DiagId: diag::err_omp_atomic_capture_not_expression_statement,
12758 NoteId: diag::note_omp_atomic_update))
12759 return StmtError();
12760 E = Checker.getExpr();
12761 X = Checker.getX();
12762 UE = Checker.getUpdateExpr();
12763 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12764 IsPostfixUpdate = Checker.isPostfixUpdate();
12765 } else if (!AtomicBody->isInstantiationDependent()) {
12766 ErrorLoc = AtomicBody->getExprLoc();
12767 ErrorRange = AtomicBody->getSourceRange();
12768 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12769 : AtomicBody->getExprLoc();
12770 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12771 : AtomicBody->getSourceRange();
12772 ErrorFound = NotAnAssignmentOp;
12773 }
12774 if (ErrorFound != NoError) {
12775 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_capture_not_expression_statement)
12776 << ErrorRange;
12777 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12778 return StmtError();
12779 }
12780 if (SemaRef.CurContext->isDependentContext())
12781 UE = V = E = X = nullptr;
12782 } else {
12783 // If clause is a capture:
12784 // { v = x; x = expr; }
12785 // { v = x; x++; }
12786 // { v = x; x--; }
12787 // { v = x; ++x; }
12788 // { v = x; --x; }
12789 // { v = x; x binop= expr; }
12790 // { v = x; x = x binop expr; }
12791 // { v = x; x = expr binop x; }
12792 // { x++; v = x; }
12793 // { x--; v = x; }
12794 // { ++x; v = x; }
12795 // { --x; v = x; }
12796 // { x binop= expr; v = x; }
12797 // { x = x binop expr; v = x; }
12798 // { x = expr binop x; v = x; }
12799 if (auto *CS = dyn_cast<CompoundStmt>(Val: Body)) {
12800 // Check that this is { expr1; expr2; }
12801 if (CS->size() == 2) {
12802 Stmt *First = CS->body_front();
12803 Stmt *Second = CS->body_back();
12804 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: First))
12805 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12806 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: Second))
12807 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12808 // Need to find what subexpression is 'v' and what is 'x'.
12809 OpenMPAtomicUpdateChecker Checker(SemaRef);
12810 bool IsUpdateExprFound = !Checker.checkStatement(S: Second);
12811 BinaryOperator *BinOp = nullptr;
12812 if (IsUpdateExprFound) {
12813 BinOp = dyn_cast<BinaryOperator>(Val: First);
12814 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12815 }
12816 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
12817 // { v = x; x++; }
12818 // { v = x; x--; }
12819 // { v = x; ++x; }
12820 // { v = x; --x; }
12821 // { v = x; x binop= expr; }
12822 // { v = x; x = x binop expr; }
12823 // { v = x; x = expr binop x; }
12824 // Check that the first expression has form v = x.
12825 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12826 llvm::FoldingSetNodeID XId, PossibleXId;
12827 Checker.getX()->Profile(ID&: XId, Context, /*Canonical=*/true);
12828 PossibleX->Profile(ID&: PossibleXId, Context, /*Canonical=*/true);
12829 IsUpdateExprFound = XId == PossibleXId;
12830 if (IsUpdateExprFound) {
12831 V = BinOp->getLHS();
12832 X = Checker.getX();
12833 E = Checker.getExpr();
12834 UE = Checker.getUpdateExpr();
12835 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12836 IsPostfixUpdate = true;
12837 }
12838 }
12839 if (!IsUpdateExprFound) {
12840 IsUpdateExprFound = !Checker.checkStatement(S: First);
12841 BinOp = nullptr;
12842 if (IsUpdateExprFound) {
12843 BinOp = dyn_cast<BinaryOperator>(Val: Second);
12844 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12845 }
12846 if (IsUpdateExprFound &&
12847 !SemaRef.CurContext->isDependentContext()) {
12848 // { x++; v = x; }
12849 // { x--; v = x; }
12850 // { ++x; v = x; }
12851 // { --x; v = x; }
12852 // { x binop= expr; v = x; }
12853 // { x = x binop expr; v = x; }
12854 // { x = expr binop x; v = x; }
12855 // Check that the second expression has form v = x.
12856 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12857 llvm::FoldingSetNodeID XId, PossibleXId;
12858 Checker.getX()->Profile(ID&: XId, Context, /*Canonical=*/true);
12859 PossibleX->Profile(ID&: PossibleXId, Context, /*Canonical=*/true);
12860 IsUpdateExprFound = XId == PossibleXId;
12861 if (IsUpdateExprFound) {
12862 V = BinOp->getLHS();
12863 X = Checker.getX();
12864 E = Checker.getExpr();
12865 UE = Checker.getUpdateExpr();
12866 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12867 IsPostfixUpdate = false;
12868 }
12869 }
12870 }
12871 if (!IsUpdateExprFound) {
12872 // { v = x; x = expr; }
12873 auto *FirstExpr = dyn_cast<Expr>(Val: First);
12874 auto *SecondExpr = dyn_cast<Expr>(Val: Second);
12875 if (!FirstExpr || !SecondExpr ||
12876 !(FirstExpr->isInstantiationDependent() ||
12877 SecondExpr->isInstantiationDependent())) {
12878 auto *FirstBinOp = dyn_cast<BinaryOperator>(Val: First);
12879 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12880 ErrorFound = NotAnAssignmentOp;
12881 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12882 : First->getBeginLoc();
12883 NoteRange = ErrorRange = FirstBinOp
12884 ? FirstBinOp->getSourceRange()
12885 : SourceRange(ErrorLoc, ErrorLoc);
12886 } else {
12887 auto *SecondBinOp = dyn_cast<BinaryOperator>(Val: Second);
12888 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12889 ErrorFound = NotAnAssignmentOp;
12890 NoteLoc = ErrorLoc = SecondBinOp
12891 ? SecondBinOp->getOperatorLoc()
12892 : Second->getBeginLoc();
12893 NoteRange = ErrorRange =
12894 SecondBinOp ? SecondBinOp->getSourceRange()
12895 : SourceRange(ErrorLoc, ErrorLoc);
12896 } else {
12897 Expr *PossibleXRHSInFirst =
12898 FirstBinOp->getRHS()->IgnoreParenImpCasts();
12899 Expr *PossibleXLHSInSecond =
12900 SecondBinOp->getLHS()->IgnoreParenImpCasts();
12901 llvm::FoldingSetNodeID X1Id, X2Id;
12902 PossibleXRHSInFirst->Profile(ID&: X1Id, Context,
12903 /*Canonical=*/true);
12904 PossibleXLHSInSecond->Profile(ID&: X2Id, Context,
12905 /*Canonical=*/true);
12906 IsUpdateExprFound = X1Id == X2Id;
12907 if (IsUpdateExprFound) {
12908 V = FirstBinOp->getLHS();
12909 X = SecondBinOp->getLHS();
12910 E = SecondBinOp->getRHS();
12911 UE = nullptr;
12912 IsXLHSInRHSPart = false;
12913 IsPostfixUpdate = true;
12914 } else {
12915 ErrorFound = NotASpecificExpression;
12916 ErrorLoc = FirstBinOp->getExprLoc();
12917 ErrorRange = FirstBinOp->getSourceRange();
12918 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12919 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12920 }
12921 }
12922 }
12923 }
12924 }
12925 } else {
12926 NoteLoc = ErrorLoc = Body->getBeginLoc();
12927 NoteRange = ErrorRange =
12928 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12929 ErrorFound = NotTwoSubstatements;
12930 }
12931 } else {
12932 NoteLoc = ErrorLoc = Body->getBeginLoc();
12933 NoteRange = ErrorRange =
12934 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12935 ErrorFound = NotACompoundStatement;
12936 }
12937 }
12938 if (ErrorFound != NoError) {
12939 Diag(Loc: ErrorLoc, DiagID: diag::err_omp_atomic_capture_not_compound_statement)
12940 << ErrorRange;
12941 Diag(Loc: NoteLoc, DiagID: diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12942 return StmtError();
12943 }
12944 if (SemaRef.CurContext->isDependentContext())
12945 UE = V = E = X = nullptr;
12946 } else if (AtomicKind == OMPC_compare) {
12947 if (IsCompareCapture) {
12948 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12949 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
12950 if (!Checker.checkStmt(S: Body, ErrorInfo)) {
12951 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_compare_capture)
12952 << ErrorInfo.ErrorRange;
12953 Diag(Loc: ErrorInfo.NoteLoc, DiagID: diag::note_omp_atomic_compare)
12954 << ErrorInfo.Error << ErrorInfo.NoteRange;
12955 return StmtError();
12956 }
12957 X = Checker.getX();
12958 E = Checker.getE();
12959 D = Checker.getD();
12960 CE = Checker.getCond();
12961 V = Checker.getV();
12962 R = Checker.getR();
12963 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12964 IsXLHSInRHSPart = Checker.isXBinopExpr();
12965 IsFailOnly = Checker.isFailOnly();
12966 IsPostfixUpdate = Checker.isPostfixUpdate();
12967 } else {
12968 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12969 OpenMPAtomicCompareChecker Checker(SemaRef);
12970 if (!Checker.checkStmt(S: Body, ErrorInfo)) {
12971 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_compare)
12972 << ErrorInfo.ErrorRange;
12973 Diag(Loc: ErrorInfo.NoteLoc, DiagID: diag::note_omp_atomic_compare)
12974 << ErrorInfo.Error << ErrorInfo.NoteRange;
12975 return StmtError();
12976 }
12977 X = Checker.getX();
12978 E = Checker.getE();
12979 D = Checker.getD();
12980 CE = Checker.getCond();
12981 // The weak clause may only appear if the resulting atomic operation is
12982 // an atomic conditional update for which the comparison tests for
12983 // equality. It was not possible to do this check in
12984 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
12985 // could not be performed (Clauses are not available).
12986 auto *It = find_if(Range&: Clauses, P: [](OMPClause *C) {
12987 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
12988 });
12989 if (It != Clauses.end()) {
12990 auto *Cond = dyn_cast<BinaryOperator>(Val: CE);
12991 if (Cond->getOpcode() != BO_EQ) {
12992 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
12993 ErrorInfo.ErrorLoc = Cond->getExprLoc();
12994 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
12995 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12996
12997 Diag(Loc: ErrorInfo.ErrorLoc, DiagID: diag::err_omp_atomic_weak_no_equality)
12998 << ErrorInfo.ErrorRange;
12999 return StmtError();
13000 }
13001 }
13002 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13003 IsXLHSInRHSPart = Checker.isXBinopExpr();
13004 }
13005 }
13006
13007 SemaRef.setFunctionHasBranchProtectedScope();
13008
13009 return OMPAtomicDirective::Create(
13010 C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
13011 Exprs: {.X: X, .V: V, .R: R, .E: E, .UE: UE, .D: D, .Cond: CE, .IsXLHSInRHSPart: IsXLHSInRHSPart, .IsPostfixUpdate: IsPostfixUpdate, .IsFailOnly: IsFailOnly});
13012}
13013
13014StmtResult SemaOpenMP::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
13015 Stmt *AStmt,
13016 SourceLocation StartLoc,
13017 SourceLocation EndLoc) {
13018 if (!AStmt)
13019 return StmtError();
13020
13021 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_target, AStmt);
13022
13023 // OpenMP [2.16, Nesting of Regions]
13024 // If specified, a teams construct must be contained within a target
13025 // construct. That target construct must contain no statements or directives
13026 // outside of the teams construct.
13027 if (DSAStack->hasInnerTeamsRegion()) {
13028 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13029 bool OMPTeamsFound = true;
13030 if (const auto *CS = dyn_cast<CompoundStmt>(Val: S)) {
13031 auto I = CS->body_begin();
13032 while (I != CS->body_end()) {
13033 const auto *OED = dyn_cast<OMPExecutableDirective>(Val: *I);
13034 bool IsTeams = OED && isOpenMPTeamsDirective(DKind: OED->getDirectiveKind());
13035 if (!IsTeams || I != CS->body_begin()) {
13036 OMPTeamsFound = false;
13037 if (IsTeams && I != CS->body_begin()) {
13038 // This is the two teams case. Since the InnerTeamsRegionLoc will
13039 // point to this second one reset the iterator to the other teams.
13040 --I;
13041 }
13042 break;
13043 }
13044 ++I;
13045 }
13046 assert(I != CS->body_end() && "Not found statement");
13047 S = *I;
13048 } else {
13049 const auto *OED = dyn_cast<OMPExecutableDirective>(Val: S);
13050 OMPTeamsFound = OED && isOpenMPTeamsDirective(DKind: OED->getDirectiveKind());
13051 }
13052 if (!OMPTeamsFound) {
13053 Diag(Loc: StartLoc, DiagID: diag::err_omp_target_contains_not_only_teams);
13054 Diag(DSAStack->getInnerTeamsRegionLoc(),
13055 DiagID: diag::note_omp_nested_teams_construct_here);
13056 Diag(Loc: S->getBeginLoc(), DiagID: diag::note_omp_nested_statement_here)
13057 << isa<OMPExecutableDirective>(Val: S);
13058 return StmtError();
13059 }
13060 }
13061
13062 return OMPTargetDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
13063 AssociatedStmt: AStmt);
13064}
13065
13066StmtResult SemaOpenMP::ActOnOpenMPTargetParallelDirective(
13067 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13068 SourceLocation EndLoc) {
13069 if (!AStmt)
13070 return StmtError();
13071
13072 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel, AStmt);
13073
13074 return OMPTargetParallelDirective::Create(
13075 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
13076 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13077}
13078
13079StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForDirective(
13080 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13081 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13082 if (!AStmt)
13083 return StmtError();
13084
13085 CapturedStmt *CS =
13086 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_for, AStmt);
13087
13088 OMPLoopBasedDirective::HelperExprs B;
13089 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13090 // define the nested loops number.
13091 unsigned NestedLoopCount =
13092 checkOpenMPLoop(DKind: OMPD_target_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13093 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
13094 VarsWithImplicitDSA, Built&: B);
13095 if (NestedLoopCount == 0)
13096 return StmtError();
13097
13098 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13099 return StmtError();
13100
13101 return OMPTargetParallelForDirective::Create(
13102 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13103 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13104}
13105
13106/// Check for existence of a map clause in the list of clauses.
13107static bool hasClauses(ArrayRef<OMPClause *> Clauses,
13108 const OpenMPClauseKind K) {
13109 return llvm::any_of(
13110 Range&: Clauses, P: [K](const OMPClause *C) { return C->getClauseKind() == K; });
13111}
13112
13113template <typename... Params>
13114static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
13115 const Params... ClauseTypes) {
13116 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13117}
13118
13119/// Check if the variables in the mapping clause are externally visible.
13120static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
13121 for (const OMPClause *C : Clauses) {
13122 if (auto *TC = dyn_cast<OMPToClause>(Val: C))
13123 return llvm::all_of(Range: TC->all_decls(), P: [](ValueDecl *VD) {
13124 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13125 (VD->isExternallyVisible() &&
13126 VD->getVisibility() != HiddenVisibility);
13127 });
13128 else if (auto *FC = dyn_cast<OMPFromClause>(Val: C))
13129 return llvm::all_of(Range: FC->all_decls(), P: [](ValueDecl *VD) {
13130 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13131 (VD->isExternallyVisible() &&
13132 VD->getVisibility() != HiddenVisibility);
13133 });
13134 }
13135
13136 return true;
13137}
13138
13139StmtResult
13140SemaOpenMP::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
13141 Stmt *AStmt, SourceLocation StartLoc,
13142 SourceLocation EndLoc) {
13143 if (!AStmt)
13144 return StmtError();
13145
13146 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13147
13148 // OpenMP [2.12.2, target data Construct, Restrictions]
13149 // At least one map, use_device_addr or use_device_ptr clause must appear on
13150 // the directive.
13151 if (!hasClauses(Clauses, K: OMPC_map, ClauseTypes: OMPC_use_device_ptr) &&
13152 (getLangOpts().OpenMP < 50 ||
13153 !hasClauses(Clauses, K: OMPC_use_device_addr))) {
13154 StringRef Expected;
13155 if (getLangOpts().OpenMP < 50)
13156 Expected = "'map' or 'use_device_ptr'";
13157 else
13158 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13159 unsigned OMPVersion = getLangOpts().OpenMP;
13160 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
13161 << Expected << getOpenMPDirectiveName(D: OMPD_target_data, Ver: OMPVersion);
13162 return StmtError();
13163 }
13164
13165 SemaRef.setFunctionHasBranchProtectedScope();
13166
13167 return OMPTargetDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13168 Clauses, AssociatedStmt: AStmt);
13169}
13170
13171StmtResult SemaOpenMP::ActOnOpenMPTargetEnterDataDirective(
13172 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13173 SourceLocation EndLoc, Stmt *AStmt) {
13174 if (!AStmt)
13175 return StmtError();
13176
13177 setBranchProtectedScope(SemaRef, DKind: OMPD_target_enter_data, AStmt);
13178
13179 // OpenMP [2.10.2, Restrictions, p. 99]
13180 // At least one map clause must appear on the directive.
13181 if (!hasClauses(Clauses, K: OMPC_map)) {
13182 unsigned OMPVersion = getLangOpts().OpenMP;
13183 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
13184 << "'map'"
13185 << getOpenMPDirectiveName(D: OMPD_target_enter_data, Ver: OMPVersion);
13186 return StmtError();
13187 }
13188
13189 return OMPTargetEnterDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13190 Clauses, AssociatedStmt: AStmt);
13191}
13192
13193StmtResult SemaOpenMP::ActOnOpenMPTargetExitDataDirective(
13194 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13195 SourceLocation EndLoc, Stmt *AStmt) {
13196 if (!AStmt)
13197 return StmtError();
13198
13199 setBranchProtectedScope(SemaRef, DKind: OMPD_target_exit_data, AStmt);
13200
13201 // OpenMP [2.10.3, Restrictions, p. 102]
13202 // At least one map clause must appear on the directive.
13203 if (!hasClauses(Clauses, K: OMPC_map)) {
13204 unsigned OMPVersion = getLangOpts().OpenMP;
13205 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
13206 << "'map'" << getOpenMPDirectiveName(D: OMPD_target_exit_data, Ver: OMPVersion);
13207 return StmtError();
13208 }
13209
13210 return OMPTargetExitDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13211 Clauses, AssociatedStmt: AStmt);
13212}
13213
13214StmtResult SemaOpenMP::ActOnOpenMPTargetUpdateDirective(
13215 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13216 SourceLocation EndLoc, Stmt *AStmt) {
13217 if (!AStmt)
13218 return StmtError();
13219
13220 setBranchProtectedScope(SemaRef, DKind: OMPD_target_update, AStmt);
13221
13222 if (!hasClauses(Clauses, K: OMPC_to, ClauseTypes: OMPC_from)) {
13223 Diag(Loc: StartLoc, DiagID: diag::err_omp_at_least_one_motion_clause_required);
13224 return StmtError();
13225 }
13226
13227 if (!isClauseMappable(Clauses)) {
13228 Diag(Loc: StartLoc, DiagID: diag::err_omp_cannot_update_with_internal_linkage);
13229 return StmtError();
13230 }
13231
13232 return OMPTargetUpdateDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13233 Clauses, AssociatedStmt: AStmt);
13234}
13235
13236/// This checks whether a \p ClauseType clause \p C has at most \p Max
13237/// expression. If not, a diag of number \p Diag will be emitted.
13238template <typename ClauseType>
13239static bool checkNumExprsInClause(SemaBase &SemaRef,
13240 ArrayRef<OMPClause *> Clauses,
13241 unsigned MaxNum, unsigned Diag) {
13242 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13243 if (ClauseItr == Clauses.end())
13244 return true;
13245 const auto *C = cast<ClauseType>(*ClauseItr);
13246 auto VarList = C->getVarRefs();
13247 if (VarList.size() > MaxNum) {
13248 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13249 << getOpenMPClauseNameForDiag(C->getClauseKind());
13250 return false;
13251 }
13252 return true;
13253}
13254
13255StmtResult SemaOpenMP::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
13256 Stmt *AStmt,
13257 SourceLocation StartLoc,
13258 SourceLocation EndLoc) {
13259 if (!AStmt)
13260 return StmtError();
13261
13262 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13263 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed) ||
13264 !checkNumExprsInClause<OMPThreadLimitClause>(
13265 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed))
13266 return StmtError();
13267
13268 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13269 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13270 Diag(Loc: StartLoc, DiagID: diag::warn_hip_omp_target_directives);
13271
13272 setBranchProtectedScope(SemaRef, DKind: OMPD_teams, AStmt);
13273
13274 DSAStack->setParentTeamsRegionLoc(StartLoc);
13275
13276 return OMPTeamsDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
13277 AssociatedStmt: AStmt);
13278}
13279
13280StmtResult SemaOpenMP::ActOnOpenMPCancellationPointDirective(
13281 SourceLocation StartLoc, SourceLocation EndLoc,
13282 OpenMPDirectiveKind CancelRegion) {
13283 if (DSAStack->isParentNowaitRegion()) {
13284 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_nowait) << 0;
13285 return StmtError();
13286 }
13287 if (DSAStack->isParentOrderedRegion()) {
13288 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_ordered) << 0;
13289 return StmtError();
13290 }
13291 return OMPCancellationPointDirective::Create(C: getASTContext(), StartLoc,
13292 EndLoc, CancelRegion);
13293}
13294
13295StmtResult SemaOpenMP::ActOnOpenMPCancelDirective(
13296 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13297 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13298 if (DSAStack->isParentNowaitRegion()) {
13299 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_nowait) << 1;
13300 return StmtError();
13301 }
13302 if (DSAStack->isParentOrderedRegion()) {
13303 Diag(Loc: StartLoc, DiagID: diag::err_omp_parent_cancel_region_ordered) << 1;
13304 return StmtError();
13305 }
13306 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13307 return OMPCancelDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
13308 CancelRegion);
13309}
13310
13311static bool checkReductionClauseWithNogroup(Sema &S,
13312 ArrayRef<OMPClause *> Clauses) {
13313 const OMPClause *ReductionClause = nullptr;
13314 const OMPClause *NogroupClause = nullptr;
13315 for (const OMPClause *C : Clauses) {
13316 if (C->getClauseKind() == OMPC_reduction) {
13317 ReductionClause = C;
13318 if (NogroupClause)
13319 break;
13320 continue;
13321 }
13322 if (C->getClauseKind() == OMPC_nogroup) {
13323 NogroupClause = C;
13324 if (ReductionClause)
13325 break;
13326 continue;
13327 }
13328 }
13329 if (ReductionClause && NogroupClause) {
13330 S.Diag(Loc: ReductionClause->getBeginLoc(), DiagID: diag::err_omp_reduction_with_nogroup)
13331 << SourceRange(NogroupClause->getBeginLoc(),
13332 NogroupClause->getEndLoc());
13333 return true;
13334 }
13335 return false;
13336}
13337
13338StmtResult SemaOpenMP::ActOnOpenMPTaskLoopDirective(
13339 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13340 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13341 if (!AStmt)
13342 return StmtError();
13343
13344 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13345 OMPLoopBasedDirective::HelperExprs B;
13346 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13347 // define the nested loops number.
13348 unsigned NestedLoopCount =
13349 checkOpenMPLoop(DKind: OMPD_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13350 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13351 DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
13352 if (NestedLoopCount == 0)
13353 return StmtError();
13354
13355 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13356 "omp for loop exprs were not built");
13357
13358 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13359 // The grainsize clause and num_tasks clause are mutually exclusive and may
13360 // not appear on the same taskloop directive.
13361 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13362 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13363 return StmtError();
13364 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13365 // If a reduction clause is present on the taskloop directive, the nogroup
13366 // clause must not be specified.
13367 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13368 return StmtError();
13369
13370 SemaRef.setFunctionHasBranchProtectedScope();
13371 return OMPTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13372 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13373 DSAStack->isCancelRegion());
13374}
13375
13376StmtResult SemaOpenMP::ActOnOpenMPTaskLoopSimdDirective(
13377 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13378 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13379 if (!AStmt)
13380 return StmtError();
13381
13382 CapturedStmt *CS =
13383 setBranchProtectedScope(SemaRef, DKind: OMPD_taskloop_simd, AStmt);
13384
13385 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13386 OMPLoopBasedDirective::HelperExprs B;
13387 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13388 // define the nested loops number.
13389 unsigned NestedLoopCount =
13390 checkOpenMPLoop(DKind: OMPD_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13391 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
13392 VarsWithImplicitDSA, Built&: B);
13393 if (NestedLoopCount == 0)
13394 return StmtError();
13395
13396 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13397 return StmtError();
13398
13399 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13400 // The grainsize clause and num_tasks clause are mutually exclusive and may
13401 // not appear on the same taskloop directive.
13402 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13403 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13404 return StmtError();
13405 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13406 // If a reduction clause is present on the taskloop directive, the nogroup
13407 // clause must not be specified.
13408 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13409 return StmtError();
13410 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13411 return StmtError();
13412
13413 return OMPTaskLoopSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13414 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13415}
13416
13417StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopDirective(
13418 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13419 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13420 if (!AStmt)
13421 return StmtError();
13422
13423 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13424 OMPLoopBasedDirective::HelperExprs B;
13425 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13426 // define the nested loops number.
13427 unsigned NestedLoopCount =
13428 checkOpenMPLoop(DKind: OMPD_master_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13429 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13430 DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
13431 if (NestedLoopCount == 0)
13432 return StmtError();
13433
13434 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13435 "omp for loop exprs were not built");
13436
13437 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13438 // The grainsize clause and num_tasks clause are mutually exclusive and may
13439 // not appear on the same taskloop directive.
13440 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13441 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13442 return StmtError();
13443 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13444 // If a reduction clause is present on the taskloop directive, the nogroup
13445 // clause must not be specified.
13446 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13447 return StmtError();
13448
13449 SemaRef.setFunctionHasBranchProtectedScope();
13450 return OMPMasterTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13451 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13452 DSAStack->isCancelRegion());
13453}
13454
13455StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopDirective(
13456 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13457 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13458 if (!AStmt)
13459 return StmtError();
13460
13461 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13462 OMPLoopBasedDirective::HelperExprs B;
13463 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13464 // define the nested loops number.
13465 unsigned NestedLoopCount =
13466 checkOpenMPLoop(DKind: OMPD_masked_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13467 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13468 DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
13469 if (NestedLoopCount == 0)
13470 return StmtError();
13471
13472 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13473 "omp for loop exprs were not built");
13474
13475 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13476 // The grainsize clause and num_tasks clause are mutually exclusive and may
13477 // not appear on the same taskloop directive.
13478 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13479 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13480 return StmtError();
13481 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13482 // If a reduction clause is present on the taskloop directive, the nogroup
13483 // clause must not be specified.
13484 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13485 return StmtError();
13486
13487 SemaRef.setFunctionHasBranchProtectedScope();
13488 return OMPMaskedTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13489 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13490 DSAStack->isCancelRegion());
13491}
13492
13493StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopSimdDirective(
13494 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13495 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13496 if (!AStmt)
13497 return StmtError();
13498
13499 CapturedStmt *CS =
13500 setBranchProtectedScope(SemaRef, DKind: OMPD_master_taskloop_simd, AStmt);
13501
13502 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13503 OMPLoopBasedDirective::HelperExprs B;
13504 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13505 // define the nested loops number.
13506 unsigned NestedLoopCount =
13507 checkOpenMPLoop(DKind: OMPD_master_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13508 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
13509 VarsWithImplicitDSA, Built&: B);
13510 if (NestedLoopCount == 0)
13511 return StmtError();
13512
13513 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13514 return StmtError();
13515
13516 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13517 // The grainsize clause and num_tasks clause are mutually exclusive and may
13518 // not appear on the same taskloop directive.
13519 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13520 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13521 return StmtError();
13522 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13523 // If a reduction clause is present on the taskloop directive, the nogroup
13524 // clause must not be specified.
13525 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13526 return StmtError();
13527 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13528 return StmtError();
13529
13530 return OMPMasterTaskLoopSimdDirective::Create(
13531 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13532}
13533
13534StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopSimdDirective(
13535 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13536 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13537 if (!AStmt)
13538 return StmtError();
13539
13540 CapturedStmt *CS =
13541 setBranchProtectedScope(SemaRef, DKind: OMPD_masked_taskloop_simd, AStmt);
13542
13543 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13544 OMPLoopBasedDirective::HelperExprs B;
13545 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13546 // define the nested loops number.
13547 unsigned NestedLoopCount =
13548 checkOpenMPLoop(DKind: OMPD_masked_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13549 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
13550 VarsWithImplicitDSA, Built&: B);
13551 if (NestedLoopCount == 0)
13552 return StmtError();
13553
13554 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13555 return StmtError();
13556
13557 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13558 // The grainsize clause and num_tasks clause are mutually exclusive and may
13559 // not appear on the same taskloop directive.
13560 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13561 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13562 return StmtError();
13563 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13564 // If a reduction clause is present on the taskloop directive, the nogroup
13565 // clause must not be specified.
13566 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13567 return StmtError();
13568 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13569 return StmtError();
13570
13571 return OMPMaskedTaskLoopSimdDirective::Create(
13572 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13573}
13574
13575StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopDirective(
13576 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13577 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13578 if (!AStmt)
13579 return StmtError();
13580
13581 CapturedStmt *CS =
13582 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_master_taskloop, AStmt);
13583
13584 OMPLoopBasedDirective::HelperExprs B;
13585 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13586 // define the nested loops number.
13587 unsigned NestedLoopCount = checkOpenMPLoop(
13588 DKind: OMPD_parallel_master_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13589 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
13590 VarsWithImplicitDSA, Built&: B);
13591 if (NestedLoopCount == 0)
13592 return StmtError();
13593
13594 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13595 "omp for loop exprs were not built");
13596
13597 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13598 // The grainsize clause and num_tasks clause are mutually exclusive and may
13599 // not appear on the same taskloop directive.
13600 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13601 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13602 return StmtError();
13603 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13604 // If a reduction clause is present on the taskloop directive, the nogroup
13605 // clause must not be specified.
13606 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13607 return StmtError();
13608
13609 return OMPParallelMasterTaskLoopDirective::Create(
13610 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13611 DSAStack->isCancelRegion());
13612}
13613
13614StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopDirective(
13615 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13616 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13617 if (!AStmt)
13618 return StmtError();
13619
13620 CapturedStmt *CS =
13621 setBranchProtectedScope(SemaRef, DKind: OMPD_parallel_masked_taskloop, AStmt);
13622
13623 OMPLoopBasedDirective::HelperExprs B;
13624 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13625 // define the nested loops number.
13626 unsigned NestedLoopCount = checkOpenMPLoop(
13627 DKind: OMPD_parallel_masked_taskloop, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13628 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
13629 VarsWithImplicitDSA, Built&: B);
13630 if (NestedLoopCount == 0)
13631 return StmtError();
13632
13633 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13634 "omp for loop exprs were not built");
13635
13636 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13637 // The grainsize clause and num_tasks clause are mutually exclusive and may
13638 // not appear on the same taskloop directive.
13639 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13640 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13641 return StmtError();
13642 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13643 // If a reduction clause is present on the taskloop directive, the nogroup
13644 // clause must not be specified.
13645 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13646 return StmtError();
13647
13648 return OMPParallelMaskedTaskLoopDirective::Create(
13649 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13650 DSAStack->isCancelRegion());
13651}
13652
13653StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
13654 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13655 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13656 if (!AStmt)
13657 return StmtError();
13658
13659 CapturedStmt *CS = setBranchProtectedScope(
13660 SemaRef, DKind: OMPD_parallel_master_taskloop_simd, AStmt);
13661
13662 OMPLoopBasedDirective::HelperExprs B;
13663 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13664 // define the nested loops number.
13665 unsigned NestedLoopCount = checkOpenMPLoop(
13666 DKind: OMPD_parallel_master_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13667 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
13668 VarsWithImplicitDSA, Built&: B);
13669 if (NestedLoopCount == 0)
13670 return StmtError();
13671
13672 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13673 return StmtError();
13674
13675 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13676 // The grainsize clause and num_tasks clause are mutually exclusive and may
13677 // not appear on the same taskloop directive.
13678 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13679 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13680 return StmtError();
13681 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13682 // If a reduction clause is present on the taskloop directive, the nogroup
13683 // clause must not be specified.
13684 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13685 return StmtError();
13686 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13687 return StmtError();
13688
13689 return OMPParallelMasterTaskLoopSimdDirective::Create(
13690 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13691}
13692
13693StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
13694 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13695 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13696 if (!AStmt)
13697 return StmtError();
13698
13699 CapturedStmt *CS = setBranchProtectedScope(
13700 SemaRef, DKind: OMPD_parallel_masked_taskloop_simd, AStmt);
13701
13702 OMPLoopBasedDirective::HelperExprs B;
13703 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13704 // define the nested loops number.
13705 unsigned NestedLoopCount = checkOpenMPLoop(
13706 DKind: OMPD_parallel_masked_taskloop_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13707 /*OrderedLoopCountExpr=*/nullptr, AStmt: CS, SemaRef, DSA&: *DSAStack,
13708 VarsWithImplicitDSA, Built&: B);
13709 if (NestedLoopCount == 0)
13710 return StmtError();
13711
13712 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13713 return StmtError();
13714
13715 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13716 // The grainsize clause and num_tasks clause are mutually exclusive and may
13717 // not appear on the same taskloop directive.
13718 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
13719 MutuallyExclusiveClauses: {OMPC_grainsize, OMPC_num_tasks}))
13720 return StmtError();
13721 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13722 // If a reduction clause is present on the taskloop directive, the nogroup
13723 // clause must not be specified.
13724 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13725 return StmtError();
13726 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13727 return StmtError();
13728
13729 return OMPParallelMaskedTaskLoopSimdDirective::Create(
13730 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13731}
13732
13733StmtResult SemaOpenMP::ActOnOpenMPDistributeDirective(
13734 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13735 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13736 if (!AStmt)
13737 return StmtError();
13738
13739 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13740 OMPLoopBasedDirective::HelperExprs B;
13741 // In presence of clause 'collapse' with number of loops, it will
13742 // define the nested loops number.
13743 unsigned NestedLoopCount =
13744 checkOpenMPLoop(DKind: OMPD_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13745 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt,
13746 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
13747 if (NestedLoopCount == 0)
13748 return StmtError();
13749
13750 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13751 "omp for loop exprs were not built");
13752
13753 SemaRef.setFunctionHasBranchProtectedScope();
13754 auto *DistributeDirective = OMPDistributeDirective::Create(
13755 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13756 return DistributeDirective;
13757}
13758
13759StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForDirective(
13760 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13761 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13762 if (!AStmt)
13763 return StmtError();
13764
13765 CapturedStmt *CS =
13766 setBranchProtectedScope(SemaRef, DKind: OMPD_distribute_parallel_for, AStmt);
13767
13768 OMPLoopBasedDirective::HelperExprs B;
13769 // In presence of clause 'collapse' with number of loops, it will
13770 // define the nested loops number.
13771 unsigned NestedLoopCount = checkOpenMPLoop(
13772 DKind: OMPD_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13773 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
13774 VarsWithImplicitDSA, Built&: B);
13775 if (NestedLoopCount == 0)
13776 return StmtError();
13777
13778 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13779 "omp for loop exprs were not built");
13780
13781 return OMPDistributeParallelForDirective::Create(
13782 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13783 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13784}
13785
13786StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForSimdDirective(
13787 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13788 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13789 if (!AStmt)
13790 return StmtError();
13791
13792 CapturedStmt *CS = setBranchProtectedScope(
13793 SemaRef, DKind: OMPD_distribute_parallel_for_simd, AStmt);
13794
13795 OMPLoopBasedDirective::HelperExprs B;
13796 // In presence of clause 'collapse' with number of loops, it will
13797 // define the nested loops number.
13798 unsigned NestedLoopCount = checkOpenMPLoop(
13799 DKind: OMPD_distribute_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13800 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
13801 VarsWithImplicitDSA, Built&: B);
13802 if (NestedLoopCount == 0)
13803 return StmtError();
13804
13805 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13806 return StmtError();
13807
13808 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13809 return StmtError();
13810
13811 return OMPDistributeParallelForSimdDirective::Create(
13812 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13813}
13814
13815StmtResult SemaOpenMP::ActOnOpenMPDistributeSimdDirective(
13816 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13817 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13818 if (!AStmt)
13819 return StmtError();
13820
13821 CapturedStmt *CS =
13822 setBranchProtectedScope(SemaRef, DKind: OMPD_distribute_simd, AStmt);
13823
13824 OMPLoopBasedDirective::HelperExprs B;
13825 // In presence of clause 'collapse' with number of loops, it will
13826 // define the nested loops number.
13827 unsigned NestedLoopCount =
13828 checkOpenMPLoop(DKind: OMPD_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13829 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
13830 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
13831 if (NestedLoopCount == 0)
13832 return StmtError();
13833
13834 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13835 return StmtError();
13836
13837 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13838 return StmtError();
13839
13840 return OMPDistributeSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13841 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13842}
13843
13844StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForSimdDirective(
13845 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13846 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13847 if (!AStmt)
13848 return StmtError();
13849
13850 CapturedStmt *CS =
13851 setBranchProtectedScope(SemaRef, DKind: OMPD_target_parallel_for_simd, AStmt);
13852
13853 OMPLoopBasedDirective::HelperExprs B;
13854 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13855 // define the nested loops number.
13856 unsigned NestedLoopCount = checkOpenMPLoop(
13857 DKind: OMPD_target_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13858 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
13859 VarsWithImplicitDSA, Built&: B);
13860 if (NestedLoopCount == 0)
13861 return StmtError();
13862
13863 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13864 return StmtError();
13865
13866 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13867 return StmtError();
13868
13869 return OMPTargetParallelForSimdDirective::Create(
13870 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13871}
13872
13873StmtResult SemaOpenMP::ActOnOpenMPTargetSimdDirective(
13874 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13875 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13876 if (!AStmt)
13877 return StmtError();
13878
13879 CapturedStmt *CS = setBranchProtectedScope(SemaRef, DKind: OMPD_target_simd, AStmt);
13880
13881 OMPLoopBasedDirective::HelperExprs B;
13882 // In presence of clause 'collapse' with number of loops, it will define the
13883 // nested loops number.
13884 unsigned NestedLoopCount =
13885 checkOpenMPLoop(DKind: OMPD_target_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13886 OrderedLoopCountExpr: getOrderedNumberExpr(Clauses), AStmt: CS, SemaRef, DSA&: *DSAStack,
13887 VarsWithImplicitDSA, Built&: B);
13888 if (NestedLoopCount == 0)
13889 return StmtError();
13890
13891 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13892 return StmtError();
13893
13894 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13895 return StmtError();
13896
13897 return OMPTargetSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13898 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13899}
13900
13901StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeDirective(
13902 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13903 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13904 if (!AStmt)
13905 return StmtError();
13906
13907 CapturedStmt *CS =
13908 setBranchProtectedScope(SemaRef, DKind: OMPD_teams_distribute, AStmt);
13909
13910 OMPLoopBasedDirective::HelperExprs B;
13911 // In presence of clause 'collapse' with number of loops, it will
13912 // define the nested loops number.
13913 unsigned NestedLoopCount =
13914 checkOpenMPLoop(DKind: OMPD_teams_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13915 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
13916 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
13917 if (NestedLoopCount == 0)
13918 return StmtError();
13919
13920 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13921 "omp teams distribute loop exprs were not built");
13922
13923 DSAStack->setParentTeamsRegionLoc(StartLoc);
13924
13925 return OMPTeamsDistributeDirective::Create(
13926 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13927}
13928
13929StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeSimdDirective(
13930 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13931 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13932 if (!AStmt)
13933 return StmtError();
13934
13935 CapturedStmt *CS =
13936 setBranchProtectedScope(SemaRef, DKind: OMPD_teams_distribute_simd, AStmt);
13937
13938 OMPLoopBasedDirective::HelperExprs B;
13939 // In presence of clause 'collapse' with number of loops, it will
13940 // define the nested loops number.
13941 unsigned NestedLoopCount = checkOpenMPLoop(
13942 DKind: OMPD_teams_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13943 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
13944 VarsWithImplicitDSA, Built&: B);
13945 if (NestedLoopCount == 0)
13946 return StmtError();
13947
13948 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13949 return StmtError();
13950
13951 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13952 return StmtError();
13953
13954 DSAStack->setParentTeamsRegionLoc(StartLoc);
13955
13956 return OMPTeamsDistributeSimdDirective::Create(
13957 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13958}
13959
13960StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
13961 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13962 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13963 if (!AStmt)
13964 return StmtError();
13965
13966 CapturedStmt *CS = setBranchProtectedScope(
13967 SemaRef, DKind: OMPD_teams_distribute_parallel_for_simd, AStmt);
13968
13969 OMPLoopBasedDirective::HelperExprs B;
13970 // In presence of clause 'collapse' with number of loops, it will
13971 // define the nested loops number.
13972 unsigned NestedLoopCount = checkOpenMPLoop(
13973 DKind: OMPD_teams_distribute_parallel_for_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
13974 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
13975 VarsWithImplicitDSA, Built&: B);
13976 if (NestedLoopCount == 0)
13977 return StmtError();
13978
13979 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13980 return StmtError();
13981
13982 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13983 return StmtError();
13984
13985 DSAStack->setParentTeamsRegionLoc(StartLoc);
13986
13987 return OMPTeamsDistributeParallelForSimdDirective::Create(
13988 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13989}
13990
13991StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForDirective(
13992 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13993 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13994 if (!AStmt)
13995 return StmtError();
13996
13997 CapturedStmt *CS = setBranchProtectedScope(
13998 SemaRef, DKind: OMPD_teams_distribute_parallel_for, AStmt);
13999
14000 OMPLoopBasedDirective::HelperExprs B;
14001 // In presence of clause 'collapse' with number of loops, it will
14002 // define the nested loops number.
14003 unsigned NestedLoopCount = checkOpenMPLoop(
14004 DKind: OMPD_teams_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14005 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14006 VarsWithImplicitDSA, Built&: B);
14007
14008 if (NestedLoopCount == 0)
14009 return StmtError();
14010
14011 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14012 "omp for loop exprs were not built");
14013
14014 DSAStack->setParentTeamsRegionLoc(StartLoc);
14015
14016 return OMPTeamsDistributeParallelForDirective::Create(
14017 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14018 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14019}
14020
14021StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDirective(
14022 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14023 SourceLocation EndLoc) {
14024 if (!AStmt)
14025 return StmtError();
14026
14027 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams, AStmt);
14028
14029 const OMPClause *BareClause = nullptr;
14030 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, K: OMPC_num_teams) &&
14031 hasClauses(Clauses, K: OMPC_thread_limit);
14032 bool HasBareClause = llvm::any_of(Range&: Clauses, P: [&](const OMPClause *C) {
14033 BareClause = C;
14034 return C->getClauseKind() == OMPC_ompx_bare;
14035 });
14036
14037 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14038 Diag(Loc: BareClause->getBeginLoc(), DiagID: diag::err_ompx_bare_no_grid);
14039 return StmtError();
14040 }
14041
14042 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14043 unsigned DiagNo = HasBareClause
14044 ? diag::err_ompx_more_than_three_expr_not_allowed
14045 : diag::err_omp_multi_expr_not_allowed;
14046 if (!checkNumExprsInClause<OMPNumTeamsClause>(SemaRef&: *this, Clauses,
14047 MaxNum: ClauseMaxNumExprs, Diag: DiagNo) ||
14048 !checkNumExprsInClause<OMPThreadLimitClause>(SemaRef&: *this, Clauses,
14049 MaxNum: ClauseMaxNumExprs, Diag: DiagNo))
14050 return StmtError();
14051
14052 return OMPTargetTeamsDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14053 Clauses, AssociatedStmt: AStmt);
14054}
14055
14056StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeDirective(
14057 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14058 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14059 if (!AStmt)
14060 return StmtError();
14061
14062 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14063 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed) ||
14064 !checkNumExprsInClause<OMPThreadLimitClause>(
14065 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed))
14066 return StmtError();
14067
14068 CapturedStmt *CS =
14069 setBranchProtectedScope(SemaRef, DKind: OMPD_target_teams_distribute, AStmt);
14070
14071 OMPLoopBasedDirective::HelperExprs B;
14072 // In presence of clause 'collapse' with number of loops, it will
14073 // define the nested loops number.
14074 unsigned NestedLoopCount = checkOpenMPLoop(
14075 DKind: OMPD_target_teams_distribute, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14076 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14077 VarsWithImplicitDSA, Built&: B);
14078 if (NestedLoopCount == 0)
14079 return StmtError();
14080
14081 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14082 "omp target teams distribute loop exprs were not built");
14083
14084 return OMPTargetTeamsDistributeDirective::Create(
14085 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14086}
14087
14088StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14089 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14090 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14091 if (!AStmt)
14092 return StmtError();
14093
14094 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14095 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed) ||
14096 !checkNumExprsInClause<OMPThreadLimitClause>(
14097 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed))
14098 return StmtError();
14099
14100 CapturedStmt *CS = setBranchProtectedScope(
14101 SemaRef, DKind: OMPD_target_teams_distribute_parallel_for, AStmt);
14102
14103 OMPLoopBasedDirective::HelperExprs B;
14104 // In presence of clause 'collapse' with number of loops, it will
14105 // define the nested loops number.
14106 unsigned NestedLoopCount = checkOpenMPLoop(
14107 DKind: OMPD_target_teams_distribute_parallel_for, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14108 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14109 VarsWithImplicitDSA, Built&: B);
14110 if (NestedLoopCount == 0)
14111 return StmtError();
14112
14113 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14114 return StmtError();
14115
14116 return OMPTargetTeamsDistributeParallelForDirective::Create(
14117 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14118 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14119}
14120
14121StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14122 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14123 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14124 if (!AStmt)
14125 return StmtError();
14126
14127 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14128 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed) ||
14129 !checkNumExprsInClause<OMPThreadLimitClause>(
14130 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed))
14131 return StmtError();
14132
14133 CapturedStmt *CS = setBranchProtectedScope(
14134 SemaRef, DKind: OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14135
14136 OMPLoopBasedDirective::HelperExprs B;
14137 // In presence of clause 'collapse' with number of loops, it will
14138 // define the nested loops number.
14139 unsigned NestedLoopCount =
14140 checkOpenMPLoop(DKind: OMPD_target_teams_distribute_parallel_for_simd,
14141 CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14142 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS,
14143 SemaRef, DSA&: *DSAStack, VarsWithImplicitDSA, Built&: B);
14144 if (NestedLoopCount == 0)
14145 return StmtError();
14146
14147 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14148 return StmtError();
14149
14150 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14151 return StmtError();
14152
14153 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14154 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14155}
14156
14157StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14158 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14159 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14160 if (!AStmt)
14161 return StmtError();
14162
14163 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14164 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed) ||
14165 !checkNumExprsInClause<OMPThreadLimitClause>(
14166 SemaRef&: *this, Clauses, /*MaxNum=*/1, Diag: diag::err_omp_multi_expr_not_allowed))
14167 return StmtError();
14168
14169 CapturedStmt *CS = setBranchProtectedScope(
14170 SemaRef, DKind: OMPD_target_teams_distribute_simd, AStmt);
14171
14172 OMPLoopBasedDirective::HelperExprs B;
14173 // In presence of clause 'collapse' with number of loops, it will
14174 // define the nested loops number.
14175 unsigned NestedLoopCount = checkOpenMPLoop(
14176 DKind: OMPD_target_teams_distribute_simd, CollapseLoopCountExpr: getCollapseNumberExpr(Clauses),
14177 OrderedLoopCountExpr: nullptr /*ordered not a clause on distribute*/, AStmt: CS, SemaRef, DSA&: *DSAStack,
14178 VarsWithImplicitDSA, Built&: B);
14179 if (NestedLoopCount == 0)
14180 return StmtError();
14181
14182 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14183 return StmtError();
14184
14185 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14186 return StmtError();
14187
14188 return OMPTargetTeamsDistributeSimdDirective::Create(
14189 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14190}
14191
14192bool SemaOpenMP::checkTransformableLoopNest(
14193 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14194 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14195 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits) {
14196 OriginalInits.emplace_back();
14197 bool Result = OMPLoopBasedDirective::doForAllLoops(
14198 CurStmt: AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14199 Callback: [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14200 Stmt *CurStmt) {
14201 VarsWithInheritedDSAType TmpDSA;
14202 unsigned SingleNumLoops =
14203 checkOpenMPLoop(DKind: Kind, CollapseLoopCountExpr: nullptr, OrderedLoopCountExpr: nullptr, AStmt: CurStmt, SemaRef, DSA&: *DSAStack,
14204 VarsWithImplicitDSA&: TmpDSA, Built&: LoopHelpers[Cnt]);
14205 if (SingleNumLoops == 0)
14206 return true;
14207 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14208 if (auto *For = dyn_cast<ForStmt>(Val: CurStmt)) {
14209 OriginalInits.back().push_back(Elt: For->getInit());
14210 Body = For->getBody();
14211 } else {
14212 assert(isa<CXXForRangeStmt>(CurStmt) &&
14213 "Expected canonical for or range-based for loops.");
14214 auto *CXXFor = cast<CXXForRangeStmt>(Val: CurStmt);
14215 OriginalInits.back().push_back(Elt: CXXFor->getBeginStmt());
14216 Body = CXXFor->getBody();
14217 }
14218 OriginalInits.emplace_back();
14219 return false;
14220 },
14221 OnTransformationCallback: [&OriginalInits](OMPLoopBasedDirective *Transform) {
14222 Stmt *DependentPreInits;
14223 if (auto *Dir = dyn_cast<OMPTileDirective>(Val: Transform))
14224 DependentPreInits = Dir->getPreInits();
14225 else if (auto *Dir = dyn_cast<OMPStripeDirective>(Val: Transform))
14226 DependentPreInits = Dir->getPreInits();
14227 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Val: Transform))
14228 DependentPreInits = Dir->getPreInits();
14229 else if (auto *Dir = dyn_cast<OMPReverseDirective>(Val: Transform))
14230 DependentPreInits = Dir->getPreInits();
14231 else if (auto *Dir = dyn_cast<OMPInterchangeDirective>(Val: Transform))
14232 DependentPreInits = Dir->getPreInits();
14233 else
14234 llvm_unreachable("Unhandled loop transformation");
14235
14236 appendFlattenedStmtList(TargetList&: OriginalInits.back(), Item: DependentPreInits);
14237 });
14238 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14239 OriginalInits.pop_back();
14240 return Result;
14241}
14242
14243/// Add preinit statements that need to be propageted from the selected loop.
14244static void addLoopPreInits(ASTContext &Context,
14245 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14246 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14247 SmallVectorImpl<Stmt *> &PreInits) {
14248
14249 // For range-based for-statements, ensure that their syntactic sugar is
14250 // executed by adding them as pre-init statements.
14251 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt)) {
14252 Stmt *RangeInit = CXXRangeFor->getInit();
14253 if (RangeInit)
14254 PreInits.push_back(Elt: RangeInit);
14255
14256 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14257 PreInits.push_back(Elt: new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14258 RangeStmt->getBeginLoc(),
14259 RangeStmt->getEndLoc()));
14260
14261 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14262 PreInits.push_back(Elt: new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14263 RangeEnd->getBeginLoc(),
14264 RangeEnd->getEndLoc()));
14265 }
14266
14267 llvm::append_range(C&: PreInits, R&: OriginalInit);
14268
14269 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14270 if (auto *PI = cast_or_null<DeclStmt>(Val: LoopHelper.PreInits)) {
14271 PreInits.push_back(Elt: new (Context) DeclStmt(
14272 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14273 }
14274
14275 // Gather declarations for the data members used as counters.
14276 for (Expr *CounterRef : LoopHelper.Counters) {
14277 auto *CounterDecl = cast<DeclRefExpr>(Val: CounterRef)->getDecl();
14278 if (isa<OMPCapturedExprDecl>(Val: CounterDecl))
14279 PreInits.push_back(Elt: new (Context) DeclStmt(
14280 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14281 }
14282}
14283
14284/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14285/// loop of a construct.
14286static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14287 size_t NumLoops = LoopStmts.size();
14288 OMPLoopBasedDirective::doForAllLoops(
14289 CurStmt: AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14290 Callback: [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14291 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14292 LoopStmts[Cnt] = CurStmt;
14293 return false;
14294 });
14295 assert(!is_contained(LoopStmts, nullptr) &&
14296 "Expecting a loop statement for each affected loop");
14297}
14298
14299/// Build and return a DeclRefExpr for the floor induction variable using the
14300/// SemaRef and the provided parameters.
14301static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
14302 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
14303 return buildDeclRefExpr(S&: SemaRef, D: FloorIndVars[I], Ty: IVTy,
14304 Loc: OrigCntVar->getExprLoc());
14305}
14306
14307StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
14308 Stmt *AStmt,
14309 SourceLocation StartLoc,
14310 SourceLocation EndLoc) {
14311 ASTContext &Context = getASTContext();
14312 Scope *CurScope = SemaRef.getCurScope();
14313
14314 const auto *SizesClause =
14315 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14316 if (!SizesClause ||
14317 llvm::any_of(Range: SizesClause->getSizesRefs(), P: [](Expr *E) { return !E; }))
14318 return StmtError();
14319 unsigned NumLoops = SizesClause->getNumSizes();
14320
14321 // Empty statement should only be possible if there already was an error.
14322 if (!AStmt)
14323 return StmtError();
14324
14325 // Verify and diagnose loop nest.
14326 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14327 Stmt *Body = nullptr;
14328 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14329 if (!checkTransformableLoopNest(Kind: OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14330 OriginalInits))
14331 return StmtError();
14332
14333 // Delay tiling to when template is completely instantiated.
14334 if (SemaRef.CurContext->isDependentContext())
14335 return OMPTileDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
14336 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
14337
14338 assert(LoopHelpers.size() == NumLoops &&
14339 "Expecting loop iteration space dimensionality to match number of "
14340 "affected loops");
14341 assert(OriginalInits.size() == NumLoops &&
14342 "Expecting loop iteration space dimensionality to match number of "
14343 "affected loops");
14344
14345 // Collect all affected loop statements.
14346 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14347 collectLoopStmts(AStmt, LoopStmts);
14348
14349 SmallVector<Stmt *, 4> PreInits;
14350 CaptureVars CopyTransformer(SemaRef);
14351
14352 // Create iteration variables for the generated loops.
14353 SmallVector<VarDecl *, 4> FloorIndVars;
14354 SmallVector<VarDecl *, 4> TileIndVars;
14355 FloorIndVars.resize(N: NumLoops);
14356 TileIndVars.resize(N: NumLoops);
14357 for (unsigned I = 0; I < NumLoops; ++I) {
14358 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14359
14360 assert(LoopHelper.Counters.size() == 1 &&
14361 "Expect single-dimensional loop iteration space");
14362 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
14363 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14364 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
14365 QualType CntTy = IterVarRef->getType();
14366
14367 // Iteration variable for the floor (i.e. outer) loop.
14368 {
14369 std::string FloorCntName =
14370 (Twine(".floor_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
14371 VarDecl *FloorCntDecl =
14372 buildVarDecl(SemaRef, Loc: {}, Type: CntTy, Name: FloorCntName, Attrs: nullptr, OrigRef: OrigCntVar);
14373 FloorIndVars[I] = FloorCntDecl;
14374 }
14375
14376 // Iteration variable for the tile (i.e. inner) loop.
14377 {
14378 std::string TileCntName =
14379 (Twine(".tile_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
14380
14381 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14382 // used by the expressions to derive the original iteration variable's
14383 // value from the logical iteration number.
14384 auto *TileCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
14385 TileCntDecl->setDeclName(
14386 &SemaRef.PP.getIdentifierTable().get(Name: TileCntName));
14387 TileIndVars[I] = TileCntDecl;
14388 }
14389
14390 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
14391 PreInits);
14392 }
14393
14394 // Once the original iteration values are set, append the innermost body.
14395 Stmt *Inner = Body;
14396
14397 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14398 SizesClause, CurScope](int I) -> Expr * {
14399 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14400
14401 if (DimTileSizeExpr->containsErrors())
14402 return nullptr;
14403
14404 if (isa<ConstantExpr>(Val: DimTileSizeExpr))
14405 return AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr));
14406
14407 // When the tile size is not a constant but a variable, it is possible to
14408 // pass non-positive numbers. For instance:
14409 // \code{c}
14410 // int a = 0;
14411 // #pragma omp tile sizes(a)
14412 // for (int i = 0; i < 42; ++i)
14413 // body(i);
14414 // \endcode
14415 // Although there is no meaningful interpretation of the tile size, the body
14416 // should still be executed 42 times to avoid surprises. To preserve the
14417 // invariant that every loop iteration is executed exactly once and not
14418 // cause an infinite loop, apply a minimum tile size of one.
14419 // Build expr:
14420 // \code{c}
14421 // (TS <= 0) ? 1 : TS
14422 // \endcode
14423 QualType DimTy = DimTileSizeExpr->getType();
14424 uint64_t DimWidth = Context.getTypeSize(T: DimTy);
14425 IntegerLiteral *Zero = IntegerLiteral::Create(
14426 C: Context, V: llvm::APInt::getZero(numBits: DimWidth), type: DimTy, l: {});
14427 IntegerLiteral *One =
14428 IntegerLiteral::Create(C: Context, V: llvm::APInt(DimWidth, 1), type: DimTy, l: {});
14429 Expr *Cond = AssertSuccess(R: SemaRef.BuildBinOp(
14430 S: CurScope, OpLoc: {}, Opc: BO_LE,
14431 LHSExpr: AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr)), RHSExpr: Zero));
14432 Expr *MinOne = new (Context) ConditionalOperator(
14433 Cond, {}, One, {},
14434 AssertSuccess(R: CopyTransformer.TransformExpr(E: DimTileSizeExpr)), DimTy,
14435 VK_PRValue, OK_Ordinary);
14436 return MinOne;
14437 };
14438
14439 // Create tile loops from the inside to the outside.
14440 for (int I = NumLoops - 1; I >= 0; --I) {
14441 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14442 Expr *NumIterations = LoopHelper.NumIterations;
14443 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
14444 QualType IVTy = NumIterations->getType();
14445 Stmt *LoopStmt = LoopStmts[I];
14446
14447 // Commonly used variables. One of the constraints of an AST is that every
14448 // node object must appear at most once, hence we define a lambda that
14449 // creates a new AST node at every use.
14450 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14451 OrigCntVar]() {
14452 return buildDeclRefExpr(S&: SemaRef, D: TileIndVars[I], Ty: IVTy,
14453 Loc: OrigCntVar->getExprLoc());
14454 };
14455
14456 // For init-statement: auto .tile.iv = .floor.iv
14457 SemaRef.AddInitializerToDecl(
14458 dcl: TileIndVars[I],
14459 init: SemaRef
14460 .DefaultLvalueConversion(
14461 E: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14462 .get(),
14463 /*DirectInit=*/false);
14464 Decl *CounterDecl = TileIndVars[I];
14465 StmtResult InitStmt = new (Context)
14466 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
14467 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14468 if (!InitStmt.isUsable())
14469 return StmtError();
14470
14471 // For cond-expression:
14472 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14473 Expr *DimTileSize = MakeDimTileSize(I);
14474 if (!DimTileSize)
14475 return StmtError();
14476 ExprResult EndOfTile = SemaRef.BuildBinOp(
14477 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
14478 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14479 RHSExpr: DimTileSize);
14480 if (!EndOfTile.isUsable())
14481 return StmtError();
14482 ExprResult IsPartialTile =
14483 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
14484 LHSExpr: NumIterations, RHSExpr: EndOfTile.get());
14485 if (!IsPartialTile.isUsable())
14486 return StmtError();
14487 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14488 QuestionLoc: LoopHelper.Cond->getBeginLoc(), ColonLoc: LoopHelper.Cond->getEndLoc(),
14489 CondExpr: IsPartialTile.get(), LHSExpr: NumIterations, RHSExpr: EndOfTile.get());
14490 if (!MinTileAndIterSpace.isUsable())
14491 return StmtError();
14492 ExprResult CondExpr =
14493 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
14494 LHSExpr: MakeTileIVRef(), RHSExpr: MinTileAndIterSpace.get());
14495 if (!CondExpr.isUsable())
14496 return StmtError();
14497
14498 // For incr-statement: ++.tile.iv
14499 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14500 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeTileIVRef());
14501 if (!IncrStmt.isUsable())
14502 return StmtError();
14503
14504 // Statements to set the original iteration variable's value from the
14505 // logical iteration number.
14506 // Generated for loop is:
14507 // \code
14508 // Original_for_init;
14509 // for (auto .tile.iv = .floor.iv;
14510 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
14511 // ++.tile.iv) {
14512 // Original_Body;
14513 // Original_counter_update;
14514 // }
14515 // \endcode
14516 // FIXME: If the innermost body is an loop itself, inserting these
14517 // statements stops it being recognized as a perfectly nested loop (e.g.
14518 // for applying tiling again). If this is the case, sink the expressions
14519 // further into the inner loop.
14520 SmallVector<Stmt *, 4> BodyParts;
14521 BodyParts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
14522 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
14523 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
14524 BodyParts.push_back(Elt: Inner);
14525 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
14526 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
14527 Inner = new (Context)
14528 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14529 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14530 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14531 }
14532
14533 // Create floor loops from the inside to the outside.
14534 for (int I = NumLoops - 1; I >= 0; --I) {
14535 auto &LoopHelper = LoopHelpers[I];
14536 Expr *NumIterations = LoopHelper.NumIterations;
14537 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
14538 QualType IVTy = NumIterations->getType();
14539
14540 // For init-statement: auto .floor.iv = 0
14541 SemaRef.AddInitializerToDecl(
14542 dcl: FloorIndVars[I],
14543 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
14544 /*DirectInit=*/false);
14545 Decl *CounterDecl = FloorIndVars[I];
14546 StmtResult InitStmt = new (Context)
14547 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
14548 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14549 if (!InitStmt.isUsable())
14550 return StmtError();
14551
14552 // For cond-expression: .floor.iv < NumIterations
14553 ExprResult CondExpr = SemaRef.BuildBinOp(
14554 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
14555 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14556 RHSExpr: NumIterations);
14557 if (!CondExpr.isUsable())
14558 return StmtError();
14559
14560 // For incr-statement: .floor.iv += DimTileSize
14561 Expr *DimTileSize = MakeDimTileSize(I);
14562 if (!DimTileSize)
14563 return StmtError();
14564 ExprResult IncrStmt = SemaRef.BuildBinOp(
14565 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
14566 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14567 RHSExpr: DimTileSize);
14568 if (!IncrStmt.isUsable())
14569 return StmtError();
14570
14571 Inner = new (Context)
14572 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14573 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14574 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14575 }
14576
14577 return OMPTileDirective::Create(C: Context, StartLoc, EndLoc, Clauses, NumLoops,
14578 AssociatedStmt: AStmt, TransformedStmt: Inner,
14579 PreInits: buildPreInits(Context, PreInits));
14580}
14581
14582StmtResult SemaOpenMP::ActOnOpenMPStripeDirective(ArrayRef<OMPClause *> Clauses,
14583 Stmt *AStmt,
14584 SourceLocation StartLoc,
14585 SourceLocation EndLoc) {
14586 ASTContext &Context = getASTContext();
14587 Scope *CurScope = SemaRef.getCurScope();
14588
14589 const auto *SizesClause =
14590 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14591 if (!SizesClause ||
14592 llvm::any_of(Range: SizesClause->getSizesRefs(), P: [](const Expr *SizeExpr) {
14593 return !SizeExpr || SizeExpr->containsErrors();
14594 }))
14595 return StmtError();
14596 unsigned NumLoops = SizesClause->getNumSizes();
14597
14598 // Empty statement should only be possible if there already was an error.
14599 if (!AStmt)
14600 return StmtError();
14601
14602 // Verify and diagnose loop nest.
14603 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14604 Stmt *Body = nullptr;
14605 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14606 if (!checkTransformableLoopNest(Kind: OMPD_stripe, AStmt, NumLoops, LoopHelpers,
14607 Body, OriginalInits))
14608 return StmtError();
14609
14610 // Delay striping to when template is completely instantiated.
14611 if (SemaRef.CurContext->isDependentContext())
14612 return OMPStripeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
14613 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
14614
14615 assert(LoopHelpers.size() == NumLoops &&
14616 "Expecting loop iteration space dimensionality to match number of "
14617 "affected loops");
14618 assert(OriginalInits.size() == NumLoops &&
14619 "Expecting loop iteration space dimensionality to match number of "
14620 "affected loops");
14621
14622 // Collect all affected loop statements.
14623 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14624 collectLoopStmts(AStmt, LoopStmts);
14625
14626 SmallVector<Stmt *, 4> PreInits;
14627 CaptureVars CopyTransformer(SemaRef);
14628
14629 // Create iteration variables for the generated loops.
14630 SmallVector<VarDecl *, 4> FloorIndVars;
14631 SmallVector<VarDecl *, 4> StripeIndVars;
14632 FloorIndVars.resize(N: NumLoops);
14633 StripeIndVars.resize(N: NumLoops);
14634 for (unsigned I : llvm::seq<unsigned>(Size: NumLoops)) {
14635 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14636
14637 assert(LoopHelper.Counters.size() == 1 &&
14638 "Expect single-dimensional loop iteration space");
14639 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
14640 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14641 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
14642 QualType CntTy = IterVarRef->getType();
14643
14644 // Iteration variable for the stripe (i.e. outer) loop.
14645 {
14646 std::string FloorCntName =
14647 (Twine(".floor_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
14648 VarDecl *FloorCntDecl =
14649 buildVarDecl(SemaRef, Loc: {}, Type: CntTy, Name: FloorCntName, Attrs: nullptr, OrigRef: OrigCntVar);
14650 FloorIndVars[I] = FloorCntDecl;
14651 }
14652
14653 // Iteration variable for the stripe (i.e. inner) loop.
14654 {
14655 std::string StripeCntName =
14656 (Twine(".stripe_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
14657
14658 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14659 // used by the expressions to derive the original iteration variable's
14660 // value from the logical iteration number.
14661 auto *StripeCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
14662 StripeCntDecl->setDeclName(
14663 &SemaRef.PP.getIdentifierTable().get(Name: StripeCntName));
14664 StripeIndVars[I] = StripeCntDecl;
14665 }
14666
14667 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
14668 PreInits);
14669 }
14670
14671 // Once the original iteration values are set, append the innermost body.
14672 Stmt *Inner = Body;
14673
14674 auto MakeDimStripeSize = [&](int I) -> Expr * {
14675 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
14676 if (isa<ConstantExpr>(Val: DimStripeSizeExpr))
14677 return AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr));
14678
14679 // When the stripe size is not a constant but a variable, it is possible to
14680 // pass non-positive numbers. For instance:
14681 // \code{c}
14682 // int a = 0;
14683 // #pragma omp stripe sizes(a)
14684 // for (int i = 0; i < 42; ++i)
14685 // body(i);
14686 // \endcode
14687 // Although there is no meaningful interpretation of the stripe size, the
14688 // body should still be executed 42 times to avoid surprises. To preserve
14689 // the invariant that every loop iteration is executed exactly once and not
14690 // cause an infinite loop, apply a minimum stripe size of one.
14691 // Build expr:
14692 // \code{c}
14693 // (TS <= 0) ? 1 : TS
14694 // \endcode
14695 QualType DimTy = DimStripeSizeExpr->getType();
14696 uint64_t DimWidth = Context.getTypeSize(T: DimTy);
14697 IntegerLiteral *Zero = IntegerLiteral::Create(
14698 C: Context, V: llvm::APInt::getZero(numBits: DimWidth), type: DimTy, l: {});
14699 IntegerLiteral *One =
14700 IntegerLiteral::Create(C: Context, V: llvm::APInt(DimWidth, 1), type: DimTy, l: {});
14701 Expr *Cond = AssertSuccess(R: SemaRef.BuildBinOp(
14702 S: CurScope, OpLoc: {}, Opc: BO_LE,
14703 LHSExpr: AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr)), RHSExpr: Zero));
14704 Expr *MinOne = new (Context) ConditionalOperator(
14705 Cond, {}, One, {},
14706 AssertSuccess(R: CopyTransformer.TransformExpr(E: DimStripeSizeExpr)), DimTy,
14707 VK_PRValue, OK_Ordinary);
14708 return MinOne;
14709 };
14710
14711 // Create stripe loops from the inside to the outside.
14712 for (int I = NumLoops - 1; I >= 0; --I) {
14713 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14714 Expr *NumIterations = LoopHelper.NumIterations;
14715 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
14716 QualType IVTy = NumIterations->getType();
14717 Stmt *LoopStmt = LoopStmts[I];
14718
14719 // For init-statement: auto .stripe.iv = .floor.iv
14720 SemaRef.AddInitializerToDecl(
14721 dcl: StripeIndVars[I],
14722 init: SemaRef
14723 .DefaultLvalueConversion(
14724 E: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14725 .get(),
14726 /*DirectInit=*/false);
14727 Decl *CounterDecl = StripeIndVars[I];
14728 StmtResult InitStmt = new (Context)
14729 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
14730 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14731 if (!InitStmt.isUsable())
14732 return StmtError();
14733
14734 // For cond-expression:
14735 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
14736 ExprResult EndOfStripe = SemaRef.BuildBinOp(
14737 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
14738 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14739 RHSExpr: MakeDimStripeSize(I));
14740 if (!EndOfStripe.isUsable())
14741 return StmtError();
14742 ExprResult IsPartialStripe =
14743 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
14744 LHSExpr: NumIterations, RHSExpr: EndOfStripe.get());
14745 if (!IsPartialStripe.isUsable())
14746 return StmtError();
14747 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
14748 QuestionLoc: LoopHelper.Cond->getBeginLoc(), ColonLoc: LoopHelper.Cond->getEndLoc(),
14749 CondExpr: IsPartialStripe.get(), LHSExpr: NumIterations, RHSExpr: EndOfStripe.get());
14750 if (!MinStripeAndIterSpace.isUsable())
14751 return StmtError();
14752 ExprResult CondExpr = SemaRef.BuildBinOp(
14753 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
14754 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars: StripeIndVars, I, IVTy, OrigCntVar),
14755 RHSExpr: MinStripeAndIterSpace.get());
14756 if (!CondExpr.isUsable())
14757 return StmtError();
14758
14759 // For incr-statement: ++.stripe.iv
14760 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14761 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc,
14762 Input: makeFloorIVRef(SemaRef, FloorIndVars: StripeIndVars, I, IVTy, OrigCntVar));
14763 if (!IncrStmt.isUsable())
14764 return StmtError();
14765
14766 // Statements to set the original iteration variable's value from the
14767 // logical iteration number.
14768 // Generated for loop is:
14769 // \code
14770 // Original_for_init;
14771 // for (auto .stripe.iv = .floor.iv;
14772 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
14773 // ++.stripe.iv) {
14774 // Original_Body;
14775 // Original_counter_update;
14776 // }
14777 // \endcode
14778 // FIXME: If the innermost body is a loop itself, inserting these
14779 // statements stops it being recognized as a perfectly nested loop (e.g.
14780 // for applying another loop transformation). If this is the case, sink the
14781 // expressions further into the inner loop.
14782 SmallVector<Stmt *, 4> BodyParts;
14783 BodyParts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
14784 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
14785 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
14786 BodyParts.push_back(Elt: Inner);
14787 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
14788 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
14789 Inner = new (Context)
14790 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14791 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14792 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14793 }
14794
14795 // Create grid loops from the inside to the outside.
14796 for (int I = NumLoops - 1; I >= 0; --I) {
14797 auto &LoopHelper = LoopHelpers[I];
14798 Expr *NumIterations = LoopHelper.NumIterations;
14799 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
14800 QualType IVTy = NumIterations->getType();
14801
14802 // For init-statement: auto .grid.iv = 0
14803 SemaRef.AddInitializerToDecl(
14804 dcl: FloorIndVars[I],
14805 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
14806 /*DirectInit=*/false);
14807 Decl *CounterDecl = FloorIndVars[I];
14808 StmtResult InitStmt = new (Context)
14809 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
14810 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14811 if (!InitStmt.isUsable())
14812 return StmtError();
14813
14814 // For cond-expression: .floor.iv < NumIterations
14815 ExprResult CondExpr = SemaRef.BuildBinOp(
14816 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
14817 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14818 RHSExpr: NumIterations);
14819 if (!CondExpr.isUsable())
14820 return StmtError();
14821
14822 // For incr-statement: .floor.iv += DimStripeSize
14823 ExprResult IncrStmt = SemaRef.BuildBinOp(
14824 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
14825 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14826 RHSExpr: MakeDimStripeSize(I));
14827 if (!IncrStmt.isUsable())
14828 return StmtError();
14829
14830 Inner = new (Context)
14831 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14832 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14833 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14834 }
14835
14836 return OMPStripeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
14837 NumLoops, AssociatedStmt: AStmt, TransformedStmt: Inner,
14838 PreInits: buildPreInits(Context, PreInits));
14839}
14840
14841StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
14842 Stmt *AStmt,
14843 SourceLocation StartLoc,
14844 SourceLocation EndLoc) {
14845 ASTContext &Context = getASTContext();
14846 Scope *CurScope = SemaRef.getCurScope();
14847 // Empty statement should only be possible if there already was an error.
14848 if (!AStmt)
14849 return StmtError();
14850
14851 if (checkMutuallyExclusiveClauses(S&: SemaRef, Clauses,
14852 MutuallyExclusiveClauses: {OMPC_partial, OMPC_full}))
14853 return StmtError();
14854
14855 const OMPFullClause *FullClause =
14856 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14857 const OMPPartialClause *PartialClause =
14858 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14859 assert(!(FullClause && PartialClause) &&
14860 "mutual exclusivity must have been checked before");
14861
14862 constexpr unsigned NumLoops = 1;
14863 Stmt *Body = nullptr;
14864 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
14865 NumLoops);
14866 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14867 if (!checkTransformableLoopNest(Kind: OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14868 Body, OriginalInits))
14869 return StmtError();
14870
14871 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14872
14873 // Delay unrolling to when template is completely instantiated.
14874 if (SemaRef.CurContext->isDependentContext())
14875 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
14876 NumGeneratedLoops, TransformedStmt: nullptr, PreInits: nullptr);
14877
14878 assert(LoopHelpers.size() == NumLoops &&
14879 "Expecting a single-dimensional loop iteration space");
14880 assert(OriginalInits.size() == NumLoops &&
14881 "Expecting a single-dimensional loop iteration space");
14882 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14883
14884 if (FullClause) {
14885 if (!VerifyPositiveIntegerConstantInClause(
14886 Op: LoopHelper.NumIterations, CKind: OMPC_full, /*StrictlyPositive=*/false,
14887 /*SuppressExprDiags=*/true)
14888 .isUsable()) {
14889 Diag(Loc: AStmt->getBeginLoc(), DiagID: diag::err_omp_unroll_full_variable_trip_count);
14890 Diag(Loc: FullClause->getBeginLoc(), DiagID: diag::note_omp_directive_here)
14891 << "#pragma omp unroll full";
14892 return StmtError();
14893 }
14894 }
14895
14896 // The generated loop may only be passed to other loop-associated directive
14897 // when a partial clause is specified. Without the requirement it is
14898 // sufficient to generate loop unroll metadata at code-generation.
14899 if (NumGeneratedLoops == 0)
14900 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
14901 NumGeneratedLoops, TransformedStmt: nullptr, PreInits: nullptr);
14902
14903 // Otherwise, we need to provide a de-sugared/transformed AST that can be
14904 // associated with another loop directive.
14905 //
14906 // The canonical loop analysis return by checkTransformableLoopNest assumes
14907 // the following structure to be the same loop without transformations or
14908 // directives applied: \code OriginalInits; LoopHelper.PreInits;
14909 // LoopHelper.Counters;
14910 // for (; IV < LoopHelper.NumIterations; ++IV) {
14911 // LoopHelper.Updates;
14912 // Body;
14913 // }
14914 // \endcode
14915 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
14916 // and referenced by LoopHelper.IterationVarRef.
14917 //
14918 // The unrolling directive transforms this into the following loop:
14919 // \code
14920 // OriginalInits; \
14921 // LoopHelper.PreInits; > NewPreInits
14922 // LoopHelper.Counters; /
14923 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
14924 // #pragma clang loop unroll_count(Factor)
14925 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
14926 // {
14927 // LoopHelper.Updates;
14928 // Body;
14929 // }
14930 // }
14931 // \endcode
14932 // where UIV is a new logical iteration counter. IV must be the same VarDecl
14933 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
14934 // references it. If the partially unrolled loop is associated with another
14935 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
14936 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
14937 // OpenMP canonical loop. The inner loop is not an associable canonical loop
14938 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
14939 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
14940 // property of the OMPLoopBasedDirective instead of statements in
14941 // CompoundStatement. This is to allow the loop to become a non-outermost loop
14942 // of a canonical loop nest where these PreInits are emitted before the
14943 // outermost directive.
14944
14945 // Find the loop statement.
14946 Stmt *LoopStmt = nullptr;
14947 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
14948
14949 // Determine the PreInit declarations.
14950 SmallVector<Stmt *, 4> PreInits;
14951 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
14952
14953 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
14954 QualType IVTy = IterationVarRef->getType();
14955 assert(LoopHelper.Counters.size() == 1 &&
14956 "Expecting a single-dimensional loop iteration space");
14957 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
14958
14959 // Determine the unroll factor.
14960 uint64_t Factor;
14961 SourceLocation FactorLoc;
14962 if (Expr *FactorVal = PartialClause->getFactor();
14963 FactorVal && !FactorVal->containsErrors()) {
14964 Factor = FactorVal->getIntegerConstantExpr(Ctx: Context)->getZExtValue();
14965 FactorLoc = FactorVal->getExprLoc();
14966 } else {
14967 // TODO: Use a better profitability model.
14968 Factor = 2;
14969 }
14970 assert(Factor > 0 && "Expected positive unroll factor");
14971 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
14972 return IntegerLiteral::Create(
14973 C: getASTContext(), V: llvm::APInt(getASTContext().getIntWidth(T: IVTy), Factor),
14974 type: IVTy, l: FactorLoc);
14975 };
14976
14977 // Iteration variable SourceLocations.
14978 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14979 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14980 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14981
14982 // Internal variable names.
14983 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14984 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
14985 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
14986
14987 // Create the iteration variable for the unrolled loop.
14988 VarDecl *OuterIVDecl =
14989 buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: OuterIVName, Attrs: nullptr, OrigRef: OrigVar);
14990 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
14991 return buildDeclRefExpr(S&: SemaRef, D: OuterIVDecl, Ty: IVTy, Loc: OrigVarLoc);
14992 };
14993
14994 // Iteration variable for the inner loop: Reuse the iteration variable created
14995 // by checkOpenMPLoop.
14996 auto *InnerIVDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
14997 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name: InnerIVName));
14998 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
14999 return buildDeclRefExpr(S&: SemaRef, D: InnerIVDecl, Ty: IVTy, Loc: OrigVarLoc);
15000 };
15001
15002 // Make a copy of the NumIterations expression for each use: By the AST
15003 // constraints, every expression object in a DeclContext must be unique.
15004 CaptureVars CopyTransformer(SemaRef);
15005 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15006 return AssertSuccess(
15007 R: CopyTransformer.TransformExpr(E: LoopHelper.NumIterations));
15008 };
15009
15010 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15011 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(E: MakeOuterRef());
15012 SemaRef.AddInitializerToDecl(dcl: InnerIVDecl, init: LValueConv.get(),
15013 /*DirectInit=*/false);
15014 StmtResult InnerInit = new (Context)
15015 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15016 if (!InnerInit.isUsable())
15017 return StmtError();
15018
15019 // Inner For cond-expression:
15020 // \code
15021 // .unroll_inner.iv < .unrolled.iv + Factor &&
15022 // .unroll_inner.iv < NumIterations
15023 // \endcode
15024 // This conjunction of two conditions allows ScalarEvolution to derive the
15025 // maximum trip count of the inner loop.
15026 ExprResult EndOfTile =
15027 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
15028 LHSExpr: MakeOuterRef(), RHSExpr: MakeFactorExpr());
15029 if (!EndOfTile.isUsable())
15030 return StmtError();
15031 ExprResult InnerCond1 =
15032 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15033 LHSExpr: MakeInnerRef(), RHSExpr: EndOfTile.get());
15034 if (!InnerCond1.isUsable())
15035 return StmtError();
15036 ExprResult InnerCond2 =
15037 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15038 LHSExpr: MakeInnerRef(), RHSExpr: MakeNumIterations());
15039 if (!InnerCond2.isUsable())
15040 return StmtError();
15041 ExprResult InnerCond =
15042 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LAnd,
15043 LHSExpr: InnerCond1.get(), RHSExpr: InnerCond2.get());
15044 if (!InnerCond.isUsable())
15045 return StmtError();
15046
15047 // Inner For incr-statement: ++.unroll_inner.iv
15048 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15049 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeInnerRef());
15050 if (!InnerIncr.isUsable())
15051 return StmtError();
15052
15053 // Inner For statement.
15054 SmallVector<Stmt *> InnerBodyStmts;
15055 InnerBodyStmts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
15056 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
15057 InnerBodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
15058 InnerBodyStmts.push_back(Elt: Body);
15059 CompoundStmt *InnerBody =
15060 CompoundStmt::Create(C: getASTContext(), Stmts: InnerBodyStmts, FPFeatures: FPOptionsOverride(),
15061 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
15062 ForStmt *InnerFor = new (Context)
15063 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15064 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15065 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15066
15067 // Unroll metadata for the inner loop.
15068 // This needs to take into account the remainder portion of the unrolled loop,
15069 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15070 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15071 // the maximum trip count, which will also generate a remainder loop. Just
15072 // `unroll(enable)` (which could have been useful if the user has not
15073 // specified a concrete factor; even though the outer loop cannot be
15074 // influenced anymore, would avoid more code bloat than necessary) will refuse
15075 // the loop because "Won't unroll; remainder loop could not be generated when
15076 // assuming runtime trip count". Even if it did work, it must not choose a
15077 // larger unroll factor than the maximum loop length, or it would always just
15078 // execute the remainder loop.
15079 LoopHintAttr *UnrollHintAttr =
15080 LoopHintAttr::CreateImplicit(Ctx&: Context, Option: LoopHintAttr::UnrollCount,
15081 State: LoopHintAttr::Numeric, Value: MakeFactorExpr());
15082 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15083 C: getASTContext(), Loc: StartLoc, Attrs: {UnrollHintAttr}, SubStmt: InnerFor);
15084
15085 // Outer For init-statement: auto .unrolled.iv = 0
15086 SemaRef.AddInitializerToDecl(
15087 dcl: OuterIVDecl,
15088 init: SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
15089 /*DirectInit=*/false);
15090 StmtResult OuterInit = new (Context)
15091 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15092 if (!OuterInit.isUsable())
15093 return StmtError();
15094
15095 // Outer For cond-expression: .unrolled.iv < NumIterations
15096 ExprResult OuterConde =
15097 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15098 LHSExpr: MakeOuterRef(), RHSExpr: MakeNumIterations());
15099 if (!OuterConde.isUsable())
15100 return StmtError();
15101
15102 // Outer For incr-statement: .unrolled.iv += Factor
15103 ExprResult OuterIncr =
15104 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
15105 LHSExpr: MakeOuterRef(), RHSExpr: MakeFactorExpr());
15106 if (!OuterIncr.isUsable())
15107 return StmtError();
15108
15109 // Outer For statement.
15110 ForStmt *OuterFor = new (Context)
15111 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15112 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15113 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15114
15115 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
15116 NumGeneratedLoops, TransformedStmt: OuterFor,
15117 PreInits: buildPreInits(Context, PreInits));
15118}
15119
15120StmtResult SemaOpenMP::ActOnOpenMPReverseDirective(Stmt *AStmt,
15121 SourceLocation StartLoc,
15122 SourceLocation EndLoc) {
15123 ASTContext &Context = getASTContext();
15124 Scope *CurScope = SemaRef.getCurScope();
15125
15126 // Empty statement should only be possible if there already was an error.
15127 if (!AStmt)
15128 return StmtError();
15129
15130 constexpr unsigned NumLoops = 1;
15131 Stmt *Body = nullptr;
15132 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
15133 NumLoops);
15134 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
15135 if (!checkTransformableLoopNest(Kind: OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15136 Body, OriginalInits))
15137 return StmtError();
15138
15139 // Delay applying the transformation to when template is completely
15140 // instantiated.
15141 if (SemaRef.CurContext->isDependentContext())
15142 return OMPReverseDirective::Create(C: Context, StartLoc, EndLoc, AssociatedStmt: AStmt,
15143 NumLoops, TransformedStmt: nullptr, PreInits: nullptr);
15144
15145 assert(LoopHelpers.size() == NumLoops &&
15146 "Expecting a single-dimensional loop iteration space");
15147 assert(OriginalInits.size() == NumLoops &&
15148 "Expecting a single-dimensional loop iteration space");
15149 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15150
15151 // Find the loop statement.
15152 Stmt *LoopStmt = nullptr;
15153 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
15154
15155 // Determine the PreInit declarations.
15156 SmallVector<Stmt *> PreInits;
15157 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
15158
15159 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15160 QualType IVTy = IterationVarRef->getType();
15161 uint64_t IVWidth = Context.getTypeSize(T: IVTy);
15162 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15163
15164 // Iteration variable SourceLocations.
15165 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15166 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15167 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15168
15169 // Locations pointing to the transformation.
15170 SourceLocation TransformLoc = StartLoc;
15171 SourceLocation TransformLocBegin = StartLoc;
15172 SourceLocation TransformLocEnd = EndLoc;
15173
15174 // Internal variable names.
15175 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15176 SmallString<64> ForwardIVName(".forward.iv.");
15177 ForwardIVName += OrigVarName;
15178 SmallString<64> ReversedIVName(".reversed.iv.");
15179 ReversedIVName += OrigVarName;
15180
15181 // LoopHelper.Updates will read the logical iteration number from
15182 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
15183 // that logical iteration from it, then assign it to the user loop counter
15184 // variable. We cannot directly use LoopHelper.IterationVarRef as the
15185 // induction variable of the generated loop because it may cause an underflow:
15186 // \code{.c}
15187 // for (unsigned i = 0; i < n; ++i)
15188 // body(i);
15189 // \endcode
15190 //
15191 // Naive reversal:
15192 // \code{.c}
15193 // for (unsigned i = n-1; i >= 0; --i)
15194 // body(i);
15195 // \endcode
15196 //
15197 // Instead, we introduce a new iteration variable representing the logical
15198 // iteration counter of the original loop, convert it to the logical iteration
15199 // number of the reversed loop, then let LoopHelper.Updates compute the user's
15200 // loop iteration variable from it.
15201 // \code{.cpp}
15202 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
15203 // auto .reversed.iv = n - .forward.iv - 1;
15204 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
15205 // body(i); // Body
15206 // }
15207 // \endcode
15208
15209 // Subexpressions with more than one use. One of the constraints of an AST is
15210 // that every node object must appear at most once, hence we define a lambda
15211 // that creates a new AST node at every use.
15212 CaptureVars CopyTransformer(SemaRef);
15213 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15214 return AssertSuccess(
15215 R: CopyTransformer.TransformExpr(E: LoopHelper.NumIterations));
15216 };
15217
15218 // Create the iteration variable for the forward loop (from 0 to n-1).
15219 VarDecl *ForwardIVDecl =
15220 buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: ForwardIVName, Attrs: nullptr, OrigRef: OrigVar);
15221 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15222 OrigVarLoc]() {
15223 return buildDeclRefExpr(S&: SemaRef, D: ForwardIVDecl, Ty: IVTy, Loc: OrigVarLoc);
15224 };
15225
15226 // Iteration variable for the reversed induction variable (from n-1 downto 0):
15227 // Reuse the iteration variable created by checkOpenMPLoop.
15228 auto *ReversedIVDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
15229 ReversedIVDecl->setDeclName(
15230 &SemaRef.PP.getIdentifierTable().get(Name: ReversedIVName));
15231
15232 // For init-statement:
15233 // \code{.cpp}
15234 // auto .forward.iv = 0;
15235 // \endcode
15236 auto *Zero = IntegerLiteral::Create(C: Context, V: llvm::APInt::getZero(numBits: IVWidth),
15237 type: ForwardIVDecl->getType(), l: OrigVarLoc);
15238 SemaRef.AddInitializerToDecl(dcl: ForwardIVDecl, init: Zero, /*DirectInit=*/false);
15239 StmtResult Init = new (Context)
15240 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15241 if (!Init.isUsable())
15242 return StmtError();
15243
15244 // Forward iv cond-expression:
15245 // \code{.cpp}
15246 // .forward.iv < MakeNumIterations()
15247 // \endcode
15248 ExprResult Cond =
15249 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15250 LHSExpr: MakeForwardRef(), RHSExpr: MakeNumIterations());
15251 if (!Cond.isUsable())
15252 return StmtError();
15253
15254 // Forward incr-statement:
15255 // \code{.c}
15256 // ++.forward.iv
15257 // \endcode
15258 ExprResult Incr = SemaRef.BuildUnaryOp(S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(),
15259 Opc: UO_PreInc, Input: MakeForwardRef());
15260 if (!Incr.isUsable())
15261 return StmtError();
15262
15263 // Reverse the forward-iv:
15264 // \code{.cpp}
15265 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
15266 // \endcode
15267 auto *One = IntegerLiteral::Create(C: Context, V: llvm::APInt(IVWidth, 1), type: IVTy,
15268 l: TransformLoc);
15269 ExprResult Minus = SemaRef.BuildBinOp(S: CurScope, OpLoc: TransformLoc, Opc: BO_Sub,
15270 LHSExpr: MakeNumIterations(), RHSExpr: One);
15271 if (!Minus.isUsable())
15272 return StmtError();
15273 Minus = SemaRef.BuildBinOp(S: CurScope, OpLoc: TransformLoc, Opc: BO_Sub, LHSExpr: Minus.get(),
15274 RHSExpr: MakeForwardRef());
15275 if (!Minus.isUsable())
15276 return StmtError();
15277 StmtResult InitReversed = new (Context) DeclStmt(
15278 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15279 if (!InitReversed.isUsable())
15280 return StmtError();
15281 SemaRef.AddInitializerToDecl(dcl: ReversedIVDecl, init: Minus.get(),
15282 /*DirectInit=*/false);
15283
15284 // The new loop body.
15285 SmallVector<Stmt *, 4> BodyStmts;
15286 BodyStmts.reserve(N: LoopHelper.Updates.size() + 2 +
15287 (isa<CXXForRangeStmt>(Val: LoopStmt) ? 1 : 0));
15288 BodyStmts.push_back(Elt: InitReversed.get());
15289 llvm::append_range(C&: BodyStmts, R&: LoopHelper.Updates);
15290 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
15291 BodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
15292 BodyStmts.push_back(Elt: Body);
15293 auto *ReversedBody =
15294 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
15295 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
15296
15297 // Finally create the reversed For-statement.
15298 auto *ReversedFor = new (Context)
15299 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
15300 ReversedBody, LoopHelper.Init->getBeginLoc(),
15301 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15302 return OMPReverseDirective::Create(C: Context, StartLoc, EndLoc, AssociatedStmt: AStmt, NumLoops,
15303 TransformedStmt: ReversedFor,
15304 PreInits: buildPreInits(Context, PreInits));
15305}
15306
15307StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
15308 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15309 SourceLocation EndLoc) {
15310 ASTContext &Context = getASTContext();
15311 DeclContext *CurContext = SemaRef.CurContext;
15312 Scope *CurScope = SemaRef.getCurScope();
15313
15314 // Empty statement should only be possible if there already was an error.
15315 if (!AStmt)
15316 return StmtError();
15317
15318 // interchange without permutation clause swaps two loops.
15319 const OMPPermutationClause *PermutationClause =
15320 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15321 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
15322
15323 // Verify and diagnose loop nest.
15324 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
15325 Stmt *Body = nullptr;
15326 SmallVector<SmallVector<Stmt *, 0>, 2> OriginalInits;
15327 if (!checkTransformableLoopNest(Kind: OMPD_interchange, AStmt, NumLoops,
15328 LoopHelpers, Body, OriginalInits))
15329 return StmtError();
15330
15331 // Delay interchange to when template is completely instantiated.
15332 if (CurContext->isDependentContext())
15333 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15334 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
15335
15336 // An invalid expression in the permutation clause is set to nullptr in
15337 // ActOnOpenMPPermutationClause.
15338 if (PermutationClause &&
15339 llvm::is_contained(Range: PermutationClause->getArgsRefs(), Element: nullptr))
15340 return StmtError();
15341
15342 assert(LoopHelpers.size() == NumLoops &&
15343 "Expecting loop iteration space dimensionaly to match number of "
15344 "affected loops");
15345 assert(OriginalInits.size() == NumLoops &&
15346 "Expecting loop iteration space dimensionaly to match number of "
15347 "affected loops");
15348
15349 // Decode the permutation clause.
15350 SmallVector<uint64_t, 2> Permutation;
15351 if (!PermutationClause) {
15352 Permutation = {1, 0};
15353 } else {
15354 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
15355 llvm::BitVector Flags(PermArgs.size());
15356 for (Expr *PermArg : PermArgs) {
15357 std::optional<llvm::APSInt> PermCstExpr =
15358 PermArg->getIntegerConstantExpr(Ctx: Context);
15359 if (!PermCstExpr)
15360 continue;
15361 uint64_t PermInt = PermCstExpr->getZExtValue();
15362 assert(1 <= PermInt && PermInt <= NumLoops &&
15363 "Must be a permutation; diagnostic emitted in "
15364 "ActOnOpenMPPermutationClause");
15365 if (Flags[PermInt - 1]) {
15366 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15367 Diag(Loc: PermArg->getExprLoc(),
15368 DiagID: diag::err_omp_interchange_permutation_value_repeated)
15369 << PermInt << ExprRange;
15370 continue;
15371 }
15372 Flags[PermInt - 1] = true;
15373
15374 Permutation.push_back(Elt: PermInt - 1);
15375 }
15376
15377 if (Permutation.size() != NumLoops)
15378 return StmtError();
15379 }
15380
15381 // Nothing to transform with trivial permutation.
15382 if (NumLoops <= 1 || llvm::all_of(Range: llvm::enumerate(First&: Permutation), P: [](auto P) {
15383 auto [Idx, Arg] = P;
15384 return Idx == Arg;
15385 }))
15386 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15387 NumLoops, AssociatedStmt: AStmt, TransformedStmt: AStmt, PreInits: nullptr);
15388
15389 // Find the affected loops.
15390 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15391 collectLoopStmts(AStmt, LoopStmts);
15392
15393 // Collect pre-init statements on the order before the permuation.
15394 SmallVector<Stmt *> PreInits;
15395 for (auto I : llvm::seq<int>(Size: NumLoops)) {
15396 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15397
15398 assert(LoopHelper.Counters.size() == 1 &&
15399 "Single-dimensional loop iteration space expected");
15400
15401 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
15402 PreInits);
15403 }
15404
15405 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
15406 CaptureVars CopyTransformer(SemaRef);
15407
15408 // Create the permuted loops from the inside to the outside of the
15409 // interchanged loop nest. Body of the innermost new loop is the original
15410 // innermost body.
15411 Stmt *Inner = Body;
15412 for (auto TargetIdx : llvm::reverse(C: llvm::seq<int>(Size: NumLoops))) {
15413 // Get the original loop that belongs to this new position.
15414 uint64_t SourceIdx = Permutation[TargetIdx];
15415 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15416 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15417 assert(SourceHelper.Counters.size() == 1 &&
15418 "Single-dimensional loop iteration space expected");
15419 auto *OrigCntVar = cast<DeclRefExpr>(Val: SourceHelper.Counters.front());
15420
15421 // Normalized loop counter variable: From 0 to n-1, always an integer type.
15422 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: SourceHelper.IterationVarRef);
15423 QualType IVTy = IterVarRef->getType();
15424 assert(IVTy->isIntegerType() &&
15425 "Expected the logical iteration counter to be an integer");
15426
15427 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15428 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
15429
15430 // Make a copy of the NumIterations expression for each use: By the AST
15431 // constraints, every expression object in a DeclContext must be unique.
15432 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
15433 return AssertSuccess(
15434 R: CopyTransformer.TransformExpr(E: SourceHelper.NumIterations));
15435 };
15436
15437 // Iteration variable for the permuted loop. Reuse the one from
15438 // checkOpenMPLoop which will also be used to update the original loop
15439 // variable.
15440 SmallString<64> PermutedCntName(".permuted_");
15441 PermutedCntName.append(Refs: {llvm::utostr(X: TargetIdx), ".iv.", OrigVarName});
15442 auto *PermutedCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
15443 PermutedCntDecl->setDeclName(
15444 &SemaRef.PP.getIdentifierTable().get(Name: PermutedCntName));
15445 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15446 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15447 return buildDeclRefExpr(S&: SemaRef, D: PermutedCntDecl, Ty: IVTy, Loc: OrigVarLoc);
15448 };
15449
15450 // For init-statement:
15451 // \code
15452 // auto .permuted_{target}.iv = 0
15453 // \endcode
15454 ExprResult Zero = SemaRef.ActOnIntegerConstant(Loc: OrigVarLoc, Val: 0);
15455 if (!Zero.isUsable())
15456 return StmtError();
15457 SemaRef.AddInitializerToDecl(dcl: PermutedCntDecl, init: Zero.get(),
15458 /*DirectInit=*/false);
15459 StmtResult InitStmt = new (Context)
15460 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
15461 OrigCntVar->getEndLoc());
15462 if (!InitStmt.isUsable())
15463 return StmtError();
15464
15465 // For cond-expression:
15466 // \code
15467 // .permuted_{target}.iv < MakeNumIterations()
15468 // \endcode
15469 ExprResult CondExpr =
15470 SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceHelper.Cond->getExprLoc(), Opc: BO_LT,
15471 LHSExpr: MakePermutedRef(), RHSExpr: MakeNumIterations());
15472 if (!CondExpr.isUsable())
15473 return StmtError();
15474
15475 // For incr-statement:
15476 // \code
15477 // ++.tile.iv
15478 // \endcode
15479 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15480 S: CurScope, OpLoc: SourceHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakePermutedRef());
15481 if (!IncrStmt.isUsable())
15482 return StmtError();
15483
15484 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
15485 SourceHelper.Updates.end());
15486 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: SourceLoopStmt))
15487 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
15488 BodyParts.push_back(Elt: Inner);
15489 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
15490 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
15491 Inner = new (Context) ForStmt(
15492 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
15493 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
15494 SourceHelper.Inc->getEndLoc());
15495 }
15496
15497 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15498 NumLoops, AssociatedStmt: AStmt, TransformedStmt: Inner,
15499 PreInits: buildPreInits(Context, PreInits));
15500}
15501
15502OMPClause *SemaOpenMP::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
15503 Expr *Expr,
15504 SourceLocation StartLoc,
15505 SourceLocation LParenLoc,
15506 SourceLocation EndLoc) {
15507 OMPClause *Res = nullptr;
15508 switch (Kind) {
15509 case OMPC_final:
15510 Res = ActOnOpenMPFinalClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
15511 break;
15512 case OMPC_safelen:
15513 Res = ActOnOpenMPSafelenClause(Length: Expr, StartLoc, LParenLoc, EndLoc);
15514 break;
15515 case OMPC_simdlen:
15516 Res = ActOnOpenMPSimdlenClause(Length: Expr, StartLoc, LParenLoc, EndLoc);
15517 break;
15518 case OMPC_allocator:
15519 Res = ActOnOpenMPAllocatorClause(Allocator: Expr, StartLoc, LParenLoc, EndLoc);
15520 break;
15521 case OMPC_collapse:
15522 Res = ActOnOpenMPCollapseClause(NumForLoops: Expr, StartLoc, LParenLoc, EndLoc);
15523 break;
15524 case OMPC_ordered:
15525 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, NumForLoops: Expr);
15526 break;
15527 case OMPC_priority:
15528 Res = ActOnOpenMPPriorityClause(Priority: Expr, StartLoc, LParenLoc, EndLoc);
15529 break;
15530 case OMPC_hint:
15531 Res = ActOnOpenMPHintClause(Hint: Expr, StartLoc, LParenLoc, EndLoc);
15532 break;
15533 case OMPC_depobj:
15534 Res = ActOnOpenMPDepobjClause(Depobj: Expr, StartLoc, LParenLoc, EndLoc);
15535 break;
15536 case OMPC_detach:
15537 Res = ActOnOpenMPDetachClause(Evt: Expr, StartLoc, LParenLoc, EndLoc);
15538 break;
15539 case OMPC_novariants:
15540 Res = ActOnOpenMPNovariantsClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
15541 break;
15542 case OMPC_nocontext:
15543 Res = ActOnOpenMPNocontextClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
15544 break;
15545 case OMPC_filter:
15546 Res = ActOnOpenMPFilterClause(ThreadID: Expr, StartLoc, LParenLoc, EndLoc);
15547 break;
15548 case OMPC_partial:
15549 Res = ActOnOpenMPPartialClause(FactorExpr: Expr, StartLoc, LParenLoc, EndLoc);
15550 break;
15551 case OMPC_message:
15552 Res = ActOnOpenMPMessageClause(MS: Expr, StartLoc, LParenLoc, EndLoc);
15553 break;
15554 case OMPC_align:
15555 Res = ActOnOpenMPAlignClause(Alignment: Expr, StartLoc, LParenLoc, EndLoc);
15556 break;
15557 case OMPC_ompx_dyn_cgroup_mem:
15558 Res = ActOnOpenMPXDynCGroupMemClause(Size: Expr, StartLoc, LParenLoc, EndLoc);
15559 break;
15560 case OMPC_holds:
15561 Res = ActOnOpenMPHoldsClause(E: Expr, StartLoc, LParenLoc, EndLoc);
15562 break;
15563 case OMPC_grainsize:
15564 case OMPC_num_tasks:
15565 case OMPC_num_threads:
15566 case OMPC_device:
15567 case OMPC_if:
15568 case OMPC_default:
15569 case OMPC_proc_bind:
15570 case OMPC_schedule:
15571 case OMPC_private:
15572 case OMPC_firstprivate:
15573 case OMPC_lastprivate:
15574 case OMPC_shared:
15575 case OMPC_reduction:
15576 case OMPC_task_reduction:
15577 case OMPC_in_reduction:
15578 case OMPC_linear:
15579 case OMPC_aligned:
15580 case OMPC_copyin:
15581 case OMPC_copyprivate:
15582 case OMPC_nowait:
15583 case OMPC_untied:
15584 case OMPC_mergeable:
15585 case OMPC_threadprivate:
15586 case OMPC_sizes:
15587 case OMPC_allocate:
15588 case OMPC_flush:
15589 case OMPC_read:
15590 case OMPC_write:
15591 case OMPC_update:
15592 case OMPC_capture:
15593 case OMPC_compare:
15594 case OMPC_seq_cst:
15595 case OMPC_acq_rel:
15596 case OMPC_acquire:
15597 case OMPC_release:
15598 case OMPC_relaxed:
15599 case OMPC_depend:
15600 case OMPC_threads:
15601 case OMPC_simd:
15602 case OMPC_map:
15603 case OMPC_nogroup:
15604 case OMPC_dist_schedule:
15605 case OMPC_defaultmap:
15606 case OMPC_unknown:
15607 case OMPC_uniform:
15608 case OMPC_to:
15609 case OMPC_from:
15610 case OMPC_use_device_ptr:
15611 case OMPC_use_device_addr:
15612 case OMPC_is_device_ptr:
15613 case OMPC_unified_address:
15614 case OMPC_unified_shared_memory:
15615 case OMPC_reverse_offload:
15616 case OMPC_dynamic_allocators:
15617 case OMPC_atomic_default_mem_order:
15618 case OMPC_self_maps:
15619 case OMPC_device_type:
15620 case OMPC_match:
15621 case OMPC_nontemporal:
15622 case OMPC_order:
15623 case OMPC_at:
15624 case OMPC_severity:
15625 case OMPC_destroy:
15626 case OMPC_inclusive:
15627 case OMPC_exclusive:
15628 case OMPC_uses_allocators:
15629 case OMPC_affinity:
15630 case OMPC_when:
15631 case OMPC_bind:
15632 case OMPC_num_teams:
15633 case OMPC_thread_limit:
15634 default:
15635 llvm_unreachable("Clause is not allowed.");
15636 }
15637 return Res;
15638}
15639
15640// An OpenMP directive such as 'target parallel' has two captured regions:
15641// for the 'target' and 'parallel' respectively. This function returns
15642// the region in which to capture expressions associated with a clause.
15643// A return value of OMPD_unknown signifies that the expression should not
15644// be captured.
15645static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
15646 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15647 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15648 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15649 "Invalid directive with CKind-clause");
15650
15651 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
15652 if (NameModifier != OMPD_unknown &&
15653 !isAllowedClauseForDirective(D: NameModifier, C: CKind, Version: OpenMPVersion))
15654 return OMPD_unknown;
15655
15656 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(D: DKind);
15657
15658 // [5.2:341:24-30]
15659 // If the clauses have expressions on them, such as for various clauses where
15660 // the argument of the clause is an expression, or lower-bound, length, or
15661 // stride expressions inside array sections (or subscript and stride
15662 // expressions in subscript-triplet for Fortran), or linear-step or alignment
15663 // expressions, the expressions are evaluated immediately before the construct
15664 // to which the clause has been split or duplicated per the above rules
15665 // (therefore inside of the outer leaf constructs). However, the expressions
15666 // inside the num_teams and thread_limit clauses are always evaluated before
15667 // the outermost leaf construct.
15668
15669 // Process special cases first.
15670 switch (CKind) {
15671 case OMPC_if:
15672 switch (DKind) {
15673 case OMPD_teams_loop:
15674 case OMPD_target_teams_loop:
15675 // For [target] teams loop, assume capture region is 'teams' so it's
15676 // available for codegen later to use if/when necessary.
15677 return OMPD_teams;
15678 case OMPD_target_update:
15679 case OMPD_target_enter_data:
15680 case OMPD_target_exit_data:
15681 return OMPD_task;
15682 default:
15683 break;
15684 }
15685 break;
15686 case OMPC_num_teams:
15687 case OMPC_thread_limit:
15688 case OMPC_ompx_dyn_cgroup_mem:
15689 if (Leafs[0] == OMPD_target)
15690 return OMPD_target;
15691 break;
15692 case OMPC_device:
15693 if (Leafs[0] == OMPD_target ||
15694 llvm::is_contained(Set: {OMPD_dispatch, OMPD_target_update,
15695 OMPD_target_enter_data, OMPD_target_exit_data},
15696 Element: DKind))
15697 return OMPD_task;
15698 break;
15699 case OMPC_novariants:
15700 case OMPC_nocontext:
15701 if (DKind == OMPD_dispatch)
15702 return OMPD_task;
15703 break;
15704 case OMPC_when:
15705 if (DKind == OMPD_metadirective)
15706 return OMPD_metadirective;
15707 break;
15708 case OMPC_filter:
15709 return OMPD_unknown;
15710 default:
15711 break;
15712 }
15713
15714 // If none of the special cases above applied, and DKind is a capturing
15715 // directive, find the innermost enclosing leaf construct that allows the
15716 // clause, and returns the corresponding capture region.
15717
15718 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
15719 // Find the index in "Leafs" of the last leaf that allows the given
15720 // clause. The search will only include indexes [0, EndIdx).
15721 // EndIdx may be set to the index of the NameModifier, if present.
15722 int InnermostIdx = [&]() {
15723 for (int I = EndIdx - 1; I >= 0; --I) {
15724 if (isAllowedClauseForDirective(D: Leafs[I], C: Clause, Version: OpenMPVersion))
15725 return I;
15726 }
15727 return -1;
15728 }();
15729
15730 // Find the nearest enclosing capture region.
15731 SmallVector<OpenMPDirectiveKind, 2> Regions;
15732 for (int I = InnermostIdx - 1; I >= 0; --I) {
15733 if (!isOpenMPCapturingDirective(DKind: Leafs[I]))
15734 continue;
15735 Regions.clear();
15736 getOpenMPCaptureRegions(CaptureRegions&: Regions, DKind: Leafs[I]);
15737 if (Regions[0] != OMPD_unknown)
15738 return Regions.back();
15739 }
15740 return OMPD_unknown;
15741 };
15742
15743 if (isOpenMPCapturingDirective(DKind)) {
15744 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
15745 for (int I = 0, E = Leafs.size(); I != E; ++I) {
15746 if (Leafs[I] == Dir)
15747 return I + 1;
15748 }
15749 return 0;
15750 };
15751
15752 int End = NameModifier == OMPD_unknown ? Leafs.size()
15753 : GetLeafIndex(NameModifier);
15754 return GetEnclosingRegion(End, CKind);
15755 }
15756
15757 return OMPD_unknown;
15758}
15759
15760OMPClause *SemaOpenMP::ActOnOpenMPIfClause(
15761 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
15762 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
15763 SourceLocation ColonLoc, SourceLocation EndLoc) {
15764 Expr *ValExpr = Condition;
15765 Stmt *HelperValStmt = nullptr;
15766 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15767 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15768 !Condition->isInstantiationDependent() &&
15769 !Condition->containsUnexpandedParameterPack()) {
15770 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
15771 if (Val.isInvalid())
15772 return nullptr;
15773
15774 ValExpr = Val.get();
15775
15776 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15777 CaptureRegion = getOpenMPCaptureRegionForClause(
15778 DKind, CKind: OMPC_if, OpenMPVersion: getLangOpts().OpenMP, NameModifier);
15779 if (CaptureRegion != OMPD_unknown &&
15780 !SemaRef.CurContext->isDependentContext()) {
15781 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
15782 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15783 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
15784 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
15785 }
15786 }
15787
15788 return new (getASTContext())
15789 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15790 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15791}
15792
15793OMPClause *SemaOpenMP::ActOnOpenMPFinalClause(Expr *Condition,
15794 SourceLocation StartLoc,
15795 SourceLocation LParenLoc,
15796 SourceLocation EndLoc) {
15797 Expr *ValExpr = Condition;
15798 Stmt *HelperValStmt = nullptr;
15799 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15800 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15801 !Condition->isInstantiationDependent() &&
15802 !Condition->containsUnexpandedParameterPack()) {
15803 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
15804 if (Val.isInvalid())
15805 return nullptr;
15806
15807 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
15808
15809 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15810 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_final,
15811 OpenMPVersion: getLangOpts().OpenMP);
15812 if (CaptureRegion != OMPD_unknown &&
15813 !SemaRef.CurContext->isDependentContext()) {
15814 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
15815 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15816 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
15817 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
15818 }
15819 }
15820
15821 return new (getASTContext()) OMPFinalClause(
15822 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15823}
15824
15825ExprResult
15826SemaOpenMP::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
15827 Expr *Op) {
15828 if (!Op)
15829 return ExprError();
15830
15831 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
15832 public:
15833 IntConvertDiagnoser()
15834 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
15835 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
15836 QualType T) override {
15837 return S.Diag(Loc, DiagID: diag::err_omp_not_integral) << T;
15838 }
15839 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
15840 QualType T) override {
15841 return S.Diag(Loc, DiagID: diag::err_omp_incomplete_type) << T;
15842 }
15843 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
15844 QualType T,
15845 QualType ConvTy) override {
15846 return S.Diag(Loc, DiagID: diag::err_omp_explicit_conversion) << T << ConvTy;
15847 }
15848 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
15849 QualType ConvTy) override {
15850 return S.Diag(Loc: Conv->getLocation(), DiagID: diag::note_omp_conversion_here)
15851 << ConvTy->isEnumeralType() << ConvTy;
15852 }
15853 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
15854 QualType T) override {
15855 return S.Diag(Loc, DiagID: diag::err_omp_ambiguous_conversion) << T;
15856 }
15857 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
15858 QualType ConvTy) override {
15859 return S.Diag(Loc: Conv->getLocation(), DiagID: diag::note_omp_conversion_here)
15860 << ConvTy->isEnumeralType() << ConvTy;
15861 }
15862 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
15863 QualType) override {
15864 llvm_unreachable("conversion functions are permitted");
15865 }
15866 } ConvertDiagnoser;
15867 return SemaRef.PerformContextualImplicitConversion(Loc, FromE: Op, Converter&: ConvertDiagnoser);
15868}
15869
15870static bool
15871isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
15872 bool StrictlyPositive, bool BuildCapture = false,
15873 OpenMPDirectiveKind DKind = OMPD_unknown,
15874 OpenMPDirectiveKind *CaptureRegion = nullptr,
15875 Stmt **HelperValStmt = nullptr) {
15876 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
15877 !ValExpr->isInstantiationDependent()) {
15878 SourceLocation Loc = ValExpr->getExprLoc();
15879 ExprResult Value =
15880 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, Op: ValExpr);
15881 if (Value.isInvalid())
15882 return false;
15883
15884 ValExpr = Value.get();
15885 // The expression must evaluate to a non-negative integer value.
15886 if (std::optional<llvm::APSInt> Result =
15887 ValExpr->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
15888 if (Result->isSigned() &&
15889 !((!StrictlyPositive && Result->isNonNegative()) ||
15890 (StrictlyPositive && Result->isStrictlyPositive()))) {
15891 SemaRef.Diag(Loc, DiagID: diag::err_omp_negative_expression_in_clause)
15892 << getOpenMPClauseNameForDiag(C: CKind) << (StrictlyPositive ? 1 : 0)
15893 << ValExpr->getSourceRange();
15894 return false;
15895 }
15896 }
15897 if (!BuildCapture)
15898 return true;
15899 *CaptureRegion =
15900 getOpenMPCaptureRegionForClause(DKind, CKind, OpenMPVersion: SemaRef.LangOpts.OpenMP);
15901 if (*CaptureRegion != OMPD_unknown &&
15902 !SemaRef.CurContext->isDependentContext()) {
15903 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
15904 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15905 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
15906 *HelperValStmt = buildPreInits(Context&: SemaRef.Context, Captures);
15907 }
15908 }
15909 return true;
15910}
15911
15912static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
15913 unsigned Last,
15914 ArrayRef<unsigned> Exclude = {}) {
15915 SmallString<256> Buffer;
15916 llvm::raw_svector_ostream Out(Buffer);
15917 unsigned Skipped = Exclude.size();
15918 for (unsigned I = First; I < Last; ++I) {
15919 if (llvm::is_contained(Range&: Exclude, Element: I)) {
15920 --Skipped;
15921 continue;
15922 }
15923 Out << "'" << getOpenMPSimpleClauseTypeName(Kind: K, Type: I) << "'";
15924 if (I + Skipped + 2 == Last)
15925 Out << " or ";
15926 else if (I + Skipped + 1 != Last)
15927 Out << ", ";
15928 }
15929 return std::string(Out.str());
15930}
15931
15932OMPClause *SemaOpenMP::ActOnOpenMPNumThreadsClause(
15933 OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads,
15934 SourceLocation StartLoc, SourceLocation LParenLoc,
15935 SourceLocation ModifierLoc, SourceLocation EndLoc) {
15936 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 60) &&
15937 "Unexpected num_threads modifier in OpenMP < 60.");
15938
15939 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTHREADS_unknown) {
15940 std::string Values = getListOfPossibleValues(K: OMPC_num_threads, /*First=*/0,
15941 Last: OMPC_NUMTHREADS_unknown);
15942 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
15943 << Values << getOpenMPClauseNameForDiag(C: OMPC_num_threads);
15944 return nullptr;
15945 }
15946
15947 Expr *ValExpr = NumThreads;
15948 Stmt *HelperValStmt = nullptr;
15949
15950 // OpenMP [2.5, Restrictions]
15951 // The num_threads expression must evaluate to a positive integer value.
15952 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_num_threads,
15953 /*StrictlyPositive=*/true))
15954 return nullptr;
15955
15956 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15957 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
15958 DKind, CKind: OMPC_num_threads, OpenMPVersion: getLangOpts().OpenMP);
15959 if (CaptureRegion != OMPD_unknown &&
15960 !SemaRef.CurContext->isDependentContext()) {
15961 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
15962 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15963 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
15964 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
15965 }
15966
15967 return new (getASTContext())
15968 OMPNumThreadsClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
15969 StartLoc, LParenLoc, ModifierLoc, EndLoc);
15970}
15971
15972ExprResult SemaOpenMP::VerifyPositiveIntegerConstantInClause(
15973 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
15974 bool SuppressExprDiags) {
15975 if (!E)
15976 return ExprError();
15977 if (E->isValueDependent() || E->isTypeDependent() ||
15978 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
15979 return E;
15980
15981 llvm::APSInt Result;
15982 ExprResult ICE;
15983 if (SuppressExprDiags) {
15984 // Use a custom diagnoser that suppresses 'note' diagnostics about the
15985 // expression.
15986 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
15987 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
15988 SemaBase::SemaDiagnosticBuilder
15989 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
15990 llvm_unreachable("Diagnostic suppressed");
15991 }
15992 } Diagnoser;
15993 ICE = SemaRef.VerifyIntegerConstantExpression(E, Result: &Result, Diagnoser,
15994 CanFold: AllowFoldKind::Allow);
15995 } else {
15996 ICE =
15997 SemaRef.VerifyIntegerConstantExpression(E, Result: &Result,
15998 /*FIXME*/ CanFold: AllowFoldKind::Allow);
15999 }
16000 if (ICE.isInvalid())
16001 return ExprError();
16002
16003 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16004 (!StrictlyPositive && !Result.isNonNegative())) {
16005 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_negative_expression_in_clause)
16006 << getOpenMPClauseNameForDiag(C: CKind) << (StrictlyPositive ? 1 : 0)
16007 << E->getSourceRange();
16008 return ExprError();
16009 }
16010 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
16011 CKind == OMPC_allocate) &&
16012 !Result.isPowerOf2()) {
16013 Diag(Loc: E->getExprLoc(), DiagID: diag::warn_omp_alignment_not_power_of_two)
16014 << E->getSourceRange();
16015 return ExprError();
16016 }
16017
16018 if (!Result.isRepresentableByInt64()) {
16019 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_large_expression_in_clause)
16020 << getOpenMPClauseNameForDiag(C: CKind) << E->getSourceRange();
16021 return ExprError();
16022 }
16023
16024 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16025 DSAStack->setAssociatedLoops(Result.getExtValue());
16026 else if (CKind == OMPC_ordered)
16027 DSAStack->setAssociatedLoops(Result.getExtValue());
16028 return ICE;
16029}
16030
16031void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
16032
16033void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
16034
16035int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
16036
16037void SemaOpenMP::ActOnOpenMPDeviceNum(Expr *DeviceNumExpr) {
16038 llvm::APSInt Result;
16039 Expr::EvalResult EvalResult;
16040 // Evaluate the expression to an integer value
16041 if (!DeviceNumExpr->isValueDependent() &&
16042 DeviceNumExpr->EvaluateAsInt(Result&: EvalResult, Ctx: SemaRef.Context)) {
16043 // The device expression must evaluate to a non-negative integer value.
16044 Result = EvalResult.Val.getInt();
16045 if (Result.isNonNegative()) {
16046 setOpenMPDeviceNum(Result.getZExtValue());
16047 } else {
16048 Diag(Loc: DeviceNumExpr->getExprLoc(),
16049 DiagID: diag::err_omp_negative_expression_in_clause)
16050 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
16051 }
16052 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(Val: DeviceNumExpr)) {
16053 // Check if the expression is an identifier
16054 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
16055 if (IdInfo) {
16056 setOpenMPDeviceNumID(IdInfo->getName());
16057 }
16058 } else {
16059 Diag(Loc: DeviceNumExpr->getExprLoc(), DiagID: diag::err_expected_expression);
16060 }
16061}
16062
16063OMPClause *SemaOpenMP::ActOnOpenMPSafelenClause(Expr *Len,
16064 SourceLocation StartLoc,
16065 SourceLocation LParenLoc,
16066 SourceLocation EndLoc) {
16067 // OpenMP [2.8.1, simd construct, Description]
16068 // The parameter of the safelen clause must be a constant
16069 // positive integer expression.
16070 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(E: Len, CKind: OMPC_safelen);
16071 if (Safelen.isInvalid())
16072 return nullptr;
16073 return new (getASTContext())
16074 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16075}
16076
16077OMPClause *SemaOpenMP::ActOnOpenMPSimdlenClause(Expr *Len,
16078 SourceLocation StartLoc,
16079 SourceLocation LParenLoc,
16080 SourceLocation EndLoc) {
16081 // OpenMP [2.8.1, simd construct, Description]
16082 // The parameter of the simdlen clause must be a constant
16083 // positive integer expression.
16084 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(E: Len, CKind: OMPC_simdlen);
16085 if (Simdlen.isInvalid())
16086 return nullptr;
16087 return new (getASTContext())
16088 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16089}
16090
16091/// Tries to find omp_allocator_handle_t type.
16092static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
16093 DSAStackTy *Stack) {
16094 if (!Stack->getOMPAllocatorHandleT().isNull())
16095 return true;
16096
16097 // Set the allocator handle type.
16098 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_allocator_handle_t");
16099 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
16100 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
16101 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found)
16102 << "omp_allocator_handle_t";
16103 return false;
16104 }
16105 QualType AllocatorHandleEnumTy = PT.get();
16106 AllocatorHandleEnumTy.addConst();
16107 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16108
16109 // Fill the predefined allocator map.
16110 bool ErrorFound = false;
16111 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16112 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16113 StringRef Allocator =
16114 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(Val: AllocatorKind);
16115 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Name: Allocator);
16116 auto *VD = dyn_cast_or_null<ValueDecl>(
16117 Val: S.LookupSingleName(S: S.TUScope, Name: AllocatorName, Loc, NameKind: Sema::LookupAnyName));
16118 if (!VD) {
16119 ErrorFound = true;
16120 break;
16121 }
16122 QualType AllocatorType =
16123 VD->getType().getNonLValueExprType(Context: S.getASTContext());
16124 ExprResult Res = S.BuildDeclRefExpr(D: VD, Ty: AllocatorType, VK: VK_LValue, Loc);
16125 if (!Res.isUsable()) {
16126 ErrorFound = true;
16127 break;
16128 }
16129 Res = S.PerformImplicitConversion(From: Res.get(), ToType: AllocatorHandleEnumTy,
16130 Action: AssignmentAction::Initializing,
16131 /*AllowExplicit=*/true);
16132 if (!Res.isUsable()) {
16133 ErrorFound = true;
16134 break;
16135 }
16136 Stack->setAllocator(AllocatorKind, Allocator: Res.get());
16137 }
16138 if (ErrorFound) {
16139 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found)
16140 << "omp_allocator_handle_t";
16141 return false;
16142 }
16143
16144 return true;
16145}
16146
16147OMPClause *SemaOpenMP::ActOnOpenMPAllocatorClause(Expr *A,
16148 SourceLocation StartLoc,
16149 SourceLocation LParenLoc,
16150 SourceLocation EndLoc) {
16151 // OpenMP [2.11.3, allocate Directive, Description]
16152 // allocator is an expression of omp_allocator_handle_t type.
16153 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: A->getExprLoc(), DSAStack))
16154 return nullptr;
16155
16156 ExprResult Allocator = SemaRef.DefaultLvalueConversion(E: A);
16157 if (Allocator.isInvalid())
16158 return nullptr;
16159 Allocator = SemaRef.PerformImplicitConversion(
16160 From: Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
16161 Action: AssignmentAction::Initializing,
16162 /*AllowExplicit=*/true);
16163 if (Allocator.isInvalid())
16164 return nullptr;
16165 return new (getASTContext())
16166 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
16167}
16168
16169OMPClause *SemaOpenMP::ActOnOpenMPCollapseClause(Expr *NumForLoops,
16170 SourceLocation StartLoc,
16171 SourceLocation LParenLoc,
16172 SourceLocation EndLoc) {
16173 // OpenMP [2.7.1, loop construct, Description]
16174 // OpenMP [2.8.1, simd construct, Description]
16175 // OpenMP [2.9.6, distribute construct, Description]
16176 // The parameter of the collapse clause must be a constant
16177 // positive integer expression.
16178 ExprResult NumForLoopsResult =
16179 VerifyPositiveIntegerConstantInClause(E: NumForLoops, CKind: OMPC_collapse);
16180 if (NumForLoopsResult.isInvalid())
16181 return nullptr;
16182 return new (getASTContext())
16183 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
16184}
16185
16186OMPClause *SemaOpenMP::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
16187 SourceLocation EndLoc,
16188 SourceLocation LParenLoc,
16189 Expr *NumForLoops) {
16190 // OpenMP [2.7.1, loop construct, Description]
16191 // OpenMP [2.8.1, simd construct, Description]
16192 // OpenMP [2.9.6, distribute construct, Description]
16193 // The parameter of the ordered clause must be a constant
16194 // positive integer expression if any.
16195 if (NumForLoops && LParenLoc.isValid()) {
16196 ExprResult NumForLoopsResult =
16197 VerifyPositiveIntegerConstantInClause(E: NumForLoops, CKind: OMPC_ordered);
16198 if (NumForLoopsResult.isInvalid())
16199 return nullptr;
16200 NumForLoops = NumForLoopsResult.get();
16201 } else {
16202 NumForLoops = nullptr;
16203 }
16204 auto *Clause =
16205 OMPOrderedClause::Create(C: getASTContext(), Num: NumForLoops,
16206 NumLoops: NumForLoops ? DSAStack->getAssociatedLoops() : 0,
16207 StartLoc, LParenLoc, EndLoc);
16208 DSAStack->setOrderedRegion(/*IsOrdered=*/true, Param: NumForLoops, Clause);
16209 return Clause;
16210}
16211
16212OMPClause *SemaOpenMP::ActOnOpenMPSimpleClause(
16213 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
16214 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16215 OMPClause *Res = nullptr;
16216 switch (Kind) {
16217 case OMPC_default:
16218 Res = ActOnOpenMPDefaultClause(Kind: static_cast<DefaultKind>(Argument),
16219 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16220 break;
16221 case OMPC_proc_bind:
16222 Res = ActOnOpenMPProcBindClause(Kind: static_cast<ProcBindKind>(Argument),
16223 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16224 break;
16225 case OMPC_atomic_default_mem_order:
16226 Res = ActOnOpenMPAtomicDefaultMemOrderClause(
16227 Kind: static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
16228 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16229 break;
16230 case OMPC_fail:
16231 Res = ActOnOpenMPFailClause(Kind: static_cast<OpenMPClauseKind>(Argument),
16232 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16233 break;
16234 case OMPC_update:
16235 Res = ActOnOpenMPUpdateClause(Kind: static_cast<OpenMPDependClauseKind>(Argument),
16236 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16237 break;
16238 case OMPC_bind:
16239 Res = ActOnOpenMPBindClause(Kind: static_cast<OpenMPBindClauseKind>(Argument),
16240 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16241 break;
16242 case OMPC_at:
16243 Res = ActOnOpenMPAtClause(Kind: static_cast<OpenMPAtClauseKind>(Argument),
16244 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16245 break;
16246 case OMPC_severity:
16247 Res = ActOnOpenMPSeverityClause(
16248 Kind: static_cast<OpenMPSeverityClauseKind>(Argument), KindLoc: ArgumentLoc, StartLoc,
16249 LParenLoc, EndLoc);
16250 break;
16251 case OMPC_if:
16252 case OMPC_final:
16253 case OMPC_num_threads:
16254 case OMPC_safelen:
16255 case OMPC_simdlen:
16256 case OMPC_sizes:
16257 case OMPC_allocator:
16258 case OMPC_collapse:
16259 case OMPC_schedule:
16260 case OMPC_private:
16261 case OMPC_firstprivate:
16262 case OMPC_lastprivate:
16263 case OMPC_shared:
16264 case OMPC_reduction:
16265 case OMPC_task_reduction:
16266 case OMPC_in_reduction:
16267 case OMPC_linear:
16268 case OMPC_aligned:
16269 case OMPC_copyin:
16270 case OMPC_copyprivate:
16271 case OMPC_ordered:
16272 case OMPC_nowait:
16273 case OMPC_untied:
16274 case OMPC_mergeable:
16275 case OMPC_threadprivate:
16276 case OMPC_allocate:
16277 case OMPC_flush:
16278 case OMPC_depobj:
16279 case OMPC_read:
16280 case OMPC_write:
16281 case OMPC_capture:
16282 case OMPC_compare:
16283 case OMPC_seq_cst:
16284 case OMPC_acq_rel:
16285 case OMPC_acquire:
16286 case OMPC_release:
16287 case OMPC_relaxed:
16288 case OMPC_depend:
16289 case OMPC_device:
16290 case OMPC_threads:
16291 case OMPC_simd:
16292 case OMPC_map:
16293 case OMPC_num_teams:
16294 case OMPC_thread_limit:
16295 case OMPC_priority:
16296 case OMPC_grainsize:
16297 case OMPC_nogroup:
16298 case OMPC_num_tasks:
16299 case OMPC_hint:
16300 case OMPC_dist_schedule:
16301 case OMPC_defaultmap:
16302 case OMPC_unknown:
16303 case OMPC_uniform:
16304 case OMPC_to:
16305 case OMPC_from:
16306 case OMPC_use_device_ptr:
16307 case OMPC_use_device_addr:
16308 case OMPC_is_device_ptr:
16309 case OMPC_has_device_addr:
16310 case OMPC_unified_address:
16311 case OMPC_unified_shared_memory:
16312 case OMPC_reverse_offload:
16313 case OMPC_dynamic_allocators:
16314 case OMPC_self_maps:
16315 case OMPC_device_type:
16316 case OMPC_match:
16317 case OMPC_nontemporal:
16318 case OMPC_destroy:
16319 case OMPC_novariants:
16320 case OMPC_nocontext:
16321 case OMPC_detach:
16322 case OMPC_inclusive:
16323 case OMPC_exclusive:
16324 case OMPC_uses_allocators:
16325 case OMPC_affinity:
16326 case OMPC_when:
16327 case OMPC_message:
16328 default:
16329 llvm_unreachable("Clause is not allowed.");
16330 }
16331 return Res;
16332}
16333
16334OMPClause *SemaOpenMP::ActOnOpenMPDefaultClause(DefaultKind Kind,
16335 SourceLocation KindKwLoc,
16336 SourceLocation StartLoc,
16337 SourceLocation LParenLoc,
16338 SourceLocation EndLoc) {
16339 if (Kind == OMP_DEFAULT_unknown) {
16340 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
16341 << getListOfPossibleValues(K: OMPC_default, /*First=*/0,
16342 /*Last=*/unsigned(OMP_DEFAULT_unknown))
16343 << getOpenMPClauseNameForDiag(C: OMPC_default);
16344 return nullptr;
16345 }
16346
16347 switch (Kind) {
16348 case OMP_DEFAULT_none:
16349 DSAStack->setDefaultDSANone(KindKwLoc);
16350 break;
16351 case OMP_DEFAULT_shared:
16352 DSAStack->setDefaultDSAShared(KindKwLoc);
16353 break;
16354 case OMP_DEFAULT_firstprivate:
16355 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
16356 break;
16357 case OMP_DEFAULT_private:
16358 DSAStack->setDefaultDSAPrivate(KindKwLoc);
16359 break;
16360 default:
16361 llvm_unreachable("DSA unexpected in OpenMP default clause");
16362 }
16363
16364 return new (getASTContext())
16365 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16366}
16367
16368OMPClause *SemaOpenMP::ActOnOpenMPProcBindClause(ProcBindKind Kind,
16369 SourceLocation KindKwLoc,
16370 SourceLocation StartLoc,
16371 SourceLocation LParenLoc,
16372 SourceLocation EndLoc) {
16373 if (Kind == OMP_PROC_BIND_unknown) {
16374 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
16375 << getListOfPossibleValues(K: OMPC_proc_bind,
16376 /*First=*/unsigned(OMP_PROC_BIND_master),
16377 /*Last=*/
16378 unsigned(getLangOpts().OpenMP > 50
16379 ? OMP_PROC_BIND_primary
16380 : OMP_PROC_BIND_spread) +
16381 1)
16382 << getOpenMPClauseNameForDiag(C: OMPC_proc_bind);
16383 return nullptr;
16384 }
16385 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
16386 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
16387 << getListOfPossibleValues(K: OMPC_proc_bind,
16388 /*First=*/unsigned(OMP_PROC_BIND_master),
16389 /*Last=*/
16390 unsigned(OMP_PROC_BIND_spread) + 1)
16391 << getOpenMPClauseNameForDiag(C: OMPC_proc_bind);
16392 return new (getASTContext())
16393 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16394}
16395
16396OMPClause *SemaOpenMP::ActOnOpenMPAtomicDefaultMemOrderClause(
16397 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
16398 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16399 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
16400 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
16401 << getListOfPossibleValues(
16402 K: OMPC_atomic_default_mem_order, /*First=*/0,
16403 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
16404 << getOpenMPClauseNameForDiag(C: OMPC_atomic_default_mem_order);
16405 return nullptr;
16406 }
16407 return new (getASTContext()) OMPAtomicDefaultMemOrderClause(
16408 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16409}
16410
16411OMPClause *SemaOpenMP::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
16412 SourceLocation KindKwLoc,
16413 SourceLocation StartLoc,
16414 SourceLocation LParenLoc,
16415 SourceLocation EndLoc) {
16416 if (Kind == OMPC_AT_unknown) {
16417 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
16418 << getListOfPossibleValues(K: OMPC_at, /*First=*/0,
16419 /*Last=*/OMPC_AT_unknown)
16420 << getOpenMPClauseNameForDiag(C: OMPC_at);
16421 return nullptr;
16422 }
16423 return new (getASTContext())
16424 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16425}
16426
16427OMPClause *SemaOpenMP::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
16428 SourceLocation KindKwLoc,
16429 SourceLocation StartLoc,
16430 SourceLocation LParenLoc,
16431 SourceLocation EndLoc) {
16432 if (Kind == OMPC_SEVERITY_unknown) {
16433 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
16434 << getListOfPossibleValues(K: OMPC_severity, /*First=*/0,
16435 /*Last=*/OMPC_SEVERITY_unknown)
16436 << getOpenMPClauseNameForDiag(C: OMPC_severity);
16437 return nullptr;
16438 }
16439 return new (getASTContext())
16440 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16441}
16442
16443OMPClause *SemaOpenMP::ActOnOpenMPMessageClause(Expr *ME,
16444 SourceLocation StartLoc,
16445 SourceLocation LParenLoc,
16446 SourceLocation EndLoc) {
16447 assert(ME && "NULL expr in Message clause");
16448 if (!isa<StringLiteral>(Val: ME)) {
16449 Diag(Loc: ME->getBeginLoc(), DiagID: diag::warn_clause_expected_string)
16450 << getOpenMPClauseNameForDiag(C: OMPC_message);
16451 return nullptr;
16452 }
16453 return new (getASTContext())
16454 OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
16455}
16456
16457OMPClause *SemaOpenMP::ActOnOpenMPOrderClause(
16458 OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind,
16459 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
16460 SourceLocation KindLoc, SourceLocation EndLoc) {
16461 if (Kind != OMPC_ORDER_concurrent ||
16462 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
16463 // Kind should be concurrent,
16464 // Modifiers introduced in OpenMP 5.1
16465 static_assert(OMPC_ORDER_unknown > 0,
16466 "OMPC_ORDER_unknown not greater than 0");
16467
16468 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
16469 << getListOfPossibleValues(K: OMPC_order,
16470 /*First=*/0,
16471 /*Last=*/OMPC_ORDER_unknown)
16472 << getOpenMPClauseNameForDiag(C: OMPC_order);
16473 return nullptr;
16474 }
16475 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
16476 MLoc.isValid()) {
16477 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
16478 << getListOfPossibleValues(K: OMPC_order,
16479 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
16480 /*Last=*/OMPC_ORDER_MODIFIER_last)
16481 << getOpenMPClauseNameForDiag(C: OMPC_order);
16482 } else if (getLangOpts().OpenMP >= 50) {
16483 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
16484 if (DSAStack->getCurScope()) {
16485 // mark the current scope with 'order' flag
16486 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
16487 DSAStack->getCurScope()->setFlags(existingFlags |
16488 Scope::OpenMPOrderClauseScope);
16489 }
16490 }
16491 return new (getASTContext()) OMPOrderClause(
16492 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
16493}
16494
16495OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,
16496 SourceLocation KindKwLoc,
16497 SourceLocation StartLoc,
16498 SourceLocation LParenLoc,
16499 SourceLocation EndLoc) {
16500 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
16501 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16502 SmallVector<unsigned> Except = {
16503 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16504 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16505 if (getLangOpts().OpenMP < 51)
16506 Except.push_back(Elt: OMPC_DEPEND_inoutset);
16507 Diag(Loc: KindKwLoc, DiagID: diag::err_omp_unexpected_clause_value)
16508 << getListOfPossibleValues(K: OMPC_depend, /*First=*/0,
16509 /*Last=*/OMPC_DEPEND_unknown, Exclude: Except)
16510 << getOpenMPClauseNameForDiag(C: OMPC_update);
16511 return nullptr;
16512 }
16513 return OMPUpdateClause::Create(C: getASTContext(), StartLoc, LParenLoc,
16514 ArgumentLoc: KindKwLoc, DK: Kind, EndLoc);
16515}
16516
16517OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
16518 SourceLocation StartLoc,
16519 SourceLocation LParenLoc,
16520 SourceLocation EndLoc) {
16521 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
16522
16523 for (Expr *&SizeExpr : SanitizedSizeExprs) {
16524 // Skip if already sanitized, e.g. during a partial template instantiation.
16525 if (!SizeExpr)
16526 continue;
16527
16528 bool IsValid = isNonNegativeIntegerValue(ValExpr&: SizeExpr, SemaRef, CKind: OMPC_sizes,
16529 /*StrictlyPositive=*/true);
16530
16531 // isNonNegativeIntegerValue returns true for non-integral types (but still
16532 // emits error diagnostic), so check for the expected type explicitly.
16533 QualType SizeTy = SizeExpr->getType();
16534 if (!SizeTy->isIntegerType())
16535 IsValid = false;
16536
16537 // Handling in templates is tricky. There are four possibilities to
16538 // consider:
16539 //
16540 // 1a. The expression is valid and we are in a instantiated template or not
16541 // in a template:
16542 // Pass valid expression to be further analysed later in Sema.
16543 // 1b. The expression is valid and we are in a template (including partial
16544 // instantiation):
16545 // isNonNegativeIntegerValue skipped any checks so there is no
16546 // guarantee it will be correct after instantiation.
16547 // ActOnOpenMPSizesClause will be called again at instantiation when
16548 // it is not in a dependent context anymore. This may cause warnings
16549 // to be emitted multiple times.
16550 // 2a. The expression is invalid and we are in an instantiated template or
16551 // not in a template:
16552 // Invalidate the expression with a clearly wrong value (nullptr) so
16553 // later in Sema we do not have to do the same validity analysis again
16554 // or crash from unexpected data. Error diagnostics have already been
16555 // emitted.
16556 // 2b. The expression is invalid and we are in a template (including partial
16557 // instantiation):
16558 // Pass the invalid expression as-is, template instantiation may
16559 // replace unexpected types/values with valid ones. The directives
16560 // with this clause must not try to use these expressions in dependent
16561 // contexts, but delay analysis until full instantiation.
16562 if (!SizeExpr->isInstantiationDependent() && !IsValid)
16563 SizeExpr = nullptr;
16564 }
16565
16566 return OMPSizesClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
16567 Sizes: SanitizedSizeExprs);
16568}
16569
16570OMPClause *SemaOpenMP::ActOnOpenMPPermutationClause(ArrayRef<Expr *> PermExprs,
16571 SourceLocation StartLoc,
16572 SourceLocation LParenLoc,
16573 SourceLocation EndLoc) {
16574 size_t NumLoops = PermExprs.size();
16575 SmallVector<Expr *> SanitizedPermExprs;
16576 llvm::append_range(C&: SanitizedPermExprs, R&: PermExprs);
16577
16578 for (Expr *&PermExpr : SanitizedPermExprs) {
16579 // Skip if template-dependent or already sanitized, e.g. during a partial
16580 // template instantiation.
16581 if (!PermExpr || PermExpr->isInstantiationDependent())
16582 continue;
16583
16584 llvm::APSInt PermVal;
16585 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
16586 E: PermExpr, Result: &PermVal, CanFold: AllowFoldKind::Allow);
16587 bool IsValid = PermEvalExpr.isUsable();
16588 if (IsValid)
16589 PermExpr = PermEvalExpr.get();
16590
16591 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
16592 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
16593 PermEvalExpr.get()->getEndLoc());
16594 Diag(Loc: PermEvalExpr.get()->getExprLoc(),
16595 DiagID: diag::err_omp_interchange_permutation_value_range)
16596 << NumLoops << ExprRange;
16597 IsValid = false;
16598 }
16599
16600 if (!PermExpr->isInstantiationDependent() && !IsValid)
16601 PermExpr = nullptr;
16602 }
16603
16604 return OMPPermutationClause::Create(C: getASTContext(), StartLoc, LParenLoc,
16605 EndLoc, Args: SanitizedPermExprs);
16606}
16607
16608OMPClause *SemaOpenMP::ActOnOpenMPFullClause(SourceLocation StartLoc,
16609 SourceLocation EndLoc) {
16610 return OMPFullClause::Create(C: getASTContext(), StartLoc, EndLoc);
16611}
16612
16613OMPClause *SemaOpenMP::ActOnOpenMPPartialClause(Expr *FactorExpr,
16614 SourceLocation StartLoc,
16615 SourceLocation LParenLoc,
16616 SourceLocation EndLoc) {
16617 if (FactorExpr) {
16618 // If an argument is specified, it must be a constant (or an unevaluated
16619 // template expression).
16620 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
16621 E: FactorExpr, CKind: OMPC_partial, /*StrictlyPositive=*/true);
16622 if (FactorResult.isInvalid())
16623 return nullptr;
16624 FactorExpr = FactorResult.get();
16625 }
16626
16627 return OMPPartialClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
16628 Factor: FactorExpr);
16629}
16630
16631OMPClause *SemaOpenMP::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
16632 SourceLocation LParenLoc,
16633 SourceLocation EndLoc) {
16634 ExprResult AlignVal;
16635 AlignVal = VerifyPositiveIntegerConstantInClause(E: A, CKind: OMPC_align);
16636 if (AlignVal.isInvalid())
16637 return nullptr;
16638 return OMPAlignClause::Create(C: getASTContext(), A: AlignVal.get(), StartLoc,
16639 LParenLoc, EndLoc);
16640}
16641
16642OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause(
16643 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
16644 SourceLocation StartLoc, SourceLocation LParenLoc,
16645 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
16646 SourceLocation EndLoc) {
16647 OMPClause *Res = nullptr;
16648 switch (Kind) {
16649 case OMPC_schedule:
16650 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16651 assert(Argument.size() == NumberOfElements &&
16652 ArgumentLoc.size() == NumberOfElements);
16653 Res = ActOnOpenMPScheduleClause(
16654 M1: static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
16655 M2: static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
16656 Kind: static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), ChunkSize: Expr,
16657 StartLoc, LParenLoc, M1Loc: ArgumentLoc[Modifier1], M2Loc: ArgumentLoc[Modifier2],
16658 KindLoc: ArgumentLoc[ScheduleKind], CommaLoc: DelimLoc, EndLoc);
16659 break;
16660 case OMPC_if:
16661 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16662 Res = ActOnOpenMPIfClause(NameModifier: static_cast<OpenMPDirectiveKind>(Argument.back()),
16663 Condition: Expr, StartLoc, LParenLoc, NameModifierLoc: ArgumentLoc.back(),
16664 ColonLoc: DelimLoc, EndLoc);
16665 break;
16666 case OMPC_dist_schedule:
16667 Res = ActOnOpenMPDistScheduleClause(
16668 Kind: static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), ChunkSize: Expr,
16669 StartLoc, LParenLoc, KindLoc: ArgumentLoc.back(), CommaLoc: DelimLoc, EndLoc);
16670 break;
16671 case OMPC_defaultmap:
16672 enum { Modifier, DefaultmapKind };
16673 Res = ActOnOpenMPDefaultmapClause(
16674 M: static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
16675 Kind: static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
16676 StartLoc, LParenLoc, MLoc: ArgumentLoc[Modifier], KindLoc: ArgumentLoc[DefaultmapKind],
16677 EndLoc);
16678 break;
16679 case OMPC_order:
16680 enum { OrderModifier, OrderKind };
16681 Res = ActOnOpenMPOrderClause(
16682 Modifier: static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
16683 Kind: static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
16684 LParenLoc, MLoc: ArgumentLoc[OrderModifier], KindLoc: ArgumentLoc[OrderKind], EndLoc);
16685 break;
16686 case OMPC_device:
16687 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16688 Res = ActOnOpenMPDeviceClause(
16689 Modifier: static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Device: Expr,
16690 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
16691 break;
16692 case OMPC_grainsize:
16693 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16694 "Modifier for grainsize clause and its location are expected.");
16695 Res = ActOnOpenMPGrainsizeClause(
16696 Modifier: static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Size: Expr,
16697 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
16698 break;
16699 case OMPC_num_tasks:
16700 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16701 "Modifier for num_tasks clause and its location are expected.");
16702 Res = ActOnOpenMPNumTasksClause(
16703 Modifier: static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), NumTasks: Expr,
16704 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
16705 break;
16706 case OMPC_num_threads:
16707 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16708 "Modifier for num_threads clause and its location are expected.");
16709 Res = ActOnOpenMPNumThreadsClause(
16710 Modifier: static_cast<OpenMPNumThreadsClauseModifier>(Argument.back()), NumThreads: Expr,
16711 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
16712 break;
16713 case OMPC_final:
16714 case OMPC_safelen:
16715 case OMPC_simdlen:
16716 case OMPC_sizes:
16717 case OMPC_allocator:
16718 case OMPC_collapse:
16719 case OMPC_default:
16720 case OMPC_proc_bind:
16721 case OMPC_private:
16722 case OMPC_firstprivate:
16723 case OMPC_lastprivate:
16724 case OMPC_shared:
16725 case OMPC_reduction:
16726 case OMPC_task_reduction:
16727 case OMPC_in_reduction:
16728 case OMPC_linear:
16729 case OMPC_aligned:
16730 case OMPC_copyin:
16731 case OMPC_copyprivate:
16732 case OMPC_ordered:
16733 case OMPC_nowait:
16734 case OMPC_untied:
16735 case OMPC_mergeable:
16736 case OMPC_threadprivate:
16737 case OMPC_allocate:
16738 case OMPC_flush:
16739 case OMPC_depobj:
16740 case OMPC_read:
16741 case OMPC_write:
16742 case OMPC_update:
16743 case OMPC_capture:
16744 case OMPC_compare:
16745 case OMPC_seq_cst:
16746 case OMPC_acq_rel:
16747 case OMPC_acquire:
16748 case OMPC_release:
16749 case OMPC_relaxed:
16750 case OMPC_depend:
16751 case OMPC_threads:
16752 case OMPC_simd:
16753 case OMPC_map:
16754 case OMPC_num_teams:
16755 case OMPC_thread_limit:
16756 case OMPC_priority:
16757 case OMPC_nogroup:
16758 case OMPC_hint:
16759 case OMPC_unknown:
16760 case OMPC_uniform:
16761 case OMPC_to:
16762 case OMPC_from:
16763 case OMPC_use_device_ptr:
16764 case OMPC_use_device_addr:
16765 case OMPC_is_device_ptr:
16766 case OMPC_has_device_addr:
16767 case OMPC_unified_address:
16768 case OMPC_unified_shared_memory:
16769 case OMPC_reverse_offload:
16770 case OMPC_dynamic_allocators:
16771 case OMPC_atomic_default_mem_order:
16772 case OMPC_self_maps:
16773 case OMPC_device_type:
16774 case OMPC_match:
16775 case OMPC_nontemporal:
16776 case OMPC_at:
16777 case OMPC_severity:
16778 case OMPC_message:
16779 case OMPC_destroy:
16780 case OMPC_novariants:
16781 case OMPC_nocontext:
16782 case OMPC_detach:
16783 case OMPC_inclusive:
16784 case OMPC_exclusive:
16785 case OMPC_uses_allocators:
16786 case OMPC_affinity:
16787 case OMPC_when:
16788 case OMPC_bind:
16789 default:
16790 llvm_unreachable("Clause is not allowed.");
16791 }
16792 return Res;
16793}
16794
16795static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
16796 OpenMPScheduleClauseModifier M2,
16797 SourceLocation M1Loc, SourceLocation M2Loc) {
16798 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
16799 SmallVector<unsigned, 2> Excluded;
16800 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
16801 Excluded.push_back(Elt: M2);
16802 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16803 Excluded.push_back(Elt: OMPC_SCHEDULE_MODIFIER_monotonic);
16804 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16805 Excluded.push_back(Elt: OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16806 S.Diag(Loc: M1Loc, DiagID: diag::err_omp_unexpected_clause_value)
16807 << getListOfPossibleValues(K: OMPC_schedule,
16808 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
16809 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
16810 Exclude: Excluded)
16811 << getOpenMPClauseNameForDiag(C: OMPC_schedule);
16812 return true;
16813 }
16814 return false;
16815}
16816
16817OMPClause *SemaOpenMP::ActOnOpenMPScheduleClause(
16818 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
16819 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
16820 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
16821 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
16822 if (checkScheduleModifiers(S&: SemaRef, M1, M2, M1Loc, M2Loc) ||
16823 checkScheduleModifiers(S&: SemaRef, M1: M2, M2: M1, M1Loc: M2Loc, M2Loc: M1Loc))
16824 return nullptr;
16825 // OpenMP, 2.7.1, Loop Construct, Restrictions
16826 // Either the monotonic modifier or the nonmonotonic modifier can be specified
16827 // but not both.
16828 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
16829 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16830 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16831 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16832 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16833 Diag(Loc: M2Loc, DiagID: diag::err_omp_unexpected_schedule_modifier)
16834 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule, Type: M2)
16835 << getOpenMPSimpleClauseTypeName(Kind: OMPC_schedule, Type: M1);
16836 return nullptr;
16837 }
16838 if (Kind == OMPC_SCHEDULE_unknown) {
16839 std::string Values;
16840 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
16841 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
16842 Values = getListOfPossibleValues(K: OMPC_schedule, /*First=*/0,
16843 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
16844 Exclude);
16845 } else {
16846 Values = getListOfPossibleValues(K: OMPC_schedule, /*First=*/0,
16847 /*Last=*/OMPC_SCHEDULE_unknown);
16848 }
16849 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
16850 << Values << getOpenMPClauseNameForDiag(C: OMPC_schedule);
16851 return nullptr;
16852 }
16853 // OpenMP, 2.7.1, Loop Construct, Restrictions
16854 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
16855 // schedule(guided).
16856 // OpenMP 5.0 does not have this restriction.
16857 if (getLangOpts().OpenMP < 50 &&
16858 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16859 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16860 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16861 Diag(Loc: M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16862 DiagID: diag::err_omp_schedule_nonmonotonic_static);
16863 return nullptr;
16864 }
16865 Expr *ValExpr = ChunkSize;
16866 Stmt *HelperValStmt = nullptr;
16867 if (ChunkSize) {
16868 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
16869 !ChunkSize->isInstantiationDependent() &&
16870 !ChunkSize->containsUnexpandedParameterPack()) {
16871 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
16872 ExprResult Val =
16873 PerformOpenMPImplicitIntegerConversion(Loc: ChunkSizeLoc, Op: ChunkSize);
16874 if (Val.isInvalid())
16875 return nullptr;
16876
16877 ValExpr = Val.get();
16878
16879 // OpenMP [2.7.1, Restrictions]
16880 // chunk_size must be a loop invariant integer expression with a positive
16881 // value.
16882 if (std::optional<llvm::APSInt> Result =
16883 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
16884 if (Result->isSigned() && !Result->isStrictlyPositive()) {
16885 Diag(Loc: ChunkSizeLoc, DiagID: diag::err_omp_negative_expression_in_clause)
16886 << "schedule" << 1 << ChunkSize->getSourceRange();
16887 return nullptr;
16888 }
16889 } else if (getOpenMPCaptureRegionForClause(
16890 DSAStack->getCurrentDirective(), CKind: OMPC_schedule,
16891 OpenMPVersion: getLangOpts().OpenMP) != OMPD_unknown &&
16892 !SemaRef.CurContext->isDependentContext()) {
16893 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
16894 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16895 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
16896 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
16897 }
16898 }
16899 }
16900
16901 return new (getASTContext())
16902 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
16903 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16904}
16905
16906OMPClause *SemaOpenMP::ActOnOpenMPClause(OpenMPClauseKind Kind,
16907 SourceLocation StartLoc,
16908 SourceLocation EndLoc) {
16909 OMPClause *Res = nullptr;
16910 switch (Kind) {
16911 case OMPC_ordered:
16912 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
16913 break;
16914 case OMPC_nowait:
16915 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
16916 break;
16917 case OMPC_untied:
16918 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
16919 break;
16920 case OMPC_mergeable:
16921 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
16922 break;
16923 case OMPC_read:
16924 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
16925 break;
16926 case OMPC_write:
16927 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
16928 break;
16929 case OMPC_update:
16930 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
16931 break;
16932 case OMPC_capture:
16933 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
16934 break;
16935 case OMPC_compare:
16936 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
16937 break;
16938 case OMPC_fail:
16939 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
16940 break;
16941 case OMPC_seq_cst:
16942 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
16943 break;
16944 case OMPC_acq_rel:
16945 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
16946 break;
16947 case OMPC_acquire:
16948 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
16949 break;
16950 case OMPC_release:
16951 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
16952 break;
16953 case OMPC_relaxed:
16954 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
16955 break;
16956 case OMPC_weak:
16957 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
16958 break;
16959 case OMPC_threads:
16960 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
16961 break;
16962 case OMPC_simd:
16963 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
16964 break;
16965 case OMPC_nogroup:
16966 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
16967 break;
16968 case OMPC_unified_address:
16969 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
16970 break;
16971 case OMPC_unified_shared_memory:
16972 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16973 break;
16974 case OMPC_reverse_offload:
16975 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
16976 break;
16977 case OMPC_dynamic_allocators:
16978 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
16979 break;
16980 case OMPC_self_maps:
16981 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
16982 break;
16983 case OMPC_destroy:
16984 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
16985 /*LParenLoc=*/SourceLocation(),
16986 /*VarLoc=*/SourceLocation(), EndLoc);
16987 break;
16988 case OMPC_full:
16989 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
16990 break;
16991 case OMPC_partial:
16992 Res = ActOnOpenMPPartialClause(FactorExpr: nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
16993 break;
16994 case OMPC_ompx_bare:
16995 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
16996 break;
16997 case OMPC_if:
16998 case OMPC_final:
16999 case OMPC_num_threads:
17000 case OMPC_safelen:
17001 case OMPC_simdlen:
17002 case OMPC_sizes:
17003 case OMPC_allocator:
17004 case OMPC_collapse:
17005 case OMPC_schedule:
17006 case OMPC_private:
17007 case OMPC_firstprivate:
17008 case OMPC_lastprivate:
17009 case OMPC_shared:
17010 case OMPC_reduction:
17011 case OMPC_task_reduction:
17012 case OMPC_in_reduction:
17013 case OMPC_linear:
17014 case OMPC_aligned:
17015 case OMPC_copyin:
17016 case OMPC_copyprivate:
17017 case OMPC_default:
17018 case OMPC_proc_bind:
17019 case OMPC_threadprivate:
17020 case OMPC_allocate:
17021 case OMPC_flush:
17022 case OMPC_depobj:
17023 case OMPC_depend:
17024 case OMPC_device:
17025 case OMPC_map:
17026 case OMPC_num_teams:
17027 case OMPC_thread_limit:
17028 case OMPC_priority:
17029 case OMPC_grainsize:
17030 case OMPC_num_tasks:
17031 case OMPC_hint:
17032 case OMPC_dist_schedule:
17033 case OMPC_defaultmap:
17034 case OMPC_unknown:
17035 case OMPC_uniform:
17036 case OMPC_to:
17037 case OMPC_from:
17038 case OMPC_use_device_ptr:
17039 case OMPC_use_device_addr:
17040 case OMPC_is_device_ptr:
17041 case OMPC_has_device_addr:
17042 case OMPC_atomic_default_mem_order:
17043 case OMPC_device_type:
17044 case OMPC_match:
17045 case OMPC_nontemporal:
17046 case OMPC_order:
17047 case OMPC_at:
17048 case OMPC_severity:
17049 case OMPC_message:
17050 case OMPC_novariants:
17051 case OMPC_nocontext:
17052 case OMPC_detach:
17053 case OMPC_inclusive:
17054 case OMPC_exclusive:
17055 case OMPC_uses_allocators:
17056 case OMPC_affinity:
17057 case OMPC_when:
17058 case OMPC_ompx_dyn_cgroup_mem:
17059 default:
17060 llvm_unreachable("Clause is not allowed.");
17061 }
17062 return Res;
17063}
17064
17065OMPClause *SemaOpenMP::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
17066 SourceLocation EndLoc) {
17067 DSAStack->setNowaitRegion();
17068 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
17069}
17070
17071OMPClause *SemaOpenMP::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
17072 SourceLocation EndLoc) {
17073 DSAStack->setUntiedRegion();
17074 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
17075}
17076
17077OMPClause *SemaOpenMP::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
17078 SourceLocation EndLoc) {
17079 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
17080}
17081
17082OMPClause *SemaOpenMP::ActOnOpenMPReadClause(SourceLocation StartLoc,
17083 SourceLocation EndLoc) {
17084 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
17085}
17086
17087OMPClause *SemaOpenMP::ActOnOpenMPWriteClause(SourceLocation StartLoc,
17088 SourceLocation EndLoc) {
17089 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
17090}
17091
17092OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
17093 SourceLocation EndLoc) {
17094 return OMPUpdateClause::Create(C: getASTContext(), StartLoc, EndLoc);
17095}
17096
17097OMPClause *SemaOpenMP::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
17098 SourceLocation EndLoc) {
17099 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
17100}
17101
17102OMPClause *SemaOpenMP::ActOnOpenMPCompareClause(SourceLocation StartLoc,
17103 SourceLocation EndLoc) {
17104 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
17105}
17106
17107OMPClause *SemaOpenMP::ActOnOpenMPFailClause(SourceLocation StartLoc,
17108 SourceLocation EndLoc) {
17109 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
17110}
17111
17112OMPClause *SemaOpenMP::ActOnOpenMPFailClause(OpenMPClauseKind Parameter,
17113 SourceLocation KindLoc,
17114 SourceLocation StartLoc,
17115 SourceLocation LParenLoc,
17116 SourceLocation EndLoc) {
17117
17118 if (!checkFailClauseParameter(FailClauseParameter: Parameter)) {
17119 Diag(Loc: KindLoc, DiagID: diag::err_omp_atomic_fail_wrong_or_no_clauses);
17120 return nullptr;
17121 }
17122 return new (getASTContext())
17123 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
17124}
17125
17126OMPClause *SemaOpenMP::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
17127 SourceLocation EndLoc) {
17128 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
17129}
17130
17131OMPClause *SemaOpenMP::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
17132 SourceLocation EndLoc) {
17133 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
17134}
17135
17136OMPClause *SemaOpenMP::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
17137 SourceLocation EndLoc) {
17138 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
17139}
17140
17141OMPClause *SemaOpenMP::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
17142 SourceLocation EndLoc) {
17143 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
17144}
17145
17146OMPClause *SemaOpenMP::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
17147 SourceLocation EndLoc) {
17148 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
17149}
17150
17151OMPClause *SemaOpenMP::ActOnOpenMPWeakClause(SourceLocation StartLoc,
17152 SourceLocation EndLoc) {
17153 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
17154}
17155
17156OMPClause *SemaOpenMP::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
17157 SourceLocation EndLoc) {
17158 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
17159}
17160
17161OMPClause *SemaOpenMP::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
17162 SourceLocation EndLoc) {
17163 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
17164}
17165
17166OMPClause *SemaOpenMP::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
17167 SourceLocation EndLoc) {
17168 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
17169}
17170
17171OMPClause *SemaOpenMP::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
17172 SourceLocation EndLoc) {
17173 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
17174}
17175
17176OMPClause *
17177SemaOpenMP::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
17178 SourceLocation EndLoc) {
17179 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17180}
17181
17182OMPClause *SemaOpenMP::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
17183 SourceLocation EndLoc) {
17184 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
17185}
17186
17187OMPClause *
17188SemaOpenMP::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
17189 SourceLocation EndLoc) {
17190 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17191}
17192
17193OMPClause *SemaOpenMP::ActOnOpenMPSelfMapsClause(SourceLocation StartLoc,
17194 SourceLocation EndLoc) {
17195 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
17196}
17197
17198StmtResult
17199SemaOpenMP::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
17200 SourceLocation StartLoc,
17201 SourceLocation EndLoc) {
17202
17203 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17204 // At least one action-clause must appear on a directive.
17205 if (!hasClauses(Clauses, K: OMPC_init, ClauseTypes: OMPC_use, ClauseTypes: OMPC_destroy, ClauseTypes: OMPC_nowait)) {
17206 unsigned OMPVersion = getLangOpts().OpenMP;
17207 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
17208 Diag(Loc: StartLoc, DiagID: diag::err_omp_no_clause_for_directive)
17209 << Expected << getOpenMPDirectiveName(D: OMPD_interop, Ver: OMPVersion);
17210 return StmtError();
17211 }
17212
17213 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17214 // A depend clause can only appear on the directive if a targetsync
17215 // interop-type is present or the interop-var was initialized with
17216 // the targetsync interop-type.
17217
17218 // If there is any 'init' clause diagnose if there is no 'init' clause with
17219 // interop-type of 'targetsync'. Cases involving other directives cannot be
17220 // diagnosed.
17221 const OMPDependClause *DependClause = nullptr;
17222 bool HasInitClause = false;
17223 bool IsTargetSync = false;
17224 for (const OMPClause *C : Clauses) {
17225 if (IsTargetSync)
17226 break;
17227 if (const auto *InitClause = dyn_cast<OMPInitClause>(Val: C)) {
17228 HasInitClause = true;
17229 if (InitClause->getIsTargetSync())
17230 IsTargetSync = true;
17231 } else if (const auto *DC = dyn_cast<OMPDependClause>(Val: C)) {
17232 DependClause = DC;
17233 }
17234 }
17235 if (DependClause && HasInitClause && !IsTargetSync) {
17236 Diag(Loc: DependClause->getBeginLoc(), DiagID: diag::err_omp_interop_bad_depend_clause);
17237 return StmtError();
17238 }
17239
17240 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17241 // Each interop-var may be specified for at most one action-clause of each
17242 // interop construct.
17243 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
17244 for (OMPClause *C : Clauses) {
17245 OpenMPClauseKind ClauseKind = C->getClauseKind();
17246 std::pair<ValueDecl *, bool> DeclResult;
17247 SourceLocation ELoc;
17248 SourceRange ERange;
17249
17250 if (ClauseKind == OMPC_init) {
17251 auto *E = cast<OMPInitClause>(Val: C)->getInteropVar();
17252 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
17253 } else if (ClauseKind == OMPC_use) {
17254 auto *E = cast<OMPUseClause>(Val: C)->getInteropVar();
17255 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
17256 } else if (ClauseKind == OMPC_destroy) {
17257 auto *E = cast<OMPDestroyClause>(Val: C)->getInteropVar();
17258 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
17259 }
17260
17261 if (DeclResult.first) {
17262 if (!InteropVars.insert(Ptr: DeclResult.first).second) {
17263 Diag(Loc: ELoc, DiagID: diag::err_omp_interop_var_multiple_actions)
17264 << DeclResult.first;
17265 return StmtError();
17266 }
17267 }
17268 }
17269
17270 return OMPInteropDirective::Create(C: getASTContext(), StartLoc, EndLoc,
17271 Clauses);
17272}
17273
17274static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
17275 SourceLocation VarLoc,
17276 OpenMPClauseKind Kind) {
17277 SourceLocation ELoc;
17278 SourceRange ERange;
17279 Expr *RefExpr = InteropVarExpr;
17280 auto Res =
17281 getPrivateItem(S&: SemaRef, RefExpr, ELoc, ERange,
17282 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17283
17284 if (Res.second) {
17285 // It will be analyzed later.
17286 return true;
17287 }
17288
17289 if (!Res.first)
17290 return false;
17291
17292 // Interop variable should be of type omp_interop_t.
17293 bool HasError = false;
17294 QualType InteropType;
17295 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get(Name: "omp_interop_t"),
17296 VarLoc, Sema::LookupOrdinaryName);
17297 if (SemaRef.LookupName(R&: Result, S: SemaRef.getCurScope())) {
17298 NamedDecl *ND = Result.getFoundDecl();
17299 if (const auto *TD = dyn_cast<TypeDecl>(Val: ND)) {
17300 InteropType = QualType(TD->getTypeForDecl(), 0);
17301 } else {
17302 HasError = true;
17303 }
17304 } else {
17305 HasError = true;
17306 }
17307
17308 if (HasError) {
17309 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_implied_type_not_found)
17310 << "omp_interop_t";
17311 return false;
17312 }
17313
17314 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
17315 if (!SemaRef.Context.hasSameType(T1: InteropType, T2: VarType)) {
17316 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_interop_variable_wrong_type);
17317 return false;
17318 }
17319
17320 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17321 // The interop-var passed to init or destroy must be non-const.
17322 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17323 isConstNotMutableType(SemaRef, Type: InteropVarExpr->getType())) {
17324 SemaRef.Diag(Loc: VarLoc, DiagID: diag::err_omp_interop_variable_expected)
17325 << /*non-const*/ 1;
17326 return false;
17327 }
17328 return true;
17329}
17330
17331OMPClause *SemaOpenMP::ActOnOpenMPInitClause(
17332 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
17333 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
17334
17335 if (!isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_init))
17336 return nullptr;
17337
17338 // Check prefer_type values. These foreign-runtime-id values are either
17339 // string literals or constant integral expressions.
17340 for (const Expr *E : InteropInfo.PreferTypes) {
17341 if (E->isValueDependent() || E->isTypeDependent() ||
17342 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
17343 continue;
17344 if (E->isIntegerConstantExpr(Ctx: getASTContext()))
17345 continue;
17346 if (isa<StringLiteral>(Val: E))
17347 continue;
17348 Diag(Loc: E->getExprLoc(), DiagID: diag::err_omp_interop_prefer_type);
17349 return nullptr;
17350 }
17351
17352 return OMPInitClause::Create(C: getASTContext(), InteropVar, InteropInfo,
17353 StartLoc, LParenLoc, VarLoc, EndLoc);
17354}
17355
17356OMPClause *SemaOpenMP::ActOnOpenMPUseClause(Expr *InteropVar,
17357 SourceLocation StartLoc,
17358 SourceLocation LParenLoc,
17359 SourceLocation VarLoc,
17360 SourceLocation EndLoc) {
17361
17362 if (!isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_use))
17363 return nullptr;
17364
17365 return new (getASTContext())
17366 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17367}
17368
17369OMPClause *SemaOpenMP::ActOnOpenMPDestroyClause(Expr *InteropVar,
17370 SourceLocation StartLoc,
17371 SourceLocation LParenLoc,
17372 SourceLocation VarLoc,
17373 SourceLocation EndLoc) {
17374 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
17375 DSAStack->getCurrentDirective() == OMPD_depobj) {
17376 unsigned OMPVersion = getLangOpts().OpenMP;
17377 Diag(Loc: StartLoc, DiagID: diag::err_omp_expected_clause_argument)
17378 << getOpenMPClauseNameForDiag(C: OMPC_destroy)
17379 << getOpenMPDirectiveName(D: OMPD_depobj, Ver: OMPVersion);
17380 return nullptr;
17381 }
17382 if (InteropVar &&
17383 !isValidInteropVariable(SemaRef, InteropVarExpr: InteropVar, VarLoc, Kind: OMPC_destroy))
17384 return nullptr;
17385
17386 return new (getASTContext())
17387 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17388}
17389
17390OMPClause *SemaOpenMP::ActOnOpenMPNovariantsClause(Expr *Condition,
17391 SourceLocation StartLoc,
17392 SourceLocation LParenLoc,
17393 SourceLocation EndLoc) {
17394 Expr *ValExpr = Condition;
17395 Stmt *HelperValStmt = nullptr;
17396 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17397 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17398 !Condition->isInstantiationDependent() &&
17399 !Condition->containsUnexpandedParameterPack()) {
17400 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
17401 if (Val.isInvalid())
17402 return nullptr;
17403
17404 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
17405
17406 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17407 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_novariants,
17408 OpenMPVersion: getLangOpts().OpenMP);
17409 if (CaptureRegion != OMPD_unknown &&
17410 !SemaRef.CurContext->isDependentContext()) {
17411 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17412 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17413 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17414 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
17415 }
17416 }
17417
17418 return new (getASTContext()) OMPNovariantsClause(
17419 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17420}
17421
17422OMPClause *SemaOpenMP::ActOnOpenMPNocontextClause(Expr *Condition,
17423 SourceLocation StartLoc,
17424 SourceLocation LParenLoc,
17425 SourceLocation EndLoc) {
17426 Expr *ValExpr = Condition;
17427 Stmt *HelperValStmt = nullptr;
17428 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17429 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17430 !Condition->isInstantiationDependent() &&
17431 !Condition->containsUnexpandedParameterPack()) {
17432 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
17433 if (Val.isInvalid())
17434 return nullptr;
17435
17436 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
17437
17438 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17439 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_nocontext,
17440 OpenMPVersion: getLangOpts().OpenMP);
17441 if (CaptureRegion != OMPD_unknown &&
17442 !SemaRef.CurContext->isDependentContext()) {
17443 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17444 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17445 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17446 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
17447 }
17448 }
17449
17450 return new (getASTContext()) OMPNocontextClause(
17451 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17452}
17453
17454OMPClause *SemaOpenMP::ActOnOpenMPFilterClause(Expr *ThreadID,
17455 SourceLocation StartLoc,
17456 SourceLocation LParenLoc,
17457 SourceLocation EndLoc) {
17458 Expr *ValExpr = ThreadID;
17459 Stmt *HelperValStmt = nullptr;
17460
17461 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17462 OpenMPDirectiveKind CaptureRegion =
17463 getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_filter, OpenMPVersion: getLangOpts().OpenMP);
17464 if (CaptureRegion != OMPD_unknown &&
17465 !SemaRef.CurContext->isDependentContext()) {
17466 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17467 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17468 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17469 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
17470 }
17471
17472 return new (getASTContext()) OMPFilterClause(
17473 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17474}
17475
17476OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
17477 ArrayRef<Expr *> VarList,
17478 const OMPVarListLocTy &Locs,
17479 OpenMPVarListDataTy &Data) {
17480 SourceLocation StartLoc = Locs.StartLoc;
17481 SourceLocation LParenLoc = Locs.LParenLoc;
17482 SourceLocation EndLoc = Locs.EndLoc;
17483 OMPClause *Res = nullptr;
17484 int ExtraModifier = Data.ExtraModifier;
17485 int OriginalSharingModifier = Data.OriginalSharingModifier;
17486 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
17487 SourceLocation ColonLoc = Data.ColonLoc;
17488 switch (Kind) {
17489 case OMPC_private:
17490 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17491 break;
17492 case OMPC_firstprivate:
17493 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17494 break;
17495 case OMPC_lastprivate:
17496 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
17497 "Unexpected lastprivate modifier.");
17498 Res = ActOnOpenMPLastprivateClause(
17499 VarList, LPKind: static_cast<OpenMPLastprivateModifier>(ExtraModifier),
17500 LPKindLoc: ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17501 break;
17502 case OMPC_shared:
17503 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
17504 break;
17505 case OMPC_reduction:
17506 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
17507 "Unexpected lastprivate modifier.");
17508 Res = ActOnOpenMPReductionClause(
17509 VarList,
17510 Modifiers: OpenMPVarListDataTy::OpenMPReductionClauseModifiers(
17511 ExtraModifier, OriginalSharingModifier),
17512 StartLoc, LParenLoc, ModifierLoc: ExtraModifierLoc, ColonLoc, EndLoc,
17513 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
17514 break;
17515 case OMPC_task_reduction:
17516 Res = ActOnOpenMPTaskReductionClause(
17517 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17518 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
17519 break;
17520 case OMPC_in_reduction:
17521 Res = ActOnOpenMPInReductionClause(
17522 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17523 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
17524 break;
17525 case OMPC_linear:
17526 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
17527 "Unexpected linear modifier.");
17528 Res = ActOnOpenMPLinearClause(
17529 VarList, Step: Data.DepModOrTailExpr, StartLoc, LParenLoc,
17530 LinKind: static_cast<OpenMPLinearClauseKind>(ExtraModifier), LinLoc: ExtraModifierLoc,
17531 ColonLoc, StepModifierLoc: Data.StepModifierLoc, EndLoc);
17532 break;
17533 case OMPC_aligned:
17534 Res = ActOnOpenMPAlignedClause(VarList, Alignment: Data.DepModOrTailExpr, StartLoc,
17535 LParenLoc, ColonLoc, EndLoc);
17536 break;
17537 case OMPC_copyin:
17538 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
17539 break;
17540 case OMPC_copyprivate:
17541 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17542 break;
17543 case OMPC_flush:
17544 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
17545 break;
17546 case OMPC_depend:
17547 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
17548 "Unexpected depend modifier.");
17549 Res = ActOnOpenMPDependClause(
17550 Data: {.DepKind: static_cast<OpenMPDependClauseKind>(ExtraModifier), .DepLoc: ExtraModifierLoc,
17551 .ColonLoc: ColonLoc, .OmpAllMemoryLoc: Data.OmpAllMemoryLoc},
17552 DepModifier: Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17553 break;
17554 case OMPC_map:
17555 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
17556 "Unexpected map modifier.");
17557 Res = ActOnOpenMPMapClause(
17558 IteratorModifier: Data.IteratorExpr, MapTypeModifiers: Data.MapTypeModifiers, MapTypeModifiersLoc: Data.MapTypeModifiersLoc,
17559 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId,
17560 MapType: static_cast<OpenMPMapClauseKind>(ExtraModifier), IsMapTypeImplicit: Data.IsMapTypeImplicit,
17561 MapLoc: ExtraModifierLoc, ColonLoc, VarList, Locs);
17562 break;
17563 case OMPC_to:
17564 Res =
17565 ActOnOpenMPToClause(MotionModifiers: Data.MotionModifiers, MotionModifiersLoc: Data.MotionModifiersLoc,
17566 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec,
17567 MapperId&: Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17568 break;
17569 case OMPC_from:
17570 Res = ActOnOpenMPFromClause(MotionModifiers: Data.MotionModifiers, MotionModifiersLoc: Data.MotionModifiersLoc,
17571 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec,
17572 MapperId&: Data.ReductionOrMapperId, ColonLoc, VarList,
17573 Locs);
17574 break;
17575 case OMPC_use_device_ptr:
17576 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
17577 break;
17578 case OMPC_use_device_addr:
17579 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
17580 break;
17581 case OMPC_is_device_ptr:
17582 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
17583 break;
17584 case OMPC_has_device_addr:
17585 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
17586 break;
17587 case OMPC_allocate: {
17588 OpenMPAllocateClauseModifier Modifier1 = OMPC_ALLOCATE_unknown;
17589 OpenMPAllocateClauseModifier Modifier2 = OMPC_ALLOCATE_unknown;
17590 SourceLocation Modifier1Loc, Modifier2Loc;
17591 if (!Data.AllocClauseModifiers.empty()) {
17592 assert(Data.AllocClauseModifiers.size() <= 2 &&
17593 "More allocate modifiers than expected");
17594 Modifier1 = Data.AllocClauseModifiers[0];
17595 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
17596 if (Data.AllocClauseModifiers.size() == 2) {
17597 Modifier2 = Data.AllocClauseModifiers[1];
17598 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
17599 }
17600 }
17601 Res = ActOnOpenMPAllocateClause(
17602 Allocator: Data.DepModOrTailExpr, Alignment: Data.AllocateAlignment, FirstModifier: Modifier1, FirstModifierLoc: Modifier1Loc,
17603 SecondModifier: Modifier2, SecondModifierLoc: Modifier2Loc, VarList, StartLoc, ColonLoc: LParenLoc, LParenLoc: ColonLoc,
17604 EndLoc);
17605 break;
17606 }
17607 case OMPC_nontemporal:
17608 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
17609 break;
17610 case OMPC_inclusive:
17611 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17612 break;
17613 case OMPC_exclusive:
17614 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17615 break;
17616 case OMPC_affinity:
17617 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
17618 Modifier: Data.DepModOrTailExpr, Locators: VarList);
17619 break;
17620 case OMPC_doacross:
17621 Res = ActOnOpenMPDoacrossClause(
17622 DepType: static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
17623 DepLoc: ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17624 break;
17625 case OMPC_num_teams:
17626 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
17627 break;
17628 case OMPC_thread_limit:
17629 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
17630 break;
17631 case OMPC_if:
17632 case OMPC_depobj:
17633 case OMPC_final:
17634 case OMPC_num_threads:
17635 case OMPC_safelen:
17636 case OMPC_simdlen:
17637 case OMPC_sizes:
17638 case OMPC_allocator:
17639 case OMPC_collapse:
17640 case OMPC_default:
17641 case OMPC_proc_bind:
17642 case OMPC_schedule:
17643 case OMPC_ordered:
17644 case OMPC_nowait:
17645 case OMPC_untied:
17646 case OMPC_mergeable:
17647 case OMPC_threadprivate:
17648 case OMPC_read:
17649 case OMPC_write:
17650 case OMPC_update:
17651 case OMPC_capture:
17652 case OMPC_compare:
17653 case OMPC_seq_cst:
17654 case OMPC_acq_rel:
17655 case OMPC_acquire:
17656 case OMPC_release:
17657 case OMPC_relaxed:
17658 case OMPC_device:
17659 case OMPC_threads:
17660 case OMPC_simd:
17661 case OMPC_priority:
17662 case OMPC_grainsize:
17663 case OMPC_nogroup:
17664 case OMPC_num_tasks:
17665 case OMPC_hint:
17666 case OMPC_dist_schedule:
17667 case OMPC_defaultmap:
17668 case OMPC_unknown:
17669 case OMPC_uniform:
17670 case OMPC_unified_address:
17671 case OMPC_unified_shared_memory:
17672 case OMPC_reverse_offload:
17673 case OMPC_dynamic_allocators:
17674 case OMPC_atomic_default_mem_order:
17675 case OMPC_self_maps:
17676 case OMPC_device_type:
17677 case OMPC_match:
17678 case OMPC_order:
17679 case OMPC_at:
17680 case OMPC_severity:
17681 case OMPC_message:
17682 case OMPC_destroy:
17683 case OMPC_novariants:
17684 case OMPC_nocontext:
17685 case OMPC_detach:
17686 case OMPC_uses_allocators:
17687 case OMPC_when:
17688 case OMPC_bind:
17689 default:
17690 llvm_unreachable("Clause is not allowed.");
17691 }
17692 return Res;
17693}
17694
17695ExprResult SemaOpenMP::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
17696 ExprObjectKind OK,
17697 SourceLocation Loc) {
17698 ExprResult Res = SemaRef.BuildDeclRefExpr(
17699 D: Capture, Ty: Capture->getType().getNonReferenceType(), VK: VK_LValue, Loc);
17700 if (!Res.isUsable())
17701 return ExprError();
17702 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17703 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: Loc, Opc: UO_Deref, InputExpr: Res.get());
17704 if (!Res.isUsable())
17705 return ExprError();
17706 }
17707 if (VK != VK_LValue && Res.get()->isGLValue()) {
17708 Res = SemaRef.DefaultLvalueConversion(E: Res.get());
17709 if (!Res.isUsable())
17710 return ExprError();
17711 }
17712 return Res;
17713}
17714
17715OMPClause *SemaOpenMP::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
17716 SourceLocation StartLoc,
17717 SourceLocation LParenLoc,
17718 SourceLocation EndLoc) {
17719 SmallVector<Expr *, 8> Vars;
17720 SmallVector<Expr *, 8> PrivateCopies;
17721 unsigned OMPVersion = getLangOpts().OpenMP;
17722 bool IsImplicitClause =
17723 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17724 for (Expr *RefExpr : VarList) {
17725 assert(RefExpr && "NULL expr in OpenMP private clause.");
17726 SourceLocation ELoc;
17727 SourceRange ERange;
17728 Expr *SimpleRefExpr = RefExpr;
17729 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
17730 if (Res.second) {
17731 // It will be analyzed later.
17732 Vars.push_back(Elt: RefExpr);
17733 PrivateCopies.push_back(Elt: nullptr);
17734 }
17735 ValueDecl *D = Res.first;
17736 if (!D)
17737 continue;
17738
17739 QualType Type = D->getType();
17740 auto *VD = dyn_cast<VarDecl>(Val: D);
17741
17742 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17743 // A variable that appears in a private clause must not have an incomplete
17744 // type or a reference type.
17745 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
17746 DiagID: diag::err_omp_private_incomplete_type))
17747 continue;
17748 Type = Type.getNonReferenceType();
17749
17750 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17751 // A variable that is privatized must not have a const-qualified type
17752 // unless it is of class type with a mutable member. This restriction does
17753 // not apply to the firstprivate clause.
17754 //
17755 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
17756 // A variable that appears in a private clause must not have a
17757 // const-qualified type unless it is of class type with a mutable member.
17758 if (rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_private, ELoc))
17759 continue;
17760
17761 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17762 // in a Construct]
17763 // Variables with the predetermined data-sharing attributes may not be
17764 // listed in data-sharing attributes clauses, except for the cases
17765 // listed below. For these exceptions only, listing a predetermined
17766 // variable in a data-sharing attribute clause is allowed and overrides
17767 // the variable's predetermined data-sharing attributes.
17768 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17769 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17770 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
17771 << getOpenMPClauseNameForDiag(C: DVar.CKind)
17772 << getOpenMPClauseNameForDiag(C: OMPC_private);
17773 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17774 continue;
17775 }
17776
17777 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17778 // Variably modified types are not supported for tasks.
17779 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
17780 isOpenMPTaskingDirective(Kind: CurrDir)) {
17781 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
17782 << getOpenMPClauseNameForDiag(C: OMPC_private) << Type
17783 << getOpenMPDirectiveName(D: CurrDir, Ver: OMPVersion);
17784 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17785 VarDecl::DeclarationOnly;
17786 Diag(Loc: D->getLocation(),
17787 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17788 << D;
17789 continue;
17790 }
17791
17792 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17793 // A list item cannot appear in both a map clause and a data-sharing
17794 // attribute clause on the same construct
17795 //
17796 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17797 // A list item cannot appear in both a map clause and a data-sharing
17798 // attribute clause on the same construct unless the construct is a
17799 // combined construct.
17800 if ((getLangOpts().OpenMP <= 45 &&
17801 isOpenMPTargetExecutionDirective(DKind: CurrDir)) ||
17802 CurrDir == OMPD_target) {
17803 OpenMPClauseKind ConflictKind;
17804 if (DSAStack->checkMappableExprComponentListsForDecl(
17805 VD, /*CurrentRegionOnly=*/true,
17806 Check: [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
17807 OpenMPClauseKind WhereFoundClauseKind) -> bool {
17808 ConflictKind = WhereFoundClauseKind;
17809 return true;
17810 })) {
17811 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
17812 << getOpenMPClauseNameForDiag(C: OMPC_private)
17813 << getOpenMPClauseNameForDiag(C: ConflictKind)
17814 << getOpenMPDirectiveName(D: CurrDir, Ver: OMPVersion);
17815 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17816 continue;
17817 }
17818 }
17819
17820 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
17821 // A variable of class type (or array thereof) that appears in a private
17822 // clause requires an accessible, unambiguous default constructor for the
17823 // class type.
17824 // Generate helper private variable and initialize it with the default
17825 // value. The address of the original variable is replaced by the address of
17826 // the new private variable in CodeGen. This new variable is not added to
17827 // IdResolver, so the code in the OpenMP region uses original variable for
17828 // proper diagnostics.
17829 Type = Type.getUnqualifiedType();
17830 VarDecl *VDPrivate =
17831 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
17832 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
17833 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
17834 SemaRef.ActOnUninitializedDecl(dcl: VDPrivate);
17835 if (VDPrivate->isInvalidDecl())
17836 continue;
17837 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17838 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(), Loc: ELoc);
17839
17840 DeclRefExpr *Ref = nullptr;
17841 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17842 auto *FD = dyn_cast<FieldDecl>(Val: D);
17843 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17844 if (VD)
17845 Ref = buildDeclRefExpr(S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(),
17846 Loc: RefExpr->getExprLoc());
17847 else
17848 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
17849 }
17850 if (!IsImplicitClause)
17851 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_private, PrivateCopy: Ref);
17852 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
17853 ? RefExpr->IgnoreParens()
17854 : Ref);
17855 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
17856 }
17857
17858 if (Vars.empty())
17859 return nullptr;
17860
17861 return OMPPrivateClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
17862 VL: Vars, PrivateVL: PrivateCopies);
17863}
17864
17865OMPClause *SemaOpenMP::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
17866 SourceLocation StartLoc,
17867 SourceLocation LParenLoc,
17868 SourceLocation EndLoc) {
17869 SmallVector<Expr *, 8> Vars;
17870 SmallVector<Expr *, 8> PrivateCopies;
17871 SmallVector<Expr *, 8> Inits;
17872 SmallVector<Decl *, 4> ExprCaptures;
17873 bool IsImplicitClause =
17874 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17875 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
17876 unsigned OMPVersion = getLangOpts().OpenMP;
17877
17878 for (Expr *RefExpr : VarList) {
17879 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
17880 SourceLocation ELoc;
17881 SourceRange ERange;
17882 Expr *SimpleRefExpr = RefExpr;
17883 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
17884 if (Res.second) {
17885 // It will be analyzed later.
17886 Vars.push_back(Elt: RefExpr);
17887 PrivateCopies.push_back(Elt: nullptr);
17888 Inits.push_back(Elt: nullptr);
17889 }
17890 ValueDecl *D = Res.first;
17891 if (!D)
17892 continue;
17893
17894 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17895 QualType Type = D->getType();
17896 auto *VD = dyn_cast<VarDecl>(Val: D);
17897
17898 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17899 // A variable that appears in a private clause must not have an incomplete
17900 // type or a reference type.
17901 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
17902 DiagID: diag::err_omp_firstprivate_incomplete_type))
17903 continue;
17904 Type = Type.getNonReferenceType();
17905
17906 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
17907 // A variable of class type (or array thereof) that appears in a private
17908 // clause requires an accessible, unambiguous copy constructor for the
17909 // class type.
17910 QualType ElemType =
17911 getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
17912
17913 // If an implicit firstprivate variable found it was checked already.
17914 DSAStackTy::DSAVarData TopDVar;
17915 if (!IsImplicitClause) {
17916 DSAStackTy::DSAVarData DVar =
17917 DSAStack->getTopDSA(D, /*FromParent=*/false);
17918 TopDVar = DVar;
17919 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17920 bool IsConstant = ElemType.isConstant(Ctx: getASTContext());
17921 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
17922 // A list item that specifies a given variable may not appear in more
17923 // than one clause on the same directive, except that a variable may be
17924 // specified in both firstprivate and lastprivate clauses.
17925 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17926 // A list item may appear in a firstprivate or lastprivate clause but not
17927 // both.
17928 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17929 (isOpenMPDistributeDirective(DKind: CurrDir) ||
17930 DVar.CKind != OMPC_lastprivate) &&
17931 DVar.RefExpr) {
17932 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
17933 << getOpenMPClauseNameForDiag(C: DVar.CKind)
17934 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
17935 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17936 continue;
17937 }
17938
17939 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17940 // in a Construct]
17941 // Variables with the predetermined data-sharing attributes may not be
17942 // listed in data-sharing attributes clauses, except for the cases
17943 // listed below. For these exceptions only, listing a predetermined
17944 // variable in a data-sharing attribute clause is allowed and overrides
17945 // the variable's predetermined data-sharing attributes.
17946 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17947 // in a Construct, C/C++, p.2]
17948 // Variables with const-qualified type having no mutable member may be
17949 // listed in a firstprivate clause, even if they are static data members.
17950 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17951 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17952 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
17953 << getOpenMPClauseNameForDiag(C: DVar.CKind)
17954 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
17955 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17956 continue;
17957 }
17958
17959 // OpenMP [2.9.3.4, Restrictions, p.2]
17960 // A list item that is private within a parallel region must not appear
17961 // in a firstprivate clause on a worksharing construct if any of the
17962 // worksharing regions arising from the worksharing construct ever bind
17963 // to any of the parallel regions arising from the parallel construct.
17964 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17965 // A list item that is private within a teams region must not appear in a
17966 // firstprivate clause on a distribute construct if any of the distribute
17967 // regions arising from the distribute construct ever bind to any of the
17968 // teams regions arising from the teams construct.
17969 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17970 // A list item that appears in a reduction clause of a teams construct
17971 // must not appear in a firstprivate clause on a distribute construct if
17972 // any of the distribute regions arising from the distribute construct
17973 // ever bind to any of the teams regions arising from the teams construct.
17974 if ((isOpenMPWorksharingDirective(DKind: CurrDir) ||
17975 isOpenMPDistributeDirective(DKind: CurrDir)) &&
17976 !isOpenMPParallelDirective(DKind: CurrDir) &&
17977 !isOpenMPTeamsDirective(DKind: CurrDir)) {
17978 DVar = DSAStack->getImplicitDSA(D, FromParent: true);
17979 if (DVar.CKind != OMPC_shared &&
17980 (isOpenMPParallelDirective(DKind: DVar.DKind) ||
17981 isOpenMPTeamsDirective(DKind: DVar.DKind) ||
17982 DVar.DKind == OMPD_unknown)) {
17983 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
17984 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate)
17985 << getOpenMPClauseNameForDiag(C: OMPC_shared);
17986 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17987 continue;
17988 }
17989 }
17990 // OpenMP [2.9.3.4, Restrictions, p.3]
17991 // A list item that appears in a reduction clause of a parallel construct
17992 // must not appear in a firstprivate clause on a worksharing or task
17993 // construct if any of the worksharing or task regions arising from the
17994 // worksharing or task construct ever bind to any of the parallel regions
17995 // arising from the parallel construct.
17996 // OpenMP [2.9.3.4, Restrictions, p.4]
17997 // A list item that appears in a reduction clause in worksharing
17998 // construct must not appear in a firstprivate clause in a task construct
17999 // encountered during execution of any of the worksharing regions arising
18000 // from the worksharing construct.
18001 if (isOpenMPTaskingDirective(Kind: CurrDir)) {
18002 DVar = DSAStack->hasInnermostDSA(
18003 D,
18004 CPred: [](OpenMPClauseKind C, bool AppliedToPointee) {
18005 return C == OMPC_reduction && !AppliedToPointee;
18006 },
18007 DPred: [](OpenMPDirectiveKind K) {
18008 return isOpenMPParallelDirective(DKind: K) ||
18009 isOpenMPWorksharingDirective(DKind: K) ||
18010 isOpenMPTeamsDirective(DKind: K);
18011 },
18012 /*FromParent=*/true);
18013 if (DVar.CKind == OMPC_reduction &&
18014 (isOpenMPParallelDirective(DKind: DVar.DKind) ||
18015 isOpenMPWorksharingDirective(DKind: DVar.DKind) ||
18016 isOpenMPTeamsDirective(DKind: DVar.DKind))) {
18017 Diag(Loc: ELoc, DiagID: diag::err_omp_parallel_reduction_in_task_firstprivate)
18018 << getOpenMPDirectiveName(D: DVar.DKind, Ver: OMPVersion);
18019 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
18020 continue;
18021 }
18022 }
18023
18024 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18025 // A list item cannot appear in both a map clause and a data-sharing
18026 // attribute clause on the same construct
18027 //
18028 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18029 // A list item cannot appear in both a map clause and a data-sharing
18030 // attribute clause on the same construct unless the construct is a
18031 // combined construct.
18032 if ((getLangOpts().OpenMP <= 45 &&
18033 isOpenMPTargetExecutionDirective(DKind: CurrDir)) ||
18034 CurrDir == OMPD_target) {
18035 OpenMPClauseKind ConflictKind;
18036 if (DSAStack->checkMappableExprComponentListsForDecl(
18037 VD, /*CurrentRegionOnly=*/true,
18038 Check: [&ConflictKind](
18039 OMPClauseMappableExprCommon::MappableExprComponentListRef,
18040 OpenMPClauseKind WhereFoundClauseKind) {
18041 ConflictKind = WhereFoundClauseKind;
18042 return true;
18043 })) {
18044 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
18045 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate)
18046 << getOpenMPClauseNameForDiag(C: ConflictKind)
18047 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
18048 Ver: OMPVersion);
18049 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
18050 continue;
18051 }
18052 }
18053 }
18054
18055 // Variably modified types are not supported for tasks.
18056 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18057 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18058 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
18059 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate) << Type
18060 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
18061 Ver: OMPVersion);
18062 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18063 VarDecl::DeclarationOnly;
18064 Diag(Loc: D->getLocation(),
18065 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18066 << D;
18067 continue;
18068 }
18069
18070 Type = Type.getUnqualifiedType();
18071 VarDecl *VDPrivate =
18072 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
18073 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
18074 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
18075 // Generate helper private variable and initialize it with the value of the
18076 // original variable. The address of the original variable is replaced by
18077 // the address of the new private variable in the CodeGen. This new variable
18078 // is not added to IdResolver, so the code in the OpenMP region uses
18079 // original variable for proper diagnostics and variable capturing.
18080 Expr *VDInitRefExpr = nullptr;
18081 // For arrays generate initializer for single element and replace it by the
18082 // original array element in CodeGen.
18083 if (Type->isArrayType()) {
18084 VarDecl *VDInit =
18085 buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type: ElemType, Name: D->getName());
18086 VDInitRefExpr = buildDeclRefExpr(S&: SemaRef, D: VDInit, Ty: ElemType, Loc: ELoc);
18087 Expr *Init = SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get();
18088 ElemType = ElemType.getUnqualifiedType();
18089 VarDecl *VDInitTemp = buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(),
18090 Type: ElemType, Name: ".firstprivate.temp");
18091 InitializedEntity Entity =
18092 InitializedEntity::InitializeVariable(Var: VDInitTemp);
18093 InitializationKind Kind = InitializationKind::CreateCopy(InitLoc: ELoc, EqualLoc: ELoc);
18094
18095 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
18096 ExprResult Result = InitSeq.Perform(S&: SemaRef, Entity, Kind, Args: Init);
18097 if (Result.isInvalid())
18098 VDPrivate->setInvalidDecl();
18099 else
18100 VDPrivate->setInit(Result.getAs<Expr>());
18101 // Remove temp variable declaration.
18102 getASTContext().Deallocate(Ptr: VDInitTemp);
18103 } else {
18104 VarDecl *VDInit = buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type,
18105 Name: ".firstprivate.temp");
18106 VDInitRefExpr = buildDeclRefExpr(S&: SemaRef, D: VDInit, Ty: RefExpr->getType(),
18107 Loc: RefExpr->getExprLoc());
18108 SemaRef.AddInitializerToDecl(
18109 dcl: VDPrivate, init: SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get(),
18110 /*DirectInit=*/false);
18111 }
18112 if (VDPrivate->isInvalidDecl()) {
18113 if (IsImplicitClause) {
18114 Diag(Loc: RefExpr->getExprLoc(),
18115 DiagID: diag::note_omp_task_predetermined_firstprivate_here);
18116 }
18117 continue;
18118 }
18119 SemaRef.CurContext->addDecl(D: VDPrivate);
18120 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18121 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(),
18122 Loc: RefExpr->getExprLoc());
18123 DeclRefExpr *Ref = nullptr;
18124 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18125 if (TopDVar.CKind == OMPC_lastprivate) {
18126 Ref = TopDVar.PrivateCopy;
18127 } else {
18128 auto *FD = dyn_cast<FieldDecl>(Val: D);
18129 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18130 if (VD)
18131 Ref =
18132 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: VD->getType().getNonReferenceType(),
18133 Loc: RefExpr->getExprLoc());
18134 else
18135 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
18136 if (VD || !isOpenMPCapturedDecl(D))
18137 ExprCaptures.push_back(Elt: Ref->getDecl());
18138 }
18139 }
18140 if (!IsImplicitClause)
18141 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
18142 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
18143 ? RefExpr->IgnoreParens()
18144 : Ref);
18145 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
18146 Inits.push_back(Elt: VDInitRefExpr);
18147 }
18148
18149 if (Vars.empty())
18150 return nullptr;
18151
18152 return OMPFirstprivateClause::Create(
18153 C: getASTContext(), StartLoc, LParenLoc, EndLoc, VL: Vars, PrivateVL: PrivateCopies, InitVL: Inits,
18154 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures));
18155}
18156
18157OMPClause *SemaOpenMP::ActOnOpenMPLastprivateClause(
18158 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
18159 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18160 SourceLocation LParenLoc, SourceLocation EndLoc) {
18161 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18162 assert(ColonLoc.isValid() && "Colon location must be valid.");
18163 Diag(Loc: LPKindLoc, DiagID: diag::err_omp_unexpected_clause_value)
18164 << getListOfPossibleValues(K: OMPC_lastprivate, /*First=*/0,
18165 /*Last=*/OMPC_LASTPRIVATE_unknown)
18166 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate);
18167 return nullptr;
18168 }
18169
18170 SmallVector<Expr *, 8> Vars;
18171 SmallVector<Expr *, 8> SrcExprs;
18172 SmallVector<Expr *, 8> DstExprs;
18173 SmallVector<Expr *, 8> AssignmentOps;
18174 SmallVector<Decl *, 4> ExprCaptures;
18175 SmallVector<Expr *, 4> ExprPostUpdates;
18176 for (Expr *RefExpr : VarList) {
18177 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18178 SourceLocation ELoc;
18179 SourceRange ERange;
18180 Expr *SimpleRefExpr = RefExpr;
18181 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
18182 if (Res.second) {
18183 // It will be analyzed later.
18184 Vars.push_back(Elt: RefExpr);
18185 SrcExprs.push_back(Elt: nullptr);
18186 DstExprs.push_back(Elt: nullptr);
18187 AssignmentOps.push_back(Elt: nullptr);
18188 }
18189 ValueDecl *D = Res.first;
18190 if (!D)
18191 continue;
18192
18193 QualType Type = D->getType();
18194 auto *VD = dyn_cast<VarDecl>(Val: D);
18195
18196 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18197 // A variable that appears in a lastprivate clause must not have an
18198 // incomplete type or a reference type.
18199 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
18200 DiagID: diag::err_omp_lastprivate_incomplete_type))
18201 continue;
18202 Type = Type.getNonReferenceType();
18203
18204 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18205 // A variable that is privatized must not have a const-qualified type
18206 // unless it is of class type with a mutable member. This restriction does
18207 // not apply to the firstprivate clause.
18208 //
18209 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18210 // A variable that appears in a lastprivate clause must not have a
18211 // const-qualified type unless it is of class type with a mutable member.
18212 if (rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_lastprivate, ELoc))
18213 continue;
18214
18215 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18216 // A list item that appears in a lastprivate clause with the conditional
18217 // modifier must be a scalar variable.
18218 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18219 Diag(Loc: ELoc, DiagID: diag::err_omp_lastprivate_conditional_non_scalar);
18220 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18221 VarDecl::DeclarationOnly;
18222 Diag(Loc: D->getLocation(),
18223 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18224 << D;
18225 continue;
18226 }
18227
18228 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18229 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18230 // in a Construct]
18231 // Variables with the predetermined data-sharing attributes may not be
18232 // listed in data-sharing attributes clauses, except for the cases
18233 // listed below.
18234 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18235 // A list item may appear in a firstprivate or lastprivate clause but not
18236 // both.
18237 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18238 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18239 (isOpenMPDistributeDirective(DKind: CurrDir) ||
18240 DVar.CKind != OMPC_firstprivate) &&
18241 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
18242 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
18243 << getOpenMPClauseNameForDiag(C: DVar.CKind)
18244 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate);
18245 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
18246 continue;
18247 }
18248
18249 // OpenMP [2.14.3.5, Restrictions, p.2]
18250 // A list item that is private within a parallel region, or that appears in
18251 // the reduction clause of a parallel construct, must not appear in a
18252 // lastprivate clause on a worksharing construct if any of the corresponding
18253 // worksharing regions ever binds to any of the corresponding parallel
18254 // regions.
18255 DSAStackTy::DSAVarData TopDVar = DVar;
18256 if (isOpenMPWorksharingDirective(DKind: CurrDir) &&
18257 !isOpenMPParallelDirective(DKind: CurrDir) &&
18258 !isOpenMPTeamsDirective(DKind: CurrDir)) {
18259 DVar = DSAStack->getImplicitDSA(D, FromParent: true);
18260 if (DVar.CKind != OMPC_shared) {
18261 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
18262 << getOpenMPClauseNameForDiag(C: OMPC_lastprivate)
18263 << getOpenMPClauseNameForDiag(C: OMPC_shared);
18264 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
18265 continue;
18266 }
18267 }
18268
18269 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18270 // A variable of class type (or array thereof) that appears in a
18271 // lastprivate clause requires an accessible, unambiguous default
18272 // constructor for the class type, unless the list item is also specified
18273 // in a firstprivate clause.
18274 // A variable of class type (or array thereof) that appears in a
18275 // lastprivate clause requires an accessible, unambiguous copy assignment
18276 // operator for the class type.
18277 Type = getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
18278 VarDecl *SrcVD = buildVarDecl(SemaRef, Loc: ERange.getBegin(),
18279 Type: Type.getUnqualifiedType(), Name: ".lastprivate.src",
18280 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
18281 DeclRefExpr *PseudoSrcExpr =
18282 buildDeclRefExpr(S&: SemaRef, D: SrcVD, Ty: Type.getUnqualifiedType(), Loc: ELoc);
18283 VarDecl *DstVD =
18284 buildVarDecl(SemaRef, Loc: ERange.getBegin(), Type, Name: ".lastprivate.dst",
18285 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
18286 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: Type, Loc: ELoc);
18287 // For arrays generate assignment operation for single element and replace
18288 // it by the original array element in CodeGen.
18289 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, OpLoc: ELoc, Opc: BO_Assign,
18290 LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
18291 if (AssignmentOp.isInvalid())
18292 continue;
18293 AssignmentOp = SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: ELoc,
18294 /*DiscardedValue=*/false);
18295 if (AssignmentOp.isInvalid())
18296 continue;
18297
18298 DeclRefExpr *Ref = nullptr;
18299 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18300 if (TopDVar.CKind == OMPC_firstprivate) {
18301 Ref = TopDVar.PrivateCopy;
18302 } else {
18303 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
18304 if (!isOpenMPCapturedDecl(D))
18305 ExprCaptures.push_back(Elt: Ref->getDecl());
18306 }
18307 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18308 (!isOpenMPCapturedDecl(D) &&
18309 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
18310 ExprResult RefRes = SemaRef.DefaultLvalueConversion(E: Ref);
18311 if (!RefRes.isUsable())
18312 continue;
18313 ExprResult PostUpdateRes =
18314 SemaRef.BuildBinOp(DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign,
18315 LHSExpr: SimpleRefExpr, RHSExpr: RefRes.get());
18316 if (!PostUpdateRes.isUsable())
18317 continue;
18318 ExprPostUpdates.push_back(
18319 Elt: SemaRef.IgnoredValueConversions(E: PostUpdateRes.get()).get());
18320 }
18321 }
18322 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_lastprivate, PrivateCopy: Ref);
18323 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
18324 ? RefExpr->IgnoreParens()
18325 : Ref);
18326 SrcExprs.push_back(Elt: PseudoSrcExpr);
18327 DstExprs.push_back(Elt: PseudoDstExpr);
18328 AssignmentOps.push_back(Elt: AssignmentOp.get());
18329 }
18330
18331 if (Vars.empty())
18332 return nullptr;
18333
18334 return OMPLastprivateClause::Create(
18335 C: getASTContext(), StartLoc, LParenLoc, EndLoc, VL: Vars, SrcExprs, DstExprs,
18336 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
18337 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures),
18338 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: ExprPostUpdates));
18339}
18340
18341OMPClause *SemaOpenMP::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
18342 SourceLocation StartLoc,
18343 SourceLocation LParenLoc,
18344 SourceLocation EndLoc) {
18345 SmallVector<Expr *, 8> Vars;
18346 for (Expr *RefExpr : VarList) {
18347 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18348 SourceLocation ELoc;
18349 SourceRange ERange;
18350 Expr *SimpleRefExpr = RefExpr;
18351 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
18352 if (Res.second) {
18353 // It will be analyzed later.
18354 Vars.push_back(Elt: RefExpr);
18355 }
18356 ValueDecl *D = Res.first;
18357 if (!D)
18358 continue;
18359
18360 auto *VD = dyn_cast<VarDecl>(Val: D);
18361 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18362 // in a Construct]
18363 // Variables with the predetermined data-sharing attributes may not be
18364 // listed in data-sharing attributes clauses, except for the cases
18365 // listed below. For these exceptions only, listing a predetermined
18366 // variable in a data-sharing attribute clause is allowed and overrides
18367 // the variable's predetermined data-sharing attributes.
18368 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18369 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18370 DVar.RefExpr) {
18371 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
18372 << getOpenMPClauseNameForDiag(C: DVar.CKind)
18373 << getOpenMPClauseNameForDiag(C: OMPC_shared);
18374 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
18375 continue;
18376 }
18377
18378 DeclRefExpr *Ref = nullptr;
18379 if (!VD && isOpenMPCapturedDecl(D) &&
18380 !SemaRef.CurContext->isDependentContext())
18381 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
18382 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_shared, PrivateCopy: Ref);
18383 Vars.push_back(Elt: (VD || !Ref || SemaRef.CurContext->isDependentContext())
18384 ? RefExpr->IgnoreParens()
18385 : Ref);
18386 }
18387
18388 if (Vars.empty())
18389 return nullptr;
18390
18391 return OMPSharedClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
18392 VL: Vars);
18393}
18394
18395namespace {
18396class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
18397 DSAStackTy *Stack;
18398
18399public:
18400 bool VisitDeclRefExpr(DeclRefExpr *E) {
18401 if (auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
18402 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D: VD, /*FromParent=*/false);
18403 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
18404 return false;
18405 if (DVar.CKind != OMPC_unknown)
18406 return true;
18407 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
18408 D: VD,
18409 CPred: [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
18410 return isOpenMPPrivate(Kind: C) && !AppliedToPointee;
18411 },
18412 DPred: [](OpenMPDirectiveKind) { return true; },
18413 /*FromParent=*/true);
18414 return DVarPrivate.CKind != OMPC_unknown;
18415 }
18416 return false;
18417 }
18418 bool VisitStmt(Stmt *S) {
18419 for (Stmt *Child : S->children()) {
18420 if (Child && Visit(S: Child))
18421 return true;
18422 }
18423 return false;
18424 }
18425 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
18426};
18427} // namespace
18428
18429namespace {
18430// Transform MemberExpression for specified FieldDecl of current class to
18431// DeclRefExpr to specified OMPCapturedExprDecl.
18432class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
18433 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
18434 ValueDecl *Field = nullptr;
18435 DeclRefExpr *CapturedExpr = nullptr;
18436
18437public:
18438 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18439 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
18440
18441 ExprResult TransformMemberExpr(MemberExpr *E) {
18442 if (isa<CXXThisExpr>(Val: E->getBase()->IgnoreParenImpCasts()) &&
18443 E->getMemberDecl() == Field) {
18444 CapturedExpr = buildCapture(S&: SemaRef, D: Field, CaptureExpr: E, /*WithInit=*/false);
18445 return CapturedExpr;
18446 }
18447 return BaseTransform::TransformMemberExpr(E);
18448 }
18449 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
18450};
18451} // namespace
18452
18453template <typename T, typename U>
18454static T filterLookupForUDReductionAndMapper(
18455 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
18456 for (U &Set : Lookups) {
18457 for (auto *D : Set) {
18458 if (T Res = Gen(cast<ValueDecl>(D)))
18459 return Res;
18460 }
18461 }
18462 return T();
18463}
18464
18465static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
18466 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
18467
18468 for (auto *RD : D->redecls()) {
18469 // Don't bother with extra checks if we already know this one isn't visible.
18470 if (RD == D)
18471 continue;
18472
18473 auto ND = cast<NamedDecl>(Val: RD);
18474 if (LookupResult::isVisible(SemaRef, D: ND))
18475 return ND;
18476 }
18477
18478 return nullptr;
18479}
18480
18481static void
18482argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
18483 SourceLocation Loc, QualType Ty,
18484 SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
18485 // Find all of the associated namespaces and classes based on the
18486 // arguments we have.
18487 Sema::AssociatedNamespaceSet AssociatedNamespaces;
18488 Sema::AssociatedClassSet AssociatedClasses;
18489 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
18490 SemaRef.FindAssociatedClassesAndNamespaces(InstantiationLoc: Loc, Args: &OVE, AssociatedNamespaces,
18491 AssociatedClasses);
18492
18493 // C++ [basic.lookup.argdep]p3:
18494 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18495 // and let Y be the lookup set produced by argument dependent
18496 // lookup (defined as follows). If X contains [...] then Y is
18497 // empty. Otherwise Y is the set of declarations found in the
18498 // namespaces associated with the argument types as described
18499 // below. The set of declarations found by the lookup of the name
18500 // is the union of X and Y.
18501 //
18502 // Here, we compute Y and add its members to the overloaded
18503 // candidate set.
18504 for (auto *NS : AssociatedNamespaces) {
18505 // When considering an associated namespace, the lookup is the
18506 // same as the lookup performed when the associated namespace is
18507 // used as a qualifier (3.4.3.2) except that:
18508 //
18509 // -- Any using-directives in the associated namespace are
18510 // ignored.
18511 //
18512 // -- Any namespace-scope friend functions declared in
18513 // associated classes are visible within their respective
18514 // namespaces even if they are not visible during an ordinary
18515 // lookup (11.4).
18516 DeclContext::lookup_result R = NS->lookup(Name: Id.getName());
18517 for (auto *D : R) {
18518 auto *Underlying = D;
18519 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
18520 Underlying = USD->getTargetDecl();
18521
18522 if (!isa<OMPDeclareReductionDecl>(Val: Underlying) &&
18523 !isa<OMPDeclareMapperDecl>(Val: Underlying))
18524 continue;
18525
18526 if (!SemaRef.isVisible(D)) {
18527 D = findAcceptableDecl(SemaRef, D);
18528 if (!D)
18529 continue;
18530 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
18531 Underlying = USD->getTargetDecl();
18532 }
18533 Lookups.emplace_back();
18534 Lookups.back().addDecl(D: Underlying);
18535 }
18536 }
18537}
18538
18539static ExprResult
18540buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
18541 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
18542 const DeclarationNameInfo &ReductionId, QualType Ty,
18543 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
18544 if (ReductionIdScopeSpec.isInvalid())
18545 return ExprError();
18546 SmallVector<UnresolvedSet<8>, 4> Lookups;
18547 if (S) {
18548 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18549 Lookup.suppressDiagnostics();
18550 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &ReductionIdScopeSpec,
18551 /*ObjectType=*/QualType())) {
18552 NamedDecl *D = Lookup.getRepresentativeDecl();
18553 do {
18554 S = S->getParent();
18555 } while (S && !S->isDeclScope(D));
18556 if (S)
18557 S = S->getParent();
18558 Lookups.emplace_back();
18559 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
18560 Lookup.clear();
18561 }
18562 } else if (auto *ULE =
18563 cast_or_null<UnresolvedLookupExpr>(Val: UnresolvedReduction)) {
18564 Lookups.push_back(Elt: UnresolvedSet<8>());
18565 Decl *PrevD = nullptr;
18566 for (NamedDecl *D : ULE->decls()) {
18567 if (D == PrevD)
18568 Lookups.push_back(Elt: UnresolvedSet<8>());
18569 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Val: D))
18570 Lookups.back().addDecl(D: DRD);
18571 PrevD = D;
18572 }
18573 }
18574 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
18575 Ty->isInstantiationDependentType() ||
18576 Ty->containsUnexpandedParameterPack() ||
18577 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
18578 return !D->isInvalidDecl() &&
18579 (D->getType()->isDependentType() ||
18580 D->getType()->isInstantiationDependentType() ||
18581 D->getType()->containsUnexpandedParameterPack());
18582 })) {
18583 UnresolvedSet<8> ResSet;
18584 for (const UnresolvedSet<8> &Set : Lookups) {
18585 if (Set.empty())
18586 continue;
18587 ResSet.append(I: Set.begin(), E: Set.end());
18588 // The last item marks the end of all declarations at the specified scope.
18589 ResSet.addDecl(D: Set[Set.size() - 1]);
18590 }
18591 return UnresolvedLookupExpr::Create(
18592 Context: SemaRef.Context, /*NamingClass=*/nullptr,
18593 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: SemaRef.Context), NameInfo: ReductionId,
18594 /*ADL=*/RequiresADL: true, Begin: ResSet.begin(), End: ResSet.end(), /*KnownDependent=*/false,
18595 /*KnownInstantiationDependent=*/false);
18596 }
18597 // Lookup inside the classes.
18598 // C++ [over.match.oper]p3:
18599 // For a unary operator @ with an operand of a type whose
18600 // cv-unqualified version is T1, and for a binary operator @ with
18601 // a left operand of a type whose cv-unqualified version is T1 and
18602 // a right operand of a type whose cv-unqualified version is T2,
18603 // three sets of candidate functions, designated member
18604 // candidates, non-member candidates and built-in candidates, are
18605 // constructed as follows:
18606 // -- If T1 is a complete class type or a class currently being
18607 // defined, the set of member candidates is the result of the
18608 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
18609 // the set of member candidates is empty.
18610 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18611 Lookup.suppressDiagnostics();
18612 if (const auto *TyRec = Ty->getAs<RecordType>()) {
18613 // Complete the type if it can be completed.
18614 // If the type is neither complete nor being defined, bail out now.
18615 if (SemaRef.isCompleteType(Loc, T: Ty) || TyRec->isBeingDefined() ||
18616 TyRec->getDecl()->getDefinition()) {
18617 Lookup.clear();
18618 SemaRef.LookupQualifiedName(R&: Lookup, LookupCtx: TyRec->getDecl());
18619 if (Lookup.empty()) {
18620 Lookups.emplace_back();
18621 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
18622 }
18623 }
18624 }
18625 // Perform ADL.
18626 if (SemaRef.getLangOpts().CPlusPlus)
18627 argumentDependentLookup(SemaRef, Id: ReductionId, Loc, Ty, Lookups);
18628 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18629 Lookups, Gen: [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
18630 if (!D->isInvalidDecl() &&
18631 SemaRef.Context.hasSameType(T1: D->getType(), T2: Ty))
18632 return D;
18633 return nullptr;
18634 }))
18635 return SemaRef.BuildDeclRefExpr(D: VD, Ty: VD->getType().getNonReferenceType(),
18636 VK: VK_LValue, Loc);
18637 if (SemaRef.getLangOpts().CPlusPlus) {
18638 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18639 Lookups, Gen: [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
18640 if (!D->isInvalidDecl() &&
18641 SemaRef.IsDerivedFrom(Loc, Derived: Ty, Base: D->getType()) &&
18642 !Ty.isMoreQualifiedThan(other: D->getType(),
18643 Ctx: SemaRef.getASTContext()))
18644 return D;
18645 return nullptr;
18646 })) {
18647 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18648 /*DetectVirtual=*/false);
18649 if (SemaRef.IsDerivedFrom(Loc, Derived: Ty, Base: VD->getType(), Paths)) {
18650 if (!Paths.isAmbiguous(BaseType: SemaRef.Context.getCanonicalType(
18651 T: VD->getType().getUnqualifiedType()))) {
18652 if (SemaRef.CheckBaseClassAccess(
18653 AccessLoc: Loc, Base: VD->getType(), Derived: Ty, Path: Paths.front(),
18654 /*DiagID=*/0) != Sema::AR_inaccessible) {
18655 SemaRef.BuildBasePathArray(Paths, BasePath);
18656 return SemaRef.BuildDeclRefExpr(
18657 D: VD, Ty: VD->getType().getNonReferenceType(), VK: VK_LValue, Loc);
18658 }
18659 }
18660 }
18661 }
18662 }
18663 if (ReductionIdScopeSpec.isSet()) {
18664 SemaRef.Diag(Loc, DiagID: diag::err_omp_not_resolved_reduction_identifier)
18665 << Ty << Range;
18666 return ExprError();
18667 }
18668 return ExprEmpty();
18669}
18670
18671namespace {
18672/// Data for the reduction-based clauses.
18673struct ReductionData {
18674 /// List of original reduction items.
18675 SmallVector<Expr *, 8> Vars;
18676 /// List of private copies of the reduction items.
18677 SmallVector<Expr *, 8> Privates;
18678 /// LHS expressions for the reduction_op expressions.
18679 SmallVector<Expr *, 8> LHSs;
18680 /// RHS expressions for the reduction_op expressions.
18681 SmallVector<Expr *, 8> RHSs;
18682 /// Reduction operation expression.
18683 SmallVector<Expr *, 8> ReductionOps;
18684 /// inscan copy operation expressions.
18685 SmallVector<Expr *, 8> InscanCopyOps;
18686 /// inscan copy temp array expressions for prefix sums.
18687 SmallVector<Expr *, 8> InscanCopyArrayTemps;
18688 /// inscan copy temp array element expressions for prefix sums.
18689 SmallVector<Expr *, 8> InscanCopyArrayElems;
18690 /// Taskgroup descriptors for the corresponding reduction items in
18691 /// in_reduction clauses.
18692 SmallVector<Expr *, 8> TaskgroupDescriptors;
18693 /// List of captures for clause.
18694 SmallVector<Decl *, 4> ExprCaptures;
18695 /// List of postupdate expressions.
18696 SmallVector<Expr *, 4> ExprPostUpdates;
18697 /// Reduction modifier.
18698 unsigned RedModifier = 0;
18699 /// Original modifier.
18700 unsigned OrigSharingModifier = 0;
18701 /// Private Variable Reduction
18702 SmallVector<bool, 8> IsPrivateVarReduction;
18703 ReductionData() = delete;
18704 /// Reserves required memory for the reduction data.
18705 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
18706 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
18707 Vars.reserve(N: Size);
18708 Privates.reserve(N: Size);
18709 LHSs.reserve(N: Size);
18710 RHSs.reserve(N: Size);
18711 ReductionOps.reserve(N: Size);
18712 IsPrivateVarReduction.reserve(N: Size);
18713 if (RedModifier == OMPC_REDUCTION_inscan) {
18714 InscanCopyOps.reserve(N: Size);
18715 InscanCopyArrayTemps.reserve(N: Size);
18716 InscanCopyArrayElems.reserve(N: Size);
18717 }
18718 TaskgroupDescriptors.reserve(N: Size);
18719 ExprCaptures.reserve(N: Size);
18720 ExprPostUpdates.reserve(N: Size);
18721 }
18722 /// Stores reduction item and reduction operation only (required for dependent
18723 /// reduction item).
18724 void push(Expr *Item, Expr *ReductionOp) {
18725 Vars.emplace_back(Args&: Item);
18726 Privates.emplace_back(Args: nullptr);
18727 LHSs.emplace_back(Args: nullptr);
18728 RHSs.emplace_back(Args: nullptr);
18729 ReductionOps.emplace_back(Args&: ReductionOp);
18730 IsPrivateVarReduction.emplace_back(Args: false);
18731 TaskgroupDescriptors.emplace_back(Args: nullptr);
18732 if (RedModifier == OMPC_REDUCTION_inscan) {
18733 InscanCopyOps.push_back(Elt: nullptr);
18734 InscanCopyArrayTemps.push_back(Elt: nullptr);
18735 InscanCopyArrayElems.push_back(Elt: nullptr);
18736 }
18737 }
18738 /// Stores reduction data.
18739 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
18740 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
18741 Expr *CopyArrayElem, bool IsPrivate) {
18742 Vars.emplace_back(Args&: Item);
18743 Privates.emplace_back(Args&: Private);
18744 LHSs.emplace_back(Args&: LHS);
18745 RHSs.emplace_back(Args&: RHS);
18746 ReductionOps.emplace_back(Args&: ReductionOp);
18747 TaskgroupDescriptors.emplace_back(Args&: TaskgroupDescriptor);
18748 if (RedModifier == OMPC_REDUCTION_inscan) {
18749 InscanCopyOps.push_back(Elt: CopyOp);
18750 InscanCopyArrayTemps.push_back(Elt: CopyArrayTemp);
18751 InscanCopyArrayElems.push_back(Elt: CopyArrayElem);
18752 } else {
18753 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
18754 CopyArrayElem == nullptr &&
18755 "Copy operation must be used for inscan reductions only.");
18756 }
18757 IsPrivateVarReduction.emplace_back(Args&: IsPrivate);
18758 }
18759};
18760} // namespace
18761
18762static bool checkOMPArraySectionConstantForReduction(
18763 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
18764 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
18765 const Expr *Length = OASE->getLength();
18766 if (Length == nullptr) {
18767 // For array sections of the form [1:] or [:], we would need to analyze
18768 // the lower bound...
18769 if (OASE->getColonLocFirst().isValid())
18770 return false;
18771
18772 // This is an array subscript which has implicit length 1!
18773 SingleElement = true;
18774 ArraySizes.push_back(Elt: llvm::APSInt::get(X: 1));
18775 } else {
18776 Expr::EvalResult Result;
18777 if (!Length->EvaluateAsInt(Result, Ctx: Context))
18778 return false;
18779
18780 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18781 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18782 ArraySizes.push_back(Elt: ConstantLengthValue);
18783 }
18784
18785 // Get the base of this array section and walk up from there.
18786 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
18787
18788 // We require length = 1 for all array sections except the right-most to
18789 // guarantee that the memory region is contiguous and has no holes in it.
18790 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Val: Base)) {
18791 Length = TempOASE->getLength();
18792 if (Length == nullptr) {
18793 // For array sections of the form [1:] or [:], we would need to analyze
18794 // the lower bound...
18795 if (OASE->getColonLocFirst().isValid())
18796 return false;
18797
18798 // This is an array subscript which has implicit length 1!
18799 llvm::APSInt ConstantOne = llvm::APSInt::get(X: 1);
18800 ArraySizes.push_back(Elt: ConstantOne);
18801 } else {
18802 Expr::EvalResult Result;
18803 if (!Length->EvaluateAsInt(Result, Ctx: Context))
18804 return false;
18805
18806 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18807 if (ConstantLengthValue.getSExtValue() != 1)
18808 return false;
18809
18810 ArraySizes.push_back(Elt: ConstantLengthValue);
18811 }
18812 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18813 }
18814
18815 // If we have a single element, we don't need to add the implicit lengths.
18816 if (!SingleElement) {
18817 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base)) {
18818 // Has implicit length 1!
18819 llvm::APSInt ConstantOne = llvm::APSInt::get(X: 1);
18820 ArraySizes.push_back(Elt: ConstantOne);
18821 Base = TempASE->getBase()->IgnoreParenImpCasts();
18822 }
18823 }
18824
18825 // This array section can be privatized as a single value or as a constant
18826 // sized array.
18827 return true;
18828}
18829
18830static BinaryOperatorKind
18831getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
18832 if (BOK == BO_Add)
18833 return BO_AddAssign;
18834 if (BOK == BO_Mul)
18835 return BO_MulAssign;
18836 if (BOK == BO_And)
18837 return BO_AndAssign;
18838 if (BOK == BO_Or)
18839 return BO_OrAssign;
18840 if (BOK == BO_Xor)
18841 return BO_XorAssign;
18842 return BOK;
18843}
18844
18845static bool actOnOMPReductionKindClause(
18846 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
18847 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18848 SourceLocation ColonLoc, SourceLocation EndLoc,
18849 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18850 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
18851 DeclarationName DN = ReductionId.getName();
18852 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
18853 BinaryOperatorKind BOK = BO_Comma;
18854
18855 ASTContext &Context = S.Context;
18856 // OpenMP [2.14.3.6, reduction clause]
18857 // C
18858 // reduction-identifier is either an identifier or one of the following
18859 // operators: +, -, *, &, |, ^, && and ||
18860 // C++
18861 // reduction-identifier is either an id-expression or one of the following
18862 // operators: +, -, *, &, |, ^, && and ||
18863 switch (OOK) {
18864 case OO_Plus:
18865 BOK = BO_Add;
18866 break;
18867 case OO_Minus:
18868 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
18869 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
18870 // reduction identifier.
18871 if (S.LangOpts.OpenMP > 52)
18872 BOK = BO_Comma;
18873 else
18874 BOK = BO_Add;
18875 break;
18876 case OO_Star:
18877 BOK = BO_Mul;
18878 break;
18879 case OO_Amp:
18880 BOK = BO_And;
18881 break;
18882 case OO_Pipe:
18883 BOK = BO_Or;
18884 break;
18885 case OO_Caret:
18886 BOK = BO_Xor;
18887 break;
18888 case OO_AmpAmp:
18889 BOK = BO_LAnd;
18890 break;
18891 case OO_PipePipe:
18892 BOK = BO_LOr;
18893 break;
18894 case OO_New:
18895 case OO_Delete:
18896 case OO_Array_New:
18897 case OO_Array_Delete:
18898 case OO_Slash:
18899 case OO_Percent:
18900 case OO_Tilde:
18901 case OO_Exclaim:
18902 case OO_Equal:
18903 case OO_Less:
18904 case OO_Greater:
18905 case OO_LessEqual:
18906 case OO_GreaterEqual:
18907 case OO_PlusEqual:
18908 case OO_MinusEqual:
18909 case OO_StarEqual:
18910 case OO_SlashEqual:
18911 case OO_PercentEqual:
18912 case OO_CaretEqual:
18913 case OO_AmpEqual:
18914 case OO_PipeEqual:
18915 case OO_LessLess:
18916 case OO_GreaterGreater:
18917 case OO_LessLessEqual:
18918 case OO_GreaterGreaterEqual:
18919 case OO_EqualEqual:
18920 case OO_ExclaimEqual:
18921 case OO_Spaceship:
18922 case OO_PlusPlus:
18923 case OO_MinusMinus:
18924 case OO_Comma:
18925 case OO_ArrowStar:
18926 case OO_Arrow:
18927 case OO_Call:
18928 case OO_Subscript:
18929 case OO_Conditional:
18930 case OO_Coawait:
18931 case NUM_OVERLOADED_OPERATORS:
18932 llvm_unreachable("Unexpected reduction identifier");
18933 case OO_None:
18934 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
18935 if (II->isStr(Str: "max"))
18936 BOK = BO_GT;
18937 else if (II->isStr(Str: "min"))
18938 BOK = BO_LT;
18939 }
18940 break;
18941 }
18942
18943 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
18944 // A reduction clause with the minus (-) operator was deprecated
18945 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
18946 S.Diag(Loc: ReductionId.getLoc(), DiagID: diag::warn_omp_minus_in_reduction_deprecated);
18947
18948 SourceRange ReductionIdRange;
18949 if (ReductionIdScopeSpec.isValid())
18950 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
18951 else
18952 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
18953 ReductionIdRange.setEnd(ReductionId.getEndLoc());
18954
18955 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18956 bool FirstIter = true;
18957 for (Expr *RefExpr : VarList) {
18958 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
18959 // OpenMP [2.1, C/C++]
18960 // A list item is a variable or array section, subject to the restrictions
18961 // specified in Section 2.4 on page 42 and in each of the sections
18962 // describing clauses and directives for which a list appears.
18963 // OpenMP [2.14.3.3, Restrictions, p.1]
18964 // A variable that is part of another variable (as an array or
18965 // structure element) cannot appear in a private clause.
18966 if (!FirstIter && IR != ER)
18967 ++IR;
18968 FirstIter = false;
18969 SourceLocation ELoc;
18970 SourceRange ERange;
18971 bool IsPrivate = false;
18972 Expr *SimpleRefExpr = RefExpr;
18973 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
18974 /*AllowArraySection=*/true);
18975 if (Res.second) {
18976 // Try to find 'declare reduction' corresponding construct before using
18977 // builtin/overloaded operators.
18978 QualType Type = Context.DependentTy;
18979 CXXCastPath BasePath;
18980 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18981 SemaRef&: S, Loc: ELoc, Range: ERange, S: Stack->getCurScope(), ReductionIdScopeSpec,
18982 ReductionId, Ty: Type, BasePath, UnresolvedReduction: IR == ER ? nullptr : *IR);
18983 Expr *ReductionOp = nullptr;
18984 if (S.CurContext->isDependentContext() &&
18985 (DeclareReductionRef.isUnset() ||
18986 isa<UnresolvedLookupExpr>(Val: DeclareReductionRef.get())))
18987 ReductionOp = DeclareReductionRef.get();
18988 // It will be analyzed later.
18989 RD.push(Item: RefExpr, ReductionOp);
18990 }
18991 ValueDecl *D = Res.first;
18992 if (!D)
18993 continue;
18994
18995 Expr *TaskgroupDescriptor = nullptr;
18996 QualType Type;
18997 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: RefExpr->IgnoreParens());
18998 auto *OASE = dyn_cast<ArraySectionExpr>(Val: RefExpr->IgnoreParens());
18999 if (ASE) {
19000 Type = ASE->getType().getNonReferenceType();
19001 } else if (OASE) {
19002 QualType BaseType =
19003 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
19004 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19005 Type = ATy->getElementType();
19006 else
19007 Type = BaseType->getPointeeType();
19008 Type = Type.getNonReferenceType();
19009 } else {
19010 Type = Context.getBaseElementType(QT: D->getType().getNonReferenceType());
19011 }
19012 auto *VD = dyn_cast<VarDecl>(Val: D);
19013
19014 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19015 // A variable that appears in a private clause must not have an incomplete
19016 // type or a reference type.
19017 if (S.RequireCompleteType(Loc: ELoc, T: D->getType(),
19018 DiagID: diag::err_omp_reduction_incomplete_type))
19019 continue;
19020 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19021 // A list item that appears in a reduction clause must not be
19022 // const-qualified.
19023 if (rejectConstNotMutableType(SemaRef&: S, D, Type, CKind: ClauseKind, ELoc,
19024 /*AcceptIfMutable=*/false, ListItemNotVar: ASE || OASE))
19025 continue;
19026
19027 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
19028 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19029 // If a list-item is a reference type then it must bind to the same object
19030 // for all threads of the team.
19031 if (!ASE && !OASE) {
19032 if (VD) {
19033 VarDecl *VDDef = VD->getDefinition();
19034 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
19035 DSARefChecker Check(Stack);
19036 if (Check.Visit(S: VDDef->getInit())) {
19037 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_ref_type_arg)
19038 << getOpenMPClauseNameForDiag(C: ClauseKind) << ERange;
19039 S.Diag(Loc: VDDef->getLocation(), DiagID: diag::note_defined_here) << VDDef;
19040 continue;
19041 }
19042 }
19043 }
19044
19045 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19046 // in a Construct]
19047 // Variables with the predetermined data-sharing attributes may not be
19048 // listed in data-sharing attributes clauses, except for the cases
19049 // listed below. For these exceptions only, listing a predetermined
19050 // variable in a data-sharing attribute clause is allowed and overrides
19051 // the variable's predetermined data-sharing attributes.
19052 // OpenMP [2.14.3.6, Restrictions, p.3]
19053 // Any number of reduction clauses can be specified on the directive,
19054 // but a list item can appear only once in the reduction clauses for that
19055 // directive.
19056 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19057 if (DVar.CKind == OMPC_reduction) {
19058 S.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced)
19059 << getOpenMPClauseNameForDiag(C: ClauseKind);
19060 if (DVar.RefExpr)
19061 S.Diag(Loc: DVar.RefExpr->getExprLoc(), DiagID: diag::note_omp_referenced);
19062 continue;
19063 }
19064 if (DVar.CKind != OMPC_unknown) {
19065 S.Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
19066 << getOpenMPClauseNameForDiag(C: DVar.CKind)
19067 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
19068 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
19069 continue;
19070 }
19071
19072 // OpenMP [2.14.3.6, Restrictions, p.1]
19073 // A list item that appears in a reduction clause of a worksharing
19074 // construct must be shared in the parallel regions to which any of the
19075 // worksharing regions arising from the worksharing construct bind.
19076
19077 if (S.getLangOpts().OpenMP <= 52 &&
19078 isOpenMPWorksharingDirective(DKind: CurrDir) &&
19079 !isOpenMPParallelDirective(DKind: CurrDir) &&
19080 !isOpenMPTeamsDirective(DKind: CurrDir)) {
19081 DVar = Stack->getImplicitDSA(D, FromParent: true);
19082 if (DVar.CKind != OMPC_shared) {
19083 S.Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
19084 << getOpenMPClauseNameForDiag(C: OMPC_reduction)
19085 << getOpenMPClauseNameForDiag(C: OMPC_shared);
19086 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
19087 continue;
19088 }
19089 } else if (isOpenMPWorksharingDirective(DKind: CurrDir) &&
19090 !isOpenMPParallelDirective(DKind: CurrDir) &&
19091 !isOpenMPTeamsDirective(DKind: CurrDir)) {
19092 // OpenMP 6.0 [ 7.6.10 ]
19093 // Support Reduction over private variables with reduction clause.
19094 // A list item in a reduction clause can now be private in the enclosing
19095 // context. For orphaned constructs it is assumed to be shared unless
19096 // the original(private) modifier appears in the clause.
19097 DVar = Stack->getImplicitDSA(D, FromParent: true);
19098 // Determine if the variable should be considered private
19099 IsPrivate = DVar.CKind != OMPC_shared;
19100 bool IsOrphaned = false;
19101 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
19102 IsOrphaned = ParentDir == OMPD_unknown;
19103 if ((IsOrphaned &&
19104 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
19105 IsPrivate = true;
19106 }
19107 } else {
19108 // Threadprivates cannot be shared between threads, so dignose if the base
19109 // is a threadprivate variable.
19110 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19111 if (DVar.CKind == OMPC_threadprivate) {
19112 S.Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
19113 << getOpenMPClauseNameForDiag(C: DVar.CKind)
19114 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
19115 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
19116 continue;
19117 }
19118 }
19119
19120 // Try to find 'declare reduction' corresponding construct before using
19121 // builtin/overloaded operators.
19122 CXXCastPath BasePath;
19123 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19124 SemaRef&: S, Loc: ELoc, Range: ERange, S: Stack->getCurScope(), ReductionIdScopeSpec,
19125 ReductionId, Ty: Type, BasePath, UnresolvedReduction: IR == ER ? nullptr : *IR);
19126 if (DeclareReductionRef.isInvalid())
19127 continue;
19128 if (S.CurContext->isDependentContext() &&
19129 (DeclareReductionRef.isUnset() ||
19130 isa<UnresolvedLookupExpr>(Val: DeclareReductionRef.get()))) {
19131 RD.push(Item: RefExpr, ReductionOp: DeclareReductionRef.get());
19132 continue;
19133 }
19134 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19135 // Not allowed reduction identifier is found.
19136 if (S.LangOpts.OpenMP > 52)
19137 S.Diag(Loc: ReductionId.getBeginLoc(),
19138 DiagID: diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
19139 << Type << ReductionIdRange;
19140 else
19141 S.Diag(Loc: ReductionId.getBeginLoc(),
19142 DiagID: diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
19143 << Type << ReductionIdRange;
19144 continue;
19145 }
19146
19147 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19148 // The type of a list item that appears in a reduction clause must be valid
19149 // for the reduction-identifier. For a max or min reduction in C, the type
19150 // of the list item must be an allowed arithmetic data type: char, int,
19151 // float, double, or _Bool, possibly modified with long, short, signed, or
19152 // unsigned. For a max or min reduction in C++, the type of the list item
19153 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19154 // double, or bool, possibly modified with long, short, signed, or unsigned.
19155 if (DeclareReductionRef.isUnset()) {
19156 if ((BOK == BO_GT || BOK == BO_LT) &&
19157 !(Type->isScalarType() ||
19158 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19159 S.Diag(Loc: ELoc, DiagID: diag::err_omp_clause_not_arithmetic_type_arg)
19160 << getOpenMPClauseNameForDiag(C: ClauseKind)
19161 << S.getLangOpts().CPlusPlus;
19162 if (!ASE && !OASE) {
19163 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19164 VarDecl::DeclarationOnly;
19165 S.Diag(Loc: D->getLocation(),
19166 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19167 << D;
19168 }
19169 continue;
19170 }
19171 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19172 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19173 S.Diag(Loc: ELoc, DiagID: diag::err_omp_clause_floating_type_arg)
19174 << getOpenMPClauseNameForDiag(C: ClauseKind);
19175 if (!ASE && !OASE) {
19176 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19177 VarDecl::DeclarationOnly;
19178 S.Diag(Loc: D->getLocation(),
19179 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19180 << D;
19181 }
19182 continue;
19183 }
19184 }
19185
19186 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19187 VarDecl *LHSVD = buildVarDecl(SemaRef&: S, Loc: ELoc, Type, Name: ".reduction.lhs",
19188 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
19189 VarDecl *RHSVD = buildVarDecl(SemaRef&: S, Loc: ELoc, Type, Name: D->getName(),
19190 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
19191 QualType PrivateTy = Type;
19192
19193 // Try if we can determine constant lengths for all array sections and avoid
19194 // the VLA.
19195 bool ConstantLengthOASE = false;
19196 if (OASE) {
19197 bool SingleElement;
19198 llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
19199 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19200 Context, OASE, SingleElement, ArraySizes);
19201
19202 // If we don't have a single element, we must emit a constant array type.
19203 if (ConstantLengthOASE && !SingleElement) {
19204 for (llvm::APSInt &Size : ArraySizes)
19205 PrivateTy = Context.getConstantArrayType(EltTy: PrivateTy, ArySize: Size, SizeExpr: nullptr,
19206 ASM: ArraySizeModifier::Normal,
19207 /*IndexTypeQuals=*/0);
19208 }
19209 }
19210
19211 if ((OASE && !ConstantLengthOASE) ||
19212 (!OASE && !ASE &&
19213 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
19214 if (!Context.getTargetInfo().isVLASupported()) {
19215 if (isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective())) {
19216 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_vla_unsupported) << !!OASE;
19217 S.Diag(Loc: ELoc, DiagID: diag::note_vla_unsupported);
19218 continue;
19219 } else {
19220 S.targetDiag(Loc: ELoc, DiagID: diag::err_omp_reduction_vla_unsupported) << !!OASE;
19221 S.targetDiag(Loc: ELoc, DiagID: diag::note_vla_unsupported);
19222 }
19223 }
19224 // For arrays/array sections only:
19225 // Create pseudo array type for private copy. The size for this array will
19226 // be generated during codegen.
19227 // For array subscripts or single variables Private Ty is the same as Type
19228 // (type of the variable or single array element).
19229 PrivateTy = Context.getVariableArrayType(
19230 EltTy: Type,
19231 NumElts: new (Context)
19232 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19233 ASM: ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
19234 } else if (!ASE && !OASE &&
19235 Context.getAsArrayType(T: D->getType().getNonReferenceType())) {
19236 PrivateTy = D->getType().getNonReferenceType();
19237 }
19238 // Private copy.
19239 VarDecl *PrivateVD =
19240 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: PrivateTy, Name: D->getName(),
19241 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
19242 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
19243 // Add initializer for private variable.
19244 Expr *Init = nullptr;
19245 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, D: LHSVD, Ty: Type, Loc: ELoc);
19246 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, D: RHSVD, Ty: Type, Loc: ELoc);
19247 if (DeclareReductionRef.isUsable()) {
19248 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19249 auto *DRD = cast<OMPDeclareReductionDecl>(Val: DRDRef->getDecl());
19250 if (DRD->getInitializer()) {
19251 Init = DRDRef;
19252 RHSVD->setInit(DRDRef);
19253 RHSVD->setInitStyle(VarDecl::CallInit);
19254 }
19255 } else {
19256 switch (BOK) {
19257 case BO_Add:
19258 case BO_Xor:
19259 case BO_Or:
19260 case BO_LOr:
19261 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19262 if (Type->isScalarType() || Type->isAnyComplexType())
19263 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/0).get();
19264 break;
19265 case BO_Mul:
19266 case BO_LAnd:
19267 if (Type->isScalarType() || Type->isAnyComplexType()) {
19268 // '*' and '&&' reduction ops - initializer is '1'.
19269 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
19270 }
19271 break;
19272 case BO_And: {
19273 // '&' reduction op - initializer is '~0'.
19274 QualType OrigType = Type;
19275 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
19276 Type = ComplexTy->getElementType();
19277 if (Type->isRealFloatingType()) {
19278 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19279 Semantics: Context.getFloatTypeSemantics(T: Type));
19280 Init = FloatingLiteral::Create(C: Context, V: InitValue, /*isexact=*/true,
19281 Type, L: ELoc);
19282 } else if (Type->isScalarType()) {
19283 uint64_t Size = Context.getTypeSize(T: Type);
19284 QualType IntTy = Context.getIntTypeForBitwidth(DestWidth: Size, /*Signed=*/0);
19285 llvm::APInt InitValue = llvm::APInt::getAllOnes(numBits: Size);
19286 Init = IntegerLiteral::Create(C: Context, V: InitValue, type: IntTy, l: ELoc);
19287 }
19288 if (Init && OrigType->isAnyComplexType()) {
19289 // Init = 0xFFFF + 0xFFFFi;
19290 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
19291 Init = S.CreateBuiltinBinOp(OpLoc: ELoc, Opc: BO_Add, LHSExpr: Init, RHSExpr: Im).get();
19292 }
19293 Type = OrigType;
19294 break;
19295 }
19296 case BO_LT:
19297 case BO_GT: {
19298 // 'min' reduction op - initializer is 'Largest representable number in
19299 // the reduction list item type'.
19300 // 'max' reduction op - initializer is 'Least representable number in
19301 // the reduction list item type'.
19302 if (Type->isIntegerType() || Type->isPointerType()) {
19303 bool IsSigned = Type->hasSignedIntegerRepresentation();
19304 uint64_t Size = Context.getTypeSize(T: Type);
19305 QualType IntTy =
19306 Context.getIntTypeForBitwidth(DestWidth: Size, /*Signed=*/IsSigned);
19307 llvm::APInt InitValue =
19308 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(numBits: Size)
19309 : llvm::APInt::getMinValue(numBits: Size)
19310 : IsSigned ? llvm::APInt::getSignedMaxValue(numBits: Size)
19311 : llvm::APInt::getMaxValue(numBits: Size);
19312 Init = IntegerLiteral::Create(C: Context, V: InitValue, type: IntTy, l: ELoc);
19313 if (Type->isPointerType()) {
19314 // Cast to pointer type.
19315 ExprResult CastExpr = S.BuildCStyleCastExpr(
19316 LParenLoc: ELoc, Ty: Context.getTrivialTypeSourceInfo(T: Type, Loc: ELoc), RParenLoc: ELoc, Op: Init);
19317 if (CastExpr.isInvalid())
19318 continue;
19319 Init = CastExpr.get();
19320 }
19321 } else if (Type->isRealFloatingType()) {
19322 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19323 Sem: Context.getFloatTypeSemantics(T: Type), Negative: BOK != BO_LT);
19324 Init = FloatingLiteral::Create(C: Context, V: InitValue, /*isexact=*/true,
19325 Type, L: ELoc);
19326 }
19327 break;
19328 }
19329 case BO_PtrMemD:
19330 case BO_PtrMemI:
19331 case BO_MulAssign:
19332 case BO_Div:
19333 case BO_Rem:
19334 case BO_Sub:
19335 case BO_Shl:
19336 case BO_Shr:
19337 case BO_LE:
19338 case BO_GE:
19339 case BO_EQ:
19340 case BO_NE:
19341 case BO_Cmp:
19342 case BO_AndAssign:
19343 case BO_XorAssign:
19344 case BO_OrAssign:
19345 case BO_Assign:
19346 case BO_AddAssign:
19347 case BO_SubAssign:
19348 case BO_DivAssign:
19349 case BO_RemAssign:
19350 case BO_ShlAssign:
19351 case BO_ShrAssign:
19352 case BO_Comma:
19353 llvm_unreachable("Unexpected reduction operation");
19354 }
19355 }
19356 if (Init && DeclareReductionRef.isUnset()) {
19357 S.AddInitializerToDecl(dcl: RHSVD, init: Init, /*DirectInit=*/false);
19358 // Store initializer for single element in private copy. Will be used
19359 // during codegen.
19360 PrivateVD->setInit(RHSVD->getInit());
19361 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19362 } else if (!Init) {
19363 S.ActOnUninitializedDecl(dcl: RHSVD);
19364 // Store initializer for single element in private copy. Will be used
19365 // during codegen.
19366 PrivateVD->setInit(RHSVD->getInit());
19367 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19368 }
19369 if (RHSVD->isInvalidDecl())
19370 continue;
19371 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
19372 S.Diag(Loc: ELoc, DiagID: diag::err_omp_reduction_id_not_compatible)
19373 << Type << ReductionIdRange;
19374 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19375 VarDecl::DeclarationOnly;
19376 S.Diag(Loc: D->getLocation(),
19377 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19378 << D;
19379 continue;
19380 }
19381 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, D: PrivateVD, Ty: PrivateTy, Loc: ELoc);
19382 ExprResult ReductionOp;
19383 if (DeclareReductionRef.isUsable()) {
19384 QualType RedTy = DeclareReductionRef.get()->getType();
19385 QualType PtrRedTy = Context.getPointerType(T: RedTy);
19386 ExprResult LHS = S.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: LHSDRE);
19387 ExprResult RHS = S.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: RHSDRE);
19388 if (!BasePath.empty()) {
19389 LHS = S.DefaultLvalueConversion(E: LHS.get());
19390 RHS = S.DefaultLvalueConversion(E: RHS.get());
19391 LHS = ImplicitCastExpr::Create(
19392 Context, T: PtrRedTy, Kind: CK_UncheckedDerivedToBase, Operand: LHS.get(), BasePath: &BasePath,
19393 Cat: LHS.get()->getValueKind(), FPO: FPOptionsOverride());
19394 RHS = ImplicitCastExpr::Create(
19395 Context, T: PtrRedTy, Kind: CK_UncheckedDerivedToBase, Operand: RHS.get(), BasePath: &BasePath,
19396 Cat: RHS.get()->getValueKind(), FPO: FPOptionsOverride());
19397 }
19398 FunctionProtoType::ExtProtoInfo EPI;
19399 QualType Params[] = {PtrRedTy, PtrRedTy};
19400 QualType FnTy = Context.getFunctionType(ResultTy: Context.VoidTy, Args: Params, EPI);
19401 auto *OVE = new (Context) OpaqueValueExpr(
19402 ELoc, Context.getPointerType(T: FnTy), VK_PRValue, OK_Ordinary,
19403 S.DefaultLvalueConversion(E: DeclareReductionRef.get()).get());
19404 Expr *Args[] = {LHS.get(), RHS.get()};
19405 ReductionOp =
19406 CallExpr::Create(Ctx: Context, Fn: OVE, Args, Ty: Context.VoidTy, VK: VK_PRValue, RParenLoc: ELoc,
19407 FPFeatures: S.CurFPFeatureOverrides());
19408 } else {
19409 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
19410 if (Type->isRecordType() && CombBOK != BOK) {
19411 Sema::TentativeAnalysisScope Trap(S);
19412 ReductionOp =
19413 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
19414 Opc: CombBOK, LHSExpr: LHSDRE, RHSExpr: RHSDRE);
19415 }
19416 if (!ReductionOp.isUsable()) {
19417 ReductionOp =
19418 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(), Opc: BOK,
19419 LHSExpr: LHSDRE, RHSExpr: RHSDRE);
19420 if (ReductionOp.isUsable()) {
19421 if (BOK != BO_LT && BOK != BO_GT) {
19422 ReductionOp =
19423 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
19424 Opc: BO_Assign, LHSExpr: LHSDRE, RHSExpr: ReductionOp.get());
19425 } else {
19426 auto *ConditionalOp = new (Context)
19427 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
19428 RHSDRE, Type, VK_LValue, OK_Ordinary);
19429 ReductionOp =
19430 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
19431 Opc: BO_Assign, LHSExpr: LHSDRE, RHSExpr: ConditionalOp);
19432 }
19433 }
19434 }
19435 if (ReductionOp.isUsable())
19436 ReductionOp = S.ActOnFinishFullExpr(Expr: ReductionOp.get(),
19437 /*DiscardedValue=*/false);
19438 if (!ReductionOp.isUsable())
19439 continue;
19440 }
19441
19442 // Add copy operations for inscan reductions.
19443 // LHS = RHS;
19444 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
19445 if (ClauseKind == OMPC_reduction &&
19446 RD.RedModifier == OMPC_REDUCTION_inscan) {
19447 ExprResult RHS = S.DefaultLvalueConversion(E: RHSDRE);
19448 CopyOpRes = S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: LHSDRE,
19449 RHSExpr: RHS.get());
19450 if (!CopyOpRes.isUsable())
19451 continue;
19452 CopyOpRes =
19453 S.ActOnFinishFullExpr(Expr: CopyOpRes.get(), /*DiscardedValue=*/true);
19454 if (!CopyOpRes.isUsable())
19455 continue;
19456 // For simd directive and simd-based directives in simd mode no need to
19457 // construct temp array, need just a single temp element.
19458 if (Stack->getCurrentDirective() == OMPD_simd ||
19459 (S.getLangOpts().OpenMPSimd &&
19460 isOpenMPSimdDirective(DKind: Stack->getCurrentDirective()))) {
19461 VarDecl *TempArrayVD =
19462 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: PrivateTy, Name: D->getName(),
19463 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
19464 // Add a constructor to the temp decl.
19465 S.ActOnUninitializedDecl(dcl: TempArrayVD);
19466 TempArrayRes = buildDeclRefExpr(S, D: TempArrayVD, Ty: PrivateTy, Loc: ELoc);
19467 } else {
19468 // Build temp array for prefix sum.
19469 auto *Dim = new (S.Context)
19470 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19471 QualType ArrayTy = S.Context.getVariableArrayType(
19472 EltTy: PrivateTy, NumElts: Dim, ASM: ArraySizeModifier::Normal,
19473 /*IndexTypeQuals=*/0);
19474 VarDecl *TempArrayVD =
19475 buildVarDecl(SemaRef&: S, Loc: ELoc, Type: ArrayTy, Name: D->getName(),
19476 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
19477 // Add a constructor to the temp decl.
19478 S.ActOnUninitializedDecl(dcl: TempArrayVD);
19479 TempArrayRes = buildDeclRefExpr(S, D: TempArrayVD, Ty: ArrayTy, Loc: ELoc);
19480 TempArrayElem =
19481 S.DefaultFunctionArrayLvalueConversion(E: TempArrayRes.get());
19482 auto *Idx = new (S.Context)
19483 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19484 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(Base: TempArrayElem.get(),
19485 LLoc: ELoc, Idx, RLoc: ELoc);
19486 }
19487 }
19488
19489 // OpenMP [2.15.4.6, Restrictions, p.2]
19490 // A list item that appears in an in_reduction clause of a task construct
19491 // must appear in a task_reduction clause of a construct associated with a
19492 // taskgroup region that includes the participating task in its taskgroup
19493 // set. The construct associated with the innermost region that meets this
19494 // condition must specify the same reduction-identifier as the in_reduction
19495 // clause.
19496 if (ClauseKind == OMPC_in_reduction) {
19497 SourceRange ParentSR;
19498 BinaryOperatorKind ParentBOK;
19499 const Expr *ParentReductionOp = nullptr;
19500 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
19501 DSAStackTy::DSAVarData ParentBOKDSA =
19502 Stack->getTopMostTaskgroupReductionData(D, SR&: ParentSR, BOK&: ParentBOK,
19503 TaskgroupDescriptor&: ParentBOKTD);
19504 DSAStackTy::DSAVarData ParentReductionOpDSA =
19505 Stack->getTopMostTaskgroupReductionData(
19506 D, SR&: ParentSR, ReductionRef&: ParentReductionOp, TaskgroupDescriptor&: ParentReductionOpTD);
19507 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19508 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19509 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
19510 (DeclareReductionRef.isUsable() && IsParentBOK) ||
19511 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19512 bool EmitError = true;
19513 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
19514 llvm::FoldingSetNodeID RedId, ParentRedId;
19515 ParentReductionOp->Profile(ID&: ParentRedId, Context, /*Canonical=*/true);
19516 DeclareReductionRef.get()->Profile(ID&: RedId, Context,
19517 /*Canonical=*/true);
19518 EmitError = RedId != ParentRedId;
19519 }
19520 if (EmitError) {
19521 S.Diag(Loc: ReductionId.getBeginLoc(),
19522 DiagID: diag::err_omp_reduction_identifier_mismatch)
19523 << ReductionIdRange << RefExpr->getSourceRange();
19524 S.Diag(Loc: ParentSR.getBegin(),
19525 DiagID: diag::note_omp_previous_reduction_identifier)
19526 << ParentSR
19527 << (IsParentBOK ? ParentBOKDSA.RefExpr
19528 : ParentReductionOpDSA.RefExpr)
19529 ->getSourceRange();
19530 continue;
19531 }
19532 }
19533 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19534 }
19535
19536 DeclRefExpr *Ref = nullptr;
19537 Expr *VarsExpr = RefExpr->IgnoreParens();
19538 if (!VD && !S.CurContext->isDependentContext()) {
19539 if (ASE || OASE) {
19540 TransformExprToCaptures RebuildToCapture(S, D);
19541 VarsExpr =
19542 RebuildToCapture.TransformExpr(E: RefExpr->IgnoreParens()).get();
19543 Ref = RebuildToCapture.getCapturedExpr();
19544 } else {
19545 VarsExpr = Ref = buildCapture(S, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
19546 }
19547 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
19548 RD.ExprCaptures.emplace_back(Args: Ref->getDecl());
19549 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19550 ExprResult RefRes = S.DefaultLvalueConversion(E: Ref);
19551 if (!RefRes.isUsable())
19552 continue;
19553 ExprResult PostUpdateRes =
19554 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: SimpleRefExpr,
19555 RHSExpr: RefRes.get());
19556 if (!PostUpdateRes.isUsable())
19557 continue;
19558 if (isOpenMPTaskingDirective(Kind: Stack->getCurrentDirective()) ||
19559 Stack->getCurrentDirective() == OMPD_taskgroup) {
19560 S.Diag(Loc: RefExpr->getExprLoc(),
19561 DiagID: diag::err_omp_reduction_non_addressable_expression)
19562 << RefExpr->getSourceRange();
19563 continue;
19564 }
19565 RD.ExprPostUpdates.emplace_back(
19566 Args: S.IgnoredValueConversions(E: PostUpdateRes.get()).get());
19567 }
19568 }
19569 }
19570 // All reduction items are still marked as reduction (to do not increase
19571 // code base size).
19572 unsigned Modifier = RD.RedModifier;
19573 // Consider task_reductions as reductions with task modifier. Required for
19574 // correct analysis of in_reduction clauses.
19575 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19576 Modifier = OMPC_REDUCTION_task;
19577 Stack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_reduction, PrivateCopy: Ref, Modifier,
19578 AppliedToPointee: ASE || OASE);
19579 if (Modifier == OMPC_REDUCTION_task &&
19580 (CurrDir == OMPD_taskgroup ||
19581 ((isOpenMPParallelDirective(DKind: CurrDir) ||
19582 isOpenMPWorksharingDirective(DKind: CurrDir)) &&
19583 !isOpenMPSimdDirective(DKind: CurrDir)))) {
19584 if (DeclareReductionRef.isUsable())
19585 Stack->addTaskgroupReductionData(D, SR: ReductionIdRange,
19586 ReductionRef: DeclareReductionRef.get());
19587 else
19588 Stack->addTaskgroupReductionData(D, SR: ReductionIdRange, BOK);
19589 }
19590 RD.push(Item: VarsExpr, Private: PrivateDRE, LHS: LHSDRE, RHS: RHSDRE, ReductionOp: ReductionOp.get(),
19591 TaskgroupDescriptor, CopyOp: CopyOpRes.get(), CopyArrayTemp: TempArrayRes.get(),
19592 CopyArrayElem: TempArrayElem.get(), IsPrivate);
19593 }
19594 return RD.Vars.empty();
19595}
19596
19597OMPClause *SemaOpenMP::ActOnOpenMPReductionClause(
19598 ArrayRef<Expr *> VarList,
19599 OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers,
19600 SourceLocation StartLoc, SourceLocation LParenLoc,
19601 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
19602 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19603 ArrayRef<Expr *> UnresolvedReductions) {
19604 OpenMPReductionClauseModifier Modifier =
19605 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
19606 OpenMPOriginalSharingModifier OriginalSharingModifier =
19607 static_cast<OpenMPOriginalSharingModifier>(
19608 Modifiers.OriginalSharingModifier);
19609 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
19610 Diag(Loc: LParenLoc, DiagID: diag::err_omp_unexpected_clause_value)
19611 << getListOfPossibleValues(K: OMPC_reduction, /*First=*/0,
19612 /*Last=*/OMPC_REDUCTION_unknown)
19613 << getOpenMPClauseNameForDiag(C: OMPC_reduction);
19614 return nullptr;
19615 }
19616 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
19617 // A reduction clause with the inscan reduction-modifier may only appear on a
19618 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
19619 // construct, a parallel worksharing-loop construct or a parallel
19620 // worksharing-loop SIMD construct.
19621 if (Modifier == OMPC_REDUCTION_inscan &&
19622 (DSAStack->getCurrentDirective() != OMPD_for &&
19623 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19624 DSAStack->getCurrentDirective() != OMPD_simd &&
19625 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19626 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19627 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_wrong_inscan_reduction);
19628 return nullptr;
19629 }
19630 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
19631 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_reduction, VarList,
19632 StartLoc, LParenLoc, ColonLoc, EndLoc,
19633 ReductionIdScopeSpec, ReductionId,
19634 UnresolvedReductions, RD))
19635 return nullptr;
19636
19637 return OMPReductionClause::Create(
19638 C: getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
19639 Modifier, VL: RD.Vars,
19640 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
19641 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps, CopyOps: RD.InscanCopyOps,
19642 CopyArrayTemps: RD.InscanCopyArrayTemps, CopyArrayElems: RD.InscanCopyArrayElems,
19643 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
19644 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates), IsPrivateVarReduction: RD.IsPrivateVarReduction,
19645 OriginalSharingModifier);
19646}
19647
19648OMPClause *SemaOpenMP::ActOnOpenMPTaskReductionClause(
19649 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19650 SourceLocation ColonLoc, SourceLocation EndLoc,
19651 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19652 ArrayRef<Expr *> UnresolvedReductions) {
19653 ReductionData RD(VarList.size());
19654 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_task_reduction,
19655 VarList, StartLoc, LParenLoc, ColonLoc,
19656 EndLoc, ReductionIdScopeSpec, ReductionId,
19657 UnresolvedReductions, RD))
19658 return nullptr;
19659
19660 return OMPTaskReductionClause::Create(
19661 C: getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, VL: RD.Vars,
19662 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
19663 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps,
19664 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
19665 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates));
19666}
19667
19668OMPClause *SemaOpenMP::ActOnOpenMPInReductionClause(
19669 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19670 SourceLocation ColonLoc, SourceLocation EndLoc,
19671 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19672 ArrayRef<Expr *> UnresolvedReductions) {
19673 ReductionData RD(VarList.size());
19674 if (actOnOMPReductionKindClause(S&: SemaRef, DSAStack, ClauseKind: OMPC_in_reduction, VarList,
19675 StartLoc, LParenLoc, ColonLoc, EndLoc,
19676 ReductionIdScopeSpec, ReductionId,
19677 UnresolvedReductions, RD))
19678 return nullptr;
19679
19680 return OMPInReductionClause::Create(
19681 C: getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, VL: RD.Vars,
19682 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
19683 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps, TaskgroupDescriptors: RD.TaskgroupDescriptors,
19684 PreInit: buildPreInits(Context&: getASTContext(), PreInits: RD.ExprCaptures),
19685 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates));
19686}
19687
19688bool SemaOpenMP::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
19689 SourceLocation LinLoc) {
19690 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19691 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
19692 Diag(Loc: LinLoc, DiagID: diag::err_omp_wrong_linear_modifier)
19693 << getLangOpts().CPlusPlus;
19694 return true;
19695 }
19696 return false;
19697}
19698
19699bool SemaOpenMP::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
19700 OpenMPLinearClauseKind LinKind,
19701 QualType Type, bool IsDeclareSimd) {
19702 const auto *VD = dyn_cast_or_null<VarDecl>(Val: D);
19703 // A variable must not have an incomplete type or a reference type.
19704 if (SemaRef.RequireCompleteType(Loc: ELoc, T: Type,
19705 DiagID: diag::err_omp_linear_incomplete_type))
19706 return true;
19707 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19708 !Type->isReferenceType()) {
19709 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_linear_modifier_non_reference)
19710 << Type << getOpenMPSimpleClauseTypeName(Kind: OMPC_linear, Type: LinKind);
19711 return true;
19712 }
19713 Type = Type.getNonReferenceType();
19714
19715 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19716 // A variable that is privatized must not have a const-qualified type
19717 // unless it is of class type with a mutable member. This restriction does
19718 // not apply to the firstprivate clause, nor to the linear clause on
19719 // declarative directives (like declare simd).
19720 if (!IsDeclareSimd &&
19721 rejectConstNotMutableType(SemaRef, D, Type, CKind: OMPC_linear, ELoc))
19722 return true;
19723
19724 // A list item must be of integral or pointer type.
19725 Type = Type.getUnqualifiedType().getCanonicalType();
19726 const auto *Ty = Type.getTypePtrOrNull();
19727 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19728 !Ty->isIntegralType(Ctx: getASTContext()) && !Ty->isPointerType())) {
19729 Diag(Loc: ELoc, DiagID: diag::err_omp_linear_expected_int_or_ptr) << Type;
19730 if (D) {
19731 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19732 VarDecl::DeclarationOnly;
19733 Diag(Loc: D->getLocation(),
19734 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19735 << D;
19736 }
19737 return true;
19738 }
19739 return false;
19740}
19741
19742OMPClause *SemaOpenMP::ActOnOpenMPLinearClause(
19743 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
19744 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
19745 SourceLocation LinLoc, SourceLocation ColonLoc,
19746 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
19747 SmallVector<Expr *, 8> Vars;
19748 SmallVector<Expr *, 8> Privates;
19749 SmallVector<Expr *, 8> Inits;
19750 SmallVector<Decl *, 4> ExprCaptures;
19751 SmallVector<Expr *, 4> ExprPostUpdates;
19752 // OpenMP 5.2 [Section 5.4.6, linear clause]
19753 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
19754 // 'ref'
19755 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
19756 getLangOpts().OpenMP >= 52)
19757 Diag(Loc: Step->getBeginLoc(), DiagID: diag::err_omp_step_simple_modifier_exclusive);
19758 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
19759 LinKind = OMPC_LINEAR_val;
19760 for (Expr *RefExpr : VarList) {
19761 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19762 SourceLocation ELoc;
19763 SourceRange ERange;
19764 Expr *SimpleRefExpr = RefExpr;
19765 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
19766 if (Res.second) {
19767 // It will be analyzed later.
19768 Vars.push_back(Elt: RefExpr);
19769 Privates.push_back(Elt: nullptr);
19770 Inits.push_back(Elt: nullptr);
19771 }
19772 ValueDecl *D = Res.first;
19773 if (!D)
19774 continue;
19775
19776 QualType Type = D->getType();
19777 auto *VD = dyn_cast<VarDecl>(Val: D);
19778
19779 // OpenMP [2.14.3.7, linear clause]
19780 // A list-item cannot appear in more than one linear clause.
19781 // A list-item that appears in a linear clause cannot appear in any
19782 // other data-sharing attribute clause.
19783 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19784 if (DVar.RefExpr) {
19785 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
19786 << getOpenMPClauseNameForDiag(C: DVar.CKind)
19787 << getOpenMPClauseNameForDiag(C: OMPC_linear);
19788 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19789 continue;
19790 }
19791
19792 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19793 continue;
19794 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19795
19796 // Build private copy of original var.
19797 VarDecl *Private =
19798 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
19799 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
19800 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
19801 DeclRefExpr *PrivateRef = buildDeclRefExpr(S&: SemaRef, D: Private, Ty: Type, Loc: ELoc);
19802 // Build var to save initial value.
19803 VarDecl *Init = buildVarDecl(SemaRef, Loc: ELoc, Type, Name: ".linear.start");
19804 Expr *InitExpr;
19805 DeclRefExpr *Ref = nullptr;
19806 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19807 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
19808 if (!isOpenMPCapturedDecl(D)) {
19809 ExprCaptures.push_back(Elt: Ref->getDecl());
19810 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19811 ExprResult RefRes = SemaRef.DefaultLvalueConversion(E: Ref);
19812 if (!RefRes.isUsable())
19813 continue;
19814 ExprResult PostUpdateRes =
19815 SemaRef.BuildBinOp(DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign,
19816 LHSExpr: SimpleRefExpr, RHSExpr: RefRes.get());
19817 if (!PostUpdateRes.isUsable())
19818 continue;
19819 ExprPostUpdates.push_back(
19820 Elt: SemaRef.IgnoredValueConversions(E: PostUpdateRes.get()).get());
19821 }
19822 }
19823 }
19824 if (LinKind == OMPC_LINEAR_uval)
19825 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19826 else
19827 InitExpr = VD ? SimpleRefExpr : Ref;
19828 SemaRef.AddInitializerToDecl(
19829 dcl: Init, init: SemaRef.DefaultLvalueConversion(E: InitExpr).get(),
19830 /*DirectInit=*/false);
19831 DeclRefExpr *InitRef = buildDeclRefExpr(S&: SemaRef, D: Init, Ty: Type, Loc: ELoc);
19832
19833 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_linear, PrivateCopy: Ref);
19834 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
19835 ? RefExpr->IgnoreParens()
19836 : Ref);
19837 Privates.push_back(Elt: PrivateRef);
19838 Inits.push_back(Elt: InitRef);
19839 }
19840
19841 if (Vars.empty())
19842 return nullptr;
19843
19844 Expr *StepExpr = Step;
19845 Expr *CalcStepExpr = nullptr;
19846 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
19847 !Step->isInstantiationDependent() &&
19848 !Step->containsUnexpandedParameterPack()) {
19849 SourceLocation StepLoc = Step->getBeginLoc();
19850 ExprResult Val = PerformOpenMPImplicitIntegerConversion(Loc: StepLoc, Op: Step);
19851 if (Val.isInvalid())
19852 return nullptr;
19853 StepExpr = Val.get();
19854
19855 // Build var to save the step value.
19856 VarDecl *SaveVar =
19857 buildVarDecl(SemaRef, Loc: StepLoc, Type: StepExpr->getType(), Name: ".linear.step");
19858 ExprResult SaveRef =
19859 buildDeclRefExpr(S&: SemaRef, D: SaveVar, Ty: StepExpr->getType(), Loc: StepLoc);
19860 ExprResult CalcStep = SemaRef.BuildBinOp(
19861 S: SemaRef.getCurScope(), OpLoc: StepLoc, Opc: BO_Assign, LHSExpr: SaveRef.get(), RHSExpr: StepExpr);
19862 CalcStep =
19863 SemaRef.ActOnFinishFullExpr(Expr: CalcStep.get(), /*DiscardedValue=*/false);
19864
19865 // Warn about zero linear step (it would be probably better specified as
19866 // making corresponding variables 'const').
19867 if (std::optional<llvm::APSInt> Result =
19868 StepExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
19869 if (!Result->isNegative() && !Result->isStrictlyPositive())
19870 Diag(Loc: StepLoc, DiagID: diag::warn_omp_linear_step_zero)
19871 << Vars[0] << (Vars.size() > 1);
19872 } else if (CalcStep.isUsable()) {
19873 // Calculate the step beforehand instead of doing this on each iteration.
19874 // (This is not used if the number of iterations may be kfold-ed).
19875 CalcStepExpr = CalcStep.get();
19876 }
19877 }
19878
19879 return OMPLinearClause::Create(C: getASTContext(), StartLoc, LParenLoc, Modifier: LinKind,
19880 ModifierLoc: LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19881 VL: Vars, PL: Privates, IL: Inits, Step: StepExpr, CalcStep: CalcStepExpr,
19882 PreInit: buildPreInits(Context&: getASTContext(), PreInits: ExprCaptures),
19883 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: ExprPostUpdates));
19884}
19885
19886static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
19887 Expr *NumIterations, Sema &SemaRef,
19888 Scope *S, DSAStackTy *Stack) {
19889 // Walk the vars and build update/final expressions for the CodeGen.
19890 SmallVector<Expr *, 8> Updates;
19891 SmallVector<Expr *, 8> Finals;
19892 SmallVector<Expr *, 8> UsedExprs;
19893 Expr *Step = Clause.getStep();
19894 Expr *CalcStep = Clause.getCalcStep();
19895 // OpenMP [2.14.3.7, linear clause]
19896 // If linear-step is not specified it is assumed to be 1.
19897 if (!Step)
19898 Step = SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get();
19899 else if (CalcStep)
19900 Step = cast<BinaryOperator>(Val: CalcStep)->getLHS();
19901 bool HasErrors = false;
19902 auto CurInit = Clause.inits().begin();
19903 auto CurPrivate = Clause.privates().begin();
19904 OpenMPLinearClauseKind LinKind = Clause.getModifier();
19905 for (Expr *RefExpr : Clause.varlist()) {
19906 SourceLocation ELoc;
19907 SourceRange ERange;
19908 Expr *SimpleRefExpr = RefExpr;
19909 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
19910 ValueDecl *D = Res.first;
19911 if (Res.second || !D) {
19912 Updates.push_back(Elt: nullptr);
19913 Finals.push_back(Elt: nullptr);
19914 HasErrors = true;
19915 continue;
19916 }
19917 auto &&Info = Stack->isLoopControlVariable(D);
19918 // OpenMP [2.15.11, distribute simd Construct]
19919 // A list item may not appear in a linear clause, unless it is the loop
19920 // iteration variable.
19921 if (isOpenMPDistributeDirective(DKind: Stack->getCurrentDirective()) &&
19922 isOpenMPSimdDirective(DKind: Stack->getCurrentDirective()) && !Info.first) {
19923 SemaRef.Diag(Loc: ELoc,
19924 DiagID: diag::err_omp_linear_distribute_var_non_loop_iteration);
19925 Updates.push_back(Elt: nullptr);
19926 Finals.push_back(Elt: nullptr);
19927 HasErrors = true;
19928 continue;
19929 }
19930 Expr *InitExpr = *CurInit;
19931
19932 // Build privatized reference to the current linear var.
19933 auto *DE = cast<DeclRefExpr>(Val: SimpleRefExpr);
19934 Expr *CapturedRef;
19935 if (LinKind == OMPC_LINEAR_uval)
19936 CapturedRef = cast<VarDecl>(Val: DE->getDecl())->getInit();
19937 else
19938 CapturedRef =
19939 buildDeclRefExpr(S&: SemaRef, D: cast<VarDecl>(Val: DE->getDecl()),
19940 Ty: DE->getType().getUnqualifiedType(), Loc: DE->getExprLoc(),
19941 /*RefersToCapture=*/true);
19942
19943 // Build update: Var = InitExpr + IV * Step
19944 ExprResult Update;
19945 if (!Info.first)
19946 Update = buildCounterUpdate(
19947 SemaRef, S, Loc: RefExpr->getExprLoc(), VarRef: *CurPrivate, Start: InitExpr, Iter: IV, Step,
19948 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
19949 else
19950 Update = *CurPrivate;
19951 Update = SemaRef.ActOnFinishFullExpr(Expr: Update.get(), CC: DE->getBeginLoc(),
19952 /*DiscardedValue=*/false);
19953
19954 // Build final: Var = PrivCopy;
19955 ExprResult Final;
19956 if (!Info.first)
19957 Final = SemaRef.BuildBinOp(
19958 S, OpLoc: RefExpr->getExprLoc(), Opc: BO_Assign, LHSExpr: CapturedRef,
19959 RHSExpr: SemaRef.DefaultLvalueConversion(E: *CurPrivate).get());
19960 else
19961 Final = *CurPrivate;
19962 Final = SemaRef.ActOnFinishFullExpr(Expr: Final.get(), CC: DE->getBeginLoc(),
19963 /*DiscardedValue=*/false);
19964
19965 if (!Update.isUsable() || !Final.isUsable()) {
19966 Updates.push_back(Elt: nullptr);
19967 Finals.push_back(Elt: nullptr);
19968 UsedExprs.push_back(Elt: nullptr);
19969 HasErrors = true;
19970 } else {
19971 Updates.push_back(Elt: Update.get());
19972 Finals.push_back(Elt: Final.get());
19973 if (!Info.first)
19974 UsedExprs.push_back(Elt: SimpleRefExpr);
19975 }
19976 ++CurInit;
19977 ++CurPrivate;
19978 }
19979 if (Expr *S = Clause.getStep())
19980 UsedExprs.push_back(Elt: S);
19981 // Fill the remaining part with the nullptr.
19982 UsedExprs.append(NumInputs: Clause.varlist_size() + 1 - UsedExprs.size(), Elt: nullptr);
19983 Clause.setUpdates(Updates);
19984 Clause.setFinals(Finals);
19985 Clause.setUsedExprs(UsedExprs);
19986 return HasErrors;
19987}
19988
19989OMPClause *SemaOpenMP::ActOnOpenMPAlignedClause(
19990 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
19991 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19992 SmallVector<Expr *, 8> Vars;
19993 for (Expr *RefExpr : VarList) {
19994 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19995 SourceLocation ELoc;
19996 SourceRange ERange;
19997 Expr *SimpleRefExpr = RefExpr;
19998 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
19999 if (Res.second) {
20000 // It will be analyzed later.
20001 Vars.push_back(Elt: RefExpr);
20002 }
20003 ValueDecl *D = Res.first;
20004 if (!D)
20005 continue;
20006
20007 QualType QType = D->getType();
20008 auto *VD = dyn_cast<VarDecl>(Val: D);
20009
20010 // OpenMP [2.8.1, simd construct, Restrictions]
20011 // The type of list items appearing in the aligned clause must be
20012 // array, pointer, reference to array, or reference to pointer.
20013 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20014 const Type *Ty = QType.getTypePtrOrNull();
20015 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
20016 Diag(Loc: ELoc, DiagID: diag::err_omp_aligned_expected_array_or_ptr)
20017 << QType << getLangOpts().CPlusPlus << ERange;
20018 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20019 VarDecl::DeclarationOnly;
20020 Diag(Loc: D->getLocation(),
20021 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20022 << D;
20023 continue;
20024 }
20025
20026 // OpenMP [2.8.1, simd construct, Restrictions]
20027 // A list-item cannot appear in more than one aligned clause.
20028 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, NewDE: SimpleRefExpr)) {
20029 Diag(Loc: ELoc, DiagID: diag::err_omp_used_in_clause_twice)
20030 << 0 << getOpenMPClauseNameForDiag(C: OMPC_aligned) << ERange;
20031 Diag(Loc: PrevRef->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
20032 << getOpenMPClauseNameForDiag(C: OMPC_aligned);
20033 continue;
20034 }
20035
20036 DeclRefExpr *Ref = nullptr;
20037 if (!VD && isOpenMPCapturedDecl(D))
20038 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
20039 Vars.push_back(Elt: SemaRef
20040 .DefaultFunctionArrayConversion(
20041 E: (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20042 .get());
20043 }
20044
20045 // OpenMP [2.8.1, simd construct, Description]
20046 // The parameter of the aligned clause, alignment, must be a constant
20047 // positive integer expression.
20048 // If no optional parameter is specified, implementation-defined default
20049 // alignments for SIMD instructions on the target platforms are assumed.
20050 if (Alignment != nullptr) {
20051 ExprResult AlignResult =
20052 VerifyPositiveIntegerConstantInClause(E: Alignment, CKind: OMPC_aligned);
20053 if (AlignResult.isInvalid())
20054 return nullptr;
20055 Alignment = AlignResult.get();
20056 }
20057 if (Vars.empty())
20058 return nullptr;
20059
20060 return OMPAlignedClause::Create(C: getASTContext(), StartLoc, LParenLoc,
20061 ColonLoc, EndLoc, VL: Vars, A: Alignment);
20062}
20063
20064OMPClause *SemaOpenMP::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
20065 SourceLocation StartLoc,
20066 SourceLocation LParenLoc,
20067 SourceLocation EndLoc) {
20068 SmallVector<Expr *, 8> Vars;
20069 SmallVector<Expr *, 8> SrcExprs;
20070 SmallVector<Expr *, 8> DstExprs;
20071 SmallVector<Expr *, 8> AssignmentOps;
20072 for (Expr *RefExpr : VarList) {
20073 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
20074 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
20075 // It will be analyzed later.
20076 Vars.push_back(Elt: RefExpr);
20077 SrcExprs.push_back(Elt: nullptr);
20078 DstExprs.push_back(Elt: nullptr);
20079 AssignmentOps.push_back(Elt: nullptr);
20080 continue;
20081 }
20082
20083 SourceLocation ELoc = RefExpr->getExprLoc();
20084 // OpenMP [2.1, C/C++]
20085 // A list item is a variable name.
20086 // OpenMP [2.14.4.1, Restrictions, p.1]
20087 // A list item that appears in a copyin clause must be threadprivate.
20088 auto *DE = dyn_cast<DeclRefExpr>(Val: RefExpr);
20089 if (!DE || !isa<VarDecl>(Val: DE->getDecl())) {
20090 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_var_name_member_expr)
20091 << 0 << RefExpr->getSourceRange();
20092 continue;
20093 }
20094
20095 Decl *D = DE->getDecl();
20096 auto *VD = cast<VarDecl>(Val: D);
20097
20098 QualType Type = VD->getType();
20099 if (Type->isDependentType() || Type->isInstantiationDependentType()) {
20100 // It will be analyzed later.
20101 Vars.push_back(Elt: DE);
20102 SrcExprs.push_back(Elt: nullptr);
20103 DstExprs.push_back(Elt: nullptr);
20104 AssignmentOps.push_back(Elt: nullptr);
20105 continue;
20106 }
20107
20108 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20109 // A list item that appears in a copyin clause must be threadprivate.
20110 if (!DSAStack->isThreadPrivate(D: VD)) {
20111 unsigned OMPVersion = getLangOpts().OpenMP;
20112 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
20113 << getOpenMPClauseNameForDiag(C: OMPC_copyin)
20114 << getOpenMPDirectiveName(D: OMPD_threadprivate, Ver: OMPVersion);
20115 continue;
20116 }
20117
20118 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20119 // A variable of class type (or array thereof) that appears in a
20120 // copyin clause requires an accessible, unambiguous copy assignment
20121 // operator for the class type.
20122 QualType ElemType =
20123 getASTContext().getBaseElementType(QT: Type).getNonReferenceType();
20124 VarDecl *SrcVD =
20125 buildVarDecl(SemaRef, Loc: DE->getBeginLoc(), Type: ElemType.getUnqualifiedType(),
20126 Name: ".copyin.src", Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20127 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20128 S&: SemaRef, D: SrcVD, Ty: ElemType.getUnqualifiedType(), Loc: DE->getExprLoc());
20129 VarDecl *DstVD =
20130 buildVarDecl(SemaRef, Loc: DE->getBeginLoc(), Type: ElemType, Name: ".copyin.dst",
20131 Attrs: VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20132 DeclRefExpr *PseudoDstExpr =
20133 buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: ElemType, Loc: DE->getExprLoc());
20134 // For arrays generate assignment operation for single element and replace
20135 // it by the original array element in CodeGen.
20136 ExprResult AssignmentOp =
20137 SemaRef.BuildBinOp(/*S=*/nullptr, OpLoc: DE->getExprLoc(), Opc: BO_Assign,
20138 LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
20139 if (AssignmentOp.isInvalid())
20140 continue;
20141 AssignmentOp =
20142 SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: DE->getExprLoc(),
20143 /*DiscardedValue=*/false);
20144 if (AssignmentOp.isInvalid())
20145 continue;
20146
20147 DSAStack->addDSA(D: VD, E: DE, A: OMPC_copyin);
20148 Vars.push_back(Elt: DE);
20149 SrcExprs.push_back(Elt: PseudoSrcExpr);
20150 DstExprs.push_back(Elt: PseudoDstExpr);
20151 AssignmentOps.push_back(Elt: AssignmentOp.get());
20152 }
20153
20154 if (Vars.empty())
20155 return nullptr;
20156
20157 return OMPCopyinClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
20158 VL: Vars, SrcExprs, DstExprs, AssignmentOps);
20159}
20160
20161OMPClause *SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
20162 SourceLocation StartLoc,
20163 SourceLocation LParenLoc,
20164 SourceLocation EndLoc) {
20165 SmallVector<Expr *, 8> Vars;
20166 SmallVector<Expr *, 8> SrcExprs;
20167 SmallVector<Expr *, 8> DstExprs;
20168 SmallVector<Expr *, 8> AssignmentOps;
20169 for (Expr *RefExpr : VarList) {
20170 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20171 SourceLocation ELoc;
20172 SourceRange ERange;
20173 Expr *SimpleRefExpr = RefExpr;
20174 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
20175 if (Res.second) {
20176 // It will be analyzed later.
20177 Vars.push_back(Elt: RefExpr);
20178 SrcExprs.push_back(Elt: nullptr);
20179 DstExprs.push_back(Elt: nullptr);
20180 AssignmentOps.push_back(Elt: nullptr);
20181 }
20182 ValueDecl *D = Res.first;
20183 if (!D)
20184 continue;
20185
20186 QualType Type = D->getType();
20187 auto *VD = dyn_cast<VarDecl>(Val: D);
20188
20189 // OpenMP [2.14.4.2, Restrictions, p.2]
20190 // A list item that appears in a copyprivate clause may not appear in a
20191 // private or firstprivate clause on the single construct.
20192 if (!VD || !DSAStack->isThreadPrivate(D: VD)) {
20193 DSAStackTy::DSAVarData DVar =
20194 DSAStack->getTopDSA(D, /*FromParent=*/false);
20195 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20196 DVar.RefExpr) {
20197 Diag(Loc: ELoc, DiagID: diag::err_omp_wrong_dsa)
20198 << getOpenMPClauseNameForDiag(C: DVar.CKind)
20199 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate);
20200 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20201 continue;
20202 }
20203
20204 // OpenMP [2.11.4.2, Restrictions, p.1]
20205 // All list items that appear in a copyprivate clause must be either
20206 // threadprivate or private in the enclosing context.
20207 if (DVar.CKind == OMPC_unknown) {
20208 DVar = DSAStack->getImplicitDSA(D, FromParent: false);
20209 if (DVar.CKind == OMPC_shared) {
20210 Diag(Loc: ELoc, DiagID: diag::err_omp_required_access)
20211 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate)
20212 << "threadprivate or private in the enclosing context";
20213 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20214 continue;
20215 }
20216 }
20217 }
20218
20219 // Variably modified types are not supported.
20220 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
20221 unsigned OMPVersion = getLangOpts().OpenMP;
20222 Diag(Loc: ELoc, DiagID: diag::err_omp_variably_modified_type_not_supported)
20223 << getOpenMPClauseNameForDiag(C: OMPC_copyprivate) << Type
20224 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
20225 Ver: OMPVersion);
20226 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20227 VarDecl::DeclarationOnly;
20228 Diag(Loc: D->getLocation(),
20229 DiagID: IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20230 << D;
20231 continue;
20232 }
20233
20234 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20235 // A variable of class type (or array thereof) that appears in a
20236 // copyin clause requires an accessible, unambiguous copy assignment
20237 // operator for the class type.
20238 Type = getASTContext()
20239 .getBaseElementType(QT: Type.getNonReferenceType())
20240 .getUnqualifiedType();
20241 VarDecl *SrcVD =
20242 buildVarDecl(SemaRef, Loc: RefExpr->getBeginLoc(), Type, Name: ".copyprivate.src",
20243 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
20244 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(S&: SemaRef, D: SrcVD, Ty: Type, Loc: ELoc);
20245 VarDecl *DstVD =
20246 buildVarDecl(SemaRef, Loc: RefExpr->getBeginLoc(), Type, Name: ".copyprivate.dst",
20247 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr);
20248 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: Type, Loc: ELoc);
20249 ExprResult AssignmentOp = SemaRef.BuildBinOp(
20250 DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
20251 if (AssignmentOp.isInvalid())
20252 continue;
20253 AssignmentOp = SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: ELoc,
20254 /*DiscardedValue=*/false);
20255 if (AssignmentOp.isInvalid())
20256 continue;
20257
20258 // No need to mark vars as copyprivate, they are already threadprivate or
20259 // implicitly private.
20260 assert(VD || isOpenMPCapturedDecl(D));
20261 Vars.push_back(
20262 Elt: VD ? RefExpr->IgnoreParens()
20263 : buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false));
20264 SrcExprs.push_back(Elt: PseudoSrcExpr);
20265 DstExprs.push_back(Elt: PseudoDstExpr);
20266 AssignmentOps.push_back(Elt: AssignmentOp.get());
20267 }
20268
20269 if (Vars.empty())
20270 return nullptr;
20271
20272 return OMPCopyprivateClause::Create(C: getASTContext(), StartLoc, LParenLoc,
20273 EndLoc, VL: Vars, SrcExprs, DstExprs,
20274 AssignmentOps);
20275}
20276
20277OMPClause *SemaOpenMP::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
20278 SourceLocation StartLoc,
20279 SourceLocation LParenLoc,
20280 SourceLocation EndLoc) {
20281 if (VarList.empty())
20282 return nullptr;
20283
20284 return OMPFlushClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
20285 VL: VarList);
20286}
20287
20288/// Tries to find omp_depend_t. type.
20289static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
20290 bool Diagnose = true) {
20291 QualType OMPDependT = Stack->getOMPDependT();
20292 if (!OMPDependT.isNull())
20293 return true;
20294 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_depend_t");
20295 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
20296 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
20297 if (Diagnose)
20298 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_depend_t";
20299 return false;
20300 }
20301 Stack->setOMPDependT(PT.get());
20302 return true;
20303}
20304
20305OMPClause *SemaOpenMP::ActOnOpenMPDepobjClause(Expr *Depobj,
20306 SourceLocation StartLoc,
20307 SourceLocation LParenLoc,
20308 SourceLocation EndLoc) {
20309 if (!Depobj)
20310 return nullptr;
20311
20312 bool OMPDependTFound = findOMPDependT(S&: SemaRef, Loc: StartLoc, DSAStack);
20313
20314 // OpenMP 5.0, 2.17.10.1 depobj Construct
20315 // depobj is an lvalue expression of type omp_depend_t.
20316 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
20317 !Depobj->isInstantiationDependent() &&
20318 !Depobj->containsUnexpandedParameterPack() &&
20319 (OMPDependTFound && !getASTContext().typesAreCompatible(
20320 DSAStack->getOMPDependT(), T2: Depobj->getType(),
20321 /*CompareUnqualified=*/true))) {
20322 Diag(Loc: Depobj->getExprLoc(), DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
20323 << 0 << Depobj->getType() << Depobj->getSourceRange();
20324 }
20325
20326 if (!Depobj->isLValue()) {
20327 Diag(Loc: Depobj->getExprLoc(), DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
20328 << 1 << Depobj->getSourceRange();
20329 }
20330
20331 return OMPDepobjClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
20332 Depobj);
20333}
20334
20335namespace {
20336// Utility struct that gathers the related info for doacross clause.
20337struct DoacrossDataInfoTy {
20338 // The list of expressions.
20339 SmallVector<Expr *, 8> Vars;
20340 // The OperatorOffset for doacross loop.
20341 DSAStackTy::OperatorOffsetTy OpsOffs;
20342 // The depended loop count.
20343 llvm::APSInt TotalDepCount;
20344};
20345} // namespace
20346static DoacrossDataInfoTy
20347ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource,
20348 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
20349 SourceLocation EndLoc) {
20350
20351 SmallVector<Expr *, 8> Vars;
20352 DSAStackTy::OperatorOffsetTy OpsOffs;
20353 llvm::APSInt DepCounter(/*BitWidth=*/32);
20354 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20355
20356 if (const Expr *OrderedCountExpr =
20357 Stack->getParentOrderedRegionParam().first) {
20358 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Ctx: SemaRef.Context);
20359 TotalDepCount.setIsUnsigned(/*Val=*/true);
20360 }
20361
20362 for (Expr *RefExpr : VarList) {
20363 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
20364 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
20365 // It will be analyzed later.
20366 Vars.push_back(Elt: RefExpr);
20367 continue;
20368 }
20369
20370 SourceLocation ELoc = RefExpr->getExprLoc();
20371 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20372 if (!IsSource) {
20373 if (Stack->getParentOrderedRegionParam().first &&
20374 DepCounter >= TotalDepCount) {
20375 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_unexpected_expr);
20376 continue;
20377 }
20378 ++DepCounter;
20379 // OpenMP [2.13.9, Summary]
20380 // depend(dependence-type : vec), where dependence-type is:
20381 // 'sink' and where vec is the iteration vector, which has the form:
20382 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20383 // where n is the value specified by the ordered clause in the loop
20384 // directive, xi denotes the loop iteration variable of the i-th nested
20385 // loop associated with the loop directive, and di is a constant
20386 // non-negative integer.
20387 if (SemaRef.CurContext->isDependentContext()) {
20388 // It will be analyzed later.
20389 Vars.push_back(Elt: RefExpr);
20390 continue;
20391 }
20392 SimpleExpr = SimpleExpr->IgnoreImplicit();
20393 OverloadedOperatorKind OOK = OO_None;
20394 SourceLocation OOLoc;
20395 Expr *LHS = SimpleExpr;
20396 Expr *RHS = nullptr;
20397 if (auto *BO = dyn_cast<BinaryOperator>(Val: SimpleExpr)) {
20398 OOK = BinaryOperator::getOverloadedOperator(Opc: BO->getOpcode());
20399 OOLoc = BO->getOperatorLoc();
20400 LHS = BO->getLHS()->IgnoreParenImpCasts();
20401 RHS = BO->getRHS()->IgnoreParenImpCasts();
20402 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Val: SimpleExpr)) {
20403 OOK = OCE->getOperator();
20404 OOLoc = OCE->getOperatorLoc();
20405 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20406 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20407 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Val: SimpleExpr)) {
20408 OOK = MCE->getMethodDecl()
20409 ->getNameInfo()
20410 .getName()
20411 .getCXXOverloadedOperator();
20412 OOLoc = MCE->getCallee()->getExprLoc();
20413 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
20414 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20415 }
20416 SourceLocation ELoc;
20417 SourceRange ERange;
20418 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: LHS, ELoc, ERange);
20419 if (Res.second) {
20420 // It will be analyzed later.
20421 Vars.push_back(Elt: RefExpr);
20422 }
20423 ValueDecl *D = Res.first;
20424 if (!D)
20425 continue;
20426
20427 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
20428 SemaRef.Diag(Loc: OOLoc, DiagID: diag::err_omp_depend_sink_expected_plus_minus);
20429 continue;
20430 }
20431 if (RHS) {
20432 ExprResult RHSRes =
20433 SemaRef.OpenMP().VerifyPositiveIntegerConstantInClause(
20434 E: RHS, CKind: OMPC_depend, /*StrictlyPositive=*/false);
20435 if (RHSRes.isInvalid())
20436 continue;
20437 }
20438 if (!SemaRef.CurContext->isDependentContext() &&
20439 Stack->getParentOrderedRegionParam().first &&
20440 DepCounter != Stack->isParentLoopControlVariable(D).first) {
20441 const ValueDecl *VD =
20442 Stack->getParentLoopControlVariable(I: DepCounter.getZExtValue());
20443 if (VD)
20444 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
20445 << 1 << VD;
20446 else
20447 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
20448 << 0;
20449 continue;
20450 }
20451 OpsOffs.emplace_back(Args&: RHS, Args&: OOK);
20452 }
20453 Vars.push_back(Elt: RefExpr->IgnoreParenImpCasts());
20454 }
20455 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
20456 TotalDepCount > VarList.size() &&
20457 Stack->getParentOrderedRegionParam().first &&
20458 Stack->getParentLoopControlVariable(I: VarList.size() + 1)) {
20459 SemaRef.Diag(Loc: EndLoc, DiagID: diag::err_omp_depend_sink_expected_loop_iteration)
20460 << 1 << Stack->getParentLoopControlVariable(I: VarList.size() + 1);
20461 }
20462 return {.Vars: Vars, .OpsOffs: OpsOffs, .TotalDepCount: TotalDepCount};
20463}
20464
20465OMPClause *SemaOpenMP::ActOnOpenMPDependClause(
20466 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
20467 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20468 SourceLocation EndLoc) {
20469 OpenMPDependClauseKind DepKind = Data.DepKind;
20470 SourceLocation DepLoc = Data.DepLoc;
20471 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
20472 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
20473 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
20474 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(C: OMPC_depend);
20475 return nullptr;
20476 }
20477 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
20478 DepKind == OMPC_DEPEND_mutexinoutset) {
20479 Diag(Loc: DepLoc, DiagID: diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20480 return nullptr;
20481 }
20482 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
20483 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20484 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
20485 DepKind == OMPC_DEPEND_sink ||
20486 ((getLangOpts().OpenMP < 50 ||
20487 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20488 DepKind == OMPC_DEPEND_depobj))) {
20489 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
20490 OMPC_DEPEND_outallmemory,
20491 OMPC_DEPEND_inoutallmemory};
20492 if (getLangOpts().OpenMP < 50 ||
20493 DSAStack->getCurrentDirective() == OMPD_depobj)
20494 Except.push_back(Elt: OMPC_DEPEND_depobj);
20495 if (getLangOpts().OpenMP < 51)
20496 Except.push_back(Elt: OMPC_DEPEND_inoutset);
20497 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
20498 ? "depend modifier(iterator) or "
20499 : "";
20500 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
20501 << Expected + getListOfPossibleValues(K: OMPC_depend, /*First=*/0,
20502 /*Last=*/OMPC_DEPEND_unknown,
20503 Exclude: Except)
20504 << getOpenMPClauseNameForDiag(C: OMPC_depend);
20505 return nullptr;
20506 }
20507 if (DepModifier &&
20508 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20509 Diag(Loc: DepModifier->getExprLoc(),
20510 DiagID: diag::err_omp_depend_sink_source_with_modifier);
20511 return nullptr;
20512 }
20513 if (DepModifier &&
20514 !DepModifier->getType()->isSpecificBuiltinType(K: BuiltinType::OMPIterator))
20515 Diag(Loc: DepModifier->getExprLoc(), DiagID: diag::err_omp_depend_modifier_not_iterator);
20516
20517 SmallVector<Expr *, 8> Vars;
20518 DSAStackTy::OperatorOffsetTy OpsOffs;
20519 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20520
20521 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20522 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
20523 SemaRef, IsSource: DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
20524 Vars = VarOffset.Vars;
20525 OpsOffs = VarOffset.OpsOffs;
20526 TotalDepCount = VarOffset.TotalDepCount;
20527 } else {
20528 for (Expr *RefExpr : VarList) {
20529 assert(RefExpr && "NULL expr in OpenMP shared clause.");
20530 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
20531 // It will be analyzed later.
20532 Vars.push_back(Elt: RefExpr);
20533 continue;
20534 }
20535
20536 SourceLocation ELoc = RefExpr->getExprLoc();
20537 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20538 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
20539 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
20540 if (OMPDependTFound)
20541 OMPDependTFound = findOMPDependT(S&: SemaRef, Loc: StartLoc, DSAStack,
20542 Diagnose: DepKind == OMPC_DEPEND_depobj);
20543 if (DepKind == OMPC_DEPEND_depobj) {
20544 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20545 // List items used in depend clauses with the depobj dependence type
20546 // must be expressions of the omp_depend_t type.
20547 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20548 !RefExpr->isInstantiationDependent() &&
20549 !RefExpr->containsUnexpandedParameterPack() &&
20550 (OMPDependTFound &&
20551 !getASTContext().hasSameUnqualifiedType(
20552 DSAStack->getOMPDependT(), T2: RefExpr->getType()))) {
20553 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
20554 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20555 continue;
20556 }
20557 if (!RefExpr->isLValue()) {
20558 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_omp_depend_t_lvalue)
20559 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20560 continue;
20561 }
20562 } else {
20563 // OpenMP 5.0 [2.17.11, Restrictions]
20564 // List items used in depend clauses cannot be zero-length array
20565 // sections.
20566 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20567 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: SimpleExpr);
20568 if (OASE) {
20569 QualType BaseType =
20570 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
20571 if (BaseType.isNull())
20572 return nullptr;
20573 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20574 ExprTy = ATy->getElementType();
20575 else
20576 ExprTy = BaseType->getPointeeType();
20577 if (BaseType.isNull() || ExprTy.isNull())
20578 return nullptr;
20579 ExprTy = ExprTy.getNonReferenceType();
20580 const Expr *Length = OASE->getLength();
20581 Expr::EvalResult Result;
20582 if (Length && !Length->isValueDependent() &&
20583 Length->EvaluateAsInt(Result, Ctx: getASTContext()) &&
20584 Result.Val.getInt().isZero()) {
20585 Diag(Loc: ELoc,
20586 DiagID: diag::err_omp_depend_zero_length_array_section_not_allowed)
20587 << SimpleExpr->getSourceRange();
20588 continue;
20589 }
20590 }
20591
20592 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20593 // List items used in depend clauses with the in, out, inout,
20594 // inoutset, or mutexinoutset dependence types cannot be
20595 // expressions of the omp_depend_t type.
20596 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20597 !RefExpr->isInstantiationDependent() &&
20598 !RefExpr->containsUnexpandedParameterPack() &&
20599 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20600 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
20601 ExprTy.getTypePtr()))) {
20602 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
20603 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20604 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20605 << RefExpr->getSourceRange();
20606 continue;
20607 }
20608
20609 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: SimpleExpr);
20610 if (ASE && !ASE->getBase()->isTypeDependent() &&
20611 !ASE->getBase()
20612 ->getType()
20613 .getNonReferenceType()
20614 ->isPointerType() &&
20615 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20616 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
20617 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20618 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20619 << RefExpr->getSourceRange();
20620 continue;
20621 }
20622
20623 ExprResult Res;
20624 {
20625 Sema::TentativeAnalysisScope Trap(SemaRef);
20626 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf,
20627 InputExpr: RefExpr->IgnoreParenImpCasts());
20628 }
20629 if (!Res.isUsable() && !isa<ArraySectionExpr>(Val: SimpleExpr) &&
20630 !isa<OMPArrayShapingExpr>(Val: SimpleExpr)) {
20631 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
20632 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20633 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20634 << RefExpr->getSourceRange();
20635 continue;
20636 }
20637 }
20638 }
20639 Vars.push_back(Elt: RefExpr->IgnoreParenImpCasts());
20640 }
20641 }
20642
20643 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20644 DepKind != OMPC_DEPEND_outallmemory &&
20645 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20646 return nullptr;
20647
20648 auto *C = OMPDependClause::Create(
20649 C: getASTContext(), StartLoc, LParenLoc, EndLoc,
20650 Data: {.DepKind: DepKind, .DepLoc: DepLoc, .ColonLoc: Data.ColonLoc, .OmpAllMemoryLoc: Data.OmpAllMemoryLoc}, DepModifier, VL: Vars,
20651 NumLoops: TotalDepCount.getZExtValue());
20652 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20653 DSAStack->isParentOrderedRegion())
20654 DSAStack->addDoacrossDependClause(C, OpsOffs);
20655 return C;
20656}
20657
20658OMPClause *SemaOpenMP::ActOnOpenMPDeviceClause(
20659 OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc,
20660 SourceLocation LParenLoc, SourceLocation ModifierLoc,
20661 SourceLocation EndLoc) {
20662 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
20663 "Unexpected device modifier in OpenMP < 50.");
20664
20665 bool ErrorFound = false;
20666 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
20667 std::string Values =
20668 getListOfPossibleValues(K: OMPC_device, /*First=*/0, Last: OMPC_DEVICE_unknown);
20669 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
20670 << Values << getOpenMPClauseNameForDiag(C: OMPC_device);
20671 ErrorFound = true;
20672 }
20673
20674 Expr *ValExpr = Device;
20675 Stmt *HelperValStmt = nullptr;
20676
20677 // OpenMP [2.9.1, Restrictions]
20678 // The device expression must evaluate to a non-negative integer value.
20679 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_device,
20680 /*StrictlyPositive=*/false) ||
20681 ErrorFound;
20682 if (ErrorFound)
20683 return nullptr;
20684
20685 // OpenMP 5.0 [2.12.5, Restrictions]
20686 // In case of ancestor device-modifier, a requires directive with
20687 // the reverse_offload clause must be specified.
20688 if (Modifier == OMPC_DEVICE_ancestor) {
20689 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20690 SemaRef.targetDiag(
20691 Loc: StartLoc,
20692 DiagID: diag::err_omp_device_ancestor_without_requires_reverse_offload);
20693 ErrorFound = true;
20694 }
20695 }
20696
20697 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20698 OpenMPDirectiveKind CaptureRegion =
20699 getOpenMPCaptureRegionForClause(DKind, CKind: OMPC_device, OpenMPVersion: getLangOpts().OpenMP);
20700 if (CaptureRegion != OMPD_unknown &&
20701 !SemaRef.CurContext->isDependentContext()) {
20702 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
20703 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20704 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
20705 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
20706 }
20707
20708 return new (getASTContext())
20709 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20710 LParenLoc, ModifierLoc, EndLoc);
20711}
20712
20713static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
20714 DSAStackTy *Stack, QualType QTy,
20715 bool FullCheck = true) {
20716 if (SemaRef.RequireCompleteType(Loc: SL, T: QTy, DiagID: diag::err_incomplete_type))
20717 return false;
20718 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20719 !QTy.isTriviallyCopyableType(Context: SemaRef.Context))
20720 SemaRef.Diag(Loc: SL, DiagID: diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20721 return true;
20722}
20723
20724/// Return true if it can be proven that the provided array expression
20725/// (array section or array subscript) does NOT specify the whole size of the
20726/// array whose base type is \a BaseQTy.
20727static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
20728 const Expr *E,
20729 QualType BaseQTy) {
20730 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: E);
20731
20732 // If this is an array subscript, it refers to the whole size if the size of
20733 // the dimension is constant and equals 1. Also, an array section assumes the
20734 // format of an array subscript if no colon is used.
20735 if (isa<ArraySubscriptExpr>(Val: E) ||
20736 (OASE && OASE->getColonLocFirst().isInvalid())) {
20737 if (const auto *ATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr()))
20738 return ATy->getSExtSize() != 1;
20739 // Size can't be evaluated statically.
20740 return false;
20741 }
20742
20743 assert(OASE && "Expecting array section if not an array subscript.");
20744 const Expr *LowerBound = OASE->getLowerBound();
20745 const Expr *Length = OASE->getLength();
20746
20747 // If there is a lower bound that does not evaluates to zero, we are not
20748 // covering the whole dimension.
20749 if (LowerBound) {
20750 Expr::EvalResult Result;
20751 if (!LowerBound->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
20752 return false; // Can't get the integer value as a constant.
20753
20754 llvm::APSInt ConstLowerBound = Result.Val.getInt();
20755 if (ConstLowerBound.getSExtValue())
20756 return true;
20757 }
20758
20759 // If we don't have a length we covering the whole dimension.
20760 if (!Length)
20761 return false;
20762
20763 // If the base is a pointer, we don't have a way to get the size of the
20764 // pointee.
20765 if (BaseQTy->isPointerType())
20766 return false;
20767
20768 // We can only check if the length is the same as the size of the dimension
20769 // if we have a constant array.
20770 const auto *CATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr());
20771 if (!CATy)
20772 return false;
20773
20774 Expr::EvalResult Result;
20775 if (!Length->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
20776 return false; // Can't get the integer value as a constant.
20777
20778 llvm::APSInt ConstLength = Result.Val.getInt();
20779 return CATy->getSExtSize() != ConstLength.getSExtValue();
20780}
20781
20782// Return true if it can be proven that the provided array expression (array
20783// section or array subscript) does NOT specify a single element of the array
20784// whose base type is \a BaseQTy.
20785static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
20786 const Expr *E,
20787 QualType BaseQTy) {
20788 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: E);
20789
20790 // An array subscript always refer to a single element. Also, an array section
20791 // assumes the format of an array subscript if no colon is used.
20792 if (isa<ArraySubscriptExpr>(Val: E) ||
20793 (OASE && OASE->getColonLocFirst().isInvalid()))
20794 return false;
20795
20796 assert(OASE && "Expecting array section if not an array subscript.");
20797 const Expr *Length = OASE->getLength();
20798
20799 // If we don't have a length we have to check if the array has unitary size
20800 // for this dimension. Also, we should always expect a length if the base type
20801 // is pointer.
20802 if (!Length) {
20803 if (const auto *ATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr()))
20804 return ATy->getSExtSize() != 1;
20805 // We cannot assume anything.
20806 return false;
20807 }
20808
20809 // Check if the length evaluates to 1.
20810 Expr::EvalResult Result;
20811 if (!Length->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
20812 return false; // Can't get the integer value as a constant.
20813
20814 llvm::APSInt ConstLength = Result.Val.getInt();
20815 return ConstLength.getSExtValue() != 1;
20816}
20817
20818// The base of elements of list in a map clause have to be either:
20819// - a reference to variable or field.
20820// - a member expression.
20821// - an array expression.
20822//
20823// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20824// reference to 'r'.
20825//
20826// If we have:
20827//
20828// struct SS {
20829// Bla S;
20830// foo() {
20831// #pragma omp target map (S.Arr[:12]);
20832// }
20833// }
20834//
20835// We want to retrieve the member expression 'this->S';
20836
20837// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20838// If a list item is an array section, it must specify contiguous storage.
20839//
20840// For this restriction it is sufficient that we make sure only references
20841// to variables or fields and array expressions, and that no array sections
20842// exist except in the rightmost expression (unless they cover the whole
20843// dimension of the array). E.g. these would be invalid:
20844//
20845// r.ArrS[3:5].Arr[6:7]
20846//
20847// r.ArrS[3:5].x
20848//
20849// but these would be valid:
20850// r.ArrS[3].Arr[6:7]
20851//
20852// r.ArrS[3].x
20853namespace {
20854class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20855 Sema &SemaRef;
20856 OpenMPClauseKind CKind = OMPC_unknown;
20857 OpenMPDirectiveKind DKind = OMPD_unknown;
20858 OMPClauseMappableExprCommon::MappableExprComponentList &Components;
20859 bool IsNonContiguous = false;
20860 bool NoDiagnose = false;
20861 const Expr *RelevantExpr = nullptr;
20862 bool AllowUnitySizeArraySection = true;
20863 bool AllowWholeSizeArraySection = true;
20864 bool AllowAnotherPtr = true;
20865 SourceLocation ELoc;
20866 SourceRange ERange;
20867
20868 void emitErrorMsg() {
20869 // If nothing else worked, this is not a valid map clause expression.
20870 if (SemaRef.getLangOpts().OpenMP < 50) {
20871 SemaRef.Diag(Loc: ELoc,
20872 DiagID: diag::err_omp_expected_named_var_member_or_array_expression)
20873 << ERange;
20874 } else {
20875 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20876 << getOpenMPClauseNameForDiag(C: CKind) << ERange;
20877 }
20878 }
20879
20880public:
20881 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
20882 if (!isa<VarDecl>(Val: DRE->getDecl())) {
20883 emitErrorMsg();
20884 return false;
20885 }
20886 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20887 RelevantExpr = DRE;
20888 // Record the component.
20889 Components.emplace_back(Args&: DRE, Args: DRE->getDecl(), Args&: IsNonContiguous);
20890 return true;
20891 }
20892
20893 bool VisitMemberExpr(MemberExpr *ME) {
20894 Expr *E = ME;
20895 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
20896
20897 if (isa<CXXThisExpr>(Val: BaseE)) {
20898 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20899 // We found a base expression: this->Val.
20900 RelevantExpr = ME;
20901 } else {
20902 E = BaseE;
20903 }
20904
20905 if (!isa<FieldDecl>(Val: ME->getMemberDecl())) {
20906 if (!NoDiagnose) {
20907 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_access_to_data_field)
20908 << ME->getSourceRange();
20909 return false;
20910 }
20911 if (RelevantExpr)
20912 return false;
20913 return Visit(S: E);
20914 }
20915
20916 auto *FD = cast<FieldDecl>(Val: ME->getMemberDecl());
20917
20918 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
20919 // A bit-field cannot appear in a map clause.
20920 //
20921 if (FD->isBitField()) {
20922 if (!NoDiagnose) {
20923 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_bit_fields_forbidden_in_clause)
20924 << ME->getSourceRange() << getOpenMPClauseNameForDiag(C: CKind);
20925 return false;
20926 }
20927 if (RelevantExpr)
20928 return false;
20929 return Visit(S: E);
20930 }
20931
20932 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20933 // If the type of a list item is a reference to a type T then the type
20934 // will be considered to be T for all purposes of this clause.
20935 QualType CurType = BaseE->getType().getNonReferenceType();
20936
20937 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
20938 // A list item cannot be a variable that is a member of a structure with
20939 // a union type.
20940 //
20941 if (CurType->isUnionType()) {
20942 if (!NoDiagnose) {
20943 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_union_type_not_allowed)
20944 << ME->getSourceRange();
20945 return false;
20946 }
20947 return RelevantExpr || Visit(S: E);
20948 }
20949
20950 // If we got a member expression, we should not expect any array section
20951 // before that:
20952 //
20953 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
20954 // If a list item is an element of a structure, only the rightmost symbol
20955 // of the variable reference can be an array section.
20956 //
20957 AllowUnitySizeArraySection = false;
20958 AllowWholeSizeArraySection = false;
20959
20960 // Record the component.
20961 Components.emplace_back(Args&: ME, Args&: FD, Args&: IsNonContiguous);
20962 return RelevantExpr || Visit(S: E);
20963 }
20964
20965 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
20966 Expr *E = AE->getBase()->IgnoreParenImpCasts();
20967
20968 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
20969 if (!NoDiagnose) {
20970 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
20971 << 0 << AE->getSourceRange();
20972 return false;
20973 }
20974 return RelevantExpr || Visit(S: E);
20975 }
20976
20977 // If we got an array subscript that express the whole dimension we
20978 // can have any array expressions before. If it only expressing part of
20979 // the dimension, we can only have unitary-size array expressions.
20980 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, E: AE, BaseQTy: E->getType()))
20981 AllowWholeSizeArraySection = false;
20982
20983 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E->IgnoreParenCasts())) {
20984 Expr::EvalResult Result;
20985 if (!AE->getIdx()->isValueDependent() &&
20986 AE->getIdx()->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()) &&
20987 !Result.Val.getInt().isZero()) {
20988 SemaRef.Diag(Loc: AE->getIdx()->getExprLoc(),
20989 DiagID: diag::err_omp_invalid_map_this_expr);
20990 SemaRef.Diag(Loc: AE->getIdx()->getExprLoc(),
20991 DiagID: diag::note_omp_invalid_subscript_on_this_ptr_map);
20992 }
20993 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20994 RelevantExpr = TE;
20995 }
20996
20997 // Record the component - we don't have any declaration associated.
20998 Components.emplace_back(Args&: AE, Args: nullptr, Args&: IsNonContiguous);
20999
21000 return RelevantExpr || Visit(S: E);
21001 }
21002
21003 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
21004 // After OMP 5.0 Array section in reduction clause will be implicitly
21005 // mapped
21006 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
21007 "Array sections cannot be implicitly mapped.");
21008 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21009 QualType CurType =
21010 ArraySectionExpr::getBaseOriginalType(Base: E).getCanonicalType();
21011
21012 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21013 // If the type of a list item is a reference to a type T then the type
21014 // will be considered to be T for all purposes of this clause.
21015 if (CurType->isReferenceType())
21016 CurType = CurType->getPointeeType();
21017
21018 bool IsPointer = CurType->isAnyPointerType();
21019
21020 if (!IsPointer && !CurType->isArrayType()) {
21021 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_expected_base_var_name)
21022 << 0 << OASE->getSourceRange();
21023 return false;
21024 }
21025
21026 bool NotWhole =
21027 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, E: OASE, BaseQTy: CurType);
21028 bool NotUnity =
21029 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, E: OASE, BaseQTy: CurType);
21030
21031 if (AllowWholeSizeArraySection) {
21032 // Any array section is currently allowed. Allowing a whole size array
21033 // section implies allowing a unity array section as well.
21034 //
21035 // If this array section refers to the whole dimension we can still
21036 // accept other array sections before this one, except if the base is a
21037 // pointer. Otherwise, only unitary sections are accepted.
21038 if (NotWhole || IsPointer)
21039 AllowWholeSizeArraySection = false;
21040 } else if (DKind == OMPD_target_update &&
21041 SemaRef.getLangOpts().OpenMP >= 50) {
21042 if (IsPointer && !AllowAnotherPtr)
21043 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_section_length_undefined)
21044 << /*array of unknown bound */ 1;
21045 else
21046 IsNonContiguous = true;
21047 } else if (AllowUnitySizeArraySection && NotUnity) {
21048 // A unity or whole array section is not allowed and that is not
21049 // compatible with the properties of the current array section.
21050 if (NoDiagnose)
21051 return false;
21052 SemaRef.Diag(Loc: ELoc,
21053 DiagID: diag::err_array_section_does_not_specify_contiguous_storage)
21054 << OASE->getSourceRange();
21055 return false;
21056 }
21057
21058 if (IsPointer)
21059 AllowAnotherPtr = false;
21060
21061 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E)) {
21062 Expr::EvalResult ResultR;
21063 Expr::EvalResult ResultL;
21064 if (!OASE->getLength()->isValueDependent() &&
21065 OASE->getLength()->EvaluateAsInt(Result&: ResultR, Ctx: SemaRef.getASTContext()) &&
21066 !ResultR.Val.getInt().isOne()) {
21067 SemaRef.Diag(Loc: OASE->getLength()->getExprLoc(),
21068 DiagID: diag::err_omp_invalid_map_this_expr);
21069 SemaRef.Diag(Loc: OASE->getLength()->getExprLoc(),
21070 DiagID: diag::note_omp_invalid_length_on_this_ptr_mapping);
21071 }
21072 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
21073 OASE->getLowerBound()->EvaluateAsInt(Result&: ResultL,
21074 Ctx: SemaRef.getASTContext()) &&
21075 !ResultL.Val.getInt().isZero()) {
21076 SemaRef.Diag(Loc: OASE->getLowerBound()->getExprLoc(),
21077 DiagID: diag::err_omp_invalid_map_this_expr);
21078 SemaRef.Diag(Loc: OASE->getLowerBound()->getExprLoc(),
21079 DiagID: diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21080 }
21081 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21082 RelevantExpr = TE;
21083 }
21084
21085 // Record the component - we don't have any declaration associated.
21086 Components.emplace_back(Args&: OASE, Args: nullptr, /*IsNonContiguous=*/Args: false);
21087 return RelevantExpr || Visit(S: E);
21088 }
21089 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21090 Expr *Base = E->getBase();
21091
21092 // Record the component - we don't have any declaration associated.
21093 Components.emplace_back(Args&: E, Args: nullptr, Args&: IsNonContiguous);
21094
21095 return Visit(S: Base->IgnoreParenImpCasts());
21096 }
21097
21098 bool VisitUnaryOperator(UnaryOperator *UO) {
21099 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
21100 UO->getOpcode() != UO_Deref) {
21101 emitErrorMsg();
21102 return false;
21103 }
21104 if (!RelevantExpr) {
21105 // Record the component if haven't found base decl.
21106 Components.emplace_back(Args&: UO, Args: nullptr, /*IsNonContiguous=*/Args: false);
21107 }
21108 return RelevantExpr || Visit(S: UO->getSubExpr()->IgnoreParenImpCasts());
21109 }
21110 bool VisitBinaryOperator(BinaryOperator *BO) {
21111 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
21112 emitErrorMsg();
21113 return false;
21114 }
21115
21116 // Pointer arithmetic is the only thing we expect to happen here so after we
21117 // make sure the binary operator is a pointer type, the only thing we need
21118 // to do is to visit the subtree that has the same type as root (so that we
21119 // know the other subtree is just an offset)
21120 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
21121 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
21122 Components.emplace_back(Args&: BO, Args: nullptr, Args: false);
21123 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
21124 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
21125 "Either LHS or RHS have base decl inside");
21126 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
21127 return RelevantExpr || Visit(S: LE);
21128 return RelevantExpr || Visit(S: RE);
21129 }
21130 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21131 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21132 RelevantExpr = CTE;
21133 Components.emplace_back(Args&: CTE, Args: nullptr, Args&: IsNonContiguous);
21134 return true;
21135 }
21136 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21137 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21138 Components.emplace_back(Args&: COCE, Args: nullptr, Args&: IsNonContiguous);
21139 return true;
21140 }
21141 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21142 Expr *Source = E->getSourceExpr();
21143 if (!Source) {
21144 emitErrorMsg();
21145 return false;
21146 }
21147 return Visit(S: Source);
21148 }
21149 bool VisitStmt(Stmt *) {
21150 emitErrorMsg();
21151 return false;
21152 }
21153 const Expr *getFoundBase() const { return RelevantExpr; }
21154 explicit MapBaseChecker(
21155 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
21156 OMPClauseMappableExprCommon::MappableExprComponentList &Components,
21157 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21158 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21159 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21160};
21161} // namespace
21162
21163/// Return the expression of the base of the mappable expression or null if it
21164/// cannot be determined and do all the necessary checks to see if the
21165/// expression is valid as a standalone mappable expression. In the process,
21166/// record all the components of the expression.
21167static const Expr *checkMapClauseExpressionBase(
21168 Sema &SemaRef, Expr *E,
21169 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
21170 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
21171 SourceLocation ELoc = E->getExprLoc();
21172 SourceRange ERange = E->getSourceRange();
21173 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21174 ERange);
21175 if (Checker.Visit(S: E->IgnoreParens())) {
21176 // Check if the highest dimension array section has length specified
21177 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21178 (CKind == OMPC_to || CKind == OMPC_from)) {
21179 auto CI = CurComponents.rbegin();
21180 auto CE = CurComponents.rend();
21181 for (; CI != CE; ++CI) {
21182 const auto *OASE =
21183 dyn_cast<ArraySectionExpr>(Val: CI->getAssociatedExpression());
21184 if (!OASE)
21185 continue;
21186 if (OASE && OASE->getLength())
21187 break;
21188 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_array_section_does_not_specify_length)
21189 << ERange;
21190 }
21191 }
21192 return Checker.getFoundBase();
21193 }
21194 return nullptr;
21195}
21196
21197// Return true if expression E associated with value VD has conflicts with other
21198// map information.
21199static bool checkMapConflicts(
21200 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21201 bool CurrentRegionOnly,
21202 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
21203 OpenMPClauseKind CKind) {
21204 assert(VD && E);
21205 SourceLocation ELoc = E->getExprLoc();
21206 SourceRange ERange = E->getSourceRange();
21207
21208 // In order to easily check the conflicts we need to match each component of
21209 // the expression under test with the components of the expressions that are
21210 // already in the stack.
21211
21212 assert(!CurComponents.empty() && "Map clause expression with no components!");
21213 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21214 "Map clause expression with unexpected base!");
21215
21216 // Variables to help detecting enclosing problems in data environment nests.
21217 bool IsEnclosedByDataEnvironmentExpr = false;
21218 const Expr *EnclosingExpr = nullptr;
21219
21220 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21221 VD, CurrentRegionOnly,
21222 Check: [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21223 ERange, CKind, &EnclosingExpr,
21224 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
21225 StackComponents,
21226 OpenMPClauseKind Kind) {
21227 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21228 return false;
21229 assert(!StackComponents.empty() &&
21230 "Map clause expression with no components!");
21231 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21232 "Map clause expression with unexpected base!");
21233 (void)VD;
21234
21235 // The whole expression in the stack.
21236 const Expr *RE = StackComponents.front().getAssociatedExpression();
21237
21238 // Expressions must start from the same base. Here we detect at which
21239 // point both expressions diverge from each other and see if we can
21240 // detect if the memory referred to both expressions is contiguous and
21241 // do not overlap.
21242 auto CI = CurComponents.rbegin();
21243 auto CE = CurComponents.rend();
21244 auto SI = StackComponents.rbegin();
21245 auto SE = StackComponents.rend();
21246 for (; CI != CE && SI != SE; ++CI, ++SI) {
21247
21248 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21249 // At most one list item can be an array item derived from a given
21250 // variable in map clauses of the same construct.
21251 if (CurrentRegionOnly &&
21252 (isa<ArraySubscriptExpr>(Val: CI->getAssociatedExpression()) ||
21253 isa<ArraySectionExpr>(Val: CI->getAssociatedExpression()) ||
21254 isa<OMPArrayShapingExpr>(Val: CI->getAssociatedExpression())) &&
21255 (isa<ArraySubscriptExpr>(Val: SI->getAssociatedExpression()) ||
21256 isa<ArraySectionExpr>(Val: SI->getAssociatedExpression()) ||
21257 isa<OMPArrayShapingExpr>(Val: SI->getAssociatedExpression()))) {
21258 SemaRef.Diag(Loc: CI->getAssociatedExpression()->getExprLoc(),
21259 DiagID: diag::err_omp_multiple_array_items_in_map_clause)
21260 << CI->getAssociatedExpression()->getSourceRange();
21261 SemaRef.Diag(Loc: SI->getAssociatedExpression()->getExprLoc(),
21262 DiagID: diag::note_used_here)
21263 << SI->getAssociatedExpression()->getSourceRange();
21264 return true;
21265 }
21266
21267 // Do both expressions have the same kind?
21268 if (CI->getAssociatedExpression()->getStmtClass() !=
21269 SI->getAssociatedExpression()->getStmtClass())
21270 break;
21271
21272 // Are we dealing with different variables/fields?
21273 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21274 break;
21275 }
21276 // Check if the extra components of the expressions in the enclosing
21277 // data environment are redundant for the current base declaration.
21278 // If they are, the maps completely overlap, which is legal.
21279 for (; SI != SE; ++SI) {
21280 QualType Type;
21281 if (const auto *ASE =
21282 dyn_cast<ArraySubscriptExpr>(Val: SI->getAssociatedExpression())) {
21283 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21284 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
21285 Val: SI->getAssociatedExpression())) {
21286 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21287 Type = ArraySectionExpr::getBaseOriginalType(Base: E).getCanonicalType();
21288 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21289 Val: SI->getAssociatedExpression())) {
21290 Type = OASE->getBase()->getType()->getPointeeType();
21291 }
21292 if (Type.isNull() || Type->isAnyPointerType() ||
21293 checkArrayExpressionDoesNotReferToWholeSize(
21294 SemaRef, E: SI->getAssociatedExpression(), BaseQTy: Type))
21295 break;
21296 }
21297
21298 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21299 // List items of map clauses in the same construct must not share
21300 // original storage.
21301 //
21302 // If the expressions are exactly the same or one is a subset of the
21303 // other, it means they are sharing storage.
21304 if (CI == CE && SI == SE) {
21305 if (CurrentRegionOnly) {
21306 if (CKind == OMPC_map) {
21307 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << ERange;
21308 } else {
21309 assert(CKind == OMPC_to || CKind == OMPC_from);
21310 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced_in_target_update)
21311 << ERange;
21312 }
21313 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
21314 << RE->getSourceRange();
21315 return true;
21316 }
21317 // If we find the same expression in the enclosing data environment,
21318 // that is legal.
21319 IsEnclosedByDataEnvironmentExpr = true;
21320 return false;
21321 }
21322
21323 QualType DerivedType =
21324 std::prev(x: CI)->getAssociatedDeclaration()->getType();
21325 SourceLocation DerivedLoc =
21326 std::prev(x: CI)->getAssociatedExpression()->getExprLoc();
21327
21328 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21329 // If the type of a list item is a reference to a type T then the type
21330 // will be considered to be T for all purposes of this clause.
21331 DerivedType = DerivedType.getNonReferenceType();
21332
21333 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21334 // A variable for which the type is pointer and an array section
21335 // derived from that variable must not appear as list items of map
21336 // clauses of the same construct.
21337 //
21338 // Also, cover one of the cases in:
21339 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21340 // If any part of the original storage of a list item has corresponding
21341 // storage in the device data environment, all of the original storage
21342 // must have corresponding storage in the device data environment.
21343 //
21344 if (DerivedType->isAnyPointerType()) {
21345 if (CI == CE || SI == SE) {
21346 SemaRef.Diag(
21347 Loc: DerivedLoc,
21348 DiagID: diag::err_omp_pointer_mapped_along_with_derived_section)
21349 << DerivedLoc;
21350 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
21351 << RE->getSourceRange();
21352 return true;
21353 }
21354 if (CI->getAssociatedExpression()->getStmtClass() !=
21355 SI->getAssociatedExpression()->getStmtClass() ||
21356 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21357 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21358 assert(CI != CE && SI != SE);
21359 SemaRef.Diag(Loc: DerivedLoc, DiagID: diag::err_omp_same_pointer_dereferenced)
21360 << DerivedLoc;
21361 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
21362 << RE->getSourceRange();
21363 return true;
21364 }
21365 }
21366
21367 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21368 // List items of map clauses in the same construct must not share
21369 // original storage.
21370 //
21371 // An expression is a subset of the other.
21372 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21373 if (CKind == OMPC_map) {
21374 if (CI != CE || SI != SE) {
21375 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21376 // a pointer.
21377 auto Begin =
21378 CI != CE ? CurComponents.begin() : StackComponents.begin();
21379 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21380 auto It = Begin;
21381 while (It != End && !It->getAssociatedDeclaration())
21382 std::advance(i&: It, n: 1);
21383 assert(It != End &&
21384 "Expected at least one component with the declaration.");
21385 if (It != Begin && It->getAssociatedDeclaration()
21386 ->getType()
21387 .getCanonicalType()
21388 ->isAnyPointerType()) {
21389 IsEnclosedByDataEnvironmentExpr = false;
21390 EnclosingExpr = nullptr;
21391 return false;
21392 }
21393 }
21394 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << ERange;
21395 } else {
21396 assert(CKind == OMPC_to || CKind == OMPC_from);
21397 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_once_referenced_in_target_update)
21398 << ERange;
21399 }
21400 SemaRef.Diag(Loc: RE->getExprLoc(), DiagID: diag::note_used_here)
21401 << RE->getSourceRange();
21402 return true;
21403 }
21404
21405 // The current expression uses the same base as other expression in the
21406 // data environment but does not contain it completely.
21407 if (!CurrentRegionOnly && SI != SE)
21408 EnclosingExpr = RE;
21409
21410 // The current expression is a subset of the expression in the data
21411 // environment.
21412 IsEnclosedByDataEnvironmentExpr |=
21413 (!CurrentRegionOnly && CI != CE && SI == SE);
21414
21415 return false;
21416 });
21417
21418 if (CurrentRegionOnly)
21419 return FoundError;
21420
21421 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21422 // If any part of the original storage of a list item has corresponding
21423 // storage in the device data environment, all of the original storage must
21424 // have corresponding storage in the device data environment.
21425 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21426 // If a list item is an element of a structure, and a different element of
21427 // the structure has a corresponding list item in the device data environment
21428 // prior to a task encountering the construct associated with the map clause,
21429 // then the list item must also have a corresponding list item in the device
21430 // data environment prior to the task encountering the construct.
21431 //
21432 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21433 SemaRef.Diag(Loc: ELoc,
21434 DiagID: diag::err_omp_original_storage_is_shared_and_does_not_contain)
21435 << ERange;
21436 SemaRef.Diag(Loc: EnclosingExpr->getExprLoc(), DiagID: diag::note_used_here)
21437 << EnclosingExpr->getSourceRange();
21438 return true;
21439 }
21440
21441 return FoundError;
21442}
21443
21444// Look up the user-defined mapper given the mapper name and mapped type, and
21445// build a reference to it.
21446static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
21447 CXXScopeSpec &MapperIdScopeSpec,
21448 const DeclarationNameInfo &MapperId,
21449 QualType Type,
21450 Expr *UnresolvedMapper) {
21451 if (MapperIdScopeSpec.isInvalid())
21452 return ExprError();
21453 // Get the actual type for the array type.
21454 if (Type->isArrayType()) {
21455 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
21456 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
21457 }
21458 // Find all user-defined mappers with the given MapperId.
21459 SmallVector<UnresolvedSet<8>, 4> Lookups;
21460 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21461 Lookup.suppressDiagnostics();
21462 if (S) {
21463 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &MapperIdScopeSpec,
21464 /*ObjectType=*/QualType())) {
21465 NamedDecl *D = Lookup.getRepresentativeDecl();
21466 while (S && !S->isDeclScope(D))
21467 S = S->getParent();
21468 if (S)
21469 S = S->getParent();
21470 Lookups.emplace_back();
21471 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
21472 Lookup.clear();
21473 }
21474 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(Val: UnresolvedMapper)) {
21475 // Extract the user-defined mappers with the given MapperId.
21476 Lookups.push_back(Elt: UnresolvedSet<8>());
21477 for (NamedDecl *D : ULE->decls()) {
21478 auto *DMD = cast<OMPDeclareMapperDecl>(Val: D);
21479 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
21480 Lookups.back().addDecl(D: DMD);
21481 }
21482 }
21483 // Defer the lookup for dependent types. The results will be passed through
21484 // UnresolvedMapper on instantiation.
21485 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21486 Type->isInstantiationDependentType() ||
21487 Type->containsUnexpandedParameterPack() ||
21488 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
21489 return !D->isInvalidDecl() &&
21490 (D->getType()->isDependentType() ||
21491 D->getType()->isInstantiationDependentType() ||
21492 D->getType()->containsUnexpandedParameterPack());
21493 })) {
21494 UnresolvedSet<8> URS;
21495 for (const UnresolvedSet<8> &Set : Lookups) {
21496 if (Set.empty())
21497 continue;
21498 URS.append(I: Set.begin(), E: Set.end());
21499 }
21500 return UnresolvedLookupExpr::Create(
21501 Context: SemaRef.Context, /*NamingClass=*/nullptr,
21502 QualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: SemaRef.Context), NameInfo: MapperId,
21503 /*ADL=*/RequiresADL: false, Begin: URS.begin(), End: URS.end(), /*KnownDependent=*/false,
21504 /*KnownInstantiationDependent=*/false);
21505 }
21506 SourceLocation Loc = MapperId.getLoc();
21507 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21508 // The type must be of struct, union or class type in C and C++
21509 if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
21510 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21511 SemaRef.Diag(Loc, DiagID: diag::err_omp_mapper_wrong_type);
21512 return ExprError();
21513 }
21514 // Perform argument dependent lookup.
21515 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21516 argumentDependentLookup(SemaRef, Id: MapperId, Loc, Ty: Type, Lookups);
21517 // Return the first user-defined mapper with the desired type.
21518 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21519 Lookups, Gen: [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21520 if (!D->isInvalidDecl() &&
21521 SemaRef.Context.hasSameType(T1: D->getType(), T2: Type))
21522 return D;
21523 return nullptr;
21524 }))
21525 return SemaRef.BuildDeclRefExpr(D: VD, Ty: Type, VK: VK_LValue, Loc);
21526 // Find the first user-defined mapper with a type derived from the desired
21527 // type.
21528 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21529 Lookups, Gen: [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21530 if (!D->isInvalidDecl() &&
21531 SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: D->getType()) &&
21532 !Type.isMoreQualifiedThan(other: D->getType(),
21533 Ctx: SemaRef.getASTContext()))
21534 return D;
21535 return nullptr;
21536 })) {
21537 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21538 /*DetectVirtual=*/false);
21539 if (SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: VD->getType(), Paths)) {
21540 if (!Paths.isAmbiguous(BaseType: SemaRef.Context.getCanonicalType(
21541 T: VD->getType().getUnqualifiedType()))) {
21542 if (SemaRef.CheckBaseClassAccess(
21543 AccessLoc: Loc, Base: VD->getType(), Derived: Type, Path: Paths.front(),
21544 /*DiagID=*/0) != Sema::AR_inaccessible) {
21545 return SemaRef.BuildDeclRefExpr(D: VD, Ty: Type, VK: VK_LValue, Loc);
21546 }
21547 }
21548 }
21549 }
21550 // Report error if a mapper is specified, but cannot be found.
21551 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
21552 SemaRef.Diag(Loc, DiagID: diag::err_omp_invalid_mapper)
21553 << Type << MapperId.getName();
21554 return ExprError();
21555 }
21556 return ExprEmpty();
21557}
21558
21559namespace {
21560// Utility struct that gathers all the related lists associated with a mappable
21561// expression.
21562struct MappableVarListInfo {
21563 // The list of expressions.
21564 ArrayRef<Expr *> VarList;
21565 // The list of processed expressions.
21566 SmallVector<Expr *, 16> ProcessedVarList;
21567 // The mappble components for each expression.
21568 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
21569 // The base declaration of the variable.
21570 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
21571 // The reference to the user-defined mapper associated with every expression.
21572 SmallVector<Expr *, 16> UDMapperList;
21573
21574 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
21575 // We have a list of components and base declarations for each entry in the
21576 // variable list.
21577 VarComponents.reserve(N: VarList.size());
21578 VarBaseDeclarations.reserve(N: VarList.size());
21579 }
21580};
21581} // namespace
21582
21583static DeclRefExpr *buildImplicitMap(Sema &S, QualType BaseType,
21584 DSAStackTy *Stack,
21585 SmallVectorImpl<OMPClause *> &Maps) {
21586
21587 const RecordDecl *RD = BaseType->getAsRecordDecl();
21588 SourceRange Range = RD->getSourceRange();
21589 DeclarationNameInfo ImplicitName;
21590 // Dummy variable _s for Mapper.
21591 VarDecl *VD = buildVarDecl(SemaRef&: S, Loc: Range.getEnd(), Type: BaseType, Name: "_s");
21592 DeclRefExpr *MapperVarRef =
21593 buildDeclRefExpr(S, D: VD, Ty: BaseType, Loc: SourceLocation());
21594
21595 // Create implicit map clause for mapper.
21596 SmallVector<Expr *, 4> SExprs;
21597 for (auto *FD : RD->fields()) {
21598 Expr *BE = S.BuildMemberExpr(
21599 Base: MapperVarRef, /*IsArrow=*/false, OpLoc: Range.getBegin(),
21600 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: Range.getBegin(), Member: FD,
21601 FoundDecl: DeclAccessPair::make(D: FD, AS: FD->getAccess()),
21602 /*HadMultipleCandidates=*/false,
21603 MemberNameInfo: DeclarationNameInfo(FD->getDeclName(), FD->getSourceRange().getBegin()),
21604 Ty: FD->getType(), VK: VK_LValue, OK: OK_Ordinary);
21605 SExprs.push_back(Elt: BE);
21606 }
21607 CXXScopeSpec MapperIdScopeSpec;
21608 DeclarationNameInfo MapperId;
21609 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
21610
21611 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
21612 IteratorModifier: nullptr, MapTypeModifiers: OMPC_MAP_MODIFIER_unknown, MapTypeModifiersLoc: SourceLocation(), MapperIdScopeSpec,
21613 MapperId, MapType: DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
21614 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(), VarList: SExprs,
21615 Locs: OMPVarListLocTy());
21616 Maps.push_back(Elt: MapClause);
21617 return MapperVarRef;
21618}
21619
21620static ExprResult buildImplicitMapper(Sema &S, QualType BaseType,
21621 DSAStackTy *Stack) {
21622
21623 // Build impilicit map for mapper
21624 SmallVector<OMPClause *, 4> Maps;
21625 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
21626
21627 const RecordDecl *RD = BaseType->getAsRecordDecl();
21628 // AST context is RD's ParentASTContext().
21629 ASTContext &Ctx = RD->getParentASTContext();
21630 // DeclContext is RD's DeclContext.
21631 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
21632
21633 // Create implicit default mapper for "RD".
21634 DeclarationName MapperId;
21635 auto &DeclNames = Ctx.DeclarationNames;
21636 MapperId = DeclNames.getIdentifier(ID: &Ctx.Idents.get(Name: "default"));
21637 auto *DMD = OMPDeclareMapperDecl::Create(C&: Ctx, DC: DCT, L: SourceLocation(), Name: MapperId,
21638 T: BaseType, VarName: MapperId, Clauses: Maps, PrevDeclInScope: nullptr);
21639 Scope *Scope = S.getScopeForContext(Ctx: DCT);
21640 if (Scope)
21641 S.PushOnScopeChains(D: DMD, S: Scope, /*AddToContext=*/false);
21642 DCT->addDecl(D: DMD);
21643 DMD->setAccess(clang::AS_none);
21644 auto *VD = cast<DeclRefExpr>(Val: MapperVarRef)->getDecl();
21645 VD->setDeclContext(DMD);
21646 VD->setLexicalDeclContext(DMD);
21647 DMD->addDecl(D: VD);
21648 DMD->setMapperVarRef(MapperVarRef);
21649 FieldDecl *FD = *RD->field_begin();
21650 // create mapper refence.
21651 return DeclRefExpr::Create(Context: Ctx, QualifierLoc: NestedNameSpecifierLoc{}, TemplateKWLoc: FD->getLocation(),
21652 D: DMD, RefersToEnclosingVariableOrCapture: false, NameLoc: SourceLocation(), T: BaseType, VK: VK_LValue);
21653}
21654
21655// Look up the user-defined mapper given the mapper name and mapper type,
21656// return true if found one.
21657static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
21658 CXXScopeSpec &MapperIdScopeSpec,
21659 const DeclarationNameInfo &MapperId,
21660 QualType Type) {
21661 // Find all user-defined mappers with the given MapperId.
21662 SmallVector<UnresolvedSet<8>, 4> Lookups;
21663 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21664 Lookup.suppressDiagnostics();
21665 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &MapperIdScopeSpec,
21666 /*ObjectType=*/QualType())) {
21667 NamedDecl *D = Lookup.getRepresentativeDecl();
21668 while (S && !S->isDeclScope(D))
21669 S = S->getParent();
21670 if (S)
21671 S = S->getParent();
21672 Lookups.emplace_back();
21673 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
21674 Lookup.clear();
21675 }
21676 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21677 Type->isInstantiationDependentType() ||
21678 Type->containsUnexpandedParameterPack() ||
21679 filterLookupForUDReductionAndMapper<bool>(Lookups, Gen: [](ValueDecl *D) {
21680 return !D->isInvalidDecl() &&
21681 (D->getType()->isDependentType() ||
21682 D->getType()->isInstantiationDependentType() ||
21683 D->getType()->containsUnexpandedParameterPack());
21684 }))
21685 return false;
21686 // Perform argument dependent lookup.
21687 SourceLocation Loc = MapperId.getLoc();
21688 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21689 argumentDependentLookup(SemaRef, Id: MapperId, Loc, Ty: Type, Lookups);
21690 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
21691 Lookups, Gen: [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21692 if (!D->isInvalidDecl() &&
21693 SemaRef.Context.hasSameType(T1: D->getType(), T2: Type))
21694 return D;
21695 return nullptr;
21696 }))
21697 return true;
21698 // Find the first user-defined mapper with a type derived from the desired
21699 // type.
21700 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21701 Lookups, Gen: [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21702 if (!D->isInvalidDecl() &&
21703 SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: D->getType()) &&
21704 !Type.isMoreQualifiedThan(other: D->getType(), Ctx: SemaRef.getASTContext()))
21705 return D;
21706 return nullptr;
21707 });
21708 if (!VD)
21709 return false;
21710 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21711 /*DetectVirtual=*/false);
21712 if (SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: VD->getType(), Paths)) {
21713 bool IsAmbiguous = !Paths.isAmbiguous(
21714 BaseType: SemaRef.Context.getCanonicalType(T: VD->getType().getUnqualifiedType()));
21715 if (IsAmbiguous)
21716 return false;
21717 if (SemaRef.CheckBaseClassAccess(AccessLoc: Loc, Base: VD->getType(), Derived: Type, Path: Paths.front(),
21718 /*DiagID=*/0) != Sema::AR_inaccessible)
21719 return true;
21720 }
21721 return false;
21722}
21723
21724static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
21725 QualType CanonType, const Expr *E) {
21726
21727 // DFS over data members in structures/classes.
21728 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(1,
21729 {CanonType, nullptr});
21730 llvm::DenseMap<const Type *, bool> Visited;
21731 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
21732 while (!Types.empty()) {
21733 auto [BaseType, CurFD] = Types.pop_back_val();
21734 while (ParentChain.back().second == 0)
21735 ParentChain.pop_back();
21736 --ParentChain.back().second;
21737 if (BaseType.isNull())
21738 continue;
21739 // Only structs/classes are allowed to have mappers.
21740 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
21741 if (!RD)
21742 continue;
21743 auto It = Visited.find(Val: BaseType.getTypePtr());
21744 if (It == Visited.end()) {
21745 // Try to find the associated user-defined mapper.
21746 CXXScopeSpec MapperIdScopeSpec;
21747 DeclarationNameInfo DefaultMapperId;
21748 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
21749 ID: &S.Context.Idents.get(Name: "default")));
21750 DefaultMapperId.setLoc(E->getExprLoc());
21751 bool HasUDMapper =
21752 hasUserDefinedMapper(SemaRef&: S, S: Stack->getCurScope(), MapperIdScopeSpec,
21753 MapperId: DefaultMapperId, Type: BaseType);
21754 It = Visited.try_emplace(Key: BaseType.getTypePtr(), Args&: HasUDMapper).first;
21755 }
21756 // Found default mapper.
21757 if (It->second)
21758 return true;
21759 // Check for the "default" mapper for data members.
21760 bool FirstIter = true;
21761 for (FieldDecl *FD : RD->fields()) {
21762 if (!FD)
21763 continue;
21764 QualType FieldTy = FD->getType();
21765 if (FieldTy.isNull() ||
21766 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
21767 continue;
21768 if (FirstIter) {
21769 FirstIter = false;
21770 ParentChain.emplace_back(Args&: CurFD, Args: 1);
21771 } else {
21772 ++ParentChain.back().second;
21773 }
21774 Types.emplace_back(Args&: FieldTy, Args&: FD);
21775 }
21776 }
21777 return false;
21778}
21779
21780// Check the validity of the provided variable list for the provided clause kind
21781// \a CKind. In the check process the valid expressions, mappable expression
21782// components, variables, and user-defined mappers are extracted and used to
21783// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21784// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
21785// and \a MapperId are expected to be valid if the clause kind is 'map'.
21786static void checkMappableExpressionList(
21787 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
21788 MappableVarListInfo &MVLI, SourceLocation StartLoc,
21789 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
21790 ArrayRef<Expr *> UnresolvedMappers,
21791 OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
21792 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
21793 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
21794 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
21795 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21796 "Unexpected clause kind with mappable expressions!");
21797 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
21798
21799 // If the identifier of user-defined mapper is not specified, it is "default".
21800 // We do not change the actual name in this clause to distinguish whether a
21801 // mapper is specified explicitly, i.e., it is not explicitly specified when
21802 // MapperId.getName() is empty.
21803 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
21804 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
21805 MapperId.setName(DeclNames.getIdentifier(
21806 ID: &SemaRef.getASTContext().Idents.get(Name: "default")));
21807 MapperId.setLoc(StartLoc);
21808 }
21809
21810 // Iterators to find the current unresolved mapper expression.
21811 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21812 bool UpdateUMIt = false;
21813 Expr *UnresolvedMapper = nullptr;
21814
21815 bool HasHoldModifier =
21816 llvm::is_contained(Range&: Modifiers, Element: OMPC_MAP_MODIFIER_ompx_hold);
21817
21818 // Keep track of the mappable components and base declarations in this clause.
21819 // Each entry in the list is going to have a list of components associated. We
21820 // record each set of the components so that we can build the clause later on.
21821 // In the end we should have the same amount of declarations and component
21822 // lists.
21823
21824 for (Expr *RE : MVLI.VarList) {
21825 assert(RE && "Null expr in omp to/from/map clause");
21826 SourceLocation ELoc = RE->getExprLoc();
21827
21828 // Find the current unresolved mapper expression.
21829 if (UpdateUMIt && UMIt != UMEnd) {
21830 UMIt++;
21831 assert(
21832 UMIt != UMEnd &&
21833 "Expect the size of UnresolvedMappers to match with that of VarList");
21834 }
21835 UpdateUMIt = true;
21836 if (UMIt != UMEnd)
21837 UnresolvedMapper = *UMIt;
21838
21839 const Expr *VE = RE->IgnoreParenLValueCasts();
21840
21841 if (VE->isValueDependent() || VE->isTypeDependent() ||
21842 VE->isInstantiationDependent() ||
21843 VE->containsUnexpandedParameterPack()) {
21844 // Try to find the associated user-defined mapper.
21845 ExprResult ER = buildUserDefinedMapperRef(
21846 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21847 Type: VE->getType().getCanonicalType(), UnresolvedMapper);
21848 if (ER.isInvalid())
21849 continue;
21850 MVLI.UDMapperList.push_back(Elt: ER.get());
21851 // We can only analyze this information once the missing information is
21852 // resolved.
21853 MVLI.ProcessedVarList.push_back(Elt: RE);
21854 continue;
21855 }
21856
21857 Expr *SimpleExpr = RE->IgnoreParenCasts();
21858
21859 if (!RE->isLValue()) {
21860 if (SemaRef.getLangOpts().OpenMP < 50) {
21861 SemaRef.Diag(
21862 Loc: ELoc, DiagID: diag::err_omp_expected_named_var_member_or_array_expression)
21863 << RE->getSourceRange();
21864 } else {
21865 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21866 << getOpenMPClauseNameForDiag(C: CKind) << RE->getSourceRange();
21867 }
21868 continue;
21869 }
21870
21871 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
21872 ValueDecl *CurDeclaration = nullptr;
21873
21874 // Obtain the array or member expression bases if required. Also, fill the
21875 // components array with all the components identified in the process.
21876 const Expr *BE =
21877 checkMapClauseExpressionBase(SemaRef, E: SimpleExpr, CurComponents, CKind,
21878 DKind: DSAS->getCurrentDirective(), NoDiagnose);
21879 if (!BE)
21880 continue;
21881
21882 assert(!CurComponents.empty() &&
21883 "Invalid mappable expression information.");
21884
21885 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: BE)) {
21886 // Add store "this" pointer to class in DSAStackTy for future checking
21887 DSAS->addMappedClassesQualTypes(QT: TE->getType());
21888 // Try to find the associated user-defined mapper.
21889 ExprResult ER = buildUserDefinedMapperRef(
21890 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21891 Type: VE->getType().getCanonicalType(), UnresolvedMapper);
21892 if (ER.isInvalid())
21893 continue;
21894 MVLI.UDMapperList.push_back(Elt: ER.get());
21895 // Skip restriction checking for variable or field declarations
21896 MVLI.ProcessedVarList.push_back(Elt: RE);
21897 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
21898 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
21899 in_end: CurComponents.end());
21900 MVLI.VarBaseDeclarations.push_back(Elt: nullptr);
21901 continue;
21902 }
21903
21904 // For the following checks, we rely on the base declaration which is
21905 // expected to be associated with the last component. The declaration is
21906 // expected to be a variable or a field (if 'this' is being mapped).
21907 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21908 assert(CurDeclaration && "Null decl on map clause.");
21909 assert(
21910 CurDeclaration->isCanonicalDecl() &&
21911 "Expecting components to have associated only canonical declarations.");
21912
21913 auto *VD = dyn_cast<VarDecl>(Val: CurDeclaration);
21914 const auto *FD = dyn_cast<FieldDecl>(Val: CurDeclaration);
21915
21916 assert((VD || FD) && "Only variables or fields are expected here!");
21917 (void)FD;
21918
21919 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
21920 // threadprivate variables cannot appear in a map clause.
21921 // OpenMP 4.5 [2.10.5, target update Construct]
21922 // threadprivate variables cannot appear in a from clause.
21923 if (VD && DSAS->isThreadPrivate(D: VD)) {
21924 if (NoDiagnose)
21925 continue;
21926 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(D: VD, /*FromParent=*/false);
21927 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_threadprivate_in_clause)
21928 << getOpenMPClauseNameForDiag(C: CKind);
21929 reportOriginalDsa(SemaRef, Stack: DSAS, D: VD, DVar);
21930 continue;
21931 }
21932
21933 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21934 // A list item cannot appear in both a map clause and a data-sharing
21935 // attribute clause on the same construct.
21936
21937 // Check conflicts with other map clause expressions. We check the conflicts
21938 // with the current construct separately from the enclosing data
21939 // environment, because the restrictions are different. We only have to
21940 // check conflicts across regions for the map clauses.
21941 if (checkMapConflicts(SemaRef, DSAS, VD: CurDeclaration, E: SimpleExpr,
21942 /*CurrentRegionOnly=*/true, CurComponents, CKind))
21943 break;
21944 if (CKind == OMPC_map &&
21945 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
21946 checkMapConflicts(SemaRef, DSAS, VD: CurDeclaration, E: SimpleExpr,
21947 /*CurrentRegionOnly=*/false, CurComponents, CKind))
21948 break;
21949
21950 // OpenMP 4.5 [2.10.5, target update Construct]
21951 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21952 // If the type of a list item is a reference to a type T then the type will
21953 // be considered to be T for all purposes of this clause.
21954 auto I = llvm::find_if(
21955 Range&: CurComponents,
21956 P: [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
21957 return MC.getAssociatedDeclaration();
21958 });
21959 assert(I != CurComponents.end() && "Null decl on map clause.");
21960 (void)I;
21961 QualType Type;
21962 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: VE->IgnoreParens());
21963 auto *OASE = dyn_cast<ArraySectionExpr>(Val: VE->IgnoreParens());
21964 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(Val: VE->IgnoreParens());
21965 if (ASE) {
21966 Type = ASE->getType().getNonReferenceType();
21967 } else if (OASE) {
21968 QualType BaseType =
21969 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
21970 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21971 Type = ATy->getElementType();
21972 else
21973 Type = BaseType->getPointeeType();
21974 Type = Type.getNonReferenceType();
21975 } else if (OAShE) {
21976 Type = OAShE->getBase()->getType()->getPointeeType();
21977 } else {
21978 Type = VE->getType();
21979 }
21980
21981 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
21982 // A list item in a to or from clause must have a mappable type.
21983 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21984 // A list item must have a mappable type.
21985 if (!checkTypeMappable(SL: VE->getExprLoc(), SR: VE->getSourceRange(), SemaRef,
21986 Stack: DSAS, QTy: Type, /*FullCheck=*/true))
21987 continue;
21988
21989 if (CKind == OMPC_map) {
21990 // target enter data
21991 // OpenMP [2.10.2, Restrictions, p. 99]
21992 // A map-type must be specified in all map clauses and must be either
21993 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
21994 // no map type is present.
21995 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
21996 if (DKind == OMPD_target_enter_data &&
21997 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21998 SemaRef.getLangOpts().OpenMP >= 52)) {
21999 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
22000 << (IsMapTypeImplicit ? 1 : 0)
22001 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
22002 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
22003 continue;
22004 }
22005
22006 // target exit_data
22007 // OpenMP [2.10.3, Restrictions, p. 102]
22008 // A map-type must be specified in all map clauses and must be either
22009 // from, release, or delete. Starting with OpenMP 5.2 the default map
22010 // type is `from` if no map type is present.
22011 if (DKind == OMPD_target_exit_data &&
22012 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
22013 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
22014 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
22015 << (IsMapTypeImplicit ? 1 : 0)
22016 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
22017 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
22018 continue;
22019 }
22020
22021 // The 'ompx_hold' modifier is specifically intended to be used on a
22022 // 'target' or 'target data' directive to prevent data from being unmapped
22023 // during the associated statement. It is not permitted on a 'target
22024 // enter data' or 'target exit data' directive, which have no associated
22025 // statement.
22026 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
22027 HasHoldModifier) {
22028 SemaRef.Diag(Loc: StartLoc,
22029 DiagID: diag::err_omp_invalid_map_type_modifier_for_directive)
22030 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map,
22031 Type: OMPC_MAP_MODIFIER_ompx_hold)
22032 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
22033 continue;
22034 }
22035
22036 // target, target data
22037 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22038 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22039 // A map-type in a map clause must be to, from, tofrom or alloc
22040 if ((DKind == OMPD_target_data ||
22041 isOpenMPTargetExecutionDirective(DKind)) &&
22042 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
22043 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
22044 SemaRef.Diag(Loc: StartLoc, DiagID: diag::err_omp_invalid_map_type_for_directive)
22045 << (IsMapTypeImplicit ? 1 : 0)
22046 << getOpenMPSimpleClauseTypeName(Kind: OMPC_map, Type: MapType)
22047 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
22048 continue;
22049 }
22050
22051 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22052 // A list item cannot appear in both a map clause and a data-sharing
22053 // attribute clause on the same construct
22054 //
22055 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22056 // A list item cannot appear in both a map clause and a data-sharing
22057 // attribute clause on the same construct unless the construct is a
22058 // combined construct.
22059 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
22060 isOpenMPTargetExecutionDirective(DKind)) ||
22061 DKind == OMPD_target)) {
22062 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(D: VD, /*FromParent=*/false);
22063 if (isOpenMPPrivate(Kind: DVar.CKind)) {
22064 SemaRef.Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
22065 << getOpenMPClauseNameForDiag(C: DVar.CKind)
22066 << getOpenMPClauseNameForDiag(C: OMPC_map)
22067 << getOpenMPDirectiveName(D: DSAS->getCurrentDirective(),
22068 Ver: OMPVersion);
22069 reportOriginalDsa(SemaRef, Stack: DSAS, D: CurDeclaration, DVar);
22070 continue;
22071 }
22072 }
22073 }
22074
22075 // Try to find the associated user-defined mapper.
22076 ExprResult ER = buildUserDefinedMapperRef(
22077 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22078 Type: Type.getCanonicalType(), UnresolvedMapper);
22079 if (ER.isInvalid())
22080 continue;
22081
22082 // If no user-defined mapper is found, we need to create an implicit one for
22083 // arrays/array-sections on structs that have members that have
22084 // user-defined mappers. This is needed to ensure that the mapper for the
22085 // member is invoked when mapping each element of the array/array-section.
22086 if (!ER.get()) {
22087 QualType BaseType;
22088
22089 if (isa<ArraySectionExpr>(Val: VE)) {
22090 BaseType = VE->getType().getCanonicalType();
22091 if (BaseType->isSpecificBuiltinType(K: BuiltinType::ArraySection)) {
22092 const auto *OASE = cast<ArraySectionExpr>(Val: VE->IgnoreParenImpCasts());
22093 QualType BType =
22094 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
22095 QualType ElemType;
22096 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
22097 ElemType = ATy->getElementType();
22098 else
22099 ElemType = BType->getPointeeType();
22100 BaseType = ElemType.getCanonicalType();
22101 }
22102 } else if (VE->getType()->isArrayType()) {
22103 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
22104 const QualType ElemType = AT->getElementType();
22105 BaseType = ElemType.getCanonicalType();
22106 }
22107
22108 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
22109 isImplicitMapperNeeded(S&: SemaRef, Stack: DSAS, CanonType: BaseType, E: VE)) {
22110 ER = buildImplicitMapper(S&: SemaRef, BaseType, Stack: DSAS);
22111 }
22112 }
22113 MVLI.UDMapperList.push_back(Elt: ER.get());
22114
22115 // Save the current expression.
22116 MVLI.ProcessedVarList.push_back(Elt: RE);
22117
22118 // Store the components in the stack so that they can be used to check
22119 // against other clauses later on.
22120 DSAS->addMappableExpressionComponents(VD: CurDeclaration, Components: CurComponents,
22121 /*WhereFoundClauseKind=*/OMPC_map);
22122
22123 // Save the components and declaration to create the clause. For purposes of
22124 // the clause creation, any component list that has base 'this' uses
22125 // null as base declaration.
22126 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
22127 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
22128 in_end: CurComponents.end());
22129 MVLI.VarBaseDeclarations.push_back(Elt: isa<MemberExpr>(Val: BE) ? nullptr
22130 : CurDeclaration);
22131 }
22132}
22133
22134OMPClause *SemaOpenMP::ActOnOpenMPMapClause(
22135 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
22136 ArrayRef<SourceLocation> MapTypeModifiersLoc,
22137 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22138 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
22139 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22140 const OMPVarListLocTy &Locs, bool NoDiagnose,
22141 ArrayRef<Expr *> UnresolvedMappers) {
22142 OpenMPMapModifierKind Modifiers[] = {
22143 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22144 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22145 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22146 OMPC_MAP_MODIFIER_unknown};
22147 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
22148
22149 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
22150 K: BuiltinType::OMPIterator))
22151 Diag(Loc: IteratorModifier->getExprLoc(),
22152 DiagID: diag::err_omp_map_modifier_not_iterator);
22153
22154 // Process map-type-modifiers, flag errors for duplicate modifiers.
22155 unsigned Count = 0;
22156 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22157 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
22158 llvm::is_contained(Range&: Modifiers, Element: MapTypeModifiers[I])) {
22159 Diag(Loc: MapTypeModifiersLoc[I], DiagID: diag::err_omp_duplicate_map_type_modifier);
22160 continue;
22161 }
22162 assert(Count < NumberOfOMPMapClauseModifiers &&
22163 "Modifiers exceed the allowed number of map type modifiers");
22164 Modifiers[Count] = MapTypeModifiers[I];
22165 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22166 ++Count;
22167 }
22168
22169 MappableVarListInfo MVLI(VarList);
22170 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_map, MVLI, StartLoc: Locs.StartLoc,
22171 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22172 MapType, Modifiers, IsMapTypeImplicit,
22173 NoDiagnose);
22174
22175 // We need to produce a map clause even if we don't have variables so that
22176 // other diagnostics related with non-existing map clauses are accurate.
22177 return OMPMapClause::Create(
22178 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
22179 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, IteratorModifier, MapModifiers: Modifiers,
22180 MapModifiersLoc: ModifiersLoc, UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()),
22181 MapperId, Type: MapType, TypeIsImplicit: IsMapTypeImplicit, TypeLoc: MapLoc);
22182}
22183
22184QualType SemaOpenMP::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
22185 TypeResult ParsedType) {
22186 assert(ParsedType.isUsable());
22187
22188 QualType ReductionType = SemaRef.GetTypeFromParser(Ty: ParsedType.get());
22189 if (ReductionType.isNull())
22190 return QualType();
22191
22192 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22193 // A type name in a declare reduction directive cannot be a function type, an
22194 // array type, a reference type, or a type qualified with const, volatile or
22195 // restrict.
22196 if (ReductionType.hasQualifiers()) {
22197 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 0;
22198 return QualType();
22199 }
22200
22201 if (ReductionType->isFunctionType()) {
22202 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 1;
22203 return QualType();
22204 }
22205 if (ReductionType->isReferenceType()) {
22206 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 2;
22207 return QualType();
22208 }
22209 if (ReductionType->isArrayType()) {
22210 Diag(Loc: TyLoc, DiagID: diag::err_omp_reduction_wrong_type) << 3;
22211 return QualType();
22212 }
22213 return ReductionType;
22214}
22215
22216SemaOpenMP::DeclGroupPtrTy
22217SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveStart(
22218 Scope *S, DeclContext *DC, DeclarationName Name,
22219 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22220 AccessSpecifier AS, Decl *PrevDeclInScope) {
22221 SmallVector<Decl *, 8> Decls;
22222 Decls.reserve(N: ReductionTypes.size());
22223
22224 LookupResult Lookup(SemaRef, Name, SourceLocation(),
22225 Sema::LookupOMPReductionName,
22226 SemaRef.forRedeclarationInCurContext());
22227 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22228 // A reduction-identifier may not be re-declared in the current scope for the
22229 // same type or for a type that is compatible according to the base language
22230 // rules.
22231 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22232 OMPDeclareReductionDecl *PrevDRD = nullptr;
22233 bool InCompoundScope = true;
22234 if (S != nullptr) {
22235 // Find previous declaration with the same name not referenced in other
22236 // declarations.
22237 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
22238 InCompoundScope =
22239 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22240 SemaRef.LookupName(R&: Lookup, S);
22241 SemaRef.FilterLookupForScope(R&: Lookup, Ctx: DC, S, /*ConsiderLinkage=*/false,
22242 /*AllowInlineNamespace=*/false);
22243 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22244 LookupResult::Filter Filter = Lookup.makeFilter();
22245 while (Filter.hasNext()) {
22246 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Val: Filter.next());
22247 if (InCompoundScope) {
22248 UsedAsPrevious.try_emplace(Key: PrevDecl, Args: false);
22249 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
22250 UsedAsPrevious[D] = true;
22251 }
22252 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22253 PrevDecl->getLocation();
22254 }
22255 Filter.done();
22256 if (InCompoundScope) {
22257 for (const auto &PrevData : UsedAsPrevious) {
22258 if (!PrevData.second) {
22259 PrevDRD = PrevData.first;
22260 break;
22261 }
22262 }
22263 }
22264 } else if (PrevDeclInScope != nullptr) {
22265 auto *PrevDRDInScope = PrevDRD =
22266 cast<OMPDeclareReductionDecl>(Val: PrevDeclInScope);
22267 do {
22268 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22269 PrevDRDInScope->getLocation();
22270 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22271 } while (PrevDRDInScope != nullptr);
22272 }
22273 for (const auto &TyData : ReductionTypes) {
22274 const auto I = PreviousRedeclTypes.find(Val: TyData.first.getCanonicalType());
22275 bool Invalid = false;
22276 if (I != PreviousRedeclTypes.end()) {
22277 Diag(Loc: TyData.second, DiagID: diag::err_omp_declare_reduction_redefinition)
22278 << TyData.first;
22279 Diag(Loc: I->second, DiagID: diag::note_previous_definition);
22280 Invalid = true;
22281 }
22282 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22283 auto *DRD = OMPDeclareReductionDecl::Create(
22284 C&: getASTContext(), DC, L: TyData.second, Name, T: TyData.first, PrevDeclInScope: PrevDRD);
22285 DC->addDecl(D: DRD);
22286 DRD->setAccess(AS);
22287 Decls.push_back(Elt: DRD);
22288 if (Invalid)
22289 DRD->setInvalidDecl();
22290 else
22291 PrevDRD = DRD;
22292 }
22293
22294 return DeclGroupPtrTy::make(
22295 P: DeclGroupRef::Create(C&: getASTContext(), Decls: Decls.begin(), NumDecls: Decls.size()));
22296}
22297
22298void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
22299 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
22300
22301 // Enter new function scope.
22302 SemaRef.PushFunctionScope();
22303 SemaRef.setFunctionHasBranchProtectedScope();
22304 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
22305
22306 if (S != nullptr)
22307 SemaRef.PushDeclContext(S, DC: DRD);
22308 else
22309 SemaRef.CurContext = DRD;
22310
22311 SemaRef.PushExpressionEvaluationContext(
22312 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
22313
22314 QualType ReductionType = DRD->getType();
22315 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22316 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22317 // uses semantics of argument handles by value, but it should be passed by
22318 // reference. C lang does not support references, so pass all parameters as
22319 // pointers.
22320 // Create 'T omp_in;' variable.
22321 VarDecl *OmpInParm =
22322 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_in");
22323 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22324 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22325 // uses semantics of argument handles by value, but it should be passed by
22326 // reference. C lang does not support references, so pass all parameters as
22327 // pointers.
22328 // Create 'T omp_out;' variable.
22329 VarDecl *OmpOutParm =
22330 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_out");
22331 if (S != nullptr) {
22332 SemaRef.PushOnScopeChains(D: OmpInParm, S);
22333 SemaRef.PushOnScopeChains(D: OmpOutParm, S);
22334 } else {
22335 DRD->addDecl(D: OmpInParm);
22336 DRD->addDecl(D: OmpOutParm);
22337 }
22338 Expr *InE =
22339 ::buildDeclRefExpr(S&: SemaRef, D: OmpInParm, Ty: ReductionType, Loc: D->getLocation());
22340 Expr *OutE =
22341 ::buildDeclRefExpr(S&: SemaRef, D: OmpOutParm, Ty: ReductionType, Loc: D->getLocation());
22342 DRD->setCombinerData(InE, OutE);
22343}
22344
22345void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D,
22346 Expr *Combiner) {
22347 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
22348 SemaRef.DiscardCleanupsInEvaluationContext();
22349 SemaRef.PopExpressionEvaluationContext();
22350
22351 SemaRef.PopDeclContext();
22352 SemaRef.PopFunctionScopeInfo();
22353
22354 if (Combiner != nullptr)
22355 DRD->setCombiner(Combiner);
22356 else
22357 DRD->setInvalidDecl();
22358}
22359
22360VarDecl *SemaOpenMP::ActOnOpenMPDeclareReductionInitializerStart(Scope *S,
22361 Decl *D) {
22362 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
22363
22364 // Enter new function scope.
22365 SemaRef.PushFunctionScope();
22366 SemaRef.setFunctionHasBranchProtectedScope();
22367
22368 if (S != nullptr)
22369 SemaRef.PushDeclContext(S, DC: DRD);
22370 else
22371 SemaRef.CurContext = DRD;
22372
22373 SemaRef.PushExpressionEvaluationContext(
22374 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
22375
22376 QualType ReductionType = DRD->getType();
22377 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22378 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22379 // uses semantics of argument handles by value, but it should be passed by
22380 // reference. C lang does not support references, so pass all parameters as
22381 // pointers.
22382 // Create 'T omp_priv;' variable.
22383 VarDecl *OmpPrivParm =
22384 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_priv");
22385 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22386 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22387 // uses semantics of argument handles by value, but it should be passed by
22388 // reference. C lang does not support references, so pass all parameters as
22389 // pointers.
22390 // Create 'T omp_orig;' variable.
22391 VarDecl *OmpOrigParm =
22392 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_orig");
22393 if (S != nullptr) {
22394 SemaRef.PushOnScopeChains(D: OmpPrivParm, S);
22395 SemaRef.PushOnScopeChains(D: OmpOrigParm, S);
22396 } else {
22397 DRD->addDecl(D: OmpPrivParm);
22398 DRD->addDecl(D: OmpOrigParm);
22399 }
22400 Expr *OrigE =
22401 ::buildDeclRefExpr(S&: SemaRef, D: OmpOrigParm, Ty: ReductionType, Loc: D->getLocation());
22402 Expr *PrivE =
22403 ::buildDeclRefExpr(S&: SemaRef, D: OmpPrivParm, Ty: ReductionType, Loc: D->getLocation());
22404 DRD->setInitializerData(OrigE, PrivE);
22405 return OmpPrivParm;
22406}
22407
22408void SemaOpenMP::ActOnOpenMPDeclareReductionInitializerEnd(
22409 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
22410 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
22411 SemaRef.DiscardCleanupsInEvaluationContext();
22412 SemaRef.PopExpressionEvaluationContext();
22413
22414 SemaRef.PopDeclContext();
22415 SemaRef.PopFunctionScopeInfo();
22416
22417 if (Initializer != nullptr) {
22418 DRD->setInitializer(E: Initializer, IK: OMPDeclareReductionInitKind::Call);
22419 } else if (OmpPrivParm->hasInit()) {
22420 DRD->setInitializer(E: OmpPrivParm->getInit(),
22421 IK: OmpPrivParm->isDirectInit()
22422 ? OMPDeclareReductionInitKind::Direct
22423 : OMPDeclareReductionInitKind::Copy);
22424 } else {
22425 DRD->setInvalidDecl();
22426 }
22427}
22428
22429SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveEnd(
22430 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22431 for (Decl *D : DeclReductions.get()) {
22432 if (IsValid) {
22433 if (S)
22434 SemaRef.PushOnScopeChains(D: cast<OMPDeclareReductionDecl>(Val: D), S,
22435 /*AddToContext=*/false);
22436 } else {
22437 D->setInvalidDecl();
22438 }
22439 }
22440 return DeclReductions;
22441}
22442
22443TypeResult SemaOpenMP::ActOnOpenMPDeclareMapperVarDecl(Scope *S,
22444 Declarator &D) {
22445 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
22446 QualType T = TInfo->getType();
22447 if (D.isInvalidType())
22448 return true;
22449
22450 if (getLangOpts().CPlusPlus) {
22451 // Check that there are no default arguments (C++ only).
22452 SemaRef.CheckExtraCXXDefaultArguments(D);
22453 }
22454
22455 return SemaRef.CreateParsedType(T, TInfo);
22456}
22457
22458QualType SemaOpenMP::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
22459 TypeResult ParsedType) {
22460 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
22461
22462 QualType MapperType = SemaRef.GetTypeFromParser(Ty: ParsedType.get());
22463 assert(!MapperType.isNull() && "Expect valid mapper type");
22464
22465 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22466 // The type must be of struct, union or class type in C and C++
22467 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22468 Diag(Loc: TyLoc, DiagID: diag::err_omp_mapper_wrong_type);
22469 return QualType();
22470 }
22471 return MapperType;
22472}
22473
22474SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareMapperDirective(
22475 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22476 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
22477 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22478 LookupResult Lookup(SemaRef, Name, SourceLocation(),
22479 Sema::LookupOMPMapperName,
22480 SemaRef.forRedeclarationInCurContext());
22481 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22482 // A mapper-identifier may not be redeclared in the current scope for the
22483 // same type or for a type that is compatible according to the base language
22484 // rules.
22485 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22486 OMPDeclareMapperDecl *PrevDMD = nullptr;
22487 bool InCompoundScope = true;
22488 if (S != nullptr) {
22489 // Find previous declaration with the same name not referenced in other
22490 // declarations.
22491 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
22492 InCompoundScope =
22493 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22494 SemaRef.LookupName(R&: Lookup, S);
22495 SemaRef.FilterLookupForScope(R&: Lookup, Ctx: DC, S, /*ConsiderLinkage=*/false,
22496 /*AllowInlineNamespace=*/false);
22497 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22498 LookupResult::Filter Filter = Lookup.makeFilter();
22499 while (Filter.hasNext()) {
22500 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Val: Filter.next());
22501 if (InCompoundScope) {
22502 UsedAsPrevious.try_emplace(Key: PrevDecl, Args: false);
22503 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22504 UsedAsPrevious[D] = true;
22505 }
22506 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22507 PrevDecl->getLocation();
22508 }
22509 Filter.done();
22510 if (InCompoundScope) {
22511 for (const auto &PrevData : UsedAsPrevious) {
22512 if (!PrevData.second) {
22513 PrevDMD = PrevData.first;
22514 break;
22515 }
22516 }
22517 }
22518 } else if (PrevDeclInScope) {
22519 auto *PrevDMDInScope = PrevDMD =
22520 cast<OMPDeclareMapperDecl>(Val: PrevDeclInScope);
22521 do {
22522 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22523 PrevDMDInScope->getLocation();
22524 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22525 } while (PrevDMDInScope != nullptr);
22526 }
22527 const auto I = PreviousRedeclTypes.find(Val: MapperType.getCanonicalType());
22528 bool Invalid = false;
22529 if (I != PreviousRedeclTypes.end()) {
22530 Diag(Loc: StartLoc, DiagID: diag::err_omp_declare_mapper_redefinition)
22531 << MapperType << Name;
22532 Diag(Loc: I->second, DiagID: diag::note_previous_definition);
22533 Invalid = true;
22534 }
22535 // Build expressions for implicit maps of data members with 'default'
22536 // mappers.
22537 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
22538 if (getLangOpts().OpenMP >= 50)
22539 processImplicitMapsWithDefaultMappers(S&: SemaRef, DSAStack,
22540 Clauses&: ClausesWithImplicit);
22541 auto *DMD = OMPDeclareMapperDecl::Create(C&: getASTContext(), DC, L: StartLoc, Name,
22542 T: MapperType, VarName: VN, Clauses: ClausesWithImplicit,
22543 PrevDeclInScope: PrevDMD);
22544 if (S)
22545 SemaRef.PushOnScopeChains(D: DMD, S);
22546 else
22547 DC->addDecl(D: DMD);
22548 DMD->setAccess(AS);
22549 if (Invalid)
22550 DMD->setInvalidDecl();
22551
22552 auto *VD = cast<DeclRefExpr>(Val: MapperVarRef)->getDecl();
22553 VD->setDeclContext(DMD);
22554 VD->setLexicalDeclContext(DMD);
22555 DMD->addDecl(D: VD);
22556 DMD->setMapperVarRef(MapperVarRef);
22557
22558 return DeclGroupPtrTy::make(P: DeclGroupRef(DMD));
22559}
22560
22561ExprResult SemaOpenMP::ActOnOpenMPDeclareMapperDirectiveVarDecl(
22562 Scope *S, QualType MapperType, SourceLocation StartLoc,
22563 DeclarationName VN) {
22564 TypeSourceInfo *TInfo =
22565 getASTContext().getTrivialTypeSourceInfo(T: MapperType, Loc: StartLoc);
22566 auto *VD = VarDecl::Create(
22567 C&: getASTContext(), DC: getASTContext().getTranslationUnitDecl(), StartLoc,
22568 IdLoc: StartLoc, Id: VN.getAsIdentifierInfo(), T: MapperType, TInfo, S: SC_None);
22569 if (S)
22570 SemaRef.PushOnScopeChains(D: VD, S, /*AddToContext=*/false);
22571 Expr *E = buildDeclRefExpr(S&: SemaRef, D: VD, Ty: MapperType, Loc: StartLoc);
22572 DSAStack->addDeclareMapperVarRef(Ref: E);
22573 return E;
22574}
22575
22576void SemaOpenMP::ActOnOpenMPIteratorVarDecl(VarDecl *VD) {
22577 if (DSAStack->getDeclareMapperVarRef())
22578 DSAStack->addIteratorVarDecl(VD);
22579}
22580
22581bool SemaOpenMP::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
22582 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22583 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22584 if (const auto *DRE = cast_or_null<DeclRefExpr>(Val: Ref)) {
22585 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22586 return true;
22587 if (VD->isUsableInConstantExpressions(C: getASTContext()))
22588 return true;
22589 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22590 return true;
22591 return false;
22592 }
22593 return true;
22594}
22595
22596const ValueDecl *SemaOpenMP::getOpenMPDeclareMapperVarName() const {
22597 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22598 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22599}
22600
22601OMPClause *SemaOpenMP::ActOnOpenMPNumTeamsClause(ArrayRef<Expr *> VarList,
22602 SourceLocation StartLoc,
22603 SourceLocation LParenLoc,
22604 SourceLocation EndLoc) {
22605 if (VarList.empty())
22606 return nullptr;
22607
22608 for (Expr *ValExpr : VarList) {
22609 // OpenMP [teams Constrcut, Restrictions]
22610 // The num_teams expression must evaluate to a positive integer value.
22611 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_num_teams,
22612 /*StrictlyPositive=*/true))
22613 return nullptr;
22614 }
22615
22616 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22617 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
22618 DKind, CKind: OMPC_num_teams, OpenMPVersion: getLangOpts().OpenMP);
22619 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22620 return OMPNumTeamsClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
22621 LParenLoc, EndLoc, VL: VarList,
22622 /*PreInit=*/nullptr);
22623
22624 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22625 SmallVector<Expr *, 3> Vars;
22626 for (Expr *ValExpr : VarList) {
22627 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
22628 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
22629 Vars.push_back(Elt: ValExpr);
22630 }
22631
22632 Stmt *PreInit = buildPreInits(Context&: getASTContext(), Captures);
22633 return OMPNumTeamsClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
22634 LParenLoc, EndLoc, VL: Vars, PreInit);
22635}
22636
22637OMPClause *SemaOpenMP::ActOnOpenMPThreadLimitClause(ArrayRef<Expr *> VarList,
22638 SourceLocation StartLoc,
22639 SourceLocation LParenLoc,
22640 SourceLocation EndLoc) {
22641 if (VarList.empty())
22642 return nullptr;
22643
22644 for (Expr *ValExpr : VarList) {
22645 // OpenMP [teams Constrcut, Restrictions]
22646 // The thread_limit expression must evaluate to a positive integer value.
22647 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_thread_limit,
22648 /*StrictlyPositive=*/true))
22649 return nullptr;
22650 }
22651
22652 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22653 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
22654 DKind, CKind: OMPC_thread_limit, OpenMPVersion: getLangOpts().OpenMP);
22655 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22656 return OMPThreadLimitClause::Create(C: getASTContext(), CaptureRegion,
22657 StartLoc, LParenLoc, EndLoc, VL: VarList,
22658 /*PreInit=*/nullptr);
22659
22660 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22661 SmallVector<Expr *, 3> Vars;
22662 for (Expr *ValExpr : VarList) {
22663 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
22664 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
22665 Vars.push_back(Elt: ValExpr);
22666 }
22667
22668 Stmt *PreInit = buildPreInits(Context&: getASTContext(), Captures);
22669 return OMPThreadLimitClause::Create(C: getASTContext(), CaptureRegion, StartLoc,
22670 LParenLoc, EndLoc, VL: Vars, PreInit);
22671}
22672
22673OMPClause *SemaOpenMP::ActOnOpenMPPriorityClause(Expr *Priority,
22674 SourceLocation StartLoc,
22675 SourceLocation LParenLoc,
22676 SourceLocation EndLoc) {
22677 Expr *ValExpr = Priority;
22678 Stmt *HelperValStmt = nullptr;
22679 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22680
22681 // OpenMP [2.9.1, task Constrcut]
22682 // The priority-value is a non-negative numerical scalar expression.
22683 if (!isNonNegativeIntegerValue(
22684 ValExpr, SemaRef, CKind: OMPC_priority,
22685 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22686 DSAStack->getCurrentDirective(), CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
22687 return nullptr;
22688
22689 return new (getASTContext()) OMPPriorityClause(
22690 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22691}
22692
22693OMPClause *SemaOpenMP::ActOnOpenMPGrainsizeClause(
22694 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22695 SourceLocation StartLoc, SourceLocation LParenLoc,
22696 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22697 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22698 "Unexpected grainsize modifier in OpenMP < 51.");
22699
22700 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22701 std::string Values = getListOfPossibleValues(K: OMPC_grainsize, /*First=*/0,
22702 Last: OMPC_GRAINSIZE_unknown);
22703 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
22704 << Values << getOpenMPClauseNameForDiag(C: OMPC_grainsize);
22705 return nullptr;
22706 }
22707
22708 Expr *ValExpr = Grainsize;
22709 Stmt *HelperValStmt = nullptr;
22710 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22711
22712 // OpenMP [2.9.2, taskloop Constrcut]
22713 // The parameter of the grainsize clause must be a positive integer
22714 // expression.
22715 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_grainsize,
22716 /*StrictlyPositive=*/true,
22717 /*BuildCapture=*/true,
22718 DSAStack->getCurrentDirective(),
22719 CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
22720 return nullptr;
22721
22722 return new (getASTContext())
22723 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22724 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22725}
22726
22727OMPClause *SemaOpenMP::ActOnOpenMPNumTasksClause(
22728 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
22729 SourceLocation StartLoc, SourceLocation LParenLoc,
22730 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22731 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22732 "Unexpected num_tasks modifier in OpenMP < 51.");
22733
22734 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
22735 std::string Values = getListOfPossibleValues(K: OMPC_num_tasks, /*First=*/0,
22736 Last: OMPC_NUMTASKS_unknown);
22737 Diag(Loc: ModifierLoc, DiagID: diag::err_omp_unexpected_clause_value)
22738 << Values << getOpenMPClauseNameForDiag(C: OMPC_num_tasks);
22739 return nullptr;
22740 }
22741
22742 Expr *ValExpr = NumTasks;
22743 Stmt *HelperValStmt = nullptr;
22744 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22745
22746 // OpenMP [2.9.2, taskloop Constrcut]
22747 // The parameter of the num_tasks clause must be a positive integer
22748 // expression.
22749 if (!isNonNegativeIntegerValue(
22750 ValExpr, SemaRef, CKind: OMPC_num_tasks,
22751 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22752 DSAStack->getCurrentDirective(), CaptureRegion: &CaptureRegion, HelperValStmt: &HelperValStmt))
22753 return nullptr;
22754
22755 return new (getASTContext())
22756 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22757 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22758}
22759
22760OMPClause *SemaOpenMP::ActOnOpenMPHintClause(Expr *Hint,
22761 SourceLocation StartLoc,
22762 SourceLocation LParenLoc,
22763 SourceLocation EndLoc) {
22764 // OpenMP [2.13.2, critical construct, Description]
22765 // ... where hint-expression is an integer constant expression that evaluates
22766 // to a valid lock hint.
22767 ExprResult HintExpr =
22768 VerifyPositiveIntegerConstantInClause(E: Hint, CKind: OMPC_hint, StrictlyPositive: false);
22769 if (HintExpr.isInvalid())
22770 return nullptr;
22771 return new (getASTContext())
22772 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22773}
22774
22775/// Tries to find omp_event_handle_t type.
22776static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
22777 DSAStackTy *Stack) {
22778 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22779 if (!OMPEventHandleT.isNull())
22780 return true;
22781 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_event_handle_t");
22782 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
22783 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22784 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22785 return false;
22786 }
22787 Stack->setOMPEventHandleT(PT.get());
22788 return true;
22789}
22790
22791OMPClause *SemaOpenMP::ActOnOpenMPDetachClause(Expr *Evt,
22792 SourceLocation StartLoc,
22793 SourceLocation LParenLoc,
22794 SourceLocation EndLoc) {
22795 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22796 !Evt->isInstantiationDependent() &&
22797 !Evt->containsUnexpandedParameterPack()) {
22798 if (!findOMPEventHandleT(S&: SemaRef, Loc: Evt->getExprLoc(), DSAStack))
22799 return nullptr;
22800 // OpenMP 5.0, 2.10.1 task Construct.
22801 // event-handle is a variable of the omp_event_handle_t type.
22802 auto *Ref = dyn_cast<DeclRefExpr>(Val: Evt->IgnoreParenImpCasts());
22803 if (!Ref) {
22804 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
22805 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22806 return nullptr;
22807 }
22808 auto *VD = dyn_cast_or_null<VarDecl>(Val: Ref->getDecl());
22809 if (!VD) {
22810 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
22811 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22812 return nullptr;
22813 }
22814 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
22815 T2: VD->getType()) ||
22816 VD->getType().isConstant(Ctx: getASTContext())) {
22817 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_var_expected)
22818 << "omp_event_handle_t" << 1 << VD->getType()
22819 << Evt->getSourceRange();
22820 return nullptr;
22821 }
22822 // OpenMP 5.0, 2.10.1 task Construct
22823 // [detach clause]... The event-handle will be considered as if it was
22824 // specified on a firstprivate clause.
22825 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
22826 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22827 DVar.RefExpr) {
22828 Diag(Loc: Evt->getExprLoc(), DiagID: diag::err_omp_wrong_dsa)
22829 << getOpenMPClauseNameForDiag(C: DVar.CKind)
22830 << getOpenMPClauseNameForDiag(C: OMPC_firstprivate);
22831 reportOriginalDsa(SemaRef, DSAStack, D: VD, DVar);
22832 return nullptr;
22833 }
22834 }
22835
22836 return new (getASTContext())
22837 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
22838}
22839
22840OMPClause *SemaOpenMP::ActOnOpenMPDistScheduleClause(
22841 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
22842 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
22843 SourceLocation EndLoc) {
22844 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
22845 std::string Values;
22846 Values += "'";
22847 Values += getOpenMPSimpleClauseTypeName(Kind: OMPC_dist_schedule, Type: 0);
22848 Values += "'";
22849 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
22850 << Values << getOpenMPClauseNameForDiag(C: OMPC_dist_schedule);
22851 return nullptr;
22852 }
22853 Expr *ValExpr = ChunkSize;
22854 Stmt *HelperValStmt = nullptr;
22855 if (ChunkSize) {
22856 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
22857 !ChunkSize->isInstantiationDependent() &&
22858 !ChunkSize->containsUnexpandedParameterPack()) {
22859 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
22860 ExprResult Val =
22861 PerformOpenMPImplicitIntegerConversion(Loc: ChunkSizeLoc, Op: ChunkSize);
22862 if (Val.isInvalid())
22863 return nullptr;
22864
22865 ValExpr = Val.get();
22866
22867 // OpenMP [2.7.1, Restrictions]
22868 // chunk_size must be a loop invariant integer expression with a positive
22869 // value.
22870 if (std::optional<llvm::APSInt> Result =
22871 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
22872 if (Result->isSigned() && !Result->isStrictlyPositive()) {
22873 Diag(Loc: ChunkSizeLoc, DiagID: diag::err_omp_negative_expression_in_clause)
22874 << "dist_schedule" << /*strictly positive*/ 1
22875 << ChunkSize->getSourceRange();
22876 return nullptr;
22877 }
22878 } else if (getOpenMPCaptureRegionForClause(
22879 DSAStack->getCurrentDirective(), CKind: OMPC_dist_schedule,
22880 OpenMPVersion: getLangOpts().OpenMP) != OMPD_unknown &&
22881 !SemaRef.CurContext->isDependentContext()) {
22882 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
22883 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22884 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
22885 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
22886 }
22887 }
22888 }
22889
22890 return new (getASTContext())
22891 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
22892 Kind, ValExpr, HelperValStmt);
22893}
22894
22895OMPClause *SemaOpenMP::ActOnOpenMPDefaultmapClause(
22896 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
22897 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
22898 SourceLocation KindLoc, SourceLocation EndLoc) {
22899 if (getLangOpts().OpenMP < 50) {
22900 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22901 Kind != OMPC_DEFAULTMAP_scalar) {
22902 std::string Value;
22903 SourceLocation Loc;
22904 Value += "'";
22905 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22906 Value += getOpenMPSimpleClauseTypeName(Kind: OMPC_defaultmap,
22907 Type: OMPC_DEFAULTMAP_MODIFIER_tofrom);
22908 Loc = MLoc;
22909 } else {
22910 Value += getOpenMPSimpleClauseTypeName(Kind: OMPC_defaultmap,
22911 Type: OMPC_DEFAULTMAP_scalar);
22912 Loc = KindLoc;
22913 }
22914 Value += "'";
22915 Diag(Loc, DiagID: diag::err_omp_unexpected_clause_value)
22916 << Value << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
22917 return nullptr;
22918 }
22919 } else {
22920 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
22921 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
22922 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
22923 if (!isDefaultmapKind || !isDefaultmapModifier) {
22924 StringRef KindValue = getLangOpts().OpenMP < 52
22925 ? "'scalar', 'aggregate', 'pointer'"
22926 : "'scalar', 'aggregate', 'pointer', 'all'";
22927 if (getLangOpts().OpenMP == 50) {
22928 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
22929 "'firstprivate', 'none', 'default'";
22930 if (!isDefaultmapKind && isDefaultmapModifier) {
22931 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
22932 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
22933 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22934 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
22935 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
22936 } else {
22937 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
22938 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
22939 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
22940 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
22941 }
22942 } else {
22943 StringRef ModifierValue =
22944 "'alloc', 'from', 'to', 'tofrom', "
22945 "'firstprivate', 'none', 'default', 'present'";
22946 if (!isDefaultmapKind && isDefaultmapModifier) {
22947 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
22948 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
22949 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22950 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
22951 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
22952 } else {
22953 Diag(Loc: MLoc, DiagID: diag::err_omp_unexpected_clause_value)
22954 << ModifierValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
22955 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
22956 << KindValue << getOpenMPClauseNameForDiag(C: OMPC_defaultmap);
22957 }
22958 }
22959 return nullptr;
22960 }
22961
22962 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
22963 // At most one defaultmap clause for each category can appear on the
22964 // directive.
22965 if (DSAStack->checkDefaultmapCategory(VariableCategory: Kind)) {
22966 Diag(Loc: StartLoc, DiagID: diag::err_omp_one_defaultmap_each_category);
22967 return nullptr;
22968 }
22969 }
22970 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
22971 // Variable category is not specified - mark all categories.
22972 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_aggregate, Loc: StartLoc);
22973 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_scalar, Loc: StartLoc);
22974 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_pointer, Loc: StartLoc);
22975 } else {
22976 DSAStack->setDefaultDMAAttr(M, Kind, Loc: StartLoc);
22977 }
22978
22979 return new (getASTContext())
22980 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
22981}
22982
22983bool SemaOpenMP::ActOnStartOpenMPDeclareTargetContext(
22984 DeclareTargetContextInfo &DTCI) {
22985 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
22986 if (!CurLexicalContext->isFileContext() &&
22987 !CurLexicalContext->isExternCContext() &&
22988 !CurLexicalContext->isExternCXXContext() &&
22989 !isa<CXXRecordDecl>(Val: CurLexicalContext) &&
22990 !isa<ClassTemplateDecl>(Val: CurLexicalContext) &&
22991 !isa<ClassTemplatePartialSpecializationDecl>(Val: CurLexicalContext) &&
22992 !isa<ClassTemplateSpecializationDecl>(Val: CurLexicalContext)) {
22993 Diag(Loc: DTCI.Loc, DiagID: diag::err_omp_region_not_file_context);
22994 return false;
22995 }
22996
22997 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22998 if (getLangOpts().HIP)
22999 Diag(Loc: DTCI.Loc, DiagID: diag::warn_hip_omp_target_directives);
23000
23001 DeclareTargetNesting.push_back(Elt: DTCI);
23002 return true;
23003}
23004
23005const SemaOpenMP::DeclareTargetContextInfo
23006SemaOpenMP::ActOnOpenMPEndDeclareTargetDirective() {
23007 assert(!DeclareTargetNesting.empty() &&
23008 "check isInOpenMPDeclareTargetContext() first!");
23009 return DeclareTargetNesting.pop_back_val();
23010}
23011
23012void SemaOpenMP::ActOnFinishedOpenMPDeclareTargetContext(
23013 DeclareTargetContextInfo &DTCI) {
23014 for (auto &It : DTCI.ExplicitlyMapped)
23015 ActOnOpenMPDeclareTargetName(ND: It.first, Loc: It.second.Loc, MT: It.second.MT, DTCI);
23016}
23017
23018void SemaOpenMP::DiagnoseUnterminatedOpenMPDeclareTarget() {
23019 if (DeclareTargetNesting.empty())
23020 return;
23021 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23022 unsigned OMPVersion = getLangOpts().OpenMP;
23023 Diag(Loc: DTCI.Loc, DiagID: diag::warn_omp_unterminated_declare_target)
23024 << getOpenMPDirectiveName(D: DTCI.Kind, Ver: OMPVersion);
23025}
23026
23027NamedDecl *SemaOpenMP::lookupOpenMPDeclareTargetName(
23028 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
23029 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
23030 SemaRef.LookupParsedName(R&: Lookup, S: CurScope, SS: &ScopeSpec,
23031 /*ObjectType=*/QualType(),
23032 /*AllowBuiltinCreation=*/true);
23033
23034 if (Lookup.isAmbiguous())
23035 return nullptr;
23036 Lookup.suppressDiagnostics();
23037
23038 if (!Lookup.isSingleResult()) {
23039 VarOrFuncDeclFilterCCC CCC(SemaRef);
23040 if (TypoCorrection Corrected =
23041 SemaRef.CorrectTypo(Typo: Id, LookupKind: Sema::LookupOrdinaryName, S: CurScope, SS: nullptr,
23042 CCC, Mode: CorrectTypoKind::ErrorRecovery)) {
23043 SemaRef.diagnoseTypo(Correction: Corrected,
23044 TypoDiag: SemaRef.PDiag(DiagID: diag::err_undeclared_var_use_suggest)
23045 << Id.getName());
23046 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: Corrected.getCorrectionDecl());
23047 return nullptr;
23048 }
23049
23050 Diag(Loc: Id.getLoc(), DiagID: diag::err_undeclared_var_use) << Id.getName();
23051 return nullptr;
23052 }
23053
23054 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
23055 if (!isa<VarDecl>(Val: ND) && !isa<FunctionDecl>(Val: ND) &&
23056 !isa<FunctionTemplateDecl>(Val: ND)) {
23057 Diag(Loc: Id.getLoc(), DiagID: diag::err_omp_invalid_target_decl) << Id.getName();
23058 return nullptr;
23059 }
23060 return ND;
23061}
23062
23063void SemaOpenMP::ActOnOpenMPDeclareTargetName(
23064 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
23065 DeclareTargetContextInfo &DTCI) {
23066 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
23067 isa<FunctionTemplateDecl>(ND)) &&
23068 "Expected variable, function or function template.");
23069
23070 if (auto *VD = dyn_cast<VarDecl>(Val: ND)) {
23071 // Only global variables can be marked as declare target.
23072 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23073 !VD->isStaticDataMember()) {
23074 Diag(Loc, DiagID: diag::err_omp_declare_target_has_local_vars)
23075 << VD->getNameAsString();
23076 return;
23077 }
23078 }
23079 // Diagnose marking after use as it may lead to incorrect diagnosis and
23080 // codegen.
23081 if (getLangOpts().OpenMP >= 50 &&
23082 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
23083 Diag(Loc, DiagID: diag::warn_omp_declare_target_after_first_use);
23084
23085 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23086 if (getLangOpts().HIP)
23087 Diag(Loc, DiagID: diag::warn_hip_omp_target_directives);
23088
23089 // Explicit declare target lists have precedence.
23090 const unsigned Level = -1;
23091
23092 auto *VD = cast<ValueDecl>(Val: ND);
23093 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23094 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23095 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
23096 (*ActiveAttr)->getLevel() == Level) {
23097 Diag(Loc, DiagID: diag::err_omp_device_type_mismatch)
23098 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(Val: DTCI.DT)
23099 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23100 Val: (*ActiveAttr)->getDevType());
23101 return;
23102 }
23103 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
23104 (*ActiveAttr)->getLevel() == Level) {
23105 Diag(Loc, DiagID: diag::err_omp_declare_target_to_and_link) << ND;
23106 return;
23107 }
23108
23109 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
23110 return;
23111
23112 Expr *IndirectE = nullptr;
23113 bool IsIndirect = false;
23114 if (DTCI.Indirect) {
23115 IndirectE = *DTCI.Indirect;
23116 if (!IndirectE)
23117 IsIndirect = true;
23118 }
23119 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23120 Ctx&: getASTContext(), MapType: MT, DevType: DTCI.DT, IndirectExpr: IndirectE, Indirect: IsIndirect, Level,
23121 Range: SourceRange(Loc, Loc));
23122 ND->addAttr(A);
23123 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
23124 ML->DeclarationMarkedOpenMPDeclareTarget(D: ND, Attr: A);
23125 checkDeclIsAllowedInOpenMPTarget(E: nullptr, D: ND, IdLoc: Loc);
23126 if (auto *VD = dyn_cast<VarDecl>(Val: ND);
23127 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
23128 VD->hasGlobalStorage())
23129 ActOnOpenMPDeclareTargetInitializer(D: ND);
23130}
23131
23132static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
23133 Sema &SemaRef, Decl *D) {
23134 if (!D || !isa<VarDecl>(Val: D))
23135 return;
23136 auto *VD = cast<VarDecl>(Val: D);
23137 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
23138 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
23139 if (SemaRef.LangOpts.OpenMP >= 50 &&
23140 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23141 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
23142 VD->hasGlobalStorage()) {
23143 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
23144 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
23145 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23146 // If a lambda declaration and definition appears between a
23147 // declare target directive and the matching end declare target
23148 // directive, all variables that are captured by the lambda
23149 // expression must also appear in a to clause.
23150 SemaRef.Diag(Loc: VD->getLocation(),
23151 DiagID: diag::err_omp_lambda_capture_in_declare_target_not_to);
23152 SemaRef.Diag(Loc: SL, DiagID: diag::note_var_explicitly_captured_here)
23153 << VD << 0 << SR;
23154 return;
23155 }
23156 }
23157 if (MapTy)
23158 return;
23159 SemaRef.Diag(Loc: VD->getLocation(), DiagID: diag::warn_omp_not_in_target_context);
23160 SemaRef.Diag(Loc: SL, DiagID: diag::note_used_here) << SR;
23161}
23162
23163static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
23164 Sema &SemaRef, DSAStackTy *Stack,
23165 ValueDecl *VD) {
23166 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23167 checkTypeMappable(SL, SR, SemaRef, Stack, QTy: VD->getType(),
23168 /*FullCheck=*/false);
23169}
23170
23171void SemaOpenMP::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
23172 SourceLocation IdLoc) {
23173 if (!D || D->isInvalidDecl())
23174 return;
23175 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
23176 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
23177 if (auto *VD = dyn_cast<VarDecl>(Val: D)) {
23178 // Only global variables can be marked as declare target.
23179 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23180 !VD->isStaticDataMember())
23181 return;
23182 // 2.10.6: threadprivate variable cannot appear in a declare target
23183 // directive.
23184 if (DSAStack->isThreadPrivate(D: VD)) {
23185 Diag(Loc: SL, DiagID: diag::err_omp_threadprivate_in_target);
23186 reportOriginalDsa(SemaRef, DSAStack, D: VD, DSAStack->getTopDSA(D: VD, FromParent: false));
23187 return;
23188 }
23189 }
23190 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: D))
23191 D = FTD->getTemplatedDecl();
23192 if (auto *FD = dyn_cast<FunctionDecl>(Val: D)) {
23193 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23194 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD: FD);
23195 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23196 Diag(Loc: IdLoc, DiagID: diag::err_omp_function_in_link_clause);
23197 Diag(Loc: FD->getLocation(), DiagID: diag::note_defined_here) << FD;
23198 return;
23199 }
23200 }
23201 if (auto *VD = dyn_cast<ValueDecl>(Val: D)) {
23202 // Problem if any with var declared with incomplete type will be reported
23203 // as normal, so no need to check it here.
23204 if ((E || !VD->getType()->isIncompleteType()) &&
23205 !checkValueDeclInTarget(SL, SR, SemaRef, DSAStack, VD))
23206 return;
23207 if (!E && isInOpenMPDeclareTargetContext()) {
23208 // Checking declaration inside declare target region.
23209 if (isa<VarDecl>(Val: D) || isa<FunctionDecl>(Val: D) ||
23210 isa<FunctionTemplateDecl>(Val: D)) {
23211 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23212 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23213 unsigned Level = DeclareTargetNesting.size();
23214 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23215 return;
23216 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23217 Expr *IndirectE = nullptr;
23218 bool IsIndirect = false;
23219 if (DTCI.Indirect) {
23220 IndirectE = *DTCI.Indirect;
23221 if (!IndirectE)
23222 IsIndirect = true;
23223 }
23224 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23225 Ctx&: getASTContext(),
23226 MapType: getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23227 : OMPDeclareTargetDeclAttr::MT_To,
23228 DevType: DTCI.DT, IndirectExpr: IndirectE, Indirect: IsIndirect, Level,
23229 Range: SourceRange(DTCI.Loc, DTCI.Loc));
23230 D->addAttr(A);
23231 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
23232 ML->DeclarationMarkedOpenMPDeclareTarget(D, Attr: A);
23233 }
23234 return;
23235 }
23236 }
23237 if (!E)
23238 return;
23239 checkDeclInTargetContext(SL: E->getExprLoc(), SR: E->getSourceRange(), SemaRef, D);
23240}
23241
23242/// This class visits every VarDecl that the initializer references and adds
23243/// OMPDeclareTargetDeclAttr to each of them.
23244class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
23245 SmallVector<VarDecl *> DeclVector;
23246 Attr *A;
23247
23248public:
23249 /// A StmtVisitor class function that visits all DeclRefExpr and adds
23250 /// OMPDeclareTargetDeclAttr to them.
23251 void VisitDeclRefExpr(DeclRefExpr *Node) {
23252 if (auto *VD = dyn_cast<VarDecl>(Val: Node->getDecl())) {
23253 VD->addAttr(A);
23254 DeclVector.push_back(Elt: VD);
23255 }
23256 }
23257 /// A function that iterates across each of the Expr's children.
23258 void VisitExpr(Expr *Ex) {
23259 for (auto *Child : Ex->children()) {
23260 Visit(S: Child);
23261 }
23262 }
23263 /// A function that keeps a record of all the Decls that are variables, has
23264 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23265 /// each Decl one at a time and use the inherited 'visit' functions to look
23266 /// for DeclRefExpr.
23267 void declareTargetInitializer(Decl *TD) {
23268 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
23269 DeclVector.push_back(Elt: cast<VarDecl>(Val: TD));
23270 llvm::SmallDenseSet<Decl *> Visited;
23271 while (!DeclVector.empty()) {
23272 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23273 if (!Visited.insert(V: TargetVarDecl).second)
23274 continue;
23275
23276 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
23277 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
23278 if (Expr *Ex = TargetVarDecl->getInit())
23279 Visit(S: Ex);
23280 }
23281 }
23282 }
23283};
23284
23285/// Adding OMPDeclareTargetDeclAttr to variables with static storage
23286/// duration that are referenced in the initializer expression list of
23287/// variables with static storage duration in declare target directive.
23288void SemaOpenMP::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) {
23289 GlobalDeclRefChecker Checker;
23290 if (isa<VarDecl>(Val: TargetDecl))
23291 Checker.declareTargetInitializer(TD: TargetDecl);
23292}
23293
23294OMPClause *SemaOpenMP::ActOnOpenMPToClause(
23295 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23296 ArrayRef<SourceLocation> MotionModifiersLoc,
23297 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23298 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23299 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23300 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23301 OMPC_MOTION_MODIFIER_unknown};
23302 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23303
23304 // Process motion-modifiers, flag errors for duplicate modifiers.
23305 unsigned Count = 0;
23306 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23307 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23308 llvm::is_contained(Range&: Modifiers, Element: MotionModifiers[I])) {
23309 Diag(Loc: MotionModifiersLoc[I], DiagID: diag::err_omp_duplicate_motion_modifier);
23310 continue;
23311 }
23312 assert(Count < NumberOfOMPMotionModifiers &&
23313 "Modifiers exceed the allowed number of motion modifiers");
23314 Modifiers[Count] = MotionModifiers[I];
23315 ModifiersLoc[Count] = MotionModifiersLoc[I];
23316 ++Count;
23317 }
23318
23319 MappableVarListInfo MVLI(VarList);
23320 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_to, MVLI, StartLoc: Locs.StartLoc,
23321 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23322 if (MVLI.ProcessedVarList.empty())
23323 return nullptr;
23324
23325 return OMPToClause::Create(
23326 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
23327 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, MotionModifiers: Modifiers, MotionModifiersLoc: ModifiersLoc,
23328 UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()), MapperId);
23329}
23330
23331OMPClause *SemaOpenMP::ActOnOpenMPFromClause(
23332 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23333 ArrayRef<SourceLocation> MotionModifiersLoc,
23334 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23335 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23336 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23337 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23338 OMPC_MOTION_MODIFIER_unknown};
23339 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23340
23341 // Process motion-modifiers, flag errors for duplicate modifiers.
23342 unsigned Count = 0;
23343 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23344 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23345 llvm::is_contained(Range&: Modifiers, Element: MotionModifiers[I])) {
23346 Diag(Loc: MotionModifiersLoc[I], DiagID: diag::err_omp_duplicate_motion_modifier);
23347 continue;
23348 }
23349 assert(Count < NumberOfOMPMotionModifiers &&
23350 "Modifiers exceed the allowed number of motion modifiers");
23351 Modifiers[Count] = MotionModifiers[I];
23352 ModifiersLoc[Count] = MotionModifiersLoc[I];
23353 ++Count;
23354 }
23355
23356 MappableVarListInfo MVLI(VarList);
23357 checkMappableExpressionList(SemaRef, DSAStack, CKind: OMPC_from, MVLI, StartLoc: Locs.StartLoc,
23358 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23359 if (MVLI.ProcessedVarList.empty())
23360 return nullptr;
23361
23362 return OMPFromClause::Create(
23363 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
23364 ComponentLists: MVLI.VarComponents, UDMapperRefs: MVLI.UDMapperList, MotionModifiers: Modifiers, MotionModifiersLoc: ModifiersLoc,
23365 UDMQualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()), MapperId);
23366}
23367
23368OMPClause *
23369SemaOpenMP::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
23370 const OMPVarListLocTy &Locs) {
23371 MappableVarListInfo MVLI(VarList);
23372 SmallVector<Expr *, 8> PrivateCopies;
23373 SmallVector<Expr *, 8> Inits;
23374
23375 for (Expr *RefExpr : VarList) {
23376 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
23377 SourceLocation ELoc;
23378 SourceRange ERange;
23379 Expr *SimpleRefExpr = RefExpr;
23380 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
23381 if (Res.second) {
23382 // It will be analyzed later.
23383 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
23384 PrivateCopies.push_back(Elt: nullptr);
23385 Inits.push_back(Elt: nullptr);
23386 }
23387 ValueDecl *D = Res.first;
23388 if (!D)
23389 continue;
23390
23391 QualType Type = D->getType();
23392 Type = Type.getNonReferenceType().getUnqualifiedType();
23393
23394 auto *VD = dyn_cast<VarDecl>(Val: D);
23395
23396 // Item should be a pointer or reference to pointer.
23397 if (!Type->isPointerType()) {
23398 Diag(Loc: ELoc, DiagID: diag::err_omp_usedeviceptr_not_a_pointer)
23399 << 0 << RefExpr->getSourceRange();
23400 continue;
23401 }
23402
23403 // Build the private variable and the expression that refers to it.
23404 auto VDPrivate =
23405 buildVarDecl(SemaRef, Loc: ELoc, Type, Name: D->getName(),
23406 Attrs: D->hasAttrs() ? &D->getAttrs() : nullptr,
23407 OrigRef: VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
23408 if (VDPrivate->isInvalidDecl())
23409 continue;
23410
23411 SemaRef.CurContext->addDecl(D: VDPrivate);
23412 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
23413 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(), Loc: ELoc);
23414
23415 // Add temporary variable to initialize the private copy of the pointer.
23416 VarDecl *VDInit =
23417 buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type, Name: ".devptr.temp");
23418 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
23419 S&: SemaRef, D: VDInit, Ty: RefExpr->getType(), Loc: RefExpr->getExprLoc());
23420 SemaRef.AddInitializerToDecl(
23421 dcl: VDPrivate, init: SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get(),
23422 /*DirectInit=*/false);
23423
23424 // If required, build a capture to implement the privatization initialized
23425 // with the current list item value.
23426 DeclRefExpr *Ref = nullptr;
23427 if (!VD)
23428 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
23429 MVLI.ProcessedVarList.push_back(Elt: VD ? RefExpr->IgnoreParens() : Ref);
23430 PrivateCopies.push_back(Elt: VDPrivateRefExpr);
23431 Inits.push_back(Elt: VDInitRefExpr);
23432
23433 // We need to add a data sharing attribute for this variable to make sure it
23434 // is correctly captured. A variable that shows up in a use_device_ptr has
23435 // similar properties of a first private variable.
23436 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
23437
23438 // Create a mappable component for the list item. List items in this clause
23439 // only need a component.
23440 MVLI.VarBaseDeclarations.push_back(Elt: D);
23441 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
23442 MVLI.VarComponents.back().emplace_back(Args&: SimpleRefExpr, Args&: D,
23443 /*IsNonContiguous=*/Args: false);
23444 }
23445
23446 if (MVLI.ProcessedVarList.empty())
23447 return nullptr;
23448
23449 return OMPUseDevicePtrClause::Create(
23450 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, PrivateVars: PrivateCopies, Inits,
23451 Declarations: MVLI.VarBaseDeclarations, ComponentLists: MVLI.VarComponents);
23452}
23453
23454OMPClause *
23455SemaOpenMP::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
23456 const OMPVarListLocTy &Locs) {
23457 MappableVarListInfo MVLI(VarList);
23458
23459 for (Expr *RefExpr : VarList) {
23460 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
23461 SourceLocation ELoc;
23462 SourceRange ERange;
23463 Expr *SimpleRefExpr = RefExpr;
23464 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
23465 /*AllowArraySection=*/true);
23466 if (Res.second) {
23467 // It will be analyzed later.
23468 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
23469 }
23470 ValueDecl *D = Res.first;
23471 if (!D)
23472 continue;
23473 auto *VD = dyn_cast<VarDecl>(Val: D);
23474
23475 // If required, build a capture to implement the privatization initialized
23476 // with the current list item value.
23477 DeclRefExpr *Ref = nullptr;
23478 if (!VD)
23479 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
23480 MVLI.ProcessedVarList.push_back(Elt: VD ? RefExpr->IgnoreParens() : Ref);
23481
23482 // We need to add a data sharing attribute for this variable to make sure it
23483 // is correctly captured. A variable that shows up in a use_device_addr has
23484 // similar properties of a first private variable.
23485 DSAStack->addDSA(D, E: RefExpr->IgnoreParens(), A: OMPC_firstprivate, PrivateCopy: Ref);
23486
23487 // Create a mappable component for the list item. List items in this clause
23488 // only need a component.
23489 MVLI.VarBaseDeclarations.push_back(Elt: D);
23490 MVLI.VarComponents.emplace_back();
23491 Expr *Component = SimpleRefExpr;
23492 if (VD && (isa<ArraySectionExpr>(Val: RefExpr->IgnoreParenImpCasts()) ||
23493 isa<ArraySubscriptExpr>(Val: RefExpr->IgnoreParenImpCasts())))
23494 Component =
23495 SemaRef.DefaultFunctionArrayLvalueConversion(E: SimpleRefExpr).get();
23496 MVLI.VarComponents.back().emplace_back(Args&: Component, Args&: D,
23497 /*IsNonContiguous=*/Args: false);
23498 }
23499
23500 if (MVLI.ProcessedVarList.empty())
23501 return nullptr;
23502
23503 return OMPUseDeviceAddrClause::Create(
23504 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
23505 ComponentLists: MVLI.VarComponents);
23506}
23507
23508OMPClause *
23509SemaOpenMP::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
23510 const OMPVarListLocTy &Locs) {
23511 MappableVarListInfo MVLI(VarList);
23512 for (Expr *RefExpr : VarList) {
23513 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
23514 SourceLocation ELoc;
23515 SourceRange ERange;
23516 Expr *SimpleRefExpr = RefExpr;
23517 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
23518 if (Res.second) {
23519 // It will be analyzed later.
23520 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
23521 }
23522 ValueDecl *D = Res.first;
23523 if (!D)
23524 continue;
23525
23526 QualType Type = D->getType();
23527 // item should be a pointer or array or reference to pointer or array
23528 if (!Type.getNonReferenceType()->isPointerType() &&
23529 !Type.getNonReferenceType()->isArrayType()) {
23530 Diag(Loc: ELoc, DiagID: diag::err_omp_argument_type_isdeviceptr)
23531 << 0 << RefExpr->getSourceRange();
23532 continue;
23533 }
23534
23535 // Check if the declaration in the clause does not show up in any data
23536 // sharing attribute.
23537 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23538 if (isOpenMPPrivate(Kind: DVar.CKind)) {
23539 unsigned OMPVersion = getLangOpts().OpenMP;
23540 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
23541 << getOpenMPClauseNameForDiag(C: DVar.CKind)
23542 << getOpenMPClauseNameForDiag(C: OMPC_is_device_ptr)
23543 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
23544 Ver: OMPVersion);
23545 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
23546 continue;
23547 }
23548
23549 const Expr *ConflictExpr;
23550 if (DSAStack->checkMappableExprComponentListsForDecl(
23551 VD: D, /*CurrentRegionOnly=*/true,
23552 Check: [&ConflictExpr](
23553 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23554 OpenMPClauseKind) -> bool {
23555 ConflictExpr = R.front().getAssociatedExpression();
23556 return true;
23557 })) {
23558 Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23559 Diag(Loc: ConflictExpr->getExprLoc(), DiagID: diag::note_used_here)
23560 << ConflictExpr->getSourceRange();
23561 continue;
23562 }
23563
23564 // Store the components in the stack so that they can be used to check
23565 // against other clauses later on.
23566 OMPClauseMappableExprCommon::MappableComponent MC(
23567 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23568 DSAStack->addMappableExpressionComponents(
23569 VD: D, Components: MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23570
23571 // Record the expression we've just processed.
23572 MVLI.ProcessedVarList.push_back(Elt: SimpleRefExpr);
23573
23574 // Create a mappable component for the list item. List items in this clause
23575 // only need a component. We use a null declaration to signal fields in
23576 // 'this'.
23577 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23578 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23579 "Unexpected device pointer expression!");
23580 MVLI.VarBaseDeclarations.push_back(
23581 Elt: isa<DeclRefExpr>(Val: SimpleRefExpr) ? D : nullptr);
23582 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
23583 MVLI.VarComponents.back().push_back(Elt: MC);
23584 }
23585
23586 if (MVLI.ProcessedVarList.empty())
23587 return nullptr;
23588
23589 return OMPIsDevicePtrClause::Create(
23590 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
23591 ComponentLists: MVLI.VarComponents);
23592}
23593
23594OMPClause *
23595SemaOpenMP::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
23596 const OMPVarListLocTy &Locs) {
23597 MappableVarListInfo MVLI(VarList);
23598 for (Expr *RefExpr : VarList) {
23599 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23600 SourceLocation ELoc;
23601 SourceRange ERange;
23602 Expr *SimpleRefExpr = RefExpr;
23603 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
23604 /*AllowArraySection=*/true);
23605 if (Res.second) {
23606 // It will be analyzed later.
23607 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
23608 }
23609 ValueDecl *D = Res.first;
23610 if (!D)
23611 continue;
23612
23613 // Check if the declaration in the clause does not show up in any data
23614 // sharing attribute.
23615 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23616 if (isOpenMPPrivate(Kind: DVar.CKind)) {
23617 unsigned OMPVersion = getLangOpts().OpenMP;
23618 Diag(Loc: ELoc, DiagID: diag::err_omp_variable_in_given_clause_and_dsa)
23619 << getOpenMPClauseNameForDiag(C: DVar.CKind)
23620 << getOpenMPClauseNameForDiag(C: OMPC_has_device_addr)
23621 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
23622 Ver: OMPVersion);
23623 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
23624 continue;
23625 }
23626
23627 const Expr *ConflictExpr;
23628 if (DSAStack->checkMappableExprComponentListsForDecl(
23629 VD: D, /*CurrentRegionOnly=*/true,
23630 Check: [&ConflictExpr](
23631 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23632 OpenMPClauseKind) -> bool {
23633 ConflictExpr = R.front().getAssociatedExpression();
23634 return true;
23635 })) {
23636 Diag(Loc: ELoc, DiagID: diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23637 Diag(Loc: ConflictExpr->getExprLoc(), DiagID: diag::note_used_here)
23638 << ConflictExpr->getSourceRange();
23639 continue;
23640 }
23641
23642 // Store the components in the stack so that they can be used to check
23643 // against other clauses later on.
23644 Expr *Component = SimpleRefExpr;
23645 auto *VD = dyn_cast<VarDecl>(Val: D);
23646 if (VD && (isa<ArraySectionExpr>(Val: RefExpr->IgnoreParenImpCasts()) ||
23647 isa<ArraySubscriptExpr>(Val: RefExpr->IgnoreParenImpCasts())))
23648 Component =
23649 SemaRef.DefaultFunctionArrayLvalueConversion(E: SimpleRefExpr).get();
23650 OMPClauseMappableExprCommon::MappableComponent MC(
23651 Component, D, /*IsNonContiguous=*/false);
23652 DSAStack->addMappableExpressionComponents(
23653 VD: D, Components: MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23654
23655 // Record the expression we've just processed.
23656 if (!VD && !SemaRef.CurContext->isDependentContext()) {
23657 DeclRefExpr *Ref =
23658 buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
23659 assert(Ref && "has_device_addr capture failed");
23660 MVLI.ProcessedVarList.push_back(Elt: Ref);
23661 } else
23662 MVLI.ProcessedVarList.push_back(Elt: RefExpr->IgnoreParens());
23663
23664 // Create a mappable component for the list item. List items in this clause
23665 // only need a component. We use a null declaration to signal fields in
23666 // 'this'.
23667 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23668 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23669 "Unexpected device pointer expression!");
23670 MVLI.VarBaseDeclarations.push_back(
23671 Elt: isa<DeclRefExpr>(Val: SimpleRefExpr) ? D : nullptr);
23672 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
23673 MVLI.VarComponents.back().push_back(Elt: MC);
23674 }
23675
23676 if (MVLI.ProcessedVarList.empty())
23677 return nullptr;
23678
23679 return OMPHasDeviceAddrClause::Create(
23680 C: getASTContext(), Locs, Vars: MVLI.ProcessedVarList, Declarations: MVLI.VarBaseDeclarations,
23681 ComponentLists: MVLI.VarComponents);
23682}
23683
23684OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause(
23685 Expr *Allocator, Expr *Alignment,
23686 OpenMPAllocateClauseModifier FirstAllocateModifier,
23687 SourceLocation FirstAllocateModifierLoc,
23688 OpenMPAllocateClauseModifier SecondAllocateModifier,
23689 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
23690 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23691 SourceLocation EndLoc) {
23692 if (Allocator) {
23693 // Allocator expression is dependent - skip it for now and build the
23694 // allocator when instantiated.
23695 bool AllocDependent =
23696 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
23697 Allocator->isInstantiationDependent() ||
23698 Allocator->containsUnexpandedParameterPack());
23699 if (!AllocDependent) {
23700 // OpenMP [2.11.4 allocate Clause, Description]
23701 // allocator is an expression of omp_allocator_handle_t type.
23702 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: Allocator->getExprLoc(), DSAStack))
23703 return nullptr;
23704
23705 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(E: Allocator);
23706 if (AllocatorRes.isInvalid())
23707 return nullptr;
23708 AllocatorRes = SemaRef.PerformImplicitConversion(
23709 From: AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
23710 Action: AssignmentAction::Initializing,
23711 /*AllowExplicit=*/true);
23712 if (AllocatorRes.isInvalid())
23713 return nullptr;
23714 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
23715 }
23716 } else {
23717 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23718 // allocate clauses that appear on a target construct or on constructs in a
23719 // target region must specify an allocator expression unless a requires
23720 // directive with the dynamic_allocators clause is present in the same
23721 // compilation unit.
23722 if (getLangOpts().OpenMPIsTargetDevice &&
23723 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23724 SemaRef.targetDiag(Loc: StartLoc, DiagID: diag::err_expected_allocator_expression);
23725 }
23726 if (Alignment) {
23727 bool AlignmentDependent = Alignment->isTypeDependent() ||
23728 Alignment->isValueDependent() ||
23729 Alignment->isInstantiationDependent() ||
23730 Alignment->containsUnexpandedParameterPack();
23731 if (!AlignmentDependent) {
23732 ExprResult AlignResult =
23733 VerifyPositiveIntegerConstantInClause(E: Alignment, CKind: OMPC_allocate);
23734 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
23735 }
23736 }
23737 // Analyze and build list of variables.
23738 SmallVector<Expr *, 8> Vars;
23739 for (Expr *RefExpr : VarList) {
23740 assert(RefExpr && "NULL expr in OpenMP private clause.");
23741 SourceLocation ELoc;
23742 SourceRange ERange;
23743 Expr *SimpleRefExpr = RefExpr;
23744 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
23745 if (Res.second) {
23746 // It will be analyzed later.
23747 Vars.push_back(Elt: RefExpr);
23748 }
23749 ValueDecl *D = Res.first;
23750 if (!D)
23751 continue;
23752
23753 auto *VD = dyn_cast<VarDecl>(Val: D);
23754 DeclRefExpr *Ref = nullptr;
23755 if (!VD && !SemaRef.CurContext->isDependentContext())
23756 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
23757 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
23758 ? RefExpr->IgnoreParens()
23759 : Ref);
23760 }
23761
23762 if (Vars.empty())
23763 return nullptr;
23764
23765 if (Allocator)
23766 DSAStack->addInnerAllocatorExpr(E: Allocator);
23767
23768 return OMPAllocateClause::Create(
23769 C: getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
23770 Modifier1: FirstAllocateModifier, Modifier1Loc: FirstAllocateModifierLoc, Modifier2: SecondAllocateModifier,
23771 Modifier2Loc: SecondAllocateModifierLoc, EndLoc, VL: Vars);
23772}
23773
23774OMPClause *SemaOpenMP::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
23775 SourceLocation StartLoc,
23776 SourceLocation LParenLoc,
23777 SourceLocation EndLoc) {
23778 SmallVector<Expr *, 8> Vars;
23779 for (Expr *RefExpr : VarList) {
23780 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23781 SourceLocation ELoc;
23782 SourceRange ERange;
23783 Expr *SimpleRefExpr = RefExpr;
23784 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
23785 if (Res.second)
23786 // It will be analyzed later.
23787 Vars.push_back(Elt: RefExpr);
23788 ValueDecl *D = Res.first;
23789 if (!D)
23790 continue;
23791
23792 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23793 // A list-item cannot appear in more than one nontemporal clause.
23794 if (const Expr *PrevRef =
23795 DSAStack->addUniqueNontemporal(D, NewDE: SimpleRefExpr)) {
23796 Diag(Loc: ELoc, DiagID: diag::err_omp_used_in_clause_twice)
23797 << 0 << getOpenMPClauseNameForDiag(C: OMPC_nontemporal) << ERange;
23798 Diag(Loc: PrevRef->getExprLoc(), DiagID: diag::note_omp_explicit_dsa)
23799 << getOpenMPClauseNameForDiag(C: OMPC_nontemporal);
23800 continue;
23801 }
23802
23803 Vars.push_back(Elt: RefExpr);
23804 }
23805
23806 if (Vars.empty())
23807 return nullptr;
23808
23809 return OMPNontemporalClause::Create(C: getASTContext(), StartLoc, LParenLoc,
23810 EndLoc, VL: Vars);
23811}
23812
23813StmtResult SemaOpenMP::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
23814 Stmt *AStmt,
23815 SourceLocation StartLoc,
23816 SourceLocation EndLoc) {
23817 if (!AStmt)
23818 return StmtError();
23819
23820 SemaRef.setFunctionHasBranchProtectedScope();
23821
23822 return OMPScopeDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
23823 AssociatedStmt: AStmt);
23824}
23825
23826OMPClause *SemaOpenMP::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
23827 SourceLocation StartLoc,
23828 SourceLocation LParenLoc,
23829 SourceLocation EndLoc) {
23830 SmallVector<Expr *, 8> Vars;
23831 for (Expr *RefExpr : VarList) {
23832 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23833 SourceLocation ELoc;
23834 SourceRange ERange;
23835 Expr *SimpleRefExpr = RefExpr;
23836 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
23837 /*AllowArraySection=*/true);
23838 if (Res.second)
23839 // It will be analyzed later.
23840 Vars.push_back(Elt: RefExpr);
23841 ValueDecl *D = Res.first;
23842 if (!D)
23843 continue;
23844
23845 const DSAStackTy::DSAVarData DVar =
23846 DSAStack->getTopDSA(D, /*FromParent=*/true);
23847 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23848 // A list item that appears in the inclusive or exclusive clause must appear
23849 // in a reduction clause with the inscan modifier on the enclosing
23850 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23851 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23852 Diag(Loc: ELoc, DiagID: diag::err_omp_inclusive_exclusive_not_reduction)
23853 << RefExpr->getSourceRange();
23854
23855 if (DSAStack->getParentDirective() != OMPD_unknown)
23856 DSAStack->markDeclAsUsedInScanDirective(D);
23857 Vars.push_back(Elt: RefExpr);
23858 }
23859
23860 if (Vars.empty())
23861 return nullptr;
23862
23863 return OMPInclusiveClause::Create(C: getASTContext(), StartLoc, LParenLoc,
23864 EndLoc, VL: Vars);
23865}
23866
23867OMPClause *SemaOpenMP::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
23868 SourceLocation StartLoc,
23869 SourceLocation LParenLoc,
23870 SourceLocation EndLoc) {
23871 SmallVector<Expr *, 8> Vars;
23872 for (Expr *RefExpr : VarList) {
23873 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23874 SourceLocation ELoc;
23875 SourceRange ERange;
23876 Expr *SimpleRefExpr = RefExpr;
23877 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
23878 /*AllowArraySection=*/true);
23879 if (Res.second)
23880 // It will be analyzed later.
23881 Vars.push_back(Elt: RefExpr);
23882 ValueDecl *D = Res.first;
23883 if (!D)
23884 continue;
23885
23886 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
23887 DSAStackTy::DSAVarData DVar;
23888 if (ParentDirective != OMPD_unknown)
23889 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
23890 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23891 // A list item that appears in the inclusive or exclusive clause must appear
23892 // in a reduction clause with the inscan modifier on the enclosing
23893 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23894 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23895 DVar.Modifier != OMPC_REDUCTION_inscan) {
23896 Diag(Loc: ELoc, DiagID: diag::err_omp_inclusive_exclusive_not_reduction)
23897 << RefExpr->getSourceRange();
23898 } else {
23899 DSAStack->markDeclAsUsedInScanDirective(D);
23900 }
23901 Vars.push_back(Elt: RefExpr);
23902 }
23903
23904 if (Vars.empty())
23905 return nullptr;
23906
23907 return OMPExclusiveClause::Create(C: getASTContext(), StartLoc, LParenLoc,
23908 EndLoc, VL: Vars);
23909}
23910
23911/// Tries to find omp_alloctrait_t type.
23912static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
23913 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23914 if (!OMPAlloctraitT.isNull())
23915 return true;
23916 IdentifierInfo &II = S.PP.getIdentifierTable().get(Name: "omp_alloctrait_t");
23917 ParsedType PT = S.getTypeName(II, NameLoc: Loc, S: S.getCurScope());
23918 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23919 S.Diag(Loc, DiagID: diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
23920 return false;
23921 }
23922 Stack->setOMPAlloctraitT(PT.get());
23923 return true;
23924}
23925
23926OMPClause *SemaOpenMP::ActOnOpenMPUsesAllocatorClause(
23927 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
23928 ArrayRef<UsesAllocatorsData> Data) {
23929 ASTContext &Context = getASTContext();
23930 // OpenMP [2.12.5, target Construct]
23931 // allocator is an identifier of omp_allocator_handle_t type.
23932 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: StartLoc, DSAStack))
23933 return nullptr;
23934 // OpenMP [2.12.5, target Construct]
23935 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
23936 if (llvm::any_of(
23937 Range&: Data,
23938 P: [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
23939 !findOMPAlloctraitT(S&: SemaRef, Loc: StartLoc, DSAStack))
23940 return nullptr;
23941 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
23942 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23943 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
23944 StringRef Allocator =
23945 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(Val: AllocatorKind);
23946 DeclarationName AllocatorName = &Context.Idents.get(Name: Allocator);
23947 PredefinedAllocators.insert(Ptr: SemaRef.LookupSingleName(
23948 S: SemaRef.TUScope, Name: AllocatorName, Loc: StartLoc, NameKind: Sema::LookupAnyName));
23949 }
23950
23951 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
23952 for (const UsesAllocatorsData &D : Data) {
23953 Expr *AllocatorExpr = nullptr;
23954 // Check allocator expression.
23955 if (D.Allocator->isTypeDependent()) {
23956 AllocatorExpr = D.Allocator;
23957 } else {
23958 // Traits were specified - need to assign new allocator to the specified
23959 // allocator, so it must be an lvalue.
23960 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
23961 auto *DRE = dyn_cast<DeclRefExpr>(Val: AllocatorExpr);
23962 bool IsPredefinedAllocator = false;
23963 if (DRE) {
23964 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23965 getAllocatorKind(S&: SemaRef, DSAStack, Allocator: AllocatorExpr);
23966 IsPredefinedAllocator =
23967 AllocatorTy !=
23968 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23969 }
23970 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
23971 QualType AllocatorExprType = AllocatorExpr->getType();
23972 bool IsTypeCompatible = IsPredefinedAllocator;
23973 IsTypeCompatible = IsTypeCompatible ||
23974 Context.hasSameUnqualifiedType(T1: AllocatorExprType,
23975 T2: OMPAllocatorHandleT);
23976 IsTypeCompatible =
23977 IsTypeCompatible ||
23978 Context.typesAreCompatible(T1: AllocatorExprType, T2: OMPAllocatorHandleT);
23979 bool IsNonConstantLValue =
23980 !AllocatorExprType.isConstant(Ctx: Context) && AllocatorExpr->isLValue();
23981 if (!DRE || !IsTypeCompatible ||
23982 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23983 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::err_omp_var_expected)
23984 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
23985 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
23986 continue;
23987 }
23988 // OpenMP [2.12.5, target Construct]
23989 // Predefined allocators appearing in a uses_allocators clause cannot have
23990 // traits specified.
23991 if (IsPredefinedAllocator && D.AllocatorTraits) {
23992 Diag(Loc: D.AllocatorTraits->getExprLoc(),
23993 DiagID: diag::err_omp_predefined_allocator_with_traits)
23994 << D.AllocatorTraits->getSourceRange();
23995 Diag(Loc: D.Allocator->getExprLoc(), DiagID: diag::note_omp_predefined_allocator)
23996 << cast<NamedDecl>(Val: DRE->getDecl())->getName()
23997 << D.Allocator->getSourceRange();
23998 continue;
23999 }
24000 // OpenMP [2.12.5, target Construct]
24001 // Non-predefined allocators appearing in a uses_allocators clause must
24002 // have traits specified.
24003 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
24004 Diag(Loc: D.Allocator->getExprLoc(),
24005 DiagID: diag::err_omp_nonpredefined_allocator_without_traits);
24006 continue;
24007 }
24008 // No allocator traits - just convert it to rvalue.
24009 if (!D.AllocatorTraits)
24010 AllocatorExpr = SemaRef.DefaultLvalueConversion(E: AllocatorExpr).get();
24011 DSAStack->addUsesAllocatorsDecl(
24012 D: DRE->getDecl(),
24013 Kind: IsPredefinedAllocator
24014 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24015 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
24016 }
24017 Expr *AllocatorTraitsExpr = nullptr;
24018 if (D.AllocatorTraits) {
24019 if (D.AllocatorTraits->isTypeDependent()) {
24020 AllocatorTraitsExpr = D.AllocatorTraits;
24021 } else {
24022 // OpenMP [2.12.5, target Construct]
24023 // Arrays that contain allocator traits that appear in a uses_allocators
24024 // clause must be constant arrays, have constant values and be defined
24025 // in the same scope as the construct in which the clause appears.
24026 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
24027 // Check that traits expr is a constant array.
24028 QualType TraitTy;
24029 if (const ArrayType *Ty =
24030 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
24031 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Val: Ty))
24032 TraitTy = ConstArrayTy->getElementType();
24033 if (TraitTy.isNull() ||
24034 !(Context.hasSameUnqualifiedType(T1: TraitTy,
24035 DSAStack->getOMPAlloctraitT()) ||
24036 Context.typesAreCompatible(T1: TraitTy, DSAStack->getOMPAlloctraitT(),
24037 /*CompareUnqualified=*/true))) {
24038 Diag(Loc: D.AllocatorTraits->getExprLoc(),
24039 DiagID: diag::err_omp_expected_array_alloctraits)
24040 << AllocatorTraitsExpr->getType();
24041 continue;
24042 }
24043 // Do not map by default allocator traits if it is a standalone
24044 // variable.
24045 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: AllocatorTraitsExpr))
24046 DSAStack->addUsesAllocatorsDecl(
24047 D: DRE->getDecl(),
24048 Kind: DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
24049 }
24050 }
24051 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
24052 NewD.Allocator = AllocatorExpr;
24053 NewD.AllocatorTraits = AllocatorTraitsExpr;
24054 NewD.LParenLoc = D.LParenLoc;
24055 NewD.RParenLoc = D.RParenLoc;
24056 }
24057 return OMPUsesAllocatorsClause::Create(C: getASTContext(), StartLoc, LParenLoc,
24058 EndLoc, Data: NewData);
24059}
24060
24061OMPClause *SemaOpenMP::ActOnOpenMPAffinityClause(
24062 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24063 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
24064 SmallVector<Expr *, 8> Vars;
24065 for (Expr *RefExpr : Locators) {
24066 assert(RefExpr && "NULL expr in OpenMP shared clause.");
24067 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr) || RefExpr->isTypeDependent()) {
24068 // It will be analyzed later.
24069 Vars.push_back(Elt: RefExpr);
24070 continue;
24071 }
24072
24073 SourceLocation ELoc = RefExpr->getExprLoc();
24074 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
24075
24076 if (!SimpleExpr->isLValue()) {
24077 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
24078 << 1 << 0 << RefExpr->getSourceRange();
24079 continue;
24080 }
24081
24082 ExprResult Res;
24083 {
24084 Sema::TentativeAnalysisScope Trap(SemaRef);
24085 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: SimpleExpr);
24086 }
24087 if (!Res.isUsable() && !isa<ArraySectionExpr>(Val: SimpleExpr) &&
24088 !isa<OMPArrayShapingExpr>(Val: SimpleExpr)) {
24089 Diag(Loc: ELoc, DiagID: diag::err_omp_expected_addressable_lvalue_or_array_item)
24090 << 1 << 0 << RefExpr->getSourceRange();
24091 continue;
24092 }
24093 Vars.push_back(Elt: SimpleExpr);
24094 }
24095
24096 return OMPAffinityClause::Create(C: getASTContext(), StartLoc, LParenLoc,
24097 ColonLoc, EndLoc, Modifier, Locators: Vars);
24098}
24099
24100OMPClause *SemaOpenMP::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
24101 SourceLocation KindLoc,
24102 SourceLocation StartLoc,
24103 SourceLocation LParenLoc,
24104 SourceLocation EndLoc) {
24105 if (Kind == OMPC_BIND_unknown) {
24106 Diag(Loc: KindLoc, DiagID: diag::err_omp_unexpected_clause_value)
24107 << getListOfPossibleValues(K: OMPC_bind, /*First=*/0,
24108 /*Last=*/unsigned(OMPC_BIND_unknown))
24109 << getOpenMPClauseNameForDiag(C: OMPC_bind);
24110 return nullptr;
24111 }
24112
24113 return OMPBindClause::Create(C: getASTContext(), K: Kind, KLoc: KindLoc, StartLoc,
24114 LParenLoc, EndLoc);
24115}
24116
24117OMPClause *SemaOpenMP::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
24118 SourceLocation StartLoc,
24119 SourceLocation LParenLoc,
24120 SourceLocation EndLoc) {
24121 Expr *ValExpr = Size;
24122 Stmt *HelperValStmt = nullptr;
24123
24124 // OpenMP [2.5, Restrictions]
24125 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24126 // value.
24127 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, CKind: OMPC_ompx_dyn_cgroup_mem,
24128 /*StrictlyPositive=*/false))
24129 return nullptr;
24130
24131 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24132 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
24133 DKind, CKind: OMPC_ompx_dyn_cgroup_mem, OpenMPVersion: getLangOpts().OpenMP);
24134 if (CaptureRegion != OMPD_unknown &&
24135 !SemaRef.CurContext->isDependentContext()) {
24136 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
24137 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24138 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
24139 HelperValStmt = buildPreInits(Context&: getASTContext(), Captures);
24140 }
24141
24142 return new (getASTContext()) OMPXDynCGroupMemClause(
24143 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24144}
24145
24146OMPClause *SemaOpenMP::ActOnOpenMPDoacrossClause(
24147 OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
24148 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
24149 SourceLocation LParenLoc, SourceLocation EndLoc) {
24150
24151 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
24152 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
24153 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
24154 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
24155 Diag(Loc: DepLoc, DiagID: diag::err_omp_unexpected_clause_value)
24156 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(C: OMPC_doacross);
24157 return nullptr;
24158 }
24159
24160 SmallVector<Expr *, 8> Vars;
24161 DSAStackTy::OperatorOffsetTy OpsOffs;
24162 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
24163 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
24164 SemaRef,
24165 IsSource: DepType == OMPC_DOACROSS_source ||
24166 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
24167 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
24168 VarList, DSAStack, EndLoc);
24169 Vars = VarOffset.Vars;
24170 OpsOffs = VarOffset.OpsOffs;
24171 TotalDepCount = VarOffset.TotalDepCount;
24172 auto *C = OMPDoacrossClause::Create(C: getASTContext(), StartLoc, LParenLoc,
24173 EndLoc, DepType, DepLoc, ColonLoc, VL: Vars,
24174 NumLoops: TotalDepCount.getZExtValue());
24175 if (DSAStack->isParentOrderedRegion())
24176 DSAStack->addDoacrossDependClause(C, OpsOffs);
24177 return C;
24178}
24179
24180OMPClause *SemaOpenMP::ActOnOpenMPXAttributeClause(ArrayRef<const Attr *> Attrs,
24181 SourceLocation StartLoc,
24182 SourceLocation LParenLoc,
24183 SourceLocation EndLoc) {
24184 return new (getASTContext())
24185 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
24186}
24187
24188OMPClause *SemaOpenMP::ActOnOpenMPXBareClause(SourceLocation StartLoc,
24189 SourceLocation EndLoc) {
24190 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
24191}
24192
24193OMPClause *SemaOpenMP::ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc,
24194 SourceLocation LParenLoc,
24195 SourceLocation EndLoc) {
24196 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
24197}
24198
24199OMPClause *SemaOpenMP::ActOnOpenMPDirectivePresenceClause(
24200 OpenMPClauseKind CK, llvm::ArrayRef<OpenMPDirectiveKind> DKVec,
24201 SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc) {
24202 switch (CK) {
24203 case OMPC_absent:
24204 return OMPAbsentClause::Create(C: getASTContext(), DKVec, Loc, LLoc, RLoc);
24205 case OMPC_contains:
24206 return OMPContainsClause::Create(C: getASTContext(), DKVec, Loc, LLoc, RLoc);
24207 default:
24208 llvm_unreachable("Unexpected OpenMP clause");
24209 }
24210}
24211
24212OMPClause *SemaOpenMP::ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK,
24213 SourceLocation Loc,
24214 SourceLocation RLoc) {
24215 switch (CK) {
24216 case OMPC_no_openmp:
24217 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
24218 case OMPC_no_openmp_routines:
24219 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
24220 case OMPC_no_parallelism:
24221 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
24222 case OMPC_no_openmp_constructs:
24223 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
24224 default:
24225 llvm_unreachable("Unexpected OpenMP clause");
24226 }
24227}
24228
24229ExprResult SemaOpenMP::ActOnOMPArraySectionExpr(
24230 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
24231 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
24232 Expr *Stride, SourceLocation RBLoc) {
24233 ASTContext &Context = getASTContext();
24234 if (Base->hasPlaceholderType() &&
24235 !Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
24236 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base);
24237 if (Result.isInvalid())
24238 return ExprError();
24239 Base = Result.get();
24240 }
24241 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
24242 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: LowerBound);
24243 if (Result.isInvalid())
24244 return ExprError();
24245 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
24246 if (Result.isInvalid())
24247 return ExprError();
24248 LowerBound = Result.get();
24249 }
24250 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
24251 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Length);
24252 if (Result.isInvalid())
24253 return ExprError();
24254 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
24255 if (Result.isInvalid())
24256 return ExprError();
24257 Length = Result.get();
24258 }
24259 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
24260 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Stride);
24261 if (Result.isInvalid())
24262 return ExprError();
24263 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
24264 if (Result.isInvalid())
24265 return ExprError();
24266 Stride = Result.get();
24267 }
24268
24269 // Build an unanalyzed expression if either operand is type-dependent.
24270 if (Base->isTypeDependent() ||
24271 (LowerBound &&
24272 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
24273 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
24274 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
24275 return new (Context) ArraySectionExpr(
24276 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
24277 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24278 }
24279
24280 // Perform default conversions.
24281 QualType OriginalTy = ArraySectionExpr::getBaseOriginalType(Base);
24282 QualType ResultTy;
24283 if (OriginalTy->isAnyPointerType()) {
24284 ResultTy = OriginalTy->getPointeeType();
24285 } else if (OriginalTy->isArrayType()) {
24286 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
24287 } else {
24288 return ExprError(
24289 Diag(Loc: Base->getExprLoc(), DiagID: diag::err_omp_typecheck_section_value)
24290 << Base->getSourceRange());
24291 }
24292 // C99 6.5.2.1p1
24293 if (LowerBound) {
24294 auto Res = PerformOpenMPImplicitIntegerConversion(Loc: LowerBound->getExprLoc(),
24295 Op: LowerBound);
24296 if (Res.isInvalid())
24297 return ExprError(Diag(Loc: LowerBound->getExprLoc(),
24298 DiagID: diag::err_omp_typecheck_section_not_integer)
24299 << 0 << LowerBound->getSourceRange());
24300 LowerBound = Res.get();
24301
24302 if (LowerBound->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
24303 LowerBound->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
24304 Diag(Loc: LowerBound->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
24305 << 0 << LowerBound->getSourceRange();
24306 }
24307 if (Length) {
24308 auto Res =
24309 PerformOpenMPImplicitIntegerConversion(Loc: Length->getExprLoc(), Op: Length);
24310 if (Res.isInvalid())
24311 return ExprError(Diag(Loc: Length->getExprLoc(),
24312 DiagID: diag::err_omp_typecheck_section_not_integer)
24313 << 1 << Length->getSourceRange());
24314 Length = Res.get();
24315
24316 if (Length->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
24317 Length->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
24318 Diag(Loc: Length->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
24319 << 1 << Length->getSourceRange();
24320 }
24321 if (Stride) {
24322 ExprResult Res =
24323 PerformOpenMPImplicitIntegerConversion(Loc: Stride->getExprLoc(), Op: Stride);
24324 if (Res.isInvalid())
24325 return ExprError(Diag(Loc: Stride->getExprLoc(),
24326 DiagID: diag::err_omp_typecheck_section_not_integer)
24327 << 1 << Stride->getSourceRange());
24328 Stride = Res.get();
24329
24330 if (Stride->getType()->isSpecificBuiltinType(K: BuiltinType::Char_S) ||
24331 Stride->getType()->isSpecificBuiltinType(K: BuiltinType::Char_U))
24332 Diag(Loc: Stride->getExprLoc(), DiagID: diag::warn_omp_section_is_char)
24333 << 1 << Stride->getSourceRange();
24334 }
24335
24336 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
24337 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
24338 // type. Note that functions are not objects, and that (in C99 parlance)
24339 // incomplete types are not object types.
24340 if (ResultTy->isFunctionType()) {
24341 Diag(Loc: Base->getExprLoc(), DiagID: diag::err_omp_section_function_type)
24342 << ResultTy << Base->getSourceRange();
24343 return ExprError();
24344 }
24345
24346 if (SemaRef.RequireCompleteType(Loc: Base->getExprLoc(), T: ResultTy,
24347 DiagID: diag::err_omp_section_incomplete_type, Args: Base))
24348 return ExprError();
24349
24350 if (LowerBound && !OriginalTy->isAnyPointerType()) {
24351 Expr::EvalResult Result;
24352 if (LowerBound->EvaluateAsInt(Result, Ctx: Context)) {
24353 // OpenMP 5.0, [2.1.5 Array Sections]
24354 // The array section must be a subset of the original array.
24355 llvm::APSInt LowerBoundValue = Result.Val.getInt();
24356 if (LowerBoundValue.isNegative()) {
24357 Diag(Loc: LowerBound->getExprLoc(),
24358 DiagID: diag::err_omp_section_not_subset_of_array)
24359 << LowerBound->getSourceRange();
24360 return ExprError();
24361 }
24362 }
24363 }
24364
24365 if (Length) {
24366 Expr::EvalResult Result;
24367 if (Length->EvaluateAsInt(Result, Ctx: Context)) {
24368 // OpenMP 5.0, [2.1.5 Array Sections]
24369 // The length must evaluate to non-negative integers.
24370 llvm::APSInt LengthValue = Result.Val.getInt();
24371 if (LengthValue.isNegative()) {
24372 Diag(Loc: Length->getExprLoc(), DiagID: diag::err_omp_section_length_negative)
24373 << toString(I: LengthValue, /*Radix=*/10, /*Signed=*/true)
24374 << Length->getSourceRange();
24375 return ExprError();
24376 }
24377 }
24378 } else if (ColonLocFirst.isValid() &&
24379 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
24380 !OriginalTy->isVariableArrayType()))) {
24381 // OpenMP 5.0, [2.1.5 Array Sections]
24382 // When the size of the array dimension is not known, the length must be
24383 // specified explicitly.
24384 Diag(Loc: ColonLocFirst, DiagID: diag::err_omp_section_length_undefined)
24385 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
24386 return ExprError();
24387 }
24388
24389 if (Stride) {
24390 Expr::EvalResult Result;
24391 if (Stride->EvaluateAsInt(Result, Ctx: Context)) {
24392 // OpenMP 5.0, [2.1.5 Array Sections]
24393 // The stride must evaluate to a positive integer.
24394 llvm::APSInt StrideValue = Result.Val.getInt();
24395 if (!StrideValue.isStrictlyPositive()) {
24396 Diag(Loc: Stride->getExprLoc(), DiagID: diag::err_omp_section_stride_non_positive)
24397 << toString(I: StrideValue, /*Radix=*/10, /*Signed=*/true)
24398 << Stride->getSourceRange();
24399 return ExprError();
24400 }
24401 }
24402 }
24403
24404 if (!Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
24405 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(E: Base);
24406 if (Result.isInvalid())
24407 return ExprError();
24408 Base = Result.get();
24409 }
24410 return new (Context) ArraySectionExpr(
24411 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
24412 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24413}
24414
24415ExprResult SemaOpenMP::ActOnOMPArrayShapingExpr(
24416 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
24417 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
24418 ASTContext &Context = getASTContext();
24419 if (Base->hasPlaceholderType()) {
24420 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base);
24421 if (Result.isInvalid())
24422 return ExprError();
24423 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
24424 if (Result.isInvalid())
24425 return ExprError();
24426 Base = Result.get();
24427 }
24428 QualType BaseTy = Base->getType();
24429 // Delay analysis of the types/expressions if instantiation/specialization is
24430 // required.
24431 if (!BaseTy->isPointerType() && Base->isTypeDependent())
24432 return OMPArrayShapingExpr::Create(Context, T: Context.DependentTy, Op: Base,
24433 L: LParenLoc, R: RParenLoc, Dims, BracketRanges: Brackets);
24434 if (!BaseTy->isPointerType() ||
24435 (!Base->isTypeDependent() &&
24436 BaseTy->getPointeeType()->isIncompleteType()))
24437 return ExprError(Diag(Loc: Base->getExprLoc(),
24438 DiagID: diag::err_omp_non_pointer_type_array_shaping_base)
24439 << Base->getSourceRange());
24440
24441 SmallVector<Expr *, 4> NewDims;
24442 bool ErrorFound = false;
24443 for (Expr *Dim : Dims) {
24444 if (Dim->hasPlaceholderType()) {
24445 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Dim);
24446 if (Result.isInvalid()) {
24447 ErrorFound = true;
24448 continue;
24449 }
24450 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
24451 if (Result.isInvalid()) {
24452 ErrorFound = true;
24453 continue;
24454 }
24455 Dim = Result.get();
24456 }
24457 if (!Dim->isTypeDependent()) {
24458 ExprResult Result =
24459 PerformOpenMPImplicitIntegerConversion(Loc: Dim->getExprLoc(), Op: Dim);
24460 if (Result.isInvalid()) {
24461 ErrorFound = true;
24462 Diag(Loc: Dim->getExprLoc(), DiagID: diag::err_omp_typecheck_shaping_not_integer)
24463 << Dim->getSourceRange();
24464 continue;
24465 }
24466 Dim = Result.get();
24467 Expr::EvalResult EvResult;
24468 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(Result&: EvResult, Ctx: Context)) {
24469 // OpenMP 5.0, [2.1.4 Array Shaping]
24470 // Each si is an integral type expression that must evaluate to a
24471 // positive integer.
24472 llvm::APSInt Value = EvResult.Val.getInt();
24473 if (!Value.isStrictlyPositive()) {
24474 Diag(Loc: Dim->getExprLoc(), DiagID: diag::err_omp_shaping_dimension_not_positive)
24475 << toString(I: Value, /*Radix=*/10, /*Signed=*/true)
24476 << Dim->getSourceRange();
24477 ErrorFound = true;
24478 continue;
24479 }
24480 }
24481 }
24482 NewDims.push_back(Elt: Dim);
24483 }
24484 if (ErrorFound)
24485 return ExprError();
24486 return OMPArrayShapingExpr::Create(Context, T: Context.OMPArrayShapingTy, Op: Base,
24487 L: LParenLoc, R: RParenLoc, Dims: NewDims, BracketRanges: Brackets);
24488}
24489
24490ExprResult SemaOpenMP::ActOnOMPIteratorExpr(Scope *S,
24491 SourceLocation IteratorKwLoc,
24492 SourceLocation LLoc,
24493 SourceLocation RLoc,
24494 ArrayRef<OMPIteratorData> Data) {
24495 ASTContext &Context = getASTContext();
24496 SmallVector<OMPIteratorExpr::IteratorDefinition, 4> ID;
24497 bool IsCorrect = true;
24498 for (const OMPIteratorData &D : Data) {
24499 TypeSourceInfo *TInfo = nullptr;
24500 SourceLocation StartLoc;
24501 QualType DeclTy;
24502 if (!D.Type.getAsOpaquePtr()) {
24503 // OpenMP 5.0, 2.1.6 Iterators
24504 // In an iterator-specifier, if the iterator-type is not specified then
24505 // the type of that iterator is of int type.
24506 DeclTy = Context.IntTy;
24507 StartLoc = D.DeclIdentLoc;
24508 } else {
24509 DeclTy = Sema::GetTypeFromParser(Ty: D.Type, TInfo: &TInfo);
24510 StartLoc = TInfo->getTypeLoc().getBeginLoc();
24511 }
24512
24513 bool IsDeclTyDependent = DeclTy->isDependentType() ||
24514 DeclTy->containsUnexpandedParameterPack() ||
24515 DeclTy->isInstantiationDependentType();
24516 if (!IsDeclTyDependent) {
24517 if (!DeclTy->isIntegralType(Ctx: Context) && !DeclTy->isAnyPointerType()) {
24518 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24519 // The iterator-type must be an integral or pointer type.
24520 Diag(Loc: StartLoc, DiagID: diag::err_omp_iterator_not_integral_or_pointer)
24521 << DeclTy;
24522 IsCorrect = false;
24523 continue;
24524 }
24525 if (DeclTy.isConstant(Ctx: Context)) {
24526 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24527 // The iterator-type must not be const qualified.
24528 Diag(Loc: StartLoc, DiagID: diag::err_omp_iterator_not_integral_or_pointer)
24529 << DeclTy;
24530 IsCorrect = false;
24531 continue;
24532 }
24533 }
24534
24535 // Iterator declaration.
24536 assert(D.DeclIdent && "Identifier expected.");
24537 // Always try to create iterator declarator to avoid extra error messages
24538 // about unknown declarations use.
24539 auto *VD =
24540 VarDecl::Create(C&: Context, DC: SemaRef.CurContext, StartLoc, IdLoc: D.DeclIdentLoc,
24541 Id: D.DeclIdent, T: DeclTy, TInfo, S: SC_None);
24542 VD->setImplicit();
24543 if (S) {
24544 // Check for conflicting previous declaration.
24545 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
24546 LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
24547 RedeclarationKind::ForVisibleRedeclaration);
24548 Previous.suppressDiagnostics();
24549 SemaRef.LookupName(R&: Previous, S);
24550
24551 SemaRef.FilterLookupForScope(R&: Previous, Ctx: SemaRef.CurContext, S,
24552 /*ConsiderLinkage=*/false,
24553 /*AllowInlineNamespace=*/false);
24554 if (!Previous.empty()) {
24555 NamedDecl *Old = Previous.getRepresentativeDecl();
24556 Diag(Loc: D.DeclIdentLoc, DiagID: diag::err_redefinition) << VD->getDeclName();
24557 Diag(Loc: Old->getLocation(), DiagID: diag::note_previous_definition);
24558 } else {
24559 SemaRef.PushOnScopeChains(D: VD, S);
24560 }
24561 } else {
24562 SemaRef.CurContext->addDecl(D: VD);
24563 }
24564
24565 /// Act on the iterator variable declaration.
24566 ActOnOpenMPIteratorVarDecl(VD);
24567
24568 Expr *Begin = D.Range.Begin;
24569 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
24570 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
24571 From: Begin, ToType: DeclTy, Action: AssignmentAction::Converting);
24572 Begin = BeginRes.get();
24573 }
24574 Expr *End = D.Range.End;
24575 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
24576 ExprResult EndRes = SemaRef.PerformImplicitConversion(
24577 From: End, ToType: DeclTy, Action: AssignmentAction::Converting);
24578 End = EndRes.get();
24579 }
24580 Expr *Step = D.Range.Step;
24581 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
24582 if (!Step->getType()->isIntegralType(Ctx: Context)) {
24583 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_iterator_step_not_integral)
24584 << Step << Step->getSourceRange();
24585 IsCorrect = false;
24586 continue;
24587 }
24588 std::optional<llvm::APSInt> Result =
24589 Step->getIntegerConstantExpr(Ctx: Context);
24590 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
24591 // If the step expression of a range-specification equals zero, the
24592 // behavior is unspecified.
24593 if (Result && Result->isZero()) {
24594 Diag(Loc: Step->getExprLoc(), DiagID: diag::err_omp_iterator_step_constant_zero)
24595 << Step << Step->getSourceRange();
24596 IsCorrect = false;
24597 continue;
24598 }
24599 }
24600 if (!Begin || !End || !IsCorrect) {
24601 IsCorrect = false;
24602 continue;
24603 }
24604 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
24605 IDElem.IteratorDecl = VD;
24606 IDElem.AssignmentLoc = D.AssignLoc;
24607 IDElem.Range.Begin = Begin;
24608 IDElem.Range.End = End;
24609 IDElem.Range.Step = Step;
24610 IDElem.ColonLoc = D.ColonLoc;
24611 IDElem.SecondColonLoc = D.SecColonLoc;
24612 }
24613 if (!IsCorrect) {
24614 // Invalidate all created iterator declarations if error is found.
24615 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24616 if (Decl *ID = D.IteratorDecl)
24617 ID->setInvalidDecl();
24618 }
24619 return ExprError();
24620 }
24621 SmallVector<OMPIteratorHelperData, 4> Helpers;
24622 if (!SemaRef.CurContext->isDependentContext()) {
24623 // Build number of ityeration for each iteration range.
24624 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
24625 // ((Begini-Stepi-1-Endi) / -Stepi);
24626 for (OMPIteratorExpr::IteratorDefinition &D : ID) {
24627 // (Endi - Begini)
24628 ExprResult Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Sub,
24629 LHSExpr: D.Range.End, RHSExpr: D.Range.Begin);
24630 if (!Res.isUsable()) {
24631 IsCorrect = false;
24632 continue;
24633 }
24634 ExprResult St, St1;
24635 if (D.Range.Step) {
24636 St = D.Range.Step;
24637 // (Endi - Begini) + Stepi
24638 Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add, LHSExpr: Res.get(),
24639 RHSExpr: St.get());
24640 if (!Res.isUsable()) {
24641 IsCorrect = false;
24642 continue;
24643 }
24644 // (Endi - Begini) + Stepi - 1
24645 Res = SemaRef.CreateBuiltinBinOp(
24646 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: Res.get(),
24647 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 1).get());
24648 if (!Res.isUsable()) {
24649 IsCorrect = false;
24650 continue;
24651 }
24652 // ((Endi - Begini) + Stepi - 1) / Stepi
24653 Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Div, LHSExpr: Res.get(),
24654 RHSExpr: St.get());
24655 if (!Res.isUsable()) {
24656 IsCorrect = false;
24657 continue;
24658 }
24659 St1 = SemaRef.CreateBuiltinUnaryOp(OpLoc: D.AssignmentLoc, Opc: UO_Minus,
24660 InputExpr: D.Range.Step);
24661 // (Begini - Endi)
24662 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
24663 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: D.Range.Begin, RHSExpr: D.Range.End);
24664 if (!Res1.isUsable()) {
24665 IsCorrect = false;
24666 continue;
24667 }
24668 // (Begini - Endi) - Stepi
24669 Res1 = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add, LHSExpr: Res1.get(),
24670 RHSExpr: St1.get());
24671 if (!Res1.isUsable()) {
24672 IsCorrect = false;
24673 continue;
24674 }
24675 // (Begini - Endi) - Stepi - 1
24676 Res1 = SemaRef.CreateBuiltinBinOp(
24677 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: Res1.get(),
24678 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 1).get());
24679 if (!Res1.isUsable()) {
24680 IsCorrect = false;
24681 continue;
24682 }
24683 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
24684 Res1 = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Div, LHSExpr: Res1.get(),
24685 RHSExpr: St1.get());
24686 if (!Res1.isUsable()) {
24687 IsCorrect = false;
24688 continue;
24689 }
24690 // Stepi > 0.
24691 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
24692 OpLoc: D.AssignmentLoc, Opc: BO_GT, LHSExpr: D.Range.Step,
24693 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 0).get());
24694 if (!CmpRes.isUsable()) {
24695 IsCorrect = false;
24696 continue;
24697 }
24698 Res = SemaRef.ActOnConditionalOp(QuestionLoc: D.AssignmentLoc, ColonLoc: D.AssignmentLoc,
24699 CondExpr: CmpRes.get(), LHSExpr: Res.get(), RHSExpr: Res1.get());
24700 if (!Res.isUsable()) {
24701 IsCorrect = false;
24702 continue;
24703 }
24704 }
24705 Res = SemaRef.ActOnFinishFullExpr(Expr: Res.get(), /*DiscardedValue=*/false);
24706 if (!Res.isUsable()) {
24707 IsCorrect = false;
24708 continue;
24709 }
24710
24711 // Build counter update.
24712 // Build counter.
24713 auto *CounterVD = VarDecl::Create(C&: Context, DC: SemaRef.CurContext,
24714 StartLoc: D.IteratorDecl->getBeginLoc(),
24715 IdLoc: D.IteratorDecl->getBeginLoc(), Id: nullptr,
24716 T: Res.get()->getType(), TInfo: nullptr, S: SC_None);
24717 CounterVD->setImplicit();
24718 ExprResult RefRes =
24719 SemaRef.BuildDeclRefExpr(D: CounterVD, Ty: CounterVD->getType(), VK: VK_LValue,
24720 Loc: D.IteratorDecl->getBeginLoc());
24721 // Build counter update.
24722 // I = Begini + counter * Stepi;
24723 ExprResult UpdateRes;
24724 if (D.Range.Step) {
24725 UpdateRes = SemaRef.CreateBuiltinBinOp(
24726 OpLoc: D.AssignmentLoc, Opc: BO_Mul,
24727 LHSExpr: SemaRef.DefaultLvalueConversion(E: RefRes.get()).get(), RHSExpr: St.get());
24728 } else {
24729 UpdateRes = SemaRef.DefaultLvalueConversion(E: RefRes.get());
24730 }
24731 if (!UpdateRes.isUsable()) {
24732 IsCorrect = false;
24733 continue;
24734 }
24735 UpdateRes = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add,
24736 LHSExpr: D.Range.Begin, RHSExpr: UpdateRes.get());
24737 if (!UpdateRes.isUsable()) {
24738 IsCorrect = false;
24739 continue;
24740 }
24741 ExprResult VDRes =
24742 SemaRef.BuildDeclRefExpr(D: cast<VarDecl>(Val: D.IteratorDecl),
24743 Ty: cast<VarDecl>(Val: D.IteratorDecl)->getType(),
24744 VK: VK_LValue, Loc: D.IteratorDecl->getBeginLoc());
24745 UpdateRes = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Assign,
24746 LHSExpr: VDRes.get(), RHSExpr: UpdateRes.get());
24747 if (!UpdateRes.isUsable()) {
24748 IsCorrect = false;
24749 continue;
24750 }
24751 UpdateRes =
24752 SemaRef.ActOnFinishFullExpr(Expr: UpdateRes.get(), /*DiscardedValue=*/true);
24753 if (!UpdateRes.isUsable()) {
24754 IsCorrect = false;
24755 continue;
24756 }
24757 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
24758 OpLoc: D.AssignmentLoc, Opc: UO_PreInc, InputExpr: RefRes.get());
24759 if (!CounterUpdateRes.isUsable()) {
24760 IsCorrect = false;
24761 continue;
24762 }
24763 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(Expr: CounterUpdateRes.get(),
24764 /*DiscardedValue=*/true);
24765 if (!CounterUpdateRes.isUsable()) {
24766 IsCorrect = false;
24767 continue;
24768 }
24769 OMPIteratorHelperData &HD = Helpers.emplace_back();
24770 HD.CounterVD = CounterVD;
24771 HD.Upper = Res.get();
24772 HD.Update = UpdateRes.get();
24773 HD.CounterUpdate = CounterUpdateRes.get();
24774 }
24775 } else {
24776 Helpers.assign(NumElts: ID.size(), Elt: {});
24777 }
24778 if (!IsCorrect) {
24779 // Invalidate all created iterator declarations if error is found.
24780 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24781 if (Decl *ID = D.IteratorDecl)
24782 ID->setInvalidDecl();
24783 }
24784 return ExprError();
24785 }
24786 return OMPIteratorExpr::Create(Context, T: Context.OMPIteratorTy, IteratorKwLoc,
24787 L: LLoc, R: RLoc, Data: ID, Helpers);
24788}
24789
24790/// Check if \p AssumptionStr is a known assumption and warn if not.
24791static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc,
24792 StringRef AssumptionStr) {
24793 if (llvm::KnownAssumptionStrings.count(Key: AssumptionStr))
24794 return;
24795
24796 unsigned BestEditDistance = 3;
24797 StringRef Suggestion;
24798 for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
24799 unsigned EditDistance =
24800 AssumptionStr.edit_distance(Other: KnownAssumptionIt.getKey());
24801 if (EditDistance < BestEditDistance) {
24802 Suggestion = KnownAssumptionIt.getKey();
24803 BestEditDistance = EditDistance;
24804 }
24805 }
24806
24807 if (!Suggestion.empty())
24808 S.Diag(Loc, DiagID: diag::warn_omp_assume_attribute_string_unknown_suggested)
24809 << AssumptionStr << Suggestion;
24810 else
24811 S.Diag(Loc, DiagID: diag::warn_omp_assume_attribute_string_unknown)
24812 << AssumptionStr;
24813}
24814
24815void SemaOpenMP::handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL) {
24816 // Handle the case where the attribute has a text message.
24817 StringRef Str;
24818 SourceLocation AttrStrLoc;
24819 if (!SemaRef.checkStringLiteralArgumentAttr(Attr: AL, ArgNum: 0, Str, ArgLocation: &AttrStrLoc))
24820 return;
24821
24822 checkOMPAssumeAttr(S&: SemaRef, Loc: AttrStrLoc, AssumptionStr: Str);
24823
24824 D->addAttr(A: ::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
24825}
24826
24827SemaOpenMP::SemaOpenMP(Sema &S)
24828 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
24829