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 "TreeTransform.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/ASTMutationListener.h"
17#include "clang/AST/CXXInheritance.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/DeclCXX.h"
20#include "clang/AST/DeclOpenMP.h"
21#include "clang/AST/OpenMPClause.h"
22#include "clang/AST/StmtCXX.h"
23#include "clang/AST/StmtOpenMP.h"
24#include "clang/AST/StmtVisitor.h"
25#include "clang/AST/TypeOrdering.h"
26#include "clang/Basic/DiagnosticSema.h"
27#include "clang/Basic/OpenMPKinds.h"
28#include "clang/Basic/PartialDiagnostic.h"
29#include "clang/Basic/TargetInfo.h"
30#include "clang/Sema/EnterExpressionEvaluationContext.h"
31#include "clang/Sema/Initialization.h"
32#include "clang/Sema/Lookup.h"
33#include "clang/Sema/ParsedAttr.h"
34#include "clang/Sema/Scope.h"
35#include "clang/Sema/ScopeInfo.h"
36#include "clang/Sema/SemaInternal.h"
37#include "llvm/ADT/IndexedMap.h"
38#include "llvm/ADT/PointerEmbeddedInt.h"
39#include "llvm/ADT/STLExtras.h"
40#include "llvm/ADT/SmallSet.h"
41#include "llvm/ADT/StringExtras.h"
42#include "llvm/Frontend/OpenMP/OMPAssume.h"
43#include "llvm/Frontend/OpenMP/OMPConstants.h"
44#include <optional>
45#include <set>
46
47using namespace clang;
48using namespace llvm::omp;
49
50//===----------------------------------------------------------------------===//
51// Stack of data-sharing attributes for variables
52//===----------------------------------------------------------------------===//
53
54static const Expr *checkMapClauseExpressionBase(
55 Sema &SemaRef, Expr *E,
56 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
57 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
58
59namespace {
60/// Default data sharing attributes, which can be applied to directive.
61enum DefaultDataSharingAttributes {
62 DSA_unspecified = 0, /// Data sharing attribute not specified.
63 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
64 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
65 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
66 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
67};
68
69/// Stack for tracking declarations used in OpenMP directives and
70/// clauses and their data-sharing attributes.
71class DSAStackTy {
72public:
73 struct DSAVarData {
74 OpenMPDirectiveKind DKind = OMPD_unknown;
75 OpenMPClauseKind CKind = OMPC_unknown;
76 unsigned Modifier = 0;
77 const Expr *RefExpr = nullptr;
78 DeclRefExpr *PrivateCopy = nullptr;
79 SourceLocation ImplicitDSALoc;
80 bool AppliedToPointee = false;
81 DSAVarData() = default;
82 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
83 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
84 SourceLocation ImplicitDSALoc, unsigned Modifier,
85 bool AppliedToPointee)
86 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
87 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
88 AppliedToPointee(AppliedToPointee) {}
89 };
90 using OperatorOffsetTy =
91 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
92 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
93 /// Kind of the declaration used in the uses_allocators clauses.
94 enum class UsesAllocatorsDeclKind {
95 /// Predefined allocator
96 PredefinedAllocator,
97 /// User-defined allocator
98 UserDefinedAllocator,
99 /// The declaration that represent allocator trait
100 AllocatorTrait,
101 };
102
103private:
104 struct DSAInfo {
105 OpenMPClauseKind Attributes = OMPC_unknown;
106 unsigned Modifier = 0;
107 /// Pointer to a reference expression and a flag which shows that the
108 /// variable is marked as lastprivate(true) or not (false).
109 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
110 DeclRefExpr *PrivateCopy = nullptr;
111 /// true if the attribute is applied to the pointee, not the variable
112 /// itself.
113 bool AppliedToPointee = false;
114 };
115 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
116 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
117 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
118 using LoopControlVariablesMapTy =
119 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
120 /// Struct that associates a component with the clause kind where they are
121 /// found.
122 struct MappedExprComponentTy {
123 OMPClauseMappableExprCommon::MappableExprComponentLists Components;
124 OpenMPClauseKind Kind = OMPC_unknown;
125 };
126 using MappedExprComponentsTy =
127 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
128 using CriticalsWithHintsTy =
129 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
130 struct ReductionData {
131 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
132 SourceRange ReductionRange;
133 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
134 ReductionData() = default;
135 void set(BinaryOperatorKind BO, SourceRange RR) {
136 ReductionRange = RR;
137 ReductionOp = BO;
138 }
139 void set(const Expr *RefExpr, SourceRange RR) {
140 ReductionRange = RR;
141 ReductionOp = RefExpr;
142 }
143 };
144 using DeclReductionMapTy =
145 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
146 struct DefaultmapInfo {
147 OpenMPDefaultmapClauseModifier ImplicitBehavior =
148 OMPC_DEFAULTMAP_MODIFIER_unknown;
149 SourceLocation SLoc;
150 DefaultmapInfo() = default;
151 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
152 : ImplicitBehavior(M), SLoc(Loc) {}
153 };
154
155 struct SharingMapTy {
156 DeclSAMapTy SharingMap;
157 DeclReductionMapTy ReductionMap;
158 UsedRefMapTy AlignedMap;
159 UsedRefMapTy NontemporalMap;
160 MappedExprComponentsTy MappedExprComponents;
161 LoopControlVariablesMapTy LCVMap;
162 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
163 SourceLocation DefaultAttrLoc;
164 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
165 OpenMPDirectiveKind Directive = OMPD_unknown;
166 /// GenericLoopDirective with bind clause is mapped to other directives,
167 /// like for, distribute and simd. Presently, set MappedDirective to
168 /// OMPLoop. This may also be used in a similar way for other constructs.
169 OpenMPDirectiveKind MappedDirective = OMPD_unknown;
170 DeclarationNameInfo DirectiveName;
171 Scope *CurScope = nullptr;
172 DeclContext *Context = nullptr;
173 SourceLocation ConstructLoc;
174 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
175 /// get the data (loop counters etc.) about enclosing loop-based construct.
176 /// This data is required during codegen.
177 DoacrossClauseMapTy DoacrossDepends;
178 /// First argument (Expr *) contains optional argument of the
179 /// 'ordered' clause, the second one is true if the regions has 'ordered'
180 /// clause, false otherwise.
181 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
182 bool RegionHasOrderConcurrent = false;
183 unsigned AssociatedLoops = 1;
184 bool HasMutipleLoops = false;
185 const Decl *PossiblyLoopCounter = nullptr;
186 bool NowaitRegion = false;
187 bool UntiedRegion = false;
188 bool CancelRegion = false;
189 bool LoopStart = false;
190 bool BodyComplete = false;
191 SourceLocation PrevScanLocation;
192 SourceLocation PrevOrderedLocation;
193 SourceLocation InnerTeamsRegionLoc;
194 /// Reference to the taskgroup task_reduction reference expression.
195 Expr *TaskgroupReductionRef = nullptr;
196 llvm::DenseSet<QualType> MappedClassesQualTypes;
197 SmallVector<Expr *, 4> InnerUsedAllocators;
198 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
199 /// List of globals marked as declare target link in this target region
200 /// (isOpenMPTargetExecutionDirective(Directive) == true).
201 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
202 /// List of decls used in inclusive/exclusive clauses of the scan directive.
203 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
204 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
205 UsesAllocatorsDecls;
206 /// Data is required on creating capture fields for implicit
207 /// default first|private clause.
208 struct ImplicitDefaultFDInfoTy {
209 /// Field decl.
210 const FieldDecl *FD = nullptr;
211 /// Nesting stack level
212 size_t StackLevel = 0;
213 /// Capture variable decl.
214 VarDecl *VD = nullptr;
215 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
216 VarDecl *VD)
217 : FD(FD), StackLevel(StackLevel), VD(VD) {}
218 };
219 /// List of captured fields
220 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
221 ImplicitDefaultFirstprivateFDs;
222 Expr *DeclareMapperVar = nullptr;
223 SmallVector<VarDecl *, 16> IteratorVarDecls;
224 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
225 Scope *CurScope, SourceLocation Loc)
226 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
227 ConstructLoc(Loc) {}
228 SharingMapTy() = default;
229 };
230
231 using StackTy = SmallVector<SharingMapTy, 4>;
232
233 /// Stack of used declaration and their data-sharing attributes.
234 DeclSAMapTy Threadprivates;
235 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
236 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
237 /// true, if check for DSA must be from parent directive, false, if
238 /// from current directive.
239 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
240 Sema &SemaRef;
241 bool ForceCapturing = false;
242 /// true if all the variables in the target executable directives must be
243 /// captured by reference.
244 bool ForceCaptureByReferenceInTargetExecutable = false;
245 CriticalsWithHintsTy Criticals;
246 unsigned IgnoredStackElements = 0;
247
248 /// Iterators over the stack iterate in order from innermost to outermost
249 /// directive.
250 using const_iterator = StackTy::const_reverse_iterator;
251 const_iterator begin() const {
252 return Stack.empty() ? const_iterator()
253 : Stack.back().first.rbegin() + IgnoredStackElements;
254 }
255 const_iterator end() const {
256 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
257 }
258 using iterator = StackTy::reverse_iterator;
259 iterator begin() {
260 return Stack.empty() ? iterator()
261 : Stack.back().first.rbegin() + IgnoredStackElements;
262 }
263 iterator end() {
264 return Stack.empty() ? iterator() : Stack.back().first.rend();
265 }
266
267 // Convenience operations to get at the elements of the stack.
268
269 bool isStackEmpty() const {
270 return Stack.empty() ||
271 Stack.back().second != CurrentNonCapturingFunctionScope ||
272 Stack.back().first.size() <= IgnoredStackElements;
273 }
274 size_t getStackSize() const {
275 return isStackEmpty() ? 0
276 : Stack.back().first.size() - IgnoredStackElements;
277 }
278
279 SharingMapTy *getTopOfStackOrNull() {
280 size_t Size = getStackSize();
281 if (Size == 0)
282 return nullptr;
283 return &Stack.back().first[Size - 1];
284 }
285 const SharingMapTy *getTopOfStackOrNull() const {
286 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
287 }
288 SharingMapTy &getTopOfStack() {
289 assert(!isStackEmpty() && "no current directive");
290 return *getTopOfStackOrNull();
291 }
292 const SharingMapTy &getTopOfStack() const {
293 return const_cast<DSAStackTy &>(*this).getTopOfStack();
294 }
295
296 SharingMapTy *getSecondOnStackOrNull() {
297 size_t Size = getStackSize();
298 if (Size <= 1)
299 return nullptr;
300 return &Stack.back().first[Size - 2];
301 }
302 const SharingMapTy *getSecondOnStackOrNull() const {
303 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
304 }
305
306 /// Get the stack element at a certain level (previously returned by
307 /// \c getNestingLevel).
308 ///
309 /// Note that nesting levels count from outermost to innermost, and this is
310 /// the reverse of our iteration order where new inner levels are pushed at
311 /// the front of the stack.
312 SharingMapTy &getStackElemAtLevel(unsigned Level) {
313 assert(Level < getStackSize() && "no such stack element");
314 return Stack.back().first[Level];
315 }
316 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
317 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
318 }
319
320 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
321
322 /// Checks if the variable is a local for OpenMP region.
323 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
324
325 /// Vector of previously declared requires directives
326 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
327 /// omp_allocator_handle_t type.
328 QualType OMPAllocatorHandleT;
329 /// omp_depend_t type.
330 QualType OMPDependT;
331 /// omp_event_handle_t type.
332 QualType OMPEventHandleT;
333 /// omp_alloctrait_t type.
334 QualType OMPAlloctraitT;
335 /// Expression for the predefined allocators.
336 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
337 nullptr};
338 /// Vector of previously encountered target directives
339 SmallVector<SourceLocation, 2> TargetLocations;
340 SourceLocation AtomicLocation;
341 /// Vector of declare variant construct traits.
342 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
343
344public:
345 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
346
347 /// Sets omp_allocator_handle_t type.
348 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
349 /// Gets omp_allocator_handle_t type.
350 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
351 /// Sets omp_alloctrait_t type.
352 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
353 /// Gets omp_alloctrait_t type.
354 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
355 /// Sets the given default allocator.
356 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
357 Expr *Allocator) {
358 OMPPredefinedAllocators[AllocatorKind] = Allocator;
359 }
360 /// Returns the specified default allocator.
361 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
362 return OMPPredefinedAllocators[AllocatorKind];
363 }
364 /// Sets omp_depend_t type.
365 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
366 /// Gets omp_depend_t type.
367 QualType getOMPDependT() const { return OMPDependT; }
368
369 /// Sets omp_event_handle_t type.
370 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
371 /// Gets omp_event_handle_t type.
372 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
373
374 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
375 OpenMPClauseKind getClauseParsingMode() const {
376 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
377 return ClauseKindMode;
378 }
379 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
380
381 bool isBodyComplete() const {
382 const SharingMapTy *Top = getTopOfStackOrNull();
383 return Top && Top->BodyComplete;
384 }
385 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
386
387 bool isForceVarCapturing() const { return ForceCapturing; }
388 void setForceVarCapturing(bool V) { ForceCapturing = V; }
389
390 void setForceCaptureByReferenceInTargetExecutable(bool V) {
391 ForceCaptureByReferenceInTargetExecutable = V;
392 }
393 bool isForceCaptureByReferenceInTargetExecutable() const {
394 return ForceCaptureByReferenceInTargetExecutable;
395 }
396
397 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
398 Scope *CurScope, SourceLocation Loc) {
399 assert(!IgnoredStackElements &&
400 "cannot change stack while ignoring elements");
401 if (Stack.empty() ||
402 Stack.back().second != CurrentNonCapturingFunctionScope)
403 Stack.emplace_back(Args: StackTy(), Args&: CurrentNonCapturingFunctionScope);
404 Stack.back().first.emplace_back(Args&: DKind, Args: DirName, Args&: CurScope, Args&: Loc);
405 Stack.back().first.back().DefaultAttrLoc = Loc;
406 }
407
408 void pop() {
409 assert(!IgnoredStackElements &&
410 "cannot change stack while ignoring elements");
411 assert(!Stack.back().first.empty() &&
412 "Data-sharing attributes stack is empty!");
413 Stack.back().first.pop_back();
414 }
415
416 /// RAII object to temporarily leave the scope of a directive when we want to
417 /// logically operate in its parent.
418 class ParentDirectiveScope {
419 DSAStackTy &Self;
420 bool Active;
421
422 public:
423 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
424 : Self(Self), Active(false) {
425 if (Activate)
426 enable();
427 }
428 ~ParentDirectiveScope() { disable(); }
429 void disable() {
430 if (Active) {
431 --Self.IgnoredStackElements;
432 Active = false;
433 }
434 }
435 void enable() {
436 if (!Active) {
437 ++Self.IgnoredStackElements;
438 Active = true;
439 }
440 }
441 };
442
443 /// Marks that we're started loop parsing.
444 void loopInit() {
445 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
446 "Expected loop-based directive.");
447 getTopOfStack().LoopStart = true;
448 }
449 /// Start capturing of the variables in the loop context.
450 void loopStart() {
451 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
452 "Expected loop-based directive.");
453 getTopOfStack().LoopStart = false;
454 }
455 /// true, if variables are captured, false otherwise.
456 bool isLoopStarted() const {
457 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
458 "Expected loop-based directive.");
459 return !getTopOfStack().LoopStart;
460 }
461 /// Marks (or clears) declaration as possibly loop counter.
462 void resetPossibleLoopCounter(const Decl *D = nullptr) {
463 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
464 }
465 /// Gets the possible loop counter decl.
466 const Decl *getPossiblyLoopCunter() const {
467 return getTopOfStack().PossiblyLoopCounter;
468 }
469 /// Start new OpenMP region stack in new non-capturing function.
470 void pushFunction() {
471 assert(!IgnoredStackElements &&
472 "cannot change stack while ignoring elements");
473 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
474 assert(!isa<CapturingScopeInfo>(CurFnScope));
475 CurrentNonCapturingFunctionScope = CurFnScope;
476 }
477 /// Pop region stack for non-capturing function.
478 void popFunction(const FunctionScopeInfo *OldFSI) {
479 assert(!IgnoredStackElements &&
480 "cannot change stack while ignoring elements");
481 if (!Stack.empty() && Stack.back().second == OldFSI) {
482 assert(Stack.back().first.empty());
483 Stack.pop_back();
484 }
485 CurrentNonCapturingFunctionScope = nullptr;
486 for (const FunctionScopeInfo *FSI : llvm::reverse(C&: SemaRef.FunctionScopes)) {
487 if (!isa<CapturingScopeInfo>(Val: FSI)) {
488 CurrentNonCapturingFunctionScope = FSI;
489 break;
490 }
491 }
492 }
493
494 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
495 Criticals.try_emplace(Key: D->getDirectiveName().getAsString(), Args&: D, Args&: Hint);
496 }
497 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
498 getCriticalWithHint(const DeclarationNameInfo &Name) const {
499 auto I = Criticals.find(Key: Name.getAsString());
500 if (I != Criticals.end())
501 return I->second;
502 return std::make_pair(x: nullptr, y: llvm::APSInt());
503 }
504 /// If 'aligned' declaration for given variable \a D was not seen yet,
505 /// add it and return NULL; otherwise return previous occurrence's expression
506 /// for diagnostics.
507 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
508 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
509 /// add it and return NULL; otherwise return previous occurrence's expression
510 /// for diagnostics.
511 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
512
513 /// Register specified variable as loop control variable.
514 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
515 /// Check if the specified variable is a loop control variable for
516 /// current region.
517 /// \return The index of the loop control variable in the list of associated
518 /// for-loops (from outer to inner).
519 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
520 /// Check if the specified variable is a loop control variable for
521 /// parent region.
522 /// \return The index of the loop control variable in the list of associated
523 /// for-loops (from outer to inner).
524 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
525 /// Check if the specified variable is a loop control variable for
526 /// current region.
527 /// \return The index of the loop control variable in the list of associated
528 /// for-loops (from outer to inner).
529 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
530 unsigned Level) const;
531 /// Get the loop control variable for the I-th loop (or nullptr) in
532 /// parent directive.
533 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
534
535 /// Marks the specified decl \p D as used in scan directive.
536 void markDeclAsUsedInScanDirective(ValueDecl *D) {
537 if (SharingMapTy *Stack = getSecondOnStackOrNull())
538 Stack->UsedInScanDirective.insert(D);
539 }
540
541 /// Checks if the specified declaration was used in the inner scan directive.
542 bool isUsedInScanDirective(ValueDecl *D) const {
543 if (const SharingMapTy *Stack = getTopOfStackOrNull())
544 return Stack->UsedInScanDirective.contains(D);
545 return false;
546 }
547
548 /// Adds explicit data sharing attribute to the specified declaration.
549 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
550 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
551 bool AppliedToPointee = false);
552
553 /// Adds additional information for the reduction items with the reduction id
554 /// represented as an operator.
555 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
556 BinaryOperatorKind BOK);
557 /// Adds additional information for the reduction items with the reduction id
558 /// represented as reduction identifier.
559 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
560 const Expr *ReductionRef);
561 /// Returns the location and reduction operation from the innermost parent
562 /// region for the given \p D.
563 const DSAVarData
564 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
565 BinaryOperatorKind &BOK,
566 Expr *&TaskgroupDescriptor) const;
567 /// Returns the location and reduction operation from the innermost parent
568 /// region for the given \p D.
569 const DSAVarData
570 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
571 const Expr *&ReductionRef,
572 Expr *&TaskgroupDescriptor) const;
573 /// Return reduction reference expression for the current taskgroup or
574 /// parallel/worksharing directives with task reductions.
575 Expr *getTaskgroupReductionRef() const {
576 assert((getTopOfStack().Directive == OMPD_taskgroup ||
577 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
578 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
579 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
580 "taskgroup reference expression requested for non taskgroup or "
581 "parallel/worksharing directive.");
582 return getTopOfStack().TaskgroupReductionRef;
583 }
584 /// Checks if the given \p VD declaration is actually a taskgroup reduction
585 /// descriptor variable at the \p Level of OpenMP regions.
586 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
587 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
588 cast<DeclRefExpr>(Val: getStackElemAtLevel(Level).TaskgroupReductionRef)
589 ->getDecl() == VD;
590 }
591
592 /// Returns data sharing attributes from top of the stack for the
593 /// specified declaration.
594 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
595 /// Returns data-sharing attributes for the specified declaration.
596 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
597 /// Returns data-sharing attributes for the specified declaration.
598 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
599 /// Checks if the specified variables has data-sharing attributes which
600 /// match specified \a CPred predicate in any directive which matches \a DPred
601 /// predicate.
602 const DSAVarData
603 hasDSA(ValueDecl *D,
604 const llvm::function_ref<bool(OpenMPClauseKind, bool,
605 DefaultDataSharingAttributes)>
606 CPred,
607 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
608 bool FromParent) const;
609 /// Checks if the specified variables has data-sharing attributes which
610 /// match specified \a CPred predicate in any innermost directive which
611 /// matches \a DPred predicate.
612 const DSAVarData
613 hasInnermostDSA(ValueDecl *D,
614 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
615 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
616 bool FromParent) const;
617 /// Checks if the specified variables has explicit data-sharing
618 /// attributes which match specified \a CPred predicate at the specified
619 /// OpenMP region.
620 bool
621 hasExplicitDSA(const ValueDecl *D,
622 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
623 unsigned Level, bool NotLastprivate = false) const;
624
625 /// Returns true if the directive at level \Level matches in the
626 /// specified \a DPred predicate.
627 bool hasExplicitDirective(
628 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
629 unsigned Level) const;
630
631 /// Finds a directive which matches specified \a DPred predicate.
632 bool hasDirective(
633 const llvm::function_ref<bool(
634 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
635 DPred,
636 bool FromParent) const;
637
638 /// Returns currently analyzed directive.
639 OpenMPDirectiveKind getCurrentDirective() const {
640 const SharingMapTy *Top = getTopOfStackOrNull();
641 return Top ? Top->Directive : OMPD_unknown;
642 }
643 OpenMPDirectiveKind getMappedDirective() const {
644 const SharingMapTy *Top = getTopOfStackOrNull();
645 return Top ? Top->MappedDirective : OMPD_unknown;
646 }
647 void setCurrentDirective(OpenMPDirectiveKind NewDK) {
648 SharingMapTy *Top = getTopOfStackOrNull();
649 assert(Top &&
650 "Before calling setCurrentDirective Top of Stack not to be NULL.");
651 // Store the old into MappedDirective & assign argument NewDK to Directive.
652 Top->Directive = NewDK;
653 }
654 void setMappedDirective(OpenMPDirectiveKind NewDK) {
655 SharingMapTy *Top = getTopOfStackOrNull();
656 assert(Top &&
657 "Before calling setMappedDirective Top of Stack not to be NULL.");
658 // Store the old into MappedDirective & assign argument NewDK to Directive.
659 Top->MappedDirective = NewDK;
660 }
661 /// Returns directive kind at specified level.
662 OpenMPDirectiveKind getDirective(unsigned Level) const {
663 assert(!isStackEmpty() && "No directive at specified level.");
664 return getStackElemAtLevel(Level).Directive;
665 }
666 /// Returns the capture region at the specified level.
667 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
668 unsigned OpenMPCaptureLevel) const {
669 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
670 getOpenMPCaptureRegions(CaptureRegions, DKind: getDirective(Level));
671 return CaptureRegions[OpenMPCaptureLevel];
672 }
673 /// Returns parent directive.
674 OpenMPDirectiveKind getParentDirective() const {
675 const SharingMapTy *Parent = getSecondOnStackOrNull();
676 return Parent ? Parent->Directive : OMPD_unknown;
677 }
678
679 /// Add requires decl to internal vector
680 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(Elt: RD); }
681
682 /// Checks if the defined 'requires' directive has specified type of clause.
683 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
684 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
685 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
686 return isa<ClauseType>(C);
687 });
688 });
689 }
690
691 /// Checks for a duplicate clause amongst previously declared requires
692 /// directives
693 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
694 bool IsDuplicate = false;
695 for (OMPClause *CNew : ClauseList) {
696 for (const OMPRequiresDecl *D : RequiresDecls) {
697 for (const OMPClause *CPrev : D->clauselists()) {
698 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
699 SemaRef.Diag(CNew->getBeginLoc(),
700 diag::err_omp_requires_clause_redeclaration)
701 << getOpenMPClauseName(CNew->getClauseKind());
702 SemaRef.Diag(CPrev->getBeginLoc(),
703 diag::note_omp_requires_previous_clause)
704 << getOpenMPClauseName(CPrev->getClauseKind());
705 IsDuplicate = true;
706 }
707 }
708 }
709 }
710 return IsDuplicate;
711 }
712
713 /// Add location of previously encountered target to internal vector
714 void addTargetDirLocation(SourceLocation LocStart) {
715 TargetLocations.push_back(Elt: LocStart);
716 }
717
718 /// Add location for the first encountered atomicc directive.
719 void addAtomicDirectiveLoc(SourceLocation Loc) {
720 if (AtomicLocation.isInvalid())
721 AtomicLocation = Loc;
722 }
723
724 /// Returns the location of the first encountered atomic directive in the
725 /// module.
726 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
727
728 // Return previously encountered target region locations.
729 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
730 return TargetLocations;
731 }
732
733 /// Set default data sharing attribute to none.
734 void setDefaultDSANone(SourceLocation Loc) {
735 getTopOfStack().DefaultAttr = DSA_none;
736 getTopOfStack().DefaultAttrLoc = Loc;
737 }
738 /// Set default data sharing attribute to shared.
739 void setDefaultDSAShared(SourceLocation Loc) {
740 getTopOfStack().DefaultAttr = DSA_shared;
741 getTopOfStack().DefaultAttrLoc = Loc;
742 }
743 /// Set default data sharing attribute to private.
744 void setDefaultDSAPrivate(SourceLocation Loc) {
745 getTopOfStack().DefaultAttr = DSA_private;
746 getTopOfStack().DefaultAttrLoc = Loc;
747 }
748 /// Set default data sharing attribute to firstprivate.
749 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
750 getTopOfStack().DefaultAttr = DSA_firstprivate;
751 getTopOfStack().DefaultAttrLoc = Loc;
752 }
753 /// Set default data mapping attribute to Modifier:Kind
754 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
755 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
756 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
757 DMI.ImplicitBehavior = M;
758 DMI.SLoc = Loc;
759 }
760 /// Check whether the implicit-behavior has been set in defaultmap
761 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
762 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
763 return getTopOfStack()
764 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
765 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
766 getTopOfStack()
767 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
768 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
769 getTopOfStack()
770 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
771 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
772 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
773 OMPC_DEFAULTMAP_MODIFIER_unknown;
774 }
775
776 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
777 return ConstructTraits;
778 }
779 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
780 bool ScopeEntry) {
781 if (ScopeEntry)
782 ConstructTraits.append(in_start: Traits.begin(), in_end: Traits.end());
783 else
784 for (llvm::omp::TraitProperty Trait : llvm::reverse(C&: Traits)) {
785 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
786 assert(Top == Trait && "Something left a trait on the stack!");
787 (void)Trait;
788 (void)Top;
789 }
790 }
791
792 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
793 return getStackSize() <= Level ? DSA_unspecified
794 : getStackElemAtLevel(Level).DefaultAttr;
795 }
796 DefaultDataSharingAttributes getDefaultDSA() const {
797 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
798 }
799 SourceLocation getDefaultDSALocation() const {
800 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
801 }
802 OpenMPDefaultmapClauseModifier
803 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
804 return isStackEmpty()
805 ? OMPC_DEFAULTMAP_MODIFIER_unknown
806 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
807 }
808 OpenMPDefaultmapClauseModifier
809 getDefaultmapModifierAtLevel(unsigned Level,
810 OpenMPDefaultmapClauseKind Kind) const {
811 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
812 }
813 bool isDefaultmapCapturedByRef(unsigned Level,
814 OpenMPDefaultmapClauseKind Kind) const {
815 OpenMPDefaultmapClauseModifier M =
816 getDefaultmapModifierAtLevel(Level, Kind);
817 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
818 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
819 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
820 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
821 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom);
822 }
823 return true;
824 }
825 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
826 OpenMPDefaultmapClauseKind Kind) {
827 switch (Kind) {
828 case OMPC_DEFAULTMAP_scalar:
829 case OMPC_DEFAULTMAP_pointer:
830 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
831 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
832 (M == OMPC_DEFAULTMAP_MODIFIER_default);
833 case OMPC_DEFAULTMAP_aggregate:
834 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
835 default:
836 break;
837 }
838 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
839 }
840 bool mustBeFirstprivateAtLevel(unsigned Level,
841 OpenMPDefaultmapClauseKind Kind) const {
842 OpenMPDefaultmapClauseModifier M =
843 getDefaultmapModifierAtLevel(Level, Kind);
844 return mustBeFirstprivateBase(M, Kind);
845 }
846 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
847 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
848 return mustBeFirstprivateBase(M, Kind);
849 }
850
851 /// Checks if the specified variable is a threadprivate.
852 bool isThreadPrivate(VarDecl *D) {
853 const DSAVarData DVar = getTopDSA(D, false);
854 return isOpenMPThreadPrivate(DVar.CKind);
855 }
856
857 /// Marks current region as ordered (it has an 'ordered' clause).
858 void setOrderedRegion(bool IsOrdered, const Expr *Param,
859 OMPOrderedClause *Clause) {
860 if (IsOrdered)
861 getTopOfStack().OrderedRegion.emplace(args&: Param, args&: Clause);
862 else
863 getTopOfStack().OrderedRegion.reset();
864 }
865 /// Returns true, if region is ordered (has associated 'ordered' clause),
866 /// false - otherwise.
867 bool isOrderedRegion() const {
868 if (const SharingMapTy *Top = getTopOfStackOrNull())
869 return Top->OrderedRegion.has_value();
870 return false;
871 }
872 /// Returns optional parameter for the ordered region.
873 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
874 if (const SharingMapTy *Top = getTopOfStackOrNull())
875 if (Top->OrderedRegion)
876 return *Top->OrderedRegion;
877 return std::make_pair(x: nullptr, y: nullptr);
878 }
879 /// Returns true, if parent region is ordered (has associated
880 /// 'ordered' clause), false - otherwise.
881 bool isParentOrderedRegion() const {
882 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
883 return Parent->OrderedRegion.has_value();
884 return false;
885 }
886 /// Returns optional parameter for the ordered region.
887 std::pair<const Expr *, OMPOrderedClause *>
888 getParentOrderedRegionParam() const {
889 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
890 if (Parent->OrderedRegion)
891 return *Parent->OrderedRegion;
892 return std::make_pair(x: nullptr, y: nullptr);
893 }
894 /// Marks current region as having an 'order' clause.
895 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
896 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
897 }
898 /// Returns true, if parent region is order (has associated
899 /// 'order' clause), false - otherwise.
900 bool isParentOrderConcurrent() const {
901 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
902 return Parent->RegionHasOrderConcurrent;
903 return false;
904 }
905 /// Marks current region as nowait (it has a 'nowait' clause).
906 void setNowaitRegion(bool IsNowait = true) {
907 getTopOfStack().NowaitRegion = IsNowait;
908 }
909 /// Returns true, if parent region is nowait (has associated
910 /// 'nowait' clause), false - otherwise.
911 bool isParentNowaitRegion() const {
912 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
913 return Parent->NowaitRegion;
914 return false;
915 }
916 /// Marks current region as untied (it has a 'untied' clause).
917 void setUntiedRegion(bool IsUntied = true) {
918 getTopOfStack().UntiedRegion = IsUntied;
919 }
920 /// Return true if current region is untied.
921 bool isUntiedRegion() const {
922 const SharingMapTy *Top = getTopOfStackOrNull();
923 return Top ? Top->UntiedRegion : false;
924 }
925 /// Marks parent region as cancel region.
926 void setParentCancelRegion(bool Cancel = true) {
927 if (SharingMapTy *Parent = getSecondOnStackOrNull())
928 Parent->CancelRegion |= Cancel;
929 }
930 /// Return true if current region has inner cancel construct.
931 bool isCancelRegion() const {
932 const SharingMapTy *Top = getTopOfStackOrNull();
933 return Top ? Top->CancelRegion : false;
934 }
935
936 /// Mark that parent region already has scan directive.
937 void setParentHasScanDirective(SourceLocation Loc) {
938 if (SharingMapTy *Parent = getSecondOnStackOrNull())
939 Parent->PrevScanLocation = Loc;
940 }
941 /// Return true if current region has inner cancel construct.
942 bool doesParentHasScanDirective() const {
943 const SharingMapTy *Top = getSecondOnStackOrNull();
944 return Top ? Top->PrevScanLocation.isValid() : false;
945 }
946 /// Return true if current region has inner cancel construct.
947 SourceLocation getParentScanDirectiveLoc() const {
948 const SharingMapTy *Top = getSecondOnStackOrNull();
949 return Top ? Top->PrevScanLocation : SourceLocation();
950 }
951 /// Mark that parent region already has ordered directive.
952 void setParentHasOrderedDirective(SourceLocation Loc) {
953 if (SharingMapTy *Parent = getSecondOnStackOrNull())
954 Parent->PrevOrderedLocation = Loc;
955 }
956 /// Return true if current region has inner ordered construct.
957 bool doesParentHasOrderedDirective() const {
958 const SharingMapTy *Top = getSecondOnStackOrNull();
959 return Top ? Top->PrevOrderedLocation.isValid() : false;
960 }
961 /// Returns the location of the previously specified ordered directive.
962 SourceLocation getParentOrderedDirectiveLoc() const {
963 const SharingMapTy *Top = getSecondOnStackOrNull();
964 return Top ? Top->PrevOrderedLocation : SourceLocation();
965 }
966
967 /// Set collapse value for the region.
968 void setAssociatedLoops(unsigned Val) {
969 getTopOfStack().AssociatedLoops = Val;
970 if (Val > 1)
971 getTopOfStack().HasMutipleLoops = true;
972 }
973 /// Return collapse value for region.
974 unsigned getAssociatedLoops() const {
975 const SharingMapTy *Top = getTopOfStackOrNull();
976 return Top ? Top->AssociatedLoops : 0;
977 }
978 /// Returns true if the construct is associated with multiple loops.
979 bool hasMutipleLoops() const {
980 const SharingMapTy *Top = getTopOfStackOrNull();
981 return Top ? Top->HasMutipleLoops : false;
982 }
983
984 /// Marks current target region as one with closely nested teams
985 /// region.
986 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
987 if (SharingMapTy *Parent = getSecondOnStackOrNull())
988 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
989 }
990 /// Returns true, if current region has closely nested teams region.
991 bool hasInnerTeamsRegion() const {
992 return getInnerTeamsRegionLoc().isValid();
993 }
994 /// Returns location of the nested teams region (if any).
995 SourceLocation getInnerTeamsRegionLoc() const {
996 const SharingMapTy *Top = getTopOfStackOrNull();
997 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
998 }
999
1000 Scope *getCurScope() const {
1001 const SharingMapTy *Top = getTopOfStackOrNull();
1002 return Top ? Top->CurScope : nullptr;
1003 }
1004 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1005 SourceLocation getConstructLoc() const {
1006 const SharingMapTy *Top = getTopOfStackOrNull();
1007 return Top ? Top->ConstructLoc : SourceLocation();
1008 }
1009
1010 /// Do the check specified in \a Check to all component lists and return true
1011 /// if any issue is found.
1012 bool checkMappableExprComponentListsForDecl(
1013 const ValueDecl *VD, bool CurrentRegionOnly,
1014 const llvm::function_ref<
1015 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1016 OpenMPClauseKind)>
1017 Check) const {
1018 if (isStackEmpty())
1019 return false;
1020 auto SI = begin();
1021 auto SE = end();
1022
1023 if (SI == SE)
1024 return false;
1025
1026 if (CurrentRegionOnly)
1027 SE = std::next(x: SI);
1028 else
1029 std::advance(i&: SI, n: 1);
1030
1031 for (; SI != SE; ++SI) {
1032 auto MI = SI->MappedExprComponents.find(Val: VD);
1033 if (MI != SI->MappedExprComponents.end())
1034 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1035 MI->second.Components)
1036 if (Check(L, MI->second.Kind))
1037 return true;
1038 }
1039 return false;
1040 }
1041
1042 /// Do the check specified in \a Check to all component lists at a given level
1043 /// and return true if any issue is found.
1044 bool checkMappableExprComponentListsForDeclAtLevel(
1045 const ValueDecl *VD, unsigned Level,
1046 const llvm::function_ref<
1047 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1048 OpenMPClauseKind)>
1049 Check) const {
1050 if (getStackSize() <= Level)
1051 return false;
1052
1053 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1054 auto MI = StackElem.MappedExprComponents.find(Val: VD);
1055 if (MI != StackElem.MappedExprComponents.end())
1056 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1057 MI->second.Components)
1058 if (Check(L, MI->second.Kind))
1059 return true;
1060 return false;
1061 }
1062
1063 /// Create a new mappable expression component list associated with a given
1064 /// declaration and initialize it with the provided list of components.
1065 void addMappableExpressionComponents(
1066 const ValueDecl *VD,
1067 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
1068 OpenMPClauseKind WhereFoundClauseKind) {
1069 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1070 // Create new entry and append the new components there.
1071 MEC.Components.resize(N: MEC.Components.size() + 1);
1072 MEC.Components.back().append(in_start: Components.begin(), in_end: Components.end());
1073 MEC.Kind = WhereFoundClauseKind;
1074 }
1075
1076 unsigned getNestingLevel() const {
1077 assert(!isStackEmpty());
1078 return getStackSize() - 1;
1079 }
1080 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1081 SharingMapTy *Parent = getSecondOnStackOrNull();
1082 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1083 Parent->DoacrossDepends.try_emplace(Key: C, Args: OpsOffs);
1084 }
1085 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1086 getDoacrossDependClauses() const {
1087 const SharingMapTy &StackElem = getTopOfStack();
1088 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1089 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1090 return llvm::make_range(x: Ref.begin(), y: Ref.end());
1091 }
1092 return llvm::make_range(x: StackElem.DoacrossDepends.end(),
1093 y: StackElem.DoacrossDepends.end());
1094 }
1095
1096 // Store types of classes which have been explicitly mapped
1097 void addMappedClassesQualTypes(QualType QT) {
1098 SharingMapTy &StackElem = getTopOfStack();
1099 StackElem.MappedClassesQualTypes.insert(V: QT);
1100 }
1101
1102 // Return set of mapped classes types
1103 bool isClassPreviouslyMapped(QualType QT) const {
1104 const SharingMapTy &StackElem = getTopOfStack();
1105 return StackElem.MappedClassesQualTypes.contains(V: QT);
1106 }
1107
1108 /// Adds global declare target to the parent target region.
1109 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1110 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1111 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1112 "Expected declare target link global.");
1113 for (auto &Elem : *this) {
1114 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1115 Elem.DeclareTargetLinkVarDecls.push_back(Elt: E);
1116 return;
1117 }
1118 }
1119 }
1120
1121 /// Returns the list of globals with declare target link if current directive
1122 /// is target.
1123 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1124 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1125 "Expected target executable directive.");
1126 return getTopOfStack().DeclareTargetLinkVarDecls;
1127 }
1128
1129 /// Adds list of allocators expressions.
1130 void addInnerAllocatorExpr(Expr *E) {
1131 getTopOfStack().InnerUsedAllocators.push_back(Elt: E);
1132 }
1133 /// Return list of used allocators.
1134 ArrayRef<Expr *> getInnerAllocators() const {
1135 return getTopOfStack().InnerUsedAllocators;
1136 }
1137 /// Marks the declaration as implicitly firstprivate nin the task-based
1138 /// regions.
1139 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1140 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(V: D);
1141 }
1142 /// Checks if the decl is implicitly firstprivate in the task-based region.
1143 bool isImplicitTaskFirstprivate(Decl *D) const {
1144 return getTopOfStack().ImplicitTaskFirstprivates.contains(V: D);
1145 }
1146
1147 /// Marks decl as used in uses_allocators clause as the allocator.
1148 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1149 getTopOfStack().UsesAllocatorsDecls.try_emplace(Key: D, Args&: Kind);
1150 }
1151 /// Checks if specified decl is used in uses allocator clause as the
1152 /// allocator.
1153 std::optional<UsesAllocatorsDeclKind>
1154 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1155 const SharingMapTy &StackElem = getTopOfStack();
1156 auto I = StackElem.UsesAllocatorsDecls.find(Val: D);
1157 if (I == StackElem.UsesAllocatorsDecls.end())
1158 return std::nullopt;
1159 return I->getSecond();
1160 }
1161 std::optional<UsesAllocatorsDeclKind>
1162 isUsesAllocatorsDecl(const Decl *D) const {
1163 const SharingMapTy &StackElem = getTopOfStack();
1164 auto I = StackElem.UsesAllocatorsDecls.find(Val: D);
1165 if (I == StackElem.UsesAllocatorsDecls.end())
1166 return std::nullopt;
1167 return I->getSecond();
1168 }
1169
1170 void addDeclareMapperVarRef(Expr *Ref) {
1171 SharingMapTy &StackElem = getTopOfStack();
1172 StackElem.DeclareMapperVar = Ref;
1173 }
1174 const Expr *getDeclareMapperVarRef() const {
1175 const SharingMapTy *Top = getTopOfStackOrNull();
1176 return Top ? Top->DeclareMapperVar : nullptr;
1177 }
1178
1179 /// Add a new iterator variable.
1180 void addIteratorVarDecl(VarDecl *VD) {
1181 SharingMapTy &StackElem = getTopOfStack();
1182 StackElem.IteratorVarDecls.push_back(Elt: VD->getCanonicalDecl());
1183 }
1184 /// Check if variable declaration is an iterator VarDecl.
1185 bool isIteratorVarDecl(const VarDecl *VD) const {
1186 const SharingMapTy *Top = getTopOfStackOrNull();
1187 if (!Top)
1188 return false;
1189
1190 return llvm::is_contained(Range: Top->IteratorVarDecls, Element: VD->getCanonicalDecl());
1191 }
1192 /// get captured field from ImplicitDefaultFirstprivateFDs
1193 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1194 const_iterator I = begin();
1195 const_iterator EndI = end();
1196 size_t StackLevel = getStackSize();
1197 for (; I != EndI; ++I) {
1198 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1199 break;
1200 StackLevel--;
1201 }
1202 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1203 if (I == EndI)
1204 return nullptr;
1205 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1206 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1207 return IFD.VD;
1208 return nullptr;
1209 }
1210 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1211 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1212 const_iterator I = begin();
1213 const_iterator EndI = end();
1214 for (; I != EndI; ++I)
1215 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1216 break;
1217 if (I == EndI)
1218 return false;
1219 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1220 if (IFD.VD == VD)
1221 return true;
1222 return false;
1223 }
1224 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1225 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1226 iterator I = begin();
1227 const_iterator EndI = end();
1228 size_t StackLevel = getStackSize();
1229 for (; I != EndI; ++I) {
1230 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1231 I->ImplicitDefaultFirstprivateFDs.emplace_back(Args&: FD, Args&: StackLevel, Args&: VD);
1232 break;
1233 }
1234 StackLevel--;
1235 }
1236 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1237 }
1238};
1239
1240bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1241 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1242}
1243
1244bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1245 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1246 DKind == OMPD_unknown;
1247}
1248
1249} // namespace
1250
1251static const Expr *getExprAsWritten(const Expr *E) {
1252 if (const auto *FE = dyn_cast<FullExpr>(Val: E))
1253 E = FE->getSubExpr();
1254
1255 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Val: E))
1256 E = MTE->getSubExpr();
1257
1258 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(Val: E))
1259 E = Binder->getSubExpr();
1260
1261 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(Val: E))
1262 E = ICE->getSubExprAsWritten();
1263 return E->IgnoreParens();
1264}
1265
1266static Expr *getExprAsWritten(Expr *E) {
1267 return const_cast<Expr *>(getExprAsWritten(E: const_cast<const Expr *>(E)));
1268}
1269
1270static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1271 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: D))
1272 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1273 D = ME->getMemberDecl();
1274 const auto *VD = dyn_cast<VarDecl>(Val: D);
1275 const auto *FD = dyn_cast<FieldDecl>(Val: D);
1276 if (VD != nullptr) {
1277 VD = VD->getCanonicalDecl();
1278 D = VD;
1279 } else {
1280 assert(FD);
1281 FD = FD->getCanonicalDecl();
1282 D = FD;
1283 }
1284 return D;
1285}
1286
1287static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1288 return const_cast<ValueDecl *>(
1289 getCanonicalDecl(D: const_cast<const ValueDecl *>(D)));
1290}
1291
1292DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1293 ValueDecl *D) const {
1294 D = getCanonicalDecl(D);
1295 auto *VD = dyn_cast<VarDecl>(Val: D);
1296 const auto *FD = dyn_cast<FieldDecl>(Val: D);
1297 DSAVarData DVar;
1298 if (Iter == end()) {
1299 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1300 // in a region but not in construct]
1301 // File-scope or namespace-scope variables referenced in called routines
1302 // in the region are shared unless they appear in a threadprivate
1303 // directive.
1304 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1305 DVar.CKind = OMPC_shared;
1306
1307 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1308 // in a region but not in construct]
1309 // Variables with static storage duration that are declared in called
1310 // routines in the region are shared.
1311 if (VD && VD->hasGlobalStorage())
1312 DVar.CKind = OMPC_shared;
1313
1314 // Non-static data members are shared by default.
1315 if (FD)
1316 DVar.CKind = OMPC_shared;
1317
1318 return DVar;
1319 }
1320
1321 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1322 // in a Construct, C/C++, predetermined, p.1]
1323 // Variables with automatic storage duration that are declared in a scope
1324 // inside the construct are private.
1325 if (VD && isOpenMPLocal(D: VD, Iter) && VD->isLocalVarDecl() &&
1326 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1327 DVar.CKind = OMPC_private;
1328 return DVar;
1329 }
1330
1331 DVar.DKind = Iter->Directive;
1332 // Explicitly specified attributes and local variables with predetermined
1333 // attributes.
1334 if (Iter->SharingMap.count(D)) {
1335 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1336 DVar.RefExpr = Data.RefExpr.getPointer();
1337 DVar.PrivateCopy = Data.PrivateCopy;
1338 DVar.CKind = Data.Attributes;
1339 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1340 DVar.Modifier = Data.Modifier;
1341 DVar.AppliedToPointee = Data.AppliedToPointee;
1342 return DVar;
1343 }
1344
1345 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1346 // in a Construct, C/C++, implicitly determined, p.1]
1347 // In a parallel or task construct, the data-sharing attributes of these
1348 // variables are determined by the default clause, if present.
1349 switch (Iter->DefaultAttr) {
1350 case DSA_shared:
1351 DVar.CKind = OMPC_shared;
1352 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1353 return DVar;
1354 case DSA_none:
1355 return DVar;
1356 case DSA_firstprivate:
1357 if (VD && VD->getStorageDuration() == SD_Static &&
1358 VD->getDeclContext()->isFileContext()) {
1359 DVar.CKind = OMPC_unknown;
1360 } else {
1361 DVar.CKind = OMPC_firstprivate;
1362 }
1363 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1364 return DVar;
1365 case DSA_private:
1366 // each variable with static storage duration that is declared
1367 // in a namespace or global scope and referenced in the construct,
1368 // and that does not have a predetermined data-sharing attribute
1369 if (VD && VD->getStorageDuration() == SD_Static &&
1370 VD->getDeclContext()->isFileContext()) {
1371 DVar.CKind = OMPC_unknown;
1372 } else {
1373 DVar.CKind = OMPC_private;
1374 }
1375 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1376 return DVar;
1377 case DSA_unspecified:
1378 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1379 // in a Construct, implicitly determined, p.2]
1380 // In a parallel construct, if no default clause is present, these
1381 // variables are shared.
1382 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1383 if ((isOpenMPParallelDirective(DVar.DKind) &&
1384 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1385 isOpenMPTeamsDirective(DVar.DKind)) {
1386 DVar.CKind = OMPC_shared;
1387 return DVar;
1388 }
1389
1390 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1391 // in a Construct, implicitly determined, p.4]
1392 // In a task construct, if no default clause is present, a variable that in
1393 // the enclosing context is determined to be shared by all implicit tasks
1394 // bound to the current team is shared.
1395 if (isOpenMPTaskingDirective(DVar.DKind)) {
1396 DSAVarData DVarTemp;
1397 const_iterator I = Iter, E = end();
1398 do {
1399 ++I;
1400 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1401 // Referenced in a Construct, implicitly determined, p.6]
1402 // In a task construct, if no default clause is present, a variable
1403 // whose data-sharing attribute is not determined by the rules above is
1404 // firstprivate.
1405 DVarTemp = getDSA(Iter&: I, D);
1406 if (DVarTemp.CKind != OMPC_shared) {
1407 DVar.RefExpr = nullptr;
1408 DVar.CKind = OMPC_firstprivate;
1409 return DVar;
1410 }
1411 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1412 DVar.CKind =
1413 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1414 return DVar;
1415 }
1416 }
1417 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1418 // in a Construct, implicitly determined, p.3]
1419 // For constructs other than task, if no default clause is present, these
1420 // variables inherit their data-sharing attributes from the enclosing
1421 // context.
1422 return getDSA(Iter&: ++Iter, D);
1423}
1424
1425const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1426 const Expr *NewDE) {
1427 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1428 D = getCanonicalDecl(D);
1429 SharingMapTy &StackElem = getTopOfStack();
1430 auto It = StackElem.AlignedMap.find(Val: D);
1431 if (It == StackElem.AlignedMap.end()) {
1432 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1433 StackElem.AlignedMap[D] = NewDE;
1434 return nullptr;
1435 }
1436 assert(It->second && "Unexpected nullptr expr in the aligned map");
1437 return It->second;
1438}
1439
1440const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1441 const Expr *NewDE) {
1442 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1443 D = getCanonicalDecl(D);
1444 SharingMapTy &StackElem = getTopOfStack();
1445 auto It = StackElem.NontemporalMap.find(Val: D);
1446 if (It == StackElem.NontemporalMap.end()) {
1447 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1448 StackElem.NontemporalMap[D] = NewDE;
1449 return nullptr;
1450 }
1451 assert(It->second && "Unexpected nullptr expr in the aligned map");
1452 return It->second;
1453}
1454
1455void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1456 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1457 D = getCanonicalDecl(D);
1458 SharingMapTy &StackElem = getTopOfStack();
1459 StackElem.LCVMap.try_emplace(
1460 Key: D, Args: LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1461}
1462
1463const DSAStackTy::LCDeclInfo
1464DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1465 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1466 D = getCanonicalDecl(D);
1467 const SharingMapTy &StackElem = getTopOfStack();
1468 auto It = StackElem.LCVMap.find(Val: D);
1469 if (It != StackElem.LCVMap.end())
1470 return It->second;
1471 return {0, nullptr};
1472}
1473
1474const DSAStackTy::LCDeclInfo
1475DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1476 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1477 D = getCanonicalDecl(D);
1478 for (unsigned I = Level + 1; I > 0; --I) {
1479 const SharingMapTy &StackElem = getStackElemAtLevel(Level: I - 1);
1480 auto It = StackElem.LCVMap.find(Val: D);
1481 if (It != StackElem.LCVMap.end())
1482 return It->second;
1483 }
1484 return {0, nullptr};
1485}
1486
1487const DSAStackTy::LCDeclInfo
1488DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1489 const SharingMapTy *Parent = getSecondOnStackOrNull();
1490 assert(Parent && "Data-sharing attributes stack is empty");
1491 D = getCanonicalDecl(D);
1492 auto It = Parent->LCVMap.find(Val: D);
1493 if (It != Parent->LCVMap.end())
1494 return It->second;
1495 return {0, nullptr};
1496}
1497
1498const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1499 const SharingMapTy *Parent = getSecondOnStackOrNull();
1500 assert(Parent && "Data-sharing attributes stack is empty");
1501 if (Parent->LCVMap.size() < I)
1502 return nullptr;
1503 for (const auto &Pair : Parent->LCVMap)
1504 if (Pair.second.first == I)
1505 return Pair.first;
1506 return nullptr;
1507}
1508
1509void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1510 DeclRefExpr *PrivateCopy, unsigned Modifier,
1511 bool AppliedToPointee) {
1512 D = getCanonicalDecl(D);
1513 if (A == OMPC_threadprivate) {
1514 DSAInfo &Data = Threadprivates[D];
1515 Data.Attributes = A;
1516 Data.RefExpr.setPointer(E);
1517 Data.PrivateCopy = nullptr;
1518 Data.Modifier = Modifier;
1519 } else {
1520 DSAInfo &Data = getTopOfStack().SharingMap[D];
1521 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1522 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1523 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1524 (isLoopControlVariable(D).first && A == OMPC_private));
1525 Data.Modifier = Modifier;
1526 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1527 Data.RefExpr.setInt(/*IntVal=*/true);
1528 return;
1529 }
1530 const bool IsLastprivate =
1531 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1532 Data.Attributes = A;
1533 Data.RefExpr.setPointerAndInt(PtrVal: E, IntVal: IsLastprivate);
1534 Data.PrivateCopy = PrivateCopy;
1535 Data.AppliedToPointee = AppliedToPointee;
1536 if (PrivateCopy) {
1537 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1538 Data.Modifier = Modifier;
1539 Data.Attributes = A;
1540 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1541 Data.PrivateCopy = nullptr;
1542 Data.AppliedToPointee = AppliedToPointee;
1543 }
1544 }
1545}
1546
1547/// Build a variable declaration for OpenMP loop iteration variable.
1548static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
1549 StringRef Name, const AttrVec *Attrs = nullptr,
1550 DeclRefExpr *OrigRef = nullptr) {
1551 DeclContext *DC = SemaRef.CurContext;
1552 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1553 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(T: Type, Loc);
1554 auto *Decl =
1555 VarDecl::Create(C&: SemaRef.Context, DC, StartLoc: Loc, IdLoc: Loc, Id: II, T: Type, TInfo, S: SC_None);
1556 if (Attrs) {
1557 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1558 I != E; ++I)
1559 Decl->addAttr(*I);
1560 }
1561 Decl->setImplicit();
1562 if (OrigRef) {
1563 Decl->addAttr(
1564 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1565 }
1566 return Decl;
1567}
1568
1569static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
1570 SourceLocation Loc,
1571 bool RefersToCapture = false) {
1572 D->setReferenced();
1573 D->markUsed(S.Context);
1574 return DeclRefExpr::Create(S.getASTContext(), NestedNameSpecifierLoc(),
1575 SourceLocation(), D, RefersToCapture, Loc, Ty,
1576 VK_LValue);
1577}
1578
1579void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1580 BinaryOperatorKind BOK) {
1581 D = getCanonicalDecl(D);
1582 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1583 assert(
1584 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1585 "Additional reduction info may be specified only for reduction items.");
1586 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1587 assert(ReductionData.ReductionRange.isInvalid() &&
1588 (getTopOfStack().Directive == OMPD_taskgroup ||
1589 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1590 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1591 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1592 "Additional reduction info may be specified only once for reduction "
1593 "items.");
1594 ReductionData.set(BO: BOK, RR: SR);
1595 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1596 if (!TaskgroupReductionRef) {
1597 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1598 SemaRef.Context.VoidPtrTy, ".task_red.");
1599 TaskgroupReductionRef =
1600 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1601 }
1602}
1603
1604void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1605 const Expr *ReductionRef) {
1606 D = getCanonicalDecl(D);
1607 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1608 assert(
1609 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1610 "Additional reduction info may be specified only for reduction items.");
1611 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1612 assert(ReductionData.ReductionRange.isInvalid() &&
1613 (getTopOfStack().Directive == OMPD_taskgroup ||
1614 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1615 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1616 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1617 "Additional reduction info may be specified only once for reduction "
1618 "items.");
1619 ReductionData.set(RefExpr: ReductionRef, RR: SR);
1620 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1621 if (!TaskgroupReductionRef) {
1622 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1623 SemaRef.Context.VoidPtrTy, ".task_red.");
1624 TaskgroupReductionRef =
1625 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1626 }
1627}
1628
1629const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1630 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1631 Expr *&TaskgroupDescriptor) const {
1632 D = getCanonicalDecl(D);
1633 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1634 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1635 const DSAInfo &Data = I->SharingMap.lookup(D);
1636 if (Data.Attributes != OMPC_reduction ||
1637 Data.Modifier != OMPC_REDUCTION_task)
1638 continue;
1639 const ReductionData &ReductionData = I->ReductionMap.lookup(Val: D);
1640 if (!ReductionData.ReductionOp ||
1641 ReductionData.ReductionOp.is<const Expr *>())
1642 return DSAVarData();
1643 SR = ReductionData.ReductionRange;
1644 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1645 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1646 "expression for the descriptor is not "
1647 "set.");
1648 TaskgroupDescriptor = I->TaskgroupReductionRef;
1649 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1650 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1651 /*AppliedToPointee=*/false);
1652 }
1653 return DSAVarData();
1654}
1655
1656const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1657 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1658 Expr *&TaskgroupDescriptor) const {
1659 D = getCanonicalDecl(D);
1660 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1661 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1662 const DSAInfo &Data = I->SharingMap.lookup(D);
1663 if (Data.Attributes != OMPC_reduction ||
1664 Data.Modifier != OMPC_REDUCTION_task)
1665 continue;
1666 const ReductionData &ReductionData = I->ReductionMap.lookup(Val: D);
1667 if (!ReductionData.ReductionOp ||
1668 !ReductionData.ReductionOp.is<const Expr *>())
1669 return DSAVarData();
1670 SR = ReductionData.ReductionRange;
1671 ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
1672 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1673 "expression for the descriptor is not "
1674 "set.");
1675 TaskgroupDescriptor = I->TaskgroupReductionRef;
1676 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1677 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1678 /*AppliedToPointee=*/false);
1679 }
1680 return DSAVarData();
1681}
1682
1683bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1684 D = D->getCanonicalDecl();
1685 for (const_iterator E = end(); I != E; ++I) {
1686 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1687 isOpenMPTargetExecutionDirective(I->Directive)) {
1688 if (I->CurScope) {
1689 Scope *TopScope = I->CurScope->getParent();
1690 Scope *CurScope = getCurScope();
1691 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1692 CurScope = CurScope->getParent();
1693 return CurScope != TopScope;
1694 }
1695 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1696 if (I->Context == DC)
1697 return true;
1698 return false;
1699 }
1700 }
1701 return false;
1702}
1703
1704static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
1705 bool AcceptIfMutable = true,
1706 bool *IsClassType = nullptr) {
1707 ASTContext &Context = SemaRef.getASTContext();
1708 Type = Type.getNonReferenceType().getCanonicalType();
1709 bool IsConstant = Type.isConstant(Ctx: Context);
1710 Type = Context.getBaseElementType(QT: Type);
1711 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1712 ? Type->getAsCXXRecordDecl()
1713 : nullptr;
1714 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(Val: RD))
1715 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1716 RD = CTD->getTemplatedDecl();
1717 if (IsClassType)
1718 *IsClassType = RD;
1719 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1720 RD->hasDefinition() && RD->hasMutableFields());
1721}
1722
1723static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1724 QualType Type, OpenMPClauseKind CKind,
1725 SourceLocation ELoc,
1726 bool AcceptIfMutable = true,
1727 bool ListItemNotVar = false) {
1728 ASTContext &Context = SemaRef.getASTContext();
1729 bool IsClassType;
1730 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, IsClassType: &IsClassType)) {
1731 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1732 : IsClassType ? diag::err_omp_const_not_mutable_variable
1733 : diag::err_omp_const_variable;
1734 SemaRef.Diag(Loc: ELoc, DiagID: Diag) << getOpenMPClauseName(CKind);
1735 if (!ListItemNotVar && D) {
1736 const VarDecl *VD = dyn_cast<VarDecl>(Val: D);
1737 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1738 VarDecl::DeclarationOnly;
1739 SemaRef.Diag(D->getLocation(),
1740 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1741 << D;
1742 }
1743 return true;
1744 }
1745 return false;
1746}
1747
1748const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1749 bool FromParent) {
1750 D = getCanonicalDecl(D);
1751 DSAVarData DVar;
1752
1753 auto *VD = dyn_cast<VarDecl>(Val: D);
1754 auto TI = Threadprivates.find(D);
1755 if (TI != Threadprivates.end()) {
1756 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1757 DVar.CKind = OMPC_threadprivate;
1758 DVar.Modifier = TI->getSecond().Modifier;
1759 return DVar;
1760 }
1761 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1762 DVar.RefExpr = buildDeclRefExpr(
1763 SemaRef, VD, D->getType().getNonReferenceType(),
1764 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1765 DVar.CKind = OMPC_threadprivate;
1766 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1767 return DVar;
1768 }
1769 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1770 // in a Construct, C/C++, predetermined, p.1]
1771 // Variables appearing in threadprivate directives are threadprivate.
1772 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1773 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1774 SemaRef.getLangOpts().OpenMPUseTLS &&
1775 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1776 (VD && VD->getStorageClass() == SC_Register &&
1777 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1778 DVar.RefExpr = buildDeclRefExpr(
1779 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1780 DVar.CKind = OMPC_threadprivate;
1781 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1782 return DVar;
1783 }
1784 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1785 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1786 !isLoopControlVariable(D).first) {
1787 const_iterator IterTarget =
1788 std::find_if(first: begin(), last: end(), pred: [](const SharingMapTy &Data) {
1789 return isOpenMPTargetExecutionDirective(Data.Directive);
1790 });
1791 if (IterTarget != end()) {
1792 const_iterator ParentIterTarget = IterTarget + 1;
1793 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1794 if (isOpenMPLocal(D: VD, I: Iter)) {
1795 DVar.RefExpr =
1796 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1797 D->getLocation());
1798 DVar.CKind = OMPC_threadprivate;
1799 return DVar;
1800 }
1801 }
1802 if (!isClauseParsingMode() || IterTarget != begin()) {
1803 auto DSAIter = IterTarget->SharingMap.find(D);
1804 if (DSAIter != IterTarget->SharingMap.end() &&
1805 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1806 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1807 DVar.CKind = OMPC_threadprivate;
1808 return DVar;
1809 }
1810 const_iterator End = end();
1811 if (!SemaRef.isOpenMPCapturedByRef(D,
1812 Level: std::distance(first: ParentIterTarget, last: End),
1813 /*OpenMPCaptureLevel=*/0)) {
1814 DVar.RefExpr =
1815 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1816 Loc: IterTarget->ConstructLoc);
1817 DVar.CKind = OMPC_threadprivate;
1818 return DVar;
1819 }
1820 }
1821 }
1822 }
1823
1824 if (isStackEmpty())
1825 // Not in OpenMP execution region and top scope was already checked.
1826 return DVar;
1827
1828 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1829 // in a Construct, C/C++, predetermined, p.4]
1830 // Static data members are shared.
1831 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1832 // in a Construct, C/C++, predetermined, p.7]
1833 // Variables with static storage duration that are declared in a scope
1834 // inside the construct are shared.
1835 if (VD && VD->isStaticDataMember()) {
1836 // Check for explicitly specified attributes.
1837 const_iterator I = begin();
1838 const_iterator EndI = end();
1839 if (FromParent && I != EndI)
1840 ++I;
1841 if (I != EndI) {
1842 auto It = I->SharingMap.find(D);
1843 if (It != I->SharingMap.end()) {
1844 const DSAInfo &Data = It->getSecond();
1845 DVar.RefExpr = Data.RefExpr.getPointer();
1846 DVar.PrivateCopy = Data.PrivateCopy;
1847 DVar.CKind = Data.Attributes;
1848 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1849 DVar.DKind = I->Directive;
1850 DVar.Modifier = Data.Modifier;
1851 DVar.AppliedToPointee = Data.AppliedToPointee;
1852 return DVar;
1853 }
1854 }
1855
1856 DVar.CKind = OMPC_shared;
1857 return DVar;
1858 }
1859
1860 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1861 // The predetermined shared attribute for const-qualified types having no
1862 // mutable members was removed after OpenMP 3.1.
1863 if (SemaRef.LangOpts.OpenMP <= 31) {
1864 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1865 // in a Construct, C/C++, predetermined, p.6]
1866 // Variables with const qualified type having no mutable member are
1867 // shared.
1868 if (isConstNotMutableType(SemaRef, Type: D->getType())) {
1869 // Variables with const-qualified type having no mutable member may be
1870 // listed in a firstprivate clause, even if they are static data members.
1871 DSAVarData DVarTemp = hasInnermostDSA(
1872 D,
1873 [](OpenMPClauseKind C, bool) {
1874 return C == OMPC_firstprivate || C == OMPC_shared;
1875 },
1876 MatchesAlways, FromParent);
1877 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1878 return DVarTemp;
1879
1880 DVar.CKind = OMPC_shared;
1881 return DVar;
1882 }
1883 }
1884
1885 // Explicitly specified attributes and local variables with predetermined
1886 // attributes.
1887 const_iterator I = begin();
1888 const_iterator EndI = end();
1889 if (FromParent && I != EndI)
1890 ++I;
1891 if (I == EndI)
1892 return DVar;
1893 auto It = I->SharingMap.find(D);
1894 if (It != I->SharingMap.end()) {
1895 const DSAInfo &Data = It->getSecond();
1896 DVar.RefExpr = Data.RefExpr.getPointer();
1897 DVar.PrivateCopy = Data.PrivateCopy;
1898 DVar.CKind = Data.Attributes;
1899 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1900 DVar.DKind = I->Directive;
1901 DVar.Modifier = Data.Modifier;
1902 DVar.AppliedToPointee = Data.AppliedToPointee;
1903 }
1904
1905 return DVar;
1906}
1907
1908const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1909 bool FromParent) const {
1910 if (isStackEmpty()) {
1911 const_iterator I;
1912 return getDSA(Iter&: I, D);
1913 }
1914 D = getCanonicalDecl(D);
1915 const_iterator StartI = begin();
1916 const_iterator EndI = end();
1917 if (FromParent && StartI != EndI)
1918 ++StartI;
1919 return getDSA(Iter&: StartI, D);
1920}
1921
1922const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1923 unsigned Level) const {
1924 if (getStackSize() <= Level)
1925 return DSAVarData();
1926 D = getCanonicalDecl(D);
1927 const_iterator StartI = std::next(x: begin(), n: getStackSize() - 1 - Level);
1928 return getDSA(Iter&: StartI, D);
1929}
1930
1931const DSAStackTy::DSAVarData
1932DSAStackTy::hasDSA(ValueDecl *D,
1933 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1934 DefaultDataSharingAttributes)>
1935 CPred,
1936 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1937 bool FromParent) const {
1938 if (isStackEmpty())
1939 return {};
1940 D = getCanonicalDecl(D);
1941 const_iterator I = begin();
1942 const_iterator EndI = end();
1943 if (FromParent && I != EndI)
1944 ++I;
1945 for (; I != EndI; ++I) {
1946 if (!DPred(I->Directive) &&
1947 !isImplicitOrExplicitTaskingRegion(I->Directive))
1948 continue;
1949 const_iterator NewI = I;
1950 DSAVarData DVar = getDSA(Iter&: NewI, D);
1951 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1952 return DVar;
1953 }
1954 return {};
1955}
1956
1957const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1958 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1959 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1960 bool FromParent) const {
1961 if (isStackEmpty())
1962 return {};
1963 D = getCanonicalDecl(D);
1964 const_iterator StartI = begin();
1965 const_iterator EndI = end();
1966 if (FromParent && StartI != EndI)
1967 ++StartI;
1968 if (StartI == EndI || !DPred(StartI->Directive))
1969 return {};
1970 const_iterator NewI = StartI;
1971 DSAVarData DVar = getDSA(Iter&: NewI, D);
1972 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1973 ? DVar
1974 : DSAVarData();
1975}
1976
1977bool DSAStackTy::hasExplicitDSA(
1978 const ValueDecl *D,
1979 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1980 unsigned Level, bool NotLastprivate) const {
1981 if (getStackSize() <= Level)
1982 return false;
1983 D = getCanonicalDecl(D);
1984 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1985 auto I = StackElem.SharingMap.find(D);
1986 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1987 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1988 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1989 return true;
1990 // Check predetermined rules for the loop control variables.
1991 auto LI = StackElem.LCVMap.find(Val: D);
1992 if (LI != StackElem.LCVMap.end())
1993 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1994 return false;
1995}
1996
1997bool DSAStackTy::hasExplicitDirective(
1998 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1999 unsigned Level) const {
2000 if (getStackSize() <= Level)
2001 return false;
2002 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2003 return DPred(StackElem.Directive);
2004}
2005
2006bool DSAStackTy::hasDirective(
2007 const llvm::function_ref<bool(OpenMPDirectiveKind,
2008 const DeclarationNameInfo &, SourceLocation)>
2009 DPred,
2010 bool FromParent) const {
2011 // We look only in the enclosing region.
2012 size_t Skip = FromParent ? 2 : 1;
2013 for (const_iterator I = begin() + std::min(a: Skip, b: getStackSize()), E = end();
2014 I != E; ++I) {
2015 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2016 return true;
2017 }
2018 return false;
2019}
2020
2021void Sema::InitDataSharingAttributesStack() {
2022 VarDataSharingAttributesStack = new DSAStackTy(*this);
2023}
2024
2025#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2026
2027void Sema::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2028
2029void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2030 DSAStack->popFunction(OldFSI);
2031}
2032
2033static bool isOpenMPDeviceDelayedContext(Sema &S) {
2034 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2035 "Expected OpenMP device compilation.");
2036 return !S.isInOpenMPTargetExecutionDirective();
2037}
2038
2039namespace {
2040/// Status of the function emission on the host/device.
2041enum class FunctionEmissionStatus {
2042 Emitted,
2043 Discarded,
2044 Unknown,
2045};
2046} // anonymous namespace
2047
2048Sema::SemaDiagnosticBuilder
2049Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID,
2050 const FunctionDecl *FD) {
2051 assert(LangOpts.OpenMP && LangOpts.OpenMPIsTargetDevice &&
2052 "Expected OpenMP device compilation.");
2053
2054 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2055 if (FD) {
2056 FunctionEmissionStatus FES = getEmissionStatus(Decl: FD);
2057 switch (FES) {
2058 case FunctionEmissionStatus::Emitted:
2059 Kind = SemaDiagnosticBuilder::K_Immediate;
2060 break;
2061 case FunctionEmissionStatus::Unknown:
2062 // TODO: We should always delay diagnostics here in case a target
2063 // region is in a function we do not emit. However, as the
2064 // current diagnostics are associated with the function containing
2065 // the target region and we do not emit that one, we would miss out
2066 // on diagnostics for the target region itself. We need to anchor
2067 // the diagnostics with the new generated function *or* ensure we
2068 // emit diagnostics associated with the surrounding function.
2069 Kind = isOpenMPDeviceDelayedContext(S&: *this)
2070 ? SemaDiagnosticBuilder::K_Deferred
2071 : SemaDiagnosticBuilder::K_Immediate;
2072 break;
2073 case FunctionEmissionStatus::TemplateDiscarded:
2074 case FunctionEmissionStatus::OMPDiscarded:
2075 Kind = SemaDiagnosticBuilder::K_Nop;
2076 break;
2077 case FunctionEmissionStatus::CUDADiscarded:
2078 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2079 break;
2080 }
2081 }
2082
2083 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2084}
2085
2086Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc,
2087 unsigned DiagID,
2088 const FunctionDecl *FD) {
2089 assert(LangOpts.OpenMP && !LangOpts.OpenMPIsTargetDevice &&
2090 "Expected OpenMP host compilation.");
2091
2092 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2093 if (FD) {
2094 FunctionEmissionStatus FES = getEmissionStatus(Decl: FD);
2095 switch (FES) {
2096 case FunctionEmissionStatus::Emitted:
2097 Kind = SemaDiagnosticBuilder::K_Immediate;
2098 break;
2099 case FunctionEmissionStatus::Unknown:
2100 Kind = SemaDiagnosticBuilder::K_Deferred;
2101 break;
2102 case FunctionEmissionStatus::TemplateDiscarded:
2103 case FunctionEmissionStatus::OMPDiscarded:
2104 case FunctionEmissionStatus::CUDADiscarded:
2105 Kind = SemaDiagnosticBuilder::K_Nop;
2106 break;
2107 }
2108 }
2109
2110 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2111}
2112
2113static OpenMPDefaultmapClauseKind
2114getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) {
2115 if (LO.OpenMP <= 45) {
2116 if (VD->getType().getNonReferenceType()->isScalarType())
2117 return OMPC_DEFAULTMAP_scalar;
2118 return OMPC_DEFAULTMAP_aggregate;
2119 }
2120 if (VD->getType().getNonReferenceType()->isAnyPointerType())
2121 return OMPC_DEFAULTMAP_pointer;
2122 if (VD->getType().getNonReferenceType()->isScalarType())
2123 return OMPC_DEFAULTMAP_scalar;
2124 return OMPC_DEFAULTMAP_aggregate;
2125}
2126
2127bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2128 unsigned OpenMPCaptureLevel) const {
2129 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2130
2131 ASTContext &Ctx = getASTContext();
2132 bool IsByRef = true;
2133
2134 // Find the directive that is associated with the provided scope.
2135 D = cast<ValueDecl>(D->getCanonicalDecl());
2136 QualType Ty = D->getType();
2137
2138 bool IsVariableUsedInMapClause = false;
2139 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective, Level)) {
2140 // This table summarizes how a given variable should be passed to the device
2141 // given its type and the clauses where it appears. This table is based on
2142 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2143 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2144 //
2145 // =========================================================================
2146 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2147 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2148 // =========================================================================
2149 // | scl | | | | - | | bycopy|
2150 // | scl | | - | x | - | - | bycopy|
2151 // | scl | | x | - | - | - | null |
2152 // | scl | x | | | - | | byref |
2153 // | scl | x | - | x | - | - | bycopy|
2154 // | scl | x | x | - | - | - | null |
2155 // | scl | | - | - | - | x | byref |
2156 // | scl | x | - | - | - | x | byref |
2157 //
2158 // | agg | n.a. | | | - | | byref |
2159 // | agg | n.a. | - | x | - | - | byref |
2160 // | agg | n.a. | x | - | - | - | null |
2161 // | agg | n.a. | - | - | - | x | byref |
2162 // | agg | n.a. | - | - | - | x[] | byref |
2163 //
2164 // | ptr | n.a. | | | - | | bycopy|
2165 // | ptr | n.a. | - | x | - | - | bycopy|
2166 // | ptr | n.a. | x | - | - | - | null |
2167 // | ptr | n.a. | - | - | - | x | byref |
2168 // | ptr | n.a. | - | - | - | x[] | bycopy|
2169 // | ptr | n.a. | - | - | x | | bycopy|
2170 // | ptr | n.a. | - | - | x | x | bycopy|
2171 // | ptr | n.a. | - | - | x | x[] | bycopy|
2172 // =========================================================================
2173 // Legend:
2174 // scl - scalar
2175 // ptr - pointer
2176 // agg - aggregate
2177 // x - applies
2178 // - - invalid in this combination
2179 // [] - mapped with an array section
2180 // byref - should be mapped by reference
2181 // byval - should be mapped by value
2182 // null - initialize a local variable to null on the device
2183 //
2184 // Observations:
2185 // - All scalar declarations that show up in a map clause have to be passed
2186 // by reference, because they may have been mapped in the enclosing data
2187 // environment.
2188 // - If the scalar value does not fit the size of uintptr, it has to be
2189 // passed by reference, regardless the result in the table above.
2190 // - For pointers mapped by value that have either an implicit map or an
2191 // array section, the runtime library may pass the NULL value to the
2192 // device instead of the value passed to it by the compiler.
2193
2194 if (Ty->isReferenceType())
2195 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2196
2197 // Locate map clauses and see if the variable being captured is referred to
2198 // in any of those clauses. Here we only care about variables, not fields,
2199 // because fields are part of aggregates.
2200 bool IsVariableAssociatedWithSection = false;
2201
2202 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2203 VD: D, Level,
2204 Check: [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2205 D](OMPClauseMappableExprCommon::MappableExprComponentListRef
2206 MapExprComponents,
2207 OpenMPClauseKind WhereFoundClauseKind) {
2208 // Both map and has_device_addr clauses information influences how a
2209 // variable is captured. E.g. is_device_ptr does not require changing
2210 // the default behavior.
2211 if (WhereFoundClauseKind != OMPC_map &&
2212 WhereFoundClauseKind != OMPC_has_device_addr)
2213 return false;
2214
2215 auto EI = MapExprComponents.rbegin();
2216 auto EE = MapExprComponents.rend();
2217
2218 assert(EI != EE && "Invalid map expression!");
2219
2220 if (isa<DeclRefExpr>(Val: EI->getAssociatedExpression()))
2221 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2222
2223 ++EI;
2224 if (EI == EE)
2225 return false;
2226 auto Last = std::prev(x: EE);
2227 const auto *UO =
2228 dyn_cast<UnaryOperator>(Val: Last->getAssociatedExpression());
2229 if ((UO && UO->getOpcode() == UO_Deref) ||
2230 isa<ArraySubscriptExpr>(Val: Last->getAssociatedExpression()) ||
2231 isa<OMPArraySectionExpr>(Val: Last->getAssociatedExpression()) ||
2232 isa<MemberExpr>(Val: EI->getAssociatedExpression()) ||
2233 isa<OMPArrayShapingExpr>(Val: Last->getAssociatedExpression())) {
2234 IsVariableAssociatedWithSection = true;
2235 // There is nothing more we need to know about this variable.
2236 return true;
2237 }
2238
2239 // Keep looking for more map info.
2240 return false;
2241 });
2242
2243 if (IsVariableUsedInMapClause) {
2244 // If variable is identified in a map clause it is always captured by
2245 // reference except if it is a pointer that is dereferenced somehow.
2246 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2247 } else {
2248 // By default, all the data that has a scalar type is mapped by copy
2249 // (except for reduction variables).
2250 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2251 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2252 !Ty->isAnyPointerType()) ||
2253 !Ty->isScalarType() ||
2254 DSAStack->isDefaultmapCapturedByRef(
2255 Level, Kind: getVariableCategoryFromDecl(LO: LangOpts, VD: D)) ||
2256 DSAStack->hasExplicitDSA(
2257 D,
2258 [](OpenMPClauseKind K, bool AppliedToPointee) {
2259 return K == OMPC_reduction && !AppliedToPointee;
2260 },
2261 Level);
2262 }
2263 }
2264
2265 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2266 IsByRef =
2267 ((IsVariableUsedInMapClause &&
2268 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2269 OMPD_target) ||
2270 !(DSAStack->hasExplicitDSA(
2271 D,
2272 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2273 return K == OMPC_firstprivate ||
2274 (K == OMPC_reduction && AppliedToPointee);
2275 },
2276 Level, /*NotLastprivate=*/true) ||
2277 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2278 // If the variable is artificial and must be captured by value - try to
2279 // capture by value.
2280 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2281 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2282 // If the variable is implicitly firstprivate and scalar - capture by
2283 // copy
2284 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2285 DSAStack->getDefaultDSA() == DSA_private) &&
2286 !DSAStack->hasExplicitDSA(
2287 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2288 Level) &&
2289 !DSAStack->isLoopControlVariable(D, Level).first);
2290 }
2291
2292 // When passing data by copy, we need to make sure it fits the uintptr size
2293 // and alignment, because the runtime library only deals with uintptr types.
2294 // If it does not fit the uintptr size, we need to pass the data by reference
2295 // instead.
2296 if (!IsByRef && (Ctx.getTypeSizeInChars(T: Ty) >
2297 Ctx.getTypeSizeInChars(T: Ctx.getUIntPtrType()) ||
2298 Ctx.getAlignOfGlobalVarInChars(T: Ty, VD: dyn_cast<VarDecl>(Val: D)) >
2299 Ctx.getTypeAlignInChars(T: Ctx.getUIntPtrType()))) {
2300 IsByRef = true;
2301 }
2302
2303 return IsByRef;
2304}
2305
2306unsigned Sema::getOpenMPNestingLevel() const {
2307 assert(getLangOpts().OpenMP);
2308 return DSAStack->getNestingLevel();
2309}
2310
2311bool Sema::isInOpenMPTaskUntiedContext() const {
2312 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2313 DSAStack->isUntiedRegion();
2314}
2315
2316bool Sema::isInOpenMPTargetExecutionDirective() const {
2317 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2318 !DSAStack->isClauseParsingMode()) ||
2319 DSAStack->hasDirective(
2320 DPred: [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2321 SourceLocation) -> bool {
2322 return isOpenMPTargetExecutionDirective(DKind: K);
2323 },
2324 FromParent: false);
2325}
2326
2327bool Sema::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2328 // Only rebuild for Field.
2329 if (!dyn_cast<FieldDecl>(Val: D))
2330 return false;
2331 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2332 D,
2333 [](OpenMPClauseKind C, bool AppliedToPointee,
2334 DefaultDataSharingAttributes DefaultAttr) {
2335 return isOpenMPPrivate(C) && !AppliedToPointee &&
2336 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2337 },
2338 [](OpenMPDirectiveKind) { return true; },
2339 DSAStack->isClauseParsingMode());
2340 if (DVarPrivate.CKind != OMPC_unknown)
2341 return true;
2342 return false;
2343}
2344
2345static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
2346 Expr *CaptureExpr, bool WithInit,
2347 DeclContext *CurContext,
2348 bool AsExpression);
2349
2350VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2351 unsigned StopAt) {
2352 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2353 D = getCanonicalDecl(D);
2354
2355 auto *VD = dyn_cast<VarDecl>(Val: D);
2356 // Do not capture constexpr variables.
2357 if (VD && VD->isConstexpr())
2358 return nullptr;
2359
2360 // If we want to determine whether the variable should be captured from the
2361 // perspective of the current capturing scope, and we've already left all the
2362 // capturing scopes of the top directive on the stack, check from the
2363 // perspective of its parent directive (if any) instead.
2364 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2365 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2366
2367 // If we are attempting to capture a global variable in a directive with
2368 // 'target' we return true so that this global is also mapped to the device.
2369 //
2370 if (VD && !VD->hasLocalStorage() &&
2371 (getCurCapturedRegion() || getCurBlock() || getCurLambda())) {
2372 if (isInOpenMPTargetExecutionDirective()) {
2373 DSAStackTy::DSAVarData DVarTop =
2374 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2375 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2376 return VD;
2377 // If the declaration is enclosed in a 'declare target' directive,
2378 // then it should not be captured.
2379 //
2380 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2381 return nullptr;
2382 CapturedRegionScopeInfo *CSI = nullptr;
2383 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2384 RangeOrContainer: llvm::reverse(C&: FunctionScopes),
2385 N: CheckScopeInfo ? (FunctionScopes.size() - (StopAt + 1)) : 0)) {
2386 if (!isa<CapturingScopeInfo>(Val: FSI))
2387 return nullptr;
2388 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(Val: FSI))
2389 if (RSI->CapRegionKind == CR_OpenMP) {
2390 CSI = RSI;
2391 break;
2392 }
2393 }
2394 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2395 SmallVector<OpenMPDirectiveKind, 4> Regions;
2396 getOpenMPCaptureRegions(CaptureRegions&: Regions,
2397 DSAStack->getDirective(Level: CSI->OpenMPLevel));
2398 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2399 return VD;
2400 }
2401 if (isInOpenMPDeclareTargetContext()) {
2402 // Try to mark variable as declare target if it is used in capturing
2403 // regions.
2404 if (LangOpts.OpenMP <= 45 &&
2405 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2406 checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
2407 return nullptr;
2408 }
2409 }
2410
2411 if (CheckScopeInfo) {
2412 bool OpenMPFound = false;
2413 for (unsigned I = StopAt + 1; I > 0; --I) {
2414 FunctionScopeInfo *FSI = FunctionScopes[I - 1];
2415 if (!isa<CapturingScopeInfo>(Val: FSI))
2416 return nullptr;
2417 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(Val: FSI))
2418 if (RSI->CapRegionKind == CR_OpenMP) {
2419 OpenMPFound = true;
2420 break;
2421 }
2422 }
2423 if (!OpenMPFound)
2424 return nullptr;
2425 }
2426
2427 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2428 (!DSAStack->isClauseParsingMode() ||
2429 DSAStack->getParentDirective() != OMPD_unknown)) {
2430 auto &&Info = DSAStack->isLoopControlVariable(D);
2431 if (Info.first ||
2432 (VD && VD->hasLocalStorage() &&
2433 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2434 (VD && DSAStack->isForceVarCapturing()))
2435 return VD ? VD : Info.second;
2436 DSAStackTy::DSAVarData DVarTop =
2437 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2438 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2439 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2440 return VD ? VD : cast<VarDecl>(Val: DVarTop.PrivateCopy->getDecl());
2441 // Threadprivate variables must not be captured.
2442 if (isOpenMPThreadPrivate(DVarTop.CKind))
2443 return nullptr;
2444 // The variable is not private or it is the variable in the directive with
2445 // default(none) clause and not used in any clause.
2446 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2447 D,
2448 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2449 return isOpenMPPrivate(C) && !AppliedToPointee;
2450 },
2451 [](OpenMPDirectiveKind) { return true; },
2452 DSAStack->isClauseParsingMode());
2453 // Global shared must not be captured.
2454 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2455 ((DSAStack->getDefaultDSA() != DSA_none &&
2456 DSAStack->getDefaultDSA() != DSA_private &&
2457 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2458 DVarTop.CKind == OMPC_shared))
2459 return nullptr;
2460 auto *FD = dyn_cast<FieldDecl>(Val: D);
2461 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2462 !DVarPrivate.PrivateCopy) {
2463 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2464 D,
2465 [](OpenMPClauseKind C, bool AppliedToPointee,
2466 DefaultDataSharingAttributes DefaultAttr) {
2467 return isOpenMPPrivate(C) && !AppliedToPointee &&
2468 (DefaultAttr == DSA_firstprivate ||
2469 DefaultAttr == DSA_private);
2470 },
2471 [](OpenMPDirectiveKind) { return true; },
2472 DSAStack->isClauseParsingMode());
2473 if (DVarPrivate.CKind == OMPC_unknown)
2474 return nullptr;
2475
2476 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2477 if (VD)
2478 return VD;
2479 if (getCurrentThisType().isNull())
2480 return nullptr;
2481 Expr *ThisExpr = BuildCXXThisExpr(Loc: SourceLocation(), Type: getCurrentThisType(),
2482 /*IsImplicit=*/true);
2483 const CXXScopeSpec CS = CXXScopeSpec();
2484 Expr *ME = BuildMemberExpr(ThisExpr, /*IsArrow=*/true, SourceLocation(),
2485 NestedNameSpecifierLoc(), SourceLocation(), FD,
2486 DeclAccessPair::make(D: FD, AS: FD->getAccess()),
2487 /*HadMultipleCandidates=*/false,
2488 DeclarationNameInfo(), FD->getType(),
2489 VK_LValue, OK_Ordinary);
2490 OMPCapturedExprDecl *CD = buildCaptureDecl(
2491 *this, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2492 CurContext->getParent(), /*AsExpression=*/false);
2493 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2494 *this, CD, CD->getType().getNonReferenceType(), SourceLocation());
2495 VD = cast<VarDecl>(Val: VDPrivateRefExpr->getDecl());
2496 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2497 return VD;
2498 }
2499 if (DVarPrivate.CKind != OMPC_unknown ||
2500 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2501 DSAStack->getDefaultDSA() == DSA_private ||
2502 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2503 return VD ? VD : cast<VarDecl>(Val: DVarPrivate.PrivateCopy->getDecl());
2504 }
2505 return nullptr;
2506}
2507
2508void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2509 unsigned Level) const {
2510 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2511}
2512
2513void Sema::startOpenMPLoop() {
2514 assert(LangOpts.OpenMP && "OpenMP must be enabled.");
2515 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2516 DSAStack->loopInit();
2517}
2518
2519void Sema::startOpenMPCXXRangeFor() {
2520 assert(LangOpts.OpenMP && "OpenMP must be enabled.");
2521 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2522 DSAStack->resetPossibleLoopCounter();
2523 DSAStack->loopStart();
2524 }
2525}
2526
2527OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2528 unsigned CapLevel) const {
2529 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2530 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2531 (!DSAStack->isClauseParsingMode() ||
2532 DSAStack->getParentDirective() != OMPD_unknown)) {
2533 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2534 D,
2535 [](OpenMPClauseKind C, bool AppliedToPointee,
2536 DefaultDataSharingAttributes DefaultAttr) {
2537 return isOpenMPPrivate(C) && !AppliedToPointee &&
2538 DefaultAttr == DSA_private;
2539 },
2540 [](OpenMPDirectiveKind) { return true; },
2541 DSAStack->isClauseParsingMode());
2542 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2543 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2544 !DSAStack->isLoopControlVariable(D).first)
2545 return OMPC_private;
2546 }
2547 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTaskingDirective, Level)) {
2548 bool IsTriviallyCopyable =
2549 D->getType().getNonReferenceType().isTriviallyCopyableType(Context) &&
2550 !D->getType()
2551 .getNonReferenceType()
2552 .getCanonicalType()
2553 ->getAsCXXRecordDecl();
2554 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2555 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2556 getOpenMPCaptureRegions(CaptureRegions, DKind);
2557 if (isOpenMPTaskingDirective(Kind: CaptureRegions[CapLevel]) &&
2558 (IsTriviallyCopyable ||
2559 !isOpenMPTaskLoopDirective(DKind: CaptureRegions[CapLevel]))) {
2560 if (DSAStack->hasExplicitDSA(
2561 D,
2562 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2563 Level, /*NotLastprivate=*/true))
2564 return OMPC_firstprivate;
2565 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2566 if (DVar.CKind != OMPC_shared &&
2567 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2568 DSAStack->addImplicitTaskFirstprivate(Level, D);
2569 return OMPC_firstprivate;
2570 }
2571 }
2572 }
2573 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2574 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2575 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2576 DSAStack->resetPossibleLoopCounter(D);
2577 DSAStack->loopStart();
2578 return OMPC_private;
2579 }
2580 if ((DSAStack->getPossiblyLoopCunter() == D->getCanonicalDecl() ||
2581 DSAStack->isLoopControlVariable(D).first) &&
2582 !DSAStack->hasExplicitDSA(
2583 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2584 Level) &&
2585 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2586 return OMPC_private;
2587 }
2588 if (const auto *VD = dyn_cast<VarDecl>(Val: D)) {
2589 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2590 DSAStack->isForceVarCapturing() &&
2591 !DSAStack->hasExplicitDSA(
2592 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2593 Level))
2594 return OMPC_private;
2595 }
2596 // User-defined allocators are private since they must be defined in the
2597 // context of target region.
2598 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2599 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2600 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2601 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2602 return OMPC_private;
2603 return (DSAStack->hasExplicitDSA(
2604 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2605 Level) ||
2606 (DSAStack->isClauseParsingMode() &&
2607 DSAStack->getClauseParsingMode() == OMPC_private) ||
2608 // Consider taskgroup reduction descriptor variable a private
2609 // to avoid possible capture in the region.
2610 (DSAStack->hasExplicitDirective(
2611 [](OpenMPDirectiveKind K) {
2612 return K == OMPD_taskgroup ||
2613 ((isOpenMPParallelDirective(K) ||
2614 isOpenMPWorksharingDirective(K)) &&
2615 !isOpenMPSimdDirective(K));
2616 },
2617 Level) &&
2618 DSAStack->isTaskgroupReductionRef(D, Level)))
2619 ? OMPC_private
2620 : OMPC_unknown;
2621}
2622
2623void Sema::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2624 unsigned Level) {
2625 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2626 D = getCanonicalDecl(D);
2627 OpenMPClauseKind OMPC = OMPC_unknown;
2628 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2629 const unsigned NewLevel = I - 1;
2630 if (DSAStack->hasExplicitDSA(
2631 D,
2632 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2633 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2634 OMPC = K;
2635 return true;
2636 }
2637 return false;
2638 },
2639 NewLevel))
2640 break;
2641 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2642 VD: D, Level: NewLevel,
2643 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2644 OpenMPClauseKind) { return true; })) {
2645 OMPC = OMPC_map;
2646 break;
2647 }
2648 if (DSAStack->hasExplicitDirective(DPred: isOpenMPTargetExecutionDirective,
2649 Level: NewLevel)) {
2650 OMPC = OMPC_map;
2651 if (DSAStack->mustBeFirstprivateAtLevel(
2652 NewLevel, getVariableCategoryFromDecl(LangOpts, D)))
2653 OMPC = OMPC_firstprivate;
2654 break;
2655 }
2656 }
2657 if (OMPC != OMPC_unknown)
2658 FD->addAttr(OMPCaptureKindAttr::CreateImplicit(Context, unsigned(OMPC)));
2659}
2660
2661bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2662 unsigned CaptureLevel) const {
2663 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2664 // Return true if the current level is no longer enclosed in a target region.
2665
2666 SmallVector<OpenMPDirectiveKind, 4> Regions;
2667 getOpenMPCaptureRegions(CaptureRegions&: Regions, DSAStack->getDirective(Level));
2668 const auto *VD = dyn_cast<VarDecl>(Val: D);
2669 return VD && !VD->hasLocalStorage() &&
2670 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2671 Level) &&
2672 Regions[CaptureLevel] != OMPD_task;
2673}
2674
2675bool Sema::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2676 unsigned CaptureLevel) const {
2677 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2678 // Return true if the current level is no longer enclosed in a target region.
2679
2680 if (const auto *VD = dyn_cast<VarDecl>(Val: D)) {
2681 if (!VD->hasLocalStorage()) {
2682 if (isInOpenMPTargetExecutionDirective())
2683 return true;
2684 DSAStackTy::DSAVarData TopDVar =
2685 DSAStack->getTopDSA(D, /*FromParent=*/false);
2686 unsigned NumLevels =
2687 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2688 if (Level == 0)
2689 // non-file scope static variale with default(firstprivate)
2690 // should be gloabal captured.
2691 return (NumLevels == CaptureLevel + 1 &&
2692 (TopDVar.CKind != OMPC_shared ||
2693 DSAStack->getDefaultDSA() == DSA_firstprivate));
2694 do {
2695 --Level;
2696 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2697 if (DVar.CKind != OMPC_shared)
2698 return true;
2699 } while (Level > 0);
2700 }
2701 }
2702 return true;
2703}
2704
2705void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
2706
2707void Sema::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2708 OMPTraitInfo &TI) {
2709 OMPDeclareVariantScopes.push_back(Elt: OMPDeclareVariantScope(TI));
2710}
2711
2712void Sema::ActOnOpenMPEndDeclareVariant() {
2713 assert(isInOpenMPDeclareVariantScope() &&
2714 "Not in OpenMP declare variant scope!");
2715
2716 OMPDeclareVariantScopes.pop_back();
2717}
2718
2719void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2720 const FunctionDecl *Callee,
2721 SourceLocation Loc) {
2722 assert(LangOpts.OpenMP && "Expected OpenMP compilation mode.");
2723 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2724 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2725 // Ignore host functions during device analyzis.
2726 if (LangOpts.OpenMPIsTargetDevice &&
2727 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2728 return;
2729 // Ignore nohost functions during host analyzis.
2730 if (!LangOpts.OpenMPIsTargetDevice && DevTy &&
2731 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2732 return;
2733 const FunctionDecl *FD = Callee->getMostRecentDecl();
2734 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2735 if (LangOpts.OpenMPIsTargetDevice && DevTy &&
2736 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2737 // Diagnose host function called during device codegen.
2738 StringRef HostDevTy =
2739 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2740 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2741 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2742 diag::note_omp_marked_device_type_here)
2743 << HostDevTy;
2744 return;
2745 }
2746 if (!LangOpts.OpenMPIsTargetDevice && !LangOpts.OpenMPOffloadMandatory &&
2747 DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2748 // In OpenMP 5.2 or later, if the function has a host variant then allow
2749 // that to be called instead
2750 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2751 for (OMPDeclareVariantAttr *A :
2752 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2753 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2754 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2755 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2756 OMPDeclareTargetDeclAttr::getDeviceType(
2757 VariantFD->getMostRecentDecl());
2758 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2759 return true;
2760 }
2761 return false;
2762 };
2763 if (getLangOpts().OpenMP >= 52 &&
2764 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2765 return;
2766 // Diagnose nohost function called during host codegen.
2767 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2768 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2769 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2770 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2771 diag::note_omp_marked_device_type_here)
2772 << NoHostDevTy;
2773 }
2774}
2775
2776void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2777 const DeclarationNameInfo &DirName,
2778 Scope *CurScope, SourceLocation Loc) {
2779 DSAStack->push(DKind, DirName, CurScope, Loc);
2780 PushExpressionEvaluationContext(
2781 NewContext: ExpressionEvaluationContext::PotentiallyEvaluated);
2782}
2783
2784void Sema::StartOpenMPClause(OpenMPClauseKind K) {
2785 DSAStack->setClauseParsingMode(K);
2786}
2787
2788void Sema::EndOpenMPClause() {
2789 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2790 CleanupVarDeclMarking();
2791}
2792
2793static std::pair<ValueDecl *, bool>
2794getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2795 SourceRange &ERange, bool AllowArraySection = false,
2796 StringRef DiagType = "");
2797
2798/// Check consistency of the reduction clauses.
2799static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2800 ArrayRef<OMPClause *> Clauses) {
2801 bool InscanFound = false;
2802 SourceLocation InscanLoc;
2803 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2804 // A reduction clause without the inscan reduction-modifier may not appear on
2805 // a construct on which a reduction clause with the inscan reduction-modifier
2806 // appears.
2807 for (OMPClause *C : Clauses) {
2808 if (C->getClauseKind() != OMPC_reduction)
2809 continue;
2810 auto *RC = cast<OMPReductionClause>(Val: C);
2811 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2812 InscanFound = true;
2813 InscanLoc = RC->getModifierLoc();
2814 continue;
2815 }
2816 if (RC->getModifier() == OMPC_REDUCTION_task) {
2817 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2818 // A reduction clause with the task reduction-modifier may only appear on
2819 // a parallel construct, a worksharing construct or a combined or
2820 // composite construct for which any of the aforementioned constructs is a
2821 // constituent construct and simd or loop are not constituent constructs.
2822 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2823 if (!(isOpenMPParallelDirective(CurDir) ||
2824 isOpenMPWorksharingDirective(CurDir)) ||
2825 isOpenMPSimdDirective(CurDir))
2826 S.Diag(RC->getModifierLoc(),
2827 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2828 continue;
2829 }
2830 }
2831 if (InscanFound) {
2832 for (OMPClause *C : Clauses) {
2833 if (C->getClauseKind() != OMPC_reduction)
2834 continue;
2835 auto *RC = cast<OMPReductionClause>(Val: C);
2836 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2837 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2838 ? RC->getBeginLoc()
2839 : RC->getModifierLoc(),
2840 diag::err_omp_inscan_reduction_expected);
2841 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2842 continue;
2843 }
2844 for (Expr *Ref : RC->varlists()) {
2845 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2846 SourceLocation ELoc;
2847 SourceRange ERange;
2848 Expr *SimpleRefExpr = Ref;
2849 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
2850 /*AllowArraySection=*/true);
2851 ValueDecl *D = Res.first;
2852 if (!D)
2853 continue;
2854 if (!Stack->isUsedInScanDirective(D: getCanonicalDecl(D))) {
2855 S.Diag(Ref->getExprLoc(),
2856 diag::err_omp_reduction_not_inclusive_exclusive)
2857 << Ref->getSourceRange();
2858 }
2859 }
2860 }
2861 }
2862}
2863
2864static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2865 ArrayRef<OMPClause *> Clauses);
2866static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2867 bool WithInit);
2868
2869static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2870 const ValueDecl *D,
2871 const DSAStackTy::DSAVarData &DVar,
2872 bool IsLoopIterVar = false);
2873
2874void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
2875 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2876 // A variable of class type (or array thereof) that appears in a lastprivate
2877 // clause requires an accessible, unambiguous default constructor for the
2878 // class type, unless the list item is also specified in a firstprivate
2879 // clause.
2880 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(Val: CurDirective)) {
2881 for (OMPClause *C : D->clauses()) {
2882 if (auto *Clause = dyn_cast<OMPLastprivateClause>(Val: C)) {
2883 SmallVector<Expr *, 8> PrivateCopies;
2884 for (Expr *DE : Clause->varlists()) {
2885 if (DE->isValueDependent() || DE->isTypeDependent()) {
2886 PrivateCopies.push_back(Elt: nullptr);
2887 continue;
2888 }
2889 auto *DRE = cast<DeclRefExpr>(Val: DE->IgnoreParens());
2890 auto *VD = cast<VarDecl>(Val: DRE->getDecl());
2891 QualType Type = VD->getType().getNonReferenceType();
2892 const DSAStackTy::DSAVarData DVar =
2893 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2894 if (DVar.CKind == OMPC_lastprivate) {
2895 // Generate helper private variable and initialize it with the
2896 // default value. The address of the original variable is replaced
2897 // by the address of the new private variable in CodeGen. This new
2898 // variable is not added to IdResolver, so the code in the OpenMP
2899 // region uses original variable for proper diagnostics.
2900 VarDecl *VDPrivate = buildVarDecl(
2901 *this, DE->getExprLoc(), Type.getUnqualifiedType(),
2902 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2903 ActOnUninitializedDecl(VDPrivate);
2904 if (VDPrivate->isInvalidDecl()) {
2905 PrivateCopies.push_back(Elt: nullptr);
2906 continue;
2907 }
2908 PrivateCopies.push_back(buildDeclRefExpr(
2909 S&: *this, D: VDPrivate, Ty: DE->getType(), Loc: DE->getExprLoc()));
2910 } else {
2911 // The variable is also a firstprivate, so initialization sequence
2912 // for private copy is generated already.
2913 PrivateCopies.push_back(Elt: nullptr);
2914 }
2915 }
2916 Clause->setPrivateCopies(PrivateCopies);
2917 continue;
2918 }
2919 // Finalize nontemporal clause by handling private copies, if any.
2920 if (auto *Clause = dyn_cast<OMPNontemporalClause>(Val: C)) {
2921 SmallVector<Expr *, 8> PrivateRefs;
2922 for (Expr *RefExpr : Clause->varlists()) {
2923 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2924 SourceLocation ELoc;
2925 SourceRange ERange;
2926 Expr *SimpleRefExpr = RefExpr;
2927 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange);
2928 if (Res.second)
2929 // It will be analyzed later.
2930 PrivateRefs.push_back(Elt: RefExpr);
2931 ValueDecl *D = Res.first;
2932 if (!D)
2933 continue;
2934
2935 const DSAStackTy::DSAVarData DVar =
2936 DSAStack->getTopDSA(D, /*FromParent=*/false);
2937 PrivateRefs.push_back(Elt: DVar.PrivateCopy ? DVar.PrivateCopy
2938 : SimpleRefExpr);
2939 }
2940 Clause->setPrivateRefs(PrivateRefs);
2941 continue;
2942 }
2943 if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(Val: C)) {
2944 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2945 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2946 auto *DRE = dyn_cast<DeclRefExpr>(Val: D.Allocator->IgnoreParenImpCasts());
2947 if (!DRE)
2948 continue;
2949 ValueDecl *VD = DRE->getDecl();
2950 if (!VD || !isa<VarDecl>(Val: VD))
2951 continue;
2952 DSAStackTy::DSAVarData DVar =
2953 DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
2954 // OpenMP [2.12.5, target Construct]
2955 // Memory allocators that appear in a uses_allocators clause cannot
2956 // appear in other data-sharing attribute clauses or data-mapping
2957 // attribute clauses in the same construct.
2958 Expr *MapExpr = nullptr;
2959 if (DVar.RefExpr ||
2960 DSAStack->checkMappableExprComponentListsForDecl(
2961 VD, /*CurrentRegionOnly=*/true,
2962 Check: [VD, &MapExpr](
2963 OMPClauseMappableExprCommon::MappableExprComponentListRef
2964 MapExprComponents,
2965 OpenMPClauseKind C) {
2966 auto MI = MapExprComponents.rbegin();
2967 auto ME = MapExprComponents.rend();
2968 if (MI != ME &&
2969 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2970 VD->getCanonicalDecl()) {
2971 MapExpr = MI->getAssociatedExpression();
2972 return true;
2973 }
2974 return false;
2975 })) {
2976 Diag(D.Allocator->getExprLoc(),
2977 diag::err_omp_allocator_used_in_clauses)
2978 << D.Allocator->getSourceRange();
2979 if (DVar.RefExpr)
2980 reportOriginalDsa(SemaRef&: *this, DSAStack, D: VD, DVar);
2981 else
2982 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2983 << MapExpr->getSourceRange();
2984 }
2985 }
2986 continue;
2987 }
2988 }
2989 // Check allocate clauses.
2990 if (!CurContext->isDependentContext())
2991 checkAllocateClauses(S&: *this, DSAStack, Clauses: D->clauses());
2992 checkReductionClauses(S&: *this, DSAStack, Clauses: D->clauses());
2993 }
2994
2995 DSAStack->pop();
2996 DiscardCleanupsInEvaluationContext();
2997 PopExpressionEvaluationContext();
2998}
2999
3000static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3001 Expr *NumIterations, Sema &SemaRef,
3002 Scope *S, DSAStackTy *Stack);
3003
3004namespace {
3005
3006class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3007private:
3008 Sema &SemaRef;
3009
3010public:
3011 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3012 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3013 NamedDecl *ND = Candidate.getCorrectionDecl();
3014 if (const auto *VD = dyn_cast_or_null<VarDecl>(Val: ND)) {
3015 return VD->hasGlobalStorage() &&
3016 SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(),
3017 S: SemaRef.getCurScope());
3018 }
3019 return false;
3020 }
3021
3022 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3023 return std::make_unique<VarDeclFilterCCC>(args&: *this);
3024 }
3025};
3026
3027class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3028private:
3029 Sema &SemaRef;
3030
3031public:
3032 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3033 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3034 NamedDecl *ND = Candidate.getCorrectionDecl();
3035 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3036 isa<FunctionDecl>(ND))) {
3037 return SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(),
3038 S: SemaRef.getCurScope());
3039 }
3040 return false;
3041 }
3042
3043 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3044 return std::make_unique<VarOrFuncDeclFilterCCC>(args&: *this);
3045 }
3046};
3047
3048} // namespace
3049
3050ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
3051 CXXScopeSpec &ScopeSpec,
3052 const DeclarationNameInfo &Id,
3053 OpenMPDirectiveKind Kind) {
3054 LookupResult Lookup(*this, Id, LookupOrdinaryName);
3055 LookupParsedName(R&: Lookup, S: CurScope, SS: &ScopeSpec, AllowBuiltinCreation: true);
3056
3057 if (Lookup.isAmbiguous())
3058 return ExprError();
3059
3060 VarDecl *VD;
3061 if (!Lookup.isSingleResult()) {
3062 VarDeclFilterCCC CCC(*this);
3063 if (TypoCorrection Corrected =
3064 CorrectTypo(Typo: Id, LookupKind: LookupOrdinaryName, S: CurScope, SS: nullptr, CCC,
3065 Mode: CTK_ErrorRecovery)) {
3066 diagnoseTypo(Corrected,
3067 PDiag(Lookup.empty()
3068 ? diag::err_undeclared_var_use_suggest
3069 : diag::err_omp_expected_var_arg_suggest)
3070 << Id.getName());
3071 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3072 } else {
3073 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3074 : diag::err_omp_expected_var_arg)
3075 << Id.getName();
3076 return ExprError();
3077 }
3078 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3079 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3080 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3081 return ExprError();
3082 }
3083 Lookup.suppressDiagnostics();
3084
3085 // OpenMP [2.9.2, Syntax, C/C++]
3086 // Variables must be file-scope, namespace-scope, or static block-scope.
3087 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3088 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3089 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3090 bool IsDecl =
3091 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3092 Diag(VD->getLocation(),
3093 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3094 << VD;
3095 return ExprError();
3096 }
3097
3098 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3099 NamedDecl *ND = CanonicalVD;
3100 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3101 // A threadprivate directive for file-scope variables must appear outside
3102 // any definition or declaration.
3103 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3104 !getCurLexicalContext()->isTranslationUnit()) {
3105 Diag(Id.getLoc(), diag::err_omp_var_scope)
3106 << getOpenMPDirectiveName(Kind) << VD;
3107 bool IsDecl =
3108 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3109 Diag(VD->getLocation(),
3110 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3111 << VD;
3112 return ExprError();
3113 }
3114 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3115 // A threadprivate directive for static class member variables must appear
3116 // in the class definition, in the same scope in which the member
3117 // variables are declared.
3118 if (CanonicalVD->isStaticDataMember() &&
3119 !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
3120 Diag(Id.getLoc(), diag::err_omp_var_scope)
3121 << getOpenMPDirectiveName(Kind) << VD;
3122 bool IsDecl =
3123 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3124 Diag(VD->getLocation(),
3125 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3126 << VD;
3127 return ExprError();
3128 }
3129 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3130 // A threadprivate directive for namespace-scope variables must appear
3131 // outside any definition or declaration other than the namespace
3132 // definition itself.
3133 if (CanonicalVD->getDeclContext()->isNamespace() &&
3134 (!getCurLexicalContext()->isFileContext() ||
3135 !getCurLexicalContext()->Encloses(DC: CanonicalVD->getDeclContext()))) {
3136 Diag(Id.getLoc(), diag::err_omp_var_scope)
3137 << getOpenMPDirectiveName(Kind) << VD;
3138 bool IsDecl =
3139 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3140 Diag(VD->getLocation(),
3141 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3142 << VD;
3143 return ExprError();
3144 }
3145 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3146 // A threadprivate directive for static block-scope variables must appear
3147 // in the scope of the variable and not in a nested scope.
3148 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3149 !isDeclInScope(D: ND, Ctx: getCurLexicalContext(), S: CurScope)) {
3150 Diag(Id.getLoc(), diag::err_omp_var_scope)
3151 << getOpenMPDirectiveName(Kind) << VD;
3152 bool IsDecl =
3153 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3154 Diag(VD->getLocation(),
3155 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3156 << VD;
3157 return ExprError();
3158 }
3159
3160 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3161 // A threadprivate directive must lexically precede all references to any
3162 // of the variables in its list.
3163 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3164 !DSAStack->isThreadPrivate(VD)) {
3165 Diag(Id.getLoc(), diag::err_omp_var_used)
3166 << getOpenMPDirectiveName(Kind) << VD;
3167 return ExprError();
3168 }
3169
3170 QualType ExprType = VD->getType().getNonReferenceType();
3171 return DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
3172 SourceLocation(), VD,
3173 /*RefersToEnclosingVariableOrCapture=*/false,
3174 Id.getLoc(), ExprType, VK_LValue);
3175}
3176
3177Sema::DeclGroupPtrTy
3178Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3179 ArrayRef<Expr *> VarList) {
3180 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3181 CurContext->addDecl(D);
3182 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3183 }
3184 return nullptr;
3185}
3186
3187namespace {
3188class LocalVarRefChecker final
3189 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3190 Sema &SemaRef;
3191
3192public:
3193 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3194 if (const auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
3195 if (VD->hasLocalStorage()) {
3196 SemaRef.Diag(E->getBeginLoc(),
3197 diag::err_omp_local_var_in_threadprivate_init)
3198 << E->getSourceRange();
3199 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3200 << VD << VD->getSourceRange();
3201 return true;
3202 }
3203 }
3204 return false;
3205 }
3206 bool VisitStmt(const Stmt *S) {
3207 for (const Stmt *Child : S->children()) {
3208 if (Child && Visit(Child))
3209 return true;
3210 }
3211 return false;
3212 }
3213 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3214};
3215} // namespace
3216
3217OMPThreadPrivateDecl *
3218Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
3219 SmallVector<Expr *, 8> Vars;
3220 for (Expr *RefExpr : VarList) {
3221 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3222 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3223 SourceLocation ILoc = DE->getExprLoc();
3224
3225 // Mark variable as used.
3226 VD->setReferenced();
3227 VD->markUsed(Context);
3228
3229 QualType QType = VD->getType();
3230 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3231 // It will be analyzed later.
3232 Vars.push_back(DE);
3233 continue;
3234 }
3235
3236 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3237 // A threadprivate variable must not have an incomplete type.
3238 if (RequireCompleteType(ILoc, VD->getType(),
3239 diag::err_omp_threadprivate_incomplete_type)) {
3240 continue;
3241 }
3242
3243 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3244 // A threadprivate variable must not have a reference type.
3245 if (VD->getType()->isReferenceType()) {
3246 Diag(ILoc, diag::err_omp_ref_type_arg)
3247 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3248 bool IsDecl =
3249 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3250 Diag(VD->getLocation(),
3251 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3252 << VD;
3253 continue;
3254 }
3255
3256 // Check if this is a TLS variable. If TLS is not being supported, produce
3257 // the corresponding diagnostic.
3258 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3259 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3260 getLangOpts().OpenMPUseTLS &&
3261 getASTContext().getTargetInfo().isTLSSupported())) ||
3262 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3263 !VD->isLocalVarDecl())) {
3264 Diag(ILoc, diag::err_omp_var_thread_local)
3265 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3266 bool IsDecl =
3267 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3268 Diag(VD->getLocation(),
3269 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3270 << VD;
3271 continue;
3272 }
3273
3274 // Check if initial value of threadprivate variable reference variable with
3275 // local storage (it is not supported by runtime).
3276 if (const Expr *Init = VD->getAnyInitializer()) {
3277 LocalVarRefChecker Checker(*this);
3278 if (Checker.Visit(Init))
3279 continue;
3280 }
3281
3282 Vars.push_back(Elt: RefExpr);
3283 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3284 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3285 Context, SourceRange(Loc, Loc)));
3286 if (ASTMutationListener *ML = Context.getASTMutationListener())
3287 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3288 }
3289 OMPThreadPrivateDecl *D = nullptr;
3290 if (!Vars.empty()) {
3291 D = OMPThreadPrivateDecl::Create(C&: Context, DC: getCurLexicalContext(), L: Loc,
3292 VL: Vars);
3293 D->setAccess(AS_public);
3294 }
3295 return D;
3296}
3297
3298static OMPAllocateDeclAttr::AllocatorTypeTy
3299getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3300 if (!Allocator)
3301 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3302 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3303 Allocator->isInstantiationDependent() ||
3304 Allocator->containsUnexpandedParameterPack())
3305 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3306 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3307 llvm::FoldingSetNodeID AEId;
3308 const Expr *AE = Allocator->IgnoreParenImpCasts();
3309 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3310 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3311 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3312 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3313 llvm::FoldingSetNodeID DAEId;
3314 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3315 /*Canonical=*/true);
3316 if (AEId == DAEId) {
3317 AllocatorKindRes = AllocatorKind;
3318 break;
3319 }
3320 }
3321 return AllocatorKindRes;
3322}
3323
3324static bool checkPreviousOMPAllocateAttribute(
3325 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3326 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3327 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3328 return false;
3329 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3330 Expr *PrevAllocator = A->getAllocator();
3331 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3332 getAllocatorKind(S, Stack, PrevAllocator);
3333 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3334 if (AllocatorsMatch &&
3335 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3336 Allocator && PrevAllocator) {
3337 const Expr *AE = Allocator->IgnoreParenImpCasts();
3338 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3339 llvm::FoldingSetNodeID AEId, PAEId;
3340 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3341 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3342 AllocatorsMatch = AEId == PAEId;
3343 }
3344 if (!AllocatorsMatch) {
3345 SmallString<256> AllocatorBuffer;
3346 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3347 if (Allocator)
3348 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3349 SmallString<256> PrevAllocatorBuffer;
3350 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3351 if (PrevAllocator)
3352 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3353 S.getPrintingPolicy());
3354
3355 SourceLocation AllocatorLoc =
3356 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3357 SourceRange AllocatorRange =
3358 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3359 SourceLocation PrevAllocatorLoc =
3360 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3361 SourceRange PrevAllocatorRange =
3362 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3363 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3364 << (Allocator ? 1 : 0) << AllocatorStream.str()
3365 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3366 << AllocatorRange;
3367 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3368 << PrevAllocatorRange;
3369 return true;
3370 }
3371 return false;
3372}
3373
3374static void
3375applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3376 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3377 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3378 if (VD->hasAttr<OMPAllocateDeclAttr>())
3379 return;
3380 if (Alignment &&
3381 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3382 Alignment->isInstantiationDependent() ||
3383 Alignment->containsUnexpandedParameterPack()))
3384 // Apply later when we have a usable value.
3385 return;
3386 if (Allocator &&
3387 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3388 Allocator->isInstantiationDependent() ||
3389 Allocator->containsUnexpandedParameterPack()))
3390 return;
3391 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3392 Allocator, Alignment, SR);
3393 VD->addAttr(A: A);
3394 if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3395 ML->DeclarationMarkedOpenMPAllocate(D: VD, A: A);
3396}
3397
3398Sema::DeclGroupPtrTy
3399Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef<Expr *> VarList,
3400 ArrayRef<OMPClause *> Clauses,
3401 DeclContext *Owner) {
3402 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3403 Expr *Alignment = nullptr;
3404 Expr *Allocator = nullptr;
3405 if (Clauses.empty()) {
3406 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3407 // allocate directives that appear in a target region must specify an
3408 // allocator clause unless a requires directive with the dynamic_allocators
3409 // clause is present in the same compilation unit.
3410 if (LangOpts.OpenMPIsTargetDevice &&
3411 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3412 targetDiag(Loc, diag::err_expected_allocator_clause);
3413 } else {
3414 for (const OMPClause *C : Clauses)
3415 if (const auto *AC = dyn_cast<OMPAllocatorClause>(Val: C))
3416 Allocator = AC->getAllocator();
3417 else if (const auto *AC = dyn_cast<OMPAlignClause>(Val: C))
3418 Alignment = AC->getAlignment();
3419 else
3420 llvm_unreachable("Unexpected clause on allocate directive");
3421 }
3422 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3423 getAllocatorKind(*this, DSAStack, Allocator);
3424 SmallVector<Expr *, 8> Vars;
3425 for (Expr *RefExpr : VarList) {
3426 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3427 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3428
3429 // Check if this is a TLS variable or global register.
3430 if (VD->getTLSKind() != VarDecl::TLS_None ||
3431 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3432 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3433 !VD->isLocalVarDecl()))
3434 continue;
3435
3436 // If the used several times in the allocate directive, the same allocator
3437 // must be used.
3438 if (checkPreviousOMPAllocateAttribute(*this, DSAStack, RefExpr, VD,
3439 AllocatorKind, Allocator))
3440 continue;
3441
3442 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3443 // If a list item has a static storage type, the allocator expression in the
3444 // allocator clause must be a constant expression that evaluates to one of
3445 // the predefined memory allocator values.
3446 if (Allocator && VD->hasGlobalStorage()) {
3447 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3448 Diag(Allocator->getExprLoc(),
3449 diag::err_omp_expected_predefined_allocator)
3450 << Allocator->getSourceRange();
3451 bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
3452 VarDecl::DeclarationOnly;
3453 Diag(VD->getLocation(),
3454 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3455 << VD;
3456 continue;
3457 }
3458 }
3459
3460 Vars.push_back(Elt: RefExpr);
3461 applyOMPAllocateAttribute(*this, VD, AllocatorKind, Allocator, Alignment,
3462 DE->getSourceRange());
3463 }
3464 if (Vars.empty())
3465 return nullptr;
3466 if (!Owner)
3467 Owner = getCurLexicalContext();
3468 auto *D = OMPAllocateDecl::Create(C&: Context, DC: Owner, L: Loc, VL: Vars, CL: Clauses);
3469 D->setAccess(AS_public);
3470 Owner->addDecl(D);
3471 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3472}
3473
3474Sema::DeclGroupPtrTy
3475Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3476 ArrayRef<OMPClause *> ClauseList) {
3477 OMPRequiresDecl *D = nullptr;
3478 if (!CurContext->isFileContext()) {
3479 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3480 } else {
3481 D = CheckOMPRequiresDecl(Loc, Clauses: ClauseList);
3482 if (D) {
3483 CurContext->addDecl(D);
3484 DSAStack->addRequiresDecl(RD: D);
3485 }
3486 }
3487 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3488}
3489
3490void Sema::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3491 OpenMPDirectiveKind DKind,
3492 ArrayRef<std::string> Assumptions,
3493 bool SkippedClauses) {
3494 if (!SkippedClauses && Assumptions.empty())
3495 Diag(Loc, diag::err_omp_no_clause_for_directive)
3496 << llvm::omp::getAllAssumeClauseOptions()
3497 << llvm::omp::getOpenMPDirectiveName(DKind);
3498
3499 auto *AA = AssumptionAttr::Create(Context, llvm::join(Assumptions, ","), Loc);
3500 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3501 OMPAssumeScoped.push_back(AA);
3502 return;
3503 }
3504
3505 // Global assumes without assumption clauses are ignored.
3506 if (Assumptions.empty())
3507 return;
3508
3509 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3510 "Unexpected omp assumption directive!");
3511 OMPAssumeGlobal.push_back(AA);
3512
3513 // The OMPAssumeGlobal scope above will take care of new declarations but
3514 // we also want to apply the assumption to existing ones, e.g., to
3515 // declarations in included headers. To this end, we traverse all existing
3516 // declaration contexts and annotate function declarations here.
3517 SmallVector<DeclContext *, 8> DeclContexts;
3518 auto *Ctx = CurContext;
3519 while (Ctx->getLexicalParent())
3520 Ctx = Ctx->getLexicalParent();
3521 DeclContexts.push_back(Elt: Ctx);
3522 while (!DeclContexts.empty()) {
3523 DeclContext *DC = DeclContexts.pop_back_val();
3524 for (auto *SubDC : DC->decls()) {
3525 if (SubDC->isInvalidDecl())
3526 continue;
3527 if (auto *CTD = dyn_cast<ClassTemplateDecl>(Val: SubDC)) {
3528 DeclContexts.push_back(CTD->getTemplatedDecl());
3529 llvm::append_range(C&: DeclContexts, R: CTD->specializations());
3530 continue;
3531 }
3532 if (auto *DC = dyn_cast<DeclContext>(Val: SubDC))
3533 DeclContexts.push_back(Elt: DC);
3534 if (auto *F = dyn_cast<FunctionDecl>(Val: SubDC)) {
3535 F->addAttr(A: AA);
3536 continue;
3537 }
3538 }
3539 }
3540}
3541
3542void Sema::ActOnOpenMPEndAssumesDirective() {
3543 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3544 OMPAssumeScoped.pop_back();
3545}
3546
3547OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc,
3548 ArrayRef<OMPClause *> ClauseList) {
3549 /// For target specific clauses, the requires directive cannot be
3550 /// specified after the handling of any of the target regions in the
3551 /// current compilation unit.
3552 ArrayRef<SourceLocation> TargetLocations =
3553 DSAStack->getEncounteredTargetLocs();
3554 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3555 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3556 for (const OMPClause *CNew : ClauseList) {
3557 // Check if any of the requires clauses affect target regions.
3558 if (isa<OMPUnifiedSharedMemoryClause>(Val: CNew) ||
3559 isa<OMPUnifiedAddressClause>(Val: CNew) ||
3560 isa<OMPReverseOffloadClause>(Val: CNew) ||
3561 isa<OMPDynamicAllocatorsClause>(Val: CNew)) {
3562 Diag(Loc, diag::err_omp_directive_before_requires)
3563 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3564 for (SourceLocation TargetLoc : TargetLocations) {
3565 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3566 << "target";
3567 }
3568 } else if (!AtomicLoc.isInvalid() &&
3569 isa<OMPAtomicDefaultMemOrderClause>(Val: CNew)) {
3570 Diag(Loc, diag::err_omp_directive_before_requires)
3571 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3572 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3573 << "atomic";
3574 }
3575 }
3576 }
3577
3578 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3579 return OMPRequiresDecl::Create(C&: Context, DC: getCurLexicalContext(), L: Loc,
3580 CL: ClauseList);
3581 return nullptr;
3582}
3583
3584static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3585 const ValueDecl *D,
3586 const DSAStackTy::DSAVarData &DVar,
3587 bool IsLoopIterVar) {
3588 if (DVar.RefExpr) {
3589 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3590 << getOpenMPClauseName(DVar.CKind);
3591 return;
3592 }
3593 enum {
3594 PDSA_StaticMemberShared,
3595 PDSA_StaticLocalVarShared,
3596 PDSA_LoopIterVarPrivate,
3597 PDSA_LoopIterVarLinear,
3598 PDSA_LoopIterVarLastprivate,
3599 PDSA_ConstVarShared,
3600 PDSA_GlobalVarShared,
3601 PDSA_TaskVarFirstprivate,
3602 PDSA_LocalVarPrivate,
3603 PDSA_Implicit
3604 } Reason = PDSA_Implicit;
3605 bool ReportHint = false;
3606 auto ReportLoc = D->getLocation();
3607 auto *VD = dyn_cast<VarDecl>(Val: D);
3608 if (IsLoopIterVar) {
3609 if (DVar.CKind == OMPC_private)
3610 Reason = PDSA_LoopIterVarPrivate;
3611 else if (DVar.CKind == OMPC_lastprivate)
3612 Reason = PDSA_LoopIterVarLastprivate;
3613 else
3614 Reason = PDSA_LoopIterVarLinear;
3615 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3616 DVar.CKind == OMPC_firstprivate) {
3617 Reason = PDSA_TaskVarFirstprivate;
3618 ReportLoc = DVar.ImplicitDSALoc;
3619 } else if (VD && VD->isStaticLocal())
3620 Reason = PDSA_StaticLocalVarShared;
3621 else if (VD && VD->isStaticDataMember())
3622 Reason = PDSA_StaticMemberShared;
3623 else if (VD && VD->isFileVarDecl())
3624 Reason = PDSA_GlobalVarShared;
3625 else if (D->getType().isConstant(Ctx: SemaRef.getASTContext()))
3626 Reason = PDSA_ConstVarShared;
3627 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3628 ReportHint = true;
3629 Reason = PDSA_LocalVarPrivate;
3630 }
3631 if (Reason != PDSA_Implicit) {
3632 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3633 << Reason << ReportHint
3634 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3635 } else if (DVar.ImplicitDSALoc.isValid()) {
3636 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3637 << getOpenMPClauseName(DVar.CKind);
3638 }
3639}
3640
3641static OpenMPMapClauseKind
3642getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
3643 bool IsAggregateOrDeclareTarget) {
3644 OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
3645 switch (M) {
3646 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3647 Kind = OMPC_MAP_alloc;
3648 break;
3649 case OMPC_DEFAULTMAP_MODIFIER_to:
3650 Kind = OMPC_MAP_to;
3651 break;
3652 case OMPC_DEFAULTMAP_MODIFIER_from:
3653 Kind = OMPC_MAP_from;
3654 break;
3655 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3656 Kind = OMPC_MAP_tofrom;
3657 break;
3658 case OMPC_DEFAULTMAP_MODIFIER_present:
3659 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3660 // If implicit-behavior is present, each variable referenced in the
3661 // construct in the category specified by variable-category is treated as if
3662 // it had been listed in a map clause with the map-type of alloc and
3663 // map-type-modifier of present.
3664 Kind = OMPC_MAP_alloc;
3665 break;
3666 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3667 case OMPC_DEFAULTMAP_MODIFIER_last:
3668 llvm_unreachable("Unexpected defaultmap implicit behavior");
3669 case OMPC_DEFAULTMAP_MODIFIER_none:
3670 case OMPC_DEFAULTMAP_MODIFIER_default:
3671 case OMPC_DEFAULTMAP_MODIFIER_unknown:
3672 // IsAggregateOrDeclareTarget could be true if:
3673 // 1. the implicit behavior for aggregate is tofrom
3674 // 2. it's a declare target link
3675 if (IsAggregateOrDeclareTarget) {
3676 Kind = OMPC_MAP_tofrom;
3677 break;
3678 }
3679 llvm_unreachable("Unexpected defaultmap implicit behavior");
3680 }
3681 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3682 return Kind;
3683}
3684
3685namespace {
3686class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3687 DSAStackTy *Stack;
3688 Sema &SemaRef;
3689 bool ErrorFound = false;
3690 bool TryCaptureCXXThisMembers = false;
3691 CapturedStmt *CS = nullptr;
3692 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3693 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3694 llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3695 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3696 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3697 ImplicitMapModifier[DefaultmapKindNum];
3698 Sema::VarsWithInheritedDSAType VarsWithInheritedDSA;
3699 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3700
3701 void VisitSubCaptures(OMPExecutableDirective *S) {
3702 // Check implicitly captured variables.
3703 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3704 return;
3705 if (S->getDirectiveKind() == OMPD_atomic ||
3706 S->getDirectiveKind() == OMPD_critical ||
3707 S->getDirectiveKind() == OMPD_section ||
3708 S->getDirectiveKind() == OMPD_master ||
3709 S->getDirectiveKind() == OMPD_masked ||
3710 S->getDirectiveKind() == OMPD_scope ||
3711 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3712 Visit(S->getAssociatedStmt());
3713 return;
3714 }
3715 visitSubCaptures(S: S->getInnermostCapturedStmt());
3716 // Try to capture inner this->member references to generate correct mappings
3717 // and diagnostics.
3718 if (TryCaptureCXXThisMembers ||
3719 (isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective()) &&
3720 llvm::any_of(Range: S->getInnermostCapturedStmt()->captures(),
3721 P: [](const CapturedStmt::Capture &C) {
3722 return C.capturesThis();
3723 }))) {
3724 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3725 TryCaptureCXXThisMembers = true;
3726 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3727 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3728 }
3729 // In tasks firstprivates are not captured anymore, need to analyze them
3730 // explicitly.
3731 if (isOpenMPTaskingDirective(Kind: S->getDirectiveKind()) &&
3732 !isOpenMPTaskLoopDirective(DKind: S->getDirectiveKind())) {
3733 for (OMPClause *C : S->clauses())
3734 if (auto *FC = dyn_cast<OMPFirstprivateClause>(Val: C)) {
3735 for (Expr *Ref : FC->varlists())
3736 Visit(Ref);
3737 }
3738 }
3739 }
3740
3741public:
3742 void VisitDeclRefExpr(DeclRefExpr *E) {
3743 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3744 E->isValueDependent() || E->containsUnexpandedParameterPack() ||
3745 E->isInstantiationDependent())
3746 return;
3747 if (auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
3748 // Check the datasharing rules for the expressions in the clauses.
3749 if (!CS || (isa<OMPCapturedExprDecl>(Val: VD) && !CS->capturesVariable(Var: VD) &&
3750 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3751 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3752 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: VD))
3753 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3754 Visit(CED->getInit());
3755 return;
3756 }
3757 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(Val: VD))
3758 // Do not analyze internal variables and do not enclose them into
3759 // implicit clauses.
3760 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3761 return;
3762 VD = VD->getCanonicalDecl();
3763 // Skip internally declared variables.
3764 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(Var: VD) &&
3765 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3766 !Stack->isImplicitTaskFirstprivate(VD))
3767 return;
3768 // Skip allocators in uses_allocators clauses.
3769 if (Stack->isUsesAllocatorsDecl(VD))
3770 return;
3771
3772 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3773 // Check if the variable has explicit DSA set and stop analysis if it so.
3774 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3775 return;
3776
3777 // Skip internally declared static variables.
3778 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3779 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3780 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3781 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3782 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3783 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3784 !Stack->isImplicitTaskFirstprivate(VD))
3785 return;
3786
3787 SourceLocation ELoc = E->getExprLoc();
3788 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3789 // The default(none) clause requires that each variable that is referenced
3790 // in the construct, and does not have a predetermined data-sharing
3791 // attribute, must have its data-sharing attribute explicitly determined
3792 // by being listed in a data-sharing attribute clause.
3793 if (DVar.CKind == OMPC_unknown &&
3794 (Stack->getDefaultDSA() == DSA_none ||
3795 Stack->getDefaultDSA() == DSA_private ||
3796 Stack->getDefaultDSA() == DSA_firstprivate) &&
3797 isImplicitOrExplicitTaskingRegion(DKind) &&
3798 VarsWithInheritedDSA.count(VD) == 0) {
3799 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3800 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3801 Stack->getDefaultDSA() == DSA_private)) {
3802 DSAStackTy::DSAVarData DVar =
3803 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3804 InheritedDSA = DVar.CKind == OMPC_unknown;
3805 }
3806 if (InheritedDSA)
3807 VarsWithInheritedDSA[VD] = E;
3808 if (Stack->getDefaultDSA() == DSA_none)
3809 return;
3810 }
3811
3812 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3813 // If implicit-behavior is none, each variable referenced in the
3814 // construct that does not have a predetermined data-sharing attribute
3815 // and does not appear in a to or link clause on a declare target
3816 // directive must be listed in a data-mapping attribute clause, a
3817 // data-sharing attribute clause (including a data-sharing attribute
3818 // clause on a combined construct where target. is one of the
3819 // constituent constructs), or an is_device_ptr clause.
3820 OpenMPDefaultmapClauseKind ClauseKind =
3821 getVariableCategoryFromDecl(SemaRef.getLangOpts(), VD);
3822 if (SemaRef.getLangOpts().OpenMP >= 50) {
3823 bool IsModifierNone = Stack->getDefaultmapModifier(Kind: ClauseKind) ==
3824 OMPC_DEFAULTMAP_MODIFIER_none;
3825 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3826 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3827 // Only check for data-mapping attribute and is_device_ptr here
3828 // since we have already make sure that the declaration does not
3829 // have a data-sharing attribute above
3830 if (!Stack->checkMappableExprComponentListsForDecl(
3831 VD, /*CurrentRegionOnly=*/true,
3832 [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
3833 MapExprComponents,
3834 OpenMPClauseKind) {
3835 auto MI = MapExprComponents.rbegin();
3836 auto ME = MapExprComponents.rend();
3837 return MI != ME && MI->getAssociatedDeclaration() == VD;
3838 })) {
3839 VarsWithInheritedDSA[VD] = E;
3840 return;
3841 }
3842 }
3843 }
3844 if (SemaRef.getLangOpts().OpenMP > 50) {
3845 bool IsModifierPresent = Stack->getDefaultmapModifier(Kind: ClauseKind) ==
3846 OMPC_DEFAULTMAP_MODIFIER_present;
3847 if (IsModifierPresent) {
3848 if (!llvm::is_contained(Range&: ImplicitMapModifier[ClauseKind],
3849 Element: OMPC_MAP_MODIFIER_present)) {
3850 ImplicitMapModifier[ClauseKind].push_back(
3851 Elt: OMPC_MAP_MODIFIER_present);
3852 }
3853 }
3854 }
3855
3856 if (isOpenMPTargetExecutionDirective(DKind) &&
3857 !Stack->isLoopControlVariable(VD).first) {
3858 if (!Stack->checkMappableExprComponentListsForDecl(
3859 VD, /*CurrentRegionOnly=*/true,
3860 [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
3861 StackComponents,
3862 OpenMPClauseKind) {
3863 if (SemaRef.LangOpts.OpenMP >= 50)
3864 return !StackComponents.empty();
3865 // Variable is used if it has been marked as an array, array
3866 // section, array shaping or the variable iself.
3867 return StackComponents.size() == 1 ||
3868 llvm::all_of(
3869 Range: llvm::drop_begin(RangeOrContainer: llvm::reverse(C&: StackComponents)),
3870 P: [](const OMPClauseMappableExprCommon::
3871 MappableComponent &MC) {
3872 return MC.getAssociatedDeclaration() ==
3873 nullptr &&
3874 (isa<OMPArraySectionExpr>(
3875 Val: MC.getAssociatedExpression()) ||
3876 isa<OMPArrayShapingExpr>(
3877 Val: MC.getAssociatedExpression()) ||
3878 isa<ArraySubscriptExpr>(
3879 Val: MC.getAssociatedExpression()));
3880 });
3881 })) {
3882 bool IsFirstprivate = false;
3883 // By default lambdas are captured as firstprivates.
3884 if (const auto *RD =
3885 VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
3886 IsFirstprivate = RD->isLambda();
3887 IsFirstprivate =
3888 IsFirstprivate || (Stack->mustBeFirstprivate(Kind: ClauseKind) && !Res);
3889 if (IsFirstprivate) {
3890 ImplicitFirstprivate.emplace_back(Args&: E);
3891 } else {
3892 OpenMPDefaultmapClauseModifier M =
3893 Stack->getDefaultmapModifier(Kind: ClauseKind);
3894 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3895 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3896 ImplicitMap[ClauseKind][Kind].emplace_back(Args&: E);
3897 }
3898 return;
3899 }
3900 }
3901
3902 // OpenMP [2.9.3.6, Restrictions, p.2]
3903 // A list item that appears in a reduction clause of the innermost
3904 // enclosing worksharing or parallel construct may not be accessed in an
3905 // explicit task.
3906 DVar = Stack->hasInnermostDSA(
3907 VD,
3908 [](OpenMPClauseKind C, bool AppliedToPointee) {
3909 return C == OMPC_reduction && !AppliedToPointee;
3910 },
3911 [](OpenMPDirectiveKind K) {
3912 return isOpenMPParallelDirective(DKind: K) ||
3913 isOpenMPWorksharingDirective(DKind: K) || isOpenMPTeamsDirective(DKind: K);
3914 },
3915 /*FromParent=*/true);
3916 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3917 ErrorFound = true;
3918 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3919 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3920 return;
3921 }
3922
3923 // Define implicit data-sharing attributes for task.
3924 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3925 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3926 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3927 DVar.CKind == OMPC_firstprivate) ||
3928 (Stack->getDefaultDSA() == DSA_private &&
3929 DVar.CKind == OMPC_private)) &&
3930 !DVar.RefExpr)) &&
3931 !Stack->isLoopControlVariable(VD).first) {
3932 if (Stack->getDefaultDSA() == DSA_private)
3933 ImplicitPrivate.push_back(E);
3934 else
3935 ImplicitFirstprivate.push_back(E);
3936 return;
3937 }
3938
3939 // Store implicitly used globals with declare target link for parent
3940 // target.
3941 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3942 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3943 Stack->addToParentTargetRegionLinkGlobals(E);
3944 return;
3945 }
3946 }
3947 }
3948 void VisitMemberExpr(MemberExpr *E) {
3949 if (E->isTypeDependent() || E->isValueDependent() ||
3950 E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
3951 return;
3952 auto *FD = dyn_cast<FieldDecl>(Val: E->getMemberDecl());
3953 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3954 if (auto *TE = dyn_cast<CXXThisExpr>(Val: E->getBase()->IgnoreParenCasts())) {
3955 if (!FD)
3956 return;
3957 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3958 // Check if the variable has explicit DSA set and stop analysis if it
3959 // so.
3960 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3961 return;
3962
3963 if (isOpenMPTargetExecutionDirective(DKind) &&
3964 !Stack->isLoopControlVariable(FD).first &&
3965 !Stack->checkMappableExprComponentListsForDecl(
3966 FD, /*CurrentRegionOnly=*/true,
3967 [](OMPClauseMappableExprCommon::MappableExprComponentListRef
3968 StackComponents,
3969 OpenMPClauseKind) {
3970 return isa<CXXThisExpr>(
3971 Val: cast<MemberExpr>(
3972 Val: StackComponents.back().getAssociatedExpression())
3973 ->getBase()
3974 ->IgnoreParens());
3975 })) {
3976 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
3977 // A bit-field cannot appear in a map clause.
3978 //
3979 if (FD->isBitField())
3980 return;
3981
3982 // Check to see if the member expression is referencing a class that
3983 // has already been explicitly mapped
3984 if (Stack->isClassPreviouslyMapped(QT: TE->getType()))
3985 return;
3986
3987 OpenMPDefaultmapClauseModifier Modifier =
3988 Stack->getDefaultmapModifier(Kind: OMPC_DEFAULTMAP_aggregate);
3989 OpenMPDefaultmapClauseKind ClauseKind =
3990 getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD);
3991 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3992 M: Modifier, /*IsAggregateOrDeclareTarget*/ true);
3993 ImplicitMap[ClauseKind][Kind].emplace_back(Args&: E);
3994 return;
3995 }
3996
3997 SourceLocation ELoc = E->getExprLoc();
3998 // OpenMP [2.9.3.6, Restrictions, p.2]
3999 // A list item that appears in a reduction clause of the innermost
4000 // enclosing worksharing or parallel construct may not be accessed in
4001 // an explicit task.
4002 DVar = Stack->hasInnermostDSA(
4003 FD,
4004 [](OpenMPClauseKind C, bool AppliedToPointee) {
4005 return C == OMPC_reduction && !AppliedToPointee;
4006 },
4007 [](OpenMPDirectiveKind K) {
4008 return isOpenMPParallelDirective(DKind: K) ||
4009 isOpenMPWorksharingDirective(DKind: K) || isOpenMPTeamsDirective(DKind: K);
4010 },
4011 /*FromParent=*/true);
4012 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4013 ErrorFound = true;
4014 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4015 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4016 return;
4017 }
4018
4019 // Define implicit data-sharing attributes for task.
4020 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4021 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4022 !Stack->isLoopControlVariable(FD).first) {
4023 // Check if there is a captured expression for the current field in the
4024 // region. Do not mark it as firstprivate unless there is no captured
4025 // expression.
4026 // TODO: try to make it firstprivate.
4027 if (DVar.CKind != OMPC_unknown)
4028 ImplicitFirstprivate.push_back(E);
4029 }
4030 return;
4031 }
4032 if (isOpenMPTargetExecutionDirective(DKind)) {
4033 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
4034 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4035 Stack->getCurrentDirective(),
4036 /*NoDiagnose=*/true))
4037 return;
4038 const auto *VD = cast<ValueDecl>(
4039 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4040 if (!Stack->checkMappableExprComponentListsForDecl(
4041 VD: VD, /*CurrentRegionOnly=*/true,
4042 Check: [&CurComponents](
4043 OMPClauseMappableExprCommon::MappableExprComponentListRef
4044 StackComponents,
4045 OpenMPClauseKind) {
4046 auto CCI = CurComponents.rbegin();
4047 auto CCE = CurComponents.rend();
4048 for (const auto &SC : llvm::reverse(C&: StackComponents)) {
4049 // Do both expressions have the same kind?
4050 if (CCI->getAssociatedExpression()->getStmtClass() !=
4051 SC.getAssociatedExpression()->getStmtClass())
4052 if (!((isa<OMPArraySectionExpr>(
4053 Val: SC.getAssociatedExpression()) ||
4054 isa<OMPArrayShapingExpr>(
4055 Val: SC.getAssociatedExpression())) &&
4056 isa<ArraySubscriptExpr>(
4057 Val: CCI->getAssociatedExpression())))
4058 return false;
4059
4060 const Decl *CCD = CCI->getAssociatedDeclaration();
4061 const Decl *SCD = SC.getAssociatedDeclaration();
4062 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4063 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4064 if (SCD != CCD)
4065 return false;
4066 std::advance(i&: CCI, n: 1);
4067 if (CCI == CCE)
4068 break;
4069 }
4070 return true;
4071 })) {
4072 Visit(E->getBase());
4073 }
4074 } else if (!TryCaptureCXXThisMembers) {
4075 Visit(E->getBase());
4076 }
4077 }
4078 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4079 for (OMPClause *C : S->clauses()) {
4080 // Skip analysis of arguments of private clauses for task|target
4081 // directives.
4082 if (isa_and_nonnull<OMPPrivateClause>(Val: C))
4083 continue;
4084 // Skip analysis of arguments of implicitly defined firstprivate clause
4085 // for task|target directives.
4086 // Skip analysis of arguments of implicitly defined map clause for target
4087 // directives.
4088 if (C && !((isa<OMPFirstprivateClause>(Val: C) || isa<OMPMapClause>(Val: C)) &&
4089 C->isImplicit() &&
4090 !isOpenMPTaskingDirective(Kind: Stack->getCurrentDirective()))) {
4091 for (Stmt *CC : C->children()) {
4092 if (CC)
4093 Visit(CC);
4094 }
4095 }
4096 }
4097 // Check implicitly captured variables.
4098 VisitSubCaptures(S);
4099 }
4100
4101 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4102 // Loop transformation directives do not introduce data sharing
4103 VisitStmt(S);
4104 }
4105
4106 void VisitCallExpr(CallExpr *S) {
4107 for (Stmt *C : S->arguments()) {
4108 if (C) {
4109 // Check implicitly captured variables in the task-based directives to
4110 // check if they must be firstprivatized.
4111 Visit(C);
4112 }
4113 }
4114 if (Expr *Callee = S->getCallee()) {
4115 auto *CI = Callee->IgnoreParenImpCasts();
4116 if (auto *CE = dyn_cast<MemberExpr>(Val: CI))
4117 Visit(CE->getBase());
4118 else if (auto *CE = dyn_cast<DeclRefExpr>(Val: CI))
4119 Visit(CE);
4120 }
4121 }
4122 void VisitStmt(Stmt *S) {
4123 for (Stmt *C : S->children()) {
4124 if (C) {
4125 // Check implicitly captured variables in the task-based directives to
4126 // check if they must be firstprivatized.
4127 Visit(C);
4128 }
4129 }
4130 }
4131
4132 void visitSubCaptures(CapturedStmt *S) {
4133 for (const CapturedStmt::Capture &Cap : S->captures()) {
4134 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4135 continue;
4136 VarDecl *VD = Cap.getCapturedVar();
4137 // Do not try to map the variable if it or its sub-component was mapped
4138 // already.
4139 if (isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective()) &&
4140 Stack->checkMappableExprComponentListsForDecl(
4141 VD, /*CurrentRegionOnly=*/true,
4142 [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4143 OpenMPClauseKind) { return true; }))
4144 continue;
4145 DeclRefExpr *DRE = buildDeclRefExpr(
4146 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4147 Cap.getLocation(), /*RefersToCapture=*/true);
4148 Visit(DRE);
4149 }
4150 }
4151 bool isErrorFound() const { return ErrorFound; }
4152 ArrayRef<Expr *> getImplicitFirstprivate() const {
4153 return ImplicitFirstprivate;
4154 }
4155 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
4156 ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind DK,
4157 OpenMPMapClauseKind MK) const {
4158 return ImplicitMap[DK][MK];
4159 }
4160 ArrayRef<OpenMPMapModifierKind>
4161 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4162 return ImplicitMapModifier[Kind];
4163 }
4164 const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4165 return VarsWithInheritedDSA;
4166 }
4167
4168 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4169 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4170 // Process declare target link variables for the target directives.
4171 if (isOpenMPTargetExecutionDirective(DKind: S->getCurrentDirective())) {
4172 for (DeclRefExpr *E : Stack->getLinkGlobals())
4173 Visit(E);
4174 }
4175 }
4176};
4177} // namespace
4178
4179static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4180 OpenMPDirectiveKind DKind,
4181 bool ScopeEntry) {
4182 SmallVector<llvm::omp::TraitProperty, 8> Traits;
4183 if (isOpenMPTargetExecutionDirective(DKind))
4184 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_target_target);
4185 if (isOpenMPTeamsDirective(DKind))
4186 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_teams_teams);
4187 if (isOpenMPParallelDirective(DKind))
4188 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_parallel_parallel);
4189 if (isOpenMPWorksharingDirective(DKind))
4190 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_for_for);
4191 if (isOpenMPSimdDirective(DKind))
4192 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_simd_simd);
4193 Stack->handleConstructTrait(Traits, ScopeEntry);
4194}
4195
4196void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
4197 switch (DKind) {
4198 case OMPD_parallel:
4199 case OMPD_parallel_for:
4200 case OMPD_parallel_for_simd:
4201 case OMPD_parallel_sections:
4202 case OMPD_parallel_master:
4203 case OMPD_parallel_masked:
4204 case OMPD_parallel_loop:
4205 case OMPD_teams:
4206 case OMPD_teams_distribute:
4207 case OMPD_teams_distribute_simd: {
4208 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(DestWidth: 32, Signed: 1).withConst();
4209 QualType KmpInt32PtrTy =
4210 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4211 Sema::CapturedParamNameType Params[] = {
4212 std::make_pair(x: ".global_tid.", y&: KmpInt32PtrTy),
4213 std::make_pair(x: ".bound_tid.", y&: KmpInt32PtrTy),
4214 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4215 };
4216 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, Kind: CR_OpenMP,
4217 Params);
4218 break;
4219 }
4220 case OMPD_target_teams:
4221 case OMPD_target_parallel:
4222 case OMPD_target_parallel_for:
4223 case OMPD_target_parallel_for_simd:
4224 case OMPD_target_parallel_loop:
4225 case OMPD_target_teams_distribute:
4226 case OMPD_target_teams_distribute_simd: {
4227 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(DestWidth: 32, Signed: 1).withConst();
4228 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4229 QualType KmpInt32PtrTy =
4230 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4231 QualType Args[] = {VoidPtrTy};
4232 FunctionProtoType::ExtProtoInfo EPI;
4233 EPI.Variadic = true;
4234 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4235 Sema::CapturedParamNameType Params[] = {
4236 std::make_pair(".global_tid.", KmpInt32Ty),
4237 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4238 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4239 std::make_pair(
4240 x: ".copy_fn.",
4241 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4242 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4243 std::make_pair(StringRef(), QualType()) // __context with shared vars
4244 };
4245 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4246 Params, /*OpenMPCaptureLevel=*/0);
4247 // Mark this captured region as inlined, because we don't use outlined
4248 // function directly.
4249 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4250 AlwaysInlineAttr::CreateImplicit(
4251 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4252 SmallVector<Sema::CapturedParamNameType, 2> ParamsTarget;
4253 if (getLangOpts().OpenMPIsTargetDevice)
4254 ParamsTarget.push_back(Elt: std::make_pair(x: StringRef("dyn_ptr"), y&: VoidPtrTy));
4255 ParamsTarget.push_back(
4256 Elt: std::make_pair(StringRef(), QualType())); // __context with shared vars;
4257 // Start a captured region for 'target' with no implicit parameters.
4258 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, Kind: CR_OpenMP,
4259 Params: ParamsTarget,
4260 /*OpenMPCaptureLevel=*/1);
4261 Sema::CapturedParamNameType ParamsTeamsOrParallel[] = {
4262 std::make_pair(".global_tid.", KmpInt32PtrTy),
4263 std::make_pair(x: ".bound_tid.", y&: KmpInt32PtrTy),
4264 std::make_pair(StringRef(), QualType()) // __context with shared vars
4265 };
4266 // Start a captured region for 'teams' or 'parallel'. Both regions have
4267 // the same implicit parameters.
4268 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4269 ParamsTeamsOrParallel, /*OpenMPCaptureLevel=*/2);
4270 break;
4271 }
4272 case OMPD_target:
4273 case OMPD_target_simd: {
4274 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(DestWidth: 32, Signed: 1).withConst();
4275 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4276 QualType KmpInt32PtrTy =
4277 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4278 QualType Args[] = {VoidPtrTy};
4279 FunctionProtoType::ExtProtoInfo EPI;
4280 EPI.Variadic = true;
4281 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4282 Sema::CapturedParamNameType Params[] = {
4283 std::make_pair(".global_tid.", KmpInt32Ty),
4284 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4285 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4286 std::make_pair(
4287 x: ".copy_fn.",
4288 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4289 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4290 std::make_pair(StringRef(), QualType()) // __context with shared vars
4291 };
4292 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4293 Params, /*OpenMPCaptureLevel=*/0);
4294 // Mark this captured region as inlined, because we don't use outlined
4295 // function directly.
4296 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4297 AlwaysInlineAttr::CreateImplicit(
4298 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4299 SmallVector<Sema::CapturedParamNameType, 2> ParamsTarget;
4300 if (getLangOpts().OpenMPIsTargetDevice)
4301 ParamsTarget.push_back(Elt: std::make_pair(x: StringRef("dyn_ptr"), y&: VoidPtrTy));
4302 ParamsTarget.push_back(
4303 Elt: std::make_pair(StringRef(), QualType())); // __context with shared vars;
4304 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, Kind: CR_OpenMP,
4305 Params: ParamsTarget,
4306 /*OpenMPCaptureLevel=*/1);
4307 break;
4308 }
4309 case OMPD_atomic:
4310 case OMPD_critical:
4311 case OMPD_section:
4312 case OMPD_master:
4313 case OMPD_masked:
4314 case OMPD_tile:
4315 case OMPD_unroll:
4316 break;
4317 case OMPD_loop:
4318 // TODO: 'loop' may require additional parameters depending on the binding.
4319 // Treat similar to OMPD_simd/OMPD_for for now.
4320 case OMPD_simd:
4321 case OMPD_for:
4322 case OMPD_for_simd:
4323 case OMPD_sections:
4324 case OMPD_single:
4325 case OMPD_taskgroup:
4326 case OMPD_distribute:
4327 case OMPD_distribute_simd:
4328 case OMPD_ordered:
4329 case OMPD_scope:
4330 case OMPD_target_data:
4331 case OMPD_dispatch: {
4332 Sema::CapturedParamNameType Params[] = {
4333 std::make_pair(StringRef(), QualType()) // __context with shared vars
4334 };
4335 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4336 Params);
4337 break;
4338 }
4339 case OMPD_task: {
4340 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(DestWidth: 32, Signed: 1).withConst();
4341 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4342 QualType KmpInt32PtrTy =
4343 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4344 QualType Args[] = {VoidPtrTy};
4345 FunctionProtoType::ExtProtoInfo EPI;
4346 EPI.Variadic = true;
4347 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4348 Sema::CapturedParamNameType Params[] = {
4349 std::make_pair(".global_tid.", KmpInt32Ty),
4350 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4351 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4352 std::make_pair(
4353 x: ".copy_fn.",
4354 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4355 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4356 std::make_pair(StringRef(), QualType()) // __context with shared vars
4357 };
4358 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4359 Params);
4360 // Mark this captured region as inlined, because we don't use outlined
4361 // function directly.
4362 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4363 AlwaysInlineAttr::CreateImplicit(
4364 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4365 break;
4366 }
4367 case OMPD_taskloop:
4368 case OMPD_taskloop_simd:
4369 case OMPD_master_taskloop:
4370 case OMPD_masked_taskloop:
4371 case OMPD_masked_taskloop_simd:
4372 case OMPD_master_taskloop_simd: {
4373 QualType KmpInt32Ty =
4374 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4375 .withConst();
4376 QualType KmpUInt64Ty =
4377 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4378 .withConst();
4379 QualType KmpInt64Ty =
4380 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4381 .withConst();
4382 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4383 QualType KmpInt32PtrTy =
4384 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4385 QualType Args[] = {VoidPtrTy};
4386 FunctionProtoType::ExtProtoInfo EPI;
4387 EPI.Variadic = true;
4388 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4389 Sema::CapturedParamNameType Params[] = {
4390 std::make_pair(".global_tid.", KmpInt32Ty),
4391 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4392 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4393 std::make_pair(
4394 x: ".copy_fn.",
4395 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4396 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4397 std::make_pair(x: ".lb.", y&: KmpUInt64Ty),
4398 std::make_pair(x: ".ub.", y&: KmpUInt64Ty),
4399 std::make_pair(x: ".st.", y&: KmpInt64Ty),
4400 std::make_pair(x: ".liter.", y&: KmpInt32Ty),
4401 std::make_pair(".reductions.", VoidPtrTy),
4402 std::make_pair(StringRef(), QualType()) // __context with shared vars
4403 };
4404 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4405 Params);
4406 // Mark this captured region as inlined, because we don't use outlined
4407 // function directly.
4408 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4409 AlwaysInlineAttr::CreateImplicit(
4410 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4411 break;
4412 }
4413 case OMPD_parallel_masked_taskloop:
4414 case OMPD_parallel_masked_taskloop_simd:
4415 case OMPD_parallel_master_taskloop:
4416 case OMPD_parallel_master_taskloop_simd: {
4417 QualType KmpInt32Ty =
4418 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4419 .withConst();
4420 QualType KmpUInt64Ty =
4421 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4422 .withConst();
4423 QualType KmpInt64Ty =
4424 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4425 .withConst();
4426 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4427 QualType KmpInt32PtrTy =
4428 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4429 Sema::CapturedParamNameType ParamsParallel[] = {
4430 std::make_pair(".global_tid.", KmpInt32PtrTy),
4431 std::make_pair(x: ".bound_tid.", y&: KmpInt32PtrTy),
4432 std::make_pair(StringRef(), QualType()) // __context with shared vars
4433 };
4434 // Start a captured region for 'parallel'.
4435 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4436 ParamsParallel, /*OpenMPCaptureLevel=*/0);
4437 QualType Args[] = {VoidPtrTy};
4438 FunctionProtoType::ExtProtoInfo EPI;
4439 EPI.Variadic = true;
4440 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4441 Sema::CapturedParamNameType Params[] = {
4442 std::make_pair(".global_tid.", KmpInt32Ty),
4443 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4444 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4445 std::make_pair(
4446 x: ".copy_fn.",
4447 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4448 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4449 std::make_pair(x: ".lb.", y&: KmpUInt64Ty),
4450 std::make_pair(x: ".ub.", y&: KmpUInt64Ty),
4451 std::make_pair(x: ".st.", y&: KmpInt64Ty),
4452 std::make_pair(x: ".liter.", y&: KmpInt32Ty),
4453 std::make_pair(".reductions.", VoidPtrTy),
4454 std::make_pair(StringRef(), QualType()) // __context with shared vars
4455 };
4456 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4457 Params, /*OpenMPCaptureLevel=*/1);
4458 // Mark this captured region as inlined, because we don't use outlined
4459 // function directly.
4460 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4461 AlwaysInlineAttr::CreateImplicit(
4462 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4463 break;
4464 }
4465 case OMPD_distribute_parallel_for_simd:
4466 case OMPD_distribute_parallel_for: {
4467 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(DestWidth: 32, Signed: 1).withConst();
4468 QualType KmpInt32PtrTy =
4469 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4470 Sema::CapturedParamNameType Params[] = {
4471 std::make_pair(".global_tid.", KmpInt32PtrTy),
4472 std::make_pair(x: ".bound_tid.", y&: KmpInt32PtrTy),
4473 std::make_pair(x: ".previous.lb.", y: Context.getSizeType().withConst()),
4474 std::make_pair(x: ".previous.ub.", y: Context.getSizeType().withConst()),
4475 std::make_pair(StringRef(), QualType()) // __context with shared vars
4476 };
4477 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4478 Params);
4479 break;
4480 }
4481 case OMPD_target_teams_loop:
4482 case OMPD_target_teams_distribute_parallel_for:
4483 case OMPD_target_teams_distribute_parallel_for_simd: {
4484 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(DestWidth: 32, Signed: 1).withConst();
4485 QualType KmpInt32PtrTy =
4486 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4487 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4488
4489 QualType Args[] = {VoidPtrTy};
4490 FunctionProtoType::ExtProtoInfo EPI;
4491 EPI.Variadic = true;
4492 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4493 Sema::CapturedParamNameType Params[] = {
4494 std::make_pair(".global_tid.", KmpInt32Ty),
4495 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4496 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4497 std::make_pair(
4498 x: ".copy_fn.",
4499 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4500 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4501 std::make_pair(StringRef(), QualType()) // __context with shared vars
4502 };
4503 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4504 Params, /*OpenMPCaptureLevel=*/0);
4505 // Mark this captured region as inlined, because we don't use outlined
4506 // function directly.
4507 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4508 AlwaysInlineAttr::CreateImplicit(
4509 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4510 SmallVector<Sema::CapturedParamNameType, 2> ParamsTarget;
4511 if (getLangOpts().OpenMPIsTargetDevice)
4512 ParamsTarget.push_back(Elt: std::make_pair(x: StringRef("dyn_ptr"), y&: VoidPtrTy));
4513 ParamsTarget.push_back(
4514 Elt: std::make_pair(StringRef(), QualType())); // __context with shared vars;
4515 // Start a captured region for 'target' with no implicit parameters.
4516 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, Kind: CR_OpenMP,
4517 Params: ParamsTarget, /*OpenMPCaptureLevel=*/1);
4518
4519 Sema::CapturedParamNameType ParamsTeams[] = {
4520 std::make_pair(".global_tid.", KmpInt32PtrTy),
4521 std::make_pair(x: ".bound_tid.", y&: KmpInt32PtrTy),
4522 std::make_pair(StringRef(), QualType()) // __context with shared vars
4523 };
4524 // Start a captured region for 'target' with no implicit parameters.
4525 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4526 ParamsTeams, /*OpenMPCaptureLevel=*/2);
4527
4528 Sema::CapturedParamNameType ParamsParallel[] = {
4529 std::make_pair(".global_tid.", KmpInt32PtrTy),
4530 std::make_pair(x: ".bound_tid.", y&: KmpInt32PtrTy),
4531 std::make_pair(x: ".previous.lb.", y: Context.getSizeType().withConst()),
4532 std::make_pair(x: ".previous.ub.", y: Context.getSizeType().withConst()),
4533 std::make_pair(StringRef(), QualType()) // __context with shared vars
4534 };
4535 // Start a captured region for 'teams' or 'parallel'. Both regions have
4536 // the same implicit parameters.
4537 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4538 ParamsParallel, /*OpenMPCaptureLevel=*/3);
4539 break;
4540 }
4541
4542 case OMPD_teams_loop:
4543 case OMPD_teams_distribute_parallel_for:
4544 case OMPD_teams_distribute_parallel_for_simd: {
4545 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(DestWidth: 32, Signed: 1).withConst();
4546 QualType KmpInt32PtrTy =
4547 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4548
4549 Sema::CapturedParamNameType ParamsTeams[] = {
4550 std::make_pair(".global_tid.", KmpInt32PtrTy),
4551 std::make_pair(x: ".bound_tid.", y&: KmpInt32PtrTy),
4552 std::make_pair(StringRef(), QualType()) // __context with shared vars
4553 };
4554 // Start a captured region for 'target' with no implicit parameters.
4555 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4556 ParamsTeams, /*OpenMPCaptureLevel=*/0);
4557
4558 Sema::CapturedParamNameType ParamsParallel[] = {
4559 std::make_pair(".global_tid.", KmpInt32PtrTy),
4560 std::make_pair(x: ".bound_tid.", y&: KmpInt32PtrTy),
4561 std::make_pair(x: ".previous.lb.", y: Context.getSizeType().withConst()),
4562 std::make_pair(x: ".previous.ub.", y: Context.getSizeType().withConst()),
4563 std::make_pair(StringRef(), QualType()) // __context with shared vars
4564 };
4565 // Start a captured region for 'teams' or 'parallel'. Both regions have
4566 // the same implicit parameters.
4567 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4568 ParamsParallel, /*OpenMPCaptureLevel=*/1);
4569 break;
4570 }
4571 case OMPD_target_update:
4572 case OMPD_target_enter_data:
4573 case OMPD_target_exit_data: {
4574 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(DestWidth: 32, Signed: 1).withConst();
4575 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4576 QualType KmpInt32PtrTy =
4577 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4578 QualType Args[] = {VoidPtrTy};
4579 FunctionProtoType::ExtProtoInfo EPI;
4580 EPI.Variadic = true;
4581 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4582 Sema::CapturedParamNameType Params[] = {
4583 std::make_pair(".global_tid.", KmpInt32Ty),
4584 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4585 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4586 std::make_pair(
4587 x: ".copy_fn.",
4588 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4589 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4590 std::make_pair(StringRef(), QualType()) // __context with shared vars
4591 };
4592 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4593 Params);
4594 // Mark this captured region as inlined, because we don't use outlined
4595 // function directly.
4596 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4597 AlwaysInlineAttr::CreateImplicit(
4598 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4599 break;
4600 }
4601 case OMPD_threadprivate:
4602 case OMPD_allocate:
4603 case OMPD_taskyield:
4604 case OMPD_error:
4605 case OMPD_barrier:
4606 case OMPD_taskwait:
4607 case OMPD_cancellation_point:
4608 case OMPD_cancel:
4609 case OMPD_flush:
4610 case OMPD_depobj:
4611 case OMPD_scan:
4612 case OMPD_declare_reduction:
4613 case OMPD_declare_mapper:
4614 case OMPD_declare_simd:
4615 case OMPD_declare_target:
4616 case OMPD_end_declare_target:
4617 case OMPD_requires:
4618 case OMPD_declare_variant:
4619 case OMPD_begin_declare_variant:
4620 case OMPD_end_declare_variant:
4621 case OMPD_metadirective:
4622 llvm_unreachable("OpenMP Directive is not allowed");
4623 case OMPD_unknown:
4624 default:
4625 llvm_unreachable("Unknown OpenMP directive");
4626 }
4627 DSAStack->setContext(CurContext);
4628 handleDeclareVariantConstructTrait(DSAStack, DKind, /* ScopeEntry */ true);
4629}
4630
4631int Sema::getNumberOfConstructScopes(unsigned Level) const {
4632 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4633}
4634
4635int Sema::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4636 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4637 getOpenMPCaptureRegions(CaptureRegions, DKind);
4638 return CaptureRegions.size();
4639}
4640
4641static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
4642 Expr *CaptureExpr, bool WithInit,
4643 DeclContext *CurContext,
4644 bool AsExpression) {
4645 assert(CaptureExpr);
4646 ASTContext &C = S.getASTContext();
4647 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4648 QualType Ty = Init->getType();
4649 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4650 if (S.getLangOpts().CPlusPlus) {
4651 Ty = C.getLValueReferenceType(T: Ty);
4652 } else {
4653 Ty = C.getPointerType(T: Ty);
4654 ExprResult Res =
4655 S.CreateBuiltinUnaryOp(OpLoc: CaptureExpr->getExprLoc(), Opc: UO_AddrOf, InputExpr: Init);
4656 if (!Res.isUsable())
4657 return nullptr;
4658 Init = Res.get();
4659 }
4660 WithInit = true;
4661 }
4662 auto *CED = OMPCapturedExprDecl::Create(C, DC: CurContext, Id, T: Ty,
4663 StartLoc: CaptureExpr->getBeginLoc());
4664 if (!WithInit)
4665 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4666 CurContext->addHiddenDecl(D: CED);
4667 Sema::TentativeAnalysisScope Trap(S);
4668 S.AddInitializerToDecl(dcl: CED, init: Init, /*DirectInit=*/false);
4669 return CED;
4670}
4671
4672static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4673 bool WithInit) {
4674 OMPCapturedExprDecl *CD;
4675 if (VarDecl *VD = S.isOpenMPCapturedDecl(D))
4676 CD = cast<OMPCapturedExprDecl>(Val: VD);
4677 else
4678 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4679 S.CurContext,
4680 /*AsExpression=*/false);
4681 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4682 CaptureExpr->getExprLoc());
4683}
4684
4685static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4686 StringRef Name) {
4687 CaptureExpr = S.DefaultLvalueConversion(E: CaptureExpr).get();
4688 if (!Ref) {
4689 OMPCapturedExprDecl *CD = buildCaptureDecl(
4690 S, Id: &S.getASTContext().Idents.get(Name), CaptureExpr,
4691 /*WithInit=*/true, CurContext: S.CurContext, /*AsExpression=*/true);
4692 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4693 CaptureExpr->getExprLoc());
4694 }
4695 ExprResult Res = Ref;
4696 if (!S.getLangOpts().CPlusPlus &&
4697 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4698 Ref->getType()->isPointerType()) {
4699 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4700 if (!Res.isUsable())
4701 return ExprError();
4702 }
4703 return S.DefaultLvalueConversion(E: Res.get());
4704}
4705
4706namespace {
4707// OpenMP directives parsed in this section are represented as a
4708// CapturedStatement with an associated statement. If a syntax error
4709// is detected during the parsing of the associated statement, the
4710// compiler must abort processing and close the CapturedStatement.
4711//
4712// Combined directives such as 'target parallel' have more than one
4713// nested CapturedStatements. This RAII ensures that we unwind out
4714// of all the nested CapturedStatements when an error is found.
4715class CaptureRegionUnwinderRAII {
4716private:
4717 Sema &S;
4718 bool &ErrorFound;
4719 OpenMPDirectiveKind DKind = OMPD_unknown;
4720
4721public:
4722 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4723 OpenMPDirectiveKind DKind)
4724 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4725 ~CaptureRegionUnwinderRAII() {
4726 if (ErrorFound) {
4727 int ThisCaptureLevel = S.getOpenMPCaptureLevels(DKind);
4728 while (--ThisCaptureLevel >= 0)
4729 S.ActOnCapturedRegionError();
4730 }
4731 }
4732};
4733} // namespace
4734
4735void Sema::tryCaptureOpenMPLambdas(ValueDecl *V) {
4736 // Capture variables captured by reference in lambdas for target-based
4737 // directives.
4738 if (!CurContext->isDependentContext() &&
4739 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4740 isOpenMPTargetDataManagementDirective(
4741 DSAStack->getCurrentDirective()))) {
4742 QualType Type = V->getType();
4743 if (const auto *RD = Type.getCanonicalType()
4744 .getNonReferenceType()
4745 ->getAsCXXRecordDecl()) {
4746 bool SavedForceCaptureByReferenceInTargetExecutable =
4747 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4748 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4749 /*V=*/true);
4750 if (RD->isLambda()) {
4751 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4752 FieldDecl *ThisCapture;
4753 RD->getCaptureFields(Captures, ThisCapture);
4754 for (const LambdaCapture &LC : RD->captures()) {
4755 if (LC.getCaptureKind() == LCK_ByRef) {
4756 VarDecl *VD = cast<VarDecl>(Val: LC.getCapturedVar());
4757 DeclContext *VDC = VD->getDeclContext();
4758 if (!VDC->Encloses(DC: CurContext))
4759 continue;
4760 MarkVariableReferenced(Loc: LC.getLocation(), Var: VD);
4761 } else if (LC.getCaptureKind() == LCK_This) {
4762 QualType ThisTy = getCurrentThisType();
4763 if (!ThisTy.isNull() &&
4764 Context.typesAreCompatible(T1: ThisTy, T2: ThisCapture->getType()))
4765 CheckCXXThisCapture(Loc: LC.getLocation());
4766 }
4767 }
4768 }
4769 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4770 SavedForceCaptureByReferenceInTargetExecutable);
4771 }
4772 }
4773}
4774
4775static bool checkOrderedOrderSpecified(Sema &S,
4776 const ArrayRef<OMPClause *> Clauses) {
4777 const OMPOrderedClause *Ordered = nullptr;
4778 const OMPOrderClause *Order = nullptr;
4779
4780 for (const OMPClause *Clause : Clauses) {
4781 if (Clause->getClauseKind() == OMPC_ordered)
4782 Ordered = cast<OMPOrderedClause>(Val: Clause);
4783 else if (Clause->getClauseKind() == OMPC_order) {
4784 Order = cast<OMPOrderClause>(Val: Clause);
4785 if (Order->getKind() != OMPC_ORDER_concurrent)
4786 Order = nullptr;
4787 }
4788 if (Ordered && Order)
4789 break;
4790 }
4791
4792 if (Ordered && Order) {
4793 S.Diag(Order->getKindKwLoc(),
4794 diag::err_omp_simple_clause_incompatible_with_ordered)
4795 << getOpenMPClauseName(OMPC_order)
4796 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4797 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4798 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4799 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4800 return true;
4801 }
4802 return false;
4803}
4804
4805StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
4806 ArrayRef<OMPClause *> Clauses) {
4807 handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(),
4808 /* ScopeEntry */ false);
4809 if (DSAStack->getCurrentDirective() == OMPD_atomic ||
4810 DSAStack->getCurrentDirective() == OMPD_critical ||
4811 DSAStack->getCurrentDirective() == OMPD_section ||
4812 DSAStack->getCurrentDirective() == OMPD_master ||
4813 DSAStack->getCurrentDirective() == OMPD_masked)
4814 return S;
4815
4816 bool ErrorFound = false;
4817 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4818 *this, ErrorFound, DSAStack->getCurrentDirective());
4819 if (!S.isUsable()) {
4820 ErrorFound = true;
4821 return StmtError();
4822 }
4823
4824 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4825 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4826 OMPOrderedClause *OC = nullptr;
4827 OMPScheduleClause *SC = nullptr;
4828 SmallVector<const OMPLinearClause *, 4> LCs;
4829 SmallVector<const OMPClauseWithPreInit *, 4> PICs;
4830 // This is required for proper codegen.
4831 for (OMPClause *Clause : Clauses) {
4832 if (!LangOpts.OpenMPSimd &&
4833 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4834 DSAStack->getCurrentDirective() == OMPD_target) &&
4835 Clause->getClauseKind() == OMPC_in_reduction) {
4836 // Capture taskgroup task_reduction descriptors inside the tasking regions
4837 // with the corresponding in_reduction items.
4838 auto *IRC = cast<OMPInReductionClause>(Val: Clause);
4839 for (Expr *E : IRC->taskgroup_descriptors())
4840 if (E)
4841 MarkDeclarationsReferencedInExpr(E);
4842 }
4843 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4844 Clause->getClauseKind() == OMPC_copyprivate ||
4845 (getLangOpts().OpenMPUseTLS &&
4846 getASTContext().getTargetInfo().isTLSSupported() &&
4847 Clause->getClauseKind() == OMPC_copyin)) {
4848 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4849 // Mark all variables in private list clauses as used in inner region.
4850 for (Stmt *VarRef : Clause->children()) {
4851 if (auto *E = cast_or_null<Expr>(Val: VarRef)) {
4852 MarkDeclarationsReferencedInExpr(E);
4853 }
4854 }
4855 DSAStack->setForceVarCapturing(/*V=*/false);
4856 } else if (isOpenMPLoopTransformationDirective(
4857 DSAStack->getCurrentDirective())) {
4858 assert(CaptureRegions.empty() &&
4859 "No captured regions in loop transformation directives.");
4860 } else if (CaptureRegions.size() > 1 ||
4861 CaptureRegions.back() != OMPD_unknown) {
4862 if (auto *C = OMPClauseWithPreInit::get(C: Clause))
4863 PICs.push_back(Elt: C);
4864 if (auto *C = OMPClauseWithPostUpdate::get(C: Clause)) {
4865 if (Expr *E = C->getPostUpdateExpr())
4866 MarkDeclarationsReferencedInExpr(E);
4867 }
4868 }
4869 if (Clause->getClauseKind() == OMPC_schedule)
4870 SC = cast<OMPScheduleClause>(Val: Clause);
4871 else if (Clause->getClauseKind() == OMPC_ordered)
4872 OC = cast<OMPOrderedClause>(Val: Clause);
4873 else if (Clause->getClauseKind() == OMPC_linear)
4874 LCs.push_back(Elt: cast<OMPLinearClause>(Val: Clause));
4875 }
4876 // Capture allocator expressions if used.
4877 for (Expr *E : DSAStack->getInnerAllocators())
4878 MarkDeclarationsReferencedInExpr(E);
4879 // OpenMP, 2.7.1 Loop Construct, Restrictions
4880 // The nonmonotonic modifier cannot be specified if an ordered clause is
4881 // specified.
4882 if (SC &&
4883 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4884 SC->getSecondScheduleModifier() ==
4885 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4886 OC) {
4887 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4888 ? SC->getFirstScheduleModifierLoc()
4889 : SC->getSecondScheduleModifierLoc(),
4890 diag::err_omp_simple_clause_incompatible_with_ordered)
4891 << getOpenMPClauseName(OMPC_schedule)
4892 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4893 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4894 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4895 ErrorFound = true;
4896 }
4897 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4898 // If an order(concurrent) clause is present, an ordered clause may not appear
4899 // on the same directive.
4900 if (checkOrderedOrderSpecified(S&: *this, Clauses))
4901 ErrorFound = true;
4902 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4903 for (const OMPLinearClause *C : LCs) {
4904 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4905 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4906 }
4907 ErrorFound = true;
4908 }
4909 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4910 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4911 OC->getNumForLoops()) {
4912 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4913 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4914 ErrorFound = true;
4915 }
4916 if (ErrorFound) {
4917 return StmtError();
4918 }
4919 StmtResult SR = S;
4920 unsigned CompletedRegions = 0;
4921 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(C&: CaptureRegions)) {
4922 // Mark all variables in private list clauses as used in inner region.
4923 // Required for proper codegen of combined directives.
4924 // TODO: add processing for other clauses.
4925 if (ThisCaptureRegion != OMPD_unknown) {
4926 for (const clang::OMPClauseWithPreInit *C : PICs) {
4927 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4928 // Find the particular capture region for the clause if the
4929 // directive is a combined one with multiple capture regions.
4930 // If the directive is not a combined one, the capture region
4931 // associated with the clause is OMPD_unknown and is generated
4932 // only once.
4933 if (CaptureRegion == ThisCaptureRegion ||
4934 CaptureRegion == OMPD_unknown) {
4935 if (auto *DS = cast_or_null<DeclStmt>(Val: C->getPreInitStmt())) {
4936 for (Decl *D : DS->decls())
4937 MarkVariableReferenced(Loc: D->getLocation(), Var: cast<VarDecl>(Val: D));
4938 }
4939 }
4940 }
4941 }
4942 if (ThisCaptureRegion == OMPD_target) {
4943 // Capture allocator traits in the target region. They are used implicitly
4944 // and, thus, are not captured by default.
4945 for (OMPClause *C : Clauses) {
4946 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(Val: C)) {
4947 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4948 ++I) {
4949 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4950 if (Expr *E = D.AllocatorTraits)
4951 MarkDeclarationsReferencedInExpr(E);
4952 }
4953 continue;
4954 }
4955 }
4956 }
4957 if (ThisCaptureRegion == OMPD_parallel) {
4958 // Capture temp arrays for inscan reductions and locals in aligned
4959 // clauses.
4960 for (OMPClause *C : Clauses) {
4961 if (auto *RC = dyn_cast<OMPReductionClause>(Val: C)) {
4962 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4963 continue;
4964 for (Expr *E : RC->copy_array_temps())
4965 MarkDeclarationsReferencedInExpr(E);
4966 }
4967 if (auto *AC = dyn_cast<OMPAlignedClause>(Val: C)) {
4968 for (Expr *E : AC->varlists())
4969 MarkDeclarationsReferencedInExpr(E);
4970 }
4971 }
4972 }
4973 if (++CompletedRegions == CaptureRegions.size())
4974 DSAStack->setBodyComplete();
4975 SR = ActOnCapturedRegionEnd(S: SR.get());
4976 }
4977 return SR;
4978}
4979
4980static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4981 OpenMPDirectiveKind CancelRegion,
4982 SourceLocation StartLoc) {
4983 // CancelRegion is only needed for cancel and cancellation_point.
4984 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4985 return false;
4986
4987 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4988 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4989 return false;
4990
4991 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4992 << getOpenMPDirectiveName(CancelRegion);
4993 return true;
4994}
4995
4996static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4997 OpenMPDirectiveKind CurrentRegion,
4998 const DeclarationNameInfo &CurrentName,
4999 OpenMPDirectiveKind CancelRegion,
5000 OpenMPBindClauseKind BindKind,
5001 SourceLocation StartLoc) {
5002 if (Stack->getCurScope()) {
5003 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
5004 OpenMPDirectiveKind OffendingRegion = ParentRegion;
5005 bool NestingProhibited = false;
5006 bool CloseNesting = true;
5007 bool OrphanSeen = false;
5008 enum {
5009 NoRecommend,
5010 ShouldBeInParallelRegion,
5011 ShouldBeInOrderedRegion,
5012 ShouldBeInTargetRegion,
5013 ShouldBeInTeamsRegion,
5014 ShouldBeInLoopSimdRegion,
5015 } Recommend = NoRecommend;
5016 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
5017 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
5018 CurrentRegion != OMPD_parallel &&
5019 !isOpenMPCombinedParallelADirective(CurrentRegion)) {
5020 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
5021 << getOpenMPDirectiveName(CurrentRegion);
5022 return true;
5023 }
5024 if (isOpenMPSimdDirective(ParentRegion) &&
5025 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
5026 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
5027 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5028 CurrentRegion != OMPD_scan))) {
5029 // OpenMP [2.16, Nesting of Regions]
5030 // OpenMP constructs may not be nested inside a simd region.
5031 // OpenMP [2.8.1,simd Construct, Restrictions]
5032 // An ordered construct with the simd clause is the only OpenMP
5033 // construct that can appear in the simd region.
5034 // Allowing a SIMD construct nested in another SIMD construct is an
5035 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5036 // message.
5037 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5038 // The only OpenMP constructs that can be encountered during execution of
5039 // a simd region are the atomic construct, the loop construct, the simd
5040 // construct and the ordered construct with the simd clause.
5041 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
5042 ? diag::err_omp_prohibited_region_simd
5043 : diag::warn_omp_nesting_simd)
5044 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
5045 return CurrentRegion != OMPD_simd;
5046 }
5047 if (ParentRegion == OMPD_atomic) {
5048 // OpenMP [2.16, Nesting of Regions]
5049 // OpenMP constructs may not be nested inside an atomic region.
5050 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5051 return true;
5052 }
5053 if (CurrentRegion == OMPD_section) {
5054 // OpenMP [2.7.2, sections Construct, Restrictions]
5055 // Orphaned section directives are prohibited. That is, the section
5056 // directives must appear within the sections construct and must not be
5057 // encountered elsewhere in the sections region.
5058 if (ParentRegion != OMPD_sections &&
5059 ParentRegion != OMPD_parallel_sections) {
5060 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5061 << (ParentRegion != OMPD_unknown)
5062 << getOpenMPDirectiveName(ParentRegion);
5063 return true;
5064 }
5065 return false;
5066 }
5067 // Allow some constructs (except teams and cancellation constructs) to be
5068 // orphaned (they could be used in functions, called from OpenMP regions
5069 // with the required preconditions).
5070 if (ParentRegion == OMPD_unknown &&
5071 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5072 CurrentRegion != OMPD_cancellation_point &&
5073 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5074 return false;
5075 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5076 // for a detailed explanation
5077 if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
5078 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5079 (isOpenMPWorksharingDirective(ParentRegion) ||
5080 ParentRegion == OMPD_loop)) {
5081 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5082 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5083 << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
5084 << getOpenMPDirectiveName(CurrentRegion);
5085 return true;
5086 }
5087 if (CurrentRegion == OMPD_cancellation_point ||
5088 CurrentRegion == OMPD_cancel) {
5089 // OpenMP [2.16, Nesting of Regions]
5090 // A cancellation point construct for which construct-type-clause is
5091 // taskgroup must be nested inside a task construct. A cancellation
5092 // point construct for which construct-type-clause is not taskgroup must
5093 // be closely nested inside an OpenMP construct that matches the type
5094 // specified in construct-type-clause.
5095 // A cancel construct for which construct-type-clause is taskgroup must be
5096 // nested inside a task construct. A cancel construct for which
5097 // construct-type-clause is not taskgroup must be closely nested inside an
5098 // OpenMP construct that matches the type specified in
5099 // construct-type-clause.
5100 NestingProhibited =
5101 !((CancelRegion == OMPD_parallel &&
5102 (ParentRegion == OMPD_parallel ||
5103 ParentRegion == OMPD_target_parallel)) ||
5104 (CancelRegion == OMPD_for &&
5105 (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for ||
5106 ParentRegion == OMPD_target_parallel_for ||
5107 ParentRegion == OMPD_distribute_parallel_for ||
5108 ParentRegion == OMPD_teams_distribute_parallel_for ||
5109 ParentRegion == OMPD_target_teams_distribute_parallel_for)) ||
5110 (CancelRegion == OMPD_taskgroup &&
5111 (ParentRegion == OMPD_task ||
5112 (SemaRef.getLangOpts().OpenMP >= 50 &&
5113 (ParentRegion == OMPD_taskloop ||
5114 ParentRegion == OMPD_master_taskloop ||
5115 ParentRegion == OMPD_masked_taskloop ||
5116 ParentRegion == OMPD_parallel_masked_taskloop ||
5117 ParentRegion == OMPD_parallel_master_taskloop)))) ||
5118 (CancelRegion == OMPD_sections &&
5119 (ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
5120 ParentRegion == OMPD_parallel_sections)));
5121 OrphanSeen = ParentRegion == OMPD_unknown;
5122 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5123 // OpenMP 5.1 [2.22, Nesting of Regions]
5124 // A masked region may not be closely nested inside a worksharing, loop,
5125 // atomic, task, or taskloop region.
5126 NestingProhibited = isOpenMPWorksharingDirective(DKind: ParentRegion) ||
5127 isOpenMPGenericLoopDirective(DKind: ParentRegion) ||
5128 isOpenMPTaskingDirective(Kind: ParentRegion);
5129 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5130 // OpenMP [2.16, Nesting of Regions]
5131 // A critical region may not be nested (closely or otherwise) inside a
5132 // critical region with the same name. Note that this restriction is not
5133 // sufficient to prevent deadlock.
5134 SourceLocation PreviousCriticalLoc;
5135 bool DeadLock = Stack->hasDirective(
5136 DPred: [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5137 const DeclarationNameInfo &DNI,
5138 SourceLocation Loc) {
5139 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5140 PreviousCriticalLoc = Loc;
5141 return true;
5142 }
5143 return false;
5144 },
5145 FromParent: false /* skip top directive */);
5146 if (DeadLock) {
5147 SemaRef.Diag(StartLoc,
5148 diag::err_omp_prohibited_region_critical_same_name)
5149 << CurrentName.getName();
5150 if (PreviousCriticalLoc.isValid())
5151 SemaRef.Diag(PreviousCriticalLoc,
5152 diag::note_omp_previous_critical_region);
5153 return true;
5154 }
5155 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5156 // OpenMP 5.1 [2.22, Nesting of Regions]
5157 // A scope region may not be closely nested inside a worksharing, loop,
5158 // task, taskloop, critical, ordered, atomic, or masked region.
5159 // OpenMP 5.1 [2.22, Nesting of Regions]
5160 // A barrier region may not be closely nested inside a worksharing, loop,
5161 // task, taskloop, critical, ordered, atomic, or masked region.
5162 NestingProhibited =
5163 isOpenMPWorksharingDirective(ParentRegion) ||
5164 isOpenMPGenericLoopDirective(ParentRegion) ||
5165 isOpenMPTaskingDirective(ParentRegion) ||
5166 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5167 ParentRegion == OMPD_parallel_master ||
5168 ParentRegion == OMPD_parallel_masked ||
5169 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5170 } else if (isOpenMPWorksharingDirective(DKind: CurrentRegion) &&
5171 !isOpenMPParallelDirective(DKind: CurrentRegion) &&
5172 !isOpenMPTeamsDirective(DKind: CurrentRegion)) {
5173 // OpenMP 5.1 [2.22, Nesting of Regions]
5174 // A loop region that binds to a parallel region or a worksharing region
5175 // may not be closely nested inside a worksharing, loop, task, taskloop,
5176 // critical, ordered, atomic, or masked region.
5177 NestingProhibited =
5178 isOpenMPWorksharingDirective(ParentRegion) ||
5179 isOpenMPGenericLoopDirective(ParentRegion) ||
5180 isOpenMPTaskingDirective(ParentRegion) ||
5181 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5182 ParentRegion == OMPD_parallel_master ||
5183 ParentRegion == OMPD_parallel_masked ||
5184 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5185 Recommend = ShouldBeInParallelRegion;
5186 } else if (CurrentRegion == OMPD_ordered) {
5187 // OpenMP [2.16, Nesting of Regions]
5188 // An ordered region may not be closely nested inside a critical,
5189 // atomic, or explicit task region.
5190 // An ordered region must be closely nested inside a loop region (or
5191 // parallel loop region) with an ordered clause.
5192 // OpenMP [2.8.1,simd Construct, Restrictions]
5193 // An ordered construct with the simd clause is the only OpenMP construct
5194 // that can appear in the simd region.
5195 NestingProhibited = ParentRegion == OMPD_critical ||
5196 isOpenMPTaskingDirective(ParentRegion) ||
5197 !(isOpenMPSimdDirective(ParentRegion) ||
5198 Stack->isParentOrderedRegion());
5199 Recommend = ShouldBeInOrderedRegion;
5200 } else if (isOpenMPNestingTeamsDirective(DKind: CurrentRegion)) {
5201 // OpenMP [2.16, Nesting of Regions]
5202 // If specified, a teams construct must be contained within a target
5203 // construct.
5204 NestingProhibited =
5205 (SemaRef.LangOpts.OpenMP <= 45 && ParentRegion != OMPD_target) ||
5206 (SemaRef.LangOpts.OpenMP >= 50 && ParentRegion != OMPD_unknown &&
5207 ParentRegion != OMPD_target);
5208 OrphanSeen = ParentRegion == OMPD_unknown;
5209 Recommend = ShouldBeInTargetRegion;
5210 } else if (CurrentRegion == OMPD_scan) {
5211 // OpenMP [2.16, Nesting of Regions]
5212 // If specified, a teams construct must be contained within a target
5213 // construct.
5214 NestingProhibited =
5215 SemaRef.LangOpts.OpenMP < 50 ||
5216 (ParentRegion != OMPD_simd && ParentRegion != OMPD_for &&
5217 ParentRegion != OMPD_for_simd && ParentRegion != OMPD_parallel_for &&
5218 ParentRegion != OMPD_parallel_for_simd);
5219 OrphanSeen = ParentRegion == OMPD_unknown;
5220 Recommend = ShouldBeInLoopSimdRegion;
5221 }
5222 if (!NestingProhibited &&
5223 !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5224 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5225 (ParentRegion == OMPD_teams || ParentRegion == OMPD_target_teams)) {
5226 // OpenMP [5.1, 2.22, Nesting of Regions]
5227 // distribute, distribute simd, distribute parallel worksharing-loop,
5228 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5229 // including any parallel regions arising from combined constructs,
5230 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5231 // only OpenMP regions that may be strictly nested inside the teams
5232 // region.
5233 //
5234 // As an extension, we permit atomic within teams as well.
5235 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5236 !isOpenMPDistributeDirective(CurrentRegion) &&
5237 CurrentRegion != OMPD_loop &&
5238 !(SemaRef.getLangOpts().OpenMPExtensions &&
5239 CurrentRegion == OMPD_atomic);
5240 Recommend = ShouldBeInParallelRegion;
5241 }
5242 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5243 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5244 // If the bind clause is present on the loop construct and binding is
5245 // teams then the corresponding loop region must be strictly nested inside
5246 // a teams region.
5247 NestingProhibited = BindKind == OMPC_BIND_teams &&
5248 ParentRegion != OMPD_teams &&
5249 ParentRegion != OMPD_target_teams;
5250 Recommend = ShouldBeInTeamsRegion;
5251 }
5252 if (!NestingProhibited &&
5253 isOpenMPNestingDistributeDirective(DKind: CurrentRegion)) {
5254 // OpenMP 4.5 [2.17 Nesting of Regions]
5255 // The region associated with the distribute construct must be strictly
5256 // nested inside a teams region
5257 NestingProhibited =
5258 (ParentRegion != OMPD_teams && ParentRegion != OMPD_target_teams);
5259 Recommend = ShouldBeInTeamsRegion;
5260 }
5261 if (!NestingProhibited &&
5262 (isOpenMPTargetExecutionDirective(DKind: CurrentRegion) ||
5263 isOpenMPTargetDataManagementDirective(DKind: CurrentRegion))) {
5264 // OpenMP 4.5 [2.17 Nesting of Regions]
5265 // If a target, target update, target data, target enter data, or
5266 // target exit data construct is encountered during execution of a
5267 // target region, the behavior is unspecified.
5268 NestingProhibited = Stack->hasDirective(
5269 DPred: [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5270 SourceLocation) {
5271 if (isOpenMPTargetExecutionDirective(DKind: K)) {
5272 OffendingRegion = K;
5273 return true;
5274 }
5275 return false;
5276 },
5277 FromParent: false /* don't skip top directive */);
5278 CloseNesting = false;
5279 }
5280 if (NestingProhibited) {
5281 if (OrphanSeen) {
5282 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5283 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5284 } else {
5285 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5286 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5287 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5288 }
5289 return true;
5290 }
5291 }
5292 return false;
5293}
5294
5295struct Kind2Unsigned {
5296 using argument_type = OpenMPDirectiveKind;
5297 unsigned operator()(argument_type DK) { return unsigned(DK); }
5298};
5299static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5300 ArrayRef<OMPClause *> Clauses,
5301 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5302 bool ErrorFound = false;
5303 unsigned NamedModifiersNumber = 0;
5304 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5305 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5306 SmallVector<SourceLocation, 4> NameModifierLoc;
5307 for (const OMPClause *C : Clauses) {
5308 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(Val: C)) {
5309 // At most one if clause without a directive-name-modifier can appear on
5310 // the directive.
5311 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5312 if (FoundNameModifiers[CurNM]) {
5313 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5314 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5315 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5316 ErrorFound = true;
5317 } else if (CurNM != OMPD_unknown) {
5318 NameModifierLoc.push_back(Elt: IC->getNameModifierLoc());
5319 ++NamedModifiersNumber;
5320 }
5321 FoundNameModifiers[CurNM] = IC;
5322 if (CurNM == OMPD_unknown)
5323 continue;
5324 // Check if the specified name modifier is allowed for the current
5325 // directive.
5326 // At most one if clause with the particular directive-name-modifier can
5327 // appear on the directive.
5328 if (!llvm::is_contained(Range&: AllowedNameModifiers, Element: CurNM)) {
5329 S.Diag(IC->getNameModifierLoc(),
5330 diag::err_omp_wrong_if_directive_name_modifier)
5331 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5332 ErrorFound = true;
5333 }
5334 }
5335 }
5336 // If any if clause on the directive includes a directive-name-modifier then
5337 // all if clauses on the directive must include a directive-name-modifier.
5338 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5339 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5340 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5341 diag::err_omp_no_more_if_clause);
5342 } else {
5343 std::string Values;
5344 std::string Sep(", ");
5345 unsigned AllowedCnt = 0;
5346 unsigned TotalAllowedNum =
5347 AllowedNameModifiers.size() - NamedModifiersNumber;
5348 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5349 ++Cnt) {
5350 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5351 if (!FoundNameModifiers[NM]) {
5352 Values += "'";
5353 Values += getOpenMPDirectiveName(NM);
5354 Values += "'";
5355 if (AllowedCnt + 2 == TotalAllowedNum)
5356 Values += " or ";
5357 else if (AllowedCnt + 1 != TotalAllowedNum)
5358 Values += Sep;
5359 ++AllowedCnt;
5360 }
5361 }
5362 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5363 diag::err_omp_unnamed_if_clause)
5364 << (TotalAllowedNum > 1) << Values;
5365 }
5366 for (SourceLocation Loc : NameModifierLoc) {
5367 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5368 }
5369 ErrorFound = true;
5370 }
5371 return ErrorFound;
5372}
5373
5374static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5375 SourceLocation &ELoc,
5376 SourceRange &ERange,
5377 bool AllowArraySection,
5378 StringRef DiagType) {
5379 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5380 RefExpr->containsUnexpandedParameterPack())
5381 return std::make_pair(x: nullptr, y: true);
5382
5383 // OpenMP [3.1, C/C++]
5384 // A list item is a variable name.
5385 // OpenMP [2.9.3.3, Restrictions, p.1]
5386 // A variable that is part of another variable (as an array or
5387 // structure element) cannot appear in a private clause.
5388 RefExpr = RefExpr->IgnoreParens();
5389 enum {
5390 NoArrayExpr = -1,
5391 ArraySubscript = 0,
5392 OMPArraySection = 1
5393 } IsArrayExpr = NoArrayExpr;
5394 if (AllowArraySection) {
5395 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(Val: RefExpr)) {
5396 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5397 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base))
5398 Base = TempASE->getBase()->IgnoreParenImpCasts();
5399 RefExpr = Base;
5400 IsArrayExpr = ArraySubscript;
5401 } else if (auto *OASE = dyn_cast_or_null<OMPArraySectionExpr>(Val: RefExpr)) {
5402 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5403 while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Val: Base))
5404 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5405 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base))
5406 Base = TempASE->getBase()->IgnoreParenImpCasts();
5407 RefExpr = Base;
5408 IsArrayExpr = OMPArraySection;
5409 }
5410 }
5411 ELoc = RefExpr->getExprLoc();
5412 ERange = RefExpr->getSourceRange();
5413 RefExpr = RefExpr->IgnoreParenImpCasts();
5414 auto *DE = dyn_cast_or_null<DeclRefExpr>(Val: RefExpr);
5415 auto *ME = dyn_cast_or_null<MemberExpr>(Val: RefExpr);
5416 if ((!DE || !isa<VarDecl>(Val: DE->getDecl())) &&
5417 (S.getCurrentThisType().isNull() || !ME ||
5418 !isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()) ||
5419 !isa<FieldDecl>(Val: ME->getMemberDecl()))) {
5420 if (IsArrayExpr != NoArrayExpr) {
5421 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5422 << IsArrayExpr << ERange;
5423 } else if (!DiagType.empty()) {
5424 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5425 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5426 : 0;
5427 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5428 << DiagSelect << DiagType << ERange;
5429 } else {
5430 S.Diag(ELoc,
5431 AllowArraySection
5432 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5433 : diag::err_omp_expected_var_name_member_expr)
5434 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5435 }
5436 return std::make_pair(x: nullptr, y: false);
5437 }
5438 return std::make_pair(
5439 x: getCanonicalDecl(D: DE ? DE->getDecl() : ME->getMemberDecl()), y: false);
5440}
5441
5442namespace {
5443/// Checks if the allocator is used in uses_allocators clause to be allowed in
5444/// target regions.
5445class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5446 DSAStackTy *S = nullptr;
5447
5448public:
5449 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5450 return S->isUsesAllocatorsDecl(E->getDecl())
5451 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5452 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5453 }
5454 bool VisitStmt(const Stmt *S) {
5455 for (const Stmt *Child : S->children()) {
5456 if (Child && Visit(Child))
5457 return true;
5458 }
5459 return false;
5460 }
5461 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5462};
5463} // namespace
5464
5465static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5466 ArrayRef<OMPClause *> Clauses) {
5467 assert(!S.CurContext->isDependentContext() &&
5468 "Expected non-dependent context.");
5469 auto AllocateRange =
5470 llvm::make_filter_range(Range&: Clauses, Pred: OMPAllocateClause::classof);
5471 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5472 auto PrivateRange = llvm::make_filter_range(Range&: Clauses, Pred: [](const OMPClause *C) {
5473 return isOpenMPPrivate(Kind: C->getClauseKind());
5474 });
5475 for (OMPClause *Cl : PrivateRange) {
5476 MutableArrayRef<Expr *>::iterator I, It, Et;
5477 if (Cl->getClauseKind() == OMPC_private) {
5478 auto *PC = cast<OMPPrivateClause>(Val: Cl);
5479 I = PC->private_copies().begin();
5480 It = PC->varlist_begin();
5481 Et = PC->varlist_end();
5482 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5483 auto *PC = cast<OMPFirstprivateClause>(Val: Cl);
5484 I = PC->private_copies().begin();
5485 It = PC->varlist_begin();
5486 Et = PC->varlist_end();
5487 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5488 auto *PC = cast<OMPLastprivateClause>(Val: Cl);
5489 I = PC->private_copies().begin();
5490 It = PC->varlist_begin();
5491 Et = PC->varlist_end();
5492 } else if (Cl->getClauseKind() == OMPC_linear) {
5493 auto *PC = cast<OMPLinearClause>(Val: Cl);
5494 I = PC->privates().begin();
5495 It = PC->varlist_begin();
5496 Et = PC->varlist_end();
5497 } else if (Cl->getClauseKind() == OMPC_reduction) {
5498 auto *PC = cast<OMPReductionClause>(Val: Cl);
5499 I = PC->privates().begin();
5500 It = PC->varlist_begin();
5501 Et = PC->varlist_end();
5502 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5503 auto *PC = cast<OMPTaskReductionClause>(Val: Cl);
5504 I = PC->privates().begin();
5505 It = PC->varlist_begin();
5506 Et = PC->varlist_end();
5507 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5508 auto *PC = cast<OMPInReductionClause>(Val: Cl);
5509 I = PC->privates().begin();
5510 It = PC->varlist_begin();
5511 Et = PC->varlist_end();
5512 } else {
5513 llvm_unreachable("Expected private clause.");
5514 }
5515 for (Expr *E : llvm::make_range(x: It, y: Et)) {
5516 if (!*I) {
5517 ++I;
5518 continue;
5519 }
5520 SourceLocation ELoc;
5521 SourceRange ERange;
5522 Expr *SimpleRefExpr = E;
5523 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
5524 /*AllowArraySection=*/true);
5525 DeclToCopy.try_emplace(Res.first,
5526 cast<VarDecl>(Val: cast<DeclRefExpr>(Val: *I)->getDecl()));
5527 ++I;
5528 }
5529 }
5530 for (OMPClause *C : AllocateRange) {
5531 auto *AC = cast<OMPAllocateClause>(Val: C);
5532 if (S.getLangOpts().OpenMP >= 50 &&
5533 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5534 isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective()) &&
5535 AC->getAllocator()) {
5536 Expr *Allocator = AC->getAllocator();
5537 // OpenMP, 2.12.5 target Construct
5538 // Memory allocators that do not appear in a uses_allocators clause cannot
5539 // appear as an allocator in an allocate clause or be used in the target
5540 // region unless a requires directive with the dynamic_allocators clause
5541 // is present in the same compilation unit.
5542 AllocatorChecker Checker(Stack);
5543 if (Checker.Visit(Allocator))
5544 S.Diag(Allocator->getExprLoc(),
5545 diag::err_omp_allocator_not_in_uses_allocators)
5546 << Allocator->getSourceRange();
5547 }
5548 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5549 getAllocatorKind(S, Stack, AC->getAllocator());
5550 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5551 // For task, taskloop or target directives, allocation requests to memory
5552 // allocators with the trait access set to thread result in unspecified
5553 // behavior.
5554 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5555 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5556 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5557 S.Diag(AC->getAllocator()->getExprLoc(),
5558 diag::warn_omp_allocate_thread_on_task_target_directive)
5559 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5560 }
5561 for (Expr *E : AC->varlists()) {
5562 SourceLocation ELoc;
5563 SourceRange ERange;
5564 Expr *SimpleRefExpr = E;
5565 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange);
5566 ValueDecl *VD = Res.first;
5567 DSAStackTy::DSAVarData Data = Stack->getTopDSA(D: VD, /*FromParent=*/false);
5568 if (!isOpenMPPrivate(Data.CKind)) {
5569 S.Diag(E->getExprLoc(),
5570 diag::err_omp_expected_private_copy_for_allocate);
5571 continue;
5572 }
5573 VarDecl *PrivateVD = DeclToCopy[VD];
5574 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5575 AllocatorKind, AC->getAllocator()))
5576 continue;
5577 // Placeholder until allocate clause supports align modifier.
5578 Expr *Alignment = nullptr;
5579 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5580 Alignment, E->getSourceRange());
5581 }
5582 }
5583}
5584
5585namespace {
5586/// Rewrite statements and expressions for Sema \p Actions CurContext.
5587///
5588/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5589/// context. DeclRefExpr used inside the new context are changed to refer to the
5590/// captured variable instead.
5591class CaptureVars : public TreeTransform<CaptureVars> {
5592 using BaseTransform = TreeTransform<CaptureVars>;
5593
5594public:
5595 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5596
5597 bool AlwaysRebuild() { return true; }
5598};
5599} // namespace
5600
5601static VarDecl *precomputeExpr(Sema &Actions,
5602 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5603 StringRef Name) {
5604 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5605 VarDecl *NewVar = buildVarDecl(SemaRef&: Actions, Loc: {}, Type: NewE->getType(), Name, Attrs: nullptr,
5606 OrigRef: dyn_cast<DeclRefExpr>(Val: E->IgnoreImplicit()));
5607 auto *NewDeclStmt = cast<DeclStmt>(Val: AssertSuccess(
5608 R: Actions.ActOnDeclStmt(Decl: Actions.ConvertDeclToDeclGroup(NewVar), StartLoc: {}, EndLoc: {})));
5609 Actions.AddInitializerToDecl(dcl: NewDeclStmt->getSingleDecl(), init: NewE, DirectInit: false);
5610 BodyStmts.push_back(Elt: NewDeclStmt);
5611 return NewVar;
5612}
5613
5614/// Create a closure that computes the number of iterations of a loop.
5615///
5616/// \param Actions The Sema object.
5617/// \param LogicalTy Type for the logical iteration number.
5618/// \param Rel Comparison operator of the loop condition.
5619/// \param StartExpr Value of the loop counter at the first iteration.
5620/// \param StopExpr Expression the loop counter is compared against in the loop
5621/// condition. \param StepExpr Amount of increment after each iteration.
5622///
5623/// \return Closure (CapturedStmt) of the distance calculation.
5624static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5625 BinaryOperator::Opcode Rel,
5626 Expr *StartExpr, Expr *StopExpr,
5627 Expr *StepExpr) {
5628 ASTContext &Ctx = Actions.getASTContext();
5629 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(T: LogicalTy);
5630
5631 // Captured regions currently don't support return values, we use an
5632 // out-parameter instead. All inputs are implicit captures.
5633 // TODO: Instead of capturing each DeclRefExpr occurring in
5634 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5635 QualType ResultTy = Ctx.getLValueReferenceType(T: LogicalTy);
5636 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5637 {StringRef(), QualType()}};
5638 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5639
5640 Stmt *Body;
5641 {
5642 Sema::CompoundScopeRAII CompoundScope(Actions);
5643 CapturedDecl *CS = cast<CapturedDecl>(Val: Actions.CurContext);
5644
5645 // Get the LValue expression for the result.
5646 ImplicitParamDecl *DistParam = CS->getParam(i: 0);
5647 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5648 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5649
5650 SmallVector<Stmt *, 4> BodyStmts;
5651
5652 // Capture all referenced variable references.
5653 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5654 // CapturedStmt, we could compute them before and capture the result, to be
5655 // used jointly with the LoopVar function.
5656 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, E: StartExpr, Name: ".start");
5657 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, E: StopExpr, Name: ".stop");
5658 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, E: StepExpr, Name: ".step");
5659 auto BuildVarRef = [&](VarDecl *VD) {
5660 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5661 };
5662
5663 IntegerLiteral *Zero = IntegerLiteral::Create(
5664 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 0), type: LogicalTy, l: {});
5665 IntegerLiteral *One = IntegerLiteral::Create(
5666 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 1), type: LogicalTy, l: {});
5667 Expr *Dist;
5668 if (Rel == BO_NE) {
5669 // When using a != comparison, the increment can be +1 or -1. This can be
5670 // dynamic at runtime, so we need to check for the direction.
5671 Expr *IsNegStep = AssertSuccess(
5672 Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_LT, LHSExpr: BuildVarRef(NewStep), RHSExpr: Zero));
5673
5674 // Positive increment.
5675 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5676 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStop), RHSExpr: BuildVarRef(NewStart)));
5677 ForwardRange = AssertSuccess(
5678 R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: ForwardRange));
5679 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5680 S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: ForwardRange, RHSExpr: BuildVarRef(NewStep)));
5681
5682 // Negative increment.
5683 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5684 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5685 BackwardRange = AssertSuccess(
5686 R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: BackwardRange));
5687 Expr *NegIncAmount = AssertSuccess(
5688 Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: BuildVarRef(NewStep)));
5689 Expr *BackwardDist = AssertSuccess(
5690 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: BackwardRange, RHSExpr: NegIncAmount));
5691
5692 // Use the appropriate case.
5693 Dist = AssertSuccess(R: Actions.ActOnConditionalOp(
5694 QuestionLoc: {}, ColonLoc: {}, CondExpr: IsNegStep, LHSExpr: BackwardDist, RHSExpr: ForwardDist));
5695 } else {
5696 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5697 "Expected one of these relational operators");
5698
5699 // We can derive the direction from any other comparison operator. It is
5700 // non well-formed OpenMP if Step increments/decrements in the other
5701 // directions. Whether at least the first iteration passes the loop
5702 // condition.
5703 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5704 S: nullptr, OpLoc: {}, Opc: Rel, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5705
5706 // Compute the range between first and last counter value.
5707 Expr *Range;
5708 if (Rel == BO_GE || Rel == BO_GT)
5709 Range = AssertSuccess(Actions.BuildBinOp(
5710 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5711 else
5712 Range = AssertSuccess(Actions.BuildBinOp(
5713 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStop), RHSExpr: BuildVarRef(NewStart)));
5714
5715 // Ensure unsigned range space.
5716 Range =
5717 AssertSuccess(R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: Range));
5718
5719 if (Rel == BO_LE || Rel == BO_GE) {
5720 // Add one to the range if the relational operator is inclusive.
5721 Range =
5722 AssertSuccess(R: Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5723 }
5724
5725 // Divide by the absolute step amount. If the range is not a multiple of
5726 // the step size, rounding-up the effective upper bound ensures that the
5727 // last iteration is included.
5728 // Note that the rounding-up may cause an overflow in a temporry that
5729 // could be avoided, but would have occurred in a C-style for-loop as
5730 // well.
5731 Expr *Divisor = BuildVarRef(NewStep);
5732 if (Rel == BO_GE || Rel == BO_GT)
5733 Divisor =
5734 AssertSuccess(R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: Divisor));
5735 Expr *DivisorMinusOne =
5736 AssertSuccess(R: Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5737 Expr *RangeRoundUp = AssertSuccess(
5738 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: Range, RHSExpr: DivisorMinusOne));
5739 Dist = AssertSuccess(
5740 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: RangeRoundUp, RHSExpr: Divisor));
5741
5742 // If there is not at least one iteration, the range contains garbage. Fix
5743 // to zero in this case.
5744 Dist = AssertSuccess(
5745 R: Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5746 }
5747
5748 // Assign the result to the out-parameter.
5749 Stmt *ResultAssign = AssertSuccess(R: Actions.BuildBinOp(
5750 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5751 BodyStmts.push_back(Elt: ResultAssign);
5752
5753 Body = AssertSuccess(R: Actions.ActOnCompoundStmt(L: {}, R: {}, Elts: BodyStmts, isStmtExpr: false));
5754 }
5755
5756 return cast<CapturedStmt>(
5757 Val: AssertSuccess(R: Actions.ActOnCapturedRegionEnd(S: Body)));
5758}
5759
5760/// Create a closure that computes the loop variable from the logical iteration
5761/// number.
5762///
5763/// \param Actions The Sema object.
5764/// \param LoopVarTy Type for the loop variable used for result value.
5765/// \param LogicalTy Type for the logical iteration number.
5766/// \param StartExpr Value of the loop counter at the first iteration.
5767/// \param Step Amount of increment after each iteration.
5768/// \param Deref Whether the loop variable is a dereference of the loop
5769/// counter variable.
5770///
5771/// \return Closure (CapturedStmt) of the loop value calculation.
5772static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5773 QualType LogicalTy,
5774 DeclRefExpr *StartExpr, Expr *Step,
5775 bool Deref) {
5776 ASTContext &Ctx = Actions.getASTContext();
5777
5778 // Pass the result as an out-parameter. Passing as return value would require
5779 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5780 // invoke a copy constructor.
5781 QualType TargetParamTy = Ctx.getLValueReferenceType(T: LoopVarTy);
5782 Sema::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5783 {"Logical", LogicalTy},
5784 {StringRef(), QualType()}};
5785 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5786
5787 // Capture the initial iterator which represents the LoopVar value at the
5788 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5789 // it in every iteration, capture it by value before it is modified.
5790 VarDecl *StartVar = cast<VarDecl>(Val: StartExpr->getDecl());
5791 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5792 Sema::TryCapture_ExplicitByVal, {});
5793 (void)Invalid;
5794 assert(!Invalid && "Expecting capture-by-value to work.");
5795
5796 Expr *Body;
5797 {
5798 Sema::CompoundScopeRAII CompoundScope(Actions);
5799 auto *CS = cast<CapturedDecl>(Val: Actions.CurContext);
5800
5801 ImplicitParamDecl *TargetParam = CS->getParam(i: 0);
5802 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5803 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5804 ImplicitParamDecl *IndvarParam = CS->getParam(i: 1);
5805 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5806 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5807
5808 // Capture the Start expression.
5809 CaptureVars Recap(Actions);
5810 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5811 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5812
5813 Expr *Skip = AssertSuccess(
5814 R: Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5815 // TODO: Explicitly cast to the iterator's difference_type instead of
5816 // relying on implicit conversion.
5817 Expr *Advanced =
5818 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: NewStart, RHSExpr: Skip));
5819
5820 if (Deref) {
5821 // For range-based for-loops convert the loop counter value to a concrete
5822 // loop variable value by dereferencing the iterator.
5823 Advanced =
5824 AssertSuccess(R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Deref, Input: Advanced));
5825 }
5826
5827 // Assign the result to the output parameter.
5828 Body = AssertSuccess(R: Actions.BuildBinOp(Actions.getCurScope(), {},
5829 BO_Assign, TargetRef, Advanced));
5830 }
5831 return cast<CapturedStmt>(
5832 Val: AssertSuccess(R: Actions.ActOnCapturedRegionEnd(Body)));
5833}
5834
5835StmtResult Sema::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
5836 ASTContext &Ctx = getASTContext();
5837
5838 // Extract the common elements of ForStmt and CXXForRangeStmt:
5839 // Loop variable, repeat condition, increment
5840 Expr *Cond, *Inc;
5841 VarDecl *LIVDecl, *LUVDecl;
5842 if (auto *For = dyn_cast<ForStmt>(Val: AStmt)) {
5843 Stmt *Init = For->getInit();
5844 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Val: Init)) {
5845 // For statement declares loop variable.
5846 LIVDecl = cast<VarDecl>(Val: LCVarDeclStmt->getSingleDecl());
5847 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Val: Init)) {
5848 // For statement reuses variable.
5849 assert(LCAssign->getOpcode() == BO_Assign &&
5850 "init part must be a loop variable assignment");
5851 auto *CounterRef = cast<DeclRefExpr>(Val: LCAssign->getLHS());
5852 LIVDecl = cast<VarDecl>(Val: CounterRef->getDecl());
5853 } else
5854 llvm_unreachable("Cannot determine loop variable");
5855 LUVDecl = LIVDecl;
5856
5857 Cond = For->getCond();
5858 Inc = For->getInc();
5859 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(Val: AStmt)) {
5860 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5861 LIVDecl = cast<VarDecl>(Val: BeginStmt->getSingleDecl());
5862 LUVDecl = RangeFor->getLoopVariable();
5863
5864 Cond = RangeFor->getCond();
5865 Inc = RangeFor->getInc();
5866 } else
5867 llvm_unreachable("unhandled kind of loop");
5868
5869 QualType CounterTy = LIVDecl->getType();
5870 QualType LVTy = LUVDecl->getType();
5871
5872 // Analyze the loop condition.
5873 Expr *LHS, *RHS;
5874 BinaryOperator::Opcode CondRel;
5875 Cond = Cond->IgnoreImplicit();
5876 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Val: Cond)) {
5877 LHS = CondBinExpr->getLHS();
5878 RHS = CondBinExpr->getRHS();
5879 CondRel = CondBinExpr->getOpcode();
5880 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Val: Cond)) {
5881 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5882 LHS = CondCXXOp->getArg(0);
5883 RHS = CondCXXOp->getArg(1);
5884 switch (CondCXXOp->getOperator()) {
5885 case OO_ExclaimEqual:
5886 CondRel = BO_NE;
5887 break;
5888 case OO_Less:
5889 CondRel = BO_LT;
5890 break;
5891 case OO_LessEqual:
5892 CondRel = BO_LE;
5893 break;
5894 case OO_Greater:
5895 CondRel = BO_GT;
5896 break;
5897 case OO_GreaterEqual:
5898 CondRel = BO_GE;
5899 break;
5900 default:
5901 llvm_unreachable("unexpected iterator operator");
5902 }
5903 } else
5904 llvm_unreachable("unexpected loop condition");
5905
5906 // Normalize such that the loop counter is on the LHS.
5907 if (!isa<DeclRefExpr>(Val: LHS->IgnoreImplicit()) ||
5908 cast<DeclRefExpr>(Val: LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5909 std::swap(a&: LHS, b&: RHS);
5910 CondRel = BinaryOperator::reverseComparisonOp(Opc: CondRel);
5911 }
5912 auto *CounterRef = cast<DeclRefExpr>(Val: LHS->IgnoreImplicit());
5913
5914 // Decide the bit width for the logical iteration counter. By default use the
5915 // unsigned ptrdiff_t integer size (for iterators and pointers).
5916 // TODO: For iterators, use iterator::difference_type,
5917 // std::iterator_traits<>::difference_type or decltype(it - end).
5918 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5919 if (CounterTy->isIntegerType()) {
5920 unsigned BitWidth = Ctx.getIntWidth(T: CounterTy);
5921 LogicalTy = Ctx.getIntTypeForBitwidth(DestWidth: BitWidth, Signed: false);
5922 }
5923
5924 // Analyze the loop increment.
5925 Expr *Step;
5926 if (auto *IncUn = dyn_cast<UnaryOperator>(Val: Inc)) {
5927 int Direction;
5928 switch (IncUn->getOpcode()) {
5929 case UO_PreInc:
5930 case UO_PostInc:
5931 Direction = 1;
5932 break;
5933 case UO_PreDec:
5934 case UO_PostDec:
5935 Direction = -1;
5936 break;
5937 default:
5938 llvm_unreachable("unhandled unary increment operator");
5939 }
5940 Step = IntegerLiteral::Create(
5941 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), Direction), type: LogicalTy, l: {});
5942 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Val: Inc)) {
5943 if (IncBin->getOpcode() == BO_AddAssign) {
5944 Step = IncBin->getRHS();
5945 } else if (IncBin->getOpcode() == BO_SubAssign) {
5946 Step =
5947 AssertSuccess(R: BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: IncBin->getRHS()));
5948 } else
5949 llvm_unreachable("unhandled binary increment operator");
5950 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Val: Inc)) {
5951 switch (CondCXXOp->getOperator()) {
5952 case OO_PlusPlus:
5953 Step = IntegerLiteral::Create(
5954 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 1), type: LogicalTy, l: {});
5955 break;
5956 case OO_MinusMinus:
5957 Step = IntegerLiteral::Create(
5958 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), -1), type: LogicalTy, l: {});
5959 break;
5960 case OO_PlusEqual:
5961 Step = CondCXXOp->getArg(1);
5962 break;
5963 case OO_MinusEqual:
5964 Step = AssertSuccess(
5965 BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: CondCXXOp->getArg(1)));
5966 break;
5967 default:
5968 llvm_unreachable("unhandled overloaded increment operator");
5969 }
5970 } else
5971 llvm_unreachable("unknown increment expression");
5972
5973 CapturedStmt *DistanceFunc =
5974 buildDistanceFunc(Actions&: *this, LogicalTy, Rel: CondRel, StartExpr: LHS, StopExpr: RHS, StepExpr: Step);
5975 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5976 Actions&: *this, LoopVarTy: LVTy, LogicalTy, StartExpr: CounterRef, Step, Deref: isa<CXXForRangeStmt>(Val: AStmt));
5977 DeclRefExpr *LVRef = BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue,
5978 {}, nullptr, nullptr, {}, nullptr);
5979 return OMPCanonicalLoop::create(Ctx: getASTContext(), LoopStmt: AStmt, DistanceFunc,
5980 LoopVarFunc, LoopVarRef: LVRef);
5981}
5982
5983StmtResult Sema::ActOnOpenMPLoopnest(Stmt *AStmt) {
5984 // Handle a literal loop.
5985 if (isa<ForStmt>(Val: AStmt) || isa<CXXForRangeStmt>(Val: AStmt))
5986 return ActOnOpenMPCanonicalLoop(AStmt);
5987
5988 // If not a literal loop, it must be the result of a loop transformation.
5989 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(Val: AStmt);
5990 assert(
5991 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5992 "Loop transformation directive expected");
5993 return LoopTransform;
5994}
5995
5996static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
5997 CXXScopeSpec &MapperIdScopeSpec,
5998 const DeclarationNameInfo &MapperId,
5999 QualType Type,
6000 Expr *UnresolvedMapper);
6001
6002/// Perform DFS through the structure/class data members trying to find
6003/// member(s) with user-defined 'default' mapper and generate implicit map
6004/// clauses for such members with the found 'default' mapper.
6005static void
6006processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
6007 SmallVectorImpl<OMPClause *> &Clauses) {
6008 // Check for the deault mapper for data members.
6009 if (S.getLangOpts().OpenMP < 50)
6010 return;
6011 SmallVector<OMPClause *, 4> ImplicitMaps;
6012 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6013 auto *C = dyn_cast<OMPMapClause>(Val: Clauses[Cnt]);
6014 if (!C)
6015 continue;
6016 SmallVector<Expr *, 4> SubExprs;
6017 auto *MI = C->mapperlist_begin();
6018 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
6019 ++I, ++MI) {
6020 // Expression is mapped using mapper - skip it.
6021 if (*MI)
6022 continue;
6023 Expr *E = *I;
6024 // Expression is dependent - skip it, build the mapper when it gets
6025 // instantiated.
6026 if (E->isTypeDependent() || E->isValueDependent() ||
6027 E->containsUnexpandedParameterPack())
6028 continue;
6029 // Array section - need to check for the mapping of the array section
6030 // element.
6031 QualType CanonType = E->getType().getCanonicalType();
6032 if (CanonType->isSpecificBuiltinType(K: BuiltinType::OMPArraySection)) {
6033 const auto *OASE = cast<OMPArraySectionExpr>(Val: E->IgnoreParenImpCasts());
6034 QualType BaseType =
6035 OMPArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
6036 QualType ElemType;
6037 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6038 ElemType = ATy->getElementType();
6039 else
6040 ElemType = BaseType->getPointeeType();
6041 CanonType = ElemType;
6042 }
6043
6044 // DFS over data members in structures/classes.
6045 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
6046 1, {CanonType, nullptr});
6047 llvm::DenseMap<const Type *, Expr *> Visited;
6048 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
6049 1, {nullptr, 1});
6050 while (!Types.empty()) {
6051 QualType BaseType;
6052 FieldDecl *CurFD;
6053 std::tie(args&: BaseType, args&: CurFD) = Types.pop_back_val();
6054 while (ParentChain.back().second == 0)
6055 ParentChain.pop_back();
6056 --ParentChain.back().second;
6057 if (BaseType.isNull())
6058 continue;
6059 // Only structs/classes are allowed to have mappers.
6060 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6061 if (!RD)
6062 continue;
6063 auto It = Visited.find(Val: BaseType.getTypePtr());
6064 if (It == Visited.end()) {
6065 // Try to find the associated user-defined mapper.
6066 CXXScopeSpec MapperIdScopeSpec;
6067 DeclarationNameInfo DefaultMapperId;
6068 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
6069 ID: &S.Context.Idents.get(Name: "default")));
6070 DefaultMapperId.setLoc(E->getExprLoc());
6071 ExprResult ER = buildUserDefinedMapperRef(
6072 SemaRef&: S, S: Stack->getCurScope(), MapperIdScopeSpec, MapperId: DefaultMapperId,
6073 Type: BaseType, /*UnresolvedMapper=*/nullptr);
6074 if (ER.isInvalid())
6075 continue;
6076 It = Visited.try_emplace(Key: BaseType.getTypePtr(), Args: ER.get()).first;
6077 }
6078 // Found default mapper.
6079 if (It->second) {
6080 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6081 VK_LValue, OK_Ordinary, E);
6082 OE->setIsUnique(/*V=*/true);
6083 Expr *BaseExpr = OE;
6084 for (const auto &P : ParentChain) {
6085 if (P.first) {
6086 BaseExpr = S.BuildMemberExpr(
6087 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6088 NestedNameSpecifierLoc(), SourceLocation(), P.first,
6089 DeclAccessPair::make(D: P.first, AS: P.first->getAccess()),
6090 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6091 P.first->getType(), VK_LValue, OK_Ordinary);
6092 BaseExpr = S.DefaultLvalueConversion(E: BaseExpr).get();
6093 }
6094 }
6095 if (CurFD)
6096 BaseExpr = S.BuildMemberExpr(
6097 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6098 NestedNameSpecifierLoc(), SourceLocation(), CurFD,
6099 DeclAccessPair::make(D: CurFD, AS: CurFD->getAccess()),
6100 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6101 CurFD->getType(), VK_LValue, OK_Ordinary);
6102 SubExprs.push_back(Elt: BaseExpr);
6103 continue;
6104 }
6105 // Check for the "default" mapper for data members.
6106 bool FirstIter = true;
6107 for (FieldDecl *FD : RD->fields()) {
6108 if (!FD)
6109 continue;
6110 QualType FieldTy = FD->getType();
6111 if (FieldTy.isNull() ||
6112 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6113 continue;
6114 if (FirstIter) {
6115 FirstIter = false;
6116 ParentChain.emplace_back(Args&: CurFD, Args: 1);
6117 } else {
6118 ++ParentChain.back().second;
6119 }
6120 Types.emplace_back(Args&: FieldTy, Args&: FD);
6121 }
6122 }
6123 }
6124 if (SubExprs.empty())
6125 continue;
6126 CXXScopeSpec MapperIdScopeSpec;
6127 DeclarationNameInfo MapperId;
6128 if (OMPClause *NewClause = S.ActOnOpenMPMapClause(
6129 IteratorModifier: nullptr, MapTypeModifiers: C->getMapTypeModifiers(), MapTypeModifiersLoc: C->getMapTypeModifiersLoc(),
6130 MapperIdScopeSpec, MapperId, MapType: C->getMapType(),
6131 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(),
6132 VarList: SubExprs, Locs: OMPVarListLocTy()))
6133 Clauses.push_back(Elt: NewClause);
6134 }
6135}
6136
6137bool Sema::mapLoopConstruct(llvm::SmallVector<OMPClause *> &ClausesWithoutBind,
6138 ArrayRef<OMPClause *> Clauses,
6139 OpenMPBindClauseKind &BindKind,
6140 OpenMPDirectiveKind &Kind,
6141 OpenMPDirectiveKind &PrevMappedDirective,
6142 SourceLocation StartLoc, SourceLocation EndLoc,
6143 const DeclarationNameInfo &DirName,
6144 OpenMPDirectiveKind CancelRegion) {
6145
6146 bool UseClausesWithoutBind = false;
6147
6148 // Restricting to "#pragma omp loop bind"
6149 if (getLangOpts().OpenMP >= 50 && Kind == OMPD_loop) {
6150
6151 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6152
6153 if (BindKind == OMPC_BIND_unknown) {
6154 // Setting the enclosing teams or parallel construct for the loop
6155 // directive without bind clause.
6156 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6157
6158 if (ParentDirective == OMPD_unknown) {
6159 Diag(DSAStack->getDefaultDSALocation(),
6160 diag::err_omp_bind_required_on_loop);
6161 } else if (ParentDirective == OMPD_parallel ||
6162 ParentDirective == OMPD_target_parallel) {
6163 BindKind = OMPC_BIND_parallel;
6164 } else if (ParentDirective == OMPD_teams ||
6165 ParentDirective == OMPD_target_teams) {
6166 BindKind = OMPC_BIND_teams;
6167 }
6168 } else {
6169 // bind clause is present in loop directive. When the loop directive is
6170 // changed to a new directive the bind clause is not used. So, we should
6171 // set flag indicating to only use the clauses that aren't the
6172 // bind clause.
6173 UseClausesWithoutBind = true;
6174 }
6175
6176 for (OMPClause *C : Clauses) {
6177 // Spec restriction : bind(teams) and reduction not permitted.
6178 if (BindKind == OMPC_BIND_teams &&
6179 C->getClauseKind() == llvm::omp::Clause::OMPC_reduction)
6180 Diag(DSAStack->getDefaultDSALocation(),
6181 diag::err_omp_loop_reduction_clause);
6182
6183 // A new Vector ClausesWithoutBind, which does not contain the bind
6184 // clause, for passing to new directive.
6185 if (C->getClauseKind() != llvm::omp::Clause::OMPC_bind)
6186 ClausesWithoutBind.push_back(Elt: C);
6187 }
6188
6189 switch (BindKind) {
6190 case OMPC_BIND_parallel:
6191 Kind = OMPD_for;
6192 DSAStack->setCurrentDirective(OMPD_for);
6193 DSAStack->setMappedDirective(OMPD_loop);
6194 PrevMappedDirective = OMPD_loop;
6195 break;
6196 case OMPC_BIND_teams:
6197 Kind = OMPD_distribute;
6198 DSAStack->setCurrentDirective(OMPD_distribute);
6199 DSAStack->setMappedDirective(OMPD_loop);
6200 PrevMappedDirective = OMPD_loop;
6201 break;
6202 case OMPC_BIND_thread:
6203 Kind = OMPD_simd;
6204 DSAStack->setCurrentDirective(OMPD_simd);
6205 DSAStack->setMappedDirective(OMPD_loop);
6206 PrevMappedDirective = OMPD_loop;
6207 break;
6208 case OMPC_BIND_unknown:
6209 break;
6210 }
6211 } else if (PrevMappedDirective == OMPD_loop) {
6212 /// An initial pass after recognizing all the statements is done in the
6213 /// Parser when the directive OMPD_loop is mapped to OMPD_for,
6214 /// OMPD_distribute or OMPD_simd. A second transform pass with call from
6215 /// clang::TreeTransform::TransformOMPExecutableDirective() is done
6216 /// with the Directive as one of the above mapped directive without
6217 /// the bind clause. Then "PrevMappedDirective" stored in the
6218 /// OMPExecutableDirective is accessed and hence this else statement.
6219
6220 DSAStack->setMappedDirective(OMPD_loop);
6221 }
6222
6223 return UseClausesWithoutBind;
6224}
6225
6226StmtResult Sema::ActOnOpenMPExecutableDirective(
6227 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6228 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6229 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc,
6230 OpenMPDirectiveKind PrevMappedDirective) {
6231 StmtResult Res = StmtError();
6232 OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
6233 llvm::SmallVector<OMPClause *> ClausesWithoutBind;
6234 bool UseClausesWithoutBind = false;
6235
6236 if (const OMPBindClause *BC =
6237 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6238 BindKind = BC->getBindKind();
6239
6240 // Variable used to note down the DirectiveKind because mapLoopConstruct may
6241 // change "Kind" variable, due to mapping of "omp loop" to other directives.
6242 OpenMPDirectiveKind DK = Kind;
6243 if (Kind == OMPD_loop || PrevMappedDirective == OMPD_loop) {
6244 UseClausesWithoutBind = mapLoopConstruct(
6245 ClausesWithoutBind, Clauses, BindKind, Kind, PrevMappedDirective,
6246 StartLoc, EndLoc, DirName, CancelRegion);
6247 DK = OMPD_loop;
6248 }
6249
6250 // First check CancelRegion which is then used in checkNestingOfRegions.
6251 if (checkCancelRegion(SemaRef&: *this, CurrentRegion: Kind, CancelRegion, StartLoc) ||
6252 checkNestingOfRegions(SemaRef&: *this, DSAStack, CurrentRegion: DK, CurrentName: DirName, CancelRegion,
6253 BindKind, StartLoc)) {
6254 return StmtError();
6255 }
6256
6257 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6258 if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(Kind) ||
6259 isOpenMPTargetDataManagementDirective(Kind)))
6260 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6261
6262 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6263 VarsWithInheritedDSAType VarsWithInheritedDSA;
6264 bool ErrorFound = false;
6265 if (getLangOpts().OpenMP >= 50 && UseClausesWithoutBind) {
6266 ClausesWithImplicit.append(in_start: ClausesWithoutBind.begin(),
6267 in_end: ClausesWithoutBind.end());
6268 } else {
6269 ClausesWithImplicit.append(in_start: Clauses.begin(), in_end: Clauses.end());
6270 }
6271 if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic &&
6272 Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master &&
6273 Kind != OMPD_masked && !isOpenMPLoopTransformationDirective(Kind)) {
6274 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6275
6276 // Check default data sharing attributes for referenced variables.
6277 DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(Val: AStmt));
6278 int ThisCaptureLevel = getOpenMPCaptureLevels(DKind: Kind);
6279 Stmt *S = AStmt;
6280 while (--ThisCaptureLevel >= 0)
6281 S = cast<CapturedStmt>(Val: S)->getCapturedStmt();
6282 DSAChecker.Visit(S);
6283 if (!isOpenMPTargetDataManagementDirective(DKind: Kind) &&
6284 !isOpenMPTaskingDirective(Kind)) {
6285 // Visit subcaptures to generate implicit clauses for captured vars.
6286 auto *CS = cast<CapturedStmt>(Val: AStmt);
6287 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
6288 getOpenMPCaptureRegions(CaptureRegions, DKind: Kind);
6289 // Ignore outer tasking regions for target directives.
6290 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6291 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
6292 DSAChecker.visitSubCaptures(S: CS);
6293 }
6294 if (DSAChecker.isErrorFound())
6295 return StmtError();
6296 // Generate list of implicitly defined firstprivate variables.
6297 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6298
6299 SmallVector<Expr *, 4> ImplicitFirstprivates(
6300 DSAChecker.getImplicitFirstprivate().begin(),
6301 DSAChecker.getImplicitFirstprivate().end());
6302 SmallVector<Expr *, 4> ImplicitPrivates(
6303 DSAChecker.getImplicitPrivate().begin(),
6304 DSAChecker.getImplicitPrivate().end());
6305 const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
6306 SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
6307 SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
6308 ImplicitMapModifiers[DefaultmapKindNum];
6309 SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
6310 ImplicitMapModifiersLoc[DefaultmapKindNum];
6311 // Get the original location of present modifier from Defaultmap clause.
6312 SourceLocation PresentModifierLocs[DefaultmapKindNum];
6313 for (OMPClause *C : Clauses) {
6314 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(Val: C))
6315 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6316 PresentModifierLocs[DMC->getDefaultmapKind()] =
6317 DMC->getDefaultmapModifierLoc();
6318 }
6319 for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6320 auto Kind = static_cast<OpenMPDefaultmapClauseKind>(VC);
6321 for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6322 ArrayRef<Expr *> ImplicitMap = DSAChecker.getImplicitMap(
6323 DK: Kind, MK: static_cast<OpenMPMapClauseKind>(I));
6324 ImplicitMaps[VC][I].append(in_start: ImplicitMap.begin(), in_end: ImplicitMap.end());
6325 }
6326 ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
6327 DSAChecker.getImplicitMapModifier(Kind);
6328 ImplicitMapModifiers[VC].append(in_start: ImplicitModifier.begin(),
6329 in_end: ImplicitModifier.end());
6330 std::fill_n(first: std::back_inserter(x&: ImplicitMapModifiersLoc[VC]),
6331 n: ImplicitModifier.size(), value: PresentModifierLocs[VC]);
6332 }
6333 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6334 for (OMPClause *C : Clauses) {
6335 if (auto *IRC = dyn_cast<OMPInReductionClause>(Val: C)) {
6336 for (Expr *E : IRC->taskgroup_descriptors())
6337 if (E)
6338 ImplicitFirstprivates.emplace_back(Args&: E);
6339 }
6340 // OpenMP 5.0, 2.10.1 task Construct
6341 // [detach clause]... The event-handle will be considered as if it was
6342 // specified on a firstprivate clause.
6343 if (auto *DC = dyn_cast<OMPDetachClause>(Val: C))
6344 ImplicitFirstprivates.push_back(Elt: DC->getEventHandler());
6345 }
6346 if (!ImplicitFirstprivates.empty()) {
6347 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6348 VarList: ImplicitFirstprivates, StartLoc: SourceLocation(), LParenLoc: SourceLocation(),
6349 EndLoc: SourceLocation())) {
6350 ClausesWithImplicit.push_back(Elt: Implicit);
6351 ErrorFound = cast<OMPFirstprivateClause>(Val: Implicit)->varlist_size() !=
6352 ImplicitFirstprivates.size();
6353 } else {
6354 ErrorFound = true;
6355 }
6356 }
6357 if (!ImplicitPrivates.empty()) {
6358 if (OMPClause *Implicit =
6359 ActOnOpenMPPrivateClause(VarList: ImplicitPrivates, StartLoc: SourceLocation(),
6360 LParenLoc: SourceLocation(), EndLoc: SourceLocation())) {
6361 ClausesWithImplicit.push_back(Elt: Implicit);
6362 ErrorFound = cast<OMPPrivateClause>(Val: Implicit)->varlist_size() !=
6363 ImplicitPrivates.size();
6364 } else {
6365 ErrorFound = true;
6366 }
6367 }
6368 // OpenMP 5.0 [2.19.7]
6369 // If a list item appears in a reduction, lastprivate or linear
6370 // clause on a combined target construct then it is treated as
6371 // if it also appears in a map clause with a map-type of tofrom
6372 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6373 isOpenMPTargetExecutionDirective(Kind)) {
6374 SmallVector<Expr *, 4> ImplicitExprs;
6375 for (OMPClause *C : Clauses) {
6376 if (auto *RC = dyn_cast<OMPReductionClause>(Val: C))
6377 for (Expr *E : RC->varlists())
6378 if (!isa<DeclRefExpr>(Val: E->IgnoreParenImpCasts()))
6379 ImplicitExprs.emplace_back(Args&: E);
6380 }
6381 if (!ImplicitExprs.empty()) {
6382 ArrayRef<Expr *> Exprs = ImplicitExprs;
6383 CXXScopeSpec MapperIdScopeSpec;
6384 DeclarationNameInfo MapperId;
6385 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6386 IteratorModifier: nullptr, MapTypeModifiers: OMPC_MAP_MODIFIER_unknown, MapTypeModifiersLoc: SourceLocation(),
6387 MapperIdScopeSpec, MapperId, MapType: OMPC_MAP_tofrom,
6388 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(),
6389 VarList: Exprs, Locs: OMPVarListLocTy(), /*NoDiagnose=*/true))
6390 ClausesWithImplicit.emplace_back(Args&: Implicit);
6391 }
6392 }
6393 for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) {
6394 int ClauseKindCnt = -1;
6395 for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
6396 ++ClauseKindCnt;
6397 if (ImplicitMap.empty())
6398 continue;
6399 CXXScopeSpec MapperIdScopeSpec;
6400 DeclarationNameInfo MapperId;
6401 auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6402 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6403 IteratorModifier: nullptr, MapTypeModifiers: ImplicitMapModifiers[I], MapTypeModifiersLoc: ImplicitMapModifiersLoc[I],
6404 MapperIdScopeSpec, MapperId, MapType: Kind, /*IsMapTypeImplicit=*/true,
6405 MapLoc: SourceLocation(), ColonLoc: SourceLocation(), VarList: ImplicitMap,
6406 Locs: OMPVarListLocTy())) {
6407 ClausesWithImplicit.emplace_back(Args&: Implicit);
6408 ErrorFound |= cast<OMPMapClause>(Val: Implicit)->varlist_size() !=
6409 ImplicitMap.size();
6410 } else {
6411 ErrorFound = true;
6412 }
6413 }
6414 }
6415 // Build expressions for implicit maps of data members with 'default'
6416 // mappers.
6417 if (LangOpts.OpenMP >= 50)
6418 processImplicitMapsWithDefaultMappers(S&: *this, DSAStack,
6419 Clauses&: ClausesWithImplicit);
6420 }
6421
6422 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6423 switch (Kind) {
6424 case OMPD_parallel:
6425 Res = ActOnOpenMPParallelDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6426 EndLoc);
6427 AllowedNameModifiers.push_back(OMPD_parallel);
6428 break;
6429 case OMPD_simd:
6430 Res = ActOnOpenMPSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6431 VarsWithImplicitDSA&: VarsWithInheritedDSA);
6432 if (LangOpts.OpenMP >= 50)
6433 AllowedNameModifiers.push_back(OMPD_simd);
6434 break;
6435 case OMPD_tile:
6436 Res =
6437 ActOnOpenMPTileDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6438 break;
6439 case OMPD_unroll:
6440 Res = ActOnOpenMPUnrollDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6441 EndLoc);
6442 break;
6443 case OMPD_for:
6444 Res = ActOnOpenMPForDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6445 VarsWithImplicitDSA&: VarsWithInheritedDSA);
6446 break;
6447 case OMPD_for_simd:
6448 Res = ActOnOpenMPForSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6449 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6450 if (LangOpts.OpenMP >= 50)
6451 AllowedNameModifiers.push_back(OMPD_simd);
6452 break;
6453 case OMPD_sections:
6454 Res = ActOnOpenMPSectionsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6455 EndLoc);
6456 break;
6457 case OMPD_section:
6458 assert(ClausesWithImplicit.empty() &&
6459 "No clauses are allowed for 'omp section' directive");
6460 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6461 break;
6462 case OMPD_single:
6463 Res = ActOnOpenMPSingleDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6464 EndLoc);
6465 break;
6466 case OMPD_master:
6467 assert(ClausesWithImplicit.empty() &&
6468 "No clauses are allowed for 'omp master' directive");
6469 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6470 break;
6471 case OMPD_masked:
6472 Res = ActOnOpenMPMaskedDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6473 EndLoc);
6474 break;
6475 case OMPD_critical:
6476 Res = ActOnOpenMPCriticalDirective(DirName, Clauses: ClausesWithImplicit, AStmt,
6477 StartLoc, EndLoc);
6478 break;
6479 case OMPD_parallel_for:
6480 Res = ActOnOpenMPParallelForDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6481 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6482 AllowedNameModifiers.push_back(OMPD_parallel);
6483 break;
6484 case OMPD_parallel_for_simd:
6485 Res = ActOnOpenMPParallelForSimdDirective(
6486 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6487 AllowedNameModifiers.push_back(OMPD_parallel);
6488 if (LangOpts.OpenMP >= 50)
6489 AllowedNameModifiers.push_back(OMPD_simd);
6490 break;
6491 case OMPD_scope:
6492 Res =
6493 ActOnOpenMPScopeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6494 break;
6495 case OMPD_parallel_master:
6496 Res = ActOnOpenMPParallelMasterDirective(Clauses: ClausesWithImplicit, AStmt,
6497 StartLoc, EndLoc);
6498 AllowedNameModifiers.push_back(OMPD_parallel);
6499 break;
6500 case OMPD_parallel_masked:
6501 Res = ActOnOpenMPParallelMaskedDirective(Clauses: ClausesWithImplicit, AStmt,
6502 StartLoc, EndLoc);
6503 AllowedNameModifiers.push_back(OMPD_parallel);
6504 break;
6505 case OMPD_parallel_sections:
6506 Res = ActOnOpenMPParallelSectionsDirective(Clauses: ClausesWithImplicit, AStmt,
6507 StartLoc, EndLoc);
6508 AllowedNameModifiers.push_back(OMPD_parallel);
6509 break;
6510 case OMPD_task:
6511 Res =
6512 ActOnOpenMPTaskDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6513 AllowedNameModifiers.push_back(OMPD_task);
6514 break;
6515 case OMPD_taskyield:
6516 assert(ClausesWithImplicit.empty() &&
6517 "No clauses are allowed for 'omp taskyield' directive");
6518 assert(AStmt == nullptr &&
6519 "No associated statement allowed for 'omp taskyield' directive");
6520 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6521 break;
6522 case OMPD_error:
6523 assert(AStmt == nullptr &&
6524 "No associated statement allowed for 'omp error' directive");
6525 Res = ActOnOpenMPErrorDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6526 break;
6527 case OMPD_barrier:
6528 assert(ClausesWithImplicit.empty() &&
6529 "No clauses are allowed for 'omp barrier' directive");
6530 assert(AStmt == nullptr &&
6531 "No associated statement allowed for 'omp barrier' directive");
6532 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6533 break;
6534 case OMPD_taskwait:
6535 assert(AStmt == nullptr &&
6536 "No associated statement allowed for 'omp taskwait' directive");
6537 Res = ActOnOpenMPTaskwaitDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6538 break;
6539 case OMPD_taskgroup:
6540 Res = ActOnOpenMPTaskgroupDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6541 EndLoc);
6542 break;
6543 case OMPD_flush:
6544 assert(AStmt == nullptr &&
6545 "No associated statement allowed for 'omp flush' directive");
6546 Res = ActOnOpenMPFlushDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6547 break;
6548 case OMPD_depobj:
6549 assert(AStmt == nullptr &&
6550 "No associated statement allowed for 'omp depobj' directive");
6551 Res = ActOnOpenMPDepobjDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6552 break;
6553 case OMPD_scan:
6554 assert(AStmt == nullptr &&
6555 "No associated statement allowed for 'omp scan' directive");
6556 Res = ActOnOpenMPScanDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6557 break;
6558 case OMPD_ordered:
6559 Res = ActOnOpenMPOrderedDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6560 EndLoc);
6561 break;
6562 case OMPD_atomic:
6563 Res = ActOnOpenMPAtomicDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6564 EndLoc);
6565 break;
6566 case OMPD_teams:
6567 Res =
6568 ActOnOpenMPTeamsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6569 break;
6570 case OMPD_target:
6571 Res = ActOnOpenMPTargetDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6572 EndLoc);
6573 AllowedNameModifiers.push_back(OMPD_target);
6574 break;
6575 case OMPD_target_parallel:
6576 Res = ActOnOpenMPTargetParallelDirective(Clauses: ClausesWithImplicit, AStmt,
6577 StartLoc, EndLoc);
6578 AllowedNameModifiers.push_back(OMPD_target);
6579 AllowedNameModifiers.push_back(OMPD_parallel);
6580 break;
6581 case OMPD_target_parallel_for:
6582 Res = ActOnOpenMPTargetParallelForDirective(
6583 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6584 AllowedNameModifiers.push_back(OMPD_target);
6585 AllowedNameModifiers.push_back(OMPD_parallel);
6586 break;
6587 case OMPD_cancellation_point:
6588 assert(ClausesWithImplicit.empty() &&
6589 "No clauses are allowed for 'omp cancellation point' directive");
6590 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6591 "cancellation point' directive");
6592 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6593 break;
6594 case OMPD_cancel:
6595 assert(AStmt == nullptr &&
6596 "No associated statement allowed for 'omp cancel' directive");
6597 Res = ActOnOpenMPCancelDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc,
6598 CancelRegion);
6599 AllowedNameModifiers.push_back(OMPD_cancel);
6600 break;
6601 case OMPD_target_data:
6602 Res = ActOnOpenMPTargetDataDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6603 EndLoc);
6604 AllowedNameModifiers.push_back(OMPD_target_data);
6605 break;
6606 case OMPD_target_enter_data:
6607 Res = ActOnOpenMPTargetEnterDataDirective(Clauses: ClausesWithImplicit, StartLoc,
6608 EndLoc, AStmt);
6609 AllowedNameModifiers.push_back(OMPD_target_enter_data);
6610 break;
6611 case OMPD_target_exit_data:
6612 Res = ActOnOpenMPTargetExitDataDirective(Clauses: ClausesWithImplicit, StartLoc,
6613 EndLoc, AStmt);
6614 AllowedNameModifiers.push_back(OMPD_target_exit_data);
6615 break;
6616 case OMPD_taskloop:
6617 Res = ActOnOpenMPTaskLoopDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6618 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6619 AllowedNameModifiers.push_back(OMPD_taskloop);
6620 break;
6621 case OMPD_taskloop_simd:
6622 Res = ActOnOpenMPTaskLoopSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6623 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6624 AllowedNameModifiers.push_back(OMPD_taskloop);
6625 if (LangOpts.OpenMP >= 50)
6626 AllowedNameModifiers.push_back(OMPD_simd);
6627 break;
6628 case OMPD_master_taskloop:
6629 Res = ActOnOpenMPMasterTaskLoopDirective(
6630 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6631 AllowedNameModifiers.push_back(OMPD_taskloop);
6632 break;
6633 case OMPD_masked_taskloop:
6634 Res = ActOnOpenMPMaskedTaskLoopDirective(
6635 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6636 AllowedNameModifiers.push_back(OMPD_taskloop);
6637 break;
6638 case OMPD_master_taskloop_simd:
6639 Res = ActOnOpenMPMasterTaskLoopSimdDirective(
6640 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6641 AllowedNameModifiers.push_back(OMPD_taskloop);
6642 if (LangOpts.OpenMP >= 50)
6643 AllowedNameModifiers.push_back(OMPD_simd);
6644 break;
6645 case OMPD_masked_taskloop_simd:
6646 Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
6647 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6648 if (LangOpts.OpenMP >= 51) {
6649 AllowedNameModifiers.push_back(OMPD_taskloop);
6650 AllowedNameModifiers.push_back(OMPD_simd);
6651 }
6652 break;
6653 case OMPD_parallel_master_taskloop:
6654 Res = ActOnOpenMPParallelMasterTaskLoopDirective(
6655 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6656 AllowedNameModifiers.push_back(OMPD_taskloop);
6657 AllowedNameModifiers.push_back(OMPD_parallel);
6658 break;
6659 case OMPD_parallel_masked_taskloop:
6660 Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
6661 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6662 if (LangOpts.OpenMP >= 51) {
6663 AllowedNameModifiers.push_back(OMPD_taskloop);
6664 AllowedNameModifiers.push_back(OMPD_parallel);
6665 }
6666 break;
6667 case OMPD_parallel_master_taskloop_simd:
6668 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6669 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6670 AllowedNameModifiers.push_back(OMPD_taskloop);
6671 AllowedNameModifiers.push_back(OMPD_parallel);
6672 if (LangOpts.OpenMP >= 50)
6673 AllowedNameModifiers.push_back(OMPD_simd);
6674 break;
6675 case OMPD_parallel_masked_taskloop_simd:
6676 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6677 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6678 if (LangOpts.OpenMP >= 51) {
6679 AllowedNameModifiers.push_back(OMPD_taskloop);
6680 AllowedNameModifiers.push_back(OMPD_parallel);
6681 AllowedNameModifiers.push_back(OMPD_simd);
6682 }
6683 break;
6684 case OMPD_distribute:
6685 Res = ActOnOpenMPDistributeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6686 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6687 break;
6688 case OMPD_target_update:
6689 Res = ActOnOpenMPTargetUpdateDirective(Clauses: ClausesWithImplicit, StartLoc,
6690 EndLoc, AStmt);
6691 AllowedNameModifiers.push_back(OMPD_target_update);
6692 break;
6693 case OMPD_distribute_parallel_for:
6694 Res = ActOnOpenMPDistributeParallelForDirective(
6695 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6696 AllowedNameModifiers.push_back(OMPD_parallel);
6697 break;
6698 case OMPD_distribute_parallel_for_simd:
6699 Res = ActOnOpenMPDistributeParallelForSimdDirective(
6700 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6701 AllowedNameModifiers.push_back(OMPD_parallel);
6702 if (LangOpts.OpenMP >= 50)
6703 AllowedNameModifiers.push_back(OMPD_simd);
6704 break;
6705 case OMPD_distribute_simd:
6706 Res = ActOnOpenMPDistributeSimdDirective(
6707 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6708 if (LangOpts.OpenMP >= 50)
6709 AllowedNameModifiers.push_back(OMPD_simd);
6710 break;
6711 case OMPD_target_parallel_for_simd:
6712 Res = ActOnOpenMPTargetParallelForSimdDirective(
6713 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6714 AllowedNameModifiers.push_back(OMPD_target);
6715 AllowedNameModifiers.push_back(OMPD_parallel);
6716 if (LangOpts.OpenMP >= 50)
6717 AllowedNameModifiers.push_back(OMPD_simd);
6718 break;
6719 case OMPD_target_simd:
6720 Res = ActOnOpenMPTargetSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6721 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6722 AllowedNameModifiers.push_back(OMPD_target);
6723 if (LangOpts.OpenMP >= 50)
6724 AllowedNameModifiers.push_back(OMPD_simd);
6725 break;
6726 case OMPD_teams_distribute:
6727 Res = ActOnOpenMPTeamsDistributeDirective(
6728 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6729 break;
6730 case OMPD_teams_distribute_simd:
6731 Res = ActOnOpenMPTeamsDistributeSimdDirective(
6732 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6733 if (LangOpts.OpenMP >= 50)
6734 AllowedNameModifiers.push_back(OMPD_simd);
6735 break;
6736 case OMPD_teams_distribute_parallel_for_simd:
6737 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6738 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6739 AllowedNameModifiers.push_back(OMPD_parallel);
6740 if (LangOpts.OpenMP >= 50)
6741 AllowedNameModifiers.push_back(OMPD_simd);
6742 break;
6743 case OMPD_teams_distribute_parallel_for:
6744 Res = ActOnOpenMPTeamsDistributeParallelForDirective(
6745 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6746 AllowedNameModifiers.push_back(OMPD_parallel);
6747 break;
6748 case OMPD_target_teams:
6749 Res = ActOnOpenMPTargetTeamsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6750 EndLoc);
6751 AllowedNameModifiers.push_back(OMPD_target);
6752 break;
6753 case OMPD_target_teams_distribute:
6754 Res = ActOnOpenMPTargetTeamsDistributeDirective(
6755 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6756 AllowedNameModifiers.push_back(OMPD_target);
6757 break;
6758 case OMPD_target_teams_distribute_parallel_for:
6759 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6760 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6761 AllowedNameModifiers.push_back(OMPD_target);
6762 AllowedNameModifiers.push_back(OMPD_parallel);
6763 break;
6764 case OMPD_target_teams_distribute_parallel_for_simd:
6765 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6766 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6767 AllowedNameModifiers.push_back(OMPD_target);
6768 AllowedNameModifiers.push_back(OMPD_parallel);
6769 if (LangOpts.OpenMP >= 50)
6770 AllowedNameModifiers.push_back(OMPD_simd);
6771 break;
6772 case OMPD_target_teams_distribute_simd:
6773 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
6774 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6775 AllowedNameModifiers.push_back(OMPD_target);
6776 if (LangOpts.OpenMP >= 50)
6777 AllowedNameModifiers.push_back(OMPD_simd);
6778 break;
6779 case OMPD_interop:
6780 assert(AStmt == nullptr &&
6781 "No associated statement allowed for 'omp interop' directive");
6782 Res = ActOnOpenMPInteropDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6783 break;
6784 case OMPD_dispatch:
6785 Res = ActOnOpenMPDispatchDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6786 EndLoc);
6787 break;
6788 case OMPD_loop:
6789 Res = ActOnOpenMPGenericLoopDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6790 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6791 break;
6792 case OMPD_teams_loop:
6793 Res = ActOnOpenMPTeamsGenericLoopDirective(
6794 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6795 break;
6796 case OMPD_target_teams_loop:
6797 Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
6798 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6799 AllowedNameModifiers.push_back(OMPD_target);
6800 break;
6801 case OMPD_parallel_loop:
6802 Res = ActOnOpenMPParallelGenericLoopDirective(
6803 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6804 break;
6805 case OMPD_target_parallel_loop:
6806 Res = ActOnOpenMPTargetParallelGenericLoopDirective(
6807 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6808 break;
6809 case OMPD_declare_target:
6810 case OMPD_end_declare_target:
6811 case OMPD_threadprivate:
6812 case OMPD_allocate:
6813 case OMPD_declare_reduction:
6814 case OMPD_declare_mapper:
6815 case OMPD_declare_simd:
6816 case OMPD_requires:
6817 case OMPD_declare_variant:
6818 case OMPD_begin_declare_variant:
6819 case OMPD_end_declare_variant:
6820 llvm_unreachable("OpenMP Directive is not allowed");
6821 case OMPD_unknown:
6822 default:
6823 llvm_unreachable("Unknown OpenMP directive");
6824 }
6825
6826 ErrorFound = Res.isInvalid() || ErrorFound;
6827
6828 // Check variables in the clauses if default(none) or
6829 // default(firstprivate) was specified.
6830 if (DSAStack->getDefaultDSA() == DSA_none ||
6831 DSAStack->getDefaultDSA() == DSA_private ||
6832 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6833 DSAAttrChecker DSAChecker(DSAStack, *this, nullptr);
6834 for (OMPClause *C : Clauses) {
6835 switch (C->getClauseKind()) {
6836 case OMPC_num_threads:
6837 case OMPC_dist_schedule:
6838 // Do not analyse if no parent teams directive.
6839 if (isOpenMPTeamsDirective(DKind: Kind))
6840 break;
6841 continue;
6842 case OMPC_if:
6843 if (isOpenMPTeamsDirective(Kind) &&
6844 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6845 break;
6846 if (isOpenMPParallelDirective(Kind) &&
6847 isOpenMPTaskLoopDirective(Kind) &&
6848 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6849 break;
6850 continue;
6851 case OMPC_schedule:
6852 case OMPC_detach:
6853 break;
6854 case OMPC_grainsize:
6855 case OMPC_num_tasks:
6856 case OMPC_final:
6857 case OMPC_priority:
6858 case OMPC_novariants:
6859 case OMPC_nocontext:
6860 // Do not analyze if no parent parallel directive.
6861 if (isOpenMPParallelDirective(DKind: Kind))
6862 break;
6863 continue;
6864 case OMPC_ordered:
6865 case OMPC_device:
6866 case OMPC_num_teams:
6867 case OMPC_thread_limit:
6868 case OMPC_hint:
6869 case OMPC_collapse:
6870 case OMPC_safelen:
6871 case OMPC_simdlen:
6872 case OMPC_sizes:
6873 case OMPC_default:
6874 case OMPC_proc_bind:
6875 case OMPC_private:
6876 case OMPC_firstprivate:
6877 case OMPC_lastprivate:
6878 case OMPC_shared:
6879 case OMPC_reduction:
6880 case OMPC_task_reduction:
6881 case OMPC_in_reduction:
6882 case OMPC_linear:
6883 case OMPC_aligned:
6884 case OMPC_copyin:
6885 case OMPC_copyprivate:
6886 case OMPC_nowait:
6887 case OMPC_untied:
6888 case OMPC_mergeable:
6889 case OMPC_allocate:
6890 case OMPC_read:
6891 case OMPC_write:
6892 case OMPC_update:
6893 case OMPC_capture:
6894 case OMPC_compare:
6895 case OMPC_seq_cst:
6896 case OMPC_acq_rel:
6897 case OMPC_acquire:
6898 case OMPC_release:
6899 case OMPC_relaxed:
6900 case OMPC_depend:
6901 case OMPC_threads:
6902 case OMPC_simd:
6903 case OMPC_map:
6904 case OMPC_nogroup:
6905 case OMPC_defaultmap:
6906 case OMPC_to:
6907 case OMPC_from:
6908 case OMPC_use_device_ptr:
6909 case OMPC_use_device_addr:
6910 case OMPC_is_device_ptr:
6911 case OMPC_has_device_addr:
6912 case OMPC_nontemporal:
6913 case OMPC_order:
6914 case OMPC_destroy:
6915 case OMPC_inclusive:
6916 case OMPC_exclusive:
6917 case OMPC_uses_allocators:
6918 case OMPC_affinity:
6919 case OMPC_bind:
6920 case OMPC_filter:
6921 continue;
6922 case OMPC_allocator:
6923 case OMPC_flush:
6924 case OMPC_depobj:
6925 case OMPC_threadprivate:
6926 case OMPC_uniform:
6927 case OMPC_unknown:
6928 case OMPC_unified_address:
6929 case OMPC_unified_shared_memory:
6930 case OMPC_reverse_offload:
6931 case OMPC_dynamic_allocators:
6932 case OMPC_atomic_default_mem_order:
6933 case OMPC_device_type:
6934 case OMPC_match:
6935 case OMPC_when:
6936 case OMPC_at:
6937 case OMPC_severity:
6938 case OMPC_message:
6939 default:
6940 llvm_unreachable("Unexpected clause");
6941 }
6942 for (Stmt *CC : C->children()) {
6943 if (CC)
6944 DSAChecker.Visit(CC);
6945 }
6946 }
6947 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6948 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6949 }
6950 for (const auto &P : VarsWithInheritedDSA) {
6951 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(Val: P.getFirst()))
6952 continue;
6953 ErrorFound = true;
6954 if (DSAStack->getDefaultDSA() == DSA_none ||
6955 DSAStack->getDefaultDSA() == DSA_private ||
6956 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6957 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6958 << P.first << P.second->getSourceRange();
6959 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6960 } else if (getLangOpts().OpenMP >= 50) {
6961 Diag(P.second->getExprLoc(),
6962 diag::err_omp_defaultmap_no_attr_for_variable)
6963 << P.first << P.second->getSourceRange();
6964 Diag(DSAStack->getDefaultDSALocation(),
6965 diag::note_omp_defaultmap_attr_none);
6966 }
6967 }
6968
6969 if (!AllowedNameModifiers.empty())
6970 ErrorFound = checkIfClauses(S&: *this, Kind, Clauses, AllowedNameModifiers) ||
6971 ErrorFound;
6972
6973 if (ErrorFound)
6974 return StmtError();
6975
6976 if (!CurContext->isDependentContext() &&
6977 isOpenMPTargetExecutionDirective(DKind: Kind) &&
6978 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6979 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6980 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6981 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6982 // Register target to DSA Stack.
6983 DSAStack->addTargetDirLocation(LocStart: StartLoc);
6984 }
6985
6986 return Res;
6987}
6988
6989Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
6990 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6991 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6992 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6993 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6994 assert(Aligneds.size() == Alignments.size());
6995 assert(Linears.size() == LinModifiers.size());
6996 assert(Linears.size() == Steps.size());
6997 if (!DG || DG.get().isNull())
6998 return DeclGroupPtrTy();
6999
7000 const int SimdId = 0;
7001 if (!DG.get().isSingleDecl()) {
7002 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7003 << SimdId;
7004 return DG;
7005 }
7006 Decl *ADecl = DG.get().getSingleDecl();
7007 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: ADecl))
7008 ADecl = FTD->getTemplatedDecl();
7009
7010 auto *FD = dyn_cast<FunctionDecl>(Val: ADecl);
7011 if (!FD) {
7012 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
7013 return DeclGroupPtrTy();
7014 }
7015
7016 // OpenMP [2.8.2, declare simd construct, Description]
7017 // The parameter of the simdlen clause must be a constant positive integer
7018 // expression.
7019 ExprResult SL;
7020 if (Simdlen)
7021 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
7022 // OpenMP [2.8.2, declare simd construct, Description]
7023 // The special this pointer can be used as if was one of the arguments to the
7024 // function in any of the linear, aligned, or uniform clauses.
7025 // The uniform clause declares one or more arguments to have an invariant
7026 // value for all concurrent invocations of the function in the execution of a
7027 // single SIMD loop.
7028 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
7029 const Expr *UniformedLinearThis = nullptr;
7030 for (const Expr *E : Uniforms) {
7031 E = E->IgnoreParenImpCasts();
7032 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7033 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl()))
7034 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7035 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7036 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
7037 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
7038 continue;
7039 }
7040 if (isa<CXXThisExpr>(Val: E)) {
7041 UniformedLinearThis = E;
7042 continue;
7043 }
7044 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7045 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7046 }
7047 // OpenMP [2.8.2, declare simd construct, Description]
7048 // The aligned clause declares that the object to which each list item points
7049 // is aligned to the number of bytes expressed in the optional parameter of
7050 // the aligned clause.
7051 // The special this pointer can be used as if was one of the arguments to the
7052 // function in any of the linear, aligned, or uniform clauses.
7053 // The type of list items appearing in the aligned clause must be array,
7054 // pointer, reference to array, or reference to pointer.
7055 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
7056 const Expr *AlignedThis = nullptr;
7057 for (const Expr *E : Aligneds) {
7058 E = E->IgnoreParenImpCasts();
7059 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7060 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7061 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7062 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7063 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7064 ->getCanonicalDecl() == CanonPVD) {
7065 // OpenMP [2.8.1, simd construct, Restrictions]
7066 // A list-item cannot appear in more than one aligned clause.
7067 if (AlignedArgs.count(CanonPVD) > 0) {
7068 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7069 << 1 << getOpenMPClauseName(OMPC_aligned)
7070 << E->getSourceRange();
7071 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
7072 diag::note_omp_explicit_dsa)
7073 << getOpenMPClauseName(OMPC_aligned);
7074 continue;
7075 }
7076 AlignedArgs[CanonPVD] = E;
7077 QualType QTy = PVD->getType()
7078 .getNonReferenceType()
7079 .getUnqualifiedType()
7080 .getCanonicalType();
7081 const Type *Ty = QTy.getTypePtrOrNull();
7082 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
7083 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
7084 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
7085 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7086 }
7087 continue;
7088 }
7089 }
7090 if (isa<CXXThisExpr>(Val: E)) {
7091 if (AlignedThis) {
7092 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7093 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
7094 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
7095 << getOpenMPClauseName(OMPC_aligned);
7096 }
7097 AlignedThis = E;
7098 continue;
7099 }
7100 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7101 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7102 }
7103 // The optional parameter of the aligned clause, alignment, must be a constant
7104 // positive integer expression. If no optional parameter is specified,
7105 // implementation-defined default alignments for SIMD instructions on the
7106 // target platforms are assumed.
7107 SmallVector<const Expr *, 4> NewAligns;
7108 for (Expr *E : Alignments) {
7109 ExprResult Align;
7110 if (E)
7111 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
7112 NewAligns.push_back(Elt: Align.get());
7113 }
7114 // OpenMP [2.8.2, declare simd construct, Description]
7115 // The linear clause declares one or more list items to be private to a SIMD
7116 // lane and to have a linear relationship with respect to the iteration space
7117 // of a loop.
7118 // The special this pointer can be used as if was one of the arguments to the
7119 // function in any of the linear, aligned, or uniform clauses.
7120 // When a linear-step expression is specified in a linear clause it must be
7121 // either a constant integer expression or an integer-typed parameter that is
7122 // specified in a uniform clause on the directive.
7123 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7124 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7125 auto MI = LinModifiers.begin();
7126 for (const Expr *E : Linears) {
7127 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7128 ++MI;
7129 E = E->IgnoreParenImpCasts();
7130 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
7131 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7132 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7133 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7134 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7135 ->getCanonicalDecl() == CanonPVD) {
7136 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7137 // A list-item cannot appear in more than one linear clause.
7138 if (LinearArgs.count(CanonPVD) > 0) {
7139 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7140 << getOpenMPClauseName(OMPC_linear)
7141 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
7142 Diag(LinearArgs[CanonPVD]->getExprLoc(),
7143 diag::note_omp_explicit_dsa)
7144 << getOpenMPClauseName(OMPC_linear);
7145 continue;
7146 }
7147 // Each argument can appear in at most one uniform or linear clause.
7148 if (UniformedArgs.count(CanonPVD) > 0) {
7149 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7150 << getOpenMPClauseName(OMPC_linear)
7151 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
7152 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
7153 diag::note_omp_explicit_dsa)
7154 << getOpenMPClauseName(OMPC_uniform);
7155 continue;
7156 }
7157 LinearArgs[CanonPVD] = E;
7158 if (E->isValueDependent() || E->isTypeDependent() ||
7159 E->isInstantiationDependent() ||
7160 E->containsUnexpandedParameterPack())
7161 continue;
7162 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7163 PVD->getOriginalType(),
7164 /*IsDeclareSimd=*/true);
7165 continue;
7166 }
7167 }
7168 if (isa<CXXThisExpr>(Val: E)) {
7169 if (UniformedLinearThis) {
7170 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7171 << getOpenMPClauseName(OMPC_linear)
7172 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
7173 << E->getSourceRange();
7174 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7175 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
7176 : OMPC_linear);
7177 continue;
7178 }
7179 UniformedLinearThis = E;
7180 if (E->isValueDependent() || E->isTypeDependent() ||
7181 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
7182 continue;
7183 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, ELoc: E->getExprLoc(), LinKind,
7184 Type: E->getType(), /*IsDeclareSimd=*/true);
7185 continue;
7186 }
7187 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7188 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7189 }
7190 Expr *Step = nullptr;
7191 Expr *NewStep = nullptr;
7192 SmallVector<Expr *, 4> NewSteps;
7193 for (Expr *E : Steps) {
7194 // Skip the same step expression, it was checked already.
7195 if (Step == E || !E) {
7196 NewSteps.push_back(Elt: E ? NewStep : nullptr);
7197 continue;
7198 }
7199 Step = E;
7200 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: Step))
7201 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7202 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7203 if (UniformedArgs.count(CanonPVD) == 0) {
7204 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7205 << Step->getSourceRange();
7206 } else if (E->isValueDependent() || E->isTypeDependent() ||
7207 E->isInstantiationDependent() ||
7208 E->containsUnexpandedParameterPack() ||
7209 CanonPVD->getType()->hasIntegerRepresentation()) {
7210 NewSteps.push_back(Elt: Step);
7211 } else {
7212 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7213 << Step->getSourceRange();
7214 }
7215 continue;
7216 }
7217 NewStep = Step;
7218 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7219 !Step->isInstantiationDependent() &&
7220 !Step->containsUnexpandedParameterPack()) {
7221 NewStep = PerformOpenMPImplicitIntegerConversion(OpLoc: Step->getExprLoc(), Op: Step)
7222 .get();
7223 if (NewStep)
7224 NewStep =
7225 VerifyIntegerConstantExpression(E: NewStep, /*FIXME*/ CanFold: AllowFold).get();
7226 }
7227 NewSteps.push_back(Elt: NewStep);
7228 }
7229 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7230 Context, BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7231 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7232 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7233 const_cast<Expr **>(Linears.data()), Linears.size(),
7234 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7235 NewSteps.data(), NewSteps.size(), SR);
7236 ADecl->addAttr(A: NewAttr);
7237 return DG;
7238}
7239
7240static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7241 QualType NewType) {
7242 assert(NewType->isFunctionProtoType() &&
7243 "Expected function type with prototype.");
7244 assert(FD->getType()->isFunctionNoProtoType() &&
7245 "Expected function with type with no prototype.");
7246 assert(FDWithProto->getType()->isFunctionProtoType() &&
7247 "Expected function with prototype.");
7248 // Synthesize parameters with the same types.
7249 FD->setType(NewType);
7250 SmallVector<ParmVarDecl *, 16> Params;
7251 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7252 auto *Param = ParmVarDecl::Create(C&: S.getASTContext(), DC: FD, StartLoc: SourceLocation(),
7253 IdLoc: SourceLocation(), Id: nullptr, T: P->getType(),
7254 /*TInfo=*/nullptr, S: SC_None, DefArg: nullptr);
7255 Param->setScopeInfo(0, Params.size());
7256 Param->setImplicit();
7257 Params.push_back(Elt: Param);
7258 }
7259
7260 FD->setParams(Params);
7261}
7262
7263void Sema::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
7264 if (D->isInvalidDecl())
7265 return;
7266 FunctionDecl *FD = nullptr;
7267 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(Val: D))
7268 FD = UTemplDecl->getTemplatedDecl();
7269 else
7270 FD = cast<FunctionDecl>(Val: D);
7271 assert(FD && "Expected a function declaration!");
7272
7273 // If we are instantiating templates we do *not* apply scoped assumptions but
7274 // only global ones. We apply scoped assumption to the template definition
7275 // though.
7276 if (!inTemplateInstantiation()) {
7277 for (AssumptionAttr *AA : OMPAssumeScoped)
7278 FD->addAttr(AA);
7279 }
7280 for (AssumptionAttr *AA : OMPAssumeGlobal)
7281 FD->addAttr(AA);
7282}
7283
7284Sema::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7285 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7286
7287void Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7288 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7289 SmallVectorImpl<FunctionDecl *> &Bases) {
7290 if (!D.getIdentifier())
7291 return;
7292
7293 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7294
7295 // Template specialization is an extension, check if we do it.
7296 bool IsTemplated = !TemplateParamLists.empty();
7297 if (IsTemplated &
7298 !DVScope.TI->isExtensionActive(
7299 TP: llvm::omp::TraitProperty::implementation_extension_allow_templates))
7300 return;
7301
7302 IdentifierInfo *BaseII = D.getIdentifier();
7303 LookupResult Lookup(*this, DeclarationName(BaseII), D.getIdentifierLoc(),
7304 LookupOrdinaryName);
7305 LookupParsedName(R&: Lookup, S, SS: &D.getCXXScopeSpec());
7306
7307 TypeSourceInfo *TInfo = GetTypeForDeclarator(D);
7308 QualType FType = TInfo->getType();
7309
7310 bool IsConstexpr =
7311 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7312 bool IsConsteval =
7313 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7314
7315 for (auto *Candidate : Lookup) {
7316 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7317 FunctionDecl *UDecl = nullptr;
7318 if (IsTemplated && isa<FunctionTemplateDecl>(Val: CandidateDecl)) {
7319 auto *FTD = cast<FunctionTemplateDecl>(Val: CandidateDecl);
7320 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7321 UDecl = FTD->getTemplatedDecl();
7322 } else if (!IsTemplated)
7323 UDecl = dyn_cast<FunctionDecl>(Val: CandidateDecl);
7324 if (!UDecl)
7325 continue;
7326
7327 // Don't specialize constexpr/consteval functions with
7328 // non-constexpr/consteval functions.
7329 if (UDecl->isConstexpr() && !IsConstexpr)
7330 continue;
7331 if (UDecl->isConsteval() && !IsConsteval)
7332 continue;
7333
7334 QualType UDeclTy = UDecl->getType();
7335 if (!UDeclTy->isDependentType()) {
7336 QualType NewType = Context.mergeFunctionTypes(
7337 FType, UDeclTy, /* OfBlockPointer */ false,
7338 /* Unqualified */ false, /* AllowCXX */ true);
7339 if (NewType.isNull())
7340 continue;
7341 }
7342
7343 // Found a base!
7344 Bases.push_back(Elt: UDecl);
7345 }
7346
7347 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7348 TP: llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7349 // If no base was found we create a declaration that we use as base.
7350 if (Bases.empty() && UseImplicitBase) {
7351 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7352 Decl *BaseD = HandleDeclarator(S, D, TemplateParameterLists: TemplateParamLists);
7353 BaseD->setImplicit(true);
7354 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7355 Bases.push_back(Elt: BaseTemplD->getTemplatedDecl());
7356 else
7357 Bases.push_back(Elt: cast<FunctionDecl>(Val: BaseD));
7358 }
7359
7360 std::string MangledName;
7361 MangledName += D.getIdentifier()->getName();
7362 MangledName += getOpenMPVariantManglingSeparatorStr();
7363 MangledName += DVScope.NameSuffix;
7364 IdentifierInfo &VariantII = Context.Idents.get(Name: MangledName);
7365
7366 VariantII.setMangledOpenMPVariantName(true);
7367 D.SetIdentifier(Id: &VariantII, IdLoc: D.getBeginLoc());
7368}
7369
7370void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7371 Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
7372 // Do not mark function as is used to prevent its emission if this is the
7373 // only place where it is used.
7374 EnterExpressionEvaluationContext Unevaluated(
7375 *this, Sema::ExpressionEvaluationContext::Unevaluated);
7376
7377 FunctionDecl *FD = nullptr;
7378 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(Val: D))
7379 FD = UTemplDecl->getTemplatedDecl();
7380 else
7381 FD = cast<FunctionDecl>(Val: D);
7382 auto *VariantFuncRef = DeclRefExpr::Create(
7383 Context, NestedNameSpecifierLoc(), SourceLocation(), FD,
7384 /* RefersToEnclosingVariableOrCapture */ false,
7385 /* NameLoc */ FD->getLocation(), FD->getType(),
7386 ExprValueKind::VK_PRValue);
7387
7388 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7389 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7390 Context, VariantFuncRef, DVScope.TI,
7391 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7392 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7393 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7394 for (FunctionDecl *BaseFD : Bases)
7395 BaseFD->addAttr(A: OMPDeclareVariantA);
7396}
7397
7398ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
7399 SourceLocation LParenLoc,
7400 MultiExprArg ArgExprs,
7401 SourceLocation RParenLoc, Expr *ExecConfig) {
7402 // The common case is a regular call we do not want to specialize at all. Try
7403 // to make that case fast by bailing early.
7404 CallExpr *CE = dyn_cast<CallExpr>(Val: Call.get());
7405 if (!CE)
7406 return Call;
7407
7408 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7409 if (!CalleeFnDecl)
7410 return Call;
7411
7412 if (LangOpts.OpenMP >= 51 && CalleeFnDecl->getIdentifier() &&
7413 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7414 // checking for any calls inside an Order region
7415 if (Scope && Scope->isOpenMPOrderClauseScope())
7416 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7417 }
7418
7419 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7420 return Call;
7421
7422 ASTContext &Context = getASTContext();
7423 std::function<void(StringRef)> DiagUnknownTrait = [this,
7424 CE](StringRef ISATrait) {
7425 // TODO Track the selector locations in a way that is accessible here to
7426 // improve the diagnostic location.
7427 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7428 << ISATrait;
7429 };
7430 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7431 getCurFunctionDecl(), DSAStack->getConstructTraits());
7432
7433 QualType CalleeFnType = CalleeFnDecl->getType();
7434
7435 SmallVector<Expr *, 4> Exprs;
7436 SmallVector<VariantMatchInfo, 4> VMIs;
7437 while (CalleeFnDecl) {
7438 for (OMPDeclareVariantAttr *A :
7439 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7440 Expr *VariantRef = A->getVariantFuncRef();
7441
7442 VariantMatchInfo VMI;
7443 OMPTraitInfo &TI = A->getTraitInfo();
7444 TI.getAsVariantMatchInfo(Context, VMI);
7445 if (!isVariantApplicableInContext(VMI, OMPCtx,
7446 /* DeviceSetOnly */ false))
7447 continue;
7448
7449 VMIs.push_back(VMI);
7450 Exprs.push_back(VariantRef);
7451 }
7452
7453 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7454 }
7455
7456 ExprResult NewCall;
7457 do {
7458 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7459 if (BestIdx < 0)
7460 return Call;
7461 Expr *BestExpr = cast<DeclRefExpr>(Val: Exprs[BestIdx]);
7462 Decl *BestDecl = cast<DeclRefExpr>(Val: BestExpr)->getDecl();
7463
7464 {
7465 // Try to build a (member) call expression for the current best applicable
7466 // variant expression. We allow this to fail in which case we continue
7467 // with the next best variant expression. The fail case is part of the
7468 // implementation defined behavior in the OpenMP standard when it talks
7469 // about what differences in the function prototypes: "Any differences
7470 // that the specific OpenMP context requires in the prototype of the
7471 // variant from the base function prototype are implementation defined."
7472 // This wording is there to allow the specialized variant to have a
7473 // different type than the base function. This is intended and OK but if
7474 // we cannot create a call the difference is not in the "implementation
7475 // defined range" we allow.
7476 Sema::TentativeAnalysisScope Trap(*this);
7477
7478 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7479 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(Val: CE);
7480 BestExpr = MemberExpr::CreateImplicit(
7481 C: Context, Base: MemberCall->getImplicitObjectArgument(),
7482 /* IsArrow */ false, MemberDecl: SpecializedMethod, T: Context.BoundMemberTy,
7483 VK: MemberCall->getValueKind(), OK: MemberCall->getObjectKind());
7484 }
7485 NewCall = BuildCallExpr(S: Scope, Fn: BestExpr, LParenLoc, ArgExprs, RParenLoc,
7486 ExecConfig);
7487 if (NewCall.isUsable()) {
7488 if (CallExpr *NCE = dyn_cast<CallExpr>(Val: NewCall.get())) {
7489 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7490 QualType NewType = Context.mergeFunctionTypes(
7491 CalleeFnType, NewCalleeFnDecl->getType(),
7492 /* OfBlockPointer */ false,
7493 /* Unqualified */ false, /* AllowCXX */ true);
7494 if (!NewType.isNull())
7495 break;
7496 // Don't use the call if the function type was not compatible.
7497 NewCall = nullptr;
7498 }
7499 }
7500 }
7501
7502 VMIs.erase(CI: VMIs.begin() + BestIdx);
7503 Exprs.erase(CI: Exprs.begin() + BestIdx);
7504 } while (!VMIs.empty());
7505
7506 if (!NewCall.isUsable())
7507 return Call;
7508 return PseudoObjectExpr::Create(Context, CE, {NewCall.get()}, 0);
7509}
7510
7511std::optional<std::pair<FunctionDecl *, Expr *>>
7512Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
7513 Expr *VariantRef, OMPTraitInfo &TI,
7514 unsigned NumAppendArgs,
7515 SourceRange SR) {
7516 if (!DG || DG.get().isNull())
7517 return std::nullopt;
7518
7519 const int VariantId = 1;
7520 // Must be applied only to single decl.
7521 if (!DG.get().isSingleDecl()) {
7522 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7523 << VariantId << SR;
7524 return std::nullopt;
7525 }
7526 Decl *ADecl = DG.get().getSingleDecl();
7527 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: ADecl))
7528 ADecl = FTD->getTemplatedDecl();
7529
7530 // Decl must be a function.
7531 auto *FD = dyn_cast<FunctionDecl>(Val: ADecl);
7532 if (!FD) {
7533 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7534 << VariantId << SR;
7535 return std::nullopt;
7536 }
7537
7538 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7539 // The 'target' attribute needs to be separately checked because it does
7540 // not always signify a multiversion function declaration.
7541 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7542 };
7543 // OpenMP is not compatible with multiversion function attributes.
7544 if (HasMultiVersionAttributes(FD)) {
7545 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7546 << SR;
7547 return std::nullopt;
7548 }
7549
7550 // Allow #pragma omp declare variant only if the function is not used.
7551 if (FD->isUsed(false))
7552 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7553 << FD->getLocation();
7554
7555 // Check if the function was emitted already.
7556 const FunctionDecl *Definition;
7557 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7558 (LangOpts.EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7559 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7560 << FD->getLocation();
7561
7562 // The VariantRef must point to function.
7563 if (!VariantRef) {
7564 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7565 return std::nullopt;
7566 }
7567
7568 auto ShouldDelayChecks = [](Expr *&E, bool) {
7569 return E && (E->isTypeDependent() || E->isValueDependent() ||
7570 E->containsUnexpandedParameterPack() ||
7571 E->isInstantiationDependent());
7572 };
7573 // Do not check templates, wait until instantiation.
7574 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7575 TI.anyScoreOrCondition(Cond: ShouldDelayChecks))
7576 return std::make_pair(x&: FD, y&: VariantRef);
7577
7578 // Deal with non-constant score and user condition expressions.
7579 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7580 bool IsScore) -> bool {
7581 if (!E || E->isIntegerConstantExpr(Ctx: Context))
7582 return false;
7583
7584 if (IsScore) {
7585 // We warn on non-constant scores and pretend they were not present.
7586 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7587 << E;
7588 E = nullptr;
7589 } else {
7590 // We could replace a non-constant user condition with "false" but we
7591 // will soon need to handle these anyway for the dynamic version of
7592 // OpenMP context selectors.
7593 Diag(E->getExprLoc(),
7594 diag::err_omp_declare_variant_user_condition_not_constant)
7595 << E;
7596 }
7597 return true;
7598 };
7599 if (TI.anyScoreOrCondition(Cond: HandleNonConstantScoresAndConditions))
7600 return std::nullopt;
7601
7602 QualType AdjustedFnType = FD->getType();
7603 if (NumAppendArgs) {
7604 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7605 if (!PTy) {
7606 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7607 << SR;
7608 return std::nullopt;
7609 }
7610 // Adjust the function type to account for an extra omp_interop_t for each
7611 // specified in the append_args clause.
7612 const TypeDecl *TD = nullptr;
7613 LookupResult Result(*this, &Context.Idents.get(Name: "omp_interop_t"),
7614 SR.getBegin(), Sema::LookupOrdinaryName);
7615 if (LookupName(R&: Result, S: getCurScope())) {
7616 NamedDecl *ND = Result.getFoundDecl();
7617 TD = dyn_cast_or_null<TypeDecl>(Val: ND);
7618 }
7619 if (!TD) {
7620 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7621 return std::nullopt;
7622 }
7623 QualType InteropType = Context.getTypeDeclType(Decl: TD);
7624 if (PTy->isVariadic()) {
7625 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7626 return std::nullopt;
7627 }
7628 llvm::SmallVector<QualType, 8> Params;
7629 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7630 Params.insert(I: Params.end(), NumToInsert: NumAppendArgs, Elt: InteropType);
7631 AdjustedFnType = Context.getFunctionType(ResultTy: PTy->getReturnType(), Args: Params,
7632 EPI: PTy->getExtProtoInfo());
7633 }
7634
7635 // Convert VariantRef expression to the type of the original function to
7636 // resolve possible conflicts.
7637 ExprResult VariantRefCast = VariantRef;
7638 if (LangOpts.CPlusPlus) {
7639 QualType FnPtrType;
7640 auto *Method = dyn_cast<CXXMethodDecl>(Val: FD);
7641 if (Method && !Method->isStatic()) {
7642 const Type *ClassType =
7643 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7644 FnPtrType = Context.getMemberPointerType(T: AdjustedFnType, Cls: ClassType);
7645 ExprResult ER;
7646 {
7647 // Build adrr_of unary op to correctly handle type checks for member
7648 // functions.
7649 Sema::TentativeAnalysisScope Trap(*this);
7650 ER = CreateBuiltinUnaryOp(OpLoc: VariantRef->getBeginLoc(), Opc: UO_AddrOf,
7651 InputExpr: VariantRef);
7652 }
7653 if (!ER.isUsable()) {
7654 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7655 << VariantId << VariantRef->getSourceRange();
7656 return std::nullopt;
7657 }
7658 VariantRef = ER.get();
7659 } else {
7660 FnPtrType = Context.getPointerType(T: AdjustedFnType);
7661 }
7662 QualType VarianPtrType = Context.getPointerType(T: VariantRef->getType());
7663 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7664 ImplicitConversionSequence ICS = TryImplicitConversion(
7665 From: VariantRef, ToType: FnPtrType.getUnqualifiedType(),
7666 /*SuppressUserConversions=*/false, AllowExplicit: AllowedExplicit::None,
7667 /*InOverloadResolution=*/false,
7668 /*CStyle=*/false,
7669 /*AllowObjCWritebackConversion=*/false);
7670 if (ICS.isFailure()) {
7671 Diag(VariantRef->getExprLoc(),
7672 diag::err_omp_declare_variant_incompat_types)
7673 << VariantRef->getType()
7674 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7675 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7676 return std::nullopt;
7677 }
7678 VariantRefCast = PerformImplicitConversion(
7679 From: VariantRef, ToType: FnPtrType.getUnqualifiedType(), Action: AA_Converting);
7680 if (!VariantRefCast.isUsable())
7681 return std::nullopt;
7682 }
7683 // Drop previously built artificial addr_of unary op for member functions.
7684 if (Method && !Method->isStatic()) {
7685 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7686 if (auto *UO = dyn_cast<UnaryOperator>(
7687 Val: PossibleAddrOfVariantRef->IgnoreImplicit()))
7688 VariantRefCast = UO->getSubExpr();
7689 }
7690 }
7691
7692 ExprResult ER = CheckPlaceholderExpr(E: VariantRefCast.get());
7693 if (!ER.isUsable() ||
7694 !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7695 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7696 << VariantId << VariantRef->getSourceRange();
7697 return std::nullopt;
7698 }
7699
7700 // The VariantRef must point to function.
7701 auto *DRE = dyn_cast<DeclRefExpr>(Val: ER.get()->IgnoreParenImpCasts());
7702 if (!DRE) {
7703 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7704 << VariantId << VariantRef->getSourceRange();
7705 return std::nullopt;
7706 }
7707 auto *NewFD = dyn_cast_or_null<FunctionDecl>(Val: DRE->getDecl());
7708 if (!NewFD) {
7709 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7710 << VariantId << VariantRef->getSourceRange();
7711 return std::nullopt;
7712 }
7713
7714 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7715 Diag(VariantRef->getExprLoc(),
7716 diag::err_omp_declare_variant_same_base_function)
7717 << VariantRef->getSourceRange();
7718 return std::nullopt;
7719 }
7720
7721 // Check if function types are compatible in C.
7722 if (!LangOpts.CPlusPlus) {
7723 QualType NewType =
7724 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7725 if (NewType.isNull()) {
7726 Diag(VariantRef->getExprLoc(),
7727 diag::err_omp_declare_variant_incompat_types)
7728 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7729 << VariantRef->getSourceRange();
7730 return std::nullopt;
7731 }
7732 if (NewType->isFunctionProtoType()) {
7733 if (FD->getType()->isFunctionNoProtoType())
7734 setPrototype(S&: *this, FD, FDWithProto: NewFD, NewType);
7735 else if (NewFD->getType()->isFunctionNoProtoType())
7736 setPrototype(S&: *this, FD: NewFD, FDWithProto: FD, NewType);
7737 }
7738 }
7739
7740 // Check if variant function is not marked with declare variant directive.
7741 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7742 Diag(VariantRef->getExprLoc(),
7743 diag::warn_omp_declare_variant_marked_as_declare_variant)
7744 << VariantRef->getSourceRange();
7745 SourceRange SR =
7746 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7747 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7748 return std::nullopt;
7749 }
7750
7751 enum DoesntSupport {
7752 VirtFuncs = 1,
7753 Constructors = 3,
7754 Destructors = 4,
7755 DeletedFuncs = 5,
7756 DefaultedFuncs = 6,
7757 ConstexprFuncs = 7,
7758 ConstevalFuncs = 8,
7759 };
7760 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(Val: FD)) {
7761 if (CXXFD->isVirtual()) {
7762 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7763 << VirtFuncs;
7764 return std::nullopt;
7765 }
7766
7767 if (isa<CXXConstructorDecl>(Val: FD)) {
7768 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7769 << Constructors;
7770 return std::nullopt;
7771 }
7772
7773 if (isa<CXXDestructorDecl>(Val: FD)) {
7774 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7775 << Destructors;
7776 return std::nullopt;
7777 }
7778 }
7779
7780 if (FD->isDeleted()) {
7781 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7782 << DeletedFuncs;
7783 return std::nullopt;
7784 }
7785
7786 if (FD->isDefaulted()) {
7787 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7788 << DefaultedFuncs;
7789 return std::nullopt;
7790 }
7791
7792 if (FD->isConstexpr()) {
7793 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7794 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7795 return std::nullopt;
7796 }
7797
7798 // Check general compatibility.
7799 if (areMultiversionVariantFunctionsCompatible(
7800 FD, NewFD, PartialDiagnostic::NullDiagnostic(),
7801 PartialDiagnosticAt(SourceLocation(),
7802 PartialDiagnostic::NullDiagnostic()),
7803 PartialDiagnosticAt(
7804 VariantRef->getExprLoc(),
7805 PDiag(diag::err_omp_declare_variant_doesnt_support)),
7806 PartialDiagnosticAt(VariantRef->getExprLoc(),
7807 PDiag(diag::err_omp_declare_variant_diff)
7808 << FD->getLocation()),
7809 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7810 /*CLinkageMayDiffer=*/true))
7811 return std::nullopt;
7812 return std::make_pair(x&: FD, y: cast<Expr>(Val: DRE));
7813}
7814
7815void Sema::ActOnOpenMPDeclareVariantDirective(
7816 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7817 ArrayRef<Expr *> AdjustArgsNothing,
7818 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7819 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7820 SourceLocation AppendArgsLoc, SourceRange SR) {
7821
7822 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7823 // An adjust_args clause or append_args clause can only be specified if the
7824 // dispatch selector of the construct selector set appears in the match
7825 // clause.
7826
7827 SmallVector<Expr *, 8> AllAdjustArgs;
7828 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNothing);
7829 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNeedDevicePtr);
7830
7831 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7832 VariantMatchInfo VMI;
7833 TI.getAsVariantMatchInfo(ASTCtx&: Context, VMI);
7834 if (!llvm::is_contained(
7835 Range&: VMI.ConstructTraits,
7836 Element: llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7837 if (!AllAdjustArgs.empty())
7838 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7839 << getOpenMPClauseName(OMPC_adjust_args);
7840 if (!AppendArgs.empty())
7841 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7842 << getOpenMPClauseName(OMPC_append_args);
7843 return;
7844 }
7845 }
7846
7847 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7848 // Each argument can only appear in a single adjust_args clause for each
7849 // declare variant directive.
7850 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
7851
7852 for (Expr *E : AllAdjustArgs) {
7853 E = E->IgnoreParenImpCasts();
7854 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E)) {
7855 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7856 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7857 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7858 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7859 ->getCanonicalDecl() == CanonPVD) {
7860 // It's a parameter of the function, check duplicates.
7861 if (!AdjustVars.insert(Ptr: CanonPVD).second) {
7862 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7863 << PVD;
7864 return;
7865 }
7866 continue;
7867 }
7868 }
7869 }
7870 // Anything that is not a function parameter is an error.
7871 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7872 return;
7873 }
7874
7875 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7876 Context, VariantRef, &TI, const_cast<Expr **>(AdjustArgsNothing.data()),
7877 AdjustArgsNothing.size(),
7878 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7879 AdjustArgsNeedDevicePtr.size(),
7880 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7881 FD->addAttr(A: NewAttr);
7882}
7883
7884StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
7885 Stmt *AStmt,
7886 SourceLocation StartLoc,
7887 SourceLocation EndLoc) {
7888 if (!AStmt)
7889 return StmtError();
7890
7891 auto *CS = cast<CapturedStmt>(Val: AStmt);
7892 // 1.2.2 OpenMP Language Terminology
7893 // Structured block - An executable statement with a single entry at the
7894 // top and a single exit at the bottom.
7895 // The point of exit cannot be a branch out of the structured block.
7896 // longjmp() and throw() must not violate the entry/exit criteria.
7897 CS->getCapturedDecl()->setNothrow();
7898
7899 setFunctionHasBranchProtectedScope();
7900
7901 return OMPParallelDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
7902 DSAStack->getTaskgroupReductionRef(),
7903 DSAStack->isCancelRegion());
7904}
7905
7906namespace {
7907/// Iteration space of a single for loop.
7908struct LoopIterationSpace final {
7909 /// True if the condition operator is the strict compare operator (<, > or
7910 /// !=).
7911 bool IsStrictCompare = false;
7912 /// Condition of the loop.
7913 Expr *PreCond = nullptr;
7914 /// This expression calculates the number of iterations in the loop.
7915 /// It is always possible to calculate it before starting the loop.
7916 Expr *NumIterations = nullptr;
7917 /// The loop counter variable.
7918 Expr *CounterVar = nullptr;
7919 /// Private loop counter variable.
7920 Expr *PrivateCounterVar = nullptr;
7921 /// This is initializer for the initial value of #CounterVar.
7922 Expr *CounterInit = nullptr;
7923 /// This is step for the #CounterVar used to generate its update:
7924 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7925 Expr *CounterStep = nullptr;
7926 /// Should step be subtracted?
7927 bool Subtract = false;
7928 /// Source range of the loop init.
7929 SourceRange InitSrcRange;
7930 /// Source range of the loop condition.
7931 SourceRange CondSrcRange;
7932 /// Source range of the loop increment.
7933 SourceRange IncSrcRange;
7934 /// Minimum value that can have the loop control variable. Used to support
7935 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7936 /// since only such variables can be used in non-loop invariant expressions.
7937 Expr *MinValue = nullptr;
7938 /// Maximum value that can have the loop control variable. Used to support
7939 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7940 /// since only such variables can be used in non-loop invariant expressions.
7941 Expr *MaxValue = nullptr;
7942 /// true, if the lower bound depends on the outer loop control var.
7943 bool IsNonRectangularLB = false;
7944 /// true, if the upper bound depends on the outer loop control var.
7945 bool IsNonRectangularUB = false;
7946 /// Index of the loop this loop depends on and forms non-rectangular loop
7947 /// nest.
7948 unsigned LoopDependentIdx = 0;
7949 /// Final condition for the non-rectangular loop nest support. It is used to
7950 /// check that the number of iterations for this particular counter must be
7951 /// finished.
7952 Expr *FinalCondition = nullptr;
7953};
7954
7955/// Helper class for checking canonical form of the OpenMP loops and
7956/// extracting iteration space of each loop in the loop nest, that will be used
7957/// for IR generation.
7958class OpenMPIterationSpaceChecker {
7959 /// Reference to Sema.
7960 Sema &SemaRef;
7961 /// Does the loop associated directive support non-rectangular loops?
7962 bool SupportsNonRectangular;
7963 /// Data-sharing stack.
7964 DSAStackTy &Stack;
7965 /// A location for diagnostics (when there is no some better location).
7966 SourceLocation DefaultLoc;
7967 /// A location for diagnostics (when increment is not compatible).
7968 SourceLocation ConditionLoc;
7969 /// A source location for referring to loop init later.
7970 SourceRange InitSrcRange;
7971 /// A source location for referring to condition later.
7972 SourceRange ConditionSrcRange;
7973 /// A source location for referring to increment later.
7974 SourceRange IncrementSrcRange;
7975 /// Loop variable.
7976 ValueDecl *LCDecl = nullptr;
7977 /// Reference to loop variable.
7978 Expr *LCRef = nullptr;
7979 /// Lower bound (initializer for the var).
7980 Expr *LB = nullptr;
7981 /// Upper bound.
7982 Expr *UB = nullptr;
7983 /// Loop step (increment).
7984 Expr *Step = nullptr;
7985 /// This flag is true when condition is one of:
7986 /// Var < UB
7987 /// Var <= UB
7988 /// UB > Var
7989 /// UB >= Var
7990 /// This will have no value when the condition is !=
7991 std::optional<bool> TestIsLessOp;
7992 /// This flag is true when condition is strict ( < or > ).
7993 bool TestIsStrictOp = false;
7994 /// This flag is true when step is subtracted on each iteration.
7995 bool SubtractStep = false;
7996 /// The outer loop counter this loop depends on (if any).
7997 const ValueDecl *DepDecl = nullptr;
7998 /// Contains number of loop (starts from 1) on which loop counter init
7999 /// expression of this loop depends on.
8000 std::optional<unsigned> InitDependOnLC;
8001 /// Contains number of loop (starts from 1) on which loop counter condition
8002 /// expression of this loop depends on.
8003 std::optional<unsigned> CondDependOnLC;
8004 /// Checks if the provide statement depends on the loop counter.
8005 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8006 bool IsInitializer);
8007 /// Original condition required for checking of the exit condition for
8008 /// non-rectangular loop.
8009 Expr *Condition = nullptr;
8010
8011public:
8012 OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
8013 DSAStackTy &Stack, SourceLocation DefaultLoc)
8014 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8015 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
8016 /// Check init-expr for canonical loop form and save loop counter
8017 /// variable - #Var and its initialization value - #LB.
8018 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8019 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8020 /// for less/greater and for strict/non-strict comparison.
8021 bool checkAndSetCond(Expr *S);
8022 /// Check incr-expr for canonical loop form and return true if it
8023 /// does not conform, otherwise save loop step (#Step).
8024 bool checkAndSetInc(Expr *S);
8025 /// Return the loop counter variable.
8026 ValueDecl *getLoopDecl() const { return LCDecl; }
8027 /// Return the reference expression to loop counter variable.
8028 Expr *getLoopDeclRefExpr() const { return LCRef; }
8029 /// Source range of the loop init.
8030 SourceRange getInitSrcRange() const { return InitSrcRange; }
8031 /// Source range of the loop condition.
8032 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8033 /// Source range of the loop increment.
8034 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8035 /// True if the step should be subtracted.
8036 bool shouldSubtractStep() const { return SubtractStep; }
8037 /// True, if the compare operator is strict (<, > or !=).
8038 bool isStrictTestOp() const { return TestIsStrictOp; }
8039 /// Build the expression to calculate the number of iterations.
8040 Expr *buildNumIterations(
8041 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8042 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8043 /// Build the precondition expression for the loops.
8044 Expr *
8045 buildPreCond(Scope *S, Expr *Cond,
8046 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8047 /// Build reference expression to the counter be used for codegen.
8048 DeclRefExpr *
8049 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8050 DSAStackTy &DSA) const;
8051 /// Build reference expression to the private counter be used for
8052 /// codegen.
8053 Expr *buildPrivateCounterVar() const;
8054 /// Build initialization of the counter be used for codegen.
8055 Expr *buildCounterInit() const;
8056 /// Build step of the counter be used for codegen.
8057 Expr *buildCounterStep() const;
8058 /// Build loop data with counter value for depend clauses in ordered
8059 /// directives.
8060 Expr *
8061 buildOrderedLoopData(Scope *S, Expr *Counter,
8062 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8063 SourceLocation Loc, Expr *Inc = nullptr,
8064 OverloadedOperatorKind OOK = OO_Amp);
8065 /// Builds the minimum value for the loop counter.
8066 std::pair<Expr *, Expr *> buildMinMaxValues(
8067 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8068 /// Builds final condition for the non-rectangular loops.
8069 Expr *buildFinalCondition(Scope *S) const;
8070 /// Return true if any expression is dependent.
8071 bool dependent() const;
8072 /// Returns true if the initializer forms non-rectangular loop.
8073 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8074 /// Returns true if the condition forms non-rectangular loop.
8075 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8076 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8077 unsigned getLoopDependentIdx() const {
8078 return InitDependOnLC.value_or(u: CondDependOnLC.value_or(u: 0));
8079 }
8080
8081private:
8082 /// Check the right-hand side of an assignment in the increment
8083 /// expression.
8084 bool checkAndSetIncRHS(Expr *RHS);
8085 /// Helper to set loop counter variable and its initializer.
8086 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8087 bool EmitDiags);
8088 /// Helper to set upper bound.
8089 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8090 SourceRange SR, SourceLocation SL);
8091 /// Helper to set loop increment.
8092 bool setStep(Expr *NewStep, bool Subtract);
8093};
8094
8095bool OpenMPIterationSpaceChecker::dependent() const {
8096 if (!LCDecl) {
8097 assert(!LB && !UB && !Step);
8098 return false;
8099 }
8100 return LCDecl->getType()->isDependentType() ||
8101 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8102 (Step && Step->isValueDependent());
8103}
8104
8105bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8106 Expr *NewLCRefExpr,
8107 Expr *NewLB, bool EmitDiags) {
8108 // State consistency checking to ensure correct usage.
8109 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8110 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8111 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8112 return true;
8113 LCDecl = getCanonicalDecl(D: NewLCDecl);
8114 LCRef = NewLCRefExpr;
8115 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(Val: NewLB))
8116 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8117 if ((Ctor->isCopyOrMoveConstructor() ||
8118 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8119 CE->getNumArgs() > 0 && CE->getArg(Arg: 0) != nullptr)
8120 NewLB = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
8121 LB = NewLB;
8122 if (EmitDiags)
8123 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8124 return false;
8125}
8126
8127bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8128 bool StrictOp, SourceRange SR,
8129 SourceLocation SL) {
8130 // State consistency checking to ensure correct usage.
8131 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8132 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8133 if (!NewUB || NewUB->containsErrors())
8134 return true;
8135 UB = NewUB;
8136 if (LessOp)
8137 TestIsLessOp = LessOp;
8138 TestIsStrictOp = StrictOp;
8139 ConditionSrcRange = SR;
8140 ConditionLoc = SL;
8141 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8142 return false;
8143}
8144
8145bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8146 // State consistency checking to ensure correct usage.
8147 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8148 if (!NewStep || NewStep->containsErrors())
8149 return true;
8150 if (!NewStep->isValueDependent()) {
8151 // Check that the step is integer expression.
8152 SourceLocation StepLoc = NewStep->getBeginLoc();
8153 ExprResult Val = SemaRef.PerformOpenMPImplicitIntegerConversion(
8154 OpLoc: StepLoc, Op: getExprAsWritten(E: NewStep));
8155 if (Val.isInvalid())
8156 return true;
8157 NewStep = Val.get();
8158
8159 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8160 // If test-expr is of form var relational-op b and relational-op is < or
8161 // <= then incr-expr must cause var to increase on each iteration of the
8162 // loop. If test-expr is of form var relational-op b and relational-op is
8163 // > or >= then incr-expr must cause var to decrease on each iteration of
8164 // the loop.
8165 // If test-expr is of form b relational-op var and relational-op is < or
8166 // <= then incr-expr must cause var to decrease on each iteration of the
8167 // loop. If test-expr is of form b relational-op var and relational-op is
8168 // > or >= then incr-expr must cause var to increase on each iteration of
8169 // the loop.
8170 std::optional<llvm::APSInt> Result =
8171 NewStep->getIntegerConstantExpr(Ctx: SemaRef.Context);
8172 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8173 bool IsConstNeg =
8174 Result && Result->isSigned() && (Subtract != Result->isNegative());
8175 bool IsConstPos =
8176 Result && Result->isSigned() && (Subtract == Result->isNegative());
8177 bool IsConstZero = Result && !Result->getBoolValue();
8178
8179 // != with increment is treated as <; != with decrement is treated as >
8180 if (!TestIsLessOp)
8181 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8182 if (UB && (IsConstZero ||
8183 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8184 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8185 SemaRef.Diag(NewStep->getExprLoc(),
8186 diag::err_omp_loop_incr_not_compatible)
8187 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8188 SemaRef.Diag(ConditionLoc,
8189 diag::note_omp_loop_cond_requres_compatible_incr)
8190 << *TestIsLessOp << ConditionSrcRange;
8191 return true;
8192 }
8193 if (*TestIsLessOp == Subtract) {
8194 NewStep =
8195 SemaRef.CreateBuiltinUnaryOp(OpLoc: NewStep->getExprLoc(), Opc: UO_Minus, InputExpr: NewStep)
8196 .get();
8197 Subtract = !Subtract;
8198 }
8199 }
8200
8201 Step = NewStep;
8202 SubtractStep = Subtract;
8203 return false;
8204}
8205
8206namespace {
8207/// Checker for the non-rectangular loops. Checks if the initializer or
8208/// condition expression references loop counter variable.
8209class LoopCounterRefChecker final
8210 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8211 Sema &SemaRef;
8212 DSAStackTy &Stack;
8213 const ValueDecl *CurLCDecl = nullptr;
8214 const ValueDecl *DepDecl = nullptr;
8215 const ValueDecl *PrevDepDecl = nullptr;
8216 bool IsInitializer = true;
8217 bool SupportsNonRectangular;
8218 unsigned BaseLoopId = 0;
8219 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8220 if (getCanonicalDecl(D: VD) == getCanonicalDecl(D: CurLCDecl)) {
8221 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8222 << (IsInitializer ? 0 : 1);
8223 return false;
8224 }
8225 const auto &&Data = Stack.isLoopControlVariable(D: VD);
8226 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8227 // The type of the loop iterator on which we depend may not have a random
8228 // access iterator type.
8229 if (Data.first && VD->getType()->isRecordType()) {
8230 SmallString<128> Name;
8231 llvm::raw_svector_ostream OS(Name);
8232 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8233 /*Qualified=*/true);
8234 SemaRef.Diag(E->getExprLoc(),
8235 diag::err_omp_wrong_dependency_iterator_type)
8236 << OS.str();
8237 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8238 return false;
8239 }
8240 if (Data.first && !SupportsNonRectangular) {
8241 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8242 return false;
8243 }
8244 if (Data.first &&
8245 (DepDecl || (PrevDepDecl &&
8246 getCanonicalDecl(D: VD) != getCanonicalDecl(D: PrevDepDecl)))) {
8247 if (!DepDecl && PrevDepDecl)
8248 DepDecl = PrevDepDecl;
8249 SmallString<128> Name;
8250 llvm::raw_svector_ostream OS(Name);
8251 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8252 /*Qualified=*/true);
8253 SemaRef.Diag(E->getExprLoc(),
8254 diag::err_omp_invariant_or_linear_dependency)
8255 << OS.str();
8256 return false;
8257 }
8258 if (Data.first) {
8259 DepDecl = VD;
8260 BaseLoopId = Data.first;
8261 }
8262 return Data.first;
8263 }
8264
8265public:
8266 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8267 const ValueDecl *VD = E->getDecl();
8268 if (isa<VarDecl>(Val: VD))
8269 return checkDecl(E, VD);
8270 return false;
8271 }
8272 bool VisitMemberExpr(const MemberExpr *E) {
8273 if (isa<CXXThisExpr>(Val: E->getBase()->IgnoreParens())) {
8274 const ValueDecl *VD = E->getMemberDecl();
8275 if (isa<VarDecl>(Val: VD) || isa<FieldDecl>(Val: VD))
8276 return checkDecl(E, VD);
8277 }
8278 return false;
8279 }
8280 bool VisitStmt(const Stmt *S) {
8281 bool Res = false;
8282 for (const Stmt *Child : S->children())
8283 Res = (Child && Visit(Child)) || Res;
8284 return Res;
8285 }
8286 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8287 const ValueDecl *CurLCDecl, bool IsInitializer,
8288 const ValueDecl *PrevDepDecl = nullptr,
8289 bool SupportsNonRectangular = true)
8290 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8291 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8292 SupportsNonRectangular(SupportsNonRectangular) {}
8293 unsigned getBaseLoopId() const {
8294 assert(CurLCDecl && "Expected loop dependency.");
8295 return BaseLoopId;
8296 }
8297 const ValueDecl *getDepDecl() const {
8298 assert(CurLCDecl && "Expected loop dependency.");
8299 return DepDecl;
8300 }
8301};
8302} // namespace
8303
8304std::optional<unsigned>
8305OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8306 bool IsInitializer) {
8307 // Check for the non-rectangular loops.
8308 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8309 DepDecl, SupportsNonRectangular);
8310 if (LoopStmtChecker.Visit(S)) {
8311 DepDecl = LoopStmtChecker.getDepDecl();
8312 return LoopStmtChecker.getBaseLoopId();
8313 }
8314 return std::nullopt;
8315}
8316
8317bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8318 // Check init-expr for canonical loop form and save loop counter
8319 // variable - #Var and its initialization value - #LB.
8320 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8321 // var = lb
8322 // integer-type var = lb
8323 // random-access-iterator-type var = lb
8324 // pointer-type var = lb
8325 //
8326 if (!S) {
8327 if (EmitDiags) {
8328 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8329 }
8330 return true;
8331 }
8332 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: S))
8333 if (!ExprTemp->cleanupsHaveSideEffects())
8334 S = ExprTemp->getSubExpr();
8335
8336 InitSrcRange = S->getSourceRange();
8337 if (Expr *E = dyn_cast<Expr>(Val: S))
8338 S = E->IgnoreParens();
8339 if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8340 if (BO->getOpcode() == BO_Assign) {
8341 Expr *LHS = BO->getLHS()->IgnoreParens();
8342 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS)) {
8343 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: DRE->getDecl()))
8344 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8345 return setLCDeclAndLB(NewLCDecl: ME->getMemberDecl(), NewLCRefExpr: ME, NewLB: BO->getRHS(),
8346 EmitDiags);
8347 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8348 }
8349 if (auto *ME = dyn_cast<MemberExpr>(Val: LHS)) {
8350 if (ME->isArrow() &&
8351 isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
8352 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8353 EmitDiags);
8354 }
8355 }
8356 } else if (auto *DS = dyn_cast<DeclStmt>(Val: S)) {
8357 if (DS->isSingleDecl()) {
8358 if (auto *Var = dyn_cast_or_null<VarDecl>(Val: DS->getSingleDecl())) {
8359 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8360 // Accept non-canonical init form here but emit ext. warning.
8361 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8362 SemaRef.Diag(S->getBeginLoc(),
8363 diag::ext_omp_loop_not_canonical_init)
8364 << S->getSourceRange();
8365 return setLCDeclAndLB(
8366 NewLCDecl: Var,
8367 NewLCRefExpr: buildDeclRefExpr(SemaRef, Var,
8368 Var->getType().getNonReferenceType(),
8369 DS->getBeginLoc()),
8370 NewLB: Var->getInit(), EmitDiags);
8371 }
8372 }
8373 }
8374 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8375 if (CE->getOperator() == OO_Equal) {
8376 Expr *LHS = CE->getArg(0);
8377 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8378 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8379 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8380 return setLCDeclAndLB(NewLCDecl: ME->getMemberDecl(), NewLCRefExpr: ME, NewLB: BO->getRHS(),
8381 EmitDiags);
8382 return setLCDeclAndLB(NewLCDecl: DRE->getDecl(), NewLCRefExpr: DRE, NewLB: CE->getArg(1), EmitDiags);
8383 }
8384 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8385 if (ME->isArrow() &&
8386 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8387 return setLCDeclAndLB(NewLCDecl: ME->getMemberDecl(), NewLCRefExpr: ME, NewLB: BO->getRHS(),
8388 EmitDiags);
8389 }
8390 }
8391 }
8392
8393 if (dependent() || SemaRef.CurContext->isDependentContext())
8394 return false;
8395 if (EmitDiags) {
8396 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8397 << S->getSourceRange();
8398 }
8399 return true;
8400}
8401
8402/// Ignore parenthesizes, implicit casts, copy constructor and return the
8403/// variable (which may be the loop variable) if possible.
8404static const ValueDecl *getInitLCDecl(const Expr *E) {
8405 if (!E)
8406 return nullptr;
8407 E = getExprAsWritten(E);
8408 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(Val: E))
8409 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8410 if ((Ctor->isCopyOrMoveConstructor() ||
8411 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8412 CE->getNumArgs() > 0 && CE->getArg(Arg: 0) != nullptr)
8413 E = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
8414 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(Val: E)) {
8415 if (const auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
8416 return getCanonicalDecl(VD);
8417 }
8418 if (const auto *ME = dyn_cast_or_null<MemberExpr>(Val: E))
8419 if (ME->isArrow() && isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
8420 return getCanonicalDecl(D: ME->getMemberDecl());
8421 return nullptr;
8422}
8423
8424bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8425 // Check test-expr for canonical form, save upper-bound UB, flags for
8426 // less/greater and for strict/non-strict comparison.
8427 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8428 // var relational-op b
8429 // b relational-op var
8430 //
8431 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8432 if (!S) {
8433 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8434 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8435 return true;
8436 }
8437 Condition = S;
8438 S = getExprAsWritten(E: S);
8439 SourceLocation CondLoc = S->getBeginLoc();
8440 auto &&CheckAndSetCond =
8441 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8442 const Expr *RHS, SourceRange SR,
8443 SourceLocation OpLoc) -> std::optional<bool> {
8444 if (BinaryOperator::isRelationalOp(Opc: Opcode)) {
8445 if (getInitLCDecl(E: LHS) == LCDecl)
8446 return setUB(NewUB: const_cast<Expr *>(RHS),
8447 LessOp: (Opcode == BO_LT || Opcode == BO_LE),
8448 StrictOp: (Opcode == BO_LT || Opcode == BO_GT), SR, SL: OpLoc);
8449 if (getInitLCDecl(E: RHS) == LCDecl)
8450 return setUB(NewUB: const_cast<Expr *>(LHS),
8451 LessOp: (Opcode == BO_GT || Opcode == BO_GE),
8452 StrictOp: (Opcode == BO_LT || Opcode == BO_GT), SR, SL: OpLoc);
8453 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8454 return setUB(NewUB: const_cast<Expr *>(getInitLCDecl(E: LHS) == LCDecl ? RHS : LHS),
8455 /*LessOp=*/std::nullopt,
8456 /*StrictOp=*/true, SR, SL: OpLoc);
8457 }
8458 return std::nullopt;
8459 };
8460 std::optional<bool> Res;
8461 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(Val: S)) {
8462 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8463 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8464 RBO->getOperatorLoc());
8465 } else if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8466 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8467 BO->getSourceRange(), BO->getOperatorLoc());
8468 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8469 if (CE->getNumArgs() == 2) {
8470 Res = CheckAndSetCond(
8471 BinaryOperator::getOverloadedOpcode(OO: CE->getOperator()), CE->getArg(0),
8472 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8473 }
8474 }
8475 if (Res)
8476 return *Res;
8477 if (dependent() || SemaRef.CurContext->isDependentContext())
8478 return false;
8479 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8480 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8481 return true;
8482}
8483
8484bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8485 // RHS of canonical loop form increment can be:
8486 // var + incr
8487 // incr + var
8488 // var - incr
8489 //
8490 RHS = RHS->IgnoreParenImpCasts();
8491 if (auto *BO = dyn_cast<BinaryOperator>(Val: RHS)) {
8492 if (BO->isAdditiveOp()) {
8493 bool IsAdd = BO->getOpcode() == BO_Add;
8494 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8495 return setStep(NewStep: BO->getRHS(), Subtract: !IsAdd);
8496 if (IsAdd && getInitLCDecl(E: BO->getRHS()) == LCDecl)
8497 return setStep(NewStep: BO->getLHS(), /*Subtract=*/false);
8498 }
8499 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: RHS)) {
8500 bool IsAdd = CE->getOperator() == OO_Plus;
8501 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8502 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8503 return setStep(NewStep: CE->getArg(1), Subtract: !IsAdd);
8504 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8505 return setStep(NewStep: CE->getArg(0), /*Subtract=*/false);
8506 }
8507 }
8508 if (dependent() || SemaRef.CurContext->isDependentContext())
8509 return false;
8510 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8511 << RHS->getSourceRange() << LCDecl;
8512 return true;
8513}
8514
8515bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8516 // Check incr-expr for canonical loop form and return true if it
8517 // does not conform.
8518 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8519 // ++var
8520 // var++
8521 // --var
8522 // var--
8523 // var += incr
8524 // var -= incr
8525 // var = var + incr
8526 // var = incr + var
8527 // var = var - incr
8528 //
8529 if (!S) {
8530 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8531 return true;
8532 }
8533 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: S))
8534 if (!ExprTemp->cleanupsHaveSideEffects())
8535 S = ExprTemp->getSubExpr();
8536
8537 IncrementSrcRange = S->getSourceRange();
8538 S = S->IgnoreParens();
8539 if (auto *UO = dyn_cast<UnaryOperator>(Val: S)) {
8540 if (UO->isIncrementDecrementOp() &&
8541 getInitLCDecl(E: UO->getSubExpr()) == LCDecl)
8542 return setStep(NewStep: SemaRef
8543 .ActOnIntegerConstant(Loc: UO->getBeginLoc(),
8544 Val: (UO->isDecrementOp() ? -1 : 1))
8545 .get(),
8546 /*Subtract=*/false);
8547 } else if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8548 switch (BO->getOpcode()) {
8549 case BO_AddAssign:
8550 case BO_SubAssign:
8551 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8552 return setStep(NewStep: BO->getRHS(), Subtract: BO->getOpcode() == BO_SubAssign);
8553 break;
8554 case BO_Assign:
8555 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8556 return checkAndSetIncRHS(RHS: BO->getRHS());
8557 break;
8558 default:
8559 break;
8560 }
8561 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8562 switch (CE->getOperator()) {
8563 case OO_PlusPlus:
8564 case OO_MinusMinus:
8565 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8566 return setStep(NewStep: SemaRef
8567 .ActOnIntegerConstant(
8568 Loc: CE->getBeginLoc(),
8569 Val: ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8570 .get(),
8571 /*Subtract=*/false);
8572 break;
8573 case OO_PlusEqual:
8574 case OO_MinusEqual:
8575 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8576 return setStep(NewStep: CE->getArg(1), Subtract: CE->getOperator() == OO_MinusEqual);
8577 break;
8578 case OO_Equal:
8579 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8580 return checkAndSetIncRHS(RHS: CE->getArg(1));
8581 break;
8582 default:
8583 break;
8584 }
8585 }
8586 if (dependent() || SemaRef.CurContext->isDependentContext())
8587 return false;
8588 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8589 << S->getSourceRange() << LCDecl;
8590 return true;
8591}
8592
8593static ExprResult
8594tryBuildCapture(Sema &SemaRef, Expr *Capture,
8595 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8596 StringRef Name = ".capture_expr.") {
8597 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8598 return Capture;
8599 if (Capture->isEvaluatable(Ctx: SemaRef.Context, AllowSideEffects: Expr::SE_AllowSideEffects))
8600 return SemaRef.PerformImplicitConversion(
8601 From: Capture->IgnoreImpCasts(), ToType: Capture->getType(), Action: Sema::AA_Converting,
8602 /*AllowExplicit=*/true);
8603 auto I = Captures.find(Key: Capture);
8604 if (I != Captures.end())
8605 return buildCapture(S&: SemaRef, CaptureExpr: Capture, Ref&: I->second, Name);
8606 DeclRefExpr *Ref = nullptr;
8607 ExprResult Res = buildCapture(S&: SemaRef, CaptureExpr: Capture, Ref, Name);
8608 Captures[Capture] = Ref;
8609 return Res;
8610}
8611
8612/// Calculate number of iterations, transforming to unsigned, if number of
8613/// iterations may be larger than the original type.
8614static Expr *
8615calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8616 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8617 bool TestIsStrictOp, bool RoundToStep,
8618 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8619 ExprResult NewStep = tryBuildCapture(SemaRef, Capture: Step, Captures, Name: ".new_step");
8620 if (!NewStep.isUsable())
8621 return nullptr;
8622 llvm::APSInt LRes, SRes;
8623 bool IsLowerConst = false, IsStepConst = false;
8624 if (std::optional<llvm::APSInt> Res =
8625 Lower->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8626 LRes = *Res;
8627 IsLowerConst = true;
8628 }
8629 if (std::optional<llvm::APSInt> Res =
8630 Step->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8631 SRes = *Res;
8632 IsStepConst = true;
8633 }
8634 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8635 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8636 (TestIsStrictOp && LRes.isStrictlyPositive()));
8637 bool NeedToReorganize = false;
8638 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8639 if (!NoNeedToConvert && IsLowerConst &&
8640 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8641 NoNeedToConvert = true;
8642 if (RoundToStep) {
8643 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8644 ? LRes.getBitWidth()
8645 : SRes.getBitWidth();
8646 LRes = LRes.extend(width: BW + 1);
8647 LRes.setIsSigned(true);
8648 SRes = SRes.extend(width: BW + 1);
8649 SRes.setIsSigned(true);
8650 LRes -= SRes;
8651 NoNeedToConvert = LRes.trunc(width: BW).extend(width: BW + 1) == LRes;
8652 LRes = LRes.trunc(width: BW);
8653 }
8654 if (TestIsStrictOp) {
8655 unsigned BW = LRes.getBitWidth();
8656 LRes = LRes.extend(width: BW + 1);
8657 LRes.setIsSigned(true);
8658 ++LRes;
8659 NoNeedToConvert =
8660 NoNeedToConvert && LRes.trunc(width: BW).extend(width: BW + 1) == LRes;
8661 // truncate to the original bitwidth.
8662 LRes = LRes.trunc(width: BW);
8663 }
8664 NeedToReorganize = NoNeedToConvert;
8665 }
8666 llvm::APSInt URes;
8667 bool IsUpperConst = false;
8668 if (std::optional<llvm::APSInt> Res =
8669 Upper->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8670 URes = *Res;
8671 IsUpperConst = true;
8672 }
8673 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8674 (!RoundToStep || IsStepConst)) {
8675 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8676 : URes.getBitWidth();
8677 LRes = LRes.extend(width: BW + 1);
8678 LRes.setIsSigned(true);
8679 URes = URes.extend(width: BW + 1);
8680 URes.setIsSigned(true);
8681 URes -= LRes;
8682 NoNeedToConvert = URes.trunc(width: BW).extend(width: BW + 1) == URes;
8683 NeedToReorganize = NoNeedToConvert;
8684 }
8685 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8686 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8687 // unsigned.
8688 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8689 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8690 QualType LowerTy = Lower->getType();
8691 QualType UpperTy = Upper->getType();
8692 uint64_t LowerSize = SemaRef.Context.getTypeSize(T: LowerTy);
8693 uint64_t UpperSize = SemaRef.Context.getTypeSize(T: UpperTy);
8694 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8695 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8696 QualType CastType = SemaRef.Context.getIntTypeForBitwidth(
8697 DestWidth: LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8698 Upper =
8699 SemaRef
8700 .PerformImplicitConversion(
8701 From: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Upper).get(),
8702 ToType: CastType, Action: Sema::AA_Converting)
8703 .get();
8704 Lower = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Lower).get();
8705 NewStep = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: NewStep.get());
8706 }
8707 }
8708 if (!Lower || !Upper || NewStep.isInvalid())
8709 return nullptr;
8710
8711 ExprResult Diff;
8712 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8713 // 1]).
8714 if (NeedToReorganize) {
8715 Diff = Lower;
8716
8717 if (RoundToStep) {
8718 // Lower - Step
8719 Diff =
8720 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8721 if (!Diff.isUsable())
8722 return nullptr;
8723 }
8724
8725 // Lower - Step [+ 1]
8726 if (TestIsStrictOp)
8727 Diff = SemaRef.BuildBinOp(
8728 S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(),
8729 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
8730 if (!Diff.isUsable())
8731 return nullptr;
8732
8733 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
8734 if (!Diff.isUsable())
8735 return nullptr;
8736
8737 // Upper - (Lower - Step [+ 1]).
8738 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Diff.get());
8739 if (!Diff.isUsable())
8740 return nullptr;
8741 } else {
8742 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Lower);
8743
8744 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8745 // BuildBinOp already emitted error, this one is to point user to upper
8746 // and lower bound, and to tell what is passed to 'operator-'.
8747 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8748 << Upper->getSourceRange() << Lower->getSourceRange();
8749 return nullptr;
8750 }
8751
8752 if (!Diff.isUsable())
8753 return nullptr;
8754
8755 // Upper - Lower [- 1]
8756 if (TestIsStrictOp)
8757 Diff = SemaRef.BuildBinOp(
8758 S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Diff.get(),
8759 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
8760 if (!Diff.isUsable())
8761 return nullptr;
8762
8763 if (RoundToStep) {
8764 // Upper - Lower [- 1] + Step
8765 Diff =
8766 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8767 if (!Diff.isUsable())
8768 return nullptr;
8769 }
8770 }
8771
8772 // Parentheses (for dumping/debugging purposes only).
8773 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
8774 if (!Diff.isUsable())
8775 return nullptr;
8776
8777 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8778 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Div, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8779 if (!Diff.isUsable())
8780 return nullptr;
8781
8782 return Diff.get();
8783}
8784
8785/// Build the expression to calculate the number of iterations.
8786Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8787 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8788 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8789 QualType VarType = LCDecl->getType().getNonReferenceType();
8790 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8791 !SemaRef.getLangOpts().CPlusPlus)
8792 return nullptr;
8793 Expr *LBVal = LB;
8794 Expr *UBVal = UB;
8795 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8796 // max(LB(MinVal), LB(MaxVal)))
8797 if (InitDependOnLC) {
8798 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8799 if (!IS.MinValue || !IS.MaxValue)
8800 return nullptr;
8801 // OuterVar = Min
8802 ExprResult MinValue =
8803 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MinValue);
8804 if (!MinValue.isUsable())
8805 return nullptr;
8806
8807 ExprResult LBMinVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
8808 LHSExpr: IS.CounterVar, RHSExpr: MinValue.get());
8809 if (!LBMinVal.isUsable())
8810 return nullptr;
8811 // OuterVar = Min, LBVal
8812 LBMinVal =
8813 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: LBMinVal.get(), RHSExpr: LBVal);
8814 if (!LBMinVal.isUsable())
8815 return nullptr;
8816 // (OuterVar = Min, LBVal)
8817 LBMinVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: LBMinVal.get());
8818 if (!LBMinVal.isUsable())
8819 return nullptr;
8820
8821 // OuterVar = Max
8822 ExprResult MaxValue =
8823 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MaxValue);
8824 if (!MaxValue.isUsable())
8825 return nullptr;
8826
8827 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
8828 LHSExpr: IS.CounterVar, RHSExpr: MaxValue.get());
8829 if (!LBMaxVal.isUsable())
8830 return nullptr;
8831 // OuterVar = Max, LBVal
8832 LBMaxVal =
8833 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: LBMaxVal.get(), RHSExpr: LBVal);
8834 if (!LBMaxVal.isUsable())
8835 return nullptr;
8836 // (OuterVar = Max, LBVal)
8837 LBMaxVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: LBMaxVal.get());
8838 if (!LBMaxVal.isUsable())
8839 return nullptr;
8840
8841 Expr *LBMin =
8842 tryBuildCapture(SemaRef, Capture: LBMinVal.get(), Captures, Name: ".lb_min").get();
8843 Expr *LBMax =
8844 tryBuildCapture(SemaRef, Capture: LBMaxVal.get(), Captures, Name: ".lb_max").get();
8845 if (!LBMin || !LBMax)
8846 return nullptr;
8847 // LB(MinVal) < LB(MaxVal)
8848 ExprResult MinLessMaxRes =
8849 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_LT, LHSExpr: LBMin, RHSExpr: LBMax);
8850 if (!MinLessMaxRes.isUsable())
8851 return nullptr;
8852 Expr *MinLessMax =
8853 tryBuildCapture(SemaRef, Capture: MinLessMaxRes.get(), Captures, Name: ".min_less_max")
8854 .get();
8855 if (!MinLessMax)
8856 return nullptr;
8857 if (*TestIsLessOp) {
8858 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8859 // LB(MaxVal))
8860 ExprResult MinLB = SemaRef.ActOnConditionalOp(QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc,
8861 CondExpr: MinLessMax, LHSExpr: LBMin, RHSExpr: LBMax);
8862 if (!MinLB.isUsable())
8863 return nullptr;
8864 LBVal = MinLB.get();
8865 } else {
8866 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8867 // LB(MaxVal))
8868 ExprResult MaxLB = SemaRef.ActOnConditionalOp(QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc,
8869 CondExpr: MinLessMax, LHSExpr: LBMax, RHSExpr: LBMin);
8870 if (!MaxLB.isUsable())
8871 return nullptr;
8872 LBVal = MaxLB.get();
8873 }
8874 // OuterVar = LB
8875 LBMinVal =
8876 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign, LHSExpr: IS.CounterVar, RHSExpr: LBVal);
8877 if (!LBMinVal.isUsable())
8878 return nullptr;
8879 LBVal = LBMinVal.get();
8880 }
8881 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8882 // min(UB(MinVal), UB(MaxVal))
8883 if (CondDependOnLC) {
8884 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8885 if (!IS.MinValue || !IS.MaxValue)
8886 return nullptr;
8887 // OuterVar = Min
8888 ExprResult MinValue =
8889 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MinValue);
8890 if (!MinValue.isUsable())
8891 return nullptr;
8892
8893 ExprResult UBMinVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
8894 LHSExpr: IS.CounterVar, RHSExpr: MinValue.get());
8895 if (!UBMinVal.isUsable())
8896 return nullptr;
8897 // OuterVar = Min, UBVal
8898 UBMinVal =
8899 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: UBMinVal.get(), RHSExpr: UBVal);
8900 if (!UBMinVal.isUsable())
8901 return nullptr;
8902 // (OuterVar = Min, UBVal)
8903 UBMinVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: UBMinVal.get());
8904 if (!UBMinVal.isUsable())
8905 return nullptr;
8906
8907 // OuterVar = Max
8908 ExprResult MaxValue =
8909 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MaxValue);
8910 if (!MaxValue.isUsable())
8911 return nullptr;
8912
8913 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
8914 LHSExpr: IS.CounterVar, RHSExpr: MaxValue.get());
8915 if (!UBMaxVal.isUsable())
8916 return nullptr;
8917 // OuterVar = Max, UBVal
8918 UBMaxVal =
8919 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: UBMaxVal.get(), RHSExpr: UBVal);
8920 if (!UBMaxVal.isUsable())
8921 return nullptr;
8922 // (OuterVar = Max, UBVal)
8923 UBMaxVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: UBMaxVal.get());
8924 if (!UBMaxVal.isUsable())
8925 return nullptr;
8926
8927 Expr *UBMin =
8928 tryBuildCapture(SemaRef, Capture: UBMinVal.get(), Captures, Name: ".ub_min").get();
8929 Expr *UBMax =
8930 tryBuildCapture(SemaRef, Capture: UBMaxVal.get(), Captures, Name: ".ub_max").get();
8931 if (!UBMin || !UBMax)
8932 return nullptr;
8933 // UB(MinVal) > UB(MaxVal)
8934 ExprResult MinGreaterMaxRes =
8935 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_GT, LHSExpr: UBMin, RHSExpr: UBMax);
8936 if (!MinGreaterMaxRes.isUsable())
8937 return nullptr;
8938 Expr *MinGreaterMax = tryBuildCapture(SemaRef, Capture: MinGreaterMaxRes.get(),
8939 Captures, Name: ".min_greater_max")
8940 .get();
8941 if (!MinGreaterMax)
8942 return nullptr;
8943 if (*TestIsLessOp) {
8944 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8945 // UB(MaxVal))
8946 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8947 QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc, CondExpr: MinGreaterMax, LHSExpr: UBMin, RHSExpr: UBMax);
8948 if (!MaxUB.isUsable())
8949 return nullptr;
8950 UBVal = MaxUB.get();
8951 } else {
8952 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8953 // UB(MaxVal))
8954 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8955 QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc, CondExpr: MinGreaterMax, LHSExpr: UBMax, RHSExpr: UBMin);
8956 if (!MinUB.isUsable())
8957 return nullptr;
8958 UBVal = MinUB.get();
8959 }
8960 }
8961 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8962 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8963 Expr *Upper = tryBuildCapture(SemaRef, Capture: UBExpr, Captures, Name: ".upper").get();
8964 Expr *Lower = tryBuildCapture(SemaRef, Capture: LBExpr, Captures, Name: ".lower").get();
8965 if (!Upper || !Lower)
8966 return nullptr;
8967
8968 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8969 Step, LCTy: VarType, TestIsStrictOp,
8970 /*RoundToStep=*/true, Captures);
8971 if (!Diff.isUsable())
8972 return nullptr;
8973
8974 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8975 QualType Type = Diff.get()->getType();
8976 ASTContext &C = SemaRef.Context;
8977 bool UseVarType = VarType->hasIntegerRepresentation() &&
8978 C.getTypeSize(T: Type) > C.getTypeSize(T: VarType);
8979 if (!Type->isIntegerType() || UseVarType) {
8980 unsigned NewSize =
8981 UseVarType ? C.getTypeSize(T: VarType) : C.getTypeSize(T: Type);
8982 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8983 : Type->hasSignedIntegerRepresentation();
8984 Type = C.getIntTypeForBitwidth(DestWidth: NewSize, Signed: IsSigned);
8985 if (!SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: Type)) {
8986 Diff = SemaRef.PerformImplicitConversion(
8987 From: Diff.get(), ToType: Type, Action: Sema::AA_Converting, /*AllowExplicit=*/true);
8988 if (!Diff.isUsable())
8989 return nullptr;
8990 }
8991 }
8992 if (LimitedType) {
8993 unsigned NewSize = (C.getTypeSize(T: Type) > 32) ? 64 : 32;
8994 if (NewSize != C.getTypeSize(T: Type)) {
8995 if (NewSize < C.getTypeSize(T: Type)) {
8996 assert(NewSize == 64 && "incorrect loop var size");
8997 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8998 << InitSrcRange << ConditionSrcRange;
8999 }
9000 QualType NewType = C.getIntTypeForBitwidth(
9001 DestWidth: NewSize, Signed: Type->hasSignedIntegerRepresentation() ||
9002 C.getTypeSize(T: Type) < NewSize);
9003 if (!SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: NewType)) {
9004 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: NewType,
9005 Action: Sema::AA_Converting, AllowExplicit: true);
9006 if (!Diff.isUsable())
9007 return nullptr;
9008 }
9009 }
9010 }
9011
9012 return Diff.get();
9013}
9014
9015std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9016 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9017 // Do not build for iterators, they cannot be used in non-rectangular loop
9018 // nests.
9019 if (LCDecl->getType()->isRecordType())
9020 return std::make_pair(x: nullptr, y: nullptr);
9021 // If we subtract, the min is in the condition, otherwise the min is in the
9022 // init value.
9023 Expr *MinExpr = nullptr;
9024 Expr *MaxExpr = nullptr;
9025 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9026 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9027 bool LBNonRect =
9028 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9029 bool UBNonRect =
9030 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9031 Expr *Lower =
9032 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, Capture: LBExpr, Captures).get();
9033 Expr *Upper =
9034 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, Capture: UBExpr, Captures).get();
9035 if (!Upper || !Lower)
9036 return std::make_pair(x: nullptr, y: nullptr);
9037
9038 if (*TestIsLessOp)
9039 MinExpr = Lower;
9040 else
9041 MaxExpr = Upper;
9042
9043 // Build minimum/maximum value based on number of iterations.
9044 QualType VarType = LCDecl->getType().getNonReferenceType();
9045
9046 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9047 Step, LCTy: VarType, TestIsStrictOp,
9048 /*RoundToStep=*/false, Captures);
9049 if (!Diff.isUsable())
9050 return std::make_pair(x: nullptr, y: nullptr);
9051
9052 // ((Upper - Lower [- 1]) / Step) * Step
9053 // Parentheses (for dumping/debugging purposes only).
9054 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9055 if (!Diff.isUsable())
9056 return std::make_pair(x: nullptr, y: nullptr);
9057
9058 ExprResult NewStep = tryBuildCapture(SemaRef, Capture: Step, Captures, Name: ".new_step");
9059 if (!NewStep.isUsable())
9060 return std::make_pair(x: nullptr, y: nullptr);
9061 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Mul, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
9062 if (!Diff.isUsable())
9063 return std::make_pair(x: nullptr, y: nullptr);
9064
9065 // Parentheses (for dumping/debugging purposes only).
9066 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
9067 if (!Diff.isUsable())
9068 return std::make_pair(x: nullptr, y: nullptr);
9069
9070 // Convert to the ptrdiff_t, if original type is pointer.
9071 if (VarType->isAnyPointerType() &&
9072 !SemaRef.Context.hasSameType(
9073 T1: Diff.get()->getType(),
9074 T2: SemaRef.Context.getUnsignedPointerDiffType())) {
9075 Diff = SemaRef.PerformImplicitConversion(
9076 From: Diff.get(), ToType: SemaRef.Context.getUnsignedPointerDiffType(),
9077 Action: Sema::AA_Converting, /*AllowExplicit=*/true);
9078 }
9079 if (!Diff.isUsable())
9080 return std::make_pair(x: nullptr, y: nullptr);
9081
9082 if (*TestIsLessOp) {
9083 // MinExpr = Lower;
9084 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9085 Diff = SemaRef.BuildBinOp(
9086 S, OpLoc: DefaultLoc, Opc: BO_Add,
9087 LHSExpr: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Lower).get(),
9088 RHSExpr: Diff.get());
9089 if (!Diff.isUsable())
9090 return std::make_pair(x: nullptr, y: nullptr);
9091 } else {
9092 // MaxExpr = Upper;
9093 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9094 Diff = SemaRef.BuildBinOp(
9095 S, OpLoc: DefaultLoc, Opc: BO_Sub,
9096 LHSExpr: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Upper).get(),
9097 RHSExpr: Diff.get());
9098 if (!Diff.isUsable())
9099 return std::make_pair(x: nullptr, y: nullptr);
9100 }
9101
9102 // Convert to the original type.
9103 if (SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: VarType))
9104 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: VarType,
9105 Action: Sema::AA_Converting,
9106 /*AllowExplicit=*/true);
9107 if (!Diff.isUsable())
9108 return std::make_pair(x: nullptr, y: nullptr);
9109
9110 Sema::TentativeAnalysisScope Trap(SemaRef);
9111 Diff = SemaRef.ActOnFinishFullExpr(Expr: Diff.get(), /*DiscardedValue=*/false);
9112 if (!Diff.isUsable())
9113 return std::make_pair(x: nullptr, y: nullptr);
9114
9115 if (*TestIsLessOp)
9116 MaxExpr = Diff.get();
9117 else
9118 MinExpr = Diff.get();
9119
9120 return std::make_pair(x&: MinExpr, y&: MaxExpr);
9121}
9122
9123Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9124 if (InitDependOnLC || CondDependOnLC)
9125 return Condition;
9126 return nullptr;
9127}
9128
9129Expr *OpenMPIterationSpaceChecker::buildPreCond(
9130 Scope *S, Expr *Cond,
9131 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9132 // Do not build a precondition when the condition/initialization is dependent
9133 // to prevent pessimistic early loop exit.
9134 // TODO: this can be improved by calculating min/max values but not sure that
9135 // it will be very effective.
9136 if (CondDependOnLC || InitDependOnLC)
9137 return SemaRef
9138 .PerformImplicitConversion(
9139 SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get(),
9140 SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
9141 /*AllowExplicit=*/true)
9142 .get();
9143
9144 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9145 Sema::TentativeAnalysisScope Trap(SemaRef);
9146
9147 ExprResult NewLB = tryBuildCapture(SemaRef, Capture: LB, Captures);
9148 ExprResult NewUB = tryBuildCapture(SemaRef, Capture: UB, Captures);
9149 if (!NewLB.isUsable() || !NewUB.isUsable())
9150 return nullptr;
9151
9152 ExprResult CondExpr =
9153 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc,
9154 Opc: *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9155 : (TestIsStrictOp ? BO_GT : BO_GE),
9156 LHSExpr: NewLB.get(), RHSExpr: NewUB.get());
9157 if (CondExpr.isUsable()) {
9158 if (!SemaRef.Context.hasSameUnqualifiedType(T1: CondExpr.get()->getType(),
9159 T2: SemaRef.Context.BoolTy))
9160 CondExpr = SemaRef.PerformImplicitConversion(
9161 CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
9162 /*AllowExplicit=*/true);
9163 }
9164
9165 // Otherwise use original loop condition and evaluate it in runtime.
9166 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9167}
9168
9169/// Build reference expression to the counter be used for codegen.
9170DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9171 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9172 DSAStackTy &DSA) const {
9173 auto *VD = dyn_cast<VarDecl>(Val: LCDecl);
9174 if (!VD) {
9175 VD = SemaRef.isOpenMPCapturedDecl(D: LCDecl);
9176 DeclRefExpr *Ref = buildDeclRefExpr(
9177 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9178 const DSAStackTy::DSAVarData Data =
9179 DSA.getTopDSA(D: LCDecl, /*FromParent=*/false);
9180 // If the loop control decl is explicitly marked as private, do not mark it
9181 // as captured again.
9182 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9183 Captures.insert(KV: std::make_pair(x: LCRef, y&: Ref));
9184 return Ref;
9185 }
9186 return cast<DeclRefExpr>(Val: LCRef);
9187}
9188
9189Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9190 if (LCDecl && !LCDecl->isInvalidDecl()) {
9191 QualType Type = LCDecl->getType().getNonReferenceType();
9192 VarDecl *PrivateVar = buildVarDecl(
9193 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9194 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9195 isa<VarDecl>(Val: LCDecl)
9196 ? buildDeclRefExpr(S&: SemaRef, D: cast<VarDecl>(Val: LCDecl), Ty: Type, Loc: DefaultLoc)
9197 : nullptr);
9198 if (PrivateVar->isInvalidDecl())
9199 return nullptr;
9200 return buildDeclRefExpr(S&: SemaRef, D: PrivateVar, Ty: Type, Loc: DefaultLoc);
9201 }
9202 return nullptr;
9203}
9204
9205/// Build initialization of the counter to be used for codegen.
9206Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9207
9208/// Build step of the counter be used for codegen.
9209Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9210
9211Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9212 Scope *S, Expr *Counter,
9213 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9214 Expr *Inc, OverloadedOperatorKind OOK) {
9215 Expr *Cnt = SemaRef.DefaultLvalueConversion(E: Counter).get();
9216 if (!Cnt)
9217 return nullptr;
9218 if (Inc) {
9219 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9220 "Expected only + or - operations for depend clauses.");
9221 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9222 Cnt = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BOK, LHSExpr: Cnt, RHSExpr: Inc).get();
9223 if (!Cnt)
9224 return nullptr;
9225 }
9226 QualType VarType = LCDecl->getType().getNonReferenceType();
9227 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9228 !SemaRef.getLangOpts().CPlusPlus)
9229 return nullptr;
9230 // Upper - Lower
9231 Expr *Upper =
9232 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, Capture: LB, Captures).get();
9233 Expr *Lower =
9234 *TestIsLessOp ? tryBuildCapture(SemaRef, Capture: LB, Captures).get() : Cnt;
9235 if (!Upper || !Lower)
9236 return nullptr;
9237
9238 ExprResult Diff = calculateNumIters(
9239 SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType,
9240 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9241 if (!Diff.isUsable())
9242 return nullptr;
9243
9244 return Diff.get();
9245}
9246} // namespace
9247
9248void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
9249 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9250 assert(Init && "Expected loop in canonical form.");
9251 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9252 if (AssociatedLoops > 0 &&
9253 isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
9254 DSAStack->loopStart();
9255 OpenMPIterationSpaceChecker ISC(*this, /*SupportsNonRectangular=*/true,
9256 *DSAStack, ForLoc);
9257 if (!ISC.checkAndSetInit(S: Init, /*EmitDiags=*/false)) {
9258 if (ValueDecl *D = ISC.getLoopDecl()) {
9259 auto *VD = dyn_cast<VarDecl>(Val: D);
9260 DeclRefExpr *PrivateRef = nullptr;
9261 if (!VD) {
9262 if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9263 VD = Private;
9264 } else {
9265 PrivateRef = buildCapture(S&: *this, D, CaptureExpr: ISC.getLoopDeclRefExpr(),
9266 /*WithInit=*/false);
9267 VD = cast<VarDecl>(Val: PrivateRef->getDecl());
9268 }
9269 }
9270 DSAStack->addLoopControlVariable(D, Capture: VD);
9271 const Decl *LD = DSAStack->getPossiblyLoopCunter();
9272 if (LD != D->getCanonicalDecl()) {
9273 DSAStack->resetPossibleLoopCounter();
9274 if (auto *Var = dyn_cast_or_null<VarDecl>(Val: LD))
9275 MarkDeclarationsReferencedInExpr(
9276 E: buildDeclRefExpr(*this, const_cast<VarDecl *>(Var),
9277 Var->getType().getNonLValueExprType(Context),
9278 ForLoc, /*RefersToCapture=*/true));
9279 }
9280 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9281 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9282 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9283 // associated for-loop of a simd construct with just one associated
9284 // for-loop may be listed in a linear clause with a constant-linear-step
9285 // that is the increment of the associated for-loop. The loop iteration
9286 // variable(s) in the associated for-loop(s) of a for or parallel for
9287 // construct may be listed in a private or lastprivate clause.
9288 DSAStackTy::DSAVarData DVar =
9289 DSAStack->getTopDSA(D, /*FromParent=*/false);
9290 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9291 // is declared in the loop and it is predetermined as a private.
9292 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9293 OpenMPClauseKind PredeterminedCKind =
9294 isOpenMPSimdDirective(DKind)
9295 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9296 : OMPC_private;
9297 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9298 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9299 (LangOpts.OpenMP <= 45 || (DVar.CKind != OMPC_lastprivate &&
9300 DVar.CKind != OMPC_private))) ||
9301 ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
9302 DKind == OMPD_master_taskloop || DKind == OMPD_masked_taskloop ||
9303 DKind == OMPD_parallel_master_taskloop ||
9304 DKind == OMPD_parallel_masked_taskloop ||
9305 isOpenMPDistributeDirective(DKind)) &&
9306 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9307 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9308 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9309 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9310 << getOpenMPClauseName(DVar.CKind)
9311 << getOpenMPDirectiveName(DKind)
9312 << getOpenMPClauseName(PredeterminedCKind);
9313 if (DVar.RefExpr == nullptr)
9314 DVar.CKind = PredeterminedCKind;
9315 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar,
9316 /*IsLoopIterVar=*/true);
9317 } else if (LoopDeclRefExpr) {
9318 // Make the loop iteration variable private (for worksharing
9319 // constructs), linear (for simd directives with the only one
9320 // associated loop) or lastprivate (for simd directives with several
9321 // collapsed or ordered loops).
9322 if (DVar.CKind == OMPC_unknown)
9323 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind,
9324 PrivateRef);
9325 }
9326 }
9327 }
9328 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9329 }
9330}
9331
9332namespace {
9333// Utility for openmp doacross clause kind
9334class OMPDoacrossKind {
9335public:
9336 bool isSource(const OMPDoacrossClause *C) {
9337 return C->getDependenceType() == OMPC_DOACROSS_source ||
9338 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9339 }
9340 bool isSink(const OMPDoacrossClause *C) {
9341 return C->getDependenceType() == OMPC_DOACROSS_sink;
9342 }
9343 bool isSinkIter(const OMPDoacrossClause *C) {
9344 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9345 }
9346};
9347} // namespace
9348/// Called on a for stmt to check and extract its iteration space
9349/// for further processing (such as collapsing).
9350static bool checkOpenMPIterationSpace(
9351 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9352 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9353 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9354 Expr *OrderedLoopCountExpr,
9355 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9356 llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
9357 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9358 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9359 // OpenMP [2.9.1, Canonical Loop Form]
9360 // for (init-expr; test-expr; incr-expr) structured-block
9361 // for (range-decl: range-expr) structured-block
9362 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(Val: S))
9363 S = CanonLoop->getLoopStmt();
9364 auto *For = dyn_cast_or_null<ForStmt>(Val: S);
9365 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(Val: S);
9366 // Ranged for is supported only in OpenMP 5.0.
9367 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9368 OpenMPDirectiveKind DK = (SemaRef.getLangOpts().OpenMP < 50 ||
9369 DSA.getMappedDirective() == OMPD_unknown)
9370 ? DKind
9371 : DSA.getMappedDirective();
9372 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9373 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9374 << getOpenMPDirectiveName(DK) << TotalNestedLoopCount
9375 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9376 if (TotalNestedLoopCount > 1) {
9377 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9378 SemaRef.Diag(DSA.getConstructLoc(),
9379 diag::note_omp_collapse_ordered_expr)
9380 << 2 << CollapseLoopCountExpr->getSourceRange()
9381 << OrderedLoopCountExpr->getSourceRange();
9382 else if (CollapseLoopCountExpr)
9383 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9384 diag::note_omp_collapse_ordered_expr)
9385 << 0 << CollapseLoopCountExpr->getSourceRange();
9386 else
9387 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9388 diag::note_omp_collapse_ordered_expr)
9389 << 1 << OrderedLoopCountExpr->getSourceRange();
9390 }
9391 return true;
9392 }
9393 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9394 "No loop body.");
9395 // Postpone analysis in dependent contexts for ranged for loops.
9396 if (CXXFor && SemaRef.CurContext->isDependentContext())
9397 return false;
9398
9399 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9400 For ? For->getForLoc() : CXXFor->getForLoc());
9401
9402 // Check init.
9403 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9404 if (ISC.checkAndSetInit(S: Init))
9405 return true;
9406
9407 bool HasErrors = false;
9408
9409 // Check loop variable's type.
9410 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9411 // OpenMP [2.6, Canonical Loop Form]
9412 // Var is one of the following:
9413 // A variable of signed or unsigned integer type.
9414 // For C++, a variable of a random access iterator type.
9415 // For C, a variable of a pointer type.
9416 QualType VarType = LCDecl->getType().getNonReferenceType();
9417 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9418 !VarType->isPointerType() &&
9419 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9420 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9421 << SemaRef.getLangOpts().CPlusPlus;
9422 HasErrors = true;
9423 }
9424
9425 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9426 // a Construct
9427 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9428 // parallel for construct is (are) private.
9429 // The loop iteration variable in the associated for-loop of a simd
9430 // construct with just one associated for-loop is linear with a
9431 // constant-linear-step that is the increment of the associated for-loop.
9432 // Exclude loop var from the list of variables with implicitly defined data
9433 // sharing attributes.
9434 VarsWithImplicitDSA.erase(Val: LCDecl);
9435
9436 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9437
9438 // Check test-expr.
9439 HasErrors |= ISC.checkAndSetCond(S: For ? For->getCond() : CXXFor->getCond());
9440
9441 // Check incr-expr.
9442 HasErrors |= ISC.checkAndSetInc(S: For ? For->getInc() : CXXFor->getInc());
9443 }
9444
9445 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9446 return HasErrors;
9447
9448 // Build the loop's iteration space representation.
9449 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9450 S: DSA.getCurScope(), Cond: For ? For->getCond() : CXXFor->getCond(), Captures);
9451 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9452 ISC.buildNumIterations(S: DSA.getCurScope(), ResultIterSpaces,
9453 LimitedType: (isOpenMPWorksharingDirective(DKind) ||
9454 isOpenMPGenericLoopDirective(DKind) ||
9455 isOpenMPTaskLoopDirective(DKind) ||
9456 isOpenMPDistributeDirective(DKind) ||
9457 isOpenMPLoopTransformationDirective(DKind)),
9458 Captures);
9459 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9460 ISC.buildCounterVar(Captures, DSA);
9461 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9462 ISC.buildPrivateCounterVar();
9463 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9464 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9465 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9466 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9467 ISC.getConditionSrcRange();
9468 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9469 ISC.getIncrementSrcRange();
9470 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9471 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9472 ISC.isStrictTestOp();
9473 std::tie(args&: ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9474 args&: ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9475 ISC.buildMinMaxValues(S: DSA.getCurScope(), Captures);
9476 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9477 ISC.buildFinalCondition(S: DSA.getCurScope());
9478 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9479 ISC.doesInitDependOnLC();
9480 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9481 ISC.doesCondDependOnLC();
9482 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9483 ISC.getLoopDependentIdx();
9484
9485 HasErrors |=
9486 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9487 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9488 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9489 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9490 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9491 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9492 if (!HasErrors && DSA.isOrderedRegion()) {
9493 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9494 if (CurrentNestedLoopCount <
9495 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9496 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9497 NumLoop: CurrentNestedLoopCount,
9498 NumIterations: ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9499 DSA.getOrderedRegionParam().second->setLoopCounter(
9500 NumLoop: CurrentNestedLoopCount,
9501 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9502 }
9503 }
9504 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9505 auto *DependC = dyn_cast<OMPDependClause>(Val: Pair.first);
9506 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Val: Pair.first);
9507 unsigned NumLoops =
9508 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9509 if (CurrentNestedLoopCount >= NumLoops) {
9510 // Erroneous case - clause has some problems.
9511 continue;
9512 }
9513 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9514 Pair.second.size() <= CurrentNestedLoopCount) {
9515 // Erroneous case - clause has some problems.
9516 DependC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: nullptr);
9517 continue;
9518 }
9519 OMPDoacrossKind ODK;
9520 if (DoacrossC && ODK.isSink(C: DoacrossC) &&
9521 Pair.second.size() <= CurrentNestedLoopCount) {
9522 // Erroneous case - clause has some problems.
9523 DoacrossC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: nullptr);
9524 continue;
9525 }
9526 Expr *CntValue;
9527 SourceLocation DepLoc =
9528 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9529 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9530 (DoacrossC && ODK.isSource(C: DoacrossC)))
9531 CntValue = ISC.buildOrderedLoopData(
9532 S: DSA.getCurScope(),
9533 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9534 Loc: DepLoc);
9535 else if (DoacrossC && ODK.isSinkIter(C: DoacrossC)) {
9536 Expr *Cnt = SemaRef
9537 .DefaultLvalueConversion(
9538 E: ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9539 .get();
9540 if (!Cnt)
9541 continue;
9542 // build CounterVar - 1
9543 Expr *Inc =
9544 SemaRef.ActOnIntegerConstant(Loc: DoacrossC->getColonLoc(), /*Val=*/1)
9545 .get();
9546 CntValue = ISC.buildOrderedLoopData(
9547 S: DSA.getCurScope(),
9548 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9549 Loc: DepLoc, Inc, OOK: clang::OO_Minus);
9550 } else
9551 CntValue = ISC.buildOrderedLoopData(
9552 S: DSA.getCurScope(),
9553 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9554 Loc: DepLoc, Inc: Pair.second[CurrentNestedLoopCount].first,
9555 OOK: Pair.second[CurrentNestedLoopCount].second);
9556 if (DependC)
9557 DependC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: CntValue);
9558 else
9559 DoacrossC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: CntValue);
9560 }
9561 }
9562
9563 return HasErrors;
9564}
9565
9566/// Build 'VarRef = Start.
9567static ExprResult
9568buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9569 ExprResult Start, bool IsNonRectangularLB,
9570 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9571 // Build 'VarRef = Start.
9572 ExprResult NewStart = IsNonRectangularLB
9573 ? Start.get()
9574 : tryBuildCapture(SemaRef, Capture: Start.get(), Captures);
9575 if (!NewStart.isUsable())
9576 return ExprError();
9577 if (!SemaRef.Context.hasSameType(T1: NewStart.get()->getType(),
9578 T2: VarRef.get()->getType())) {
9579 NewStart = SemaRef.PerformImplicitConversion(
9580 From: NewStart.get(), ToType: VarRef.get()->getType(), Action: Sema::AA_Converting,
9581 /*AllowExplicit=*/true);
9582 if (!NewStart.isUsable())
9583 return ExprError();
9584 }
9585
9586 ExprResult Init =
9587 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: NewStart.get());
9588 return Init;
9589}
9590
9591/// Build 'VarRef = Start + Iter * Step'.
9592static ExprResult buildCounterUpdate(
9593 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9594 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9595 bool IsNonRectangularLB,
9596 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9597 // Add parentheses (for debugging purposes only).
9598 Iter = SemaRef.ActOnParenExpr(L: Loc, R: Loc, E: Iter.get());
9599 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9600 !Step.isUsable())
9601 return ExprError();
9602
9603 ExprResult NewStep = Step;
9604 if (Captures)
9605 NewStep = tryBuildCapture(SemaRef, Capture: Step.get(), Captures&: *Captures);
9606 if (NewStep.isInvalid())
9607 return ExprError();
9608 ExprResult Update =
9609 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Mul, LHSExpr: Iter.get(), RHSExpr: NewStep.get());
9610 if (!Update.isUsable())
9611 return ExprError();
9612
9613 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9614 // 'VarRef = Start (+|-) Iter * Step'.
9615 if (!Start.isUsable())
9616 return ExprError();
9617 ExprResult NewStart = SemaRef.ActOnParenExpr(L: Loc, R: Loc, E: Start.get());
9618 if (!NewStart.isUsable())
9619 return ExprError();
9620 if (Captures && !IsNonRectangularLB)
9621 NewStart = tryBuildCapture(SemaRef, Capture: Start.get(), Captures&: *Captures);
9622 if (NewStart.isInvalid())
9623 return ExprError();
9624
9625 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9626 ExprResult SavedUpdate = Update;
9627 ExprResult UpdateVal;
9628 if (VarRef.get()->getType()->isOverloadableType() ||
9629 NewStart.get()->getType()->isOverloadableType() ||
9630 Update.get()->getType()->isOverloadableType()) {
9631 Sema::TentativeAnalysisScope Trap(SemaRef);
9632
9633 Update =
9634 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: NewStart.get());
9635 if (Update.isUsable()) {
9636 UpdateVal =
9637 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: Subtract ? BO_SubAssign : BO_AddAssign,
9638 LHSExpr: VarRef.get(), RHSExpr: SavedUpdate.get());
9639 if (UpdateVal.isUsable()) {
9640 Update = SemaRef.CreateBuiltinBinOp(OpLoc: Loc, Opc: BO_Comma, LHSExpr: Update.get(),
9641 RHSExpr: UpdateVal.get());
9642 }
9643 }
9644 }
9645
9646 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9647 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9648 Update = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: Subtract ? BO_Sub : BO_Add,
9649 LHSExpr: NewStart.get(), RHSExpr: SavedUpdate.get());
9650 if (!Update.isUsable())
9651 return ExprError();
9652
9653 if (!SemaRef.Context.hasSameType(T1: Update.get()->getType(),
9654 T2: VarRef.get()->getType())) {
9655 Update = SemaRef.PerformImplicitConversion(
9656 From: Update.get(), ToType: VarRef.get()->getType(), Action: Sema::AA_Converting, AllowExplicit: true);
9657 if (!Update.isUsable())
9658 return ExprError();
9659 }
9660
9661 Update = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: Update.get());
9662 }
9663 return Update;
9664}
9665
9666/// Convert integer expression \a E to make it have at least \a Bits
9667/// bits.
9668static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9669 if (E == nullptr)
9670 return ExprError();
9671 ASTContext &C = SemaRef.Context;
9672 QualType OldType = E->getType();
9673 unsigned HasBits = C.getTypeSize(T: OldType);
9674 if (HasBits >= Bits)
9675 return ExprResult(E);
9676 // OK to convert to signed, because new type has more bits than old.
9677 QualType NewType = C.getIntTypeForBitwidth(DestWidth: Bits, /* Signed */ true);
9678 return SemaRef.PerformImplicitConversion(From: E, ToType: NewType, Action: Sema::AA_Converting,
9679 AllowExplicit: true);
9680}
9681
9682/// Check if the given expression \a E is a constant integer that fits
9683/// into \a Bits bits.
9684static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9685 if (E == nullptr)
9686 return false;
9687 if (std::optional<llvm::APSInt> Result =
9688 E->getIntegerConstantExpr(Ctx: SemaRef.Context))
9689 return Signed ? Result->isSignedIntN(N: Bits) : Result->isIntN(N: Bits);
9690 return false;
9691}
9692
9693/// Build preinits statement for the given declarations.
9694static Stmt *buildPreInits(ASTContext &Context,
9695 MutableArrayRef<Decl *> PreInits) {
9696 if (!PreInits.empty()) {
9697 return new (Context) DeclStmt(
9698 DeclGroupRef::Create(C&: Context, Decls: PreInits.begin(), NumDecls: PreInits.size()),
9699 SourceLocation(), SourceLocation());
9700 }
9701 return nullptr;
9702}
9703
9704/// Build preinits statement for the given declarations.
9705static Stmt *
9706buildPreInits(ASTContext &Context,
9707 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9708 if (!Captures.empty()) {
9709 SmallVector<Decl *, 16> PreInits;
9710 for (const auto &Pair : Captures)
9711 PreInits.push_back(Pair.second->getDecl());
9712 return buildPreInits(Context, PreInits);
9713 }
9714 return nullptr;
9715}
9716
9717/// Build postupdate expression for the given list of postupdates expressions.
9718static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9719 Expr *PostUpdate = nullptr;
9720 if (!PostUpdates.empty()) {
9721 for (Expr *E : PostUpdates) {
9722 Expr *ConvE = S.BuildCStyleCastExpr(
9723 LParenLoc: E->getExprLoc(),
9724 Ty: S.Context.getTrivialTypeSourceInfo(T: S.Context.VoidTy),
9725 RParenLoc: E->getExprLoc(), Op: E)
9726 .get();
9727 PostUpdate = PostUpdate
9728 ? S.CreateBuiltinBinOp(OpLoc: ConvE->getExprLoc(), Opc: BO_Comma,
9729 LHSExpr: PostUpdate, RHSExpr: ConvE)
9730 .get()
9731 : ConvE;
9732 }
9733 }
9734 return PostUpdate;
9735}
9736
9737/// Called on a for stmt to check itself and nested loops (if any).
9738/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9739/// number of collapsed loops otherwise.
9740static unsigned
9741checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9742 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9743 DSAStackTy &DSA,
9744 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9745 OMPLoopBasedDirective::HelperExprs &Built) {
9746 unsigned NestedLoopCount = 1;
9747 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9748 !isOpenMPLoopTransformationDirective(DKind);
9749
9750 if (CollapseLoopCountExpr) {
9751 // Found 'collapse' clause - calculate collapse number.
9752 Expr::EvalResult Result;
9753 if (!CollapseLoopCountExpr->isValueDependent() &&
9754 CollapseLoopCountExpr->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext())) {
9755 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9756 } else {
9757 Built.clear(/*Size=*/1);
9758 return 1;
9759 }
9760 }
9761 unsigned OrderedLoopCount = 1;
9762 if (OrderedLoopCountExpr) {
9763 // Found 'ordered' clause - calculate collapse number.
9764 Expr::EvalResult EVResult;
9765 if (!OrderedLoopCountExpr->isValueDependent() &&
9766 OrderedLoopCountExpr->EvaluateAsInt(Result&: EVResult,
9767 Ctx: SemaRef.getASTContext())) {
9768 llvm::APSInt Result = EVResult.Val.getInt();
9769 if (Result.getLimitedValue() < NestedLoopCount) {
9770 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9771 diag::err_omp_wrong_ordered_loop_count)
9772 << OrderedLoopCountExpr->getSourceRange();
9773 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9774 diag::note_collapse_loop_count)
9775 << CollapseLoopCountExpr->getSourceRange();
9776 }
9777 OrderedLoopCount = Result.getLimitedValue();
9778 } else {
9779 Built.clear(/*Size=*/1);
9780 return 1;
9781 }
9782 }
9783 // This is helper routine for loop directives (e.g., 'for', 'simd',
9784 // 'for simd', etc.).
9785 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9786 unsigned NumLoops = std::max(a: OrderedLoopCount, b: NestedLoopCount);
9787 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9788 if (!OMPLoopBasedDirective::doForAllLoops(
9789 AStmt->IgnoreContainers(IgnoreCaptured: !isOpenMPLoopTransformationDirective(DKind)),
9790 SupportsNonPerfectlyNested, NumLoops,
9791 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9792 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9793 &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
9794 if (checkOpenMPIterationSpace(
9795 DKind, S: CurStmt, SemaRef, DSA, CurrentNestedLoopCount: Cnt, NestedLoopCount,
9796 TotalNestedLoopCount: NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9797 VarsWithImplicitDSA, ResultIterSpaces: IterSpaces, Captures))
9798 return true;
9799 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9800 IterSpaces[Cnt].CounterVar) {
9801 // Handle initialization of captured loop iterator variables.
9802 auto *DRE = cast<DeclRefExpr>(Val: IterSpaces[Cnt].CounterVar);
9803 if (isa<OMPCapturedExprDecl>(Val: DRE->getDecl())) {
9804 Captures[DRE] = DRE;
9805 }
9806 }
9807 return false;
9808 },
9809 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9810 Stmt *DependentPreInits = Transform->getPreInits();
9811 if (!DependentPreInits)
9812 return;
9813 for (Decl *C : cast<DeclStmt>(Val: DependentPreInits)->getDeclGroup()) {
9814 auto *D = cast<VarDecl>(Val: C);
9815 DeclRefExpr *Ref = buildDeclRefExpr(SemaRef, D, D->getType(),
9816 Transform->getBeginLoc());
9817 Captures[Ref] = Ref;
9818 }
9819 }))
9820 return 0;
9821
9822 Built.clear(/* size */ Size: NestedLoopCount);
9823
9824 if (SemaRef.CurContext->isDependentContext())
9825 return NestedLoopCount;
9826
9827 // An example of what is generated for the following code:
9828 //
9829 // #pragma omp simd collapse(2) ordered(2)
9830 // for (i = 0; i < NI; ++i)
9831 // for (k = 0; k < NK; ++k)
9832 // for (j = J0; j < NJ; j+=2) {
9833 // <loop body>
9834 // }
9835 //
9836 // We generate the code below.
9837 // Note: the loop body may be outlined in CodeGen.
9838 // Note: some counters may be C++ classes, operator- is used to find number of
9839 // iterations and operator+= to calculate counter value.
9840 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9841 // or i64 is currently supported).
9842 //
9843 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9844 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9845 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9846 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9847 // // similar updates for vars in clauses (e.g. 'linear')
9848 // <loop body (using local i and j)>
9849 // }
9850 // i = NI; // assign final values of counters
9851 // j = NJ;
9852 //
9853
9854 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9855 // the iteration counts of the collapsed for loops.
9856 // Precondition tests if there is at least one iteration (all conditions are
9857 // true).
9858 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9859 Expr *N0 = IterSpaces[0].NumIterations;
9860 ExprResult LastIteration32 =
9861 widenIterationCount(/*Bits=*/32,
9862 E: SemaRef
9863 .PerformImplicitConversion(
9864 From: N0->IgnoreImpCasts(), ToType: N0->getType(),
9865 Action: Sema::AA_Converting, /*AllowExplicit=*/true)
9866 .get(),
9867 SemaRef);
9868 ExprResult LastIteration64 = widenIterationCount(
9869 /*Bits=*/64,
9870 E: SemaRef
9871 .PerformImplicitConversion(From: N0->IgnoreImpCasts(), ToType: N0->getType(),
9872 Action: Sema::AA_Converting,
9873 /*AllowExplicit=*/true)
9874 .get(),
9875 SemaRef);
9876
9877 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9878 return NestedLoopCount;
9879
9880 ASTContext &C = SemaRef.Context;
9881 bool AllCountsNeedLessThan32Bits = C.getTypeSize(T: N0->getType()) < 32;
9882
9883 Scope *CurScope = DSA.getCurScope();
9884 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9885 if (PreCond.isUsable()) {
9886 PreCond =
9887 SemaRef.BuildBinOp(S: CurScope, OpLoc: PreCond.get()->getExprLoc(), Opc: BO_LAnd,
9888 LHSExpr: PreCond.get(), RHSExpr: IterSpaces[Cnt].PreCond);
9889 }
9890 Expr *N = IterSpaces[Cnt].NumIterations;
9891 SourceLocation Loc = N->getExprLoc();
9892 AllCountsNeedLessThan32Bits &= C.getTypeSize(T: N->getType()) < 32;
9893 if (LastIteration32.isUsable())
9894 LastIteration32 = SemaRef.BuildBinOp(
9895 S: CurScope, OpLoc: Loc, Opc: BO_Mul, LHSExpr: LastIteration32.get(),
9896 RHSExpr: SemaRef
9897 .PerformImplicitConversion(From: N->IgnoreImpCasts(), ToType: N->getType(),
9898 Action: Sema::AA_Converting,
9899 /*AllowExplicit=*/true)
9900 .get());
9901 if (LastIteration64.isUsable())
9902 LastIteration64 = SemaRef.BuildBinOp(
9903 S: CurScope, OpLoc: Loc, Opc: BO_Mul, LHSExpr: LastIteration64.get(),
9904 RHSExpr: SemaRef
9905 .PerformImplicitConversion(From: N->IgnoreImpCasts(), ToType: N->getType(),
9906 Action: Sema::AA_Converting,
9907 /*AllowExplicit=*/true)
9908 .get());
9909 }
9910
9911 // Choose either the 32-bit or 64-bit version.
9912 ExprResult LastIteration = LastIteration64;
9913 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9914 (LastIteration32.isUsable() &&
9915 C.getTypeSize(T: LastIteration32.get()->getType()) == 32 &&
9916 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9917 fitsInto(
9918 /*Bits=*/32,
9919 Signed: LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9920 E: LastIteration64.get(), SemaRef))))
9921 LastIteration = LastIteration32;
9922 QualType VType = LastIteration.get()->getType();
9923 QualType RealVType = VType;
9924 QualType StrideVType = VType;
9925 if (isOpenMPTaskLoopDirective(DKind)) {
9926 VType =
9927 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9928 StrideVType =
9929 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9930 }
9931
9932 if (!LastIteration.isUsable())
9933 return 0;
9934
9935 // Save the number of iterations.
9936 ExprResult NumIterations = LastIteration;
9937 {
9938 LastIteration = SemaRef.BuildBinOp(
9939 S: CurScope, OpLoc: LastIteration.get()->getExprLoc(), Opc: BO_Sub,
9940 LHSExpr: LastIteration.get(),
9941 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
9942 if (!LastIteration.isUsable())
9943 return 0;
9944 }
9945
9946 // Calculate the last iteration number beforehand instead of doing this on
9947 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9948 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(Ctx: SemaRef.Context);
9949 ExprResult CalcLastIteration;
9950 if (!IsConstant) {
9951 ExprResult SaveRef =
9952 tryBuildCapture(SemaRef, Capture: LastIteration.get(), Captures);
9953 LastIteration = SaveRef;
9954
9955 // Prepare SaveRef + 1.
9956 NumIterations = SemaRef.BuildBinOp(
9957 S: CurScope, OpLoc: SaveRef.get()->getExprLoc(), Opc: BO_Add, LHSExpr: SaveRef.get(),
9958 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
9959 if (!NumIterations.isUsable())
9960 return 0;
9961 }
9962
9963 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9964
9965 // Build variables passed into runtime, necessary for worksharing directives.
9966 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9967 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
9968 isOpenMPDistributeDirective(DKind) ||
9969 isOpenMPGenericLoopDirective(DKind) ||
9970 isOpenMPLoopTransformationDirective(DKind)) {
9971 // Lower bound variable, initialized with zero.
9972 VarDecl *LBDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.lb");
9973 LB = buildDeclRefExpr(S&: SemaRef, D: LBDecl, Ty: VType, Loc: InitLoc);
9974 SemaRef.AddInitializerToDecl(LBDecl,
9975 SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
9976 /*DirectInit*/ false);
9977
9978 // Upper bound variable, initialized with last iteration number.
9979 VarDecl *UBDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.ub");
9980 UB = buildDeclRefExpr(S&: SemaRef, D: UBDecl, Ty: VType, Loc: InitLoc);
9981 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9982 /*DirectInit*/ false);
9983
9984 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9985 // This will be used to implement clause 'lastprivate'.
9986 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(DestWidth: 32, Signed: true);
9987 VarDecl *ILDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: Int32Ty, Name: ".omp.is_last");
9988 IL = buildDeclRefExpr(S&: SemaRef, D: ILDecl, Ty: Int32Ty, Loc: InitLoc);
9989 SemaRef.AddInitializerToDecl(ILDecl,
9990 SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
9991 /*DirectInit*/ false);
9992
9993 // Stride variable returned by runtime (we initialize it to 1 by default).
9994 VarDecl *STDecl =
9995 buildVarDecl(SemaRef, Loc: InitLoc, Type: StrideVType, Name: ".omp.stride");
9996 ST = buildDeclRefExpr(S&: SemaRef, D: STDecl, Ty: StrideVType, Loc: InitLoc);
9997 SemaRef.AddInitializerToDecl(STDecl,
9998 SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 1).get(),
9999 /*DirectInit*/ false);
10000
10001 // Build expression: UB = min(UB, LastIteration)
10002 // It is necessary for CodeGen of directives with static scheduling.
10003 ExprResult IsUBGreater = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_GT,
10004 LHSExpr: UB.get(), RHSExpr: LastIteration.get());
10005 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10006 QuestionLoc: LastIteration.get()->getExprLoc(), ColonLoc: InitLoc, CondExpr: IsUBGreater.get(),
10007 LHSExpr: LastIteration.get(), RHSExpr: UB.get());
10008 EUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: UB.get(),
10009 RHSExpr: CondOp.get());
10010 EUB = SemaRef.ActOnFinishFullExpr(Expr: EUB.get(), /*DiscardedValue*/ false);
10011
10012 // If we have a combined directive that combines 'distribute', 'for' or
10013 // 'simd' we need to be able to access the bounds of the schedule of the
10014 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10015 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10016 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10017 // Lower bound variable, initialized with zero.
10018 VarDecl *CombLBDecl =
10019 buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.comb.lb");
10020 CombLB = buildDeclRefExpr(S&: SemaRef, D: CombLBDecl, Ty: VType, Loc: InitLoc);
10021 SemaRef.AddInitializerToDecl(
10022 CombLBDecl, SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
10023 /*DirectInit*/ false);
10024
10025 // Upper bound variable, initialized with last iteration number.
10026 VarDecl *CombUBDecl =
10027 buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.comb.ub");
10028 CombUB = buildDeclRefExpr(S&: SemaRef, D: CombUBDecl, Ty: VType, Loc: InitLoc);
10029 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
10030 /*DirectInit*/ false);
10031
10032 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10033 S: CurScope, OpLoc: InitLoc, Opc: BO_GT, LHSExpr: CombUB.get(), RHSExpr: LastIteration.get());
10034 ExprResult CombCondOp =
10035 SemaRef.ActOnConditionalOp(QuestionLoc: InitLoc, ColonLoc: InitLoc, CondExpr: CombIsUBGreater.get(),
10036 LHSExpr: LastIteration.get(), RHSExpr: CombUB.get());
10037 CombEUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: CombUB.get(),
10038 RHSExpr: CombCondOp.get());
10039 CombEUB =
10040 SemaRef.ActOnFinishFullExpr(Expr: CombEUB.get(), /*DiscardedValue*/ false);
10041
10042 const CapturedDecl *CD = cast<CapturedStmt>(Val: AStmt)->getCapturedDecl();
10043 // We expect to have at least 2 more parameters than the 'parallel'
10044 // directive does - the lower and upper bounds of the previous schedule.
10045 assert(CD->getNumParams() >= 4 &&
10046 "Unexpected number of parameters in loop combined directive");
10047
10048 // Set the proper type for the bounds given what we learned from the
10049 // enclosed loops.
10050 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/i: 2);
10051 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/i: 3);
10052
10053 // Previous lower and upper bounds are obtained from the region
10054 // parameters.
10055 PrevLB =
10056 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10057 PrevUB =
10058 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10059 }
10060 }
10061
10062 // Build the iteration variable and its initialization before loop.
10063 ExprResult IV;
10064 ExprResult Init, CombInit;
10065 {
10066 VarDecl *IVDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: RealVType, Name: ".omp.iv");
10067 IV = buildDeclRefExpr(S&: SemaRef, D: IVDecl, Ty: RealVType, Loc: InitLoc);
10068 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10069 isOpenMPGenericLoopDirective(DKind) ||
10070 isOpenMPTaskLoopDirective(DKind) ||
10071 isOpenMPDistributeDirective(DKind) ||
10072 isOpenMPLoopTransformationDirective(DKind))
10073 ? LB.get()
10074 : SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 0).get();
10075 Init = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: RHS);
10076 Init = SemaRef.ActOnFinishFullExpr(Expr: Init.get(), /*DiscardedValue*/ false);
10077
10078 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10079 Expr *CombRHS =
10080 (isOpenMPWorksharingDirective(DKind) ||
10081 isOpenMPGenericLoopDirective(DKind) ||
10082 isOpenMPTaskLoopDirective(DKind) ||
10083 isOpenMPDistributeDirective(DKind))
10084 ? CombLB.get()
10085 : SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 0).get();
10086 CombInit =
10087 SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: CombRHS);
10088 CombInit =
10089 SemaRef.ActOnFinishFullExpr(Expr: CombInit.get(), /*DiscardedValue*/ false);
10090 }
10091 }
10092
10093 bool UseStrictCompare =
10094 RealVType->hasUnsignedIntegerRepresentation() &&
10095 llvm::all_of(Range&: IterSpaces, P: [](const LoopIterationSpace &LIS) {
10096 return LIS.IsStrictCompare;
10097 });
10098 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10099 // unsigned IV)) for worksharing loops.
10100 SourceLocation CondLoc = AStmt->getBeginLoc();
10101 Expr *BoundUB = UB.get();
10102 if (UseStrictCompare) {
10103 BoundUB =
10104 SemaRef
10105 .BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundUB,
10106 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10107 .get();
10108 BoundUB =
10109 SemaRef.ActOnFinishFullExpr(Expr: BoundUB, /*DiscardedValue*/ false).get();
10110 }
10111 ExprResult Cond =
10112 (isOpenMPWorksharingDirective(DKind) ||
10113 isOpenMPGenericLoopDirective(DKind) ||
10114 isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
10115 isOpenMPLoopTransformationDirective(DKind))
10116 ? SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc,
10117 Opc: UseStrictCompare ? BO_LT : BO_LE, LHSExpr: IV.get(),
10118 RHSExpr: BoundUB)
10119 : SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LT, LHSExpr: IV.get(),
10120 RHSExpr: NumIterations.get());
10121 ExprResult CombDistCond;
10122 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10123 CombDistCond = SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LT, LHSExpr: IV.get(),
10124 RHSExpr: NumIterations.get());
10125 }
10126
10127 ExprResult CombCond;
10128 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10129 Expr *BoundCombUB = CombUB.get();
10130 if (UseStrictCompare) {
10131 BoundCombUB =
10132 SemaRef
10133 .BuildBinOp(
10134 S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundCombUB,
10135 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10136 .get();
10137 BoundCombUB =
10138 SemaRef.ActOnFinishFullExpr(Expr: BoundCombUB, /*DiscardedValue*/ false)
10139 .get();
10140 }
10141 CombCond =
10142 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE,
10143 LHSExpr: IV.get(), RHSExpr: BoundCombUB);
10144 }
10145 // Loop increment (IV = IV + 1)
10146 SourceLocation IncLoc = AStmt->getBeginLoc();
10147 ExprResult Inc =
10148 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: IV.get(),
10149 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: IncLoc, Val: 1).get());
10150 if (!Inc.isUsable())
10151 return 0;
10152 Inc = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: Inc.get());
10153 Inc = SemaRef.ActOnFinishFullExpr(Expr: Inc.get(), /*DiscardedValue*/ false);
10154 if (!Inc.isUsable())
10155 return 0;
10156
10157 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10158 // Used for directives with static scheduling.
10159 // In combined construct, add combined version that use CombLB and CombUB
10160 // base variables for the update
10161 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10162 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
10163 isOpenMPGenericLoopDirective(DKind) ||
10164 isOpenMPDistributeDirective(DKind) ||
10165 isOpenMPLoopTransformationDirective(DKind)) {
10166 // LB + ST
10167 NextLB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: LB.get(), RHSExpr: ST.get());
10168 if (!NextLB.isUsable())
10169 return 0;
10170 // LB = LB + ST
10171 NextLB =
10172 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: LB.get(), RHSExpr: NextLB.get());
10173 NextLB =
10174 SemaRef.ActOnFinishFullExpr(Expr: NextLB.get(), /*DiscardedValue*/ false);
10175 if (!NextLB.isUsable())
10176 return 0;
10177 // UB + ST
10178 NextUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: UB.get(), RHSExpr: ST.get());
10179 if (!NextUB.isUsable())
10180 return 0;
10181 // UB = UB + ST
10182 NextUB =
10183 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: UB.get(), RHSExpr: NextUB.get());
10184 NextUB =
10185 SemaRef.ActOnFinishFullExpr(Expr: NextUB.get(), /*DiscardedValue*/ false);
10186 if (!NextUB.isUsable())
10187 return 0;
10188 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10189 CombNextLB =
10190 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: CombLB.get(), RHSExpr: ST.get());
10191 if (!NextLB.isUsable())
10192 return 0;
10193 // LB = LB + ST
10194 CombNextLB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: CombLB.get(),
10195 RHSExpr: CombNextLB.get());
10196 CombNextLB = SemaRef.ActOnFinishFullExpr(Expr: CombNextLB.get(),
10197 /*DiscardedValue*/ false);
10198 if (!CombNextLB.isUsable())
10199 return 0;
10200 // UB + ST
10201 CombNextUB =
10202 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: CombUB.get(), RHSExpr: ST.get());
10203 if (!CombNextUB.isUsable())
10204 return 0;
10205 // UB = UB + ST
10206 CombNextUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: CombUB.get(),
10207 RHSExpr: CombNextUB.get());
10208 CombNextUB = SemaRef.ActOnFinishFullExpr(Expr: CombNextUB.get(),
10209 /*DiscardedValue*/ false);
10210 if (!CombNextUB.isUsable())
10211 return 0;
10212 }
10213 }
10214
10215 // Create increment expression for distribute loop when combined in a same
10216 // directive with for as IV = IV + ST; ensure upper bound expression based
10217 // on PrevUB instead of NumIterations - used to implement 'for' when found
10218 // in combination with 'distribute', like in 'distribute parallel for'
10219 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10220 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10221 if (isOpenMPLoopBoundSharingDirective(Kind: DKind)) {
10222 DistCond = SemaRef.BuildBinOp(
10223 S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE, LHSExpr: IV.get(), RHSExpr: BoundUB);
10224 assert(DistCond.isUsable() && "distribute cond expr was not built");
10225
10226 DistInc =
10227 SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Add, LHSExpr: IV.get(), RHSExpr: ST.get());
10228 assert(DistInc.isUsable() && "distribute inc expr was not built");
10229 DistInc = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Assign, LHSExpr: IV.get(),
10230 RHSExpr: DistInc.get());
10231 DistInc =
10232 SemaRef.ActOnFinishFullExpr(Expr: DistInc.get(), /*DiscardedValue*/ false);
10233 assert(DistInc.isUsable() && "distribute inc expr was not built");
10234
10235 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10236 // construct
10237 ExprResult NewPrevUB = PrevUB;
10238 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10239 if (!SemaRef.Context.hasSameType(T1: UB.get()->getType(),
10240 T2: PrevUB.get()->getType())) {
10241 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10242 LParenLoc: DistEUBLoc,
10243 Ty: SemaRef.Context.getTrivialTypeSourceInfo(T: UB.get()->getType()),
10244 RParenLoc: DistEUBLoc, Op: NewPrevUB.get());
10245 if (!NewPrevUB.isUsable())
10246 return 0;
10247 }
10248 ExprResult IsUBGreater = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistEUBLoc, Opc: BO_GT,
10249 LHSExpr: UB.get(), RHSExpr: NewPrevUB.get());
10250 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10251 QuestionLoc: DistEUBLoc, ColonLoc: DistEUBLoc, CondExpr: IsUBGreater.get(), LHSExpr: NewPrevUB.get(), RHSExpr: UB.get());
10252 PrevEUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Assign, LHSExpr: UB.get(),
10253 RHSExpr: CondOp.get());
10254 PrevEUB =
10255 SemaRef.ActOnFinishFullExpr(Expr: PrevEUB.get(), /*DiscardedValue*/ false);
10256
10257 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10258 // parallel for is in combination with a distribute directive with
10259 // schedule(static, 1)
10260 Expr *BoundPrevUB = PrevUB.get();
10261 if (UseStrictCompare) {
10262 BoundPrevUB =
10263 SemaRef
10264 .BuildBinOp(
10265 S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundPrevUB,
10266 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10267 .get();
10268 BoundPrevUB =
10269 SemaRef.ActOnFinishFullExpr(Expr: BoundPrevUB, /*DiscardedValue*/ false)
10270 .get();
10271 }
10272 ParForInDistCond =
10273 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE,
10274 LHSExpr: IV.get(), RHSExpr: BoundPrevUB);
10275 }
10276
10277 // Build updates and final values of the loop counters.
10278 bool HasErrors = false;
10279 Built.Counters.resize(N: NestedLoopCount);
10280 Built.Inits.resize(N: NestedLoopCount);
10281 Built.Updates.resize(N: NestedLoopCount);
10282 Built.Finals.resize(N: NestedLoopCount);
10283 Built.DependentCounters.resize(N: NestedLoopCount);
10284 Built.DependentInits.resize(N: NestedLoopCount);
10285 Built.FinalsConditions.resize(N: NestedLoopCount);
10286 {
10287 // We implement the following algorithm for obtaining the
10288 // original loop iteration variable values based on the
10289 // value of the collapsed loop iteration variable IV.
10290 //
10291 // Let n+1 be the number of collapsed loops in the nest.
10292 // Iteration variables (I0, I1, .... In)
10293 // Iteration counts (N0, N1, ... Nn)
10294 //
10295 // Acc = IV;
10296 //
10297 // To compute Ik for loop k, 0 <= k <= n, generate:
10298 // Prod = N(k+1) * N(k+2) * ... * Nn;
10299 // Ik = Acc / Prod;
10300 // Acc -= Ik * Prod;
10301 //
10302 ExprResult Acc = IV;
10303 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10304 LoopIterationSpace &IS = IterSpaces[Cnt];
10305 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10306 ExprResult Iter;
10307
10308 // Compute prod
10309 ExprResult Prod = SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get();
10310 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10311 Prod = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Mul, LHSExpr: Prod.get(),
10312 RHSExpr: IterSpaces[K].NumIterations);
10313
10314 // Iter = Acc / Prod
10315 // If there is at least one more inner loop to avoid
10316 // multiplication by 1.
10317 if (Cnt + 1 < NestedLoopCount)
10318 Iter =
10319 SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Div, LHSExpr: Acc.get(), RHSExpr: Prod.get());
10320 else
10321 Iter = Acc;
10322 if (!Iter.isUsable()) {
10323 HasErrors = true;
10324 break;
10325 }
10326
10327 // Update Acc:
10328 // Acc -= Iter * Prod
10329 // Check if there is at least one more inner loop to avoid
10330 // multiplication by 1.
10331 if (Cnt + 1 < NestedLoopCount)
10332 Prod = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Mul, LHSExpr: Iter.get(),
10333 RHSExpr: Prod.get());
10334 else
10335 Prod = Iter;
10336 Acc = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Sub, LHSExpr: Acc.get(), RHSExpr: Prod.get());
10337
10338 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10339 auto *VD = cast<VarDecl>(Val: cast<DeclRefExpr>(Val: IS.CounterVar)->getDecl());
10340 DeclRefExpr *CounterVar = buildDeclRefExpr(
10341 S&: SemaRef, D: VD, Ty: IS.CounterVar->getType(), Loc: IS.CounterVar->getExprLoc(),
10342 /*RefersToCapture=*/true);
10343 ExprResult Init =
10344 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10345 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10346 if (!Init.isUsable()) {
10347 HasErrors = true;
10348 break;
10349 }
10350 ExprResult Update = buildCounterUpdate(
10351 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10352 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10353 if (!Update.isUsable()) {
10354 HasErrors = true;
10355 break;
10356 }
10357
10358 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10359 ExprResult Final =
10360 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10361 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10362 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10363 if (!Final.isUsable()) {
10364 HasErrors = true;
10365 break;
10366 }
10367
10368 if (!Update.isUsable() || !Final.isUsable()) {
10369 HasErrors = true;
10370 break;
10371 }
10372 // Save results
10373 Built.Counters[Cnt] = IS.CounterVar;
10374 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10375 Built.Inits[Cnt] = Init.get();
10376 Built.Updates[Cnt] = Update.get();
10377 Built.Finals[Cnt] = Final.get();
10378 Built.DependentCounters[Cnt] = nullptr;
10379 Built.DependentInits[Cnt] = nullptr;
10380 Built.FinalsConditions[Cnt] = nullptr;
10381 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10382 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10383 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10384 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10385 }
10386 }
10387 }
10388
10389 if (HasErrors)
10390 return 0;
10391
10392 // Save results
10393 Built.IterationVarRef = IV.get();
10394 Built.LastIteration = LastIteration.get();
10395 Built.NumIterations = NumIterations.get();
10396 Built.CalcLastIteration = SemaRef
10397 .ActOnFinishFullExpr(Expr: CalcLastIteration.get(),
10398 /*DiscardedValue=*/false)
10399 .get();
10400 Built.PreCond = PreCond.get();
10401 Built.PreInits = buildPreInits(Context&: C, Captures);
10402 Built.Cond = Cond.get();
10403 Built.Init = Init.get();
10404 Built.Inc = Inc.get();
10405 Built.LB = LB.get();
10406 Built.UB = UB.get();
10407 Built.IL = IL.get();
10408 Built.ST = ST.get();
10409 Built.EUB = EUB.get();
10410 Built.NLB = NextLB.get();
10411 Built.NUB = NextUB.get();
10412 Built.PrevLB = PrevLB.get();
10413 Built.PrevUB = PrevUB.get();
10414 Built.DistInc = DistInc.get();
10415 Built.PrevEUB = PrevEUB.get();
10416 Built.DistCombinedFields.LB = CombLB.get();
10417 Built.DistCombinedFields.UB = CombUB.get();
10418 Built.DistCombinedFields.EUB = CombEUB.get();
10419 Built.DistCombinedFields.Init = CombInit.get();
10420 Built.DistCombinedFields.Cond = CombCond.get();
10421 Built.DistCombinedFields.NLB = CombNextLB.get();
10422 Built.DistCombinedFields.NUB = CombNextUB.get();
10423 Built.DistCombinedFields.DistCond = CombDistCond.get();
10424 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10425
10426 return NestedLoopCount;
10427}
10428
10429static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
10430 auto CollapseClauses =
10431 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10432 if (CollapseClauses.begin() != CollapseClauses.end())
10433 return (*CollapseClauses.begin())->getNumForLoops();
10434 return nullptr;
10435}
10436
10437static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
10438 auto OrderedClauses =
10439 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10440 if (OrderedClauses.begin() != OrderedClauses.end())
10441 return (*OrderedClauses.begin())->getNumForLoops();
10442 return nullptr;
10443}
10444
10445static bool checkSimdlenSafelenSpecified(Sema &S,
10446 const ArrayRef<OMPClause *> Clauses) {
10447 const OMPSafelenClause *Safelen = nullptr;
10448 const OMPSimdlenClause *Simdlen = nullptr;
10449
10450 for (const OMPClause *Clause : Clauses) {
10451 if (Clause->getClauseKind() == OMPC_safelen)
10452 Safelen = cast<OMPSafelenClause>(Val: Clause);
10453 else if (Clause->getClauseKind() == OMPC_simdlen)
10454 Simdlen = cast<OMPSimdlenClause>(Val: Clause);
10455 if (Safelen && Simdlen)
10456 break;
10457 }
10458
10459 if (Simdlen && Safelen) {
10460 const Expr *SimdlenLength = Simdlen->getSimdlen();
10461 const Expr *SafelenLength = Safelen->getSafelen();
10462 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10463 SimdlenLength->isInstantiationDependent() ||
10464 SimdlenLength->containsUnexpandedParameterPack())
10465 return false;
10466 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10467 SafelenLength->isInstantiationDependent() ||
10468 SafelenLength->containsUnexpandedParameterPack())
10469 return false;
10470 Expr::EvalResult SimdlenResult, SafelenResult;
10471 SimdlenLength->EvaluateAsInt(Result&: SimdlenResult, Ctx: S.Context);
10472 SafelenLength->EvaluateAsInt(Result&: SafelenResult, Ctx: S.Context);
10473 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10474 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10475 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10476 // If both simdlen and safelen clauses are specified, the value of the
10477 // simdlen parameter must be less than or equal to the value of the safelen
10478 // parameter.
10479 if (SimdlenRes > SafelenRes) {
10480 S.Diag(SimdlenLength->getExprLoc(),
10481 diag::err_omp_wrong_simdlen_safelen_values)
10482 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10483 return true;
10484 }
10485 }
10486 return false;
10487}
10488
10489static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
10490 OpenMPDirectiveKind K,
10491 DSAStackTy *Stack);
10492
10493bool Sema::checkLastPrivateForMappedDirectives(ArrayRef<OMPClause *> Clauses) {
10494
10495 // Check for syntax of lastprivate
10496 // Param of the lastprivate have different meanings in the mapped directives
10497 // e.g. "omp loop" Only loop iteration vars are allowed in lastprivate clause
10498 // "omp for" lastprivate vars must be shared
10499 if (getLangOpts().OpenMP >= 50 &&
10500 DSAStack->getMappedDirective() == OMPD_loop &&
10501 checkGenericLoopLastprivate(*this, Clauses, OMPD_loop, DSAStack)) {
10502 return false;
10503 }
10504 return true;
10505}
10506
10507StmtResult
10508Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
10509 SourceLocation StartLoc, SourceLocation EndLoc,
10510 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10511 if (!AStmt)
10512 return StmtError();
10513
10514 if (!checkLastPrivateForMappedDirectives(Clauses))
10515 return StmtError();
10516
10517 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10518 OMPLoopBasedDirective::HelperExprs B;
10519 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10520 // define the nested loops number.
10521 unsigned NestedLoopCount = checkOpenMPLoop(
10522 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10523 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10524 if (NestedLoopCount == 0)
10525 return StmtError();
10526
10527 assert((CurContext->isDependentContext() || B.builtAll()) &&
10528 "omp simd loop exprs were not built");
10529
10530 if (!CurContext->isDependentContext()) {
10531 // Finalize the clauses that need pre-built expressions for CodeGen.
10532 for (OMPClause *C : Clauses) {
10533 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
10534 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
10535 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
10536 DSAStack))
10537 return StmtError();
10538 }
10539 }
10540
10541 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
10542 return StmtError();
10543
10544 setFunctionHasBranchProtectedScope();
10545 auto *SimdDirective = OMPSimdDirective::Create(
10546 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
10547 DSAStack->getMappedDirective());
10548 return SimdDirective;
10549}
10550
10551StmtResult
10552Sema::ActOnOpenMPForDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
10553 SourceLocation StartLoc, SourceLocation EndLoc,
10554 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10555 if (!AStmt)
10556 return StmtError();
10557
10558 if (!checkLastPrivateForMappedDirectives(Clauses))
10559 return StmtError();
10560
10561 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10562 OMPLoopBasedDirective::HelperExprs B;
10563 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10564 // define the nested loops number.
10565 unsigned NestedLoopCount = checkOpenMPLoop(
10566 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10567 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10568 if (NestedLoopCount == 0)
10569 return StmtError();
10570
10571 assert((CurContext->isDependentContext() || B.builtAll()) &&
10572 "omp for loop exprs were not built");
10573
10574 if (!CurContext->isDependentContext()) {
10575 // Finalize the clauses that need pre-built expressions for CodeGen.
10576 for (OMPClause *C : Clauses) {
10577 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
10578 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
10579 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
10580 DSAStack))
10581 return StmtError();
10582 }
10583 }
10584
10585 auto *ForDirective = OMPForDirective::Create(
10586 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
10587 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion(),
10588 DSAStack->getMappedDirective());
10589 return ForDirective;
10590}
10591
10592StmtResult Sema::ActOnOpenMPForSimdDirective(
10593 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10594 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10595 if (!AStmt)
10596 return StmtError();
10597
10598 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10599 OMPLoopBasedDirective::HelperExprs B;
10600 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10601 // define the nested loops number.
10602 unsigned NestedLoopCount =
10603 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10604 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
10605 VarsWithImplicitDSA, B);
10606 if (NestedLoopCount == 0)
10607 return StmtError();
10608
10609 assert((CurContext->isDependentContext() || B.builtAll()) &&
10610 "omp for simd loop exprs were not built");
10611
10612 if (!CurContext->isDependentContext()) {
10613 // Finalize the clauses that need pre-built expressions for CodeGen.
10614 for (OMPClause *C : Clauses) {
10615 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
10616 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
10617 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
10618 DSAStack))
10619 return StmtError();
10620 }
10621 }
10622
10623 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
10624 return StmtError();
10625
10626 setFunctionHasBranchProtectedScope();
10627 return OMPForSimdDirective::Create(C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount,
10628 Clauses, AssociatedStmt: AStmt, Exprs: B);
10629}
10630
10631StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
10632 Stmt *AStmt,
10633 SourceLocation StartLoc,
10634 SourceLocation EndLoc) {
10635 if (!AStmt)
10636 return StmtError();
10637
10638 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10639 auto BaseStmt = AStmt;
10640 while (auto *CS = dyn_cast_or_null<CapturedStmt>(Val: BaseStmt))
10641 BaseStmt = CS->getCapturedStmt();
10642 if (auto *C = dyn_cast_or_null<CompoundStmt>(Val: BaseStmt)) {
10643 auto S = C->children();
10644 if (S.begin() == S.end())
10645 return StmtError();
10646 // All associated statements must be '#pragma omp section' except for
10647 // the first one.
10648 for (Stmt *SectionStmt : llvm::drop_begin(RangeOrContainer&: S)) {
10649 if (!SectionStmt || !isa<OMPSectionDirective>(Val: SectionStmt)) {
10650 if (SectionStmt)
10651 Diag(SectionStmt->getBeginLoc(),
10652 diag::err_omp_sections_substmt_not_section);
10653 return StmtError();
10654 }
10655 cast<OMPSectionDirective>(Val: SectionStmt)
10656 ->setHasCancel(DSAStack->isCancelRegion());
10657 }
10658 } else {
10659 Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt);
10660 return StmtError();
10661 }
10662
10663 setFunctionHasBranchProtectedScope();
10664
10665 return OMPSectionsDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
10666 DSAStack->getTaskgroupReductionRef(),
10667 DSAStack->isCancelRegion());
10668}
10669
10670StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt,
10671 SourceLocation StartLoc,
10672 SourceLocation EndLoc) {
10673 if (!AStmt)
10674 return StmtError();
10675
10676 setFunctionHasBranchProtectedScope();
10677 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10678
10679 return OMPSectionDirective::Create(C: Context, StartLoc, EndLoc, AssociatedStmt: AStmt,
10680 DSAStack->isCancelRegion());
10681}
10682
10683static Expr *getDirectCallExpr(Expr *E) {
10684 E = E->IgnoreParenCasts()->IgnoreImplicit();
10685 if (auto *CE = dyn_cast<CallExpr>(Val: E))
10686 if (CE->getDirectCallee())
10687 return E;
10688 return nullptr;
10689}
10690
10691StmtResult Sema::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
10692 Stmt *AStmt,
10693 SourceLocation StartLoc,
10694 SourceLocation EndLoc) {
10695 if (!AStmt)
10696 return StmtError();
10697
10698 Stmt *S = cast<CapturedStmt>(Val: AStmt)->getCapturedStmt();
10699
10700 // 5.1 OpenMP
10701 // expression-stmt : an expression statement with one of the following forms:
10702 // expression = target-call ( [expression-list] );
10703 // target-call ( [expression-list] );
10704
10705 SourceLocation TargetCallLoc;
10706
10707 if (!CurContext->isDependentContext()) {
10708 Expr *TargetCall = nullptr;
10709
10710 auto *E = dyn_cast<Expr>(Val: S);
10711 if (!E) {
10712 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10713 return StmtError();
10714 }
10715
10716 E = E->IgnoreParenCasts()->IgnoreImplicit();
10717
10718 if (auto *BO = dyn_cast<BinaryOperator>(Val: E)) {
10719 if (BO->getOpcode() == BO_Assign)
10720 TargetCall = getDirectCallExpr(E: BO->getRHS());
10721 } else {
10722 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(Val: E))
10723 if (COCE->getOperator() == OO_Equal)
10724 TargetCall = getDirectCallExpr(COCE->getArg(1));
10725 if (!TargetCall)
10726 TargetCall = getDirectCallExpr(E);
10727 }
10728 if (!TargetCall) {
10729 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10730 return StmtError();
10731 }
10732 TargetCallLoc = TargetCall->getExprLoc();
10733 }
10734
10735 setFunctionHasBranchProtectedScope();
10736
10737 return OMPDispatchDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
10738 TargetCallLoc);
10739}
10740
10741static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
10742 OpenMPDirectiveKind K,
10743 DSAStackTy *Stack) {
10744 bool ErrorFound = false;
10745 for (OMPClause *C : Clauses) {
10746 if (auto *LPC = dyn_cast<OMPLastprivateClause>(Val: C)) {
10747 for (Expr *RefExpr : LPC->varlists()) {
10748 SourceLocation ELoc;
10749 SourceRange ERange;
10750 Expr *SimpleRefExpr = RefExpr;
10751 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange);
10752 if (ValueDecl *D = Res.first) {
10753 auto &&Info = Stack->isLoopControlVariable(D);
10754 if (!Info.first) {
10755 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10756 << getOpenMPDirectiveName(K);
10757 ErrorFound = true;
10758 }
10759 }
10760 }
10761 }
10762 }
10763 return ErrorFound;
10764}
10765
10766StmtResult Sema::ActOnOpenMPGenericLoopDirective(
10767 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10768 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10769 if (!AStmt)
10770 return StmtError();
10771
10772 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10773 // A list item may not appear in a lastprivate clause unless it is the
10774 // loop iteration variable of a loop that is associated with the construct.
10775 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_loop, DSAStack))
10776 return StmtError();
10777
10778 auto *CS = cast<CapturedStmt>(Val: AStmt);
10779 // 1.2.2 OpenMP Language Terminology
10780 // Structured block - An executable statement with a single entry at the
10781 // top and a single exit at the bottom.
10782 // The point of exit cannot be a branch out of the structured block.
10783 // longjmp() and throw() must not violate the entry/exit criteria.
10784 CS->getCapturedDecl()->setNothrow();
10785
10786 OMPLoopDirective::HelperExprs B;
10787 // In presence of clause 'collapse', it will define the nested loops number.
10788 unsigned NestedLoopCount = checkOpenMPLoop(
10789 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10790 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10791 if (NestedLoopCount == 0)
10792 return StmtError();
10793
10794 assert((CurContext->isDependentContext() || B.builtAll()) &&
10795 "omp loop exprs were not built");
10796
10797 setFunctionHasBranchProtectedScope();
10798 return OMPGenericLoopDirective::Create(C: Context, StartLoc, EndLoc,
10799 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10800}
10801
10802StmtResult Sema::ActOnOpenMPTeamsGenericLoopDirective(
10803 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10804 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10805 if (!AStmt)
10806 return StmtError();
10807
10808 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10809 // A list item may not appear in a lastprivate clause unless it is the
10810 // loop iteration variable of a loop that is associated with the construct.
10811 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_teams_loop, DSAStack))
10812 return StmtError();
10813
10814 auto *CS = cast<CapturedStmt>(Val: AStmt);
10815 // 1.2.2 OpenMP Language Terminology
10816 // Structured block - An executable statement with a single entry at the
10817 // top and a single exit at the bottom.
10818 // The point of exit cannot be a branch out of the structured block.
10819 // longjmp() and throw() must not violate the entry/exit criteria.
10820 CS->getCapturedDecl()->setNothrow();
10821 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_loop);
10822 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10823 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
10824 // 1.2.2 OpenMP Language Terminology
10825 // Structured block - An executable statement with a single entry at the
10826 // top and a single exit at the bottom.
10827 // The point of exit cannot be a branch out of the structured block.
10828 // longjmp() and throw() must not violate the entry/exit criteria.
10829 CS->getCapturedDecl()->setNothrow();
10830 }
10831
10832 OMPLoopDirective::HelperExprs B;
10833 // In presence of clause 'collapse', it will define the nested loops number.
10834 unsigned NestedLoopCount =
10835 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10836 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10837 VarsWithImplicitDSA, B);
10838 if (NestedLoopCount == 0)
10839 return StmtError();
10840
10841 assert((CurContext->isDependentContext() || B.builtAll()) &&
10842 "omp loop exprs were not built");
10843
10844 setFunctionHasBranchProtectedScope();
10845 DSAStack->setParentTeamsRegionLoc(StartLoc);
10846
10847 return OMPTeamsGenericLoopDirective::Create(
10848 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10849}
10850
10851StmtResult Sema::ActOnOpenMPTargetTeamsGenericLoopDirective(
10852 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10853 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10854 if (!AStmt)
10855 return StmtError();
10856
10857 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10858 // A list item may not appear in a lastprivate clause unless it is the
10859 // loop iteration variable of a loop that is associated with the construct.
10860 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_teams_loop,
10861 DSAStack))
10862 return StmtError();
10863
10864 auto *CS = cast<CapturedStmt>(Val: AStmt);
10865 // 1.2.2 OpenMP Language Terminology
10866 // Structured block - An executable statement with a single entry at the
10867 // top and a single exit at the bottom.
10868 // The point of exit cannot be a branch out of the structured block.
10869 // longjmp() and throw() must not violate the entry/exit criteria.
10870 CS->getCapturedDecl()->setNothrow();
10871 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams_loop);
10872 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10873 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
10874 // 1.2.2 OpenMP Language Terminology
10875 // Structured block - An executable statement with a single entry at the
10876 // top and a single exit at the bottom.
10877 // The point of exit cannot be a branch out of the structured block.
10878 // longjmp() and throw() must not violate the entry/exit criteria.
10879 CS->getCapturedDecl()->setNothrow();
10880 }
10881
10882 OMPLoopDirective::HelperExprs B;
10883 // In presence of clause 'collapse', it will define the nested loops number.
10884 unsigned NestedLoopCount =
10885 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10886 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10887 VarsWithImplicitDSA, B);
10888 if (NestedLoopCount == 0)
10889 return StmtError();
10890
10891 assert((CurContext->isDependentContext() || B.builtAll()) &&
10892 "omp loop exprs were not built");
10893
10894 setFunctionHasBranchProtectedScope();
10895
10896 return OMPTargetTeamsGenericLoopDirective::Create(
10897 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10898}
10899
10900StmtResult Sema::ActOnOpenMPParallelGenericLoopDirective(
10901 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10902 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10903 if (!AStmt)
10904 return StmtError();
10905
10906 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10907 // A list item may not appear in a lastprivate clause unless it is the
10908 // loop iteration variable of a loop that is associated with the construct.
10909 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_parallel_loop, DSAStack))
10910 return StmtError();
10911
10912 auto *CS = cast<CapturedStmt>(Val: AStmt);
10913 // 1.2.2 OpenMP Language Terminology
10914 // Structured block - An executable statement with a single entry at the
10915 // top and a single exit at the bottom.
10916 // The point of exit cannot be a branch out of the structured block.
10917 // longjmp() and throw() must not violate the entry/exit criteria.
10918 CS->getCapturedDecl()->setNothrow();
10919 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_parallel_loop);
10920 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10921 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
10922 // 1.2.2 OpenMP Language Terminology
10923 // Structured block - An executable statement with a single entry at the
10924 // top and a single exit at the bottom.
10925 // The point of exit cannot be a branch out of the structured block.
10926 // longjmp() and throw() must not violate the entry/exit criteria.
10927 CS->getCapturedDecl()->setNothrow();
10928 }
10929
10930 OMPLoopDirective::HelperExprs B;
10931 // In presence of clause 'collapse', it will define the nested loops number.
10932 unsigned NestedLoopCount =
10933 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10934 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10935 VarsWithImplicitDSA, B);
10936 if (NestedLoopCount == 0)
10937 return StmtError();
10938
10939 assert((CurContext->isDependentContext() || B.builtAll()) &&
10940 "omp loop exprs were not built");
10941
10942 setFunctionHasBranchProtectedScope();
10943
10944 return OMPParallelGenericLoopDirective::Create(
10945 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10946}
10947
10948StmtResult Sema::ActOnOpenMPTargetParallelGenericLoopDirective(
10949 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10950 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10951 if (!AStmt)
10952 return StmtError();
10953
10954 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10955 // A list item may not appear in a lastprivate clause unless it is the
10956 // loop iteration variable of a loop that is associated with the construct.
10957 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_parallel_loop,
10958 DSAStack))
10959 return StmtError();
10960
10961 auto *CS = cast<CapturedStmt>(Val: AStmt);
10962 // 1.2.2 OpenMP Language Terminology
10963 // Structured block - An executable statement with a single entry at the
10964 // top and a single exit at the bottom.
10965 // The point of exit cannot be a branch out of the structured block.
10966 // longjmp() and throw() must not violate the entry/exit criteria.
10967 CS->getCapturedDecl()->setNothrow();
10968 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_loop);
10969 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10970 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
10971 // 1.2.2 OpenMP Language Terminology
10972 // Structured block - An executable statement with a single entry at the
10973 // top and a single exit at the bottom.
10974 // The point of exit cannot be a branch out of the structured block.
10975 // longjmp() and throw() must not violate the entry/exit criteria.
10976 CS->getCapturedDecl()->setNothrow();
10977 }
10978
10979 OMPLoopDirective::HelperExprs B;
10980 // In presence of clause 'collapse', it will define the nested loops number.
10981 unsigned NestedLoopCount =
10982 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10983 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10984 VarsWithImplicitDSA, B);
10985 if (NestedLoopCount == 0)
10986 return StmtError();
10987
10988 assert((CurContext->isDependentContext() || B.builtAll()) &&
10989 "omp loop exprs were not built");
10990
10991 setFunctionHasBranchProtectedScope();
10992
10993 return OMPTargetParallelGenericLoopDirective::Create(
10994 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10995}
10996
10997StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
10998 Stmt *AStmt,
10999 SourceLocation StartLoc,
11000 SourceLocation EndLoc) {
11001 if (!AStmt)
11002 return StmtError();
11003
11004 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11005
11006 setFunctionHasBranchProtectedScope();
11007
11008 // OpenMP [2.7.3, single Construct, Restrictions]
11009 // The copyprivate clause must not be used with the nowait clause.
11010 const OMPClause *Nowait = nullptr;
11011 const OMPClause *Copyprivate = nullptr;
11012 for (const OMPClause *Clause : Clauses) {
11013 if (Clause->getClauseKind() == OMPC_nowait)
11014 Nowait = Clause;
11015 else if (Clause->getClauseKind() == OMPC_copyprivate)
11016 Copyprivate = Clause;
11017 if (Copyprivate && Nowait) {
11018 Diag(Copyprivate->getBeginLoc(),
11019 diag::err_omp_single_copyprivate_with_nowait);
11020 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
11021 return StmtError();
11022 }
11023 }
11024
11025 return OMPSingleDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt);
11026}
11027
11028StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
11029 SourceLocation StartLoc,
11030 SourceLocation EndLoc) {
11031 if (!AStmt)
11032 return StmtError();
11033
11034 setFunctionHasBranchProtectedScope();
11035
11036 return OMPMasterDirective::Create(C: Context, StartLoc, EndLoc, AssociatedStmt: AStmt);
11037}
11038
11039StmtResult Sema::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
11040 Stmt *AStmt,
11041 SourceLocation StartLoc,
11042 SourceLocation EndLoc) {
11043 if (!AStmt)
11044 return StmtError();
11045
11046 setFunctionHasBranchProtectedScope();
11047
11048 return OMPMaskedDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt);
11049}
11050
11051StmtResult Sema::ActOnOpenMPCriticalDirective(
11052 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11053 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11054 if (!AStmt)
11055 return StmtError();
11056
11057 bool ErrorFound = false;
11058 llvm::APSInt Hint;
11059 SourceLocation HintLoc;
11060 bool DependentHint = false;
11061 for (const OMPClause *C : Clauses) {
11062 if (C->getClauseKind() == OMPC_hint) {
11063 if (!DirName.getName()) {
11064 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11065 ErrorFound = true;
11066 }
11067 Expr *E = cast<OMPHintClause>(Val: C)->getHint();
11068 if (E->isTypeDependent() || E->isValueDependent() ||
11069 E->isInstantiationDependent()) {
11070 DependentHint = true;
11071 } else {
11072 Hint = E->EvaluateKnownConstInt(Ctx: Context);
11073 HintLoc = C->getBeginLoc();
11074 }
11075 }
11076 }
11077 if (ErrorFound)
11078 return StmtError();
11079 const auto Pair = DSAStack->getCriticalWithHint(Name: DirName);
11080 if (Pair.first && DirName.getName() && !DependentHint) {
11081 if (llvm::APSInt::compareValues(I1: Hint, I2: Pair.second) != 0) {
11082 Diag(StartLoc, diag::err_omp_critical_with_hint);
11083 if (HintLoc.isValid())
11084 Diag(HintLoc, diag::note_omp_critical_hint_here)
11085 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
11086 else
11087 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11088 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11089 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
11090 << 1
11091 << toString(C->getHint()->EvaluateKnownConstInt(Context),
11092 /*Radix=*/10, /*Signed=*/false);
11093 } else {
11094 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11095 }
11096 }
11097 }
11098
11099 setFunctionHasBranchProtectedScope();
11100
11101 auto *Dir = OMPCriticalDirective::Create(C: Context, Name: DirName, StartLoc, EndLoc,
11102 Clauses, AssociatedStmt: AStmt);
11103 if (!Pair.first && DirName.getName() && !DependentHint)
11104 DSAStack->addCriticalWithHint(D: Dir, Hint);
11105 return Dir;
11106}
11107
11108StmtResult Sema::ActOnOpenMPParallelForDirective(
11109 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11110 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11111 if (!AStmt)
11112 return StmtError();
11113
11114 auto *CS = cast<CapturedStmt>(Val: AStmt);
11115 // 1.2.2 OpenMP Language Terminology
11116 // Structured block - An executable statement with a single entry at the
11117 // top and a single exit at the bottom.
11118 // The point of exit cannot be a branch out of the structured block.
11119 // longjmp() and throw() must not violate the entry/exit criteria.
11120 CS->getCapturedDecl()->setNothrow();
11121
11122 OMPLoopBasedDirective::HelperExprs B;
11123 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11124 // define the nested loops number.
11125 unsigned NestedLoopCount =
11126 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
11127 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
11128 VarsWithImplicitDSA, B);
11129 if (NestedLoopCount == 0)
11130 return StmtError();
11131
11132 assert((CurContext->isDependentContext() || B.builtAll()) &&
11133 "omp parallel for loop exprs were not built");
11134
11135 if (!CurContext->isDependentContext()) {
11136 // Finalize the clauses that need pre-built expressions for CodeGen.
11137 for (OMPClause *C : Clauses) {
11138 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
11139 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
11140 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
11141 DSAStack))
11142 return StmtError();
11143 }
11144 }
11145
11146 setFunctionHasBranchProtectedScope();
11147 return OMPParallelForDirective::Create(
11148 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
11149 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11150}
11151
11152StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
11153 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11154 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11155 if (!AStmt)
11156 return StmtError();
11157
11158 auto *CS = cast<CapturedStmt>(Val: AStmt);
11159 // 1.2.2 OpenMP Language Terminology
11160 // Structured block - An executable statement with a single entry at the
11161 // top and a single exit at the bottom.
11162 // The point of exit cannot be a branch out of the structured block.
11163 // longjmp() and throw() must not violate the entry/exit criteria.
11164 CS->getCapturedDecl()->setNothrow();
11165
11166 OMPLoopBasedDirective::HelperExprs B;
11167 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11168 // define the nested loops number.
11169 unsigned NestedLoopCount =
11170 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
11171 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
11172 VarsWithImplicitDSA, B);
11173 if (NestedLoopCount == 0)
11174 return StmtError();
11175
11176 if (!CurContext->isDependentContext()) {
11177 // Finalize the clauses that need pre-built expressions for CodeGen.
11178 for (OMPClause *C : Clauses) {
11179 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
11180 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
11181 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
11182 DSAStack))
11183 return StmtError();
11184 }
11185 }
11186
11187 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
11188 return StmtError();
11189
11190 setFunctionHasBranchProtectedScope();
11191 return OMPParallelForSimdDirective::Create(
11192 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
11193}
11194
11195StmtResult
11196Sema::ActOnOpenMPParallelMasterDirective(ArrayRef<OMPClause *> Clauses,
11197 Stmt *AStmt, SourceLocation StartLoc,
11198 SourceLocation EndLoc) {
11199 if (!AStmt)
11200 return StmtError();
11201
11202 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11203 auto *CS = cast<CapturedStmt>(Val: AStmt);
11204 // 1.2.2 OpenMP Language Terminology
11205 // Structured block - An executable statement with a single entry at the
11206 // top and a single exit at the bottom.
11207 // The point of exit cannot be a branch out of the structured block.
11208 // longjmp() and throw() must not violate the entry/exit criteria.
11209 CS->getCapturedDecl()->setNothrow();
11210
11211 setFunctionHasBranchProtectedScope();
11212
11213 return OMPParallelMasterDirective::Create(
11214 C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11215 DSAStack->getTaskgroupReductionRef());
11216}
11217
11218StmtResult
11219Sema::ActOnOpenMPParallelMaskedDirective(ArrayRef<OMPClause *> Clauses,
11220 Stmt *AStmt, SourceLocation StartLoc,
11221 SourceLocation EndLoc) {
11222 if (!AStmt)
11223 return StmtError();
11224
11225 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11226 auto *CS = cast<CapturedStmt>(Val: AStmt);
11227 // 1.2.2 OpenMP Language Terminology
11228 // Structured block - An executable statement with a single entry at the
11229 // top and a single exit at the bottom.
11230 // The point of exit cannot be a branch out of the structured block.
11231 // longjmp() and throw() must not violate the entry/exit criteria.
11232 CS->getCapturedDecl()->setNothrow();
11233
11234 setFunctionHasBranchProtectedScope();
11235
11236 return OMPParallelMaskedDirective::Create(
11237 C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11238 DSAStack->getTaskgroupReductionRef());
11239}
11240
11241StmtResult
11242Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
11243 Stmt *AStmt, SourceLocation StartLoc,
11244 SourceLocation EndLoc) {
11245 if (!AStmt)
11246 return StmtError();
11247
11248 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11249 auto BaseStmt = AStmt;
11250 while (auto *CS = dyn_cast_or_null<CapturedStmt>(Val: BaseStmt))
11251 BaseStmt = CS->getCapturedStmt();
11252 if (auto *C = dyn_cast_or_null<CompoundStmt>(Val: BaseStmt)) {
11253 auto S = C->children();
11254 if (S.begin() == S.end())
11255 return StmtError();
11256 // All associated statements must be '#pragma omp section' except for
11257 // the first one.
11258 for (Stmt *SectionStmt : llvm::drop_begin(RangeOrContainer&: S)) {
11259 if (!SectionStmt || !isa<OMPSectionDirective>(Val: SectionStmt)) {
11260 if (SectionStmt)
11261 Diag(SectionStmt->getBeginLoc(),
11262 diag::err_omp_parallel_sections_substmt_not_section);
11263 return StmtError();
11264 }
11265 cast<OMPSectionDirective>(Val: SectionStmt)
11266 ->setHasCancel(DSAStack->isCancelRegion());
11267 }
11268 } else {
11269 Diag(AStmt->getBeginLoc(),
11270 diag::err_omp_parallel_sections_not_compound_stmt);
11271 return StmtError();
11272 }
11273
11274 setFunctionHasBranchProtectedScope();
11275
11276 return OMPParallelSectionsDirective::Create(
11277 C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11278 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11279}
11280
11281/// Find and diagnose mutually exclusive clause kinds.
11282static bool checkMutuallyExclusiveClauses(
11283 Sema &S, ArrayRef<OMPClause *> Clauses,
11284 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11285 const OMPClause *PrevClause = nullptr;
11286 bool ErrorFound = false;
11287 for (const OMPClause *C : Clauses) {
11288 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11289 if (!PrevClause) {
11290 PrevClause = C;
11291 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11292 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11293 << getOpenMPClauseName(C->getClauseKind())
11294 << getOpenMPClauseName(PrevClause->getClauseKind());
11295 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11296 << getOpenMPClauseName(PrevClause->getClauseKind());
11297 ErrorFound = true;
11298 }
11299 }
11300 }
11301 return ErrorFound;
11302}
11303
11304StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
11305 Stmt *AStmt, SourceLocation StartLoc,
11306 SourceLocation EndLoc) {
11307 if (!AStmt)
11308 return StmtError();
11309
11310 // OpenMP 5.0, 2.10.1 task Construct
11311 // If a detach clause appears on the directive, then a mergeable clause cannot
11312 // appear on the same directive.
11313 if (checkMutuallyExclusiveClauses(*this, Clauses,
11314 {OMPC_detach, OMPC_mergeable}))
11315 return StmtError();
11316
11317 auto *CS = cast<CapturedStmt>(Val: AStmt);
11318 // 1.2.2 OpenMP Language Terminology
11319 // Structured block - An executable statement with a single entry at the
11320 // top and a single exit at the bottom.
11321 // The point of exit cannot be a branch out of the structured block.
11322 // longjmp() and throw() must not violate the entry/exit criteria.
11323 CS->getCapturedDecl()->setNothrow();
11324
11325 setFunctionHasBranchProtectedScope();
11326
11327 return OMPTaskDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11328 DSAStack->isCancelRegion());
11329}
11330
11331StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
11332 SourceLocation EndLoc) {
11333 return OMPTaskyieldDirective::Create(C: Context, StartLoc, EndLoc);
11334}
11335
11336StmtResult Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
11337 SourceLocation EndLoc) {
11338 return OMPBarrierDirective::Create(C: Context, StartLoc, EndLoc);
11339}
11340
11341StmtResult Sema::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
11342 SourceLocation StartLoc,
11343 SourceLocation EndLoc,
11344 bool InExContext) {
11345 const OMPAtClause *AtC =
11346 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11347
11348 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11349 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11350 return StmtError();
11351 }
11352
11353 const OMPSeverityClause *SeverityC =
11354 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11355 const OMPMessageClause *MessageC =
11356 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11357 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11358
11359 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11360 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11361 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11362 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
11363 else
11364 Diag(StartLoc, diag::err_diagnose_if_succeeded)
11365 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
11366 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11367 return StmtError();
11368 }
11369 return OMPErrorDirective::Create(C: Context, StartLoc, EndLoc, Clauses);
11370}
11371
11372StmtResult Sema::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
11373 SourceLocation StartLoc,
11374 SourceLocation EndLoc) {
11375 const OMPNowaitClause *NowaitC =
11376 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11377 bool HasDependC =
11378 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11379 .empty();
11380 if (NowaitC && !HasDependC) {
11381 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11382 return StmtError();
11383 }
11384
11385 return OMPTaskwaitDirective::Create(C: Context, StartLoc, EndLoc, Clauses);
11386}
11387
11388StmtResult Sema::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
11389 Stmt *AStmt,
11390 SourceLocation StartLoc,
11391 SourceLocation EndLoc) {
11392 if (!AStmt)
11393 return StmtError();
11394
11395 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11396
11397 setFunctionHasBranchProtectedScope();
11398
11399 return OMPTaskgroupDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
11400 AssociatedStmt: AStmt,
11401 DSAStack->getTaskgroupReductionRef());
11402}
11403
11404StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
11405 SourceLocation StartLoc,
11406 SourceLocation EndLoc) {
11407 OMPFlushClause *FC = nullptr;
11408 OMPClause *OrderClause = nullptr;
11409 for (OMPClause *C : Clauses) {
11410 if (C->getClauseKind() == OMPC_flush)
11411 FC = cast<OMPFlushClause>(Val: C);
11412 else
11413 OrderClause = C;
11414 }
11415 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11416 SourceLocation MemOrderLoc;
11417 for (const OMPClause *C : Clauses) {
11418 if (C->getClauseKind() == OMPC_acq_rel ||
11419 C->getClauseKind() == OMPC_acquire ||
11420 C->getClauseKind() == OMPC_release) {
11421 if (MemOrderKind != OMPC_unknown) {
11422 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11423 << getOpenMPDirectiveName(OMPD_flush) << 1
11424 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11425 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11426 << getOpenMPClauseName(MemOrderKind);
11427 } else {
11428 MemOrderKind = C->getClauseKind();
11429 MemOrderLoc = C->getBeginLoc();
11430 }
11431 }
11432 }
11433 if (FC && OrderClause) {
11434 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11435 << getOpenMPClauseName(OrderClause->getClauseKind());
11436 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11437 << getOpenMPClauseName(OrderClause->getClauseKind());
11438 return StmtError();
11439 }
11440 return OMPFlushDirective::Create(C: Context, StartLoc, EndLoc, Clauses);
11441}
11442
11443StmtResult Sema::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
11444 SourceLocation StartLoc,
11445 SourceLocation EndLoc) {
11446 if (Clauses.empty()) {
11447 Diag(StartLoc, diag::err_omp_depobj_expected);
11448 return StmtError();
11449 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11450 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11451 return StmtError();
11452 }
11453 // Only depobj expression and another single clause is allowed.
11454 if (Clauses.size() > 2) {
11455 Diag(Clauses[2]->getBeginLoc(),
11456 diag::err_omp_depobj_single_clause_expected);
11457 return StmtError();
11458 } else if (Clauses.size() < 1) {
11459 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11460 return StmtError();
11461 }
11462 return OMPDepobjDirective::Create(C: Context, StartLoc, EndLoc, Clauses);
11463}
11464
11465StmtResult Sema::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
11466 SourceLocation StartLoc,
11467 SourceLocation EndLoc) {
11468 // Check that exactly one clause is specified.
11469 if (Clauses.size() != 1) {
11470 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11471 diag::err_omp_scan_single_clause_expected);
11472 return StmtError();
11473 }
11474 // Check that scan directive is used in the scopeof the OpenMP loop body.
11475 if (Scope *S = DSAStack->getCurScope()) {
11476 Scope *ParentS = S->getParent();
11477 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11478 !ParentS->getBreakParent()->isOpenMPLoopScope())
11479 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11480 << getOpenMPDirectiveName(OMPD_scan) << 5);
11481 }
11482 // Check that only one instance of scan directives is used in the same outer
11483 // region.
11484 if (DSAStack->doesParentHasScanDirective()) {
11485 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11486 Diag(DSAStack->getParentScanDirectiveLoc(),
11487 diag::note_omp_previous_directive)
11488 << "scan";
11489 return StmtError();
11490 }
11491 DSAStack->setParentHasScanDirective(StartLoc);
11492 return OMPScanDirective::Create(C: Context, StartLoc, EndLoc, Clauses);
11493}
11494
11495StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
11496 Stmt *AStmt,
11497 SourceLocation StartLoc,
11498 SourceLocation EndLoc) {
11499 const OMPClause *DependFound = nullptr;
11500 const OMPClause *DependSourceClause = nullptr;
11501 const OMPClause *DependSinkClause = nullptr;
11502 const OMPClause *DoacrossFound = nullptr;
11503 const OMPClause *DoacrossSourceClause = nullptr;
11504 const OMPClause *DoacrossSinkClause = nullptr;
11505 bool ErrorFound = false;
11506 const OMPThreadsClause *TC = nullptr;
11507 const OMPSIMDClause *SC = nullptr;
11508 for (const OMPClause *C : Clauses) {
11509 auto DOC = dyn_cast<OMPDoacrossClause>(Val: C);
11510 auto DC = dyn_cast<OMPDependClause>(Val: C);
11511 if (DC || DOC) {
11512 DependFound = DC ? C : nullptr;
11513 DoacrossFound = DOC ? C : nullptr;
11514 OMPDoacrossKind ODK;
11515 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11516 (DOC && (ODK.isSource(C: DOC)))) {
11517 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11518 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11519 << getOpenMPDirectiveName(OMPD_ordered)
11520 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11521 ErrorFound = true;
11522 } else {
11523 if (DC)
11524 DependSourceClause = C;
11525 else
11526 DoacrossSourceClause = C;
11527 }
11528 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11529 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11530 << (DC ? "depend" : "doacross") << 0;
11531 ErrorFound = true;
11532 }
11533 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11534 (DOC && (ODK.isSink(C: DOC) || ODK.isSinkIter(C: DOC)))) {
11535 if (DependSourceClause || DoacrossSourceClause) {
11536 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11537 << (DC ? "depend" : "doacross") << 1;
11538 ErrorFound = true;
11539 }
11540 if (DC)
11541 DependSinkClause = C;
11542 else
11543 DoacrossSinkClause = C;
11544 }
11545 } else if (C->getClauseKind() == OMPC_threads) {
11546 TC = cast<OMPThreadsClause>(Val: C);
11547 } else if (C->getClauseKind() == OMPC_simd) {
11548 SC = cast<OMPSIMDClause>(Val: C);
11549 }
11550 }
11551 if (!ErrorFound && !SC &&
11552 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11553 // OpenMP [2.8.1,simd Construct, Restrictions]
11554 // An ordered construct with the simd clause is the only OpenMP construct
11555 // that can appear in the simd region.
11556 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11557 << (LangOpts.OpenMP >= 50 ? 1 : 0);
11558 ErrorFound = true;
11559 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11560 SourceLocation Loc =
11561 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11562 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11563 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11564 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11565 ErrorFound = true;
11566 } else if ((DependFound || DoacrossFound) &&
11567 !DSAStack->getParentOrderedRegionParam().first) {
11568 SourceLocation Loc =
11569 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11570 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11571 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11572 ErrorFound = true;
11573 } else if (TC || Clauses.empty()) {
11574 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11575 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11576 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11577 << (TC != nullptr);
11578 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11579 ErrorFound = true;
11580 }
11581 }
11582 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11583 return StmtError();
11584
11585 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11586 // During execution of an iteration of a worksharing-loop or a loop nest
11587 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11588 // must not execute more than one ordered region corresponding to an ordered
11589 // construct without a depend clause.
11590 if (!DependFound && !DoacrossFound) {
11591 if (DSAStack->doesParentHasOrderedDirective()) {
11592 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11593 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11594 diag::note_omp_previous_directive)
11595 << "ordered";
11596 return StmtError();
11597 }
11598 DSAStack->setParentHasOrderedDirective(StartLoc);
11599 }
11600
11601 if (AStmt) {
11602 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11603
11604 setFunctionHasBranchProtectedScope();
11605 }
11606
11607 return OMPOrderedDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt);
11608}
11609
11610namespace {
11611/// Helper class for checking expression in 'omp atomic [update]'
11612/// construct.
11613class OpenMPAtomicUpdateChecker {
11614 /// Error results for atomic update expressions.
11615 enum ExprAnalysisErrorCode {
11616 /// A statement is not an expression statement.
11617 NotAnExpression,
11618 /// Expression is not builtin binary or unary operation.
11619 NotABinaryOrUnaryExpression,
11620 /// Unary operation is not post-/pre- increment/decrement operation.
11621 NotAnUnaryIncDecExpression,
11622 /// An expression is not of scalar type.
11623 NotAScalarType,
11624 /// A binary operation is not an assignment operation.
11625 NotAnAssignmentOp,
11626 /// RHS part of the binary operation is not a binary expression.
11627 NotABinaryExpression,
11628 /// RHS part is not additive/multiplicative/shift/biwise binary
11629 /// expression.
11630 NotABinaryOperator,
11631 /// RHS binary operation does not have reference to the updated LHS
11632 /// part.
11633 NotAnUpdateExpression,
11634 /// An expression contains semantical error not related to
11635 /// 'omp atomic [update]'
11636 NotAValidExpression,
11637 /// No errors is found.
11638 NoError
11639 };
11640 /// Reference to Sema.
11641 Sema &SemaRef;
11642 /// A location for note diagnostics (when error is found).
11643 SourceLocation NoteLoc;
11644 /// 'x' lvalue part of the source atomic expression.
11645 Expr *X;
11646 /// 'expr' rvalue part of the source atomic expression.
11647 Expr *E;
11648 /// Helper expression of the form
11649 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11650 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11651 Expr *UpdateExpr;
11652 /// Is 'x' a LHS in a RHS part of full update expression. It is
11653 /// important for non-associative operations.
11654 bool IsXLHSInRHSPart;
11655 BinaryOperatorKind Op;
11656 SourceLocation OpLoc;
11657 /// true if the source expression is a postfix unary operation, false
11658 /// if it is a prefix unary operation.
11659 bool IsPostfixUpdate;
11660
11661public:
11662 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11663 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11664 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11665 /// Check specified statement that it is suitable for 'atomic update'
11666 /// constructs and extract 'x', 'expr' and Operation from the original
11667 /// expression. If DiagId and NoteId == 0, then only check is performed
11668 /// without error notification.
11669 /// \param DiagId Diagnostic which should be emitted if error is found.
11670 /// \param NoteId Diagnostic note for the main error message.
11671 /// \return true if statement is not an update expression, false otherwise.
11672 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11673 /// Return the 'x' lvalue part of the source atomic expression.
11674 Expr *getX() const { return X; }
11675 /// Return the 'expr' rvalue part of the source atomic expression.
11676 Expr *getExpr() const { return E; }
11677 /// Return the update expression used in calculation of the updated
11678 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11679 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11680 Expr *getUpdateExpr() const { return UpdateExpr; }
11681 /// Return true if 'x' is LHS in RHS part of full update expression,
11682 /// false otherwise.
11683 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11684
11685 /// true if the source expression is a postfix unary operation, false
11686 /// if it is a prefix unary operation.
11687 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11688
11689private:
11690 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11691 unsigned NoteId = 0);
11692};
11693
11694bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11695 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11696 ExprAnalysisErrorCode ErrorFound = NoError;
11697 SourceLocation ErrorLoc, NoteLoc;
11698 SourceRange ErrorRange, NoteRange;
11699 // Allowed constructs are:
11700 // x = x binop expr;
11701 // x = expr binop x;
11702 if (AtomicBinOp->getOpcode() == BO_Assign) {
11703 X = AtomicBinOp->getLHS();
11704 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11705 Val: AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11706 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11707 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11708 AtomicInnerBinOp->isBitwiseOp()) {
11709 Op = AtomicInnerBinOp->getOpcode();
11710 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11711 Expr *LHS = AtomicInnerBinOp->getLHS();
11712 Expr *RHS = AtomicInnerBinOp->getRHS();
11713 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11714 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11715 /*Canonical=*/true);
11716 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11717 /*Canonical=*/true);
11718 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11719 /*Canonical=*/true);
11720 if (XId == LHSId) {
11721 E = RHS;
11722 IsXLHSInRHSPart = true;
11723 } else if (XId == RHSId) {
11724 E = LHS;
11725 IsXLHSInRHSPart = false;
11726 } else {
11727 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11728 ErrorRange = AtomicInnerBinOp->getSourceRange();
11729 NoteLoc = X->getExprLoc();
11730 NoteRange = X->getSourceRange();
11731 ErrorFound = NotAnUpdateExpression;
11732 }
11733 } else {
11734 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11735 ErrorRange = AtomicInnerBinOp->getSourceRange();
11736 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11737 NoteRange = SourceRange(NoteLoc, NoteLoc);
11738 ErrorFound = NotABinaryOperator;
11739 }
11740 } else {
11741 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11742 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11743 ErrorFound = NotABinaryExpression;
11744 }
11745 } else {
11746 ErrorLoc = AtomicBinOp->getExprLoc();
11747 ErrorRange = AtomicBinOp->getSourceRange();
11748 NoteLoc = AtomicBinOp->getOperatorLoc();
11749 NoteRange = SourceRange(NoteLoc, NoteLoc);
11750 ErrorFound = NotAnAssignmentOp;
11751 }
11752 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11753 SemaRef.Diag(Loc: ErrorLoc, DiagID: DiagId) << ErrorRange;
11754 SemaRef.Diag(Loc: NoteLoc, DiagID: NoteId) << ErrorFound << NoteRange;
11755 return true;
11756 }
11757 if (SemaRef.CurContext->isDependentContext())
11758 E = X = UpdateExpr = nullptr;
11759 return ErrorFound != NoError;
11760}
11761
11762bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11763 unsigned NoteId) {
11764 ExprAnalysisErrorCode ErrorFound = NoError;
11765 SourceLocation ErrorLoc, NoteLoc;
11766 SourceRange ErrorRange, NoteRange;
11767 // Allowed constructs are:
11768 // x++;
11769 // x--;
11770 // ++x;
11771 // --x;
11772 // x binop= expr;
11773 // x = x binop expr;
11774 // x = expr binop x;
11775 if (auto *AtomicBody = dyn_cast<Expr>(Val: S)) {
11776 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11777 if (AtomicBody->getType()->isScalarType() ||
11778 AtomicBody->isInstantiationDependent()) {
11779 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11780 Val: AtomicBody->IgnoreParenImpCasts())) {
11781 // Check for Compound Assignment Operation
11782 Op = BinaryOperator::getOpForCompoundAssignment(
11783 Opc: AtomicCompAssignOp->getOpcode());
11784 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11785 E = AtomicCompAssignOp->getRHS();
11786 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11787 IsXLHSInRHSPart = true;
11788 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11789 Val: AtomicBody->IgnoreParenImpCasts())) {
11790 // Check for Binary Operation
11791 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11792 return true;
11793 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11794 Val: AtomicBody->IgnoreParenImpCasts())) {
11795 // Check for Unary Operation
11796 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11797 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11798 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11799 OpLoc = AtomicUnaryOp->getOperatorLoc();
11800 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11801 E = SemaRef.ActOnIntegerConstant(Loc: OpLoc, /*uint64_t Val=*/Val: 1).get();
11802 IsXLHSInRHSPart = true;
11803 } else {
11804 ErrorFound = NotAnUnaryIncDecExpression;
11805 ErrorLoc = AtomicUnaryOp->getExprLoc();
11806 ErrorRange = AtomicUnaryOp->getSourceRange();
11807 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11808 NoteRange = SourceRange(NoteLoc, NoteLoc);
11809 }
11810 } else if (!AtomicBody->isInstantiationDependent()) {
11811 ErrorFound = NotABinaryOrUnaryExpression;
11812 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11813 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11814 } else if (AtomicBody->containsErrors()) {
11815 ErrorFound = NotAValidExpression;
11816 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11817 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11818 }
11819 } else {
11820 ErrorFound = NotAScalarType;
11821 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11822 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11823 }
11824 } else {
11825 ErrorFound = NotAnExpression;
11826 NoteLoc = ErrorLoc = S->getBeginLoc();
11827 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11828 }
11829 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11830 SemaRef.Diag(Loc: ErrorLoc, DiagID: DiagId) << ErrorRange;
11831 SemaRef.Diag(Loc: NoteLoc, DiagID: NoteId) << ErrorFound << NoteRange;
11832 return true;
11833 }
11834 if (SemaRef.CurContext->isDependentContext())
11835 E = X = UpdateExpr = nullptr;
11836 if (ErrorFound == NoError && E && X) {
11837 // Build an update expression of form 'OpaqueValueExpr(x) binop
11838 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11839 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11840 auto *OVEX = new (SemaRef.getASTContext())
11841 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11842 auto *OVEExpr = new (SemaRef.getASTContext())
11843 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
11844 ExprResult Update =
11845 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11846 IsXLHSInRHSPart ? OVEExpr : OVEX);
11847 if (Update.isInvalid())
11848 return true;
11849 Update = SemaRef.PerformImplicitConversion(From: Update.get(), ToType: X->getType(),
11850 Action: Sema::AA_Casting);
11851 if (Update.isInvalid())
11852 return true;
11853 UpdateExpr = Update.get();
11854 }
11855 return ErrorFound != NoError;
11856}
11857
11858/// Get the node id of the fixed point of an expression \a S.
11859llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11860 llvm::FoldingSetNodeID Id;
11861 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11862 return Id;
11863}
11864
11865/// Check if two expressions are same.
11866bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11867 const Expr *RHS) {
11868 return getNodeId(Context, S: LHS) == getNodeId(Context, S: RHS);
11869}
11870
11871class OpenMPAtomicCompareChecker {
11872public:
11873 /// All kinds of errors that can occur in `atomic compare`
11874 enum ErrorTy {
11875 /// Empty compound statement.
11876 NoStmt = 0,
11877 /// More than one statement in a compound statement.
11878 MoreThanOneStmt,
11879 /// Not an assignment binary operator.
11880 NotAnAssignment,
11881 /// Not a conditional operator.
11882 NotCondOp,
11883 /// Wrong false expr. According to the spec, 'x' should be at the false
11884 /// expression of a conditional expression.
11885 WrongFalseExpr,
11886 /// The condition of a conditional expression is not a binary operator.
11887 NotABinaryOp,
11888 /// Invalid binary operator (not <, >, or ==).
11889 InvalidBinaryOp,
11890 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11891 InvalidComparison,
11892 /// X is not a lvalue.
11893 XNotLValue,
11894 /// Not a scalar.
11895 NotScalar,
11896 /// Not an integer.
11897 NotInteger,
11898 /// 'else' statement is not expected.
11899 UnexpectedElse,
11900 /// Not an equality operator.
11901 NotEQ,
11902 /// Invalid assignment (not v == x).
11903 InvalidAssignment,
11904 /// Not if statement
11905 NotIfStmt,
11906 /// More than two statements in a compund statement.
11907 MoreThanTwoStmts,
11908 /// Not a compound statement.
11909 NotCompoundStmt,
11910 /// No else statement.
11911 NoElse,
11912 /// Not 'if (r)'.
11913 InvalidCondition,
11914 /// No error.
11915 NoError,
11916 };
11917
11918 struct ErrorInfoTy {
11919 ErrorTy Error;
11920 SourceLocation ErrorLoc;
11921 SourceRange ErrorRange;
11922 SourceLocation NoteLoc;
11923 SourceRange NoteRange;
11924 };
11925
11926 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11927
11928 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11929 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11930
11931 Expr *getX() const { return X; }
11932 Expr *getE() const { return E; }
11933 Expr *getD() const { return D; }
11934 Expr *getCond() const { return C; }
11935 bool isXBinopExpr() const { return IsXBinopExpr; }
11936
11937protected:
11938 /// Reference to ASTContext
11939 ASTContext &ContextRef;
11940 /// 'x' lvalue part of the source atomic expression.
11941 Expr *X = nullptr;
11942 /// 'expr' or 'e' rvalue part of the source atomic expression.
11943 Expr *E = nullptr;
11944 /// 'd' rvalue part of the source atomic expression.
11945 Expr *D = nullptr;
11946 /// 'cond' part of the source atomic expression. It is in one of the following
11947 /// forms:
11948 /// expr ordop x
11949 /// x ordop expr
11950 /// x == e
11951 /// e == x
11952 Expr *C = nullptr;
11953 /// True if the cond expr is in the form of 'x ordop expr'.
11954 bool IsXBinopExpr = true;
11955
11956 /// Check if it is a valid conditional update statement (cond-update-stmt).
11957 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11958
11959 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11960 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11961
11962 /// Check if all captured values have right type.
11963 bool checkType(ErrorInfoTy &ErrorInfo) const;
11964
11965 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11966 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11967 if (E->isInstantiationDependent())
11968 return true;
11969
11970 if (ShouldBeLValue && !E->isLValue()) {
11971 ErrorInfo.Error = ErrorTy::XNotLValue;
11972 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11973 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11974 return false;
11975 }
11976
11977 QualType QTy = E->getType();
11978 if (!QTy->isScalarType()) {
11979 ErrorInfo.Error = ErrorTy::NotScalar;
11980 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11981 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11982 return false;
11983 }
11984 if (ShouldBeInteger && !QTy->isIntegerType()) {
11985 ErrorInfo.Error = ErrorTy::NotInteger;
11986 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11987 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11988 return false;
11989 }
11990
11991 return true;
11992 }
11993 };
11994
11995bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11996 ErrorInfoTy &ErrorInfo) {
11997 auto *Then = S->getThen();
11998 if (auto *CS = dyn_cast<CompoundStmt>(Val: Then)) {
11999 if (CS->body_empty()) {
12000 ErrorInfo.Error = ErrorTy::NoStmt;
12001 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12002 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12003 return false;
12004 }
12005 if (CS->size() > 1) {
12006 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12007 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12008 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12009 return false;
12010 }
12011 Then = CS->body_front();
12012 }
12013
12014 auto *BO = dyn_cast<BinaryOperator>(Val: Then);
12015 if (!BO) {
12016 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12017 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12018 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12019 return false;
12020 }
12021 if (BO->getOpcode() != BO_Assign) {
12022 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12023 ErrorInfo.ErrorLoc = BO->getExprLoc();
12024 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12025 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12026 return false;
12027 }
12028
12029 X = BO->getLHS();
12030
12031 auto *Cond = dyn_cast<BinaryOperator>(Val: S->getCond());
12032 if (!Cond) {
12033 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12034 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12035 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12036 return false;
12037 }
12038
12039 switch (Cond->getOpcode()) {
12040 case BO_EQ: {
12041 C = Cond;
12042 D = BO->getRHS();
12043 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: Cond->getLHS())) {
12044 E = Cond->getRHS();
12045 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: Cond->getRHS())) {
12046 E = Cond->getLHS();
12047 } else {
12048 ErrorInfo.Error = ErrorTy::InvalidComparison;
12049 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12050 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12051 return false;
12052 }
12053 break;
12054 }
12055 case BO_LT:
12056 case BO_GT: {
12057 E = BO->getRHS();
12058 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: Cond->getLHS()) &&
12059 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: Cond->getRHS())) {
12060 C = Cond;
12061 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: Cond->getLHS()) &&
12062 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: Cond->getRHS())) {
12063 C = Cond;
12064 IsXBinopExpr = false;
12065 } else {
12066 ErrorInfo.Error = ErrorTy::InvalidComparison;
12067 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12068 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12069 return false;
12070 }
12071 break;
12072 }
12073 default:
12074 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12075 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12076 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12077 return false;
12078 }
12079
12080 if (S->getElse()) {
12081 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12082 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12083 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12084 return false;
12085 }
12086
12087 return true;
12088}
12089
12090bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12091 ErrorInfoTy &ErrorInfo) {
12092 auto *BO = dyn_cast<BinaryOperator>(Val: S);
12093 if (!BO) {
12094 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12095 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12096 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12097 return false;
12098 }
12099 if (BO->getOpcode() != BO_Assign) {
12100 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12101 ErrorInfo.ErrorLoc = BO->getExprLoc();
12102 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12103 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12104 return false;
12105 }
12106
12107 X = BO->getLHS();
12108
12109 auto *CO = dyn_cast<ConditionalOperator>(Val: BO->getRHS()->IgnoreParenImpCasts());
12110 if (!CO) {
12111 ErrorInfo.Error = ErrorTy::NotCondOp;
12112 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12113 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12114 return false;
12115 }
12116
12117 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: CO->getFalseExpr())) {
12118 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12119 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12120 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12121 CO->getFalseExpr()->getSourceRange();
12122 return false;
12123 }
12124
12125 auto *Cond = dyn_cast<BinaryOperator>(Val: CO->getCond());
12126 if (!Cond) {
12127 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12128 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12129 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12130 CO->getCond()->getSourceRange();
12131 return false;
12132 }
12133
12134 switch (Cond->getOpcode()) {
12135 case BO_EQ: {
12136 C = Cond;
12137 D = CO->getTrueExpr();
12138 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: Cond->getLHS())) {
12139 E = Cond->getRHS();
12140 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: Cond->getRHS())) {
12141 E = Cond->getLHS();
12142 } else {
12143 ErrorInfo.Error = ErrorTy::InvalidComparison;
12144 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12145 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12146 return false;
12147 }
12148 break;
12149 }
12150 case BO_LT:
12151 case BO_GT: {
12152 E = CO->getTrueExpr();
12153 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: Cond->getLHS()) &&
12154 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: Cond->getRHS())) {
12155 C = Cond;
12156 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: Cond->getLHS()) &&
12157 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: Cond->getRHS())) {
12158 C = Cond;
12159 IsXBinopExpr = false;
12160 } else {
12161 ErrorInfo.Error = ErrorTy::InvalidComparison;
12162 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12163 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12164 return false;
12165 }
12166 break;
12167 }
12168 default:
12169 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12170 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12171 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12172 return false;
12173 }
12174
12175 return true;
12176}
12177
12178bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12179 // 'x' and 'e' cannot be nullptr
12180 assert(X && E && "X and E cannot be nullptr");
12181
12182 if (!CheckValue(E: X, ErrorInfo, ShouldBeLValue: true))
12183 return false;
12184
12185 if (!CheckValue(E, ErrorInfo, ShouldBeLValue: false))
12186 return false;
12187
12188 if (D && !CheckValue(E: D, ErrorInfo, ShouldBeLValue: false))
12189 return false;
12190
12191 return true;
12192}
12193
12194bool OpenMPAtomicCompareChecker::checkStmt(
12195 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12196 auto *CS = dyn_cast<CompoundStmt>(Val: S);
12197 if (CS) {
12198 if (CS->body_empty()) {
12199 ErrorInfo.Error = ErrorTy::NoStmt;
12200 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12201 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12202 return false;
12203 }
12204
12205 if (CS->size() != 1) {
12206 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12207 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12208 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12209 return false;
12210 }
12211 S = CS->body_front();
12212 }
12213
12214 auto Res = false;
12215
12216 if (auto *IS = dyn_cast<IfStmt>(Val: S)) {
12217 // Check if the statement is in one of the following forms
12218 // (cond-update-stmt):
12219 // if (expr ordop x) { x = expr; }
12220 // if (x ordop expr) { x = expr; }
12221 // if (x == e) { x = d; }
12222 Res = checkCondUpdateStmt(S: IS, ErrorInfo);
12223 } else {
12224 // Check if the statement is in one of the following forms (cond-expr-stmt):
12225 // x = expr ordop x ? expr : x;
12226 // x = x ordop expr ? expr : x;
12227 // x = x == e ? d : x;
12228 Res = checkCondExprStmt(S, ErrorInfo);
12229 }
12230
12231 if (!Res)
12232 return false;
12233
12234 return checkType(ErrorInfo);
12235}
12236
12237class OpenMPAtomicCompareCaptureChecker final
12238 : public OpenMPAtomicCompareChecker {
12239public:
12240 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12241
12242 Expr *getV() const { return V; }
12243 Expr *getR() const { return R; }
12244 bool isFailOnly() const { return IsFailOnly; }
12245 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12246
12247 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12248 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12249
12250private:
12251 bool checkType(ErrorInfoTy &ErrorInfo);
12252
12253 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12254 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12255 // spec p.p. 82:
12256 // (1) { v = x; cond-update-stmt }
12257 // (2) { cond-update-stmt v = x; }
12258 // (3) if(x == e) { x = d; } else { v = x; }
12259 // (4) { r = x == e; if(r) { x = d; } }
12260 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12261
12262 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12263 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12264
12265 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12266 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12267 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12268
12269 /// 'v' lvalue part of the source atomic expression.
12270 Expr *V = nullptr;
12271 /// 'r' lvalue part of the source atomic expression.
12272 Expr *R = nullptr;
12273 /// If 'v' is only updated when the comparison fails.
12274 bool IsFailOnly = false;
12275 /// If original value of 'x' must be stored in 'v', not an updated one.
12276 bool IsPostfixUpdate = false;
12277};
12278
12279bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12280 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12281 return false;
12282
12283 if (V && !CheckValue(E: V, ErrorInfo, ShouldBeLValue: true))
12284 return false;
12285
12286 if (R && !CheckValue(E: R, ErrorInfo, ShouldBeLValue: true, ShouldBeInteger: true))
12287 return false;
12288
12289 return true;
12290}
12291
12292bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12293 ErrorInfoTy &ErrorInfo) {
12294 IsFailOnly = true;
12295
12296 auto *Then = S->getThen();
12297 if (auto *CS = dyn_cast<CompoundStmt>(Val: Then)) {
12298 if (CS->body_empty()) {
12299 ErrorInfo.Error = ErrorTy::NoStmt;
12300 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12301 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12302 return false;
12303 }
12304 if (CS->size() > 1) {
12305 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12306 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12307 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12308 return false;
12309 }
12310 Then = CS->body_front();
12311 }
12312
12313 auto *BO = dyn_cast<BinaryOperator>(Val: Then);
12314 if (!BO) {
12315 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12316 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12317 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12318 return false;
12319 }
12320 if (BO->getOpcode() != BO_Assign) {
12321 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12322 ErrorInfo.ErrorLoc = BO->getExprLoc();
12323 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12324 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12325 return false;
12326 }
12327
12328 X = BO->getLHS();
12329 D = BO->getRHS();
12330
12331 auto *Cond = dyn_cast<BinaryOperator>(Val: S->getCond());
12332 if (!Cond) {
12333 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12334 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12335 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12336 return false;
12337 }
12338 if (Cond->getOpcode() != BO_EQ) {
12339 ErrorInfo.Error = ErrorTy::NotEQ;
12340 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12341 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12342 return false;
12343 }
12344
12345 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: Cond->getLHS())) {
12346 E = Cond->getRHS();
12347 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: Cond->getRHS())) {
12348 E = Cond->getLHS();
12349 } else {
12350 ErrorInfo.Error = ErrorTy::InvalidComparison;
12351 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12352 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12353 return false;
12354 }
12355
12356 C = Cond;
12357
12358 if (!S->getElse()) {
12359 ErrorInfo.Error = ErrorTy::NoElse;
12360 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12361 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12362 return false;
12363 }
12364
12365 auto *Else = S->getElse();
12366 if (auto *CS = dyn_cast<CompoundStmt>(Val: Else)) {
12367 if (CS->body_empty()) {
12368 ErrorInfo.Error = ErrorTy::NoStmt;
12369 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12370 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12371 return false;
12372 }
12373 if (CS->size() > 1) {
12374 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12375 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12376 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12377 return false;
12378 }
12379 Else = CS->body_front();
12380 }
12381
12382 auto *ElseBO = dyn_cast<BinaryOperator>(Val: Else);
12383 if (!ElseBO) {
12384 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12385 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12386 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12387 return false;
12388 }
12389 if (ElseBO->getOpcode() != BO_Assign) {
12390 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12391 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12392 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12393 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12394 return false;
12395 }
12396
12397 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: ElseBO->getRHS())) {
12398 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12399 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12400 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12401 ElseBO->getRHS()->getSourceRange();
12402 return false;
12403 }
12404
12405 V = ElseBO->getLHS();
12406
12407 return checkType(ErrorInfo);
12408}
12409
12410bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12411 ErrorInfoTy &ErrorInfo) {
12412 // We don't check here as they should be already done before call this
12413 // function.
12414 auto *CS = cast<CompoundStmt>(Val: S);
12415 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12416 auto *S1 = cast<BinaryOperator>(Val: CS->body_front());
12417 auto *S2 = cast<IfStmt>(Val: CS->body_back());
12418 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12419
12420 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: S1->getLHS(), RHS: S2->getCond())) {
12421 ErrorInfo.Error = ErrorTy::InvalidCondition;
12422 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12423 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12424 return false;
12425 }
12426
12427 R = S1->getLHS();
12428
12429 auto *Then = S2->getThen();
12430 if (auto *ThenCS = dyn_cast<CompoundStmt>(Val: Then)) {
12431 if (ThenCS->body_empty()) {
12432 ErrorInfo.Error = ErrorTy::NoStmt;
12433 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12434 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12435 return false;
12436 }
12437 if (ThenCS->size() > 1) {
12438 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12439 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12440 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12441 return false;
12442 }
12443 Then = ThenCS->body_front();
12444 }
12445
12446 auto *ThenBO = dyn_cast<BinaryOperator>(Val: Then);
12447 if (!ThenBO) {
12448 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12449 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12450 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12451 return false;
12452 }
12453 if (ThenBO->getOpcode() != BO_Assign) {
12454 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12455 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12456 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12457 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12458 return false;
12459 }
12460
12461 X = ThenBO->getLHS();
12462 D = ThenBO->getRHS();
12463
12464 auto *BO = cast<BinaryOperator>(Val: S1->getRHS()->IgnoreImpCasts());
12465 if (BO->getOpcode() != BO_EQ) {
12466 ErrorInfo.Error = ErrorTy::NotEQ;
12467 ErrorInfo.ErrorLoc = BO->getExprLoc();
12468 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12469 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12470 return false;
12471 }
12472
12473 C = BO;
12474
12475 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: BO->getLHS())) {
12476 E = BO->getRHS();
12477 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: BO->getRHS())) {
12478 E = BO->getLHS();
12479 } else {
12480 ErrorInfo.Error = ErrorTy::InvalidComparison;
12481 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12482 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12483 return false;
12484 }
12485
12486 if (S2->getElse()) {
12487 IsFailOnly = true;
12488
12489 auto *Else = S2->getElse();
12490 if (auto *ElseCS = dyn_cast<CompoundStmt>(Val: Else)) {
12491 if (ElseCS->body_empty()) {
12492 ErrorInfo.Error = ErrorTy::NoStmt;
12493 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12494 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12495 return false;
12496 }
12497 if (ElseCS->size() > 1) {
12498 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12499 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12500 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12501 return false;
12502 }
12503 Else = ElseCS->body_front();
12504 }
12505
12506 auto *ElseBO = dyn_cast<BinaryOperator>(Val: Else);
12507 if (!ElseBO) {
12508 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12509 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12510 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12511 return false;
12512 }
12513 if (ElseBO->getOpcode() != BO_Assign) {
12514 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12515 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12516 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12517 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12518 return false;
12519 }
12520 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: ElseBO->getRHS())) {
12521 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12522 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12523 ErrorInfo.NoteLoc = X->getExprLoc();
12524 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12525 ErrorInfo.NoteRange = X->getSourceRange();
12526 return false;
12527 }
12528
12529 V = ElseBO->getLHS();
12530 }
12531
12532 return checkType(ErrorInfo);
12533}
12534
12535bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12536 ErrorInfoTy &ErrorInfo) {
12537 // if(x == e) { x = d; } else { v = x; }
12538 if (auto *IS = dyn_cast<IfStmt>(Val: S))
12539 return checkForm3(S: IS, ErrorInfo);
12540
12541 auto *CS = dyn_cast<CompoundStmt>(Val: S);
12542 if (!CS) {
12543 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12544 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12545 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12546 return false;
12547 }
12548 if (CS->body_empty()) {
12549 ErrorInfo.Error = ErrorTy::NoStmt;
12550 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12551 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12552 return false;
12553 }
12554
12555 // { if(x == e) { x = d; } else { v = x; } }
12556 if (CS->size() == 1) {
12557 auto *IS = dyn_cast<IfStmt>(Val: CS->body_front());
12558 if (!IS) {
12559 ErrorInfo.Error = ErrorTy::NotIfStmt;
12560 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12561 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12562 CS->body_front()->getSourceRange();
12563 return false;
12564 }
12565
12566 return checkForm3(S: IS, ErrorInfo);
12567 } else if (CS->size() == 2) {
12568 auto *S1 = CS->body_front();
12569 auto *S2 = CS->body_back();
12570
12571 Stmt *UpdateStmt = nullptr;
12572 Stmt *CondUpdateStmt = nullptr;
12573 Stmt *CondExprStmt = nullptr;
12574
12575 if (auto *BO = dyn_cast<BinaryOperator>(Val: S1)) {
12576 // It could be one of the following cases:
12577 // { v = x; cond-update-stmt }
12578 // { v = x; cond-expr-stmt }
12579 // { cond-expr-stmt; v = x; }
12580 // form 45
12581 if (isa<BinaryOperator>(Val: BO->getRHS()->IgnoreImpCasts()) ||
12582 isa<ConditionalOperator>(Val: BO->getRHS()->IgnoreImpCasts())) {
12583 // check if form 45
12584 if (isa<IfStmt>(Val: S2))
12585 return checkForm45(CS, ErrorInfo);
12586 // { cond-expr-stmt; v = x; }
12587 CondExprStmt = S1;
12588 UpdateStmt = S2;
12589 } else {
12590 IsPostfixUpdate = true;
12591 UpdateStmt = S1;
12592 if (isa<IfStmt>(Val: S2)) {
12593 // { v = x; cond-update-stmt }
12594 CondUpdateStmt = S2;
12595 } else {
12596 // { v = x; cond-expr-stmt }
12597 CondExprStmt = S2;
12598 }
12599 }
12600 } else {
12601 // { cond-update-stmt v = x; }
12602 UpdateStmt = S2;
12603 CondUpdateStmt = S1;
12604 }
12605
12606 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12607 auto *IS = dyn_cast<IfStmt>(Val: CUS);
12608 if (!IS) {
12609 ErrorInfo.Error = ErrorTy::NotIfStmt;
12610 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12611 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12612 return false;
12613 }
12614
12615 return checkCondUpdateStmt(S: IS, ErrorInfo);
12616 };
12617
12618 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12619 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12620 auto *BO = dyn_cast<BinaryOperator>(Val: US);
12621 if (!BO) {
12622 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12623 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12624 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12625 return false;
12626 }
12627 if (BO->getOpcode() != BO_Assign) {
12628 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12629 ErrorInfo.ErrorLoc = BO->getExprLoc();
12630 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12631 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12632 return false;
12633 }
12634 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: this->X, RHS: BO->getRHS())) {
12635 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12636 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12637 ErrorInfo.NoteLoc = this->X->getExprLoc();
12638 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12639 ErrorInfo.NoteRange = this->X->getSourceRange();
12640 return false;
12641 }
12642
12643 this->V = BO->getLHS();
12644
12645 return true;
12646 };
12647
12648 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12649 return false;
12650 if (CondExprStmt && !checkCondExprStmt(S: CondExprStmt, ErrorInfo))
12651 return false;
12652 if (!CheckUpdateStmt(UpdateStmt))
12653 return false;
12654 } else {
12655 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12656 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12657 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12658 return false;
12659 }
12660
12661 return checkType(ErrorInfo);
12662}
12663} // namespace
12664
12665StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
12666 Stmt *AStmt,
12667 SourceLocation StartLoc,
12668 SourceLocation EndLoc) {
12669 // Register location of the first atomic directive.
12670 DSAStack->addAtomicDirectiveLoc(Loc: StartLoc);
12671 if (!AStmt)
12672 return StmtError();
12673
12674 // 1.2.2 OpenMP Language Terminology
12675 // Structured block - An executable statement with a single entry at the
12676 // top and a single exit at the bottom.
12677 // The point of exit cannot be a branch out of the structured block.
12678 // longjmp() and throw() must not violate the entry/exit criteria.
12679 OpenMPClauseKind AtomicKind = OMPC_unknown;
12680 SourceLocation AtomicKindLoc;
12681 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12682 SourceLocation MemOrderLoc;
12683 bool MutexClauseEncountered = false;
12684 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12685 for (const OMPClause *C : Clauses) {
12686 switch (C->getClauseKind()) {
12687 case OMPC_read:
12688 case OMPC_write:
12689 case OMPC_update:
12690 MutexClauseEncountered = true;
12691 [[fallthrough]];
12692 case OMPC_capture:
12693 case OMPC_compare: {
12694 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12695 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12696 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12697 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12698 << getOpenMPClauseName(AtomicKind);
12699 } else {
12700 AtomicKind = C->getClauseKind();
12701 AtomicKindLoc = C->getBeginLoc();
12702 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12703 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12704 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12705 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12706 << getOpenMPClauseName(AtomicKind);
12707 }
12708 }
12709 break;
12710 }
12711 case OMPC_weak:
12712 case OMPC_fail: {
12713 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12714 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12715 << getOpenMPClauseName(C->getClauseKind())
12716 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12717 return StmtError();
12718 }
12719 break;
12720 }
12721 case OMPC_seq_cst:
12722 case OMPC_acq_rel:
12723 case OMPC_acquire:
12724 case OMPC_release:
12725 case OMPC_relaxed: {
12726 if (MemOrderKind != OMPC_unknown) {
12727 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12728 << getOpenMPDirectiveName(OMPD_atomic) << 0
12729 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12730 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12731 << getOpenMPClauseName(MemOrderKind);
12732 } else {
12733 MemOrderKind = C->getClauseKind();
12734 MemOrderLoc = C->getBeginLoc();
12735 }
12736 break;
12737 }
12738 // The following clauses are allowed, but we don't need to do anything here.
12739 case OMPC_hint:
12740 break;
12741 default:
12742 llvm_unreachable("unknown clause is encountered");
12743 }
12744 }
12745 bool IsCompareCapture = false;
12746 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12747 EncounteredAtomicKinds.contains(OMPC_capture)) {
12748 IsCompareCapture = true;
12749 AtomicKind = OMPC_compare;
12750 }
12751 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12752 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12753 // release.
12754 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12755 // acquire.
12756 // If atomic-clause is update or not present then memory-order-clause must not
12757 // be acq_rel or acquire.
12758 if ((AtomicKind == OMPC_read &&
12759 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12760 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12761 AtomicKind == OMPC_unknown) &&
12762 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12763 SourceLocation Loc = AtomicKindLoc;
12764 if (AtomicKind == OMPC_unknown)
12765 Loc = StartLoc;
12766 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12767 << getOpenMPClauseName(AtomicKind)
12768 << (AtomicKind == OMPC_unknown ? 1 : 0)
12769 << getOpenMPClauseName(MemOrderKind);
12770 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12771 << getOpenMPClauseName(MemOrderKind);
12772 }
12773
12774 Stmt *Body = AStmt;
12775 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: Body))
12776 Body = EWC->getSubExpr();
12777
12778 Expr *X = nullptr;
12779 Expr *V = nullptr;
12780 Expr *E = nullptr;
12781 Expr *UE = nullptr;
12782 Expr *D = nullptr;
12783 Expr *CE = nullptr;
12784 Expr *R = nullptr;
12785 bool IsXLHSInRHSPart = false;
12786 bool IsPostfixUpdate = false;
12787 bool IsFailOnly = false;
12788 // OpenMP [2.12.6, atomic Construct]
12789 // In the next expressions:
12790 // * x and v (as applicable) are both l-value expressions with scalar type.
12791 // * During the execution of an atomic region, multiple syntactic
12792 // occurrences of x must designate the same storage location.
12793 // * Neither of v and expr (as applicable) may access the storage location
12794 // designated by x.
12795 // * Neither of x and expr (as applicable) may access the storage location
12796 // designated by v.
12797 // * expr is an expression with scalar type.
12798 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12799 // * binop, binop=, ++, and -- are not overloaded operators.
12800 // * The expression x binop expr must be numerically equivalent to x binop
12801 // (expr). This requirement is satisfied if the operators in expr have
12802 // precedence greater than binop, or by using parentheses around expr or
12803 // subexpressions of expr.
12804 // * The expression expr binop x must be numerically equivalent to (expr)
12805 // binop x. This requirement is satisfied if the operators in expr have
12806 // precedence equal to or greater than binop, or by using parentheses around
12807 // expr or subexpressions of expr.
12808 // * For forms that allow multiple occurrences of x, the number of times
12809 // that x is evaluated is unspecified.
12810 if (AtomicKind == OMPC_read) {
12811 enum {
12812 NotAnExpression,
12813 NotAnAssignmentOp,
12814 NotAScalarType,
12815 NotAnLValue,
12816 NoError
12817 } ErrorFound = NoError;
12818 SourceLocation ErrorLoc, NoteLoc;
12819 SourceRange ErrorRange, NoteRange;
12820 // If clause is read:
12821 // v = x;
12822 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
12823 const auto *AtomicBinOp =
12824 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
12825 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12826 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12827 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12828 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12829 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12830 if (!X->isLValue() || !V->isLValue()) {
12831 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12832 ErrorFound = NotAnLValue;
12833 ErrorLoc = AtomicBinOp->getExprLoc();
12834 ErrorRange = AtomicBinOp->getSourceRange();
12835 NoteLoc = NotLValueExpr->getExprLoc();
12836 NoteRange = NotLValueExpr->getSourceRange();
12837 }
12838 } else if (!X->isInstantiationDependent() ||
12839 !V->isInstantiationDependent()) {
12840 const Expr *NotScalarExpr =
12841 (X->isInstantiationDependent() || X->getType()->isScalarType())
12842 ? V
12843 : X;
12844 ErrorFound = NotAScalarType;
12845 ErrorLoc = AtomicBinOp->getExprLoc();
12846 ErrorRange = AtomicBinOp->getSourceRange();
12847 NoteLoc = NotScalarExpr->getExprLoc();
12848 NoteRange = NotScalarExpr->getSourceRange();
12849 }
12850 } else if (!AtomicBody->isInstantiationDependent()) {
12851 ErrorFound = NotAnAssignmentOp;
12852 ErrorLoc = AtomicBody->getExprLoc();
12853 ErrorRange = AtomicBody->getSourceRange();
12854 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12855 : AtomicBody->getExprLoc();
12856 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12857 : AtomicBody->getSourceRange();
12858 }
12859 } else {
12860 ErrorFound = NotAnExpression;
12861 NoteLoc = ErrorLoc = Body->getBeginLoc();
12862 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12863 }
12864 if (ErrorFound != NoError) {
12865 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12866 << ErrorRange;
12867 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12868 << ErrorFound << NoteRange;
12869 return StmtError();
12870 }
12871 if (CurContext->isDependentContext())
12872 V = X = nullptr;
12873 } else if (AtomicKind == OMPC_write) {
12874 enum {
12875 NotAnExpression,
12876 NotAnAssignmentOp,
12877 NotAScalarType,
12878 NotAnLValue,
12879 NoError
12880 } ErrorFound = NoError;
12881 SourceLocation ErrorLoc, NoteLoc;
12882 SourceRange ErrorRange, NoteRange;
12883 // If clause is write:
12884 // x = expr;
12885 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
12886 const auto *AtomicBinOp =
12887 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
12888 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12889 X = AtomicBinOp->getLHS();
12890 E = AtomicBinOp->getRHS();
12891 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12892 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12893 if (!X->isLValue()) {
12894 ErrorFound = NotAnLValue;
12895 ErrorLoc = AtomicBinOp->getExprLoc();
12896 ErrorRange = AtomicBinOp->getSourceRange();
12897 NoteLoc = X->getExprLoc();
12898 NoteRange = X->getSourceRange();
12899 }
12900 } else if (!X->isInstantiationDependent() ||
12901 !E->isInstantiationDependent()) {
12902 const Expr *NotScalarExpr =
12903 (X->isInstantiationDependent() || X->getType()->isScalarType())
12904 ? E
12905 : X;
12906 ErrorFound = NotAScalarType;
12907 ErrorLoc = AtomicBinOp->getExprLoc();
12908 ErrorRange = AtomicBinOp->getSourceRange();
12909 NoteLoc = NotScalarExpr->getExprLoc();
12910 NoteRange = NotScalarExpr->getSourceRange();
12911 }
12912 } else if (!AtomicBody->isInstantiationDependent()) {
12913 ErrorFound = NotAnAssignmentOp;
12914 ErrorLoc = AtomicBody->getExprLoc();
12915 ErrorRange = AtomicBody->getSourceRange();
12916 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12917 : AtomicBody->getExprLoc();
12918 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12919 : AtomicBody->getSourceRange();
12920 }
12921 } else {
12922 ErrorFound = NotAnExpression;
12923 NoteLoc = ErrorLoc = Body->getBeginLoc();
12924 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12925 }
12926 if (ErrorFound != NoError) {
12927 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12928 << ErrorRange;
12929 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12930 << ErrorFound << NoteRange;
12931 return StmtError();
12932 }
12933 if (CurContext->isDependentContext())
12934 E = X = nullptr;
12935 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12936 // If clause is update:
12937 // x++;
12938 // x--;
12939 // ++x;
12940 // --x;
12941 // x binop= expr;
12942 // x = x binop expr;
12943 // x = expr binop x;
12944 OpenMPAtomicUpdateChecker Checker(*this);
12945 if (Checker.checkStatement(
12946 Body,
12947 (AtomicKind == OMPC_update)
12948 ? diag::err_omp_atomic_update_not_expression_statement
12949 : diag::err_omp_atomic_not_expression_statement,
12950 diag::note_omp_atomic_update))
12951 return StmtError();
12952 if (!CurContext->isDependentContext()) {
12953 E = Checker.getExpr();
12954 X = Checker.getX();
12955 UE = Checker.getUpdateExpr();
12956 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12957 }
12958 } else if (AtomicKind == OMPC_capture) {
12959 enum {
12960 NotAnAssignmentOp,
12961 NotACompoundStatement,
12962 NotTwoSubstatements,
12963 NotASpecificExpression,
12964 NoError
12965 } ErrorFound = NoError;
12966 SourceLocation ErrorLoc, NoteLoc;
12967 SourceRange ErrorRange, NoteRange;
12968 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
12969 // If clause is a capture:
12970 // v = x++;
12971 // v = x--;
12972 // v = ++x;
12973 // v = --x;
12974 // v = x binop= expr;
12975 // v = x = x binop expr;
12976 // v = x = expr binop x;
12977 const auto *AtomicBinOp =
12978 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
12979 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12980 V = AtomicBinOp->getLHS();
12981 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12982 OpenMPAtomicUpdateChecker Checker(*this);
12983 if (Checker.checkStatement(
12984 Body, diag::err_omp_atomic_capture_not_expression_statement,
12985 diag::note_omp_atomic_update))
12986 return StmtError();
12987 E = Checker.getExpr();
12988 X = Checker.getX();
12989 UE = Checker.getUpdateExpr();
12990 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12991 IsPostfixUpdate = Checker.isPostfixUpdate();
12992 } else if (!AtomicBody->isInstantiationDependent()) {
12993 ErrorLoc = AtomicBody->getExprLoc();
12994 ErrorRange = AtomicBody->getSourceRange();
12995 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12996 : AtomicBody->getExprLoc();
12997 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12998 : AtomicBody->getSourceRange();
12999 ErrorFound = NotAnAssignmentOp;
13000 }
13001 if (ErrorFound != NoError) {
13002 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
13003 << ErrorRange;
13004 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13005 return StmtError();
13006 }
13007 if (CurContext->isDependentContext())
13008 UE = V = E = X = nullptr;
13009 } else {
13010 // If clause is a capture:
13011 // { v = x; x = expr; }
13012 // { v = x; x++; }
13013 // { v = x; x--; }
13014 // { v = x; ++x; }
13015 // { v = x; --x; }
13016 // { v = x; x binop= expr; }
13017 // { v = x; x = x binop expr; }
13018 // { v = x; x = expr binop x; }
13019 // { x++; v = x; }
13020 // { x--; v = x; }
13021 // { ++x; v = x; }
13022 // { --x; v = x; }
13023 // { x binop= expr; v = x; }
13024 // { x = x binop expr; v = x; }
13025 // { x = expr binop x; v = x; }
13026 if (auto *CS = dyn_cast<CompoundStmt>(Val: Body)) {
13027 // Check that this is { expr1; expr2; }
13028 if (CS->size() == 2) {
13029 Stmt *First = CS->body_front();
13030 Stmt *Second = CS->body_back();
13031 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: First))
13032 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13033 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: Second))
13034 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13035 // Need to find what subexpression is 'v' and what is 'x'.
13036 OpenMPAtomicUpdateChecker Checker(*this);
13037 bool IsUpdateExprFound = !Checker.checkStatement(S: Second);
13038 BinaryOperator *BinOp = nullptr;
13039 if (IsUpdateExprFound) {
13040 BinOp = dyn_cast<BinaryOperator>(Val: First);
13041 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13042 }
13043 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
13044 // { v = x; x++; }
13045 // { v = x; x--; }
13046 // { v = x; ++x; }
13047 // { v = x; --x; }
13048 // { v = x; x binop= expr; }
13049 // { v = x; x = x binop expr; }
13050 // { v = x; x = expr binop x; }
13051 // Check that the first expression has form v = x.
13052 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13053 llvm::FoldingSetNodeID XId, PossibleXId;
13054 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13055 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13056 IsUpdateExprFound = XId == PossibleXId;
13057 if (IsUpdateExprFound) {
13058 V = BinOp->getLHS();
13059 X = Checker.getX();
13060 E = Checker.getExpr();
13061 UE = Checker.getUpdateExpr();
13062 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13063 IsPostfixUpdate = true;
13064 }
13065 }
13066 if (!IsUpdateExprFound) {
13067 IsUpdateExprFound = !Checker.checkStatement(S: First);
13068 BinOp = nullptr;
13069 if (IsUpdateExprFound) {
13070 BinOp = dyn_cast<BinaryOperator>(Val: Second);
13071 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13072 }
13073 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
13074 // { x++; v = x; }
13075 // { x--; v = x; }
13076 // { ++x; v = x; }
13077 // { --x; v = x; }
13078 // { x binop= expr; v = x; }
13079 // { x = x binop expr; v = x; }
13080 // { x = expr binop x; v = x; }
13081 // Check that the second expression has form v = x.
13082 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13083 llvm::FoldingSetNodeID XId, PossibleXId;
13084 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13085 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13086 IsUpdateExprFound = XId == PossibleXId;
13087 if (IsUpdateExprFound) {
13088 V = BinOp->getLHS();
13089 X = Checker.getX();
13090 E = Checker.getExpr();
13091 UE = Checker.getUpdateExpr();
13092 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13093 IsPostfixUpdate = false;
13094 }
13095 }
13096 }
13097 if (!IsUpdateExprFound) {
13098 // { v = x; x = expr; }
13099 auto *FirstExpr = dyn_cast<Expr>(Val: First);
13100 auto *SecondExpr = dyn_cast<Expr>(Val: Second);
13101 if (!FirstExpr || !SecondExpr ||
13102 !(FirstExpr->isInstantiationDependent() ||
13103 SecondExpr->isInstantiationDependent())) {
13104 auto *FirstBinOp = dyn_cast<BinaryOperator>(Val: First);
13105 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13106 ErrorFound = NotAnAssignmentOp;
13107 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13108 : First->getBeginLoc();
13109 NoteRange = ErrorRange = FirstBinOp
13110 ? FirstBinOp->getSourceRange()
13111 : SourceRange(ErrorLoc, ErrorLoc);
13112 } else {
13113 auto *SecondBinOp = dyn_cast<BinaryOperator>(Val: Second);
13114 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13115 ErrorFound = NotAnAssignmentOp;
13116 NoteLoc = ErrorLoc = SecondBinOp
13117 ? SecondBinOp->getOperatorLoc()
13118 : Second->getBeginLoc();
13119 NoteRange = ErrorRange =
13120 SecondBinOp ? SecondBinOp->getSourceRange()
13121 : SourceRange(ErrorLoc, ErrorLoc);
13122 } else {
13123 Expr *PossibleXRHSInFirst =
13124 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13125 Expr *PossibleXLHSInSecond =
13126 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13127 llvm::FoldingSetNodeID X1Id, X2Id;
13128 PossibleXRHSInFirst->Profile(X1Id, Context,
13129 /*Canonical=*/true);
13130 PossibleXLHSInSecond->Profile(X2Id, Context,
13131 /*Canonical=*/true);
13132 IsUpdateExprFound = X1Id == X2Id;
13133 if (IsUpdateExprFound) {
13134 V = FirstBinOp->getLHS();
13135 X = SecondBinOp->getLHS();
13136 E = SecondBinOp->getRHS();
13137 UE = nullptr;
13138 IsXLHSInRHSPart = false;
13139 IsPostfixUpdate = true;
13140 } else {
13141 ErrorFound = NotASpecificExpression;
13142 ErrorLoc = FirstBinOp->getExprLoc();
13143 ErrorRange = FirstBinOp->getSourceRange();
13144 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13145 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13146 }
13147 }
13148 }
13149 }
13150 }
13151 } else {
13152 NoteLoc = ErrorLoc = Body->getBeginLoc();
13153 NoteRange = ErrorRange =
13154 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13155 ErrorFound = NotTwoSubstatements;
13156 }
13157 } else {
13158 NoteLoc = ErrorLoc = Body->getBeginLoc();
13159 NoteRange = ErrorRange =
13160 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13161 ErrorFound = NotACompoundStatement;
13162 }
13163 }
13164 if (ErrorFound != NoError) {
13165 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13166 << ErrorRange;
13167 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13168 return StmtError();
13169 }
13170 if (CurContext->isDependentContext())
13171 UE = V = E = X = nullptr;
13172 } else if (AtomicKind == OMPC_compare) {
13173 if (IsCompareCapture) {
13174 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13175 OpenMPAtomicCompareCaptureChecker Checker(*this);
13176 if (!Checker.checkStmt(S: Body, ErrorInfo)) {
13177 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13178 << ErrorInfo.ErrorRange;
13179 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13180 << ErrorInfo.Error << ErrorInfo.NoteRange;
13181 return StmtError();
13182 }
13183 X = Checker.getX();
13184 E = Checker.getE();
13185 D = Checker.getD();
13186 CE = Checker.getCond();
13187 V = Checker.getV();
13188 R = Checker.getR();
13189 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13190 IsXLHSInRHSPart = Checker.isXBinopExpr();
13191 IsFailOnly = Checker.isFailOnly();
13192 IsPostfixUpdate = Checker.isPostfixUpdate();
13193 } else {
13194 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13195 OpenMPAtomicCompareChecker Checker(*this);
13196 if (!Checker.checkStmt(S: Body, ErrorInfo)) {
13197 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13198 << ErrorInfo.ErrorRange;
13199 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13200 << ErrorInfo.Error << ErrorInfo.NoteRange;
13201 return StmtError();
13202 }
13203 X = Checker.getX();
13204 E = Checker.getE();
13205 D = Checker.getD();
13206 CE = Checker.getCond();
13207 // The weak clause may only appear if the resulting atomic operation is
13208 // an atomic conditional update for which the comparison tests for
13209 // equality. It was not possible to do this check in
13210 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13211 // could not be performed (Clauses are not available).
13212 auto *It = find_if(Range&: Clauses, P: [](OMPClause *C) {
13213 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13214 });
13215 if (It != Clauses.end()) {
13216 auto *Cond = dyn_cast<BinaryOperator>(Val: CE);
13217 if (Cond->getOpcode() != BO_EQ) {
13218 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13219 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13220 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13221 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13222
13223 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13224 << ErrorInfo.ErrorRange;
13225 return StmtError();
13226 }
13227 }
13228 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13229 IsXLHSInRHSPart = Checker.isXBinopExpr();
13230 }
13231 }
13232
13233 setFunctionHasBranchProtectedScope();
13234
13235 return OMPAtomicDirective::Create(
13236 C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
13237 Exprs: {.X: X, .V: V, .R: R, .E: E, .UE: UE, .D: D, .Cond: CE, .IsXLHSInRHSPart: IsXLHSInRHSPart, .IsPostfixUpdate: IsPostfixUpdate, .IsFailOnly: IsFailOnly});
13238}
13239
13240StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
13241 Stmt *AStmt,
13242 SourceLocation StartLoc,
13243 SourceLocation EndLoc) {
13244 if (!AStmt)
13245 return StmtError();
13246
13247 auto *CS = cast<CapturedStmt>(Val: AStmt);
13248 // 1.2.2 OpenMP Language Terminology
13249 // Structured block - An executable statement with a single entry at the
13250 // top and a single exit at the bottom.
13251 // The point of exit cannot be a branch out of the structured block.
13252 // longjmp() and throw() must not violate the entry/exit criteria.
13253 CS->getCapturedDecl()->setNothrow();
13254 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target);
13255 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13256 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
13257 // 1.2.2 OpenMP Language Terminology
13258 // Structured block - An executable statement with a single entry at the
13259 // top and a single exit at the bottom.
13260 // The point of exit cannot be a branch out of the structured block.
13261 // longjmp() and throw() must not violate the entry/exit criteria.
13262 CS->getCapturedDecl()->setNothrow();
13263 }
13264
13265 // OpenMP [2.16, Nesting of Regions]
13266 // If specified, a teams construct must be contained within a target
13267 // construct. That target construct must contain no statements or directives
13268 // outside of the teams construct.
13269 if (DSAStack->hasInnerTeamsRegion()) {
13270 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13271 bool OMPTeamsFound = true;
13272 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13273 auto I = CS->body_begin();
13274 while (I != CS->body_end()) {
13275 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13276 if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind()) ||
13277 OMPTeamsFound) {
13278
13279 OMPTeamsFound = false;
13280 break;
13281 }
13282 ++I;
13283 }
13284 assert(I != CS->body_end() && "Not found statement");
13285 S = *I;
13286 } else {
13287 const auto *OED = dyn_cast<OMPExecutableDirective>(Val: S);
13288 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13289 }
13290 if (!OMPTeamsFound) {
13291 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13292 Diag(DSAStack->getInnerTeamsRegionLoc(),
13293 diag::note_omp_nested_teams_construct_here);
13294 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13295 << isa<OMPExecutableDirective>(S);
13296 return StmtError();
13297 }
13298 }
13299
13300 setFunctionHasBranchProtectedScope();
13301
13302 return OMPTargetDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt);
13303}
13304
13305StmtResult
13306Sema::ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses,
13307 Stmt *AStmt, SourceLocation StartLoc,
13308 SourceLocation EndLoc) {
13309 if (!AStmt)
13310 return StmtError();
13311
13312 auto *CS = cast<CapturedStmt>(Val: AStmt);
13313 // 1.2.2 OpenMP Language Terminology
13314 // Structured block - An executable statement with a single entry at the
13315 // top and a single exit at the bottom.
13316 // The point of exit cannot be a branch out of the structured block.
13317 // longjmp() and throw() must not violate the entry/exit criteria.
13318 CS->getCapturedDecl()->setNothrow();
13319 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel);
13320 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13321 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
13322 // 1.2.2 OpenMP Language Terminology
13323 // Structured block - An executable statement with a single entry at the
13324 // top and a single exit at the bottom.
13325 // The point of exit cannot be a branch out of the structured block.
13326 // longjmp() and throw() must not violate the entry/exit criteria.
13327 CS->getCapturedDecl()->setNothrow();
13328 }
13329
13330 setFunctionHasBranchProtectedScope();
13331
13332 return OMPTargetParallelDirective::Create(
13333 C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
13334 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13335}
13336
13337StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
13338 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13339 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13340 if (!AStmt)
13341 return StmtError();
13342
13343 auto *CS = cast<CapturedStmt>(Val: AStmt);
13344 // 1.2.2 OpenMP Language Terminology
13345 // Structured block - An executable statement with a single entry at the
13346 // top and a single exit at the bottom.
13347 // The point of exit cannot be a branch out of the structured block.
13348 // longjmp() and throw() must not violate the entry/exit criteria.
13349 CS->getCapturedDecl()->setNothrow();
13350 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
13351 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13352 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
13353 // 1.2.2 OpenMP Language Terminology
13354 // Structured block - An executable statement with a single entry at the
13355 // top and a single exit at the bottom.
13356 // The point of exit cannot be a branch out of the structured block.
13357 // longjmp() and throw() must not violate the entry/exit criteria.
13358 CS->getCapturedDecl()->setNothrow();
13359 }
13360
13361 OMPLoopBasedDirective::HelperExprs B;
13362 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13363 // define the nested loops number.
13364 unsigned NestedLoopCount =
13365 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13366 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
13367 VarsWithImplicitDSA, B);
13368 if (NestedLoopCount == 0)
13369 return StmtError();
13370
13371 assert((CurContext->isDependentContext() || B.builtAll()) &&
13372 "omp target parallel for loop exprs were not built");
13373
13374 if (!CurContext->isDependentContext()) {
13375 // Finalize the clauses that need pre-built expressions for CodeGen.
13376 for (OMPClause *C : Clauses) {
13377 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
13378 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
13379 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
13380 DSAStack))
13381 return StmtError();
13382 }
13383 }
13384
13385 setFunctionHasBranchProtectedScope();
13386 return OMPTargetParallelForDirective::Create(
13387 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13388 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13389}
13390
13391/// Check for existence of a map clause in the list of clauses.
13392static bool hasClauses(ArrayRef<OMPClause *> Clauses,
13393 const OpenMPClauseKind K) {
13394 return llvm::any_of(
13395 Range&: Clauses, P: [K](const OMPClause *C) { return C->getClauseKind() == K; });
13396}
13397
13398template <typename... Params>
13399static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
13400 const Params... ClauseTypes) {
13401 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13402}
13403
13404/// Check if the variables in the mapping clause are externally visible.
13405static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
13406 for (const OMPClause *C : Clauses) {
13407 if (auto *TC = dyn_cast<OMPToClause>(Val: C))
13408 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13409 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13410 (VD->isExternallyVisible() &&
13411 VD->getVisibility() != HiddenVisibility);
13412 });
13413 else if (auto *FC = dyn_cast<OMPFromClause>(Val: C))
13414 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13415 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13416 (VD->isExternallyVisible() &&
13417 VD->getVisibility() != HiddenVisibility);
13418 });
13419 }
13420
13421 return true;
13422}
13423
13424StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
13425 Stmt *AStmt,
13426 SourceLocation StartLoc,
13427 SourceLocation EndLoc) {
13428 if (!AStmt)
13429 return StmtError();
13430
13431 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13432
13433 // OpenMP [2.12.2, target data Construct, Restrictions]
13434 // At least one map, use_device_addr or use_device_ptr clause must appear on
13435 // the directive.
13436 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13437 (LangOpts.OpenMP < 50 || !hasClauses(Clauses, OMPC_use_device_addr))) {
13438 StringRef Expected;
13439 if (LangOpts.OpenMP < 50)
13440 Expected = "'map' or 'use_device_ptr'";
13441 else
13442 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13443 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13444 << Expected << getOpenMPDirectiveName(OMPD_target_data);
13445 return StmtError();
13446 }
13447
13448 setFunctionHasBranchProtectedScope();
13449
13450 return OMPTargetDataDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
13451 AssociatedStmt: AStmt);
13452}
13453
13454StmtResult
13455Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses,
13456 SourceLocation StartLoc,
13457 SourceLocation EndLoc, Stmt *AStmt) {
13458 if (!AStmt)
13459 return StmtError();
13460
13461 auto *CS = cast<CapturedStmt>(Val: AStmt);
13462 // 1.2.2 OpenMP Language Terminology
13463 // Structured block - An executable statement with a single entry at the
13464 // top and a single exit at the bottom.
13465 // The point of exit cannot be a branch out of the structured block.
13466 // longjmp() and throw() must not violate the entry/exit criteria.
13467 CS->getCapturedDecl()->setNothrow();
13468 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_enter_data);
13469 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13470 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
13471 // 1.2.2 OpenMP Language Terminology
13472 // Structured block - An executable statement with a single entry at the
13473 // top and a single exit at the bottom.
13474 // The point of exit cannot be a branch out of the structured block.
13475 // longjmp() and throw() must not violate the entry/exit criteria.
13476 CS->getCapturedDecl()->setNothrow();
13477 }
13478
13479 // OpenMP [2.10.2, Restrictions, p. 99]
13480 // At least one map clause must appear on the directive.
13481 if (!hasClauses(Clauses, OMPC_map)) {
13482 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13483 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13484 return StmtError();
13485 }
13486
13487 return OMPTargetEnterDataDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
13488 AssociatedStmt: AStmt);
13489}
13490
13491StmtResult
13492Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses,
13493 SourceLocation StartLoc,
13494 SourceLocation EndLoc, Stmt *AStmt) {
13495 if (!AStmt)
13496 return StmtError();
13497
13498 auto *CS = cast<CapturedStmt>(Val: AStmt);
13499 // 1.2.2 OpenMP Language Terminology
13500 // Structured block - An executable statement with a single entry at the
13501 // top and a single exit at the bottom.
13502 // The point of exit cannot be a branch out of the structured block.
13503 // longjmp() and throw() must not violate the entry/exit criteria.
13504 CS->getCapturedDecl()->setNothrow();
13505 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_exit_data);
13506 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13507 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
13508 // 1.2.2 OpenMP Language Terminology
13509 // Structured block - An executable statement with a single entry at the
13510 // top and a single exit at the bottom.
13511 // The point of exit cannot be a branch out of the structured block.
13512 // longjmp() and throw() must not violate the entry/exit criteria.
13513 CS->getCapturedDecl()->setNothrow();
13514 }
13515
13516 // OpenMP [2.10.3, Restrictions, p. 102]
13517 // At least one map clause must appear on the directive.
13518 if (!hasClauses(Clauses, OMPC_map)) {
13519 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13520 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13521 return StmtError();
13522 }
13523
13524 return OMPTargetExitDataDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
13525 AssociatedStmt: AStmt);
13526}
13527
13528StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses,
13529 SourceLocation StartLoc,
13530 SourceLocation EndLoc,
13531 Stmt *AStmt) {
13532 if (!AStmt)
13533 return StmtError();
13534
13535 auto *CS = cast<CapturedStmt>(Val: AStmt);
13536 // 1.2.2 OpenMP Language Terminology
13537 // Structured block - An executable statement with a single entry at the
13538 // top and a single exit at the bottom.
13539 // The point of exit cannot be a branch out of the structured block.
13540 // longjmp() and throw() must not violate the entry/exit criteria.
13541 CS->getCapturedDecl()->setNothrow();
13542 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_update);
13543 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13544 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
13545 // 1.2.2 OpenMP Language Terminology
13546 // Structured block - An executable statement with a single entry at the
13547 // top and a single exit at the bottom.
13548 // The point of exit cannot be a branch out of the structured block.
13549 // longjmp() and throw() must not violate the entry/exit criteria.
13550 CS->getCapturedDecl()->setNothrow();
13551 }
13552
13553 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13554 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13555 return StmtError();
13556 }
13557
13558 if (!isClauseMappable(Clauses)) {
13559 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13560 return StmtError();
13561 }
13562
13563 return OMPTargetUpdateDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
13564 AssociatedStmt: AStmt);
13565}
13566
13567StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
13568 Stmt *AStmt, SourceLocation StartLoc,
13569 SourceLocation EndLoc) {
13570 if (!AStmt)
13571 return StmtError();
13572
13573 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13574 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13575 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13576
13577 auto *CS = cast<CapturedStmt>(Val: AStmt);
13578 // 1.2.2 OpenMP Language Terminology
13579 // Structured block - An executable statement with a single entry at the
13580 // top and a single exit at the bottom.
13581 // The point of exit cannot be a branch out of the structured block.
13582 // longjmp() and throw() must not violate the entry/exit criteria.
13583 CS->getCapturedDecl()->setNothrow();
13584
13585 setFunctionHasBranchProtectedScope();
13586
13587 DSAStack->setParentTeamsRegionLoc(StartLoc);
13588
13589 return OMPTeamsDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt);
13590}
13591
13592StmtResult
13593Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
13594 SourceLocation EndLoc,
13595 OpenMPDirectiveKind CancelRegion) {
13596 if (DSAStack->isParentNowaitRegion()) {
13597 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13598 return StmtError();
13599 }
13600 if (DSAStack->isParentOrderedRegion()) {
13601 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13602 return StmtError();
13603 }
13604 return OMPCancellationPointDirective::Create(C: Context, StartLoc, EndLoc,
13605 CancelRegion);
13606}
13607
13608StmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses,
13609 SourceLocation StartLoc,
13610 SourceLocation EndLoc,
13611 OpenMPDirectiveKind CancelRegion) {
13612 if (DSAStack->isParentNowaitRegion()) {
13613 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13614 return StmtError();
13615 }
13616 if (DSAStack->isParentOrderedRegion()) {
13617 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13618 return StmtError();
13619 }
13620 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13621 return OMPCancelDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
13622 CancelRegion);
13623}
13624
13625static bool checkReductionClauseWithNogroup(Sema &S,
13626 ArrayRef<OMPClause *> Clauses) {
13627 const OMPClause *ReductionClause = nullptr;
13628 const OMPClause *NogroupClause = nullptr;
13629 for (const OMPClause *C : Clauses) {
13630 if (C->getClauseKind() == OMPC_reduction) {
13631 ReductionClause = C;
13632 if (NogroupClause)
13633 break;
13634 continue;
13635 }
13636 if (C->getClauseKind() == OMPC_nogroup) {
13637 NogroupClause = C;
13638 if (ReductionClause)
13639 break;
13640 continue;
13641 }
13642 }
13643 if (ReductionClause && NogroupClause) {
13644 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13645 << SourceRange(NogroupClause->getBeginLoc(),
13646 NogroupClause->getEndLoc());
13647 return true;
13648 }
13649 return false;
13650}
13651
13652StmtResult Sema::ActOnOpenMPTaskLoopDirective(
13653 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13654 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13655 if (!AStmt)
13656 return StmtError();
13657
13658 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13659 OMPLoopBasedDirective::HelperExprs B;
13660 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13661 // define the nested loops number.
13662 unsigned NestedLoopCount =
13663 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13664 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13665 VarsWithImplicitDSA, B);
13666 if (NestedLoopCount == 0)
13667 return StmtError();
13668
13669 assert((CurContext->isDependentContext() || B.builtAll()) &&
13670 "omp for loop exprs were not built");
13671
13672 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13673 // The grainsize clause and num_tasks clause are mutually exclusive and may
13674 // not appear on the same taskloop directive.
13675 if (checkMutuallyExclusiveClauses(*this, Clauses,
13676 {OMPC_grainsize, OMPC_num_tasks}))
13677 return StmtError();
13678 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13679 // If a reduction clause is present on the taskloop directive, the nogroup
13680 // clause must not be specified.
13681 if (checkReductionClauseWithNogroup(S&: *this, Clauses))
13682 return StmtError();
13683
13684 setFunctionHasBranchProtectedScope();
13685 return OMPTaskLoopDirective::Create(C: Context, StartLoc, EndLoc,
13686 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13687 DSAStack->isCancelRegion());
13688}
13689
13690StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
13691 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13692 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13693 if (!AStmt)
13694 return StmtError();
13695
13696 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13697 OMPLoopBasedDirective::HelperExprs B;
13698 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13699 // define the nested loops number.
13700 unsigned NestedLoopCount =
13701 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13702 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13703 VarsWithImplicitDSA, B);
13704 if (NestedLoopCount == 0)
13705 return StmtError();
13706
13707 assert((CurContext->isDependentContext() || B.builtAll()) &&
13708 "omp for loop exprs were not built");
13709
13710 if (!CurContext->isDependentContext()) {
13711 // Finalize the clauses that need pre-built expressions for CodeGen.
13712 for (OMPClause *C : Clauses) {
13713 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
13714 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
13715 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
13716 DSAStack))
13717 return StmtError();
13718 }
13719 }
13720
13721 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13722 // The grainsize clause and num_tasks clause are mutually exclusive and may
13723 // not appear on the same taskloop directive.
13724 if (checkMutuallyExclusiveClauses(*this, Clauses,
13725 {OMPC_grainsize, OMPC_num_tasks}))
13726 return StmtError();
13727 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13728 // If a reduction clause is present on the taskloop directive, the nogroup
13729 // clause must not be specified.
13730 if (checkReductionClauseWithNogroup(S&: *this, Clauses))
13731 return StmtError();
13732 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
13733 return StmtError();
13734
13735 setFunctionHasBranchProtectedScope();
13736 return OMPTaskLoopSimdDirective::Create(C: Context, StartLoc, EndLoc,
13737 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13738}
13739
13740StmtResult Sema::ActOnOpenMPMasterTaskLoopDirective(
13741 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13742 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13743 if (!AStmt)
13744 return StmtError();
13745
13746 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13747 OMPLoopBasedDirective::HelperExprs B;
13748 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13749 // define the nested loops number.
13750 unsigned NestedLoopCount =
13751 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13752 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13753 VarsWithImplicitDSA, B);
13754 if (NestedLoopCount == 0)
13755 return StmtError();
13756
13757 assert((CurContext->isDependentContext() || B.builtAll()) &&
13758 "omp for loop exprs were not built");
13759
13760 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13761 // The grainsize clause and num_tasks clause are mutually exclusive and may
13762 // not appear on the same taskloop directive.
13763 if (checkMutuallyExclusiveClauses(*this, Clauses,
13764 {OMPC_grainsize, OMPC_num_tasks}))
13765 return StmtError();
13766 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13767 // If a reduction clause is present on the taskloop directive, the nogroup
13768 // clause must not be specified.
13769 if (checkReductionClauseWithNogroup(S&: *this, Clauses))
13770 return StmtError();
13771
13772 setFunctionHasBranchProtectedScope();
13773 return OMPMasterTaskLoopDirective::Create(C: Context, StartLoc, EndLoc,
13774 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13775 DSAStack->isCancelRegion());
13776}
13777
13778StmtResult Sema::ActOnOpenMPMaskedTaskLoopDirective(
13779 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13780 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13781 if (!AStmt)
13782 return StmtError();
13783
13784 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13785 OMPLoopBasedDirective::HelperExprs B;
13786 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13787 // define the nested loops number.
13788 unsigned NestedLoopCount =
13789 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13790 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13791 VarsWithImplicitDSA, B);
13792 if (NestedLoopCount == 0)
13793 return StmtError();
13794
13795 assert((CurContext->isDependentContext() || B.builtAll()) &&
13796 "omp for loop exprs were not built");
13797
13798 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13799 // The grainsize clause and num_tasks clause are mutually exclusive and may
13800 // not appear on the same taskloop directive.
13801 if (checkMutuallyExclusiveClauses(*this, Clauses,
13802 {OMPC_grainsize, OMPC_num_tasks}))
13803 return StmtError();
13804 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13805 // If a reduction clause is present on the taskloop directive, the nogroup
13806 // clause must not be specified.
13807 if (checkReductionClauseWithNogroup(S&: *this, Clauses))
13808 return StmtError();
13809
13810 setFunctionHasBranchProtectedScope();
13811 return OMPMaskedTaskLoopDirective::Create(C: Context, StartLoc, EndLoc,
13812 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13813 DSAStack->isCancelRegion());
13814}
13815
13816StmtResult Sema::ActOnOpenMPMasterTaskLoopSimdDirective(
13817 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13818 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13819 if (!AStmt)
13820 return StmtError();
13821
13822 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13823 OMPLoopBasedDirective::HelperExprs B;
13824 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13825 // define the nested loops number.
13826 unsigned NestedLoopCount =
13827 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13828 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13829 VarsWithImplicitDSA, B);
13830 if (NestedLoopCount == 0)
13831 return StmtError();
13832
13833 assert((CurContext->isDependentContext() || B.builtAll()) &&
13834 "omp for loop exprs were not built");
13835
13836 if (!CurContext->isDependentContext()) {
13837 // Finalize the clauses that need pre-built expressions for CodeGen.
13838 for (OMPClause *C : Clauses) {
13839 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
13840 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
13841 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
13842 DSAStack))
13843 return StmtError();
13844 }
13845 }
13846
13847 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13848 // The grainsize clause and num_tasks clause are mutually exclusive and may
13849 // not appear on the same taskloop directive.
13850 if (checkMutuallyExclusiveClauses(*this, Clauses,
13851 {OMPC_grainsize, OMPC_num_tasks}))
13852 return StmtError();
13853 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13854 // If a reduction clause is present on the taskloop directive, the nogroup
13855 // clause must not be specified.
13856 if (checkReductionClauseWithNogroup(S&: *this, Clauses))
13857 return StmtError();
13858 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
13859 return StmtError();
13860
13861 setFunctionHasBranchProtectedScope();
13862 return OMPMasterTaskLoopSimdDirective::Create(
13863 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13864}
13865
13866StmtResult Sema::ActOnOpenMPMaskedTaskLoopSimdDirective(
13867 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13868 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13869 if (!AStmt)
13870 return StmtError();
13871
13872 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13873 OMPLoopBasedDirective::HelperExprs B;
13874 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13875 // define the nested loops number.
13876 unsigned NestedLoopCount =
13877 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13878 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13879 VarsWithImplicitDSA, B);
13880 if (NestedLoopCount == 0)
13881 return StmtError();
13882
13883 assert((CurContext->isDependentContext() || B.builtAll()) &&
13884 "omp for loop exprs were not built");
13885
13886 if (!CurContext->isDependentContext()) {
13887 // Finalize the clauses that need pre-built expressions for CodeGen.
13888 for (OMPClause *C : Clauses) {
13889 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
13890 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
13891 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
13892 DSAStack))
13893 return StmtError();
13894 }
13895 }
13896
13897 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13898 // The grainsize clause and num_tasks clause are mutually exclusive and may
13899 // not appear on the same taskloop directive.
13900 if (checkMutuallyExclusiveClauses(*this, Clauses,
13901 {OMPC_grainsize, OMPC_num_tasks}))
13902 return StmtError();
13903 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13904 // If a reduction clause is present on the taskloop directive, the nogroup
13905 // clause must not be specified.
13906 if (checkReductionClauseWithNogroup(S&: *this, Clauses))
13907 return StmtError();
13908 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
13909 return StmtError();
13910
13911 setFunctionHasBranchProtectedScope();
13912 return OMPMaskedTaskLoopSimdDirective::Create(
13913 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13914}
13915
13916StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopDirective(
13917 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13918 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13919 if (!AStmt)
13920 return StmtError();
13921
13922 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13923 auto *CS = cast<CapturedStmt>(Val: AStmt);
13924 // 1.2.2 OpenMP Language Terminology
13925 // Structured block - An executable statement with a single entry at the
13926 // top and a single exit at the bottom.
13927 // The point of exit cannot be a branch out of the structured block.
13928 // longjmp() and throw() must not violate the entry/exit criteria.
13929 CS->getCapturedDecl()->setNothrow();
13930 for (int ThisCaptureLevel =
13931 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop);
13932 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13933 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
13934 // 1.2.2 OpenMP Language Terminology
13935 // Structured block - An executable statement with a single entry at the
13936 // top and a single exit at the bottom.
13937 // The point of exit cannot be a branch out of the structured block.
13938 // longjmp() and throw() must not violate the entry/exit criteria.
13939 CS->getCapturedDecl()->setNothrow();
13940 }
13941
13942 OMPLoopBasedDirective::HelperExprs B;
13943 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13944 // define the nested loops number.
13945 unsigned NestedLoopCount = checkOpenMPLoop(
13946 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13947 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13948 VarsWithImplicitDSA, B);
13949 if (NestedLoopCount == 0)
13950 return StmtError();
13951
13952 assert((CurContext->isDependentContext() || B.builtAll()) &&
13953 "omp for loop exprs were not built");
13954
13955 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13956 // The grainsize clause and num_tasks clause are mutually exclusive and may
13957 // not appear on the same taskloop directive.
13958 if (checkMutuallyExclusiveClauses(*this, Clauses,
13959 {OMPC_grainsize, OMPC_num_tasks}))
13960 return StmtError();
13961 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13962 // If a reduction clause is present on the taskloop directive, the nogroup
13963 // clause must not be specified.
13964 if (checkReductionClauseWithNogroup(S&: *this, Clauses))
13965 return StmtError();
13966
13967 setFunctionHasBranchProtectedScope();
13968 return OMPParallelMasterTaskLoopDirective::Create(
13969 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13970 DSAStack->isCancelRegion());
13971}
13972
13973StmtResult Sema::ActOnOpenMPParallelMaskedTaskLoopDirective(
13974 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13975 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13976 if (!AStmt)
13977 return StmtError();
13978
13979 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13980 auto *CS = cast<CapturedStmt>(Val: AStmt);
13981 // 1.2.2 OpenMP Language Terminology
13982 // Structured block - An executable statement with a single entry at the
13983 // top and a single exit at the bottom.
13984 // The point of exit cannot be a branch out of the structured block.
13985 // longjmp() and throw() must not violate the entry/exit criteria.
13986 CS->getCapturedDecl()->setNothrow();
13987 for (int ThisCaptureLevel =
13988 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop);
13989 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13990 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
13991 // 1.2.2 OpenMP Language Terminology
13992 // Structured block - An executable statement with a single entry at the
13993 // top and a single exit at the bottom.
13994 // The point of exit cannot be a branch out of the structured block.
13995 // longjmp() and throw() must not violate the entry/exit criteria.
13996 CS->getCapturedDecl()->setNothrow();
13997 }
13998
13999 OMPLoopBasedDirective::HelperExprs B;
14000 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14001 // define the nested loops number.
14002 unsigned NestedLoopCount = checkOpenMPLoop(
14003 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
14004 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
14005 VarsWithImplicitDSA, B);
14006 if (NestedLoopCount == 0)
14007 return StmtError();
14008
14009 assert((CurContext->isDependentContext() || B.builtAll()) &&
14010 "omp for loop exprs were not built");
14011
14012 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14013 // The grainsize clause and num_tasks clause are mutually exclusive and may
14014 // not appear on the same taskloop directive.
14015 if (checkMutuallyExclusiveClauses(*this, Clauses,
14016 {OMPC_grainsize, OMPC_num_tasks}))
14017 return StmtError();
14018 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14019 // If a reduction clause is present on the taskloop directive, the nogroup
14020 // clause must not be specified.
14021 if (checkReductionClauseWithNogroup(S&: *this, Clauses))
14022 return StmtError();
14023
14024 setFunctionHasBranchProtectedScope();
14025 return OMPParallelMaskedTaskLoopDirective::Create(
14026 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14027 DSAStack->isCancelRegion());
14028}
14029
14030StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
14031 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14032 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14033 if (!AStmt)
14034 return StmtError();
14035
14036 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14037 auto *CS = cast<CapturedStmt>(Val: AStmt);
14038 // 1.2.2 OpenMP Language Terminology
14039 // Structured block - An executable statement with a single entry at the
14040 // top and a single exit at the bottom.
14041 // The point of exit cannot be a branch out of the structured block.
14042 // longjmp() and throw() must not violate the entry/exit criteria.
14043 CS->getCapturedDecl()->setNothrow();
14044 for (int ThisCaptureLevel =
14045 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd);
14046 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14047 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14048 // 1.2.2 OpenMP Language Terminology
14049 // Structured block - An executable statement with a single entry at the
14050 // top and a single exit at the bottom.
14051 // The point of exit cannot be a branch out of the structured block.
14052 // longjmp() and throw() must not violate the entry/exit criteria.
14053 CS->getCapturedDecl()->setNothrow();
14054 }
14055
14056 OMPLoopBasedDirective::HelperExprs B;
14057 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14058 // define the nested loops number.
14059 unsigned NestedLoopCount = checkOpenMPLoop(
14060 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
14061 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
14062 VarsWithImplicitDSA, B);
14063 if (NestedLoopCount == 0)
14064 return StmtError();
14065
14066 assert((CurContext->isDependentContext() || B.builtAll()) &&
14067 "omp for loop exprs were not built");
14068
14069 if (!CurContext->isDependentContext()) {
14070 // Finalize the clauses that need pre-built expressions for CodeGen.
14071 for (OMPClause *C : Clauses) {
14072 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
14073 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
14074 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
14075 DSAStack))
14076 return StmtError();
14077 }
14078 }
14079
14080 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14081 // The grainsize clause and num_tasks clause are mutually exclusive and may
14082 // not appear on the same taskloop directive.
14083 if (checkMutuallyExclusiveClauses(*this, Clauses,
14084 {OMPC_grainsize, OMPC_num_tasks}))
14085 return StmtError();
14086 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14087 // If a reduction clause is present on the taskloop directive, the nogroup
14088 // clause must not be specified.
14089 if (checkReductionClauseWithNogroup(S&: *this, Clauses))
14090 return StmtError();
14091 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
14092 return StmtError();
14093
14094 setFunctionHasBranchProtectedScope();
14095 return OMPParallelMasterTaskLoopSimdDirective::Create(
14096 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14097}
14098
14099StmtResult Sema::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
14100 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14101 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14102 if (!AStmt)
14103 return StmtError();
14104
14105 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14106 auto *CS = cast<CapturedStmt>(Val: AStmt);
14107 // 1.2.2 OpenMP Language Terminology
14108 // Structured block - An executable statement with a single entry at the
14109 // top and a single exit at the bottom.
14110 // The point of exit cannot be a branch out of the structured block.
14111 // longjmp() and throw() must not violate the entry/exit criteria.
14112 CS->getCapturedDecl()->setNothrow();
14113 for (int ThisCaptureLevel =
14114 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop_simd);
14115 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14116 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14117 // 1.2.2 OpenMP Language Terminology
14118 // Structured block - An executable statement with a single entry at the
14119 // top and a single exit at the bottom.
14120 // The point of exit cannot be a branch out of the structured block.
14121 // longjmp() and throw() must not violate the entry/exit criteria.
14122 CS->getCapturedDecl()->setNothrow();
14123 }
14124
14125 OMPLoopBasedDirective::HelperExprs B;
14126 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14127 // define the nested loops number.
14128 unsigned NestedLoopCount = checkOpenMPLoop(
14129 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
14130 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
14131 VarsWithImplicitDSA, B);
14132 if (NestedLoopCount == 0)
14133 return StmtError();
14134
14135 assert((CurContext->isDependentContext() || B.builtAll()) &&
14136 "omp for loop exprs were not built");
14137
14138 if (!CurContext->isDependentContext()) {
14139 // Finalize the clauses that need pre-built expressions for CodeGen.
14140 for (OMPClause *C : Clauses) {
14141 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
14142 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
14143 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
14144 DSAStack))
14145 return StmtError();
14146 }
14147 }
14148
14149 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14150 // The grainsize clause and num_tasks clause are mutually exclusive and may
14151 // not appear on the same taskloop directive.
14152 if (checkMutuallyExclusiveClauses(*this, Clauses,
14153 {OMPC_grainsize, OMPC_num_tasks}))
14154 return StmtError();
14155 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14156 // If a reduction clause is present on the taskloop directive, the nogroup
14157 // clause must not be specified.
14158 if (checkReductionClauseWithNogroup(S&: *this, Clauses))
14159 return StmtError();
14160 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
14161 return StmtError();
14162
14163 setFunctionHasBranchProtectedScope();
14164 return OMPParallelMaskedTaskLoopSimdDirective::Create(
14165 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14166}
14167
14168StmtResult Sema::ActOnOpenMPDistributeDirective(
14169 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14170 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14171 if (!AStmt)
14172 return StmtError();
14173
14174 if (!checkLastPrivateForMappedDirectives(Clauses))
14175 return StmtError();
14176
14177 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14178 OMPLoopBasedDirective::HelperExprs B;
14179 // In presence of clause 'collapse' with number of loops, it will
14180 // define the nested loops number.
14181 unsigned NestedLoopCount =
14182 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
14183 nullptr /*ordered not a clause on distribute*/, AStmt,
14184 *this, *DSAStack, VarsWithImplicitDSA, B);
14185 if (NestedLoopCount == 0)
14186 return StmtError();
14187
14188 assert((CurContext->isDependentContext() || B.builtAll()) &&
14189 "omp for loop exprs were not built");
14190
14191 setFunctionHasBranchProtectedScope();
14192 auto *DistributeDirective = OMPDistributeDirective::Create(
14193 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14194 DSAStack->getMappedDirective());
14195 return DistributeDirective;
14196}
14197
14198StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
14199 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14200 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14201 if (!AStmt)
14202 return StmtError();
14203
14204 auto *CS = cast<CapturedStmt>(Val: AStmt);
14205 // 1.2.2 OpenMP Language Terminology
14206 // Structured block - An executable statement with a single entry at the
14207 // top and a single exit at the bottom.
14208 // The point of exit cannot be a branch out of the structured block.
14209 // longjmp() and throw() must not violate the entry/exit criteria.
14210 CS->getCapturedDecl()->setNothrow();
14211 for (int ThisCaptureLevel =
14212 getOpenMPCaptureLevels(OMPD_distribute_parallel_for);
14213 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14214 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14215 // 1.2.2 OpenMP Language Terminology
14216 // Structured block - An executable statement with a single entry at the
14217 // top and a single exit at the bottom.
14218 // The point of exit cannot be a branch out of the structured block.
14219 // longjmp() and throw() must not violate the entry/exit criteria.
14220 CS->getCapturedDecl()->setNothrow();
14221 }
14222
14223 OMPLoopBasedDirective::HelperExprs B;
14224 // In presence of clause 'collapse' with number of loops, it will
14225 // define the nested loops number.
14226 unsigned NestedLoopCount = checkOpenMPLoop(
14227 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14228 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14229 VarsWithImplicitDSA, B);
14230 if (NestedLoopCount == 0)
14231 return StmtError();
14232
14233 assert((CurContext->isDependentContext() || B.builtAll()) &&
14234 "omp for loop exprs were not built");
14235
14236 setFunctionHasBranchProtectedScope();
14237 return OMPDistributeParallelForDirective::Create(
14238 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14239 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14240}
14241
14242StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
14243 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14244 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14245 if (!AStmt)
14246 return StmtError();
14247
14248 auto *CS = cast<CapturedStmt>(Val: AStmt);
14249 // 1.2.2 OpenMP Language Terminology
14250 // Structured block - An executable statement with a single entry at the
14251 // top and a single exit at the bottom.
14252 // The point of exit cannot be a branch out of the structured block.
14253 // longjmp() and throw() must not violate the entry/exit criteria.
14254 CS->getCapturedDecl()->setNothrow();
14255 for (int ThisCaptureLevel =
14256 getOpenMPCaptureLevels(OMPD_distribute_parallel_for_simd);
14257 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14258 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14259 // 1.2.2 OpenMP Language Terminology
14260 // Structured block - An executable statement with a single entry at the
14261 // top and a single exit at the bottom.
14262 // The point of exit cannot be a branch out of the structured block.
14263 // longjmp() and throw() must not violate the entry/exit criteria.
14264 CS->getCapturedDecl()->setNothrow();
14265 }
14266
14267 OMPLoopBasedDirective::HelperExprs B;
14268 // In presence of clause 'collapse' with number of loops, it will
14269 // define the nested loops number.
14270 unsigned NestedLoopCount = checkOpenMPLoop(
14271 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14272 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14273 VarsWithImplicitDSA, B);
14274 if (NestedLoopCount == 0)
14275 return StmtError();
14276
14277 assert((CurContext->isDependentContext() || B.builtAll()) &&
14278 "omp for loop exprs were not built");
14279
14280 if (!CurContext->isDependentContext()) {
14281 // Finalize the clauses that need pre-built expressions for CodeGen.
14282 for (OMPClause *C : Clauses) {
14283 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
14284 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
14285 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
14286 DSAStack))
14287 return StmtError();
14288 }
14289 }
14290
14291 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
14292 return StmtError();
14293
14294 setFunctionHasBranchProtectedScope();
14295 return OMPDistributeParallelForSimdDirective::Create(
14296 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14297}
14298
14299StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
14300 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14301 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14302 if (!AStmt)
14303 return StmtError();
14304
14305 auto *CS = cast<CapturedStmt>(Val: AStmt);
14306 // 1.2.2 OpenMP Language Terminology
14307 // Structured block - An executable statement with a single entry at the
14308 // top and a single exit at the bottom.
14309 // The point of exit cannot be a branch out of the structured block.
14310 // longjmp() and throw() must not violate the entry/exit criteria.
14311 CS->getCapturedDecl()->setNothrow();
14312 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_distribute_simd);
14313 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14314 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14315 // 1.2.2 OpenMP Language Terminology
14316 // Structured block - An executable statement with a single entry at the
14317 // top and a single exit at the bottom.
14318 // The point of exit cannot be a branch out of the structured block.
14319 // longjmp() and throw() must not violate the entry/exit criteria.
14320 CS->getCapturedDecl()->setNothrow();
14321 }
14322
14323 OMPLoopBasedDirective::HelperExprs B;
14324 // In presence of clause 'collapse' with number of loops, it will
14325 // define the nested loops number.
14326 unsigned NestedLoopCount =
14327 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14328 nullptr /*ordered not a clause on distribute*/, CS, *this,
14329 *DSAStack, VarsWithImplicitDSA, B);
14330 if (NestedLoopCount == 0)
14331 return StmtError();
14332
14333 assert((CurContext->isDependentContext() || B.builtAll()) &&
14334 "omp for loop exprs were not built");
14335
14336 if (!CurContext->isDependentContext()) {
14337 // Finalize the clauses that need pre-built expressions for CodeGen.
14338 for (OMPClause *C : Clauses) {
14339 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
14340 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
14341 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
14342 DSAStack))
14343 return StmtError();
14344 }
14345 }
14346
14347 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
14348 return StmtError();
14349
14350 setFunctionHasBranchProtectedScope();
14351 return OMPDistributeSimdDirective::Create(C: Context, StartLoc, EndLoc,
14352 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14353}
14354
14355StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
14356 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14357 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14358 if (!AStmt)
14359 return StmtError();
14360
14361 auto *CS = cast<CapturedStmt>(Val: AStmt);
14362 // 1.2.2 OpenMP Language Terminology
14363 // Structured block - An executable statement with a single entry at the
14364 // top and a single exit at the bottom.
14365 // The point of exit cannot be a branch out of the structured block.
14366 // longjmp() and throw() must not violate the entry/exit criteria.
14367 CS->getCapturedDecl()->setNothrow();
14368 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
14369 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14370 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14371 // 1.2.2 OpenMP Language Terminology
14372 // Structured block - An executable statement with a single entry at the
14373 // top and a single exit at the bottom.
14374 // The point of exit cannot be a branch out of the structured block.
14375 // longjmp() and throw() must not violate the entry/exit criteria.
14376 CS->getCapturedDecl()->setNothrow();
14377 }
14378
14379 OMPLoopBasedDirective::HelperExprs B;
14380 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14381 // define the nested loops number.
14382 unsigned NestedLoopCount = checkOpenMPLoop(
14383 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14384 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack, VarsWithImplicitDSA,
14385 B);
14386 if (NestedLoopCount == 0)
14387 return StmtError();
14388
14389 assert((CurContext->isDependentContext() || B.builtAll()) &&
14390 "omp target parallel for simd loop exprs were not built");
14391
14392 if (!CurContext->isDependentContext()) {
14393 // Finalize the clauses that need pre-built expressions for CodeGen.
14394 for (OMPClause *C : Clauses) {
14395 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
14396 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
14397 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
14398 DSAStack))
14399 return StmtError();
14400 }
14401 }
14402 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
14403 return StmtError();
14404
14405 setFunctionHasBranchProtectedScope();
14406 return OMPTargetParallelForSimdDirective::Create(
14407 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14408}
14409
14410StmtResult Sema::ActOnOpenMPTargetSimdDirective(
14411 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14412 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14413 if (!AStmt)
14414 return StmtError();
14415
14416 auto *CS = cast<CapturedStmt>(Val: AStmt);
14417 // 1.2.2 OpenMP Language Terminology
14418 // Structured block - An executable statement with a single entry at the
14419 // top and a single exit at the bottom.
14420 // The point of exit cannot be a branch out of the structured block.
14421 // longjmp() and throw() must not violate the entry/exit criteria.
14422 CS->getCapturedDecl()->setNothrow();
14423 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_simd);
14424 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14425 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14426 // 1.2.2 OpenMP Language Terminology
14427 // Structured block - An executable statement with a single entry at the
14428 // top and a single exit at the bottom.
14429 // The point of exit cannot be a branch out of the structured block.
14430 // longjmp() and throw() must not violate the entry/exit criteria.
14431 CS->getCapturedDecl()->setNothrow();
14432 }
14433
14434 OMPLoopBasedDirective::HelperExprs B;
14435 // In presence of clause 'collapse' with number of loops, it will define the
14436 // nested loops number.
14437 unsigned NestedLoopCount =
14438 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14439 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
14440 VarsWithImplicitDSA, B);
14441 if (NestedLoopCount == 0)
14442 return StmtError();
14443
14444 assert((CurContext->isDependentContext() || B.builtAll()) &&
14445 "omp target simd loop exprs were not built");
14446
14447 if (!CurContext->isDependentContext()) {
14448 // Finalize the clauses that need pre-built expressions for CodeGen.
14449 for (OMPClause *C : Clauses) {
14450 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
14451 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
14452 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
14453 DSAStack))
14454 return StmtError();
14455 }
14456 }
14457
14458 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
14459 return StmtError();
14460
14461 setFunctionHasBranchProtectedScope();
14462 return OMPTargetSimdDirective::Create(C: Context, StartLoc, EndLoc,
14463 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14464}
14465
14466StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
14467 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14468 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14469 if (!AStmt)
14470 return StmtError();
14471
14472 auto *CS = cast<CapturedStmt>(Val: AStmt);
14473 // 1.2.2 OpenMP Language Terminology
14474 // Structured block - An executable statement with a single entry at the
14475 // top and a single exit at the bottom.
14476 // The point of exit cannot be a branch out of the structured block.
14477 // longjmp() and throw() must not violate the entry/exit criteria.
14478 CS->getCapturedDecl()->setNothrow();
14479 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_distribute);
14480 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14481 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14482 // 1.2.2 OpenMP Language Terminology
14483 // Structured block - An executable statement with a single entry at the
14484 // top and a single exit at the bottom.
14485 // The point of exit cannot be a branch out of the structured block.
14486 // longjmp() and throw() must not violate the entry/exit criteria.
14487 CS->getCapturedDecl()->setNothrow();
14488 }
14489
14490 OMPLoopBasedDirective::HelperExprs B;
14491 // In presence of clause 'collapse' with number of loops, it will
14492 // define the nested loops number.
14493 unsigned NestedLoopCount =
14494 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14495 nullptr /*ordered not a clause on distribute*/, CS, *this,
14496 *DSAStack, VarsWithImplicitDSA, B);
14497 if (NestedLoopCount == 0)
14498 return StmtError();
14499
14500 assert((CurContext->isDependentContext() || B.builtAll()) &&
14501 "omp teams distribute loop exprs were not built");
14502
14503 setFunctionHasBranchProtectedScope();
14504
14505 DSAStack->setParentTeamsRegionLoc(StartLoc);
14506
14507 return OMPTeamsDistributeDirective::Create(
14508 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14509}
14510
14511StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
14512 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14513 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14514 if (!AStmt)
14515 return StmtError();
14516
14517 auto *CS = cast<CapturedStmt>(Val: AStmt);
14518 // 1.2.2 OpenMP Language Terminology
14519 // Structured block - An executable statement with a single entry at the
14520 // top and a single exit at the bottom.
14521 // The point of exit cannot be a branch out of the structured block.
14522 // longjmp() and throw() must not violate the entry/exit criteria.
14523 CS->getCapturedDecl()->setNothrow();
14524 for (int ThisCaptureLevel =
14525 getOpenMPCaptureLevels(OMPD_teams_distribute_simd);
14526 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14527 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14528 // 1.2.2 OpenMP Language Terminology
14529 // Structured block - An executable statement with a single entry at the
14530 // top and a single exit at the bottom.
14531 // The point of exit cannot be a branch out of the structured block.
14532 // longjmp() and throw() must not violate the entry/exit criteria.
14533 CS->getCapturedDecl()->setNothrow();
14534 }
14535
14536 OMPLoopBasedDirective::HelperExprs B;
14537 // In presence of clause 'collapse' with number of loops, it will
14538 // define the nested loops number.
14539 unsigned NestedLoopCount = checkOpenMPLoop(
14540 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14541 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14542 VarsWithImplicitDSA, B);
14543
14544 if (NestedLoopCount == 0)
14545 return StmtError();
14546
14547 assert((CurContext->isDependentContext() || B.builtAll()) &&
14548 "omp teams distribute simd loop exprs were not built");
14549
14550 if (!CurContext->isDependentContext()) {
14551 // Finalize the clauses that need pre-built expressions for CodeGen.
14552 for (OMPClause *C : Clauses) {
14553 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
14554 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
14555 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
14556 DSAStack))
14557 return StmtError();
14558 }
14559 }
14560
14561 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
14562 return StmtError();
14563
14564 setFunctionHasBranchProtectedScope();
14565
14566 DSAStack->setParentTeamsRegionLoc(StartLoc);
14567
14568 return OMPTeamsDistributeSimdDirective::Create(
14569 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14570}
14571
14572StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
14573 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14574 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14575 if (!AStmt)
14576 return StmtError();
14577
14578 auto *CS = cast<CapturedStmt>(Val: AStmt);
14579 // 1.2.2 OpenMP Language Terminology
14580 // Structured block - An executable statement with a single entry at the
14581 // top and a single exit at the bottom.
14582 // The point of exit cannot be a branch out of the structured block.
14583 // longjmp() and throw() must not violate the entry/exit criteria.
14584 CS->getCapturedDecl()->setNothrow();
14585
14586 for (int ThisCaptureLevel =
14587 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd);
14588 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14589 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14590 // 1.2.2 OpenMP Language Terminology
14591 // Structured block - An executable statement with a single entry at the
14592 // top and a single exit at the bottom.
14593 // The point of exit cannot be a branch out of the structured block.
14594 // longjmp() and throw() must not violate the entry/exit criteria.
14595 CS->getCapturedDecl()->setNothrow();
14596 }
14597
14598 OMPLoopBasedDirective::HelperExprs B;
14599 // In presence of clause 'collapse' with number of loops, it will
14600 // define the nested loops number.
14601 unsigned NestedLoopCount = checkOpenMPLoop(
14602 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14603 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14604 VarsWithImplicitDSA, B);
14605
14606 if (NestedLoopCount == 0)
14607 return StmtError();
14608
14609 assert((CurContext->isDependentContext() || B.builtAll()) &&
14610 "omp for loop exprs were not built");
14611
14612 if (!CurContext->isDependentContext()) {
14613 // Finalize the clauses that need pre-built expressions for CodeGen.
14614 for (OMPClause *C : Clauses) {
14615 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
14616 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
14617 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
14618 DSAStack))
14619 return StmtError();
14620 }
14621 }
14622
14623 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
14624 return StmtError();
14625
14626 setFunctionHasBranchProtectedScope();
14627
14628 DSAStack->setParentTeamsRegionLoc(StartLoc);
14629
14630 return OMPTeamsDistributeParallelForSimdDirective::Create(
14631 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14632}
14633
14634StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
14635 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14636 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14637 if (!AStmt)
14638 return StmtError();
14639
14640 auto *CS = cast<CapturedStmt>(Val: AStmt);
14641 // 1.2.2 OpenMP Language Terminology
14642 // Structured block - An executable statement with a single entry at the
14643 // top and a single exit at the bottom.
14644 // The point of exit cannot be a branch out of the structured block.
14645 // longjmp() and throw() must not violate the entry/exit criteria.
14646 CS->getCapturedDecl()->setNothrow();
14647
14648 for (int ThisCaptureLevel =
14649 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for);
14650 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14651 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14652 // 1.2.2 OpenMP Language Terminology
14653 // Structured block - An executable statement with a single entry at the
14654 // top and a single exit at the bottom.
14655 // The point of exit cannot be a branch out of the structured block.
14656 // longjmp() and throw() must not violate the entry/exit criteria.
14657 CS->getCapturedDecl()->setNothrow();
14658 }
14659
14660 OMPLoopBasedDirective::HelperExprs B;
14661 // In presence of clause 'collapse' with number of loops, it will
14662 // define the nested loops number.
14663 unsigned NestedLoopCount = checkOpenMPLoop(
14664 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14665 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14666 VarsWithImplicitDSA, B);
14667
14668 if (NestedLoopCount == 0)
14669 return StmtError();
14670
14671 assert((CurContext->isDependentContext() || B.builtAll()) &&
14672 "omp for loop exprs were not built");
14673
14674 setFunctionHasBranchProtectedScope();
14675
14676 DSAStack->setParentTeamsRegionLoc(StartLoc);
14677
14678 return OMPTeamsDistributeParallelForDirective::Create(
14679 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14680 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14681}
14682
14683StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
14684 Stmt *AStmt,
14685 SourceLocation StartLoc,
14686 SourceLocation EndLoc) {
14687 if (!AStmt)
14688 return StmtError();
14689
14690 auto *CS = cast<CapturedStmt>(Val: AStmt);
14691 // 1.2.2 OpenMP Language Terminology
14692 // Structured block - An executable statement with a single entry at the
14693 // top and a single exit at the bottom.
14694 // The point of exit cannot be a branch out of the structured block.
14695 // longjmp() and throw() must not violate the entry/exit criteria.
14696 CS->getCapturedDecl()->setNothrow();
14697
14698 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams);
14699 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14700 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14701 // 1.2.2 OpenMP Language Terminology
14702 // Structured block - An executable statement with a single entry at the
14703 // top and a single exit at the bottom.
14704 // The point of exit cannot be a branch out of the structured block.
14705 // longjmp() and throw() must not violate the entry/exit criteria.
14706 CS->getCapturedDecl()->setNothrow();
14707 }
14708 setFunctionHasBranchProtectedScope();
14709
14710 const OMPClause *BareClause = nullptr;
14711 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14712 hasClauses(Clauses, OMPC_thread_limit);
14713 bool HasBareClause = llvm::any_of(Range&: Clauses, P: [&](const OMPClause *C) {
14714 BareClause = C;
14715 return C->getClauseKind() == OMPC_ompx_bare;
14716 });
14717
14718 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14719 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14720 return StmtError();
14721 }
14722
14723 return OMPTargetTeamsDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
14724 AssociatedStmt: AStmt);
14725}
14726
14727StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
14728 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14729 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14730 if (!AStmt)
14731 return StmtError();
14732
14733 auto *CS = cast<CapturedStmt>(Val: AStmt);
14734 // 1.2.2 OpenMP Language Terminology
14735 // Structured block - An executable statement with a single entry at the
14736 // top and a single exit at the bottom.
14737 // The point of exit cannot be a branch out of the structured block.
14738 // longjmp() and throw() must not violate the entry/exit criteria.
14739 CS->getCapturedDecl()->setNothrow();
14740 for (int ThisCaptureLevel =
14741 getOpenMPCaptureLevels(OMPD_target_teams_distribute);
14742 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14743 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14744 // 1.2.2 OpenMP Language Terminology
14745 // Structured block - An executable statement with a single entry at the
14746 // top and a single exit at the bottom.
14747 // The point of exit cannot be a branch out of the structured block.
14748 // longjmp() and throw() must not violate the entry/exit criteria.
14749 CS->getCapturedDecl()->setNothrow();
14750 }
14751
14752 OMPLoopBasedDirective::HelperExprs B;
14753 // In presence of clause 'collapse' with number of loops, it will
14754 // define the nested loops number.
14755 unsigned NestedLoopCount = checkOpenMPLoop(
14756 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14757 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14758 VarsWithImplicitDSA, B);
14759 if (NestedLoopCount == 0)
14760 return StmtError();
14761
14762 assert((CurContext->isDependentContext() || B.builtAll()) &&
14763 "omp target teams distribute loop exprs were not built");
14764
14765 setFunctionHasBranchProtectedScope();
14766 return OMPTargetTeamsDistributeDirective::Create(
14767 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14768}
14769
14770StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14771 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14772 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14773 if (!AStmt)
14774 return StmtError();
14775
14776 auto *CS = cast<CapturedStmt>(Val: AStmt);
14777 // 1.2.2 OpenMP Language Terminology
14778 // Structured block - An executable statement with a single entry at the
14779 // top and a single exit at the bottom.
14780 // The point of exit cannot be a branch out of the structured block.
14781 // longjmp() and throw() must not violate the entry/exit criteria.
14782 CS->getCapturedDecl()->setNothrow();
14783 for (int ThisCaptureLevel =
14784 getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for);
14785 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14786 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14787 // 1.2.2 OpenMP Language Terminology
14788 // Structured block - An executable statement with a single entry at the
14789 // top and a single exit at the bottom.
14790 // The point of exit cannot be a branch out of the structured block.
14791 // longjmp() and throw() must not violate the entry/exit criteria.
14792 CS->getCapturedDecl()->setNothrow();
14793 }
14794
14795 OMPLoopBasedDirective::HelperExprs B;
14796 // In presence of clause 'collapse' with number of loops, it will
14797 // define the nested loops number.
14798 unsigned NestedLoopCount = checkOpenMPLoop(
14799 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14800 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14801 VarsWithImplicitDSA, B);
14802 if (NestedLoopCount == 0)
14803 return StmtError();
14804
14805 assert((CurContext->isDependentContext() || B.builtAll()) &&
14806 "omp target teams distribute parallel for loop exprs were not built");
14807
14808 if (!CurContext->isDependentContext()) {
14809 // Finalize the clauses that need pre-built expressions for CodeGen.
14810 for (OMPClause *C : Clauses) {
14811 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
14812 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
14813 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
14814 DSAStack))
14815 return StmtError();
14816 }
14817 }
14818
14819 setFunctionHasBranchProtectedScope();
14820 return OMPTargetTeamsDistributeParallelForDirective::Create(
14821 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14822 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14823}
14824
14825StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14826 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14827 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14828 if (!AStmt)
14829 return StmtError();
14830
14831 auto *CS = cast<CapturedStmt>(Val: AStmt);
14832 // 1.2.2 OpenMP Language Terminology
14833 // Structured block - An executable statement with a single entry at the
14834 // top and a single exit at the bottom.
14835 // The point of exit cannot be a branch out of the structured block.
14836 // longjmp() and throw() must not violate the entry/exit criteria.
14837 CS->getCapturedDecl()->setNothrow();
14838 for (int ThisCaptureLevel = getOpenMPCaptureLevels(
14839 OMPD_target_teams_distribute_parallel_for_simd);
14840 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14841 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14842 // 1.2.2 OpenMP Language Terminology
14843 // Structured block - An executable statement with a single entry at the
14844 // top and a single exit at the bottom.
14845 // The point of exit cannot be a branch out of the structured block.
14846 // longjmp() and throw() must not violate the entry/exit criteria.
14847 CS->getCapturedDecl()->setNothrow();
14848 }
14849
14850 OMPLoopBasedDirective::HelperExprs B;
14851 // In presence of clause 'collapse' with number of loops, it will
14852 // define the nested loops number.
14853 unsigned NestedLoopCount =
14854 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14855 getCollapseNumberExpr(Clauses),
14856 nullptr /*ordered not a clause on distribute*/, CS, *this,
14857 *DSAStack, VarsWithImplicitDSA, B);
14858 if (NestedLoopCount == 0)
14859 return StmtError();
14860
14861 assert((CurContext->isDependentContext() || B.builtAll()) &&
14862 "omp target teams distribute parallel for simd loop exprs were not "
14863 "built");
14864
14865 if (!CurContext->isDependentContext()) {
14866 // Finalize the clauses that need pre-built expressions for CodeGen.
14867 for (OMPClause *C : Clauses) {
14868 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
14869 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
14870 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
14871 DSAStack))
14872 return StmtError();
14873 }
14874 }
14875
14876 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
14877 return StmtError();
14878
14879 setFunctionHasBranchProtectedScope();
14880 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14881 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14882}
14883
14884StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14885 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14886 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14887 if (!AStmt)
14888 return StmtError();
14889
14890 auto *CS = cast<CapturedStmt>(Val: AStmt);
14891 // 1.2.2 OpenMP Language Terminology
14892 // Structured block - An executable statement with a single entry at the
14893 // top and a single exit at the bottom.
14894 // The point of exit cannot be a branch out of the structured block.
14895 // longjmp() and throw() must not violate the entry/exit criteria.
14896 CS->getCapturedDecl()->setNothrow();
14897 for (int ThisCaptureLevel =
14898 getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd);
14899 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14900 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
14901 // 1.2.2 OpenMP Language Terminology
14902 // Structured block - An executable statement with a single entry at the
14903 // top and a single exit at the bottom.
14904 // The point of exit cannot be a branch out of the structured block.
14905 // longjmp() and throw() must not violate the entry/exit criteria.
14906 CS->getCapturedDecl()->setNothrow();
14907 }
14908
14909 OMPLoopBasedDirective::HelperExprs B;
14910 // In presence of clause 'collapse' with number of loops, it will
14911 // define the nested loops number.
14912 unsigned NestedLoopCount = checkOpenMPLoop(
14913 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14914 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14915 VarsWithImplicitDSA, B);
14916 if (NestedLoopCount == 0)
14917 return StmtError();
14918
14919 assert((CurContext->isDependentContext() || B.builtAll()) &&
14920 "omp target teams distribute simd loop exprs were not built");
14921
14922 if (!CurContext->isDependentContext()) {
14923 // Finalize the clauses that need pre-built expressions for CodeGen.
14924 for (OMPClause *C : Clauses) {
14925 if (auto *LC = dyn_cast<OMPLinearClause>(Val: C))
14926 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
14927 NumIterations: B.NumIterations, SemaRef&: *this, S: CurScope,
14928 DSAStack))
14929 return StmtError();
14930 }
14931 }
14932
14933 if (checkSimdlenSafelenSpecified(S&: *this, Clauses))
14934 return StmtError();
14935
14936 setFunctionHasBranchProtectedScope();
14937 return OMPTargetTeamsDistributeSimdDirective::Create(
14938 C: Context, StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14939}
14940
14941bool Sema::checkTransformableLoopNest(
14942 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14943 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14944 Stmt *&Body,
14945 SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>>
14946 &OriginalInits) {
14947 OriginalInits.emplace_back();
14948 bool Result = OMPLoopBasedDirective::doForAllLoops(
14949 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14950 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14951 Stmt *CurStmt) {
14952 VarsWithInheritedDSAType TmpDSA;
14953 unsigned SingleNumLoops =
14954 checkOpenMPLoop(DKind: Kind, CollapseLoopCountExpr: nullptr, OrderedLoopCountExpr: nullptr, AStmt: CurStmt, SemaRef&: *this, DSA&: *DSAStack,
14955 VarsWithImplicitDSA&: TmpDSA, Built&: LoopHelpers[Cnt]);
14956 if (SingleNumLoops == 0)
14957 return true;
14958 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14959 if (auto *For = dyn_cast<ForStmt>(Val: CurStmt)) {
14960 OriginalInits.back().push_back(Elt: For->getInit());
14961 Body = For->getBody();
14962 } else {
14963 assert(isa<CXXForRangeStmt>(CurStmt) &&
14964 "Expected canonical for or range-based for loops.");
14965 auto *CXXFor = cast<CXXForRangeStmt>(Val: CurStmt);
14966 OriginalInits.back().push_back(Elt: CXXFor->getBeginStmt());
14967 Body = CXXFor->getBody();
14968 }
14969 OriginalInits.emplace_back();
14970 return false;
14971 },
14972 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14973 Stmt *DependentPreInits;
14974 if (auto *Dir = dyn_cast<OMPTileDirective>(Val: Transform))
14975 DependentPreInits = Dir->getPreInits();
14976 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Val: Transform))
14977 DependentPreInits = Dir->getPreInits();
14978 else
14979 llvm_unreachable("Unhandled loop transformation");
14980 if (!DependentPreInits)
14981 return;
14982 llvm::append_range(C&: OriginalInits.back(),
14983 R: cast<DeclStmt>(Val: DependentPreInits)->getDeclGroup());
14984 });
14985 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14986 OriginalInits.pop_back();
14987 return Result;
14988}
14989
14990StmtResult Sema::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
14991 Stmt *AStmt, SourceLocation StartLoc,
14992 SourceLocation EndLoc) {
14993 auto SizesClauses =
14994 OMPExecutableDirective::getClausesOfKind<OMPSizesClause>(Clauses);
14995 if (SizesClauses.empty()) {
14996 // A missing 'sizes' clause is already reported by the parser.
14997 return StmtError();
14998 }
14999 const OMPSizesClause *SizesClause = *SizesClauses.begin();
15000 unsigned NumLoops = SizesClause->getNumSizes();
15001
15002 // Empty statement should only be possible if there already was an error.
15003 if (!AStmt)
15004 return StmtError();
15005
15006 // Verify and diagnose loop nest.
15007 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
15008 Stmt *Body = nullptr;
15009 SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, 4>
15010 OriginalInits;
15011 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
15012 OriginalInits))
15013 return StmtError();
15014
15015 // Delay tiling to when template is completely instantiated.
15016 if (CurContext->isDependentContext())
15017 return OMPTileDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15018 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
15019
15020 SmallVector<Decl *, 4> PreInits;
15021
15022 // Create iteration variables for the generated loops.
15023 SmallVector<VarDecl *, 4> FloorIndVars;
15024 SmallVector<VarDecl *, 4> TileIndVars;
15025 FloorIndVars.resize(N: NumLoops);
15026 TileIndVars.resize(N: NumLoops);
15027 for (unsigned I = 0; I < NumLoops; ++I) {
15028 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15029
15030 assert(LoopHelper.Counters.size() == 1 &&
15031 "Expect single-dimensional loop iteration space");
15032 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15033 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15034 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15035 QualType CntTy = IterVarRef->getType();
15036
15037 // Iteration variable for the floor (i.e. outer) loop.
15038 {
15039 std::string FloorCntName =
15040 (Twine(".floor_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15041 VarDecl *FloorCntDecl =
15042 buildVarDecl(SemaRef&: *this, Loc: {}, Type: CntTy, Name: FloorCntName, Attrs: nullptr, OrigRef: OrigCntVar);
15043 FloorIndVars[I] = FloorCntDecl;
15044 }
15045
15046 // Iteration variable for the tile (i.e. inner) loop.
15047 {
15048 std::string TileCntName =
15049 (Twine(".tile_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
15050
15051 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15052 // used by the expressions to derive the original iteration variable's
15053 // value from the logical iteration number.
15054 auto *TileCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
15055 TileCntDecl->setDeclName(&PP.getIdentifierTable().get(Name: TileCntName));
15056 TileIndVars[I] = TileCntDecl;
15057 }
15058 for (auto &P : OriginalInits[I]) {
15059 if (auto *D = P.dyn_cast<Decl *>())
15060 PreInits.push_back(Elt: D);
15061 else if (auto *PI = dyn_cast_or_null<DeclStmt>(Val: P.dyn_cast<Stmt *>()))
15062 PreInits.append(in_start: PI->decl_begin(), in_end: PI->decl_end());
15063 }
15064 if (auto *PI = cast_or_null<DeclStmt>(Val: LoopHelper.PreInits))
15065 PreInits.append(in_start: PI->decl_begin(), in_end: PI->decl_end());
15066 // Gather declarations for the data members used as counters.
15067 for (Expr *CounterRef : LoopHelper.Counters) {
15068 auto *CounterDecl = cast<DeclRefExpr>(Val: CounterRef)->getDecl();
15069 if (isa<OMPCapturedExprDecl>(Val: CounterDecl))
15070 PreInits.push_back(CounterDecl);
15071 }
15072 }
15073
15074 // Once the original iteration values are set, append the innermost body.
15075 Stmt *Inner = Body;
15076
15077 // Create tile loops from the inside to the outside.
15078 for (int I = NumLoops - 1; I >= 0; --I) {
15079 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15080 Expr *NumIterations = LoopHelper.NumIterations;
15081 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15082 QualType CntTy = OrigCntVar->getType();
15083 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
15084 Scope *CurScope = getCurScope();
15085
15086 // Commonly used variables.
15087 DeclRefExpr *TileIV = buildDeclRefExpr(*this, TileIndVars[I], CntTy,
15088 OrigCntVar->getExprLoc());
15089 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
15090 OrigCntVar->getExprLoc());
15091
15092 // For init-statement: auto .tile.iv = .floor.iv
15093 AddInitializerToDecl(TileIndVars[I], DefaultLvalueConversion(FloorIV).get(),
15094 /*DirectInit=*/false);
15095 Decl *CounterDecl = TileIndVars[I];
15096 StmtResult InitStmt = new (Context)
15097 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15098 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15099 if (!InitStmt.isUsable())
15100 return StmtError();
15101
15102 // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
15103 // NumIterations)
15104 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15105 BO_Add, FloorIV, DimTileSize);
15106 if (!EndOfTile.isUsable())
15107 return StmtError();
15108 ExprResult IsPartialTile =
15109 BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15110 LHSExpr: NumIterations, RHSExpr: EndOfTile.get());
15111 if (!IsPartialTile.isUsable())
15112 return StmtError();
15113 ExprResult MinTileAndIterSpace = ActOnConditionalOp(
15114 QuestionLoc: LoopHelper.Cond->getBeginLoc(), ColonLoc: LoopHelper.Cond->getEndLoc(),
15115 CondExpr: IsPartialTile.get(), LHSExpr: NumIterations, RHSExpr: EndOfTile.get());
15116 if (!MinTileAndIterSpace.isUsable())
15117 return StmtError();
15118 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15119 BO_LT, TileIV, MinTileAndIterSpace.get());
15120 if (!CondExpr.isUsable())
15121 return StmtError();
15122
15123 // For incr-statement: ++.tile.iv
15124 ExprResult IncrStmt =
15125 BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, TileIV);
15126 if (!IncrStmt.isUsable())
15127 return StmtError();
15128
15129 // Statements to set the original iteration variable's value from the
15130 // logical iteration number.
15131 // Generated for loop is:
15132 // Original_for_init;
15133 // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
15134 // NumIterations); ++.tile.iv) {
15135 // Original_Body;
15136 // Original_counter_update;
15137 // }
15138 // FIXME: If the innermost body is an loop itself, inserting these
15139 // statements stops it being recognized as a perfectly nested loop (e.g.
15140 // for applying tiling again). If this is the case, sink the expressions
15141 // further into the inner loop.
15142 SmallVector<Stmt *, 4> BodyParts;
15143 BodyParts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
15144 BodyParts.push_back(Elt: Inner);
15145 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
15146 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
15147 Inner = new (Context)
15148 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15149 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15150 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15151 }
15152
15153 // Create floor loops from the inside to the outside.
15154 for (int I = NumLoops - 1; I >= 0; --I) {
15155 auto &LoopHelper = LoopHelpers[I];
15156 Expr *NumIterations = LoopHelper.NumIterations;
15157 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
15158 QualType CntTy = OrigCntVar->getType();
15159 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
15160 Scope *CurScope = getCurScope();
15161
15162 // Commonly used variables.
15163 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
15164 OrigCntVar->getExprLoc());
15165
15166 // For init-statement: auto .floor.iv = 0
15167 AddInitializerToDecl(
15168 FloorIndVars[I],
15169 ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
15170 /*DirectInit=*/false);
15171 Decl *CounterDecl = FloorIndVars[I];
15172 StmtResult InitStmt = new (Context)
15173 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
15174 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15175 if (!InitStmt.isUsable())
15176 return StmtError();
15177
15178 // For cond-expression: .floor.iv < NumIterations
15179 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15180 BO_LT, FloorIV, NumIterations);
15181 if (!CondExpr.isUsable())
15182 return StmtError();
15183
15184 // For incr-statement: .floor.iv += DimTileSize
15185 ExprResult IncrStmt = BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(),
15186 BO_AddAssign, FloorIV, DimTileSize);
15187 if (!IncrStmt.isUsable())
15188 return StmtError();
15189
15190 Inner = new (Context)
15191 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15192 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15193 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15194 }
15195
15196 return OMPTileDirective::Create(C: Context, StartLoc, EndLoc, Clauses, NumLoops,
15197 AssociatedStmt: AStmt, TransformedStmt: Inner,
15198 PreInits: buildPreInits(Context, PreInits));
15199}
15200
15201StmtResult Sema::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
15202 Stmt *AStmt,
15203 SourceLocation StartLoc,
15204 SourceLocation EndLoc) {
15205 // Empty statement should only be possible if there already was an error.
15206 if (!AStmt)
15207 return StmtError();
15208
15209 if (checkMutuallyExclusiveClauses(*this, Clauses, {OMPC_partial, OMPC_full}))
15210 return StmtError();
15211
15212 const OMPFullClause *FullClause =
15213 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15214 const OMPPartialClause *PartialClause =
15215 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15216 assert(!(FullClause && PartialClause) &&
15217 "mutual exclusivity must have been checked before");
15218
15219 constexpr unsigned NumLoops = 1;
15220 Stmt *Body = nullptr;
15221 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
15222 NumLoops);
15223 SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, NumLoops + 1>
15224 OriginalInits;
15225 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15226 Body, OriginalInits))
15227 return StmtError();
15228
15229 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
15230
15231 // Delay unrolling to when template is completely instantiated.
15232 if (CurContext->isDependentContext())
15233 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
15234 NumGeneratedLoops, TransformedStmt: nullptr, PreInits: nullptr);
15235
15236 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15237
15238 if (FullClause) {
15239 if (!VerifyPositiveIntegerConstantInClause(
15240 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15241 /*SuppressExprDiags=*/true)
15242 .isUsable()) {
15243 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15244 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15245 << "#pragma omp unroll full";
15246 return StmtError();
15247 }
15248 }
15249
15250 // The generated loop may only be passed to other loop-associated directive
15251 // when a partial clause is specified. Without the requirement it is
15252 // sufficient to generate loop unroll metadata at code-generation.
15253 if (NumGeneratedLoops == 0)
15254 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
15255 NumGeneratedLoops, TransformedStmt: nullptr, PreInits: nullptr);
15256
15257 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15258 // associated with another loop directive.
15259 //
15260 // The canonical loop analysis return by checkTransformableLoopNest assumes
15261 // the following structure to be the same loop without transformations or
15262 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15263 // LoopHelper.Counters;
15264 // for (; IV < LoopHelper.NumIterations; ++IV) {
15265 // LoopHelper.Updates;
15266 // Body;
15267 // }
15268 // \endcode
15269 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15270 // and referenced by LoopHelper.IterationVarRef.
15271 //
15272 // The unrolling directive transforms this into the following loop:
15273 // \code
15274 // OriginalInits; \
15275 // LoopHelper.PreInits; > NewPreInits
15276 // LoopHelper.Counters; /
15277 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15278 // #pragma clang loop unroll_count(Factor)
15279 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15280 // {
15281 // LoopHelper.Updates;
15282 // Body;
15283 // }
15284 // }
15285 // \endcode
15286 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15287 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15288 // references it. If the partially unrolled loop is associated with another
15289 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15290 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15291 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15292 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15293 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15294 // property of the OMPLoopBasedDirective instead of statements in
15295 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15296 // of a canonical loop nest where these PreInits are emitted before the
15297 // outermost directive.
15298
15299 // Determine the PreInit declarations.
15300 SmallVector<Decl *, 4> PreInits;
15301 assert(OriginalInits.size() == 1 &&
15302 "Expecting a single-dimensional loop iteration space");
15303 for (auto &P : OriginalInits[0]) {
15304 if (auto *D = P.dyn_cast<Decl *>())
15305 PreInits.push_back(Elt: D);
15306 else if (auto *PI = dyn_cast_or_null<DeclStmt>(Val: P.dyn_cast<Stmt *>()))
15307 PreInits.append(in_start: PI->decl_begin(), in_end: PI->decl_end());
15308 }
15309 if (auto *PI = cast_or_null<DeclStmt>(Val: LoopHelper.PreInits))
15310 PreInits.append(in_start: PI->decl_begin(), in_end: PI->decl_end());
15311 // Gather declarations for the data members used as counters.
15312 for (Expr *CounterRef : LoopHelper.Counters) {
15313 auto *CounterDecl = cast<DeclRefExpr>(Val: CounterRef)->getDecl();
15314 if (isa<OMPCapturedExprDecl>(Val: CounterDecl))
15315 PreInits.push_back(CounterDecl);
15316 }
15317
15318 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15319 QualType IVTy = IterationVarRef->getType();
15320 assert(LoopHelper.Counters.size() == 1 &&
15321 "Expecting a single-dimensional loop iteration space");
15322 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15323
15324 // Determine the unroll factor.
15325 uint64_t Factor;
15326 SourceLocation FactorLoc;
15327 if (Expr *FactorVal = PartialClause->getFactor()) {
15328 Factor = FactorVal->getIntegerConstantExpr(Ctx: Context)->getZExtValue();
15329 FactorLoc = FactorVal->getExprLoc();
15330 } else {
15331 // TODO: Use a better profitability model.
15332 Factor = 2;
15333 }
15334 assert(Factor > 0 && "Expected positive unroll factor");
15335 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15336 return IntegerLiteral::Create(
15337 Context, llvm::APInt(Context.getIntWidth(IVTy), Factor), IVTy,
15338 FactorLoc);
15339 };
15340
15341 // Iteration variable SourceLocations.
15342 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15343 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15344 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15345
15346 // Internal variable names.
15347 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15348 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15349 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15350 std::string InnerTripCountName =
15351 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
15352
15353 // Create the iteration variable for the unrolled loop.
15354 VarDecl *OuterIVDecl =
15355 buildVarDecl(SemaRef&: *this, Loc: {}, Type: IVTy, Name: OuterIVName, Attrs: nullptr, OrigRef: OrigVar);
15356 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15357 return buildDeclRefExpr(*this, OuterIVDecl, IVTy, OrigVarLoc);
15358 };
15359
15360 // Iteration variable for the inner loop: Reuse the iteration variable created
15361 // by checkOpenMPLoop.
15362 auto *InnerIVDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
15363 InnerIVDecl->setDeclName(&PP.getIdentifierTable().get(Name: InnerIVName));
15364 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15365 return buildDeclRefExpr(*this, InnerIVDecl, IVTy, OrigVarLoc);
15366 };
15367
15368 // Make a copy of the NumIterations expression for each use: By the AST
15369 // constraints, every expression object in a DeclContext must be unique.
15370 CaptureVars CopyTransformer(*this);
15371 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15372 return AssertSuccess(
15373 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15374 };
15375
15376 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15377 ExprResult LValueConv = DefaultLvalueConversion(E: MakeOuterRef());
15378 AddInitializerToDecl(InnerIVDecl, LValueConv.get(), /*DirectInit=*/false);
15379 StmtResult InnerInit = new (Context)
15380 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15381 if (!InnerInit.isUsable())
15382 return StmtError();
15383
15384 // Inner For cond-expression:
15385 // \code
15386 // .unroll_inner.iv < .unrolled.iv + Factor &&
15387 // .unroll_inner.iv < NumIterations
15388 // \endcode
15389 // This conjunction of two conditions allows ScalarEvolution to derive the
15390 // maximum trip count of the inner loop.
15391 ExprResult EndOfTile = BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(),
15392 Opc: BO_Add, LHSExpr: MakeOuterRef(), RHSExpr: MakeFactorExpr());
15393 if (!EndOfTile.isUsable())
15394 return StmtError();
15395 ExprResult InnerCond1 = BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(),
15396 Opc: BO_LT, LHSExpr: MakeInnerRef(), RHSExpr: EndOfTile.get());
15397 if (!InnerCond1.isUsable())
15398 return StmtError();
15399 ExprResult InnerCond2 =
15400 BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT, LHSExpr: MakeInnerRef(),
15401 RHSExpr: MakeNumIterations());
15402 if (!InnerCond2.isUsable())
15403 return StmtError();
15404 ExprResult InnerCond =
15405 BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LAnd,
15406 LHSExpr: InnerCond1.get(), RHSExpr: InnerCond2.get());
15407 if (!InnerCond.isUsable())
15408 return StmtError();
15409
15410 // Inner For incr-statement: ++.unroll_inner.iv
15411 ExprResult InnerIncr = BuildUnaryOp(S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(),
15412 Opc: UO_PreInc, Input: MakeInnerRef());
15413 if (!InnerIncr.isUsable())
15414 return StmtError();
15415
15416 // Inner For statement.
15417 SmallVector<Stmt *> InnerBodyStmts;
15418 InnerBodyStmts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
15419 InnerBodyStmts.push_back(Elt: Body);
15420 CompoundStmt *InnerBody =
15421 CompoundStmt::Create(C: Context, Stmts: InnerBodyStmts, FPFeatures: FPOptionsOverride(),
15422 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
15423 ForStmt *InnerFor = new (Context)
15424 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15425 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15426 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15427
15428 // Unroll metadata for the inner loop.
15429 // This needs to take into account the remainder portion of the unrolled loop,
15430 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15431 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15432 // the maximum trip count, which will also generate a remainder loop. Just
15433 // `unroll(enable)` (which could have been useful if the user has not
15434 // specified a concrete factor; even though the outer loop cannot be
15435 // influenced anymore, would avoid more code bloat than necessary) will refuse
15436 // the loop because "Won't unroll; remainder loop could not be generated when
15437 // assuming runtime trip count". Even if it did work, it must not choose a
15438 // larger unroll factor than the maximum loop length, or it would always just
15439 // execute the remainder loop.
15440 LoopHintAttr *UnrollHintAttr =
15441 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15442 LoopHintAttr::Numeric, MakeFactorExpr());
15443 AttributedStmt *InnerUnrolled =
15444 AttributedStmt::Create(C: Context, Loc: StartLoc, Attrs: {UnrollHintAttr}, SubStmt: InnerFor);
15445
15446 // Outer For init-statement: auto .unrolled.iv = 0
15447 AddInitializerToDecl(
15448 OuterIVDecl, ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
15449 /*DirectInit=*/false);
15450 StmtResult OuterInit = new (Context)
15451 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15452 if (!OuterInit.isUsable())
15453 return StmtError();
15454
15455 // Outer For cond-expression: .unrolled.iv < NumIterations
15456 ExprResult OuterConde =
15457 BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT, LHSExpr: MakeOuterRef(),
15458 RHSExpr: MakeNumIterations());
15459 if (!OuterConde.isUsable())
15460 return StmtError();
15461
15462 // Outer For incr-statement: .unrolled.iv += Factor
15463 ExprResult OuterIncr =
15464 BuildBinOp(S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
15465 LHSExpr: MakeOuterRef(), RHSExpr: MakeFactorExpr());
15466 if (!OuterIncr.isUsable())
15467 return StmtError();
15468
15469 // Outer For statement.
15470 ForStmt *OuterFor = new (Context)
15471 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15472 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15473 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15474
15475 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
15476 NumGeneratedLoops, TransformedStmt: OuterFor,
15477 PreInits: buildPreInits(Context, PreInits));
15478}
15479
15480OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
15481 SourceLocation StartLoc,
15482 SourceLocation LParenLoc,
15483 SourceLocation EndLoc) {
15484 OMPClause *Res = nullptr;
15485 switch (Kind) {
15486 case OMPC_final:
15487 Res = ActOnOpenMPFinalClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
15488 break;
15489 case OMPC_num_threads:
15490 Res = ActOnOpenMPNumThreadsClause(NumThreads: Expr, StartLoc, LParenLoc, EndLoc);
15491 break;
15492 case OMPC_safelen:
15493 Res = ActOnOpenMPSafelenClause(Length: Expr, StartLoc, LParenLoc, EndLoc);
15494 break;
15495 case OMPC_simdlen:
15496 Res = ActOnOpenMPSimdlenClause(Length: Expr, StartLoc, LParenLoc, EndLoc);
15497 break;
15498 case OMPC_allocator:
15499 Res = ActOnOpenMPAllocatorClause(Allocator: Expr, StartLoc, LParenLoc, EndLoc);
15500 break;
15501 case OMPC_collapse:
15502 Res = ActOnOpenMPCollapseClause(NumForLoops: Expr, StartLoc, LParenLoc, EndLoc);
15503 break;
15504 case OMPC_ordered:
15505 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, NumForLoops: Expr);
15506 break;
15507 case OMPC_num_teams:
15508 Res = ActOnOpenMPNumTeamsClause(NumTeams: Expr, StartLoc, LParenLoc, EndLoc);
15509 break;
15510 case OMPC_thread_limit:
15511 Res = ActOnOpenMPThreadLimitClause(ThreadLimit: Expr, StartLoc, LParenLoc, EndLoc);
15512 break;
15513 case OMPC_priority:
15514 Res = ActOnOpenMPPriorityClause(Priority: Expr, StartLoc, LParenLoc, EndLoc);
15515 break;
15516 case OMPC_hint:
15517 Res = ActOnOpenMPHintClause(Hint: Expr, StartLoc, LParenLoc, EndLoc);
15518 break;
15519 case OMPC_depobj:
15520 Res = ActOnOpenMPDepobjClause(Depobj: Expr, StartLoc, LParenLoc, EndLoc);
15521 break;
15522 case OMPC_detach:
15523 Res = ActOnOpenMPDetachClause(Evt: Expr, StartLoc, LParenLoc, EndLoc);
15524 break;
15525 case OMPC_novariants:
15526 Res = ActOnOpenMPNovariantsClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
15527 break;
15528 case OMPC_nocontext:
15529 Res = ActOnOpenMPNocontextClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
15530 break;
15531 case OMPC_filter:
15532 Res = ActOnOpenMPFilterClause(ThreadID: Expr, StartLoc, LParenLoc, EndLoc);
15533 break;
15534 case OMPC_partial:
15535 Res = ActOnOpenMPPartialClause(FactorExpr: Expr, StartLoc, LParenLoc, EndLoc);
15536 break;
15537 case OMPC_message:
15538 Res = ActOnOpenMPMessageClause(MS: Expr, StartLoc, LParenLoc, EndLoc);
15539 break;
15540 case OMPC_align:
15541 Res = ActOnOpenMPAlignClause(Alignment: Expr, StartLoc, LParenLoc, EndLoc);
15542 break;
15543 case OMPC_ompx_dyn_cgroup_mem:
15544 Res = ActOnOpenMPXDynCGroupMemClause(Size: Expr, StartLoc, LParenLoc, EndLoc);
15545 break;
15546 case OMPC_grainsize:
15547 case OMPC_num_tasks:
15548 case OMPC_device:
15549 case OMPC_if:
15550 case OMPC_default:
15551 case OMPC_proc_bind:
15552 case OMPC_schedule:
15553 case OMPC_private:
15554 case OMPC_firstprivate:
15555 case OMPC_lastprivate:
15556 case OMPC_shared:
15557 case OMPC_reduction:
15558 case OMPC_task_reduction:
15559 case OMPC_in_reduction:
15560 case OMPC_linear:
15561 case OMPC_aligned:
15562 case OMPC_copyin:
15563 case OMPC_copyprivate:
15564 case OMPC_nowait:
15565 case OMPC_untied:
15566 case OMPC_mergeable:
15567 case OMPC_threadprivate:
15568 case OMPC_sizes:
15569 case OMPC_allocate:
15570 case OMPC_flush:
15571 case OMPC_read:
15572 case OMPC_write:
15573 case OMPC_update:
15574 case OMPC_capture:
15575 case OMPC_compare:
15576 case OMPC_seq_cst:
15577 case OMPC_acq_rel:
15578 case OMPC_acquire:
15579 case OMPC_release:
15580 case OMPC_relaxed:
15581 case OMPC_depend:
15582 case OMPC_threads:
15583 case OMPC_simd:
15584 case OMPC_map:
15585 case OMPC_nogroup:
15586 case OMPC_dist_schedule:
15587 case OMPC_defaultmap:
15588 case OMPC_unknown:
15589 case OMPC_uniform:
15590 case OMPC_to:
15591 case OMPC_from:
15592 case OMPC_use_device_ptr:
15593 case OMPC_use_device_addr:
15594 case OMPC_is_device_ptr:
15595 case OMPC_unified_address:
15596 case OMPC_unified_shared_memory:
15597 case OMPC_reverse_offload:
15598 case OMPC_dynamic_allocators:
15599 case OMPC_atomic_default_mem_order:
15600 case OMPC_device_type:
15601 case OMPC_match:
15602 case OMPC_nontemporal:
15603 case OMPC_order:
15604 case OMPC_at:
15605 case OMPC_severity:
15606 case OMPC_destroy:
15607 case OMPC_inclusive:
15608 case OMPC_exclusive:
15609 case OMPC_uses_allocators:
15610 case OMPC_affinity:
15611 case OMPC_when:
15612 case OMPC_bind:
15613 default:
15614 llvm_unreachable("Clause is not allowed.");
15615 }
15616 return Res;
15617}
15618
15619// An OpenMP directive such as 'target parallel' has two captured regions:
15620// for the 'target' and 'parallel' respectively. This function returns
15621// the region in which to capture expressions associated with a clause.
15622// A return value of OMPD_unknown signifies that the expression should not
15623// be captured.
15624static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
15625 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15626 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15627 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15628 switch (CKind) {
15629 case OMPC_if:
15630 switch (DKind) {
15631 case OMPD_target_parallel_for_simd:
15632 if (OpenMPVersion >= 50 &&
15633 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15634 CaptureRegion = OMPD_parallel;
15635 break;
15636 }
15637 [[fallthrough]];
15638 case OMPD_target_parallel:
15639 case OMPD_target_parallel_for:
15640 case OMPD_target_parallel_loop:
15641 // If this clause applies to the nested 'parallel' region, capture within
15642 // the 'target' region, otherwise do not capture.
15643 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15644 CaptureRegion = OMPD_target;
15645 break;
15646 case OMPD_target_teams_distribute_parallel_for_simd:
15647 if (OpenMPVersion >= 50 &&
15648 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15649 CaptureRegion = OMPD_parallel;
15650 break;
15651 }
15652 [[fallthrough]];
15653 case OMPD_target_teams_loop:
15654 case OMPD_target_teams_distribute_parallel_for:
15655 // If this clause applies to the nested 'parallel' region, capture within
15656 // the 'teams' region, otherwise do not capture.
15657 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15658 CaptureRegion = OMPD_teams;
15659 break;
15660 case OMPD_teams_distribute_parallel_for_simd:
15661 if (OpenMPVersion >= 50 &&
15662 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15663 CaptureRegion = OMPD_parallel;
15664 break;
15665 }
15666 [[fallthrough]];
15667 case OMPD_teams_distribute_parallel_for:
15668 CaptureRegion = OMPD_teams;
15669 break;
15670 case OMPD_target_update:
15671 case OMPD_target_enter_data:
15672 case OMPD_target_exit_data:
15673 CaptureRegion = OMPD_task;
15674 break;
15675 case OMPD_parallel_masked_taskloop:
15676 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15677 CaptureRegion = OMPD_parallel;
15678 break;
15679 case OMPD_parallel_master_taskloop:
15680 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15681 CaptureRegion = OMPD_parallel;
15682 break;
15683 case OMPD_parallel_masked_taskloop_simd:
15684 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15685 NameModifier == OMPD_taskloop) {
15686 CaptureRegion = OMPD_parallel;
15687 break;
15688 }
15689 if (OpenMPVersion <= 45)
15690 break;
15691 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15692 CaptureRegion = OMPD_taskloop;
15693 break;
15694 case OMPD_parallel_master_taskloop_simd:
15695 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15696 NameModifier == OMPD_taskloop) {
15697 CaptureRegion = OMPD_parallel;
15698 break;
15699 }
15700 if (OpenMPVersion <= 45)
15701 break;
15702 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15703 CaptureRegion = OMPD_taskloop;
15704 break;
15705 case OMPD_parallel_for_simd:
15706 if (OpenMPVersion <= 45)
15707 break;
15708 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15709 CaptureRegion = OMPD_parallel;
15710 break;
15711 case OMPD_taskloop_simd:
15712 case OMPD_master_taskloop_simd:
15713 case OMPD_masked_taskloop_simd:
15714 if (OpenMPVersion <= 45)
15715 break;
15716 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15717 CaptureRegion = OMPD_taskloop;
15718 break;
15719 case OMPD_distribute_parallel_for_simd:
15720 if (OpenMPVersion <= 45)
15721 break;
15722 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15723 CaptureRegion = OMPD_parallel;
15724 break;
15725 case OMPD_target_simd:
15726 if (OpenMPVersion >= 50 &&
15727 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15728 CaptureRegion = OMPD_target;
15729 break;
15730 case OMPD_teams_distribute_simd:
15731 case OMPD_target_teams_distribute_simd:
15732 if (OpenMPVersion >= 50 &&
15733 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15734 CaptureRegion = OMPD_teams;
15735 break;
15736 case OMPD_cancel:
15737 case OMPD_parallel:
15738 case OMPD_parallel_master:
15739 case OMPD_parallel_masked:
15740 case OMPD_parallel_sections:
15741 case OMPD_parallel_for:
15742 case OMPD_parallel_loop:
15743 case OMPD_target:
15744 case OMPD_target_teams:
15745 case OMPD_target_teams_distribute:
15746 case OMPD_distribute_parallel_for:
15747 case OMPD_task:
15748 case OMPD_taskloop:
15749 case OMPD_master_taskloop:
15750 case OMPD_masked_taskloop:
15751 case OMPD_target_data:
15752 case OMPD_simd:
15753 case OMPD_for_simd:
15754 case OMPD_distribute_simd:
15755 // Do not capture if-clause expressions.
15756 break;
15757 case OMPD_threadprivate:
15758 case OMPD_allocate:
15759 case OMPD_taskyield:
15760 case OMPD_error:
15761 case OMPD_barrier:
15762 case OMPD_taskwait:
15763 case OMPD_cancellation_point:
15764 case OMPD_flush:
15765 case OMPD_depobj:
15766 case OMPD_scan:
15767 case OMPD_declare_reduction:
15768 case OMPD_declare_mapper:
15769 case OMPD_declare_simd:
15770 case OMPD_declare_variant:
15771 case OMPD_begin_declare_variant:
15772 case OMPD_end_declare_variant:
15773 case OMPD_declare_target:
15774 case OMPD_end_declare_target:
15775 case OMPD_loop:
15776 case OMPD_teams_loop:
15777 case OMPD_teams:
15778 case OMPD_tile:
15779 case OMPD_unroll:
15780 case OMPD_for:
15781 case OMPD_sections:
15782 case OMPD_section:
15783 case OMPD_single:
15784 case OMPD_master:
15785 case OMPD_masked:
15786 case OMPD_critical:
15787 case OMPD_taskgroup:
15788 case OMPD_distribute:
15789 case OMPD_ordered:
15790 case OMPD_atomic:
15791 case OMPD_teams_distribute:
15792 case OMPD_requires:
15793 case OMPD_metadirective:
15794 llvm_unreachable("Unexpected OpenMP directive with if-clause");
15795 case OMPD_unknown:
15796 default:
15797 llvm_unreachable("Unknown OpenMP directive");
15798 }
15799 break;
15800 case OMPC_num_threads:
15801 switch (DKind) {
15802 case OMPD_target_parallel:
15803 case OMPD_target_parallel_for:
15804 case OMPD_target_parallel_for_simd:
15805 case OMPD_target_parallel_loop:
15806 CaptureRegion = OMPD_target;
15807 break;
15808 case OMPD_teams_distribute_parallel_for:
15809 case OMPD_teams_distribute_parallel_for_simd:
15810 case OMPD_target_teams_distribute_parallel_for:
15811 case OMPD_target_teams_distribute_parallel_for_simd:
15812 CaptureRegion = OMPD_teams;
15813 break;
15814 case OMPD_parallel:
15815 case OMPD_parallel_master:
15816 case OMPD_parallel_masked:
15817 case OMPD_parallel_sections:
15818 case OMPD_parallel_for:
15819 case OMPD_parallel_for_simd:
15820 case OMPD_parallel_loop:
15821 case OMPD_distribute_parallel_for:
15822 case OMPD_distribute_parallel_for_simd:
15823 case OMPD_parallel_master_taskloop:
15824 case OMPD_parallel_masked_taskloop:
15825 case OMPD_parallel_master_taskloop_simd:
15826 case OMPD_parallel_masked_taskloop_simd:
15827 // Do not capture num_threads-clause expressions.
15828 break;
15829 case OMPD_target_data:
15830 case OMPD_target_enter_data:
15831 case OMPD_target_exit_data:
15832 case OMPD_target_update:
15833 case OMPD_target:
15834 case OMPD_target_simd:
15835 case OMPD_target_teams:
15836 case OMPD_target_teams_distribute:
15837 case OMPD_target_teams_distribute_simd:
15838 case OMPD_cancel:
15839 case OMPD_task:
15840 case OMPD_taskloop:
15841 case OMPD_taskloop_simd:
15842 case OMPD_master_taskloop:
15843 case OMPD_masked_taskloop:
15844 case OMPD_master_taskloop_simd:
15845 case OMPD_masked_taskloop_simd:
15846 case OMPD_threadprivate:
15847 case OMPD_allocate:
15848 case OMPD_taskyield:
15849 case OMPD_error:
15850 case OMPD_barrier:
15851 case OMPD_taskwait:
15852 case OMPD_cancellation_point:
15853 case OMPD_flush:
15854 case OMPD_depobj:
15855 case OMPD_scan:
15856 case OMPD_declare_reduction:
15857 case OMPD_declare_mapper:
15858 case OMPD_declare_simd:
15859 case OMPD_declare_variant:
15860 case OMPD_begin_declare_variant:
15861 case OMPD_end_declare_variant:
15862 case OMPD_declare_target:
15863 case OMPD_end_declare_target:
15864 case OMPD_loop:
15865 case OMPD_teams_loop:
15866 case OMPD_target_teams_loop:
15867 case OMPD_teams:
15868 case OMPD_simd:
15869 case OMPD_tile:
15870 case OMPD_unroll:
15871 case OMPD_for:
15872 case OMPD_for_simd:
15873 case OMPD_sections:
15874 case OMPD_section:
15875 case OMPD_single:
15876 case OMPD_master:
15877 case OMPD_masked:
15878 case OMPD_critical:
15879 case OMPD_taskgroup:
15880 case OMPD_distribute:
15881 case OMPD_ordered:
15882 case OMPD_atomic:
15883 case OMPD_distribute_simd:
15884 case OMPD_teams_distribute:
15885 case OMPD_teams_distribute_simd:
15886 case OMPD_requires:
15887 case OMPD_metadirective:
15888 llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
15889 case OMPD_unknown:
15890 default:
15891 llvm_unreachable("Unknown OpenMP directive");
15892 }
15893 break;
15894 case OMPC_num_teams:
15895 switch (DKind) {
15896 case OMPD_target_teams:
15897 case OMPD_target_teams_distribute:
15898 case OMPD_target_teams_distribute_simd:
15899 case OMPD_target_teams_distribute_parallel_for:
15900 case OMPD_target_teams_distribute_parallel_for_simd:
15901 case OMPD_target_teams_loop:
15902 CaptureRegion = OMPD_target;
15903 break;
15904 case OMPD_teams_distribute_parallel_for:
15905 case OMPD_teams_distribute_parallel_for_simd:
15906 case OMPD_teams:
15907 case OMPD_teams_distribute:
15908 case OMPD_teams_distribute_simd:
15909 case OMPD_teams_loop:
15910 // Do not capture num_teams-clause expressions.
15911 break;
15912 case OMPD_distribute_parallel_for:
15913 case OMPD_distribute_parallel_for_simd:
15914 case OMPD_task:
15915 case OMPD_taskloop:
15916 case OMPD_taskloop_simd:
15917 case OMPD_master_taskloop:
15918 case OMPD_masked_taskloop:
15919 case OMPD_master_taskloop_simd:
15920 case OMPD_masked_taskloop_simd:
15921 case OMPD_parallel_master_taskloop:
15922 case OMPD_parallel_masked_taskloop:
15923 case OMPD_parallel_master_taskloop_simd:
15924 case OMPD_parallel_masked_taskloop_simd:
15925 case OMPD_target_data:
15926 case OMPD_target_enter_data:
15927 case OMPD_target_exit_data:
15928 case OMPD_target_update:
15929 case OMPD_cancel:
15930 case OMPD_parallel:
15931 case OMPD_parallel_master:
15932 case OMPD_parallel_masked:
15933 case OMPD_parallel_sections:
15934 case OMPD_parallel_for:
15935 case OMPD_parallel_for_simd:
15936 case OMPD_parallel_loop:
15937 case OMPD_target:
15938 case OMPD_target_simd:
15939 case OMPD_target_parallel:
15940 case OMPD_target_parallel_for:
15941 case OMPD_target_parallel_for_simd:
15942 case OMPD_target_parallel_loop:
15943 case OMPD_threadprivate:
15944 case OMPD_allocate:
15945 case OMPD_taskyield:
15946 case OMPD_error:
15947 case OMPD_barrier:
15948 case OMPD_taskwait:
15949 case OMPD_cancellation_point:
15950 case OMPD_flush:
15951 case OMPD_depobj:
15952 case OMPD_scan:
15953 case OMPD_declare_reduction:
15954 case OMPD_declare_mapper:
15955 case OMPD_declare_simd:
15956 case OMPD_declare_variant:
15957 case OMPD_begin_declare_variant:
15958 case OMPD_end_declare_variant:
15959 case OMPD_declare_target:
15960 case OMPD_end_declare_target:
15961 case OMPD_loop:
15962 case OMPD_simd:
15963 case OMPD_tile:
15964 case OMPD_unroll:
15965 case OMPD_for:
15966 case OMPD_for_simd:
15967 case OMPD_sections:
15968 case OMPD_section:
15969 case OMPD_single:
15970 case OMPD_master:
15971 case OMPD_masked:
15972 case OMPD_critical:
15973 case OMPD_taskgroup:
15974 case OMPD_distribute:
15975 case OMPD_ordered:
15976 case OMPD_atomic:
15977 case OMPD_distribute_simd:
15978 case OMPD_requires:
15979 case OMPD_metadirective:
15980 llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
15981 case OMPD_unknown:
15982 default:
15983 llvm_unreachable("Unknown OpenMP directive");
15984 }
15985 break;
15986 case OMPC_thread_limit:
15987 switch (DKind) {
15988 case OMPD_target:
15989 case OMPD_target_teams:
15990 case OMPD_target_teams_distribute:
15991 case OMPD_target_teams_distribute_simd:
15992 case OMPD_target_teams_distribute_parallel_for:
15993 case OMPD_target_teams_distribute_parallel_for_simd:
15994 case OMPD_target_teams_loop:
15995 case OMPD_target_simd:
15996 case OMPD_target_parallel:
15997 case OMPD_target_parallel_for:
15998 case OMPD_target_parallel_for_simd:
15999 case OMPD_target_parallel_loop:
16000 CaptureRegion = OMPD_target;
16001 break;
16002 case OMPD_teams_distribute_parallel_for:
16003 case OMPD_teams_distribute_parallel_for_simd:
16004 case OMPD_teams:
16005 case OMPD_teams_distribute:
16006 case OMPD_teams_distribute_simd:
16007 case OMPD_teams_loop:
16008 // Do not capture thread_limit-clause expressions.
16009 break;
16010 case OMPD_distribute_parallel_for:
16011 case OMPD_distribute_parallel_for_simd:
16012 case OMPD_task:
16013 case OMPD_taskloop:
16014 case OMPD_taskloop_simd:
16015 case OMPD_master_taskloop:
16016 case OMPD_masked_taskloop:
16017 case OMPD_master_taskloop_simd:
16018 case OMPD_masked_taskloop_simd:
16019 case OMPD_parallel_master_taskloop:
16020 case OMPD_parallel_masked_taskloop:
16021 case OMPD_parallel_master_taskloop_simd:
16022 case OMPD_parallel_masked_taskloop_simd:
16023 case OMPD_target_data:
16024 case OMPD_target_enter_data:
16025 case OMPD_target_exit_data:
16026 case OMPD_target_update:
16027 case OMPD_cancel:
16028 case OMPD_parallel:
16029 case OMPD_parallel_master:
16030 case OMPD_parallel_masked:
16031 case OMPD_parallel_sections:
16032 case OMPD_parallel_for:
16033 case OMPD_parallel_for_simd:
16034 case OMPD_parallel_loop:
16035 case OMPD_threadprivate:
16036 case OMPD_allocate:
16037 case OMPD_taskyield:
16038 case OMPD_error:
16039 case OMPD_barrier:
16040 case OMPD_taskwait:
16041 case OMPD_cancellation_point:
16042 case OMPD_flush:
16043 case OMPD_depobj:
16044 case OMPD_scan:
16045 case OMPD_declare_reduction:
16046 case OMPD_declare_mapper:
16047 case OMPD_declare_simd:
16048 case OMPD_declare_variant:
16049 case OMPD_begin_declare_variant:
16050 case OMPD_end_declare_variant:
16051 case OMPD_declare_target:
16052 case OMPD_end_declare_target:
16053 case OMPD_loop:
16054 case OMPD_simd:
16055 case OMPD_tile:
16056 case OMPD_unroll:
16057 case OMPD_for:
16058 case OMPD_for_simd:
16059 case OMPD_sections:
16060 case OMPD_section:
16061 case OMPD_single:
16062 case OMPD_master:
16063 case OMPD_masked:
16064 case OMPD_critical:
16065 case OMPD_taskgroup:
16066 case OMPD_distribute:
16067 case OMPD_ordered:
16068 case OMPD_atomic:
16069 case OMPD_distribute_simd:
16070 case OMPD_requires:
16071 case OMPD_metadirective:
16072 llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
16073 case OMPD_unknown:
16074 default:
16075 llvm_unreachable("Unknown OpenMP directive");
16076 }
16077 break;
16078 case OMPC_schedule:
16079 switch (DKind) {
16080 case OMPD_parallel_for:
16081 case OMPD_parallel_for_simd:
16082 case OMPD_distribute_parallel_for:
16083 case OMPD_distribute_parallel_for_simd:
16084 case OMPD_teams_distribute_parallel_for:
16085 case OMPD_teams_distribute_parallel_for_simd:
16086 case OMPD_target_parallel_for:
16087 case OMPD_target_parallel_for_simd:
16088 case OMPD_target_teams_distribute_parallel_for:
16089 case OMPD_target_teams_distribute_parallel_for_simd:
16090 CaptureRegion = OMPD_parallel;
16091 break;
16092 case OMPD_for:
16093 case OMPD_for_simd:
16094 // Do not capture schedule-clause expressions.
16095 break;
16096 case OMPD_task:
16097 case OMPD_taskloop:
16098 case OMPD_taskloop_simd:
16099 case OMPD_master_taskloop:
16100 case OMPD_masked_taskloop:
16101 case OMPD_master_taskloop_simd:
16102 case OMPD_masked_taskloop_simd:
16103 case OMPD_parallel_master_taskloop:
16104 case OMPD_parallel_masked_taskloop:
16105 case OMPD_parallel_master_taskloop_simd:
16106 case OMPD_parallel_masked_taskloop_simd:
16107 case OMPD_target_data:
16108 case OMPD_target_enter_data:
16109 case OMPD_target_exit_data:
16110 case OMPD_target_update:
16111 case OMPD_teams:
16112 case OMPD_teams_distribute:
16113 case OMPD_teams_distribute_simd:
16114 case OMPD_target_teams_distribute:
16115 case OMPD_target_teams_distribute_simd:
16116 case OMPD_target:
16117 case OMPD_target_simd:
16118 case OMPD_target_parallel:
16119 case OMPD_cancel:
16120 case OMPD_parallel:
16121 case OMPD_parallel_master:
16122 case OMPD_parallel_masked:
16123 case OMPD_parallel_sections:
16124 case OMPD_threadprivate:
16125 case OMPD_allocate:
16126 case OMPD_taskyield:
16127 case OMPD_error:
16128 case OMPD_barrier:
16129 case OMPD_taskwait:
16130 case OMPD_cancellation_point:
16131 case OMPD_flush:
16132 case OMPD_depobj:
16133 case OMPD_scan:
16134 case OMPD_declare_reduction:
16135 case OMPD_declare_mapper:
16136 case OMPD_declare_simd:
16137 case OMPD_declare_variant:
16138 case OMPD_begin_declare_variant:
16139 case OMPD_end_declare_variant:
16140 case OMPD_declare_target:
16141 case OMPD_end_declare_target:
16142 case OMPD_loop:
16143 case OMPD_teams_loop:
16144 case OMPD_target_teams_loop:
16145 case OMPD_parallel_loop:
16146 case OMPD_target_parallel_loop:
16147 case OMPD_simd:
16148 case OMPD_tile:
16149 case OMPD_unroll:
16150 case OMPD_sections:
16151 case OMPD_section:
16152 case OMPD_single:
16153 case OMPD_master:
16154 case OMPD_masked:
16155 case OMPD_critical:
16156 case OMPD_taskgroup:
16157 case OMPD_distribute:
16158 case OMPD_ordered:
16159 case OMPD_atomic:
16160 case OMPD_distribute_simd:
16161 case OMPD_target_teams:
16162 case OMPD_requires:
16163 case OMPD_metadirective:
16164 llvm_unreachable("Unexpected OpenMP directive with schedule clause");
16165 case OMPD_unknown:
16166 default:
16167 llvm_unreachable("Unknown OpenMP directive");
16168 }
16169 break;
16170 case OMPC_dist_schedule:
16171 switch (DKind) {
16172 case OMPD_teams_distribute_parallel_for:
16173 case OMPD_teams_distribute_parallel_for_simd:
16174 case OMPD_teams_distribute:
16175 case OMPD_teams_distribute_simd:
16176 case OMPD_target_teams_distribute_parallel_for:
16177 case OMPD_target_teams_distribute_parallel_for_simd:
16178 case OMPD_target_teams_distribute:
16179 case OMPD_target_teams_distribute_simd:
16180 CaptureRegion = OMPD_teams;
16181 break;
16182 case OMPD_distribute_parallel_for:
16183 case OMPD_distribute_parallel_for_simd:
16184 case OMPD_distribute:
16185 case OMPD_distribute_simd:
16186 // Do not capture dist_schedule-clause expressions.
16187 break;
16188 case OMPD_parallel_for:
16189 case OMPD_parallel_for_simd:
16190 case OMPD_target_parallel_for_simd:
16191 case OMPD_target_parallel_for:
16192 case OMPD_task:
16193 case OMPD_taskloop:
16194 case OMPD_taskloop_simd:
16195 case OMPD_master_taskloop:
16196 case OMPD_masked_taskloop:
16197 case OMPD_master_taskloop_simd:
16198 case OMPD_masked_taskloop_simd:
16199 case OMPD_parallel_master_taskloop:
16200 case OMPD_parallel_masked_taskloop:
16201 case OMPD_parallel_master_taskloop_simd:
16202 case OMPD_parallel_masked_taskloop_simd:
16203 case OMPD_target_data:
16204 case OMPD_target_enter_data:
16205 case OMPD_target_exit_data:
16206 case OMPD_target_update:
16207 case OMPD_teams:
16208 case OMPD_target:
16209 case OMPD_target_simd:
16210 case OMPD_target_parallel:
16211 case OMPD_cancel:
16212 case OMPD_parallel:
16213 case OMPD_parallel_master:
16214 case OMPD_parallel_masked:
16215 case OMPD_parallel_sections:
16216 case OMPD_threadprivate:
16217 case OMPD_allocate:
16218 case OMPD_taskyield:
16219 case OMPD_error:
16220 case OMPD_barrier:
16221 case OMPD_taskwait:
16222 case OMPD_cancellation_point:
16223 case OMPD_flush:
16224 case OMPD_depobj:
16225 case OMPD_scan:
16226 case OMPD_declare_reduction:
16227 case OMPD_declare_mapper:
16228 case OMPD_declare_simd:
16229 case OMPD_declare_variant:
16230 case OMPD_begin_declare_variant:
16231 case OMPD_end_declare_variant:
16232 case OMPD_declare_target:
16233 case OMPD_end_declare_target:
16234 case OMPD_loop:
16235 case OMPD_teams_loop:
16236 case OMPD_target_teams_loop:
16237 case OMPD_parallel_loop:
16238 case OMPD_target_parallel_loop:
16239 case OMPD_simd:
16240 case OMPD_tile:
16241 case OMPD_unroll:
16242 case OMPD_for:
16243 case OMPD_for_simd:
16244 case OMPD_sections:
16245 case OMPD_section:
16246 case OMPD_single:
16247 case OMPD_master:
16248 case OMPD_masked:
16249 case OMPD_critical:
16250 case OMPD_taskgroup:
16251 case OMPD_ordered:
16252 case OMPD_atomic:
16253 case OMPD_target_teams:
16254 case OMPD_requires:
16255 case OMPD_metadirective:
16256 llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause");
16257 case OMPD_unknown:
16258 default:
16259 llvm_unreachable("Unknown OpenMP directive");
16260 }
16261 break;
16262 case OMPC_ompx_dyn_cgroup_mem:
16263 switch (DKind) {
16264 case OMPD_target:
16265 case OMPD_target_simd:
16266 case OMPD_target_teams:
16267 case OMPD_target_parallel:
16268 case OMPD_target_teams_distribute:
16269 case OMPD_target_teams_distribute_simd:
16270 case OMPD_target_parallel_for:
16271 case OMPD_target_parallel_for_simd:
16272 case OMPD_target_parallel_loop:
16273 case OMPD_target_teams_distribute_parallel_for:
16274 case OMPD_target_teams_distribute_parallel_for_simd:
16275 case OMPD_target_teams_loop:
16276 CaptureRegion = OMPD_target;
16277 break;
16278 default:
16279 llvm_unreachable("Unknown OpenMP directive");
16280 }
16281 break;
16282 case OMPC_device:
16283 switch (DKind) {
16284 case OMPD_target_update:
16285 case OMPD_target_enter_data:
16286 case OMPD_target_exit_data:
16287 case OMPD_target:
16288 case OMPD_target_simd:
16289 case OMPD_target_teams:
16290 case OMPD_target_parallel:
16291 case OMPD_target_teams_distribute:
16292 case OMPD_target_teams_distribute_simd:
16293 case OMPD_target_parallel_for:
16294 case OMPD_target_parallel_for_simd:
16295 case OMPD_target_parallel_loop:
16296 case OMPD_target_teams_distribute_parallel_for:
16297 case OMPD_target_teams_distribute_parallel_for_simd:
16298 case OMPD_target_teams_loop:
16299 case OMPD_dispatch:
16300 CaptureRegion = OMPD_task;
16301 break;
16302 case OMPD_target_data:
16303 case OMPD_interop:
16304 // Do not capture device-clause expressions.
16305 break;
16306 case OMPD_teams_distribute_parallel_for:
16307 case OMPD_teams_distribute_parallel_for_simd:
16308 case OMPD_teams:
16309 case OMPD_teams_distribute:
16310 case OMPD_teams_distribute_simd:
16311 case OMPD_distribute_parallel_for:
16312 case OMPD_distribute_parallel_for_simd:
16313 case OMPD_task:
16314 case OMPD_taskloop:
16315 case OMPD_taskloop_simd:
16316 case OMPD_master_taskloop:
16317 case OMPD_masked_taskloop:
16318 case OMPD_master_taskloop_simd:
16319 case OMPD_masked_taskloop_simd:
16320 case OMPD_parallel_master_taskloop:
16321 case OMPD_parallel_masked_taskloop:
16322 case OMPD_parallel_master_taskloop_simd:
16323 case OMPD_parallel_masked_taskloop_simd:
16324 case OMPD_cancel:
16325 case OMPD_parallel:
16326 case OMPD_parallel_master:
16327 case OMPD_parallel_masked:
16328 case OMPD_parallel_sections:
16329 case OMPD_parallel_for:
16330 case OMPD_parallel_for_simd:
16331 case OMPD_threadprivate:
16332 case OMPD_allocate:
16333 case OMPD_taskyield:
16334 case OMPD_error:
16335 case OMPD_barrier:
16336 case OMPD_taskwait:
16337 case OMPD_cancellation_point:
16338 case OMPD_flush:
16339 case OMPD_depobj:
16340 case OMPD_scan:
16341 case OMPD_declare_reduction:
16342 case OMPD_declare_mapper:
16343 case OMPD_declare_simd:
16344 case OMPD_declare_variant:
16345 case OMPD_begin_declare_variant:
16346 case OMPD_end_declare_variant:
16347 case OMPD_declare_target:
16348 case OMPD_end_declare_target:
16349 case OMPD_loop:
16350 case OMPD_teams_loop:
16351 case OMPD_parallel_loop:
16352 case OMPD_simd:
16353 case OMPD_tile:
16354 case OMPD_unroll:
16355 case OMPD_for:
16356 case OMPD_for_simd:
16357 case OMPD_sections:
16358 case OMPD_section:
16359 case OMPD_single:
16360 case OMPD_master:
16361 case OMPD_masked:
16362 case OMPD_critical:
16363 case OMPD_taskgroup:
16364 case OMPD_distribute:
16365 case OMPD_ordered:
16366 case OMPD_atomic:
16367 case OMPD_distribute_simd:
16368 case OMPD_requires:
16369 case OMPD_metadirective:
16370 llvm_unreachable("Unexpected OpenMP directive with device-clause");
16371 case OMPD_unknown:
16372 default:
16373 llvm_unreachable("Unknown OpenMP directive");
16374 }
16375 break;
16376 case OMPC_grainsize:
16377 case OMPC_num_tasks:
16378 case OMPC_final:
16379 case OMPC_priority:
16380 switch (DKind) {
16381 case OMPD_task:
16382 case OMPD_taskloop:
16383 case OMPD_taskloop_simd:
16384 case OMPD_master_taskloop:
16385 case OMPD_masked_taskloop:
16386 case OMPD_master_taskloop_simd:
16387 case OMPD_masked_taskloop_simd:
16388 break;
16389 case OMPD_parallel_masked_taskloop:
16390 case OMPD_parallel_masked_taskloop_simd:
16391 case OMPD_parallel_master_taskloop:
16392 case OMPD_parallel_master_taskloop_simd:
16393 CaptureRegion = OMPD_parallel;
16394 break;
16395 case OMPD_target_update:
16396 case OMPD_target_enter_data:
16397 case OMPD_target_exit_data:
16398 case OMPD_target:
16399 case OMPD_target_simd:
16400 case OMPD_target_teams:
16401 case OMPD_target_parallel:
16402 case OMPD_target_teams_distribute:
16403 case OMPD_target_teams_distribute_simd:
16404 case OMPD_target_parallel_for:
16405 case OMPD_target_parallel_for_simd:
16406 case OMPD_target_teams_distribute_parallel_for:
16407 case OMPD_target_teams_distribute_parallel_for_simd:
16408 case OMPD_target_data:
16409 case OMPD_teams_distribute_parallel_for:
16410 case OMPD_teams_distribute_parallel_for_simd:
16411 case OMPD_teams:
16412 case OMPD_teams_distribute:
16413 case OMPD_teams_distribute_simd:
16414 case OMPD_distribute_parallel_for:
16415 case OMPD_distribute_parallel_for_simd:
16416 case OMPD_cancel:
16417 case OMPD_parallel:
16418 case OMPD_parallel_master:
16419 case OMPD_parallel_masked:
16420 case OMPD_parallel_sections:
16421 case OMPD_parallel_for:
16422 case OMPD_parallel_for_simd:
16423 case OMPD_threadprivate:
16424 case OMPD_allocate:
16425 case OMPD_taskyield:
16426 case OMPD_error:
16427 case OMPD_barrier:
16428 case OMPD_taskwait:
16429 case OMPD_cancellation_point:
16430 case OMPD_flush:
16431 case OMPD_depobj:
16432 case OMPD_scan:
16433 case OMPD_declare_reduction:
16434 case OMPD_declare_mapper:
16435 case OMPD_declare_simd:
16436 case OMPD_declare_variant:
16437 case OMPD_begin_declare_variant:
16438 case OMPD_end_declare_variant:
16439 case OMPD_declare_target:
16440 case OMPD_end_declare_target:
16441 case OMPD_loop:
16442 case OMPD_teams_loop:
16443 case OMPD_target_teams_loop:
16444 case OMPD_parallel_loop:
16445 case OMPD_target_parallel_loop:
16446 case OMPD_simd:
16447 case OMPD_tile:
16448 case OMPD_unroll:
16449 case OMPD_for:
16450 case OMPD_for_simd:
16451 case OMPD_sections:
16452 case OMPD_section:
16453 case OMPD_single:
16454 case OMPD_master:
16455 case OMPD_masked:
16456 case OMPD_critical:
16457 case OMPD_taskgroup:
16458 case OMPD_distribute:
16459 case OMPD_ordered:
16460 case OMPD_atomic:
16461 case OMPD_distribute_simd:
16462 case OMPD_requires:
16463 case OMPD_metadirective:
16464 llvm_unreachable("Unexpected OpenMP directive with grainsize-clause");
16465 case OMPD_unknown:
16466 default:
16467 llvm_unreachable("Unknown OpenMP directive");
16468 }
16469 break;
16470 case OMPC_novariants:
16471 case OMPC_nocontext:
16472 switch (DKind) {
16473 case OMPD_dispatch:
16474 CaptureRegion = OMPD_task;
16475 break;
16476 default:
16477 llvm_unreachable("Unexpected OpenMP directive");
16478 }
16479 break;
16480 case OMPC_filter:
16481 // Do not capture filter-clause expressions.
16482 break;
16483 case OMPC_when:
16484 if (DKind == OMPD_metadirective) {
16485 CaptureRegion = OMPD_metadirective;
16486 } else if (DKind == OMPD_unknown) {
16487 llvm_unreachable("Unknown OpenMP directive");
16488 } else {
16489 llvm_unreachable("Unexpected OpenMP directive with when clause");
16490 }
16491 break;
16492 case OMPC_firstprivate:
16493 case OMPC_lastprivate:
16494 case OMPC_reduction:
16495 case OMPC_task_reduction:
16496 case OMPC_in_reduction:
16497 case OMPC_linear:
16498 case OMPC_default:
16499 case OMPC_proc_bind:
16500 case OMPC_safelen:
16501 case OMPC_simdlen:
16502 case OMPC_sizes:
16503 case OMPC_allocator:
16504 case OMPC_collapse:
16505 case OMPC_private:
16506 case OMPC_shared:
16507 case OMPC_aligned:
16508 case OMPC_copyin:
16509 case OMPC_copyprivate:
16510 case OMPC_ordered:
16511 case OMPC_nowait:
16512 case OMPC_untied:
16513 case OMPC_mergeable:
16514 case OMPC_threadprivate:
16515 case OMPC_allocate:
16516 case OMPC_flush:
16517 case OMPC_depobj:
16518 case OMPC_read:
16519 case OMPC_write:
16520 case OMPC_update:
16521 case OMPC_capture:
16522 case OMPC_compare:
16523 case OMPC_seq_cst:
16524 case OMPC_acq_rel:
16525 case OMPC_acquire:
16526 case OMPC_release:
16527 case OMPC_relaxed:
16528 case OMPC_depend:
16529 case OMPC_threads:
16530 case OMPC_simd:
16531 case OMPC_map:
16532 case OMPC_nogroup:
16533 case OMPC_hint:
16534 case OMPC_defaultmap:
16535 case OMPC_unknown:
16536 case OMPC_uniform:
16537 case OMPC_to:
16538 case OMPC_from:
16539 case OMPC_use_device_ptr:
16540 case OMPC_use_device_addr:
16541 case OMPC_is_device_ptr:
16542 case OMPC_unified_address:
16543 case OMPC_unified_shared_memory:
16544 case OMPC_reverse_offload:
16545 case OMPC_dynamic_allocators:
16546 case OMPC_atomic_default_mem_order:
16547 case OMPC_device_type:
16548 case OMPC_match:
16549 case OMPC_nontemporal:
16550 case OMPC_order:
16551 case OMPC_at:
16552 case OMPC_severity:
16553 case OMPC_message:
16554 case OMPC_destroy:
16555 case OMPC_detach:
16556 case OMPC_inclusive:
16557 case OMPC_exclusive:
16558 case OMPC_uses_allocators:
16559 case OMPC_affinity:
16560 case OMPC_bind:
16561 default:
16562 llvm_unreachable("Unexpected OpenMP clause.");
16563 }
16564 return CaptureRegion;
16565}
16566
16567OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
16568 Expr *Condition, SourceLocation StartLoc,
16569 SourceLocation LParenLoc,
16570 SourceLocation NameModifierLoc,
16571 SourceLocation ColonLoc,
16572 SourceLocation EndLoc) {
16573 Expr *ValExpr = Condition;
16574 Stmt *HelperValStmt = nullptr;
16575 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16576 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16577 !Condition->isInstantiationDependent() &&
16578 !Condition->containsUnexpandedParameterPack()) {
16579 ExprResult Val = CheckBooleanCondition(Loc: StartLoc, E: Condition);
16580 if (Val.isInvalid())
16581 return nullptr;
16582
16583 ValExpr = Val.get();
16584
16585 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16586 CaptureRegion = getOpenMPCaptureRegionForClause(
16587 DKind, OMPC_if, LangOpts.OpenMP, NameModifier);
16588 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16589 ValExpr = MakeFullExpr(Arg: ValExpr).get();
16590 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16591 ValExpr = tryBuildCapture(SemaRef&: *this, Capture: ValExpr, Captures).get();
16592 HelperValStmt = buildPreInits(Context, Captures);
16593 }
16594 }
16595
16596 return new (Context)
16597 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16598 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16599}
16600
16601OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition,
16602 SourceLocation StartLoc,
16603 SourceLocation LParenLoc,
16604 SourceLocation EndLoc) {
16605 Expr *ValExpr = Condition;
16606 Stmt *HelperValStmt = nullptr;
16607 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16608 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16609 !Condition->isInstantiationDependent() &&
16610 !Condition->containsUnexpandedParameterPack()) {
16611 ExprResult Val = CheckBooleanCondition(Loc: StartLoc, E: Condition);
16612 if (Val.isInvalid())
16613 return nullptr;
16614
16615 ValExpr = MakeFullExpr(Arg: Val.get()).get();
16616
16617 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16618 CaptureRegion =
16619 getOpenMPCaptureRegionForClause(DKind, OMPC_final, LangOpts.OpenMP);
16620 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16621 ValExpr = MakeFullExpr(Arg: ValExpr).get();
16622 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16623 ValExpr = tryBuildCapture(SemaRef&: *this, Capture: ValExpr, Captures).get();
16624 HelperValStmt = buildPreInits(Context, Captures);
16625 }
16626 }
16627
16628 return new (Context) OMPFinalClause(ValExpr, HelperValStmt, CaptureRegion,
16629 StartLoc, LParenLoc, EndLoc);
16630}
16631
16632ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
16633 Expr *Op) {
16634 if (!Op)
16635 return ExprError();
16636
16637 class IntConvertDiagnoser : public ICEConvertDiagnoser {
16638 public:
16639 IntConvertDiagnoser()
16640 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
16641 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16642 QualType T) override {
16643 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16644 }
16645 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16646 QualType T) override {
16647 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16648 }
16649 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16650 QualType T,
16651 QualType ConvTy) override {
16652 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16653 }
16654 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16655 QualType ConvTy) override {
16656 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16657 << ConvTy->isEnumeralType() << ConvTy;
16658 }
16659 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16660 QualType T) override {
16661 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16662 }
16663 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16664 QualType ConvTy) override {
16665 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16666 << ConvTy->isEnumeralType() << ConvTy;
16667 }
16668 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16669 QualType) override {
16670 llvm_unreachable("conversion functions are permitted");
16671 }
16672 } ConvertDiagnoser;
16673 return PerformContextualImplicitConversion(Loc, FromE: Op, Converter&: ConvertDiagnoser);
16674}
16675
16676static bool
16677isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
16678 bool StrictlyPositive, bool BuildCapture = false,
16679 OpenMPDirectiveKind DKind = OMPD_unknown,
16680 OpenMPDirectiveKind *CaptureRegion = nullptr,
16681 Stmt **HelperValStmt = nullptr) {
16682 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16683 !ValExpr->isInstantiationDependent()) {
16684 SourceLocation Loc = ValExpr->getExprLoc();
16685 ExprResult Value =
16686 SemaRef.PerformOpenMPImplicitIntegerConversion(Loc, Op: ValExpr);
16687 if (Value.isInvalid())
16688 return false;
16689
16690 ValExpr = Value.get();
16691 // The expression must evaluate to a non-negative integer value.
16692 if (std::optional<llvm::APSInt> Result =
16693 ValExpr->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
16694 if (Result->isSigned() &&
16695 !((!StrictlyPositive && Result->isNonNegative()) ||
16696 (StrictlyPositive && Result->isStrictlyPositive()))) {
16697 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16698 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16699 << ValExpr->getSourceRange();
16700 return false;
16701 }
16702 }
16703 if (!BuildCapture)
16704 return true;
16705 *CaptureRegion =
16706 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16707 if (*CaptureRegion != OMPD_unknown &&
16708 !SemaRef.CurContext->isDependentContext()) {
16709 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
16710 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16711 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
16712 *HelperValStmt = buildPreInits(Context&: SemaRef.Context, Captures);
16713 }
16714 }
16715 return true;
16716}
16717
16718OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
16719 SourceLocation StartLoc,
16720 SourceLocation LParenLoc,
16721 SourceLocation EndLoc) {
16722 Expr *ValExpr = NumThreads;
16723 Stmt *HelperValStmt = nullptr;
16724
16725 // OpenMP [2.5, Restrictions]
16726 // The num_threads expression must evaluate to a positive integer value.
16727 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
16728 /*StrictlyPositive=*/true))
16729 return nullptr;
16730
16731 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16732 OpenMPDirectiveKind CaptureRegion =
16733 getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads, LangOpts.OpenMP);
16734 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16735 ValExpr = MakeFullExpr(Arg: ValExpr).get();
16736 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16737 ValExpr = tryBuildCapture(SemaRef&: *this, Capture: ValExpr, Captures).get();
16738 HelperValStmt = buildPreInits(Context, Captures);
16739 }
16740
16741 return new (Context) OMPNumThreadsClause(
16742 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16743}
16744
16745ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
16746 OpenMPClauseKind CKind,
16747 bool StrictlyPositive,
16748 bool SuppressExprDiags) {
16749 if (!E)
16750 return ExprError();
16751 if (E->isValueDependent() || E->isTypeDependent() ||
16752 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
16753 return E;
16754
16755 llvm::APSInt Result;
16756 ExprResult ICE;
16757 if (SuppressExprDiags) {
16758 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16759 // expression.
16760 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16761 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16762 Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
16763 SourceLocation Loc) override {
16764 llvm_unreachable("Diagnostic suppressed");
16765 }
16766 } Diagnoser;
16767 ICE = VerifyIntegerConstantExpression(E, Result: &Result, Diagnoser, CanFold: AllowFold);
16768 } else {
16769 ICE = VerifyIntegerConstantExpression(E, Result: &Result, /*FIXME*/ CanFold: AllowFold);
16770 }
16771 if (ICE.isInvalid())
16772 return ExprError();
16773
16774 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16775 (!StrictlyPositive && !Result.isNonNegative())) {
16776 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16777 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16778 << E->getSourceRange();
16779 return ExprError();
16780 }
16781 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
16782 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16783 << E->getSourceRange();
16784 return ExprError();
16785 }
16786 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16787 DSAStack->setAssociatedLoops(Result.getExtValue());
16788 else if (CKind == OMPC_ordered)
16789 DSAStack->setAssociatedLoops(Result.getExtValue());
16790 return ICE;
16791}
16792
16793OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc,
16794 SourceLocation LParenLoc,
16795 SourceLocation EndLoc) {
16796 // OpenMP [2.8.1, simd construct, Description]
16797 // The parameter of the safelen clause must be a constant
16798 // positive integer expression.
16799 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16800 if (Safelen.isInvalid())
16801 return nullptr;
16802 return new (Context)
16803 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16804}
16805
16806OMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc,
16807 SourceLocation LParenLoc,
16808 SourceLocation EndLoc) {
16809 // OpenMP [2.8.1, simd construct, Description]
16810 // The parameter of the simdlen clause must be a constant
16811 // positive integer expression.
16812 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
16813 if (Simdlen.isInvalid())
16814 return nullptr;
16815 return new (Context)
16816 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16817}
16818
16819/// Tries to find omp_allocator_handle_t type.
16820static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
16821 DSAStackTy *Stack) {
16822 if (!Stack->getOMPAllocatorHandleT().isNull())
16823 return true;
16824
16825 // Set the allocator handle type.
16826 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_allocator_handle_t");
16827 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
16828 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
16829 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16830 << "omp_allocator_handle_t";
16831 return false;
16832 }
16833 QualType AllocatorHandleEnumTy = PT.get();
16834 AllocatorHandleEnumTy.addConst();
16835 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16836
16837 // Fill the predefined allocator map.
16838 bool ErrorFound = false;
16839 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16840 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16841 StringRef Allocator =
16842 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16843 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
16844 auto *VD = dyn_cast_or_null<ValueDecl>(
16845 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
16846 if (!VD) {
16847 ErrorFound = true;
16848 break;
16849 }
16850 QualType AllocatorType =
16851 VD->getType().getNonLValueExprType(S.getASTContext());
16852 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
16853 if (!Res.isUsable()) {
16854 ErrorFound = true;
16855 break;
16856 }
16857 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
16858 Sema::AA_Initializing,
16859 /* AllowExplicit */ true);
16860 if (!Res.isUsable()) {
16861 ErrorFound = true;
16862 break;
16863 }
16864 Stack->setAllocator(AllocatorKind, Res.get());
16865 }
16866 if (ErrorFound) {
16867 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16868 << "omp_allocator_handle_t";
16869 return false;
16870 }
16871
16872 return true;
16873}
16874
16875OMPClause *Sema::ActOnOpenMPAllocatorClause(Expr *A, SourceLocation StartLoc,
16876 SourceLocation LParenLoc,
16877 SourceLocation EndLoc) {
16878 // OpenMP [2.11.3, allocate Directive, Description]
16879 // allocator is an expression of omp_allocator_handle_t type.
16880 if (!findOMPAllocatorHandleT(S&: *this, Loc: A->getExprLoc(), DSAStack))
16881 return nullptr;
16882
16883 ExprResult Allocator = DefaultLvalueConversion(E: A);
16884 if (Allocator.isInvalid())
16885 return nullptr;
16886 Allocator = PerformImplicitConversion(From: Allocator.get(),
16887 DSAStack->getOMPAllocatorHandleT(),
16888 Action: Sema::AA_Initializing,
16889 /*AllowExplicit=*/true);
16890 if (Allocator.isInvalid())
16891 return nullptr;
16892 return new (Context)
16893 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
16894}
16895
16896OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,
16897 SourceLocation StartLoc,
16898 SourceLocation LParenLoc,
16899 SourceLocation EndLoc) {
16900 // OpenMP [2.7.1, loop construct, Description]
16901 // OpenMP [2.8.1, simd construct, Description]
16902 // OpenMP [2.9.6, distribute construct, Description]
16903 // The parameter of the collapse clause must be a constant
16904 // positive integer expression.
16905 ExprResult NumForLoopsResult =
16906 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
16907 if (NumForLoopsResult.isInvalid())
16908 return nullptr;
16909 return new (Context)
16910 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
16911}
16912
16913OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
16914 SourceLocation EndLoc,
16915 SourceLocation LParenLoc,
16916 Expr *NumForLoops) {
16917 // OpenMP [2.7.1, loop construct, Description]
16918 // OpenMP [2.8.1, simd construct, Description]
16919 // OpenMP [2.9.6, distribute construct, Description]
16920 // The parameter of the ordered clause must be a constant
16921 // positive integer expression if any.
16922 if (NumForLoops && LParenLoc.isValid()) {
16923 ExprResult NumForLoopsResult =
16924 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
16925 if (NumForLoopsResult.isInvalid())
16926 return nullptr;
16927 NumForLoops = NumForLoopsResult.get();
16928 } else {
16929 NumForLoops = nullptr;
16930 }
16931 auto *Clause = OMPOrderedClause::Create(
16932 C: Context, Num: NumForLoops, NumLoops: NumForLoops ? DSAStack->getAssociatedLoops() : 0,
16933 StartLoc, LParenLoc, EndLoc);
16934 DSAStack->setOrderedRegion(/*IsOrdered=*/true, Param: NumForLoops, Clause);
16935 return Clause;
16936}
16937
16938OMPClause *Sema::ActOnOpenMPSimpleClause(
16939 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
16940 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16941 OMPClause *Res = nullptr;
16942 switch (Kind) {
16943 case OMPC_default:
16944 Res = ActOnOpenMPDefaultClause(Kind: static_cast<DefaultKind>(Argument),
16945 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16946 break;
16947 case OMPC_proc_bind:
16948 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
16949 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16950 break;
16951 case OMPC_atomic_default_mem_order:
16952 Res = ActOnOpenMPAtomicDefaultMemOrderClause(
16953 Kind: static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
16954 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16955 break;
16956 case OMPC_fail:
16957 Res = ActOnOpenMPFailClause(
16958 static_cast<OpenMPClauseKind>(Argument),
16959 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16960 break;
16961 case OMPC_update:
16962 Res = ActOnOpenMPUpdateClause(Kind: static_cast<OpenMPDependClauseKind>(Argument),
16963 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16964 break;
16965 case OMPC_bind:
16966 Res = ActOnOpenMPBindClause(Kind: static_cast<OpenMPBindClauseKind>(Argument),
16967 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16968 break;
16969 case OMPC_at:
16970 Res = ActOnOpenMPAtClause(Kind: static_cast<OpenMPAtClauseKind>(Argument),
16971 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16972 break;
16973 case OMPC_severity:
16974 Res = ActOnOpenMPSeverityClause(
16975 Kind: static_cast<OpenMPSeverityClauseKind>(Argument), KindLoc: ArgumentLoc, StartLoc,
16976 LParenLoc, EndLoc);
16977 break;
16978 case OMPC_if:
16979 case OMPC_final:
16980 case OMPC_num_threads:
16981 case OMPC_safelen:
16982 case OMPC_simdlen:
16983 case OMPC_sizes:
16984 case OMPC_allocator:
16985 case OMPC_collapse:
16986 case OMPC_schedule:
16987 case OMPC_private:
16988 case OMPC_firstprivate:
16989 case OMPC_lastprivate:
16990 case OMPC_shared:
16991 case OMPC_reduction:
16992 case OMPC_task_reduction:
16993 case OMPC_in_reduction:
16994 case OMPC_linear:
16995 case OMPC_aligned:
16996 case OMPC_copyin:
16997 case OMPC_copyprivate:
16998 case OMPC_ordered:
16999 case OMPC_nowait:
17000 case OMPC_untied:
17001 case OMPC_mergeable:
17002 case OMPC_threadprivate:
17003 case OMPC_allocate:
17004 case OMPC_flush:
17005 case OMPC_depobj:
17006 case OMPC_read:
17007 case OMPC_write:
17008 case OMPC_capture:
17009 case OMPC_compare:
17010 case OMPC_seq_cst:
17011 case OMPC_acq_rel:
17012 case OMPC_acquire:
17013 case OMPC_release:
17014 case OMPC_relaxed:
17015 case OMPC_depend:
17016 case OMPC_device:
17017 case OMPC_threads:
17018 case OMPC_simd:
17019 case OMPC_map:
17020 case OMPC_num_teams:
17021 case OMPC_thread_limit:
17022 case OMPC_priority:
17023 case OMPC_grainsize:
17024 case OMPC_nogroup:
17025 case OMPC_num_tasks:
17026 case OMPC_hint:
17027 case OMPC_dist_schedule:
17028 case OMPC_defaultmap:
17029 case OMPC_unknown:
17030 case OMPC_uniform:
17031 case OMPC_to:
17032 case OMPC_from:
17033 case OMPC_use_device_ptr:
17034 case OMPC_use_device_addr:
17035 case OMPC_is_device_ptr:
17036 case OMPC_has_device_addr:
17037 case OMPC_unified_address:
17038 case OMPC_unified_shared_memory:
17039 case OMPC_reverse_offload:
17040 case OMPC_dynamic_allocators:
17041 case OMPC_device_type:
17042 case OMPC_match:
17043 case OMPC_nontemporal:
17044 case OMPC_destroy:
17045 case OMPC_novariants:
17046 case OMPC_nocontext:
17047 case OMPC_detach:
17048 case OMPC_inclusive:
17049 case OMPC_exclusive:
17050 case OMPC_uses_allocators:
17051 case OMPC_affinity:
17052 case OMPC_when:
17053 case OMPC_message:
17054 default:
17055 llvm_unreachable("Clause is not allowed.");
17056 }
17057 return Res;
17058}
17059
17060static std::string
17061getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last,
17062 ArrayRef<unsigned> Exclude = std::nullopt) {
17063 SmallString<256> Buffer;
17064 llvm::raw_svector_ostream Out(Buffer);
17065 unsigned Skipped = Exclude.size();
17066 for (unsigned I = First; I < Last; ++I) {
17067 if (llvm::is_contained(Range&: Exclude, Element: I)) {
17068 --Skipped;
17069 continue;
17070 }
17071 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
17072 if (I + Skipped + 2 == Last)
17073 Out << " or ";
17074 else if (I + Skipped + 1 != Last)
17075 Out << ", ";
17076 }
17077 return std::string(Out.str());
17078}
17079
17080OMPClause *Sema::ActOnOpenMPDefaultClause(DefaultKind Kind,
17081 SourceLocation KindKwLoc,
17082 SourceLocation StartLoc,
17083 SourceLocation LParenLoc,
17084 SourceLocation EndLoc) {
17085 if (Kind == OMP_DEFAULT_unknown) {
17086 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17087 << getListOfPossibleValues(OMPC_default, /*First=*/0,
17088 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17089 << getOpenMPClauseName(OMPC_default);
17090 return nullptr;
17091 }
17092
17093 switch (Kind) {
17094 case OMP_DEFAULT_none:
17095 DSAStack->setDefaultDSANone(KindKwLoc);
17096 break;
17097 case OMP_DEFAULT_shared:
17098 DSAStack->setDefaultDSAShared(KindKwLoc);
17099 break;
17100 case OMP_DEFAULT_firstprivate:
17101 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
17102 break;
17103 case OMP_DEFAULT_private:
17104 DSAStack->setDefaultDSAPrivate(KindKwLoc);
17105 break;
17106 default:
17107 llvm_unreachable("DSA unexpected in OpenMP default clause");
17108 }
17109
17110 return new (Context)
17111 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17112}
17113
17114OMPClause *Sema::ActOnOpenMPProcBindClause(ProcBindKind Kind,
17115 SourceLocation KindKwLoc,
17116 SourceLocation StartLoc,
17117 SourceLocation LParenLoc,
17118 SourceLocation EndLoc) {
17119 if (Kind == OMP_PROC_BIND_unknown) {
17120 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17121 << getListOfPossibleValues(OMPC_proc_bind,
17122 /*First=*/unsigned(OMP_PROC_BIND_master),
17123 /*Last=*/
17124 unsigned(LangOpts.OpenMP > 50
17125 ? OMP_PROC_BIND_primary
17126 : OMP_PROC_BIND_spread) +
17127 1)
17128 << getOpenMPClauseName(OMPC_proc_bind);
17129 return nullptr;
17130 }
17131 if (Kind == OMP_PROC_BIND_primary && LangOpts.OpenMP < 51)
17132 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17133 << getListOfPossibleValues(OMPC_proc_bind,
17134 /*First=*/unsigned(OMP_PROC_BIND_master),
17135 /*Last=*/
17136 unsigned(OMP_PROC_BIND_spread) + 1)
17137 << getOpenMPClauseName(OMPC_proc_bind);
17138 return new (Context)
17139 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17140}
17141
17142OMPClause *Sema::ActOnOpenMPAtomicDefaultMemOrderClause(
17143 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
17144 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17145 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
17146 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17147 << getListOfPossibleValues(
17148 OMPC_atomic_default_mem_order, /*First=*/0,
17149 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
17150 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
17151 return nullptr;
17152 }
17153 return new (Context) OMPAtomicDefaultMemOrderClause(Kind, KindKwLoc, StartLoc,
17154 LParenLoc, EndLoc);
17155}
17156
17157OMPClause *Sema::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
17158 SourceLocation KindKwLoc,
17159 SourceLocation StartLoc,
17160 SourceLocation LParenLoc,
17161 SourceLocation EndLoc) {
17162 if (Kind == OMPC_AT_unknown) {
17163 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17164 << getListOfPossibleValues(OMPC_at, /*First=*/0,
17165 /*Last=*/OMPC_AT_unknown)
17166 << getOpenMPClauseName(OMPC_at);
17167 return nullptr;
17168 }
17169 return new (Context)
17170 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17171}
17172
17173OMPClause *Sema::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
17174 SourceLocation KindKwLoc,
17175 SourceLocation StartLoc,
17176 SourceLocation LParenLoc,
17177 SourceLocation EndLoc) {
17178 if (Kind == OMPC_SEVERITY_unknown) {
17179 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17180 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
17181 /*Last=*/OMPC_SEVERITY_unknown)
17182 << getOpenMPClauseName(OMPC_severity);
17183 return nullptr;
17184 }
17185 return new (Context)
17186 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17187}
17188
17189OMPClause *Sema::ActOnOpenMPMessageClause(Expr *ME, SourceLocation StartLoc,
17190 SourceLocation LParenLoc,
17191 SourceLocation EndLoc) {
17192 assert(ME && "NULL expr in Message clause");
17193 if (!isa<StringLiteral>(Val: ME)) {
17194 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
17195 << getOpenMPClauseName(OMPC_message);
17196 return nullptr;
17197 }
17198 return new (Context) OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
17199}
17200
17201OMPClause *Sema::ActOnOpenMPOrderClause(
17202 OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind,
17203 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
17204 SourceLocation KindLoc, SourceLocation EndLoc) {
17205 if (Kind != OMPC_ORDER_concurrent ||
17206 (LangOpts.OpenMP < 51 && MLoc.isValid())) {
17207 // Kind should be concurrent,
17208 // Modifiers introduced in OpenMP 5.1
17209 static_assert(OMPC_ORDER_unknown > 0,
17210 "OMPC_ORDER_unknown not greater than 0");
17211
17212 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17213 << getListOfPossibleValues(OMPC_order,
17214 /*First=*/0,
17215 /*Last=*/OMPC_ORDER_unknown)
17216 << getOpenMPClauseName(OMPC_order);
17217 return nullptr;
17218 }
17219 if (LangOpts.OpenMP >= 51) {
17220 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
17221 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17222 << getListOfPossibleValues(OMPC_order,
17223 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
17224 /*Last=*/OMPC_ORDER_MODIFIER_last)
17225 << getOpenMPClauseName(OMPC_order);
17226 } else {
17227 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17228 if (DSAStack->getCurScope()) {
17229 // mark the current scope with 'order' flag
17230 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
17231 DSAStack->getCurScope()->setFlags(existingFlags |
17232 Scope::OpenMPOrderClauseScope);
17233 }
17234 }
17235 }
17236 return new (Context) OMPOrderClause(Kind, KindLoc, StartLoc, LParenLoc,
17237 EndLoc, Modifier, MLoc);
17238}
17239
17240OMPClause *Sema::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,
17241 SourceLocation KindKwLoc,
17242 SourceLocation StartLoc,
17243 SourceLocation LParenLoc,
17244 SourceLocation EndLoc) {
17245 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
17246 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17247 SmallVector<unsigned> Except = {
17248 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17249 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17250 if (LangOpts.OpenMP < 51)
17251 Except.push_back(Elt: OMPC_DEPEND_inoutset);
17252 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17253 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
17254 /*Last=*/OMPC_DEPEND_unknown, Except)
17255 << getOpenMPClauseName(OMPC_update);
17256 return nullptr;
17257 }
17258 return OMPUpdateClause::Create(C: Context, StartLoc, LParenLoc, ArgumentLoc: KindKwLoc, DK: Kind,
17259 EndLoc);
17260}
17261
17262OMPClause *Sema::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
17263 SourceLocation StartLoc,
17264 SourceLocation LParenLoc,
17265 SourceLocation EndLoc) {
17266 for (Expr *SizeExpr : SizeExprs) {
17267 ExprResult NumForLoopsResult = VerifyPositiveIntegerConstantInClause(
17268 SizeExpr, OMPC_sizes, /*StrictlyPositive=*/true);
17269 if (!NumForLoopsResult.isUsable())
17270 return nullptr;
17271 }
17272
17273 DSAStack->setAssociatedLoops(SizeExprs.size());
17274 return OMPSizesClause::Create(C: Context, StartLoc, LParenLoc, EndLoc,
17275 Sizes: SizeExprs);
17276}
17277
17278OMPClause *Sema::ActOnOpenMPFullClause(SourceLocation StartLoc,
17279 SourceLocation EndLoc) {
17280 return OMPFullClause::Create(C: Context, StartLoc, EndLoc);
17281}
17282
17283OMPClause *Sema::ActOnOpenMPPartialClause(Expr *FactorExpr,
17284 SourceLocation StartLoc,
17285 SourceLocation LParenLoc,
17286 SourceLocation EndLoc) {
17287 if (FactorExpr) {
17288 // If an argument is specified, it must be a constant (or an unevaluated
17289 // template expression).
17290 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
17291 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
17292 if (FactorResult.isInvalid())
17293 return nullptr;
17294 FactorExpr = FactorResult.get();
17295 }
17296
17297 return OMPPartialClause::Create(C: Context, StartLoc, LParenLoc, EndLoc,
17298 Factor: FactorExpr);
17299}
17300
17301OMPClause *Sema::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
17302 SourceLocation LParenLoc,
17303 SourceLocation EndLoc) {
17304 ExprResult AlignVal;
17305 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
17306 if (AlignVal.isInvalid())
17307 return nullptr;
17308 return OMPAlignClause::Create(C: Context, A: AlignVal.get(), StartLoc, LParenLoc,
17309 EndLoc);
17310}
17311
17312OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
17313 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
17314 SourceLocation StartLoc, SourceLocation LParenLoc,
17315 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
17316 SourceLocation EndLoc) {
17317 OMPClause *Res = nullptr;
17318 switch (Kind) {
17319 case OMPC_schedule:
17320 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17321 assert(Argument.size() == NumberOfElements &&
17322 ArgumentLoc.size() == NumberOfElements);
17323 Res = ActOnOpenMPScheduleClause(
17324 M1: static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
17325 M2: static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17326 Kind: static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), ChunkSize: Expr,
17327 StartLoc, LParenLoc, M1Loc: ArgumentLoc[Modifier1], M2Loc: ArgumentLoc[Modifier2],
17328 KindLoc: ArgumentLoc[ScheduleKind], CommaLoc: DelimLoc, EndLoc);
17329 break;
17330 case OMPC_if:
17331 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17332 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17333 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17334 DelimLoc, EndLoc);
17335 break;
17336 case OMPC_dist_schedule:
17337 Res = ActOnOpenMPDistScheduleClause(
17338 Kind: static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), ChunkSize: Expr,
17339 StartLoc, LParenLoc, KindLoc: ArgumentLoc.back(), CommaLoc: DelimLoc, EndLoc);
17340 break;
17341 case OMPC_defaultmap:
17342 enum { Modifier, DefaultmapKind };
17343 Res = ActOnOpenMPDefaultmapClause(
17344 M: static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17345 Kind: static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17346 StartLoc, LParenLoc, MLoc: ArgumentLoc[Modifier], KindLoc: ArgumentLoc[DefaultmapKind],
17347 EndLoc);
17348 break;
17349 case OMPC_order:
17350 enum { OrderModifier, OrderKind };
17351 Res = ActOnOpenMPOrderClause(
17352 Modifier: static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17353 Kind: static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17354 LParenLoc, MLoc: ArgumentLoc[OrderModifier], KindLoc: ArgumentLoc[OrderKind], EndLoc);
17355 break;
17356 case OMPC_device:
17357 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17358 Res = ActOnOpenMPDeviceClause(
17359 Modifier: static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Device: Expr,
17360 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
17361 break;
17362 case OMPC_grainsize:
17363 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17364 "Modifier for grainsize clause and its location are expected.");
17365 Res = ActOnOpenMPGrainsizeClause(
17366 Modifier: static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Size: Expr,
17367 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
17368 break;
17369 case OMPC_num_tasks:
17370 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17371 "Modifier for num_tasks clause and its location are expected.");
17372 Res = ActOnOpenMPNumTasksClause(
17373 Modifier: static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), NumTasks: Expr,
17374 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
17375 break;
17376 case OMPC_final:
17377 case OMPC_num_threads:
17378 case OMPC_safelen:
17379 case OMPC_simdlen:
17380 case OMPC_sizes:
17381 case OMPC_allocator:
17382 case OMPC_collapse:
17383 case OMPC_default:
17384 case OMPC_proc_bind:
17385 case OMPC_private:
17386 case OMPC_firstprivate:
17387 case OMPC_lastprivate:
17388 case OMPC_shared:
17389 case OMPC_reduction:
17390 case OMPC_task_reduction:
17391 case OMPC_in_reduction:
17392 case OMPC_linear:
17393 case OMPC_aligned:
17394 case OMPC_copyin:
17395 case OMPC_copyprivate:
17396 case OMPC_ordered:
17397 case OMPC_nowait:
17398 case OMPC_untied:
17399 case OMPC_mergeable:
17400 case OMPC_threadprivate:
17401 case OMPC_allocate:
17402 case OMPC_flush:
17403 case OMPC_depobj:
17404 case OMPC_read:
17405 case OMPC_write:
17406 case OMPC_update:
17407 case OMPC_capture:
17408 case OMPC_compare:
17409 case OMPC_seq_cst:
17410 case OMPC_acq_rel:
17411 case OMPC_acquire:
17412 case OMPC_release:
17413 case OMPC_relaxed:
17414 case OMPC_depend:
17415 case OMPC_threads:
17416 case OMPC_simd:
17417 case OMPC_map:
17418 case OMPC_num_teams:
17419 case OMPC_thread_limit:
17420 case OMPC_priority:
17421 case OMPC_nogroup:
17422 case OMPC_hint:
17423 case OMPC_unknown:
17424 case OMPC_uniform:
17425 case OMPC_to:
17426 case OMPC_from:
17427 case OMPC_use_device_ptr:
17428 case OMPC_use_device_addr:
17429 case OMPC_is_device_ptr:
17430 case OMPC_has_device_addr:
17431 case OMPC_unified_address:
17432 case OMPC_unified_shared_memory:
17433 case OMPC_reverse_offload:
17434 case OMPC_dynamic_allocators:
17435 case OMPC_atomic_default_mem_order:
17436 case OMPC_device_type:
17437 case OMPC_match:
17438 case OMPC_nontemporal:
17439 case OMPC_at:
17440 case OMPC_severity:
17441 case OMPC_message:
17442 case OMPC_destroy:
17443 case OMPC_novariants:
17444 case OMPC_nocontext:
17445 case OMPC_detach:
17446 case OMPC_inclusive:
17447 case OMPC_exclusive:
17448 case OMPC_uses_allocators:
17449 case OMPC_affinity:
17450 case OMPC_when:
17451 case OMPC_bind:
17452 default:
17453 llvm_unreachable("Clause is not allowed.");
17454 }
17455 return Res;
17456}
17457
17458static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
17459 OpenMPScheduleClauseModifier M2,
17460 SourceLocation M1Loc, SourceLocation M2Loc) {
17461 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
17462 SmallVector<unsigned, 2> Excluded;
17463 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
17464 Excluded.push_back(Elt: M2);
17465 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17466 Excluded.push_back(Elt: OMPC_SCHEDULE_MODIFIER_monotonic);
17467 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17468 Excluded.push_back(Elt: OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17469 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17470 << getListOfPossibleValues(OMPC_schedule,
17471 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
17472 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
17473 Excluded)
17474 << getOpenMPClauseName(OMPC_schedule);
17475 return true;
17476 }
17477 return false;
17478}
17479
17480OMPClause *Sema::ActOnOpenMPScheduleClause(
17481 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
17482 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
17483 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
17484 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
17485 if (checkScheduleModifiers(S&: *this, M1, M2, M1Loc, M2Loc) ||
17486 checkScheduleModifiers(S&: *this, M1: M2, M2: M1, M1Loc: M2Loc, M2Loc: M1Loc))
17487 return nullptr;
17488 // OpenMP, 2.7.1, Loop Construct, Restrictions
17489 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17490 // but not both.
17491 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
17492 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17493 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17494 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17495 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17496 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17497 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
17498 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
17499 return nullptr;
17500 }
17501 if (Kind == OMPC_SCHEDULE_unknown) {
17502 std::string Values;
17503 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
17504 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
17505 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17506 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
17507 Exclude);
17508 } else {
17509 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17510 /*Last=*/OMPC_SCHEDULE_unknown);
17511 }
17512 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17513 << Values << getOpenMPClauseName(OMPC_schedule);
17514 return nullptr;
17515 }
17516 // OpenMP, 2.7.1, Loop Construct, Restrictions
17517 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17518 // schedule(guided).
17519 // OpenMP 5.0 does not have this restriction.
17520 if (LangOpts.OpenMP < 50 &&
17521 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17522 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17523 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17524 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17525 diag::err_omp_schedule_nonmonotonic_static);
17526 return nullptr;
17527 }
17528 Expr *ValExpr = ChunkSize;
17529 Stmt *HelperValStmt = nullptr;
17530 if (ChunkSize) {
17531 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
17532 !ChunkSize->isInstantiationDependent() &&
17533 !ChunkSize->containsUnexpandedParameterPack()) {
17534 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
17535 ExprResult Val =
17536 PerformOpenMPImplicitIntegerConversion(Loc: ChunkSizeLoc, Op: ChunkSize);
17537 if (Val.isInvalid())
17538 return nullptr;
17539
17540 ValExpr = Val.get();
17541
17542 // OpenMP [2.7.1, Restrictions]
17543 // chunk_size must be a loop invariant integer expression with a positive
17544 // value.
17545 if (std::optional<llvm::APSInt> Result =
17546 ValExpr->getIntegerConstantExpr(Ctx: Context)) {
17547 if (Result->isSigned() && !Result->isStrictlyPositive()) {
17548 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
17549 << "schedule" << 1 << ChunkSize->getSourceRange();
17550 return nullptr;
17551 }
17552 } else if (getOpenMPCaptureRegionForClause(
17553 DSAStack->getCurrentDirective(), OMPC_schedule,
17554 LangOpts.OpenMP) != OMPD_unknown &&
17555 !CurContext->isDependentContext()) {
17556 ValExpr = MakeFullExpr(Arg: ValExpr).get();
17557 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17558 ValExpr = tryBuildCapture(SemaRef&: *this, Capture: ValExpr, Captures).get();
17559 HelperValStmt = buildPreInits(Context, Captures);
17560 }
17561 }
17562 }
17563
17564 return new (Context)
17565 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
17566 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
17567}
17568
17569OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
17570 SourceLocation StartLoc,
17571 SourceLocation EndLoc) {
17572 OMPClause *Res = nullptr;
17573 switch (Kind) {
17574 case OMPC_ordered:
17575 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
17576 break;
17577 case OMPC_nowait:
17578 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
17579 break;
17580 case OMPC_untied:
17581 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
17582 break;
17583 case OMPC_mergeable:
17584 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
17585 break;
17586 case OMPC_read:
17587 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
17588 break;
17589 case OMPC_write:
17590 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
17591 break;
17592 case OMPC_update:
17593 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
17594 break;
17595 case OMPC_capture:
17596 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
17597 break;
17598 case OMPC_compare:
17599 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
17600 break;
17601 case OMPC_fail:
17602 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
17603 break;
17604 case OMPC_seq_cst:
17605 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
17606 break;
17607 case OMPC_acq_rel:
17608 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
17609 break;
17610 case OMPC_acquire:
17611 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
17612 break;
17613 case OMPC_release:
17614 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
17615 break;
17616 case OMPC_relaxed:
17617 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
17618 break;
17619 case OMPC_weak:
17620 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
17621 break;
17622 case OMPC_threads:
17623 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
17624 break;
17625 case OMPC_simd:
17626 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
17627 break;
17628 case OMPC_nogroup:
17629 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
17630 break;
17631 case OMPC_unified_address:
17632 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
17633 break;
17634 case OMPC_unified_shared_memory:
17635 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17636 break;
17637 case OMPC_reverse_offload:
17638 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
17639 break;
17640 case OMPC_dynamic_allocators:
17641 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
17642 break;
17643 case OMPC_destroy:
17644 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
17645 /*LParenLoc=*/SourceLocation(),
17646 /*VarLoc=*/SourceLocation(), EndLoc);
17647 break;
17648 case OMPC_full:
17649 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
17650 break;
17651 case OMPC_partial:
17652 Res = ActOnOpenMPPartialClause(FactorExpr: nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
17653 break;
17654 case OMPC_ompx_bare:
17655 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
17656 break;
17657 case OMPC_if:
17658 case OMPC_final:
17659 case OMPC_num_threads:
17660 case OMPC_safelen:
17661 case OMPC_simdlen:
17662 case OMPC_sizes:
17663 case OMPC_allocator:
17664 case OMPC_collapse:
17665 case OMPC_schedule:
17666 case OMPC_private:
17667 case OMPC_firstprivate:
17668 case OMPC_lastprivate:
17669 case OMPC_shared:
17670 case OMPC_reduction:
17671 case OMPC_task_reduction:
17672 case OMPC_in_reduction:
17673 case OMPC_linear:
17674 case OMPC_aligned:
17675 case OMPC_copyin:
17676 case OMPC_copyprivate:
17677 case OMPC_default:
17678 case OMPC_proc_bind:
17679 case OMPC_threadprivate:
17680 case OMPC_allocate:
17681 case OMPC_flush:
17682 case OMPC_depobj:
17683 case OMPC_depend:
17684 case OMPC_device:
17685 case OMPC_map:
17686 case OMPC_num_teams:
17687 case OMPC_thread_limit:
17688 case OMPC_priority:
17689 case OMPC_grainsize:
17690 case OMPC_num_tasks:
17691 case OMPC_hint:
17692 case OMPC_dist_schedule:
17693 case OMPC_defaultmap:
17694 case OMPC_unknown:
17695 case OMPC_uniform:
17696 case OMPC_to:
17697 case OMPC_from:
17698 case OMPC_use_device_ptr:
17699 case OMPC_use_device_addr:
17700 case OMPC_is_device_ptr:
17701 case OMPC_has_device_addr:
17702 case OMPC_atomic_default_mem_order:
17703 case OMPC_device_type:
17704 case OMPC_match:
17705 case OMPC_nontemporal:
17706 case OMPC_order:
17707 case OMPC_at:
17708 case OMPC_severity:
17709 case OMPC_message:
17710 case OMPC_novariants:
17711 case OMPC_nocontext:
17712 case OMPC_detach:
17713 case OMPC_inclusive:
17714 case OMPC_exclusive:
17715 case OMPC_uses_allocators:
17716 case OMPC_affinity:
17717 case OMPC_when:
17718 case OMPC_ompx_dyn_cgroup_mem:
17719 default:
17720 llvm_unreachable("Clause is not allowed.");
17721 }
17722 return Res;
17723}
17724
17725OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
17726 SourceLocation EndLoc) {
17727 DSAStack->setNowaitRegion();
17728 return new (Context) OMPNowaitClause(StartLoc, EndLoc);
17729}
17730
17731OMPClause *Sema::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
17732 SourceLocation EndLoc) {
17733 DSAStack->setUntiedRegion();
17734 return new (Context) OMPUntiedClause(StartLoc, EndLoc);
17735}
17736
17737OMPClause *Sema::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
17738 SourceLocation EndLoc) {
17739 return new (Context) OMPMergeableClause(StartLoc, EndLoc);
17740}
17741
17742OMPClause *Sema::ActOnOpenMPReadClause(SourceLocation StartLoc,
17743 SourceLocation EndLoc) {
17744 return new (Context) OMPReadClause(StartLoc, EndLoc);
17745}
17746
17747OMPClause *Sema::ActOnOpenMPWriteClause(SourceLocation StartLoc,
17748 SourceLocation EndLoc) {
17749 return new (Context) OMPWriteClause(StartLoc, EndLoc);
17750}
17751
17752OMPClause *Sema::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
17753 SourceLocation EndLoc) {
17754 return OMPUpdateClause::Create(C: Context, StartLoc, EndLoc);
17755}
17756
17757OMPClause *Sema::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
17758 SourceLocation EndLoc) {
17759 return new (Context) OMPCaptureClause(StartLoc, EndLoc);
17760}
17761
17762OMPClause *Sema::ActOnOpenMPCompareClause(SourceLocation StartLoc,
17763 SourceLocation EndLoc) {
17764 return new (Context) OMPCompareClause(StartLoc, EndLoc);
17765}
17766
17767OMPClause *Sema::ActOnOpenMPFailClause(SourceLocation StartLoc,
17768 SourceLocation EndLoc) {
17769 return new (Context) OMPFailClause(StartLoc, EndLoc);
17770}
17771
17772OMPClause *Sema::ActOnOpenMPFailClause(
17773 OpenMPClauseKind Parameter, SourceLocation KindLoc,
17774 SourceLocation StartLoc, SourceLocation LParenLoc,
17775 SourceLocation EndLoc) {
17776
17777 if (!checkFailClauseParameter(Parameter)) {
17778 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
17779 return nullptr;
17780 }
17781 return new (Context)
17782 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
17783}
17784
17785OMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
17786 SourceLocation EndLoc) {
17787 return new (Context) OMPSeqCstClause(StartLoc, EndLoc);
17788}
17789
17790OMPClause *Sema::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
17791 SourceLocation EndLoc) {
17792 return new (Context) OMPAcqRelClause(StartLoc, EndLoc);
17793}
17794
17795OMPClause *Sema::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
17796 SourceLocation EndLoc) {
17797 return new (Context) OMPAcquireClause(StartLoc, EndLoc);
17798}
17799
17800OMPClause *Sema::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
17801 SourceLocation EndLoc) {
17802 return new (Context) OMPReleaseClause(StartLoc, EndLoc);
17803}
17804
17805OMPClause *Sema::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
17806 SourceLocation EndLoc) {
17807 return new (Context) OMPRelaxedClause(StartLoc, EndLoc);
17808}
17809
17810OMPClause *Sema::ActOnOpenMPWeakClause(SourceLocation StartLoc,
17811 SourceLocation EndLoc) {
17812 return new (Context) OMPWeakClause(StartLoc, EndLoc);
17813}
17814
17815OMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
17816 SourceLocation EndLoc) {
17817 return new (Context) OMPThreadsClause(StartLoc, EndLoc);
17818}
17819
17820OMPClause *Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
17821 SourceLocation EndLoc) {
17822 return new (Context) OMPSIMDClause(StartLoc, EndLoc);
17823}
17824
17825OMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
17826 SourceLocation EndLoc) {
17827 return new (Context) OMPNogroupClause(StartLoc, EndLoc);
17828}
17829
17830OMPClause *Sema::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
17831 SourceLocation EndLoc) {
17832 return new (Context) OMPUnifiedAddressClause(StartLoc, EndLoc);
17833}
17834
17835OMPClause *Sema::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
17836 SourceLocation EndLoc) {
17837 return new (Context) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17838}
17839
17840OMPClause *Sema::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
17841 SourceLocation EndLoc) {
17842 return new (Context) OMPReverseOffloadClause(StartLoc, EndLoc);
17843}
17844
17845OMPClause *Sema::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
17846 SourceLocation EndLoc) {
17847 return new (Context) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17848}
17849
17850StmtResult Sema::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
17851 SourceLocation StartLoc,
17852 SourceLocation EndLoc) {
17853
17854 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17855 // At least one action-clause must appear on a directive.
17856 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17857 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
17858 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17859 << Expected << getOpenMPDirectiveName(OMPD_interop);
17860 return StmtError();
17861 }
17862
17863 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17864 // A depend clause can only appear on the directive if a targetsync
17865 // interop-type is present or the interop-var was initialized with
17866 // the targetsync interop-type.
17867
17868 // If there is any 'init' clause diagnose if there is no 'init' clause with
17869 // interop-type of 'targetsync'. Cases involving other directives cannot be
17870 // diagnosed.
17871 const OMPDependClause *DependClause = nullptr;
17872 bool HasInitClause = false;
17873 bool IsTargetSync = false;
17874 for (const OMPClause *C : Clauses) {
17875 if (IsTargetSync)
17876 break;
17877 if (const auto *InitClause = dyn_cast<OMPInitClause>(Val: C)) {
17878 HasInitClause = true;
17879 if (InitClause->getIsTargetSync())
17880 IsTargetSync = true;
17881 } else if (const auto *DC = dyn_cast<OMPDependClause>(Val: C)) {
17882 DependClause = DC;
17883 }
17884 }
17885 if (DependClause && HasInitClause && !IsTargetSync) {
17886 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17887 return StmtError();
17888 }
17889
17890 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17891 // Each interop-var may be specified for at most one action-clause of each
17892 // interop construct.
17893 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
17894 for (OMPClause *C : Clauses) {
17895 OpenMPClauseKind ClauseKind = C->getClauseKind();
17896 std::pair<ValueDecl *, bool> DeclResult;
17897 SourceLocation ELoc;
17898 SourceRange ERange;
17899
17900 if (ClauseKind == OMPC_init) {
17901 auto *E = cast<OMPInitClause>(Val: C)->getInteropVar();
17902 DeclResult = getPrivateItem(S&: *this, RefExpr&: E, ELoc, ERange);
17903 } else if (ClauseKind == OMPC_use) {
17904 auto *E = cast<OMPUseClause>(Val: C)->getInteropVar();
17905 DeclResult = getPrivateItem(S&: *this, RefExpr&: E, ELoc, ERange);
17906 } else if (ClauseKind == OMPC_destroy) {
17907 auto *E = cast<OMPDestroyClause>(Val: C)->getInteropVar();
17908 DeclResult = getPrivateItem(S&: *this, RefExpr&: E, ELoc, ERange);
17909 }
17910
17911 if (DeclResult.first) {
17912 if (!InteropVars.insert(Ptr: DeclResult.first).second) {
17913 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
17914 << DeclResult.first;
17915 return StmtError();
17916 }
17917 }
17918 }
17919
17920 return OMPInteropDirective::Create(C: Context, StartLoc, EndLoc, Clauses);
17921}
17922
17923static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
17924 SourceLocation VarLoc,
17925 OpenMPClauseKind Kind) {
17926 SourceLocation ELoc;
17927 SourceRange ERange;
17928 Expr *RefExpr = InteropVarExpr;
17929 auto Res =
17930 getPrivateItem(S&: SemaRef, RefExpr, ELoc, ERange,
17931 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17932
17933 if (Res.second) {
17934 // It will be analyzed later.
17935 return true;
17936 }
17937
17938 if (!Res.first)
17939 return false;
17940
17941 // Interop variable should be of type omp_interop_t.
17942 bool HasError = false;
17943 QualType InteropType;
17944 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get(Name: "omp_interop_t"),
17945 VarLoc, Sema::LookupOrdinaryName);
17946 if (SemaRef.LookupName(R&: Result, S: SemaRef.getCurScope())) {
17947 NamedDecl *ND = Result.getFoundDecl();
17948 if (const auto *TD = dyn_cast<TypeDecl>(Val: ND)) {
17949 InteropType = QualType(TD->getTypeForDecl(), 0);
17950 } else {
17951 HasError = true;
17952 }
17953 } else {
17954 HasError = true;
17955 }
17956
17957 if (HasError) {
17958 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
17959 << "omp_interop_t";
17960 return false;
17961 }
17962
17963 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
17964 if (!SemaRef.Context.hasSameType(T1: InteropType, T2: VarType)) {
17965 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17966 return false;
17967 }
17968
17969 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17970 // The interop-var passed to init or destroy must be non-const.
17971 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17972 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
17973 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
17974 << /*non-const*/ 1;
17975 return false;
17976 }
17977 return true;
17978}
17979
17980OMPClause *
17981Sema::ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo,
17982 SourceLocation StartLoc, SourceLocation LParenLoc,
17983 SourceLocation VarLoc, SourceLocation EndLoc) {
17984
17985 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_init))
17986 return nullptr;
17987
17988 // Check prefer_type values. These foreign-runtime-id values are either
17989 // string literals or constant integral expressions.
17990 for (const Expr *E : InteropInfo.PreferTypes) {
17991 if (E->isValueDependent() || E->isTypeDependent() ||
17992 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
17993 continue;
17994 if (E->isIntegerConstantExpr(Ctx: Context))
17995 continue;
17996 if (isa<StringLiteral>(Val: E))
17997 continue;
17998 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
17999 return nullptr;
18000 }
18001
18002 return OMPInitClause::Create(C: Context, InteropVar, InteropInfo, StartLoc,
18003 LParenLoc, VarLoc, EndLoc);
18004}
18005
18006OMPClause *Sema::ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc,
18007 SourceLocation LParenLoc,
18008 SourceLocation VarLoc,
18009 SourceLocation EndLoc) {
18010
18011 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_use))
18012 return nullptr;
18013
18014 return new (Context)
18015 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18016}
18017
18018OMPClause *Sema::ActOnOpenMPDestroyClause(Expr *InteropVar,
18019 SourceLocation StartLoc,
18020 SourceLocation LParenLoc,
18021 SourceLocation VarLoc,
18022 SourceLocation EndLoc) {
18023 if (!InteropVar && LangOpts.OpenMP >= 52 &&
18024 DSAStack->getCurrentDirective() == OMPD_depobj) {
18025 Diag(StartLoc, diag::err_omp_expected_clause_argument)
18026 << getOpenMPClauseName(OMPC_destroy)
18027 << getOpenMPDirectiveName(OMPD_depobj);
18028 return nullptr;
18029 }
18030 if (InteropVar &&
18031 !isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_destroy))
18032 return nullptr;
18033
18034 return new (Context)
18035 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18036}
18037
18038OMPClause *Sema::ActOnOpenMPNovariantsClause(Expr *Condition,
18039 SourceLocation StartLoc,
18040 SourceLocation LParenLoc,
18041 SourceLocation EndLoc) {
18042 Expr *ValExpr = Condition;
18043 Stmt *HelperValStmt = nullptr;
18044 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18045 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18046 !Condition->isInstantiationDependent() &&
18047 !Condition->containsUnexpandedParameterPack()) {
18048 ExprResult Val = CheckBooleanCondition(Loc: StartLoc, E: Condition);
18049 if (Val.isInvalid())
18050 return nullptr;
18051
18052 ValExpr = MakeFullExpr(Arg: Val.get()).get();
18053
18054 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18055 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
18056 LangOpts.OpenMP);
18057 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
18058 ValExpr = MakeFullExpr(Arg: ValExpr).get();
18059 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18060 ValExpr = tryBuildCapture(SemaRef&: *this, Capture: ValExpr, Captures).get();
18061 HelperValStmt = buildPreInits(Context, Captures);
18062 }
18063 }
18064
18065 return new (Context) OMPNovariantsClause(
18066 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18067}
18068
18069OMPClause *Sema::ActOnOpenMPNocontextClause(Expr *Condition,
18070 SourceLocation StartLoc,
18071 SourceLocation LParenLoc,
18072 SourceLocation EndLoc) {
18073 Expr *ValExpr = Condition;
18074 Stmt *HelperValStmt = nullptr;
18075 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18076 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18077 !Condition->isInstantiationDependent() &&
18078 !Condition->containsUnexpandedParameterPack()) {
18079 ExprResult Val = CheckBooleanCondition(Loc: StartLoc, E: Condition);
18080 if (Val.isInvalid())
18081 return nullptr;
18082
18083 ValExpr = MakeFullExpr(Arg: Val.get()).get();
18084
18085 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18086 CaptureRegion =
18087 getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext, LangOpts.OpenMP);
18088 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
18089 ValExpr = MakeFullExpr(Arg: ValExpr).get();
18090 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18091 ValExpr = tryBuildCapture(SemaRef&: *this, Capture: ValExpr, Captures).get();
18092 HelperValStmt = buildPreInits(Context, Captures);
18093 }
18094 }
18095
18096 return new (Context) OMPNocontextClause(ValExpr, HelperValStmt, CaptureRegion,
18097 StartLoc, LParenLoc, EndLoc);
18098}
18099
18100OMPClause *Sema::ActOnOpenMPFilterClause(Expr *ThreadID,
18101 SourceLocation StartLoc,
18102 SourceLocation LParenLoc,
18103 SourceLocation EndLoc) {
18104 Expr *ValExpr = ThreadID;
18105 Stmt *HelperValStmt = nullptr;
18106
18107 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18108 OpenMPDirectiveKind CaptureRegion =
18109 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, LangOpts.OpenMP);
18110 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
18111 ValExpr = MakeFullExpr(Arg: ValExpr).get();
18112 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18113 ValExpr = tryBuildCapture(SemaRef&: *this, Capture: ValExpr, Captures).get();
18114 HelperValStmt = buildPreInits(Context, Captures);
18115 }
18116
18117 return new (Context) OMPFilterClause(ValExpr, HelperValStmt, CaptureRegion,
18118 StartLoc, LParenLoc, EndLoc);
18119}
18120
18121OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
18122 ArrayRef<Expr *> VarList,
18123 const OMPVarListLocTy &Locs,
18124 OpenMPVarListDataTy &Data) {
18125 SourceLocation StartLoc = Locs.StartLoc;
18126 SourceLocation LParenLoc = Locs.LParenLoc;
18127 SourceLocation EndLoc = Locs.EndLoc;
18128 OMPClause *Res = nullptr;
18129 int ExtraModifier = Data.ExtraModifier;
18130 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
18131 SourceLocation ColonLoc = Data.ColonLoc;
18132 switch (Kind) {
18133 case OMPC_private:
18134 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18135 break;
18136 case OMPC_firstprivate:
18137 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18138 break;
18139 case OMPC_lastprivate:
18140 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
18141 "Unexpected lastprivate modifier.");
18142 Res = ActOnOpenMPLastprivateClause(
18143 VarList, LPKind: static_cast<OpenMPLastprivateModifier>(ExtraModifier),
18144 LPKindLoc: ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18145 break;
18146 case OMPC_shared:
18147 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
18148 break;
18149 case OMPC_reduction:
18150 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
18151 "Unexpected lastprivate modifier.");
18152 Res = ActOnOpenMPReductionClause(
18153 VarList, Modifier: static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
18154 StartLoc, LParenLoc, ModifierLoc: ExtraModifierLoc, ColonLoc, EndLoc,
18155 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
18156 break;
18157 case OMPC_task_reduction:
18158 Res = ActOnOpenMPTaskReductionClause(
18159 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18160 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
18161 break;
18162 case OMPC_in_reduction:
18163 Res = ActOnOpenMPInReductionClause(
18164 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18165 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
18166 break;
18167 case OMPC_linear:
18168 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
18169 "Unexpected linear modifier.");
18170 Res = ActOnOpenMPLinearClause(
18171 VarList, Step: Data.DepModOrTailExpr, StartLoc, LParenLoc,
18172 LinKind: static_cast<OpenMPLinearClauseKind>(ExtraModifier), LinLoc: ExtraModifierLoc,
18173 ColonLoc, StepModifierLoc: Data.StepModifierLoc, EndLoc);
18174 break;
18175 case OMPC_aligned:
18176 Res = ActOnOpenMPAlignedClause(VarList, Alignment: Data.DepModOrTailExpr, StartLoc,
18177 LParenLoc, ColonLoc, EndLoc);
18178 break;
18179 case OMPC_copyin:
18180 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
18181 break;
18182 case OMPC_copyprivate:
18183 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18184 break;
18185 case OMPC_flush:
18186 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
18187 break;
18188 case OMPC_depend:
18189 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
18190 "Unexpected depend modifier.");
18191 Res = ActOnOpenMPDependClause(
18192 Data: {.DepKind: static_cast<OpenMPDependClauseKind>(ExtraModifier), .DepLoc: ExtraModifierLoc,
18193 .ColonLoc: ColonLoc, .OmpAllMemoryLoc: Data.OmpAllMemoryLoc},
18194 DepModifier: Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18195 break;
18196 case OMPC_map:
18197 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
18198 "Unexpected map modifier.");
18199 Res = ActOnOpenMPMapClause(
18200 IteratorModifier: Data.IteratorExpr, MapTypeModifiers: Data.MapTypeModifiers, MapTypeModifiersLoc: Data.MapTypeModifiersLoc,
18201 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId,
18202 MapType: static_cast<OpenMPMapClauseKind>(ExtraModifier), IsMapTypeImplicit: Data.IsMapTypeImplicit,
18203 MapLoc: ExtraModifierLoc, ColonLoc, VarList, Locs);
18204 break;
18205 case OMPC_to:
18206 Res =
18207 ActOnOpenMPToClause(MotionModifiers: Data.MotionModifiers, MotionModifiersLoc: Data.MotionModifiersLoc,
18208 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec,
18209 MapperId&: Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
18210 break;
18211 case OMPC_from:
18212 Res = ActOnOpenMPFromClause(MotionModifiers: Data.MotionModifiers, MotionModifiersLoc: Data.MotionModifiersLoc,
18213 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec,
18214 MapperId&: Data.ReductionOrMapperId, ColonLoc, VarList,
18215 Locs);
18216 break;
18217 case OMPC_use_device_ptr:
18218 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
18219 break;
18220 case OMPC_use_device_addr:
18221 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
18222 break;
18223 case OMPC_is_device_ptr:
18224 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
18225 break;
18226 case OMPC_has_device_addr:
18227 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
18228 break;
18229 case OMPC_allocate:
18230 Res = ActOnOpenMPAllocateClause(Allocator: Data.DepModOrTailExpr, VarList, StartLoc,
18231 ColonLoc: LParenLoc, LParenLoc: ColonLoc, EndLoc);
18232 break;
18233 case OMPC_nontemporal:
18234 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
18235 break;
18236 case OMPC_inclusive:
18237 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18238 break;
18239 case OMPC_exclusive:
18240 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18241 break;
18242 case OMPC_affinity:
18243 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
18244 Modifier: Data.DepModOrTailExpr, Locators: VarList);
18245 break;
18246 case OMPC_doacross:
18247 Res = ActOnOpenMPDoacrossClause(
18248 DepType: static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
18249 DepLoc: ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18250 break;
18251 case OMPC_if:
18252 case OMPC_depobj:
18253 case OMPC_final:
18254 case OMPC_num_threads:
18255 case OMPC_safelen:
18256 case OMPC_simdlen:
18257 case OMPC_sizes:
18258 case OMPC_allocator:
18259 case OMPC_collapse:
18260 case OMPC_default:
18261 case OMPC_proc_bind:
18262 case OMPC_schedule:
18263 case OMPC_ordered:
18264 case OMPC_nowait:
18265 case OMPC_untied:
18266 case OMPC_mergeable:
18267 case OMPC_threadprivate:
18268 case OMPC_read:
18269 case OMPC_write:
18270 case OMPC_update:
18271 case OMPC_capture:
18272 case OMPC_compare:
18273 case OMPC_seq_cst:
18274 case OMPC_acq_rel:
18275 case OMPC_acquire:
18276 case OMPC_release:
18277 case OMPC_relaxed:
18278 case OMPC_device:
18279 case OMPC_threads:
18280 case OMPC_simd:
18281 case OMPC_num_teams:
18282 case OMPC_thread_limit:
18283 case OMPC_priority:
18284 case OMPC_grainsize:
18285 case OMPC_nogroup:
18286 case OMPC_num_tasks:
18287 case OMPC_hint:
18288 case OMPC_dist_schedule:
18289 case OMPC_defaultmap:
18290 case OMPC_unknown:
18291 case OMPC_uniform:
18292 case OMPC_unified_address:
18293 case OMPC_unified_shared_memory:
18294 case OMPC_reverse_offload:
18295 case OMPC_dynamic_allocators:
18296 case OMPC_atomic_default_mem_order:
18297 case OMPC_device_type:
18298 case OMPC_match:
18299 case OMPC_order:
18300 case OMPC_at:
18301 case OMPC_severity:
18302 case OMPC_message:
18303 case OMPC_destroy:
18304 case OMPC_novariants:
18305 case OMPC_nocontext:
18306 case OMPC_detach:
18307 case OMPC_uses_allocators:
18308 case OMPC_when:
18309 case OMPC_bind:
18310 default:
18311 llvm_unreachable("Clause is not allowed.");
18312 }
18313 return Res;
18314}
18315
18316ExprResult Sema::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
18317 ExprObjectKind OK, SourceLocation Loc) {
18318 ExprResult Res = BuildDeclRefExpr(
18319 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
18320 if (!Res.isUsable())
18321 return ExprError();
18322 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
18323 Res = CreateBuiltinUnaryOp(OpLoc: Loc, Opc: UO_Deref, InputExpr: Res.get());
18324 if (!Res.isUsable())
18325 return ExprError();
18326 }
18327 if (VK != VK_LValue && Res.get()->isGLValue()) {
18328 Res = DefaultLvalueConversion(E: Res.get());
18329 if (!Res.isUsable())
18330 return ExprError();
18331 }
18332 return Res;
18333}
18334
18335OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
18336 SourceLocation StartLoc,
18337 SourceLocation LParenLoc,
18338 SourceLocation EndLoc) {
18339 SmallVector<Expr *, 8> Vars;
18340 SmallVector<Expr *, 8> PrivateCopies;
18341 bool IsImplicitClause =
18342 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18343 for (Expr *RefExpr : VarList) {
18344 assert(RefExpr && "NULL expr in OpenMP private clause.");
18345 SourceLocation ELoc;
18346 SourceRange ERange;
18347 Expr *SimpleRefExpr = RefExpr;
18348 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange);
18349 if (Res.second) {
18350 // It will be analyzed later.
18351 Vars.push_back(Elt: RefExpr);
18352 PrivateCopies.push_back(Elt: nullptr);
18353 }
18354 ValueDecl *D = Res.first;
18355 if (!D)
18356 continue;
18357
18358 QualType Type = D->getType();
18359 auto *VD = dyn_cast<VarDecl>(Val: D);
18360
18361 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18362 // A variable that appears in a private clause must not have an incomplete
18363 // type or a reference type.
18364 if (RequireCompleteType(ELoc, Type, diag::err_omp_private_incomplete_type))
18365 continue;
18366 Type = Type.getNonReferenceType();
18367
18368 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18369 // A variable that is privatized must not have a const-qualified type
18370 // unless it is of class type with a mutable member. This restriction does
18371 // not apply to the firstprivate clause.
18372 //
18373 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18374 // A variable that appears in a private clause must not have a
18375 // const-qualified type unless it is of class type with a mutable member.
18376 if (rejectConstNotMutableType(*this, D, Type, OMPC_private, ELoc))
18377 continue;
18378
18379 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18380 // in a Construct]
18381 // Variables with the predetermined data-sharing attributes may not be
18382 // listed in data-sharing attributes clauses, except for the cases
18383 // listed below. For these exceptions only, listing a predetermined
18384 // variable in a data-sharing attribute clause is allowed and overrides
18385 // the variable's predetermined data-sharing attributes.
18386 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18387 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18388 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18389 << getOpenMPClauseName(OMPC_private);
18390 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
18391 continue;
18392 }
18393
18394 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18395 // Variably modified types are not supported for tasks.
18396 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18397 isOpenMPTaskingDirective(Kind: CurrDir)) {
18398 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18399 << getOpenMPClauseName(OMPC_private) << Type
18400 << getOpenMPDirectiveName(CurrDir);
18401 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18402 VarDecl::DeclarationOnly;
18403 Diag(D->getLocation(),
18404 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18405 << D;
18406 continue;
18407 }
18408
18409 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18410 // A list item cannot appear in both a map clause and a data-sharing
18411 // attribute clause on the same construct
18412 //
18413 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18414 // A list item cannot appear in both a map clause and a data-sharing
18415 // attribute clause on the same construct unless the construct is a
18416 // combined construct.
18417 if ((LangOpts.OpenMP <= 45 && isOpenMPTargetExecutionDirective(CurrDir)) ||
18418 CurrDir == OMPD_target) {
18419 OpenMPClauseKind ConflictKind;
18420 if (DSAStack->checkMappableExprComponentListsForDecl(
18421 VD, /*CurrentRegionOnly=*/true,
18422 [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
18423 OpenMPClauseKind WhereFoundClauseKind) -> bool {
18424 ConflictKind = WhereFoundClauseKind;
18425 return true;
18426 })) {
18427 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18428 << getOpenMPClauseName(OMPC_private)
18429 << getOpenMPClauseName(ConflictKind)
18430 << getOpenMPDirectiveName(CurrDir);
18431 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
18432 continue;
18433 }
18434 }
18435
18436 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18437 // A variable of class type (or array thereof) that appears in a private
18438 // clause requires an accessible, unambiguous default constructor for the
18439 // class type.
18440 // Generate helper private variable and initialize it with the default
18441 // value. The address of the original variable is replaced by the address of
18442 // the new private variable in CodeGen. This new variable is not added to
18443 // IdResolver, so the code in the OpenMP region uses original variable for
18444 // proper diagnostics.
18445 Type = Type.getUnqualifiedType();
18446 VarDecl *VDPrivate =
18447 buildVarDecl(*this, ELoc, Type, D->getName(),
18448 D->hasAttrs() ? &D->getAttrs() : nullptr,
18449 VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
18450 ActOnUninitializedDecl(VDPrivate);
18451 if (VDPrivate->isInvalidDecl())
18452 continue;
18453 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18454 S&: *this, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(), Loc: ELoc);
18455
18456 DeclRefExpr *Ref = nullptr;
18457 if (!VD && !CurContext->isDependentContext()) {
18458 auto *FD = dyn_cast<FieldDecl>(Val: D);
18459 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18460 if (VD)
18461 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18462 RefExpr->getExprLoc());
18463 else
18464 Ref = buildCapture(S&: *this, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
18465 }
18466 if (!IsImplicitClause)
18467 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
18468 Vars.push_back(Elt: (VD || CurContext->isDependentContext())
18469 ? RefExpr->IgnoreParens()
18470 : Ref);
18471 PrivateCopies.push_back(VDPrivateRefExpr);
18472 }
18473
18474 if (Vars.empty())
18475 return nullptr;
18476
18477 return OMPPrivateClause::Create(C: Context, StartLoc, LParenLoc, EndLoc, VL: Vars,
18478 PrivateVL: PrivateCopies);
18479}
18480
18481OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
18482 SourceLocation StartLoc,
18483 SourceLocation LParenLoc,
18484 SourceLocation EndLoc) {
18485 SmallVector<Expr *, 8> Vars;
18486 SmallVector<Expr *, 8> PrivateCopies;
18487 SmallVector<Expr *, 8> Inits;
18488 SmallVector<Decl *, 4> ExprCaptures;
18489 bool IsImplicitClause =
18490 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18491 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
18492
18493 for (Expr *RefExpr : VarList) {
18494 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
18495 SourceLocation ELoc;
18496 SourceRange ERange;
18497 Expr *SimpleRefExpr = RefExpr;
18498 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange);
18499 if (Res.second) {
18500 // It will be analyzed later.
18501 Vars.push_back(Elt: RefExpr);
18502 PrivateCopies.push_back(Elt: nullptr);
18503 Inits.push_back(Elt: nullptr);
18504 }
18505 ValueDecl *D = Res.first;
18506 if (!D)
18507 continue;
18508
18509 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
18510 QualType Type = D->getType();
18511 auto *VD = dyn_cast<VarDecl>(Val: D);
18512
18513 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18514 // A variable that appears in a private clause must not have an incomplete
18515 // type or a reference type.
18516 if (RequireCompleteType(ELoc, Type,
18517 diag::err_omp_firstprivate_incomplete_type))
18518 continue;
18519 Type = Type.getNonReferenceType();
18520
18521 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
18522 // A variable of class type (or array thereof) that appears in a private
18523 // clause requires an accessible, unambiguous copy constructor for the
18524 // class type.
18525 QualType ElemType = Context.getBaseElementType(QT: Type).getNonReferenceType();
18526
18527 // If an implicit firstprivate variable found it was checked already.
18528 DSAStackTy::DSAVarData TopDVar;
18529 if (!IsImplicitClause) {
18530 DSAStackTy::DSAVarData DVar =
18531 DSAStack->getTopDSA(D, /*FromParent=*/false);
18532 TopDVar = DVar;
18533 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18534 bool IsConstant = ElemType.isConstant(Ctx: Context);
18535 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
18536 // A list item that specifies a given variable may not appear in more
18537 // than one clause on the same directive, except that a variable may be
18538 // specified in both firstprivate and lastprivate clauses.
18539 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18540 // A list item may appear in a firstprivate or lastprivate clause but not
18541 // both.
18542 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
18543 (isOpenMPDistributeDirective(CurrDir) ||
18544 DVar.CKind != OMPC_lastprivate) &&
18545 DVar.RefExpr) {
18546 Diag(ELoc, diag::err_omp_wrong_dsa)
18547 << getOpenMPClauseName(DVar.CKind)
18548 << getOpenMPClauseName(OMPC_firstprivate);
18549 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
18550 continue;
18551 }
18552
18553 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18554 // in a Construct]
18555 // Variables with the predetermined data-sharing attributes may not be
18556 // listed in data-sharing attributes clauses, except for the cases
18557 // listed below. For these exceptions only, listing a predetermined
18558 // variable in a data-sharing attribute clause is allowed and overrides
18559 // the variable's predetermined data-sharing attributes.
18560 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18561 // in a Construct, C/C++, p.2]
18562 // Variables with const-qualified type having no mutable member may be
18563 // listed in a firstprivate clause, even if they are static data members.
18564 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
18565 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
18566 Diag(ELoc, diag::err_omp_wrong_dsa)
18567 << getOpenMPClauseName(DVar.CKind)
18568 << getOpenMPClauseName(OMPC_firstprivate);
18569 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
18570 continue;
18571 }
18572
18573 // OpenMP [2.9.3.4, Restrictions, p.2]
18574 // A list item that is private within a parallel region must not appear
18575 // in a firstprivate clause on a worksharing construct if any of the
18576 // worksharing regions arising from the worksharing construct ever bind
18577 // to any of the parallel regions arising from the parallel construct.
18578 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18579 // A list item that is private within a teams region must not appear in a
18580 // firstprivate clause on a distribute construct if any of the distribute
18581 // regions arising from the distribute construct ever bind to any of the
18582 // teams regions arising from the teams construct.
18583 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18584 // A list item that appears in a reduction clause of a teams construct
18585 // must not appear in a firstprivate clause on a distribute construct if
18586 // any of the distribute regions arising from the distribute construct
18587 // ever bind to any of the teams regions arising from the teams construct.
18588 if ((isOpenMPWorksharingDirective(DKind: CurrDir) ||
18589 isOpenMPDistributeDirective(DKind: CurrDir)) &&
18590 !isOpenMPParallelDirective(DKind: CurrDir) &&
18591 !isOpenMPTeamsDirective(DKind: CurrDir)) {
18592 DVar = DSAStack->getImplicitDSA(D, FromParent: true);
18593 if (DVar.CKind != OMPC_shared &&
18594 (isOpenMPParallelDirective(DVar.DKind) ||
18595 isOpenMPTeamsDirective(DVar.DKind) ||
18596 DVar.DKind == OMPD_unknown)) {
18597 Diag(ELoc, diag::err_omp_required_access)
18598 << getOpenMPClauseName(OMPC_firstprivate)
18599 << getOpenMPClauseName(OMPC_shared);
18600 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
18601 continue;
18602 }
18603 }
18604 // OpenMP [2.9.3.4, Restrictions, p.3]
18605 // A list item that appears in a reduction clause of a parallel construct
18606 // must not appear in a firstprivate clause on a worksharing or task
18607 // construct if any of the worksharing or task regions arising from the
18608 // worksharing or task construct ever bind to any of the parallel regions
18609 // arising from the parallel construct.
18610 // OpenMP [2.9.3.4, Restrictions, p.4]
18611 // A list item that appears in a reduction clause in worksharing
18612 // construct must not appear in a firstprivate clause in a task construct
18613 // encountered during execution of any of the worksharing regions arising
18614 // from the worksharing construct.
18615 if (isOpenMPTaskingDirective(Kind: CurrDir)) {
18616 DVar = DSAStack->hasInnermostDSA(
18617 D,
18618 [](OpenMPClauseKind C, bool AppliedToPointee) {
18619 return C == OMPC_reduction && !AppliedToPointee;
18620 },
18621 [](OpenMPDirectiveKind K) {
18622 return isOpenMPParallelDirective(DKind: K) ||
18623 isOpenMPWorksharingDirective(DKind: K) ||
18624 isOpenMPTeamsDirective(DKind: K);
18625 },
18626 /*FromParent=*/true);
18627 if (DVar.CKind == OMPC_reduction &&
18628 (isOpenMPParallelDirective(DVar.DKind) ||
18629 isOpenMPWorksharingDirective(DVar.DKind) ||
18630 isOpenMPTeamsDirective(DVar.DKind))) {
18631 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
18632 << getOpenMPDirectiveName(DVar.DKind);
18633 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
18634 continue;
18635 }
18636 }
18637
18638 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18639 // A list item cannot appear in both a map clause and a data-sharing
18640 // attribute clause on the same construct
18641 //
18642 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18643 // A list item cannot appear in both a map clause and a data-sharing
18644 // attribute clause on the same construct unless the construct is a
18645 // combined construct.
18646 if ((LangOpts.OpenMP <= 45 &&
18647 isOpenMPTargetExecutionDirective(CurrDir)) ||
18648 CurrDir == OMPD_target) {
18649 OpenMPClauseKind ConflictKind;
18650 if (DSAStack->checkMappableExprComponentListsForDecl(
18651 VD, /*CurrentRegionOnly=*/true,
18652 [&ConflictKind](
18653 OMPClauseMappableExprCommon::MappableExprComponentListRef,
18654 OpenMPClauseKind WhereFoundClauseKind) {
18655 ConflictKind = WhereFoundClauseKind;
18656 return true;
18657 })) {
18658 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18659 << getOpenMPClauseName(OMPC_firstprivate)
18660 << getOpenMPClauseName(ConflictKind)
18661 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18662 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
18663 continue;
18664 }
18665 }
18666 }
18667
18668 // Variably modified types are not supported for tasks.
18669 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18670 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18671 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18672 << getOpenMPClauseName(OMPC_firstprivate) << Type
18673 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18674 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18675 VarDecl::DeclarationOnly;
18676 Diag(D->getLocation(),
18677 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18678 << D;
18679 continue;
18680 }
18681
18682 Type = Type.getUnqualifiedType();
18683 VarDecl *VDPrivate =
18684 buildVarDecl(*this, ELoc, Type, D->getName(),
18685 D->hasAttrs() ? &D->getAttrs() : nullptr,
18686 VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
18687 // Generate helper private variable and initialize it with the value of the
18688 // original variable. The address of the original variable is replaced by
18689 // the address of the new private variable in the CodeGen. This new variable
18690 // is not added to IdResolver, so the code in the OpenMP region uses
18691 // original variable for proper diagnostics and variable capturing.
18692 Expr *VDInitRefExpr = nullptr;
18693 // For arrays generate initializer for single element and replace it by the
18694 // original array element in CodeGen.
18695 if (Type->isArrayType()) {
18696 VarDecl *VDInit =
18697 buildVarDecl(*this, RefExpr->getExprLoc(), ElemType, D->getName());
18698 VDInitRefExpr = buildDeclRefExpr(S&: *this, D: VDInit, Ty: ElemType, Loc: ELoc);
18699 Expr *Init = DefaultLvalueConversion(E: VDInitRefExpr).get();
18700 ElemType = ElemType.getUnqualifiedType();
18701 VarDecl *VDInitTemp = buildVarDecl(SemaRef&: *this, Loc: RefExpr->getExprLoc(), Type: ElemType,
18702 Name: ".firstprivate.temp");
18703 InitializedEntity Entity =
18704 InitializedEntity::InitializeVariable(Var: VDInitTemp);
18705 InitializationKind Kind = InitializationKind::CreateCopy(InitLoc: ELoc, EqualLoc: ELoc);
18706
18707 InitializationSequence InitSeq(*this, Entity, Kind, Init);
18708 ExprResult Result = InitSeq.Perform(S&: *this, Entity, Kind, Args: Init);
18709 if (Result.isInvalid())
18710 VDPrivate->setInvalidDecl();
18711 else
18712 VDPrivate->setInit(Result.getAs<Expr>());
18713 // Remove temp variable declaration.
18714 Context.Deallocate(Ptr: VDInitTemp);
18715 } else {
18716 VarDecl *VDInit = buildVarDecl(SemaRef&: *this, Loc: RefExpr->getExprLoc(), Type,
18717 Name: ".firstprivate.temp");
18718 VDInitRefExpr = buildDeclRefExpr(S&: *this, D: VDInit, Ty: RefExpr->getType(),
18719 Loc: RefExpr->getExprLoc());
18720 AddInitializerToDecl(VDPrivate,
18721 DefaultLvalueConversion(E: VDInitRefExpr).get(),
18722 /*DirectInit=*/false);
18723 }
18724 if (VDPrivate->isInvalidDecl()) {
18725 if (IsImplicitClause) {
18726 Diag(RefExpr->getExprLoc(),
18727 diag::note_omp_task_predetermined_firstprivate_here);
18728 }
18729 continue;
18730 }
18731 CurContext->addDecl(VDPrivate);
18732 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18733 S&: *this, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(),
18734 Loc: RefExpr->getExprLoc());
18735 DeclRefExpr *Ref = nullptr;
18736 if (!VD && !CurContext->isDependentContext()) {
18737 if (TopDVar.CKind == OMPC_lastprivate) {
18738 Ref = TopDVar.PrivateCopy;
18739 } else {
18740 auto *FD = dyn_cast<FieldDecl>(Val: D);
18741 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18742 if (VD)
18743 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18744 RefExpr->getExprLoc());
18745 else
18746 Ref = buildCapture(S&: *this, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
18747 if (VD || !isOpenMPCapturedDecl(D))
18748 ExprCaptures.push_back(Ref->getDecl());
18749 }
18750 }
18751 if (!IsImplicitClause)
18752 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18753 Vars.push_back(Elt: (VD || CurContext->isDependentContext())
18754 ? RefExpr->IgnoreParens()
18755 : Ref);
18756 PrivateCopies.push_back(VDPrivateRefExpr);
18757 Inits.push_back(Elt: VDInitRefExpr);
18758 }
18759
18760 if (Vars.empty())
18761 return nullptr;
18762
18763 return OMPFirstprivateClause::Create(C: Context, StartLoc, LParenLoc, EndLoc,
18764 VL: Vars, PrivateVL: PrivateCopies, InitVL: Inits,
18765 PreInit: buildPreInits(Context, PreInits: ExprCaptures));
18766}
18767
18768OMPClause *Sema::ActOnOpenMPLastprivateClause(
18769 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
18770 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18771 SourceLocation LParenLoc, SourceLocation EndLoc) {
18772 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18773 assert(ColonLoc.isValid() && "Colon location must be valid.");
18774 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18775 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
18776 /*Last=*/OMPC_LASTPRIVATE_unknown)
18777 << getOpenMPClauseName(OMPC_lastprivate);
18778 return nullptr;
18779 }
18780
18781 SmallVector<Expr *, 8> Vars;
18782 SmallVector<Expr *, 8> SrcExprs;
18783 SmallVector<Expr *, 8> DstExprs;
18784 SmallVector<Expr *, 8> AssignmentOps;
18785 SmallVector<Decl *, 4> ExprCaptures;
18786 SmallVector<Expr *, 4> ExprPostUpdates;
18787 for (Expr *RefExpr : VarList) {
18788 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18789 SourceLocation ELoc;
18790 SourceRange ERange;
18791 Expr *SimpleRefExpr = RefExpr;
18792 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange);
18793 if (Res.second) {
18794 // It will be analyzed later.
18795 Vars.push_back(Elt: RefExpr);
18796 SrcExprs.push_back(Elt: nullptr);
18797 DstExprs.push_back(Elt: nullptr);
18798 AssignmentOps.push_back(Elt: nullptr);
18799 }
18800 ValueDecl *D = Res.first;
18801 if (!D)
18802 continue;
18803
18804 QualType Type = D->getType();
18805 auto *VD = dyn_cast<VarDecl>(Val: D);
18806
18807 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18808 // A variable that appears in a lastprivate clause must not have an
18809 // incomplete type or a reference type.
18810 if (RequireCompleteType(ELoc, Type,
18811 diag::err_omp_lastprivate_incomplete_type))
18812 continue;
18813 Type = Type.getNonReferenceType();
18814
18815 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18816 // A variable that is privatized must not have a const-qualified type
18817 // unless it is of class type with a mutable member. This restriction does
18818 // not apply to the firstprivate clause.
18819 //
18820 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18821 // A variable that appears in a lastprivate clause must not have a
18822 // const-qualified type unless it is of class type with a mutable member.
18823 if (rejectConstNotMutableType(*this, D, Type, OMPC_lastprivate, ELoc))
18824 continue;
18825
18826 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18827 // A list item that appears in a lastprivate clause with the conditional
18828 // modifier must be a scalar variable.
18829 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18830 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18831 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18832 VarDecl::DeclarationOnly;
18833 Diag(D->getLocation(),
18834 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18835 << D;
18836 continue;
18837 }
18838
18839 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18840 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18841 // in a Construct]
18842 // Variables with the predetermined data-sharing attributes may not be
18843 // listed in data-sharing attributes clauses, except for the cases
18844 // listed below.
18845 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18846 // A list item may appear in a firstprivate or lastprivate clause but not
18847 // both.
18848 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18849 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18850 (isOpenMPDistributeDirective(CurrDir) ||
18851 DVar.CKind != OMPC_firstprivate) &&
18852 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
18853 Diag(ELoc, diag::err_omp_wrong_dsa)
18854 << getOpenMPClauseName(DVar.CKind)
18855 << getOpenMPClauseName(OMPC_lastprivate);
18856 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
18857 continue;
18858 }
18859
18860 // OpenMP [2.14.3.5, Restrictions, p.2]
18861 // A list item that is private within a parallel region, or that appears in
18862 // the reduction clause of a parallel construct, must not appear in a
18863 // lastprivate clause on a worksharing construct if any of the corresponding
18864 // worksharing regions ever binds to any of the corresponding parallel
18865 // regions.
18866 DSAStackTy::DSAVarData TopDVar = DVar;
18867 if (isOpenMPWorksharingDirective(DKind: CurrDir) &&
18868 !isOpenMPParallelDirective(DKind: CurrDir) &&
18869 !isOpenMPTeamsDirective(DKind: CurrDir)) {
18870 DVar = DSAStack->getImplicitDSA(D, FromParent: true);
18871 if (DVar.CKind != OMPC_shared) {
18872 Diag(ELoc, diag::err_omp_required_access)
18873 << getOpenMPClauseName(OMPC_lastprivate)
18874 << getOpenMPClauseName(OMPC_shared);
18875 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
18876 continue;
18877 }
18878 }
18879
18880 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18881 // A variable of class type (or array thereof) that appears in a
18882 // lastprivate clause requires an accessible, unambiguous default
18883 // constructor for the class type, unless the list item is also specified
18884 // in a firstprivate clause.
18885 // A variable of class type (or array thereof) that appears in a
18886 // lastprivate clause requires an accessible, unambiguous copy assignment
18887 // operator for the class type.
18888 Type = Context.getBaseElementType(QT: Type).getNonReferenceType();
18889 VarDecl *SrcVD = buildVarDecl(*this, ERange.getBegin(),
18890 Type.getUnqualifiedType(), ".lastprivate.src",
18891 D->hasAttrs() ? &D->getAttrs() : nullptr);
18892 DeclRefExpr *PseudoSrcExpr =
18893 buildDeclRefExpr(S&: *this, D: SrcVD, Ty: Type.getUnqualifiedType(), Loc: ELoc);
18894 VarDecl *DstVD =
18895 buildVarDecl(*this, ERange.getBegin(), Type, ".lastprivate.dst",
18896 D->hasAttrs() ? &D->getAttrs() : nullptr);
18897 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(S&: *this, D: DstVD, Ty: Type, Loc: ELoc);
18898 // For arrays generate assignment operation for single element and replace
18899 // it by the original array element in CodeGen.
18900 ExprResult AssignmentOp = BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
18901 PseudoDstExpr, PseudoSrcExpr);
18902 if (AssignmentOp.isInvalid())
18903 continue;
18904 AssignmentOp =
18905 ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: ELoc, /*DiscardedValue*/ false);
18906 if (AssignmentOp.isInvalid())
18907 continue;
18908
18909 DeclRefExpr *Ref = nullptr;
18910 if (!VD && !CurContext->isDependentContext()) {
18911 if (TopDVar.CKind == OMPC_firstprivate) {
18912 Ref = TopDVar.PrivateCopy;
18913 } else {
18914 Ref = buildCapture(S&: *this, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
18915 if (!isOpenMPCapturedDecl(D))
18916 ExprCaptures.push_back(Ref->getDecl());
18917 }
18918 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18919 (!isOpenMPCapturedDecl(D) &&
18920 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
18921 ExprResult RefRes = DefaultLvalueConversion(Ref);
18922 if (!RefRes.isUsable())
18923 continue;
18924 ExprResult PostUpdateRes =
18925 BuildBinOp(DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: SimpleRefExpr,
18926 RHSExpr: RefRes.get());
18927 if (!PostUpdateRes.isUsable())
18928 continue;
18929 ExprPostUpdates.push_back(
18930 Elt: IgnoredValueConversions(E: PostUpdateRes.get()).get());
18931 }
18932 }
18933 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18934 Vars.push_back(Elt: (VD || CurContext->isDependentContext())
18935 ? RefExpr->IgnoreParens()
18936 : Ref);
18937 SrcExprs.push_back(PseudoSrcExpr);
18938 DstExprs.push_back(PseudoDstExpr);
18939 AssignmentOps.push_back(Elt: AssignmentOp.get());
18940 }
18941
18942 if (Vars.empty())
18943 return nullptr;
18944
18945 return OMPLastprivateClause::Create(C: Context, StartLoc, LParenLoc, EndLoc,
18946 VL: Vars, SrcExprs, DstExprs, AssignmentOps,
18947 LPKind, LPKindLoc, ColonLoc,
18948 PreInit: buildPreInits(Context, PreInits: ExprCaptures),
18949 PostUpdate: buildPostUpdate(S&: *this, PostUpdates: ExprPostUpdates));
18950}
18951
18952OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
18953 SourceLocation StartLoc,
18954 SourceLocation LParenLoc,
18955 SourceLocation EndLoc) {
18956 SmallVector<Expr *, 8> Vars;
18957 for (Expr *RefExpr : VarList) {
18958 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18959 SourceLocation ELoc;
18960 SourceRange ERange;
18961 Expr *SimpleRefExpr = RefExpr;
18962 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange);
18963 if (Res.second) {
18964 // It will be analyzed later.
18965 Vars.push_back(Elt: RefExpr);
18966 }
18967 ValueDecl *D = Res.first;
18968 if (!D)
18969 continue;
18970
18971 auto *VD = dyn_cast<VarDecl>(Val: D);
18972 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18973 // in a Construct]
18974 // Variables with the predetermined data-sharing attributes may not be
18975 // listed in data-sharing attributes clauses, except for the cases
18976 // listed below. For these exceptions only, listing a predetermined
18977 // variable in a data-sharing attribute clause is allowed and overrides
18978 // the variable's predetermined data-sharing attributes.
18979 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18980 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18981 DVar.RefExpr) {
18982 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18983 << getOpenMPClauseName(OMPC_shared);
18984 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
18985 continue;
18986 }
18987
18988 DeclRefExpr *Ref = nullptr;
18989 if (!VD && isOpenMPCapturedDecl(D) && !CurContext->isDependentContext())
18990 Ref = buildCapture(S&: *this, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
18991 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18992 Vars.push_back(Elt: (VD || !Ref || CurContext->isDependentContext())
18993 ? RefExpr->IgnoreParens()
18994 : Ref);
18995 }
18996
18997 if (Vars.empty())
18998 return nullptr;
18999
19000 return OMPSharedClause::Create(C: Context, StartLoc, LParenLoc, EndLoc, VL: Vars);
19001}
19002
19003namespace {
19004class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
19005 DSAStackTy *Stack;
19006
19007public:
19008 bool VisitDeclRefExpr(DeclRefExpr *E) {
19009 if (auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
19010 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
19011 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
19012 return false;
19013 if (DVar.CKind != OMPC_unknown)
19014 return true;
19015 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
19016 VD,
19017 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
19018 return isOpenMPPrivate(C) && !AppliedToPointee;
19019 },
19020 [](OpenMPDirectiveKind) { return true; },
19021 /*FromParent=*/true);
19022 return DVarPrivate.CKind != OMPC_unknown;
19023 }
19024 return false;
19025 }
19026 bool VisitStmt(Stmt *S) {
19027 for (Stmt *Child : S->children()) {
19028 if (Child && Visit(Child))
19029 return true;
19030 }
19031 return false;
19032 }
19033 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
19034};
19035} // namespace
19036
19037namespace {
19038// Transform MemberExpression for specified FieldDecl of current class to
19039// DeclRefExpr to specified OMPCapturedExprDecl.
19040class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
19041 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
19042 ValueDecl *Field = nullptr;
19043 DeclRefExpr *CapturedExpr = nullptr;
19044
19045public:
19046 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
19047 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
19048
19049 ExprResult TransformMemberExpr(MemberExpr *E) {
19050 if (isa<CXXThisExpr>(Val: E->getBase()->IgnoreParenImpCasts()) &&
19051 E->getMemberDecl() == Field) {
19052 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
19053 return CapturedExpr;
19054 }
19055 return BaseTransform::TransformMemberExpr(E);
19056 }
19057 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
19058};
19059} // namespace
19060
19061template <typename T, typename U>
19062static T filterLookupForUDReductionAndMapper(
19063 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
19064 for (U &Set : Lookups) {
19065 for (auto *D : Set) {
19066 if (T Res = Gen(cast<ValueDecl>(D)))
19067 return Res;
19068 }
19069 }
19070 return T();
19071}
19072
19073static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
19074 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
19075
19076 for (auto *RD : D->redecls()) {
19077 // Don't bother with extra checks if we already know this one isn't visible.
19078 if (RD == D)
19079 continue;
19080
19081 auto ND = cast<NamedDecl>(RD);
19082 if (LookupResult::isVisible(SemaRef, ND))
19083 return ND;
19084 }
19085
19086 return nullptr;
19087}
19088
19089static void
19090argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
19091 SourceLocation Loc, QualType Ty,
19092 SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
19093 // Find all of the associated namespaces and classes based on the
19094 // arguments we have.
19095 Sema::AssociatedNamespaceSet AssociatedNamespaces;
19096 Sema::AssociatedClassSet AssociatedClasses;
19097 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
19098 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
19099 AssociatedClasses);
19100
19101 // C++ [basic.lookup.argdep]p3:
19102 // Let X be the lookup set produced by unqualified lookup (3.4.1)
19103 // and let Y be the lookup set produced by argument dependent
19104 // lookup (defined as follows). If X contains [...] then Y is
19105 // empty. Otherwise Y is the set of declarations found in the
19106 // namespaces associated with the argument types as described
19107 // below. The set of declarations found by the lookup of the name
19108 // is the union of X and Y.
19109 //
19110 // Here, we compute Y and add its members to the overloaded
19111 // candidate set.
19112 for (auto *NS : AssociatedNamespaces) {
19113 // When considering an associated namespace, the lookup is the
19114 // same as the lookup performed when the associated namespace is
19115 // used as a qualifier (3.4.3.2) except that:
19116 //
19117 // -- Any using-directives in the associated namespace are
19118 // ignored.
19119 //
19120 // -- Any namespace-scope friend functions declared in
19121 // associated classes are visible within their respective
19122 // namespaces even if they are not visible during an ordinary
19123 // lookup (11.4).
19124 DeclContext::lookup_result R = NS->lookup(Name: Id.getName());
19125 for (auto *D : R) {
19126 auto *Underlying = D;
19127 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
19128 Underlying = USD->getTargetDecl();
19129
19130 if (!isa<OMPDeclareReductionDecl>(Val: Underlying) &&
19131 !isa<OMPDeclareMapperDecl>(Val: Underlying))
19132 continue;
19133
19134 if (!SemaRef.isVisible(D)) {
19135 D = findAcceptableDecl(SemaRef, D);
19136 if (!D)
19137 continue;
19138 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
19139 Underlying = USD->getTargetDecl();
19140 }
19141 Lookups.emplace_back();
19142 Lookups.back().addDecl(D: Underlying);
19143 }
19144 }
19145}
19146
19147static ExprResult
19148buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
19149 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
19150 const DeclarationNameInfo &ReductionId, QualType Ty,
19151 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
19152 if (ReductionIdScopeSpec.isInvalid())
19153 return ExprError();
19154 SmallVector<UnresolvedSet<8>, 4> Lookups;
19155 if (S) {
19156 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19157 Lookup.suppressDiagnostics();
19158 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &ReductionIdScopeSpec)) {
19159 NamedDecl *D = Lookup.getRepresentativeDecl();
19160 do {
19161 S = S->getParent();
19162 } while (S && !S->isDeclScope(D));
19163 if (S)
19164 S = S->getParent();
19165 Lookups.emplace_back();
19166 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
19167 Lookup.clear();
19168 }
19169 } else if (auto *ULE =
19170 cast_or_null<UnresolvedLookupExpr>(Val: UnresolvedReduction)) {
19171 Lookups.push_back(Elt: UnresolvedSet<8>());
19172 Decl *PrevD = nullptr;
19173 for (NamedDecl *D : ULE->decls()) {
19174 if (D == PrevD)
19175 Lookups.push_back(UnresolvedSet<8>());
19176 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19177 Lookups.back().addDecl(DRD);
19178 PrevD = D;
19179 }
19180 }
19181 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
19182 Ty->isInstantiationDependentType() ||
19183 Ty->containsUnexpandedParameterPack() ||
19184 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
19185 return !D->isInvalidDecl() &&
19186 (D->getType()->isDependentType() ||
19187 D->getType()->isInstantiationDependentType() ||
19188 D->getType()->containsUnexpandedParameterPack());
19189 })) {
19190 UnresolvedSet<8> ResSet;
19191 for (const UnresolvedSet<8> &Set : Lookups) {
19192 if (Set.empty())
19193 continue;
19194 ResSet.append(I: Set.begin(), E: Set.end());
19195 // The last item marks the end of all declarations at the specified scope.
19196 ResSet.addDecl(D: Set[Set.size() - 1]);
19197 }
19198 return UnresolvedLookupExpr::Create(
19199 Context: SemaRef.Context, /*NamingClass=*/nullptr,
19200 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: SemaRef.Context), NameInfo: ReductionId,
19201 /*ADL=*/RequiresADL: true, /*Overloaded=*/true, Begin: ResSet.begin(), End: ResSet.end());
19202 }
19203 // Lookup inside the classes.
19204 // C++ [over.match.oper]p3:
19205 // For a unary operator @ with an operand of a type whose
19206 // cv-unqualified version is T1, and for a binary operator @ with
19207 // a left operand of a type whose cv-unqualified version is T1 and
19208 // a right operand of a type whose cv-unqualified version is T2,
19209 // three sets of candidate functions, designated member
19210 // candidates, non-member candidates and built-in candidates, are
19211 // constructed as follows:
19212 // -- If T1 is a complete class type or a class currently being
19213 // defined, the set of member candidates is the result of the
19214 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19215 // the set of member candidates is empty.
19216 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19217 Lookup.suppressDiagnostics();
19218 if (const auto *TyRec = Ty->getAs<RecordType>()) {
19219 // Complete the type if it can be completed.
19220 // If the type is neither complete nor being defined, bail out now.
19221 if (SemaRef.isCompleteType(Loc, T: Ty) || TyRec->isBeingDefined() ||
19222 TyRec->getDecl()->getDefinition()) {
19223 Lookup.clear();
19224 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
19225 if (Lookup.empty()) {
19226 Lookups.emplace_back();
19227 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
19228 }
19229 }
19230 }
19231 // Perform ADL.
19232 if (SemaRef.getLangOpts().CPlusPlus)
19233 argumentDependentLookup(SemaRef, Id: ReductionId, Loc, Ty, Lookups);
19234 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
19235 Lookups, Gen: [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
19236 if (!D->isInvalidDecl() &&
19237 SemaRef.Context.hasSameType(T1: D->getType(), T2: Ty))
19238 return D;
19239 return nullptr;
19240 }))
19241 return SemaRef.BuildDeclRefExpr(D: VD, Ty: VD->getType().getNonReferenceType(),
19242 VK: VK_LValue, Loc);
19243 if (SemaRef.getLangOpts().CPlusPlus) {
19244 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
19245 Lookups, Gen: [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
19246 if (!D->isInvalidDecl() &&
19247 SemaRef.IsDerivedFrom(Loc, Derived: Ty, Base: D->getType()) &&
19248 !Ty.isMoreQualifiedThan(other: D->getType()))
19249 return D;
19250 return nullptr;
19251 })) {
19252 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19253 /*DetectVirtual=*/false);
19254 if (SemaRef.IsDerivedFrom(Loc, Derived: Ty, Base: VD->getType(), Paths)) {
19255 if (!Paths.isAmbiguous(BaseType: SemaRef.Context.getCanonicalType(
19256 T: VD->getType().getUnqualifiedType()))) {
19257 if (SemaRef.CheckBaseClassAccess(
19258 AccessLoc: Loc, Base: VD->getType(), Derived: Ty, Path: Paths.front(),
19259 /*DiagID=*/0) != Sema::AR_inaccessible) {
19260 SemaRef.BuildBasePathArray(Paths, BasePath);
19261 return SemaRef.BuildDeclRefExpr(
19262 D: VD, Ty: VD->getType().getNonReferenceType(), VK: VK_LValue, Loc);
19263 }
19264 }
19265 }
19266 }
19267 }
19268 if (ReductionIdScopeSpec.isSet()) {
19269 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19270 << Ty << Range;
19271 return ExprError();
19272 }
19273 return ExprEmpty();
19274}
19275
19276namespace {
19277/// Data for the reduction-based clauses.
19278struct ReductionData {
19279 /// List of original reduction items.
19280 SmallVector<Expr *, 8> Vars;
19281 /// List of private copies of the reduction items.
19282 SmallVector<Expr *, 8> Privates;
19283 /// LHS expressions for the reduction_op expressions.
19284 SmallVector<Expr *, 8> LHSs;
19285 /// RHS expressions for the reduction_op expressions.
19286 SmallVector<Expr *, 8> RHSs;
19287 /// Reduction operation expression.
19288 SmallVector<Expr *, 8> ReductionOps;
19289 /// inscan copy operation expressions.
19290 SmallVector<Expr *, 8> InscanCopyOps;
19291 /// inscan copy temp array expressions for prefix sums.
19292 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19293 /// inscan copy temp array element expressions for prefix sums.
19294 SmallVector<Expr *, 8> InscanCopyArrayElems;
19295 /// Taskgroup descriptors for the corresponding reduction items in
19296 /// in_reduction clauses.
19297 SmallVector<Expr *, 8> TaskgroupDescriptors;
19298 /// List of captures for clause.
19299 SmallVector<Decl *, 4> ExprCaptures;
19300 /// List of postupdate expressions.
19301 SmallVector<Expr *, 4> ExprPostUpdates;
19302 /// Reduction modifier.
19303 unsigned RedModifier = 0;
19304 ReductionData() = delete;
19305 /// Reserves required memory for the reduction data.
19306 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
19307 Vars.reserve(N: Size);
19308 Privates.reserve(N: Size);
19309 LHSs.reserve(N: Size);
19310 RHSs.reserve(N: Size);
19311 ReductionOps.reserve(N: Size);
19312 if (RedModifier == OMPC_REDUCTION_inscan) {
19313 InscanCopyOps.reserve(N: Size);
19314 InscanCopyArrayTemps.reserve(N: Size);
19315 InscanCopyArrayElems.reserve(N: Size);
19316 }
19317 TaskgroupDescriptors.reserve(N: Size);
19318 ExprCaptures.reserve(N: Size);
19319 ExprPostUpdates.reserve(N: Size);
19320 }
19321 /// Stores reduction item and reduction operation only (required for dependent
19322 /// reduction item).
19323 void push(Expr *Item, Expr *ReductionOp) {
19324 Vars.emplace_back(Args&: Item);
19325 Privates.emplace_back(Args: nullptr);
19326 LHSs.emplace_back(Args: nullptr);
19327 RHSs.emplace_back(Args: nullptr);
19328 ReductionOps.emplace_back(Args&: ReductionOp);
19329 TaskgroupDescriptors.emplace_back(Args: nullptr);
19330 if (RedModifier == OMPC_REDUCTION_inscan) {
19331 InscanCopyOps.push_back(Elt: nullptr);
19332 InscanCopyArrayTemps.push_back(Elt: nullptr);
19333 InscanCopyArrayElems.push_back(Elt: nullptr);
19334 }
19335 }
19336 /// Stores reduction data.
19337 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19338 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19339 Expr *CopyArrayElem) {
19340 Vars.emplace_back(Args&: Item);
19341 Privates.emplace_back(Args&: Private);
19342 LHSs.emplace_back(Args&: LHS);
19343 RHSs.emplace_back(Args&: RHS);
19344 ReductionOps.emplace_back(Args&: ReductionOp);
19345 TaskgroupDescriptors.emplace_back(Args&: TaskgroupDescriptor);
19346 if (RedModifier == OMPC_REDUCTION_inscan) {
19347 InscanCopyOps.push_back(Elt: CopyOp);
19348 InscanCopyArrayTemps.push_back(Elt: CopyArrayTemp);
19349 InscanCopyArrayElems.push_back(Elt: CopyArrayElem);
19350 } else {
19351 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
19352 CopyArrayElem == nullptr &&
19353 "Copy operation must be used for inscan reductions only.");
19354 }
19355 }
19356};
19357} // namespace
19358
19359static bool checkOMPArraySectionConstantForReduction(
19360 ASTContext &Context, const OMPArraySectionExpr *OASE, bool &SingleElement,
19361 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
19362 const Expr *Length = OASE->getLength();
19363 if (Length == nullptr) {
19364 // For array sections of the form [1:] or [:], we would need to analyze
19365 // the lower bound...
19366 if (OASE->getColonLocFirst().isValid())
19367 return false;
19368
19369 // This is an array subscript which has implicit length 1!
19370 SingleElement = true;
19371 ArraySizes.push_back(Elt: llvm::APSInt::get(X: 1));
19372 } else {
19373 Expr::EvalResult Result;
19374 if (!Length->EvaluateAsInt(Result, Ctx: Context))
19375 return false;
19376
19377 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19378 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19379 ArraySizes.push_back(Elt: ConstantLengthValue);
19380 }
19381
19382 // Get the base of this array section and walk up from there.
19383 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
19384
19385 // We require length = 1 for all array sections except the right-most to
19386 // guarantee that the memory region is contiguous and has no holes in it.
19387 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Val: Base)) {
19388 Length = TempOASE->getLength();
19389 if (Length == nullptr) {
19390 // For array sections of the form [1:] or [:], we would need to analyze
19391 // the lower bound...
19392 if (OASE->getColonLocFirst().isValid())
19393 return false;
19394
19395 // This is an array subscript which has implicit length 1!
19396 ArraySizes.push_back(Elt: llvm::APSInt::get(X: 1));
19397 } else {
19398 Expr::EvalResult Result;
19399 if (!Length->EvaluateAsInt(Result, Ctx: Context))
19400 return false;
19401
19402 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19403 if (ConstantLengthValue.getSExtValue() != 1)
19404 return false;
19405
19406 ArraySizes.push_back(Elt: ConstantLengthValue);
19407 }
19408 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19409 }
19410
19411 // If we have a single element, we don't need to add the implicit lengths.
19412 if (!SingleElement) {
19413 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base)) {
19414 // Has implicit length 1!
19415 ArraySizes.push_back(Elt: llvm::APSInt::get(X: 1));
19416 Base = TempASE->getBase()->IgnoreParenImpCasts();
19417 }
19418 }
19419
19420 // This array section can be privatized as a single value or as a constant
19421 // sized array.
19422 return true;
19423}
19424
19425static BinaryOperatorKind
19426getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
19427 if (BOK == BO_Add)
19428 return BO_AddAssign;
19429 if (BOK == BO_Mul)
19430 return BO_MulAssign;
19431 if (BOK == BO_And)
19432 return BO_AndAssign;
19433 if (BOK == BO_Or)
19434 return BO_OrAssign;
19435 if (BOK == BO_Xor)
19436 return BO_XorAssign;
19437 return BOK;
19438}
19439
19440static bool actOnOMPReductionKindClause(
19441 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
19442 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19443 SourceLocation ColonLoc, SourceLocation EndLoc,
19444 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19445 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
19446 DeclarationName DN = ReductionId.getName();
19447 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
19448 BinaryOperatorKind BOK = BO_Comma;
19449
19450 ASTContext &Context = S.Context;
19451 // OpenMP [2.14.3.6, reduction clause]
19452 // C
19453 // reduction-identifier is either an identifier or one of the following
19454 // operators: +, -, *, &, |, ^, && and ||
19455 // C++
19456 // reduction-identifier is either an id-expression or one of the following
19457 // operators: +, -, *, &, |, ^, && and ||
19458 switch (OOK) {
19459 case OO_Plus:
19460 BOK = BO_Add;
19461 break;
19462 case OO_Minus:
19463 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
19464 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
19465 // reduction identifier.
19466 if (S.LangOpts.OpenMP > 52)
19467 BOK = BO_Comma;
19468 else
19469 BOK = BO_Add;
19470 break;
19471 case OO_Star:
19472 BOK = BO_Mul;
19473 break;
19474 case OO_Amp:
19475 BOK = BO_And;
19476 break;
19477 case OO_Pipe:
19478 BOK = BO_Or;
19479 break;
19480 case OO_Caret:
19481 BOK = BO_Xor;
19482 break;
19483 case OO_AmpAmp:
19484 BOK = BO_LAnd;
19485 break;
19486 case OO_PipePipe:
19487 BOK = BO_LOr;
19488 break;
19489 case OO_New:
19490 case OO_Delete:
19491 case OO_Array_New:
19492 case OO_Array_Delete:
19493 case OO_Slash:
19494 case OO_Percent:
19495 case OO_Tilde:
19496 case OO_Exclaim:
19497 case OO_Equal:
19498 case OO_Less:
19499 case OO_Greater:
19500 case OO_LessEqual:
19501 case OO_GreaterEqual:
19502 case OO_PlusEqual:
19503 case OO_MinusEqual:
19504 case OO_StarEqual:
19505 case OO_SlashEqual:
19506 case OO_PercentEqual:
19507 case OO_CaretEqual:
19508 case OO_AmpEqual:
19509 case OO_PipeEqual:
19510 case OO_LessLess:
19511 case OO_GreaterGreater:
19512 case OO_LessLessEqual:
19513 case OO_GreaterGreaterEqual:
19514 case OO_EqualEqual:
19515 case OO_ExclaimEqual:
19516 case OO_Spaceship:
19517 case OO_PlusPlus:
19518 case OO_MinusMinus:
19519 case OO_Comma:
19520 case OO_ArrowStar:
19521 case OO_Arrow:
19522 case OO_Call:
19523 case OO_Subscript:
19524 case OO_Conditional:
19525 case OO_Coawait:
19526 case NUM_OVERLOADED_OPERATORS:
19527 llvm_unreachable("Unexpected reduction identifier");
19528 case OO_None:
19529 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
19530 if (II->isStr(Str: "max"))
19531 BOK = BO_GT;
19532 else if (II->isStr(Str: "min"))
19533 BOK = BO_LT;
19534 }
19535 break;
19536 }
19537
19538 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
19539 // A reduction clause with the minus (-) operator was deprecated
19540 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
19541 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
19542
19543 SourceRange ReductionIdRange;
19544 if (ReductionIdScopeSpec.isValid())
19545 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
19546 else
19547 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
19548 ReductionIdRange.setEnd(ReductionId.getEndLoc());
19549
19550 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
19551 bool FirstIter = true;
19552 for (Expr *RefExpr : VarList) {
19553 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
19554 // OpenMP [2.1, C/C++]
19555 // A list item is a variable or array section, subject to the restrictions
19556 // specified in Section 2.4 on page 42 and in each of the sections
19557 // describing clauses and directives for which a list appears.
19558 // OpenMP [2.14.3.3, Restrictions, p.1]
19559 // A variable that is part of another variable (as an array or
19560 // structure element) cannot appear in a private clause.
19561 if (!FirstIter && IR != ER)
19562 ++IR;
19563 FirstIter = false;
19564 SourceLocation ELoc;
19565 SourceRange ERange;
19566 Expr *SimpleRefExpr = RefExpr;
19567 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
19568 /*AllowArraySection=*/true);
19569 if (Res.second) {
19570 // Try to find 'declare reduction' corresponding construct before using
19571 // builtin/overloaded operators.
19572 QualType Type = Context.DependentTy;
19573 CXXCastPath BasePath;
19574 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19575 SemaRef&: S, Loc: ELoc, Range: ERange, S: Stack->getCurScope(), ReductionIdScopeSpec,
19576 ReductionId, Ty: Type, BasePath, UnresolvedReduction: IR == ER ? nullptr : *IR);
19577 Expr *ReductionOp = nullptr;
19578 if (S.CurContext->isDependentContext() &&
19579 (DeclareReductionRef.isUnset() ||
19580 isa<UnresolvedLookupExpr>(Val: DeclareReductionRef.get())))
19581 ReductionOp = DeclareReductionRef.get();
19582 // It will be analyzed later.
19583 RD.push(Item: RefExpr, ReductionOp);
19584 }
19585 ValueDecl *D = Res.first;
19586 if (!D)
19587 continue;
19588
19589 Expr *TaskgroupDescriptor = nullptr;
19590 QualType Type;
19591 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: RefExpr->IgnoreParens());
19592 auto *OASE = dyn_cast<OMPArraySectionExpr>(Val: RefExpr->IgnoreParens());
19593 if (ASE) {
19594 Type = ASE->getType().getNonReferenceType();
19595 } else if (OASE) {
19596 QualType BaseType =
19597 OMPArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
19598 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19599 Type = ATy->getElementType();
19600 else
19601 Type = BaseType->getPointeeType();
19602 Type = Type.getNonReferenceType();
19603 } else {
19604 Type = Context.getBaseElementType(QT: D->getType().getNonReferenceType());
19605 }
19606 auto *VD = dyn_cast<VarDecl>(Val: D);
19607
19608 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19609 // A variable that appears in a private clause must not have an incomplete
19610 // type or a reference type.
19611 if (S.RequireCompleteType(ELoc, D->getType(),
19612 diag::err_omp_reduction_incomplete_type))
19613 continue;
19614 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19615 // A list item that appears in a reduction clause must not be
19616 // const-qualified.
19617 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
19618 /*AcceptIfMutable*/ false, ASE || OASE))
19619 continue;
19620
19621 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
19622 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19623 // If a list-item is a reference type then it must bind to the same object
19624 // for all threads of the team.
19625 if (!ASE && !OASE) {
19626 if (VD) {
19627 VarDecl *VDDef = VD->getDefinition();
19628 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
19629 DSARefChecker Check(Stack);
19630 if (Check.Visit(VDDef->getInit())) {
19631 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19632 << getOpenMPClauseName(ClauseKind) << ERange;
19633 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
19634 continue;
19635 }
19636 }
19637 }
19638
19639 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19640 // in a Construct]
19641 // Variables with the predetermined data-sharing attributes may not be
19642 // listed in data-sharing attributes clauses, except for the cases
19643 // listed below. For these exceptions only, listing a predetermined
19644 // variable in a data-sharing attribute clause is allowed and overrides
19645 // the variable's predetermined data-sharing attributes.
19646 // OpenMP [2.14.3.6, Restrictions, p.3]
19647 // Any number of reduction clauses can be specified on the directive,
19648 // but a list item can appear only once in the reduction clauses for that
19649 // directive.
19650 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19651 if (DVar.CKind == OMPC_reduction) {
19652 S.Diag(ELoc, diag::err_omp_once_referenced)
19653 << getOpenMPClauseName(ClauseKind);
19654 if (DVar.RefExpr)
19655 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
19656 continue;
19657 }
19658 if (DVar.CKind != OMPC_unknown) {
19659 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19660 << getOpenMPClauseName(DVar.CKind)
19661 << getOpenMPClauseName(OMPC_reduction);
19662 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
19663 continue;
19664 }
19665
19666 // OpenMP [2.14.3.6, Restrictions, p.1]
19667 // A list item that appears in a reduction clause of a worksharing
19668 // construct must be shared in the parallel regions to which any of the
19669 // worksharing regions arising from the worksharing construct bind.
19670 if (isOpenMPWorksharingDirective(DKind: CurrDir) &&
19671 !isOpenMPParallelDirective(DKind: CurrDir) &&
19672 !isOpenMPTeamsDirective(DKind: CurrDir)) {
19673 DVar = Stack->getImplicitDSA(D, FromParent: true);
19674 if (DVar.CKind != OMPC_shared) {
19675 S.Diag(ELoc, diag::err_omp_required_access)
19676 << getOpenMPClauseName(OMPC_reduction)
19677 << getOpenMPClauseName(OMPC_shared);
19678 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
19679 continue;
19680 }
19681 }
19682 } else {
19683 // Threadprivates cannot be shared between threads, so dignose if the base
19684 // is a threadprivate variable.
19685 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19686 if (DVar.CKind == OMPC_threadprivate) {
19687 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19688 << getOpenMPClauseName(DVar.CKind)
19689 << getOpenMPClauseName(OMPC_reduction);
19690 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
19691 continue;
19692 }
19693 }
19694
19695 // Try to find 'declare reduction' corresponding construct before using
19696 // builtin/overloaded operators.
19697 CXXCastPath BasePath;
19698 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19699 SemaRef&: S, Loc: ELoc, Range: ERange, S: Stack->getCurScope(), ReductionIdScopeSpec,
19700 ReductionId, Ty: Type, BasePath, UnresolvedReduction: IR == ER ? nullptr : *IR);
19701 if (DeclareReductionRef.isInvalid())
19702 continue;
19703 if (S.CurContext->isDependentContext() &&
19704 (DeclareReductionRef.isUnset() ||
19705 isa<UnresolvedLookupExpr>(Val: DeclareReductionRef.get()))) {
19706 RD.push(Item: RefExpr, ReductionOp: DeclareReductionRef.get());
19707 continue;
19708 }
19709 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19710 // Not allowed reduction identifier is found.
19711 if (S.LangOpts.OpenMP > 52)
19712 S.Diag(ReductionId.getBeginLoc(),
19713 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
19714 << Type << ReductionIdRange;
19715 else
19716 S.Diag(ReductionId.getBeginLoc(),
19717 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
19718 << Type << ReductionIdRange;
19719 continue;
19720 }
19721
19722 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19723 // The type of a list item that appears in a reduction clause must be valid
19724 // for the reduction-identifier. For a max or min reduction in C, the type
19725 // of the list item must be an allowed arithmetic data type: char, int,
19726 // float, double, or _Bool, possibly modified with long, short, signed, or
19727 // unsigned. For a max or min reduction in C++, the type of the list item
19728 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19729 // double, or bool, possibly modified with long, short, signed, or unsigned.
19730 if (DeclareReductionRef.isUnset()) {
19731 if ((BOK == BO_GT || BOK == BO_LT) &&
19732 !(Type->isScalarType() ||
19733 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19734 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19735 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
19736 if (!ASE && !OASE) {
19737 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19738 VarDecl::DeclarationOnly;
19739 S.Diag(D->getLocation(),
19740 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19741 << D;
19742 }
19743 continue;
19744 }
19745 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19746 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19747 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19748 << getOpenMPClauseName(ClauseKind);
19749 if (!ASE && !OASE) {
19750 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19751 VarDecl::DeclarationOnly;
19752 S.Diag(D->getLocation(),
19753 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19754 << D;
19755 }
19756 continue;
19757 }
19758 }
19759
19760 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19761 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
19762 D->hasAttrs() ? &D->getAttrs() : nullptr);
19763 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
19764 D->hasAttrs() ? &D->getAttrs() : nullptr);
19765 QualType PrivateTy = Type;
19766
19767 // Try if we can determine constant lengths for all array sections and avoid
19768 // the VLA.
19769 bool ConstantLengthOASE = false;
19770 if (OASE) {
19771 bool SingleElement;
19772 llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
19773 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19774 Context, OASE, SingleElement, ArraySizes);
19775
19776 // If we don't have a single element, we must emit a constant array type.
19777 if (ConstantLengthOASE && !SingleElement) {
19778 for (llvm::APSInt &Size : ArraySizes)
19779 PrivateTy = Context.getConstantArrayType(EltTy: PrivateTy, ArySize: Size, SizeExpr: nullptr,
19780 ASM: ArraySizeModifier::Normal,
19781 /*IndexTypeQuals=*/0);
19782 }
19783 }
19784
19785 if ((OASE && !ConstantLengthOASE) ||
19786 (!OASE && !ASE &&
19787 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
19788 if (!Context.getTargetInfo().isVLASupported()) {
19789 if (isOpenMPTargetExecutionDirective(DKind: Stack->getCurrentDirective())) {
19790 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19791 S.Diag(ELoc, diag::note_vla_unsupported);
19792 continue;
19793 } else {
19794 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19795 S.targetDiag(ELoc, diag::note_vla_unsupported);
19796 }
19797 }
19798 // For arrays/array sections only:
19799 // Create pseudo array type for private copy. The size for this array will
19800 // be generated during codegen.
19801 // For array subscripts or single variables Private Ty is the same as Type
19802 // (type of the variable or single array element).
19803 PrivateTy = Context.getVariableArrayType(
19804 Type,
19805 new (Context)
19806 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19807 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange());
19808 } else if (!ASE && !OASE &&
19809 Context.getAsArrayType(T: D->getType().getNonReferenceType())) {
19810 PrivateTy = D->getType().getNonReferenceType();
19811 }
19812 // Private copy.
19813 VarDecl *PrivateVD =
19814 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19815 D->hasAttrs() ? &D->getAttrs() : nullptr,
19816 VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
19817 // Add initializer for private variable.
19818 Expr *Init = nullptr;
19819 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, D: LHSVD, Ty: Type, Loc: ELoc);
19820 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, D: RHSVD, Ty: Type, Loc: ELoc);
19821 if (DeclareReductionRef.isUsable()) {
19822 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19823 auto *DRD = cast<OMPDeclareReductionDecl>(Val: DRDRef->getDecl());
19824 if (DRD->getInitializer()) {
19825 Init = DRDRef;
19826 RHSVD->setInit(DRDRef);
19827 RHSVD->setInitStyle(VarDecl::CallInit);
19828 }
19829 } else {
19830 switch (BOK) {
19831 case BO_Add:
19832 case BO_Xor:
19833 case BO_Or:
19834 case BO_LOr:
19835 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19836 if (Type->isScalarType() || Type->isAnyComplexType())
19837 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/0).get();
19838 break;
19839 case BO_Mul:
19840 case BO_LAnd:
19841 if (Type->isScalarType() || Type->isAnyComplexType()) {
19842 // '*' and '&&' reduction ops - initializer is '1'.
19843 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
19844 }
19845 break;
19846 case BO_And: {
19847 // '&' reduction op - initializer is '~0'.
19848 QualType OrigType = Type;
19849 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
19850 Type = ComplexTy->getElementType();
19851 if (Type->isRealFloatingType()) {
19852 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19853 Semantics: Context.getFloatTypeSemantics(T: Type));
19854 Init = FloatingLiteral::Create(C: Context, V: InitValue, /*isexact=*/true,
19855 Type, L: ELoc);
19856 } else if (Type->isScalarType()) {
19857 uint64_t Size = Context.getTypeSize(T: Type);
19858 QualType IntTy = Context.getIntTypeForBitwidth(DestWidth: Size, /*Signed=*/0);
19859 llvm::APInt InitValue = llvm::APInt::getAllOnes(numBits: Size);
19860 Init = IntegerLiteral::Create(C: Context, V: InitValue, type: IntTy, l: ELoc);
19861 }
19862 if (Init && OrigType->isAnyComplexType()) {
19863 // Init = 0xFFFF + 0xFFFFi;
19864 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
19865 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
19866 }
19867 Type = OrigType;
19868 break;
19869 }
19870 case BO_LT:
19871 case BO_GT: {
19872 // 'min' reduction op - initializer is 'Largest representable number in
19873 // the reduction list item type'.
19874 // 'max' reduction op - initializer is 'Least representable number in
19875 // the reduction list item type'.
19876 if (Type->isIntegerType() || Type->isPointerType()) {
19877 bool IsSigned = Type->hasSignedIntegerRepresentation();
19878 uint64_t Size = Context.getTypeSize(T: Type);
19879 QualType IntTy =
19880 Context.getIntTypeForBitwidth(DestWidth: Size, /*Signed=*/IsSigned);
19881 llvm::APInt InitValue =
19882 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(numBits: Size)
19883 : llvm::APInt::getMinValue(numBits: Size)
19884 : IsSigned ? llvm::APInt::getSignedMaxValue(numBits: Size)
19885 : llvm::APInt::getMaxValue(numBits: Size);
19886 Init = IntegerLiteral::Create(C: Context, V: InitValue, type: IntTy, l: ELoc);
19887 if (Type->isPointerType()) {
19888 // Cast to pointer type.
19889 ExprResult CastExpr = S.BuildCStyleCastExpr(
19890 LParenLoc: ELoc, Ty: Context.getTrivialTypeSourceInfo(T: Type, Loc: ELoc), RParenLoc: ELoc, Op: Init);
19891 if (CastExpr.isInvalid())
19892 continue;
19893 Init = CastExpr.get();
19894 }
19895 } else if (Type->isRealFloatingType()) {
19896 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19897 Sem: Context.getFloatTypeSemantics(T: Type), Negative: BOK != BO_LT);
19898 Init = FloatingLiteral::Create(C: Context, V: InitValue, /*isexact=*/true,
19899 Type, L: ELoc);
19900 }
19901 break;
19902 }
19903 case BO_PtrMemD:
19904 case BO_PtrMemI:
19905 case BO_MulAssign:
19906 case BO_Div:
19907 case BO_Rem:
19908 case BO_Sub:
19909 case BO_Shl:
19910 case BO_Shr:
19911 case BO_LE:
19912 case BO_GE:
19913 case BO_EQ:
19914 case BO_NE:
19915 case BO_Cmp:
19916 case BO_AndAssign:
19917 case BO_XorAssign:
19918 case BO_OrAssign:
19919 case BO_Assign:
19920 case BO_AddAssign:
19921 case BO_SubAssign:
19922 case BO_DivAssign:
19923 case BO_RemAssign:
19924 case BO_ShlAssign:
19925 case BO_ShrAssign:
19926 case BO_Comma:
19927 llvm_unreachable("Unexpected reduction operation");
19928 }
19929 }
19930 if (Init && DeclareReductionRef.isUnset()) {
19931 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
19932 // Store initializer for single element in private copy. Will be used
19933 // during codegen.
19934 PrivateVD->setInit(RHSVD->getInit());
19935 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19936 } else if (!Init) {
19937 S.ActOnUninitializedDecl(RHSVD);
19938 // Store initializer for single element in private copy. Will be used
19939 // during codegen.
19940 PrivateVD->setInit(RHSVD->getInit());
19941 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19942 }
19943 if (RHSVD->isInvalidDecl())
19944 continue;
19945 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
19946 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19947 << Type << ReductionIdRange;
19948 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19949 VarDecl::DeclarationOnly;
19950 S.Diag(D->getLocation(),
19951 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19952 << D;
19953 continue;
19954 }
19955 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, D: PrivateVD, Ty: PrivateTy, Loc: ELoc);
19956 ExprResult ReductionOp;
19957 if (DeclareReductionRef.isUsable()) {
19958 QualType RedTy = DeclareReductionRef.get()->getType();
19959 QualType PtrRedTy = Context.getPointerType(T: RedTy);
19960 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
19961 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
19962 if (!BasePath.empty()) {
19963 LHS = S.DefaultLvalueConversion(E: LHS.get());
19964 RHS = S.DefaultLvalueConversion(E: RHS.get());
19965 LHS = ImplicitCastExpr::Create(
19966 Context, T: PtrRedTy, Kind: CK_UncheckedDerivedToBase, Operand: LHS.get(), BasePath: &BasePath,
19967 Cat: LHS.get()->getValueKind(), FPO: FPOptionsOverride());
19968 RHS = ImplicitCastExpr::Create(
19969 Context, T: PtrRedTy, Kind: CK_UncheckedDerivedToBase, Operand: RHS.get(), BasePath: &BasePath,
19970 Cat: RHS.get()->getValueKind(), FPO: FPOptionsOverride());
19971 }
19972 FunctionProtoType::ExtProtoInfo EPI;
19973 QualType Params[] = {PtrRedTy, PtrRedTy};
19974 QualType FnTy = Context.getFunctionType(ResultTy: Context.VoidTy, Args: Params, EPI);
19975 auto *OVE = new (Context) OpaqueValueExpr(
19976 ELoc, Context.getPointerType(T: FnTy), VK_PRValue, OK_Ordinary,
19977 S.DefaultLvalueConversion(E: DeclareReductionRef.get()).get());
19978 Expr *Args[] = {LHS.get(), RHS.get()};
19979 ReductionOp =
19980 CallExpr::Create(Ctx: Context, Fn: OVE, Args, Ty: Context.VoidTy, VK: VK_PRValue, RParenLoc: ELoc,
19981 FPFeatures: S.CurFPFeatureOverrides());
19982 } else {
19983 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
19984 if (Type->isRecordType() && CombBOK != BOK) {
19985 Sema::TentativeAnalysisScope Trap(S);
19986 ReductionOp =
19987 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19988 CombBOK, LHSDRE, RHSDRE);
19989 }
19990 if (!ReductionOp.isUsable()) {
19991 ReductionOp =
19992 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
19993 LHSDRE, RHSDRE);
19994 if (ReductionOp.isUsable()) {
19995 if (BOK != BO_LT && BOK != BO_GT) {
19996 ReductionOp =
19997 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19998 BO_Assign, LHSDRE, ReductionOp.get());
19999 } else {
20000 auto *ConditionalOp = new (Context)
20001 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
20002 RHSDRE, Type, VK_LValue, OK_Ordinary);
20003 ReductionOp =
20004 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
20005 Opc: BO_Assign, LHSExpr: LHSDRE, RHSExpr: ConditionalOp);
20006 }
20007 }
20008 }
20009 if (ReductionOp.isUsable())
20010 ReductionOp = S.ActOnFinishFullExpr(Expr: ReductionOp.get(),
20011 /*DiscardedValue*/ false);
20012 if (!ReductionOp.isUsable())
20013 continue;
20014 }
20015
20016 // Add copy operations for inscan reductions.
20017 // LHS = RHS;
20018 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
20019 if (ClauseKind == OMPC_reduction &&
20020 RD.RedModifier == OMPC_REDUCTION_inscan) {
20021 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
20022 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
20023 RHS.get());
20024 if (!CopyOpRes.isUsable())
20025 continue;
20026 CopyOpRes =
20027 S.ActOnFinishFullExpr(Expr: CopyOpRes.get(), /*DiscardedValue=*/true);
20028 if (!CopyOpRes.isUsable())
20029 continue;
20030 // For simd directive and simd-based directives in simd mode no need to
20031 // construct temp array, need just a single temp element.
20032 if (Stack->getCurrentDirective() == OMPD_simd ||
20033 (S.getLangOpts().OpenMPSimd &&
20034 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
20035 VarDecl *TempArrayVD =
20036 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20037 D->hasAttrs() ? &D->getAttrs() : nullptr);
20038 // Add a constructor to the temp decl.
20039 S.ActOnUninitializedDecl(TempArrayVD);
20040 TempArrayRes = buildDeclRefExpr(S, D: TempArrayVD, Ty: PrivateTy, Loc: ELoc);
20041 } else {
20042 // Build temp array for prefix sum.
20043 auto *Dim = new (S.Context)
20044 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
20045 QualType ArrayTy = S.Context.getVariableArrayType(
20046 PrivateTy, Dim, ArraySizeModifier::Normal,
20047 /*IndexTypeQuals=*/0, {ELoc, ELoc});
20048 VarDecl *TempArrayVD =
20049 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
20050 D->hasAttrs() ? &D->getAttrs() : nullptr);
20051 // Add a constructor to the temp decl.
20052 S.ActOnUninitializedDecl(TempArrayVD);
20053 TempArrayRes = buildDeclRefExpr(S, D: TempArrayVD, Ty: ArrayTy, Loc: ELoc);
20054 TempArrayElem =
20055 S.DefaultFunctionArrayLvalueConversion(E: TempArrayRes.get());
20056 auto *Idx = new (S.Context)
20057 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
20058 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
20059 ELoc, Idx, ELoc);
20060 }
20061 }
20062
20063 // OpenMP [2.15.4.6, Restrictions, p.2]
20064 // A list item that appears in an in_reduction clause of a task construct
20065 // must appear in a task_reduction clause of a construct associated with a
20066 // taskgroup region that includes the participating task in its taskgroup
20067 // set. The construct associated with the innermost region that meets this
20068 // condition must specify the same reduction-identifier as the in_reduction
20069 // clause.
20070 if (ClauseKind == OMPC_in_reduction) {
20071 SourceRange ParentSR;
20072 BinaryOperatorKind ParentBOK;
20073 const Expr *ParentReductionOp = nullptr;
20074 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
20075 DSAStackTy::DSAVarData ParentBOKDSA =
20076 Stack->getTopMostTaskgroupReductionData(D, SR&: ParentSR, BOK&: ParentBOK,
20077 TaskgroupDescriptor&: ParentBOKTD);
20078 DSAStackTy::DSAVarData ParentReductionOpDSA =
20079 Stack->getTopMostTaskgroupReductionData(
20080 D, SR&: ParentSR, ReductionRef&: ParentReductionOp, TaskgroupDescriptor&: ParentReductionOpTD);
20081 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20082 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20083 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
20084 (DeclareReductionRef.isUsable() && IsParentBOK) ||
20085 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20086 bool EmitError = true;
20087 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
20088 llvm::FoldingSetNodeID RedId, ParentRedId;
20089 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
20090 DeclareReductionRef.get()->Profile(RedId, Context,
20091 /*Canonical=*/true);
20092 EmitError = RedId != ParentRedId;
20093 }
20094 if (EmitError) {
20095 S.Diag(ReductionId.getBeginLoc(),
20096 diag::err_omp_reduction_identifier_mismatch)
20097 << ReductionIdRange << RefExpr->getSourceRange();
20098 S.Diag(ParentSR.getBegin(),
20099 diag::note_omp_previous_reduction_identifier)
20100 << ParentSR
20101 << (IsParentBOK ? ParentBOKDSA.RefExpr
20102 : ParentReductionOpDSA.RefExpr)
20103 ->getSourceRange();
20104 continue;
20105 }
20106 }
20107 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20108 }
20109
20110 DeclRefExpr *Ref = nullptr;
20111 Expr *VarsExpr = RefExpr->IgnoreParens();
20112 if (!VD && !S.CurContext->isDependentContext()) {
20113 if (ASE || OASE) {
20114 TransformExprToCaptures RebuildToCapture(S, D);
20115 VarsExpr =
20116 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20117 Ref = RebuildToCapture.getCapturedExpr();
20118 } else {
20119 VarsExpr = Ref = buildCapture(S, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
20120 }
20121 if (!S.isOpenMPCapturedDecl(D)) {
20122 RD.ExprCaptures.emplace_back(Args: Ref->getDecl());
20123 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20124 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
20125 if (!RefRes.isUsable())
20126 continue;
20127 ExprResult PostUpdateRes =
20128 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: SimpleRefExpr,
20129 RHSExpr: RefRes.get());
20130 if (!PostUpdateRes.isUsable())
20131 continue;
20132 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
20133 Stack->getCurrentDirective() == OMPD_taskgroup) {
20134 S.Diag(RefExpr->getExprLoc(),
20135 diag::err_omp_reduction_non_addressable_expression)
20136 << RefExpr->getSourceRange();
20137 continue;
20138 }
20139 RD.ExprPostUpdates.emplace_back(
20140 Args: S.IgnoredValueConversions(E: PostUpdateRes.get()).get());
20141 }
20142 }
20143 }
20144 // All reduction items are still marked as reduction (to do not increase
20145 // code base size).
20146 unsigned Modifier = RD.RedModifier;
20147 // Consider task_reductions as reductions with task modifier. Required for
20148 // correct analysis of in_reduction clauses.
20149 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20150 Modifier = OMPC_REDUCTION_task;
20151 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20152 ASE || OASE);
20153 if (Modifier == OMPC_REDUCTION_task &&
20154 (CurrDir == OMPD_taskgroup ||
20155 ((isOpenMPParallelDirective(CurrDir) ||
20156 isOpenMPWorksharingDirective(CurrDir)) &&
20157 !isOpenMPSimdDirective(CurrDir)))) {
20158 if (DeclareReductionRef.isUsable())
20159 Stack->addTaskgroupReductionData(D, SR: ReductionIdRange,
20160 ReductionRef: DeclareReductionRef.get());
20161 else
20162 Stack->addTaskgroupReductionData(D, SR: ReductionIdRange, BOK);
20163 }
20164 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
20165 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
20166 TempArrayElem.get());
20167 }
20168 return RD.Vars.empty();
20169}
20170
20171OMPClause *Sema::ActOnOpenMPReductionClause(
20172 ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier,
20173 SourceLocation StartLoc, SourceLocation LParenLoc,
20174 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
20175 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20176 ArrayRef<Expr *> UnresolvedReductions) {
20177 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
20178 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20179 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
20180 /*Last=*/OMPC_REDUCTION_unknown)
20181 << getOpenMPClauseName(OMPC_reduction);
20182 return nullptr;
20183 }
20184 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20185 // A reduction clause with the inscan reduction-modifier may only appear on a
20186 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20187 // construct, a parallel worksharing-loop construct or a parallel
20188 // worksharing-loop SIMD construct.
20189 if (Modifier == OMPC_REDUCTION_inscan &&
20190 (DSAStack->getCurrentDirective() != OMPD_for &&
20191 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20192 DSAStack->getCurrentDirective() != OMPD_simd &&
20193 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20194 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20195 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20196 return nullptr;
20197 }
20198
20199 ReductionData RD(VarList.size(), Modifier);
20200 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
20201 StartLoc, LParenLoc, ColonLoc, EndLoc,
20202 ReductionIdScopeSpec, ReductionId,
20203 UnresolvedReductions, RD))
20204 return nullptr;
20205
20206 return OMPReductionClause::Create(
20207 C: Context, StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc, Modifier,
20208 VL: RD.Vars, QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context), NameInfo: ReductionId,
20209 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps, CopyOps: RD.InscanCopyOps,
20210 CopyArrayTemps: RD.InscanCopyArrayTemps, CopyArrayElems: RD.InscanCopyArrayElems,
20211 PreInit: buildPreInits(Context, PreInits: RD.ExprCaptures),
20212 PostUpdate: buildPostUpdate(S&: *this, PostUpdates: RD.ExprPostUpdates));
20213}
20214
20215OMPClause *Sema::ActOnOpenMPTaskReductionClause(
20216 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20217 SourceLocation ColonLoc, SourceLocation EndLoc,
20218 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20219 ArrayRef<Expr *> UnresolvedReductions) {
20220 ReductionData RD(VarList.size());
20221 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_task_reduction, VarList,
20222 StartLoc, LParenLoc, ColonLoc, EndLoc,
20223 ReductionIdScopeSpec, ReductionId,
20224 UnresolvedReductions, RD))
20225 return nullptr;
20226
20227 return OMPTaskReductionClause::Create(
20228 C: Context, StartLoc, LParenLoc, ColonLoc, EndLoc, VL: RD.Vars,
20229 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context), NameInfo: ReductionId,
20230 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps,
20231 PreInit: buildPreInits(Context, PreInits: RD.ExprCaptures),
20232 PostUpdate: buildPostUpdate(S&: *this, PostUpdates: RD.ExprPostUpdates));
20233}
20234
20235OMPClause *Sema::ActOnOpenMPInReductionClause(
20236 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20237 SourceLocation ColonLoc, SourceLocation EndLoc,
20238 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20239 ArrayRef<Expr *> UnresolvedReductions) {
20240 ReductionData RD(VarList.size());
20241 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
20242 StartLoc, LParenLoc, ColonLoc, EndLoc,
20243 ReductionIdScopeSpec, ReductionId,
20244 UnresolvedReductions, RD))
20245 return nullptr;
20246
20247 return OMPInReductionClause::Create(
20248 C: Context, StartLoc, LParenLoc, ColonLoc, EndLoc, VL: RD.Vars,
20249 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context), NameInfo: ReductionId,
20250 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps, TaskgroupDescriptors: RD.TaskgroupDescriptors,
20251 PreInit: buildPreInits(Context, PreInits: RD.ExprCaptures),
20252 PostUpdate: buildPostUpdate(S&: *this, PostUpdates: RD.ExprPostUpdates));
20253}
20254
20255bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
20256 SourceLocation LinLoc) {
20257 if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
20258 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
20259 Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus;
20260 return true;
20261 }
20262 return false;
20263}
20264
20265bool Sema::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
20266 OpenMPLinearClauseKind LinKind, QualType Type,
20267 bool IsDeclareSimd) {
20268 const auto *VD = dyn_cast_or_null<VarDecl>(Val: D);
20269 // A variable must not have an incomplete type or a reference type.
20270 if (RequireCompleteType(ELoc, Type, diag::err_omp_linear_incomplete_type))
20271 return true;
20272 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20273 !Type->isReferenceType()) {
20274 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20275 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
20276 return true;
20277 }
20278 Type = Type.getNonReferenceType();
20279
20280 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20281 // A variable that is privatized must not have a const-qualified type
20282 // unless it is of class type with a mutable member. This restriction does
20283 // not apply to the firstprivate clause, nor to the linear clause on
20284 // declarative directives (like declare simd).
20285 if (!IsDeclareSimd &&
20286 rejectConstNotMutableType(*this, D, Type, OMPC_linear, ELoc))
20287 return true;
20288
20289 // A list item must be of integral or pointer type.
20290 Type = Type.getUnqualifiedType().getCanonicalType();
20291 const auto *Ty = Type.getTypePtrOrNull();
20292 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20293 !Ty->isIntegralType(Ctx: Context) && !Ty->isPointerType())) {
20294 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
20295 if (D) {
20296 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20297 VarDecl::DeclarationOnly;
20298 Diag(D->getLocation(),
20299 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20300 << D;
20301 }
20302 return true;
20303 }
20304 return false;
20305}
20306
20307OMPClause *Sema::ActOnOpenMPLinearClause(
20308 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
20309 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
20310 SourceLocation LinLoc, SourceLocation ColonLoc,
20311 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
20312 SmallVector<Expr *, 8> Vars;
20313 SmallVector<Expr *, 8> Privates;
20314 SmallVector<Expr *, 8> Inits;
20315 SmallVector<Decl *, 4> ExprCaptures;
20316 SmallVector<Expr *, 4> ExprPostUpdates;
20317 // OpenMP 5.2 [Section 5.4.6, linear clause]
20318 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
20319 // 'ref'
20320 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
20321 getLangOpts().OpenMP >= 52)
20322 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
20323 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
20324 LinKind = OMPC_LINEAR_val;
20325 for (Expr *RefExpr : VarList) {
20326 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20327 SourceLocation ELoc;
20328 SourceRange ERange;
20329 Expr *SimpleRefExpr = RefExpr;
20330 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange);
20331 if (Res.second) {
20332 // It will be analyzed later.
20333 Vars.push_back(Elt: RefExpr);
20334 Privates.push_back(Elt: nullptr);
20335 Inits.push_back(Elt: nullptr);
20336 }
20337 ValueDecl *D = Res.first;
20338 if (!D)
20339 continue;
20340
20341 QualType Type = D->getType();
20342 auto *VD = dyn_cast<VarDecl>(Val: D);
20343
20344 // OpenMP [2.14.3.7, linear clause]
20345 // A list-item cannot appear in more than one linear clause.
20346 // A list-item that appears in a linear clause cannot appear in any
20347 // other data-sharing attribute clause.
20348 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20349 if (DVar.RefExpr) {
20350 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
20351 << getOpenMPClauseName(OMPC_linear);
20352 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
20353 continue;
20354 }
20355
20356 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
20357 continue;
20358 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20359
20360 // Build private copy of original var.
20361 VarDecl *Private =
20362 buildVarDecl(*this, ELoc, Type, D->getName(),
20363 D->hasAttrs() ? &D->getAttrs() : nullptr,
20364 VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
20365 DeclRefExpr *PrivateRef = buildDeclRefExpr(S&: *this, D: Private, Ty: Type, Loc: ELoc);
20366 // Build var to save initial value.
20367 VarDecl *Init = buildVarDecl(SemaRef&: *this, Loc: ELoc, Type, Name: ".linear.start");
20368 Expr *InitExpr;
20369 DeclRefExpr *Ref = nullptr;
20370 if (!VD && !CurContext->isDependentContext()) {
20371 Ref = buildCapture(S&: *this, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
20372 if (!isOpenMPCapturedDecl(D)) {
20373 ExprCaptures.push_back(Ref->getDecl());
20374 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20375 ExprResult RefRes = DefaultLvalueConversion(Ref);
20376 if (!RefRes.isUsable())
20377 continue;
20378 ExprResult PostUpdateRes =
20379 BuildBinOp(DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign,
20380 LHSExpr: SimpleRefExpr, RHSExpr: RefRes.get());
20381 if (!PostUpdateRes.isUsable())
20382 continue;
20383 ExprPostUpdates.push_back(
20384 Elt: IgnoredValueConversions(E: PostUpdateRes.get()).get());
20385 }
20386 }
20387 }
20388 if (LinKind == OMPC_LINEAR_uval)
20389 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
20390 else
20391 InitExpr = VD ? SimpleRefExpr : Ref;
20392 AddInitializerToDecl(Init, DefaultLvalueConversion(E: InitExpr).get(),
20393 /*DirectInit=*/false);
20394 DeclRefExpr *InitRef = buildDeclRefExpr(S&: *this, D: Init, Ty: Type, Loc: ELoc);
20395
20396 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20397 Vars.push_back(Elt: (VD || CurContext->isDependentContext())
20398 ? RefExpr->IgnoreParens()
20399 : Ref);
20400 Privates.push_back(PrivateRef);
20401 Inits.push_back(InitRef);
20402 }
20403
20404 if (Vars.empty())
20405 return nullptr;
20406
20407 Expr *StepExpr = Step;
20408 Expr *CalcStepExpr = nullptr;
20409 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
20410 !Step->isInstantiationDependent() &&
20411 !Step->containsUnexpandedParameterPack()) {
20412 SourceLocation StepLoc = Step->getBeginLoc();
20413 ExprResult Val = PerformOpenMPImplicitIntegerConversion(Loc: StepLoc, Op: Step);
20414 if (Val.isInvalid())
20415 return nullptr;
20416 StepExpr = Val.get();
20417
20418 // Build var to save the step value.
20419 VarDecl *SaveVar =
20420 buildVarDecl(SemaRef&: *this, Loc: StepLoc, Type: StepExpr->getType(), Name: ".linear.step");
20421 ExprResult SaveRef =
20422 buildDeclRefExpr(S&: *this, D: SaveVar, Ty: StepExpr->getType(), Loc: StepLoc);
20423 ExprResult CalcStep =
20424 BuildBinOp(S: CurScope, OpLoc: StepLoc, Opc: BO_Assign, LHSExpr: SaveRef.get(), RHSExpr: StepExpr);
20425 CalcStep = ActOnFinishFullExpr(Expr: CalcStep.get(), /*DiscardedValue*/ false);
20426
20427 // Warn about zero linear step (it would be probably better specified as
20428 // making corresponding variables 'const').
20429 if (std::optional<llvm::APSInt> Result =
20430 StepExpr->getIntegerConstantExpr(Ctx: Context)) {
20431 if (!Result->isNegative() && !Result->isStrictlyPositive())
20432 Diag(StepLoc, diag::warn_omp_linear_step_zero)
20433 << Vars[0] << (Vars.size() > 1);
20434 } else if (CalcStep.isUsable()) {
20435 // Calculate the step beforehand instead of doing this on each iteration.
20436 // (This is not used if the number of iterations may be kfold-ed).
20437 CalcStepExpr = CalcStep.get();
20438 }
20439 }
20440
20441 return OMPLinearClause::Create(C: Context, StartLoc, LParenLoc, Modifier: LinKind, ModifierLoc: LinLoc,
20442 ColonLoc, StepModifierLoc, EndLoc, VL: Vars,
20443 PL: Privates, IL: Inits, Step: StepExpr, CalcStep: CalcStepExpr,
20444 PreInit: buildPreInits(Context, PreInits: ExprCaptures),
20445 PostUpdate: buildPostUpdate(S&: *this, PostUpdates: ExprPostUpdates));
20446}
20447
20448static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
20449 Expr *NumIterations, Sema &SemaRef,
20450 Scope *S, DSAStackTy *Stack) {
20451 // Walk the vars and build update/final expressions for the CodeGen.
20452 SmallVector<Expr *, 8> Updates;
20453 SmallVector<Expr *, 8> Finals;
20454 SmallVector<Expr *, 8> UsedExprs;
20455 Expr *Step = Clause.getStep();
20456 Expr *CalcStep = Clause.getCalcStep();
20457 // OpenMP [2.14.3.7, linear clause]
20458 // If linear-step is not specified it is assumed to be 1.
20459 if (!Step)
20460 Step = SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get();
20461 else if (CalcStep)
20462 Step = cast<BinaryOperator>(Val: CalcStep)->getLHS();
20463 bool HasErrors = false;
20464 auto CurInit = Clause.inits().begin();
20465 auto CurPrivate = Clause.privates().begin();
20466 OpenMPLinearClauseKind LinKind = Clause.getModifier();
20467 for (Expr *RefExpr : Clause.varlists()) {
20468 SourceLocation ELoc;
20469 SourceRange ERange;
20470 Expr *SimpleRefExpr = RefExpr;
20471 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
20472 ValueDecl *D = Res.first;
20473 if (Res.second || !D) {
20474 Updates.push_back(Elt: nullptr);
20475 Finals.push_back(Elt: nullptr);
20476 HasErrors = true;
20477 continue;
20478 }
20479 auto &&Info = Stack->isLoopControlVariable(D);
20480 // OpenMP [2.15.11, distribute simd Construct]
20481 // A list item may not appear in a linear clause, unless it is the loop
20482 // iteration variable.
20483 if (isOpenMPDistributeDirective(DKind: Stack->getCurrentDirective()) &&
20484 isOpenMPSimdDirective(DKind: Stack->getCurrentDirective()) && !Info.first) {
20485 SemaRef.Diag(ELoc,
20486 diag::err_omp_linear_distribute_var_non_loop_iteration);
20487 Updates.push_back(Elt: nullptr);
20488 Finals.push_back(Elt: nullptr);
20489 HasErrors = true;
20490 continue;
20491 }
20492 Expr *InitExpr = *CurInit;
20493
20494 // Build privatized reference to the current linear var.
20495 auto *DE = cast<DeclRefExpr>(Val: SimpleRefExpr);
20496 Expr *CapturedRef;
20497 if (LinKind == OMPC_LINEAR_uval)
20498 CapturedRef = cast<VarDecl>(Val: DE->getDecl())->getInit();
20499 else
20500 CapturedRef =
20501 buildDeclRefExpr(SemaRef, cast<VarDecl>(Val: DE->getDecl()),
20502 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
20503 /*RefersToCapture=*/true);
20504
20505 // Build update: Var = InitExpr + IV * Step
20506 ExprResult Update;
20507 if (!Info.first)
20508 Update = buildCounterUpdate(
20509 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
20510 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
20511 else
20512 Update = *CurPrivate;
20513 Update = SemaRef.ActOnFinishFullExpr(Expr: Update.get(), CC: DE->getBeginLoc(),
20514 /*DiscardedValue*/ false);
20515
20516 // Build final: Var = PrivCopy;
20517 ExprResult Final;
20518 if (!Info.first)
20519 Final = SemaRef.BuildBinOp(
20520 S, OpLoc: RefExpr->getExprLoc(), Opc: BO_Assign, LHSExpr: CapturedRef,
20521 RHSExpr: SemaRef.DefaultLvalueConversion(E: *CurPrivate).get());
20522 else
20523 Final = *CurPrivate;
20524 Final = SemaRef.ActOnFinishFullExpr(Expr: Final.get(), CC: DE->getBeginLoc(),
20525 /*DiscardedValue*/ false);
20526
20527 if (!Update.isUsable() || !Final.isUsable()) {
20528 Updates.push_back(Elt: nullptr);
20529 Finals.push_back(Elt: nullptr);
20530 UsedExprs.push_back(Elt: nullptr);
20531 HasErrors = true;
20532 } else {
20533 Updates.push_back(Elt: Update.get());
20534 Finals.push_back(Elt: Final.get());
20535 if (!Info.first)
20536 UsedExprs.push_back(Elt: SimpleRefExpr);
20537 }
20538 ++CurInit;
20539 ++CurPrivate;
20540 }
20541 if (Expr *S = Clause.getStep())
20542 UsedExprs.push_back(Elt: S);
20543 // Fill the remaining part with the nullptr.
20544 UsedExprs.append(NumInputs: Clause.varlist_size() + 1 - UsedExprs.size(), Elt: nullptr);
20545 Clause.setUpdates(Updates);
20546 Clause.setFinals(Finals);
20547 Clause.setUsedExprs(UsedExprs);
20548 return HasErrors;
20549}
20550
20551OMPClause *Sema::ActOnOpenMPAlignedClause(
20552 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
20553 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
20554 SmallVector<Expr *, 8> Vars;
20555 for (Expr *RefExpr : VarList) {
20556 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20557 SourceLocation ELoc;
20558 SourceRange ERange;
20559 Expr *SimpleRefExpr = RefExpr;
20560 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange);
20561 if (Res.second) {
20562 // It will be analyzed later.
20563 Vars.push_back(Elt: RefExpr);
20564 }
20565 ValueDecl *D = Res.first;
20566 if (!D)
20567 continue;
20568
20569 QualType QType = D->getType();
20570 auto *VD = dyn_cast<VarDecl>(Val: D);
20571
20572 // OpenMP [2.8.1, simd construct, Restrictions]
20573 // The type of list items appearing in the aligned clause must be
20574 // array, pointer, reference to array, or reference to pointer.
20575 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20576 const Type *Ty = QType.getTypePtrOrNull();
20577 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
20578 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
20579 << QType << getLangOpts().CPlusPlus << ERange;
20580 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20581 VarDecl::DeclarationOnly;
20582 Diag(D->getLocation(),
20583 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20584 << D;
20585 continue;
20586 }
20587
20588 // OpenMP [2.8.1, simd construct, Restrictions]
20589 // A list-item cannot appear in more than one aligned clause.
20590 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, NewDE: SimpleRefExpr)) {
20591 Diag(ELoc, diag::err_omp_used_in_clause_twice)
20592 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
20593 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20594 << getOpenMPClauseName(OMPC_aligned);
20595 continue;
20596 }
20597
20598 DeclRefExpr *Ref = nullptr;
20599 if (!VD && isOpenMPCapturedDecl(D))
20600 Ref = buildCapture(S&: *this, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
20601 Vars.push_back(Elt: DefaultFunctionArrayConversion(
20602 E: (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20603 .get());
20604 }
20605
20606 // OpenMP [2.8.1, simd construct, Description]
20607 // The parameter of the aligned clause, alignment, must be a constant
20608 // positive integer expression.
20609 // If no optional parameter is specified, implementation-defined default
20610 // alignments for SIMD instructions on the target platforms are assumed.
20611 if (Alignment != nullptr) {
20612 ExprResult AlignResult =
20613 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
20614 if (AlignResult.isInvalid())
20615 return nullptr;
20616 Alignment = AlignResult.get();
20617 }
20618 if (Vars.empty())
20619 return nullptr;
20620
20621 return OMPAlignedClause::Create(C: Context, StartLoc, LParenLoc, ColonLoc,
20622 EndLoc, VL: Vars, A: Alignment);
20623}
20624
20625OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
20626 SourceLocation StartLoc,
20627 SourceLocation LParenLoc,
20628 SourceLocation EndLoc) {
20629 SmallVector<Expr *, 8> Vars;
20630 SmallVector<Expr *, 8> SrcExprs;
20631 SmallVector<Expr *, 8> DstExprs;
20632 SmallVector<Expr *, 8> AssignmentOps;
20633 for (Expr *RefExpr : VarList) {
20634 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
20635 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
20636 // It will be analyzed later.
20637 Vars.push_back(Elt: RefExpr);
20638 SrcExprs.push_back(Elt: nullptr);
20639 DstExprs.push_back(Elt: nullptr);
20640 AssignmentOps.push_back(Elt: nullptr);
20641 continue;
20642 }
20643
20644 SourceLocation ELoc = RefExpr->getExprLoc();
20645 // OpenMP [2.1, C/C++]
20646 // A list item is a variable name.
20647 // OpenMP [2.14.4.1, Restrictions, p.1]
20648 // A list item that appears in a copyin clause must be threadprivate.
20649 auto *DE = dyn_cast<DeclRefExpr>(Val: RefExpr);
20650 if (!DE || !isa<VarDecl>(Val: DE->getDecl())) {
20651 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20652 << 0 << RefExpr->getSourceRange();
20653 continue;
20654 }
20655
20656 Decl *D = DE->getDecl();
20657 auto *VD = cast<VarDecl>(Val: D);
20658
20659 QualType Type = VD->getType();
20660 if (Type->isDependentType() || Type->isInstantiationDependentType()) {
20661 // It will be analyzed later.
20662 Vars.push_back(DE);
20663 SrcExprs.push_back(Elt: nullptr);
20664 DstExprs.push_back(Elt: nullptr);
20665 AssignmentOps.push_back(Elt: nullptr);
20666 continue;
20667 }
20668
20669 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20670 // A list item that appears in a copyin clause must be threadprivate.
20671 if (!DSAStack->isThreadPrivate(D: VD)) {
20672 Diag(ELoc, diag::err_omp_required_access)
20673 << getOpenMPClauseName(OMPC_copyin)
20674 << getOpenMPDirectiveName(OMPD_threadprivate);
20675 continue;
20676 }
20677
20678 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20679 // A variable of class type (or array thereof) that appears in a
20680 // copyin clause requires an accessible, unambiguous copy assignment
20681 // operator for the class type.
20682 QualType ElemType = Context.getBaseElementType(QT: Type).getNonReferenceType();
20683 VarDecl *SrcVD =
20684 buildVarDecl(*this, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20685 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20686 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20687 *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20688 VarDecl *DstVD =
20689 buildVarDecl(*this, DE->getBeginLoc(), ElemType, ".copyin.dst",
20690 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20691 DeclRefExpr *PseudoDstExpr =
20692 buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
20693 // For arrays generate assignment operation for single element and replace
20694 // it by the original array element in CodeGen.
20695 ExprResult AssignmentOp =
20696 BuildBinOp(/*S=*/nullptr, OpLoc: DE->getExprLoc(), Opc: BO_Assign, LHSExpr: PseudoDstExpr,
20697 RHSExpr: PseudoSrcExpr);
20698 if (AssignmentOp.isInvalid())
20699 continue;
20700 AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20701 /*DiscardedValue*/ false);
20702 if (AssignmentOp.isInvalid())
20703 continue;
20704
20705 DSAStack->addDSA(VD, DE, OMPC_copyin);
20706 Vars.push_back(DE);
20707 SrcExprs.push_back(PseudoSrcExpr);
20708 DstExprs.push_back(PseudoDstExpr);
20709 AssignmentOps.push_back(Elt: AssignmentOp.get());
20710 }
20711
20712 if (Vars.empty())
20713 return nullptr;
20714
20715 return OMPCopyinClause::Create(C: Context, StartLoc, LParenLoc, EndLoc, VL: Vars,
20716 SrcExprs, DstExprs, AssignmentOps);
20717}
20718
20719OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
20720 SourceLocation StartLoc,
20721 SourceLocation LParenLoc,
20722 SourceLocation EndLoc) {
20723 SmallVector<Expr *, 8> Vars;
20724 SmallVector<Expr *, 8> SrcExprs;
20725 SmallVector<Expr *, 8> DstExprs;
20726 SmallVector<Expr *, 8> AssignmentOps;
20727 for (Expr *RefExpr : VarList) {
20728 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20729 SourceLocation ELoc;
20730 SourceRange ERange;
20731 Expr *SimpleRefExpr = RefExpr;
20732 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange);
20733 if (Res.second) {
20734 // It will be analyzed later.
20735 Vars.push_back(Elt: RefExpr);
20736 SrcExprs.push_back(Elt: nullptr);
20737 DstExprs.push_back(Elt: nullptr);
20738 AssignmentOps.push_back(Elt: nullptr);
20739 }
20740 ValueDecl *D = Res.first;
20741 if (!D)
20742 continue;
20743
20744 QualType Type = D->getType();
20745 auto *VD = dyn_cast<VarDecl>(Val: D);
20746
20747 // OpenMP [2.14.4.2, Restrictions, p.2]
20748 // A list item that appears in a copyprivate clause may not appear in a
20749 // private or firstprivate clause on the single construct.
20750 if (!VD || !DSAStack->isThreadPrivate(D: VD)) {
20751 DSAStackTy::DSAVarData DVar =
20752 DSAStack->getTopDSA(D, /*FromParent=*/false);
20753 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20754 DVar.RefExpr) {
20755 Diag(ELoc, diag::err_omp_wrong_dsa)
20756 << getOpenMPClauseName(DVar.CKind)
20757 << getOpenMPClauseName(OMPC_copyprivate);
20758 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
20759 continue;
20760 }
20761
20762 // OpenMP [2.11.4.2, Restrictions, p.1]
20763 // All list items that appear in a copyprivate clause must be either
20764 // threadprivate or private in the enclosing context.
20765 if (DVar.CKind == OMPC_unknown) {
20766 DVar = DSAStack->getImplicitDSA(D, FromParent: false);
20767 if (DVar.CKind == OMPC_shared) {
20768 Diag(ELoc, diag::err_omp_required_access)
20769 << getOpenMPClauseName(OMPC_copyprivate)
20770 << "threadprivate or private in the enclosing context";
20771 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
20772 continue;
20773 }
20774 }
20775 }
20776
20777 // Variably modified types are not supported.
20778 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
20779 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20780 << getOpenMPClauseName(OMPC_copyprivate) << Type
20781 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
20782 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20783 VarDecl::DeclarationOnly;
20784 Diag(D->getLocation(),
20785 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20786 << D;
20787 continue;
20788 }
20789
20790 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20791 // A variable of class type (or array thereof) that appears in a
20792 // copyin clause requires an accessible, unambiguous copy assignment
20793 // operator for the class type.
20794 Type = Context.getBaseElementType(QT: Type.getNonReferenceType())
20795 .getUnqualifiedType();
20796 VarDecl *SrcVD =
20797 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
20798 D->hasAttrs() ? &D->getAttrs() : nullptr);
20799 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(S&: *this, D: SrcVD, Ty: Type, Loc: ELoc);
20800 VarDecl *DstVD =
20801 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
20802 D->hasAttrs() ? &D->getAttrs() : nullptr);
20803 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(S&: *this, D: DstVD, Ty: Type, Loc: ELoc);
20804 ExprResult AssignmentOp = BuildBinOp(
20805 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20806 if (AssignmentOp.isInvalid())
20807 continue;
20808 AssignmentOp =
20809 ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: ELoc, /*DiscardedValue*/ false);
20810 if (AssignmentOp.isInvalid())
20811 continue;
20812
20813 // No need to mark vars as copyprivate, they are already threadprivate or
20814 // implicitly private.
20815 assert(VD || isOpenMPCapturedDecl(D));
20816 Vars.push_back(
20817 Elt: VD ? RefExpr->IgnoreParens()
20818 : buildCapture(S&: *this, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false));
20819 SrcExprs.push_back(PseudoSrcExpr);
20820 DstExprs.push_back(PseudoDstExpr);
20821 AssignmentOps.push_back(Elt: AssignmentOp.get());
20822 }
20823
20824 if (Vars.empty())
20825 return nullptr;
20826
20827 return OMPCopyprivateClause::Create(C: Context, StartLoc, LParenLoc, EndLoc,
20828 VL: Vars, SrcExprs, DstExprs, AssignmentOps);
20829}
20830
20831OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
20832 SourceLocation StartLoc,
20833 SourceLocation LParenLoc,
20834 SourceLocation EndLoc) {
20835 if (VarList.empty())
20836 return nullptr;
20837
20838 return OMPFlushClause::Create(C: Context, StartLoc, LParenLoc, EndLoc, VL: VarList);
20839}
20840
20841/// Tries to find omp_depend_t. type.
20842static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
20843 bool Diagnose = true) {
20844 QualType OMPDependT = Stack->getOMPDependT();
20845 if (!OMPDependT.isNull())
20846 return true;
20847 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_depend_t");
20848 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
20849 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
20850 if (Diagnose)
20851 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
20852 return false;
20853 }
20854 Stack->setOMPDependT(PT.get());
20855 return true;
20856}
20857
20858OMPClause *Sema::ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc,
20859 SourceLocation LParenLoc,
20860 SourceLocation EndLoc) {
20861 if (!Depobj)
20862 return nullptr;
20863
20864 bool OMPDependTFound = findOMPDependT(S&: *this, Loc: StartLoc, DSAStack);
20865
20866 // OpenMP 5.0, 2.17.10.1 depobj Construct
20867 // depobj is an lvalue expression of type omp_depend_t.
20868 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
20869 !Depobj->isInstantiationDependent() &&
20870 !Depobj->containsUnexpandedParameterPack() &&
20871 (OMPDependTFound &&
20872 !Context.typesAreCompatible(DSAStack->getOMPDependT(), T2: Depobj->getType(),
20873 /*CompareUnqualified=*/true))) {
20874 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20875 << 0 << Depobj->getType() << Depobj->getSourceRange();
20876 }
20877
20878 if (!Depobj->isLValue()) {
20879 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20880 << 1 << Depobj->getSourceRange();
20881 }
20882
20883 return OMPDepobjClause::Create(C: Context, StartLoc, LParenLoc, EndLoc, Depobj);
20884}
20885
20886namespace {
20887// Utility struct that gathers the related info for doacross clause.
20888struct DoacrossDataInfoTy {
20889 // The list of expressions.
20890 SmallVector<Expr *, 8> Vars;
20891 // The OperatorOffset for doacross loop.
20892 DSAStackTy::OperatorOffsetTy OpsOffs;
20893 // The depended loop count.
20894 llvm::APSInt TotalDepCount;
20895};
20896} // namespace
20897static DoacrossDataInfoTy
20898ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource,
20899 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
20900 SourceLocation EndLoc) {
20901
20902 SmallVector<Expr *, 8> Vars;
20903 DSAStackTy::OperatorOffsetTy OpsOffs;
20904 llvm::APSInt DepCounter(/*BitWidth=*/32);
20905 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20906
20907 if (const Expr *OrderedCountExpr =
20908 Stack->getParentOrderedRegionParam().first) {
20909 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Ctx: SemaRef.Context);
20910 TotalDepCount.setIsUnsigned(/*Val=*/true);
20911 }
20912
20913 for (Expr *RefExpr : VarList) {
20914 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
20915 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
20916 // It will be analyzed later.
20917 Vars.push_back(Elt: RefExpr);
20918 continue;
20919 }
20920
20921 SourceLocation ELoc = RefExpr->getExprLoc();
20922 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20923 if (!IsSource) {
20924 if (Stack->getParentOrderedRegionParam().first &&
20925 DepCounter >= TotalDepCount) {
20926 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20927 continue;
20928 }
20929 ++DepCounter;
20930 // OpenMP [2.13.9, Summary]
20931 // depend(dependence-type : vec), where dependence-type is:
20932 // 'sink' and where vec is the iteration vector, which has the form:
20933 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20934 // where n is the value specified by the ordered clause in the loop
20935 // directive, xi denotes the loop iteration variable of the i-th nested
20936 // loop associated with the loop directive, and di is a constant
20937 // non-negative integer.
20938 if (SemaRef.CurContext->isDependentContext()) {
20939 // It will be analyzed later.
20940 Vars.push_back(Elt: RefExpr);
20941 continue;
20942 }
20943 SimpleExpr = SimpleExpr->IgnoreImplicit();
20944 OverloadedOperatorKind OOK = OO_None;
20945 SourceLocation OOLoc;
20946 Expr *LHS = SimpleExpr;
20947 Expr *RHS = nullptr;
20948 if (auto *BO = dyn_cast<BinaryOperator>(Val: SimpleExpr)) {
20949 OOK = BinaryOperator::getOverloadedOperator(Opc: BO->getOpcode());
20950 OOLoc = BO->getOperatorLoc();
20951 LHS = BO->getLHS()->IgnoreParenImpCasts();
20952 RHS = BO->getRHS()->IgnoreParenImpCasts();
20953 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Val: SimpleExpr)) {
20954 OOK = OCE->getOperator();
20955 OOLoc = OCE->getOperatorLoc();
20956 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20957 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20958 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Val: SimpleExpr)) {
20959 OOK = MCE->getMethodDecl()
20960 ->getNameInfo()
20961 .getName()
20962 .getCXXOverloadedOperator();
20963 OOLoc = MCE->getCallee()->getExprLoc();
20964 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
20965 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20966 }
20967 SourceLocation ELoc;
20968 SourceRange ERange;
20969 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: LHS, ELoc, ERange);
20970 if (Res.second) {
20971 // It will be analyzed later.
20972 Vars.push_back(Elt: RefExpr);
20973 }
20974 ValueDecl *D = Res.first;
20975 if (!D)
20976 continue;
20977
20978 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
20979 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20980 continue;
20981 }
20982 if (RHS) {
20983 ExprResult RHSRes = SemaRef.VerifyPositiveIntegerConstantInClause(
20984 RHS, OMPC_depend, /*StrictlyPositive=*/false);
20985 if (RHSRes.isInvalid())
20986 continue;
20987 }
20988 if (!SemaRef.CurContext->isDependentContext() &&
20989 Stack->getParentOrderedRegionParam().first &&
20990 DepCounter != Stack->isParentLoopControlVariable(D).first) {
20991 const ValueDecl *VD =
20992 Stack->getParentLoopControlVariable(I: DepCounter.getZExtValue());
20993 if (VD)
20994 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20995 << 1 << VD;
20996 else
20997 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20998 << 0;
20999 continue;
21000 }
21001 OpsOffs.emplace_back(Args&: RHS, Args&: OOK);
21002 }
21003 Vars.push_back(Elt: RefExpr->IgnoreParenImpCasts());
21004 }
21005 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
21006 TotalDepCount > VarList.size() &&
21007 Stack->getParentOrderedRegionParam().first &&
21008 Stack->getParentLoopControlVariable(I: VarList.size() + 1)) {
21009 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
21010 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
21011 }
21012 return {.Vars: Vars, .OpsOffs: OpsOffs, .TotalDepCount: TotalDepCount};
21013}
21014
21015OMPClause *
21016Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
21017 Expr *DepModifier, ArrayRef<Expr *> VarList,
21018 SourceLocation StartLoc, SourceLocation LParenLoc,
21019 SourceLocation EndLoc) {
21020 OpenMPDependClauseKind DepKind = Data.DepKind;
21021 SourceLocation DepLoc = Data.DepLoc;
21022 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
21023 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
21024 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21025 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
21026 return nullptr;
21027 }
21028 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
21029 DepKind == OMPC_DEPEND_mutexinoutset) {
21030 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
21031 return nullptr;
21032 }
21033 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
21034 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21035 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
21036 DepKind == OMPC_DEPEND_sink ||
21037 ((LangOpts.OpenMP < 50 ||
21038 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21039 DepKind == OMPC_DEPEND_depobj))) {
21040 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
21041 OMPC_DEPEND_outallmemory,
21042 OMPC_DEPEND_inoutallmemory};
21043 if (LangOpts.OpenMP < 50 || DSAStack->getCurrentDirective() == OMPD_depobj)
21044 Except.push_back(Elt: OMPC_DEPEND_depobj);
21045 if (LangOpts.OpenMP < 51)
21046 Except.push_back(Elt: OMPC_DEPEND_inoutset);
21047 std::string Expected = (LangOpts.OpenMP >= 50 && !DepModifier)
21048 ? "depend modifier(iterator) or "
21049 : "";
21050 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21051 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
21052 /*Last=*/OMPC_DEPEND_unknown,
21053 Except)
21054 << getOpenMPClauseName(OMPC_depend);
21055 return nullptr;
21056 }
21057 if (DepModifier &&
21058 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21059 Diag(DepModifier->getExprLoc(),
21060 diag::err_omp_depend_sink_source_with_modifier);
21061 return nullptr;
21062 }
21063 if (DepModifier &&
21064 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
21065 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21066
21067 SmallVector<Expr *, 8> Vars;
21068 DSAStackTy::OperatorOffsetTy OpsOffs;
21069 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21070
21071 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21072 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
21073 SemaRef&: *this, IsSource: DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
21074 Vars = VarOffset.Vars;
21075 OpsOffs = VarOffset.OpsOffs;
21076 TotalDepCount = VarOffset.TotalDepCount;
21077 } else {
21078 for (Expr *RefExpr : VarList) {
21079 assert(RefExpr && "NULL expr in OpenMP shared clause.");
21080 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
21081 // It will be analyzed later.
21082 Vars.push_back(Elt: RefExpr);
21083 continue;
21084 }
21085
21086 SourceLocation ELoc = RefExpr->getExprLoc();
21087 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21088 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21089 bool OMPDependTFound = LangOpts.OpenMP >= 50;
21090 if (OMPDependTFound)
21091 OMPDependTFound = findOMPDependT(S&: *this, Loc: StartLoc, DSAStack,
21092 Diagnose: DepKind == OMPC_DEPEND_depobj);
21093 if (DepKind == OMPC_DEPEND_depobj) {
21094 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21095 // List items used in depend clauses with the depobj dependence type
21096 // must be expressions of the omp_depend_t type.
21097 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21098 !RefExpr->isInstantiationDependent() &&
21099 !RefExpr->containsUnexpandedParameterPack() &&
21100 (OMPDependTFound &&
21101 !Context.hasSameUnqualifiedType(DSAStack->getOMPDependT(),
21102 T2: RefExpr->getType()))) {
21103 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21104 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21105 continue;
21106 }
21107 if (!RefExpr->isLValue()) {
21108 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21109 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21110 continue;
21111 }
21112 } else {
21113 // OpenMP 5.0 [2.17.11, Restrictions]
21114 // List items used in depend clauses cannot be zero-length array
21115 // sections.
21116 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21117 const auto *OASE = dyn_cast<OMPArraySectionExpr>(Val: SimpleExpr);
21118 if (OASE) {
21119 QualType BaseType =
21120 OMPArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
21121 if (BaseType.isNull())
21122 return nullptr;
21123 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21124 ExprTy = ATy->getElementType();
21125 else
21126 ExprTy = BaseType->getPointeeType();
21127 if (BaseType.isNull() || ExprTy.isNull())
21128 return nullptr;
21129 ExprTy = ExprTy.getNonReferenceType();
21130 const Expr *Length = OASE->getLength();
21131 Expr::EvalResult Result;
21132 if (Length && !Length->isValueDependent() &&
21133 Length->EvaluateAsInt(Result, Ctx: Context) &&
21134 Result.Val.getInt().isZero()) {
21135 Diag(ELoc,
21136 diag::err_omp_depend_zero_length_array_section_not_allowed)
21137 << SimpleExpr->getSourceRange();
21138 continue;
21139 }
21140 }
21141
21142 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21143 // List items used in depend clauses with the in, out, inout,
21144 // inoutset, or mutexinoutset dependence types cannot be
21145 // expressions of the omp_depend_t type.
21146 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21147 !RefExpr->isInstantiationDependent() &&
21148 !RefExpr->containsUnexpandedParameterPack() &&
21149 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21150 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
21151 ExprTy.getTypePtr()))) {
21152 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21153 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21154 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21155 continue;
21156 }
21157
21158 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: SimpleExpr);
21159 if (ASE && !ASE->getBase()->isTypeDependent() &&
21160 !ASE->getBase()
21161 ->getType()
21162 .getNonReferenceType()
21163 ->isPointerType() &&
21164 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21165 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21166 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21167 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21168 continue;
21169 }
21170
21171 ExprResult Res;
21172 {
21173 Sema::TentativeAnalysisScope Trap(*this);
21174 Res = CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf,
21175 InputExpr: RefExpr->IgnoreParenImpCasts());
21176 }
21177 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(Val: SimpleExpr) &&
21178 !isa<OMPArrayShapingExpr>(Val: SimpleExpr)) {
21179 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21180 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21181 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21182 continue;
21183 }
21184 }
21185 }
21186 Vars.push_back(Elt: RefExpr->IgnoreParenImpCasts());
21187 }
21188 }
21189
21190 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21191 DepKind != OMPC_DEPEND_outallmemory &&
21192 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21193 return nullptr;
21194
21195 auto *C = OMPDependClause::Create(
21196 C: Context, StartLoc, LParenLoc, EndLoc,
21197 Data: {.DepKind: DepKind, .DepLoc: DepLoc, .ColonLoc: Data.ColonLoc, .OmpAllMemoryLoc: Data.OmpAllMemoryLoc}, DepModifier, VL: Vars,
21198 NumLoops: TotalDepCount.getZExtValue());
21199 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21200 DSAStack->isParentOrderedRegion())
21201 DSAStack->addDoacrossDependClause(C, OpsOffs);
21202 return C;
21203}
21204
21205OMPClause *Sema::ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,
21206 Expr *Device, SourceLocation StartLoc,
21207 SourceLocation LParenLoc,
21208 SourceLocation ModifierLoc,
21209 SourceLocation EndLoc) {
21210 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 50) &&
21211 "Unexpected device modifier in OpenMP < 50.");
21212
21213 bool ErrorFound = false;
21214 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
21215 std::string Values =
21216 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
21217 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21218 << Values << getOpenMPClauseName(OMPC_device);
21219 ErrorFound = true;
21220 }
21221
21222 Expr *ValExpr = Device;
21223 Stmt *HelperValStmt = nullptr;
21224
21225 // OpenMP [2.9.1, Restrictions]
21226 // The device expression must evaluate to a non-negative integer value.
21227 ErrorFound = !isNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
21228 /*StrictlyPositive=*/false) ||
21229 ErrorFound;
21230 if (ErrorFound)
21231 return nullptr;
21232
21233 // OpenMP 5.0 [2.12.5, Restrictions]
21234 // In case of ancestor device-modifier, a requires directive with
21235 // the reverse_offload clause must be specified.
21236 if (Modifier == OMPC_DEVICE_ancestor) {
21237 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
21238 targetDiag(
21239 StartLoc,
21240 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21241 ErrorFound = true;
21242 }
21243 }
21244
21245 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21246 OpenMPDirectiveKind CaptureRegion =
21247 getOpenMPCaptureRegionForClause(DKind, OMPC_device, LangOpts.OpenMP);
21248 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
21249 ValExpr = MakeFullExpr(Arg: ValExpr).get();
21250 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21251 ValExpr = tryBuildCapture(SemaRef&: *this, Capture: ValExpr, Captures).get();
21252 HelperValStmt = buildPreInits(Context, Captures);
21253 }
21254
21255 return new (Context)
21256 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21257 LParenLoc, ModifierLoc, EndLoc);
21258}
21259
21260static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
21261 DSAStackTy *Stack, QualType QTy,
21262 bool FullCheck = true) {
21263 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
21264 return false;
21265 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
21266 !QTy.isTriviallyCopyableType(SemaRef.Context))
21267 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21268 return true;
21269}
21270
21271/// Return true if it can be proven that the provided array expression
21272/// (array section or array subscript) does NOT specify the whole size of the
21273/// array whose base type is \a BaseQTy.
21274static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
21275 const Expr *E,
21276 QualType BaseQTy) {
21277 const auto *OASE = dyn_cast<OMPArraySectionExpr>(Val: E);
21278
21279 // If this is an array subscript, it refers to the whole size if the size of
21280 // the dimension is constant and equals 1. Also, an array section assumes the
21281 // format of an array subscript if no colon is used.
21282 if (isa<ArraySubscriptExpr>(Val: E) ||
21283 (OASE && OASE->getColonLocFirst().isInvalid())) {
21284 if (const auto *ATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr()))
21285 return ATy->getSize().getSExtValue() != 1;
21286 // Size can't be evaluated statically.
21287 return false;
21288 }
21289
21290 assert(OASE && "Expecting array section if not an array subscript.");
21291 const Expr *LowerBound = OASE->getLowerBound();
21292 const Expr *Length = OASE->getLength();
21293
21294 // If there is a lower bound that does not evaluates to zero, we are not
21295 // covering the whole dimension.
21296 if (LowerBound) {
21297 Expr::EvalResult Result;
21298 if (!LowerBound->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
21299 return false; // Can't get the integer value as a constant.
21300
21301 llvm::APSInt ConstLowerBound = Result.Val.getInt();
21302 if (ConstLowerBound.getSExtValue())
21303 return true;
21304 }
21305
21306 // If we don't have a length we covering the whole dimension.
21307 if (!Length)
21308 return false;
21309
21310 // If the base is a pointer, we don't have a way to get the size of the
21311 // pointee.
21312 if (BaseQTy->isPointerType())
21313 return false;
21314
21315 // We can only check if the length is the same as the size of the dimension
21316 // if we have a constant array.
21317 const auto *CATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr());
21318 if (!CATy)
21319 return false;
21320
21321 Expr::EvalResult Result;
21322 if (!Length->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
21323 return false; // Can't get the integer value as a constant.
21324
21325 llvm::APSInt ConstLength = Result.Val.getInt();
21326 return CATy->getSize().getSExtValue() != ConstLength.getSExtValue();
21327}
21328
21329// Return true if it can be proven that the provided array expression (array
21330// section or array subscript) does NOT specify a single element of the array
21331// whose base type is \a BaseQTy.
21332static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
21333 const Expr *E,
21334 QualType BaseQTy) {
21335 const auto *OASE = dyn_cast<OMPArraySectionExpr>(Val: E);
21336
21337 // An array subscript always refer to a single element. Also, an array section
21338 // assumes the format of an array subscript if no colon is used.
21339 if (isa<ArraySubscriptExpr>(Val: E) ||
21340 (OASE && OASE->getColonLocFirst().isInvalid()))
21341 return false;
21342
21343 assert(OASE && "Expecting array section if not an array subscript.");
21344 const Expr *Length = OASE->getLength();
21345
21346 // If we don't have a length we have to check if the array has unitary size
21347 // for this dimension. Also, we should always expect a length if the base type
21348 // is pointer.
21349 if (!Length) {
21350 if (const auto *ATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr()))
21351 return ATy->getSize().getSExtValue() != 1;
21352 // We cannot assume anything.
21353 return false;
21354 }
21355
21356 // Check if the length evaluates to 1.
21357 Expr::EvalResult Result;
21358 if (!Length->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
21359 return false; // Can't get the integer value as a constant.
21360
21361 llvm::APSInt ConstLength = Result.Val.getInt();
21362 return ConstLength.getSExtValue() != 1;
21363}
21364
21365// The base of elements of list in a map clause have to be either:
21366// - a reference to variable or field.
21367// - a member expression.
21368// - an array expression.
21369//
21370// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
21371// reference to 'r'.
21372//
21373// If we have:
21374//
21375// struct SS {
21376// Bla S;
21377// foo() {
21378// #pragma omp target map (S.Arr[:12]);
21379// }
21380// }
21381//
21382// We want to retrieve the member expression 'this->S';
21383
21384// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
21385// If a list item is an array section, it must specify contiguous storage.
21386//
21387// For this restriction it is sufficient that we make sure only references
21388// to variables or fields and array expressions, and that no array sections
21389// exist except in the rightmost expression (unless they cover the whole
21390// dimension of the array). E.g. these would be invalid:
21391//
21392// r.ArrS[3:5].Arr[6:7]
21393//
21394// r.ArrS[3:5].x
21395//
21396// but these would be valid:
21397// r.ArrS[3].Arr[6:7]
21398//
21399// r.ArrS[3].x
21400namespace {
21401class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
21402 Sema &SemaRef;
21403 OpenMPClauseKind CKind = OMPC_unknown;
21404 OpenMPDirectiveKind DKind = OMPD_unknown;
21405 OMPClauseMappableExprCommon::MappableExprComponentList &Components;
21406 bool IsNonContiguous = false;
21407 bool NoDiagnose = false;
21408 const Expr *RelevantExpr = nullptr;
21409 bool AllowUnitySizeArraySection = true;
21410 bool AllowWholeSizeArraySection = true;
21411 bool AllowAnotherPtr = true;
21412 SourceLocation ELoc;
21413 SourceRange ERange;
21414
21415 void emitErrorMsg() {
21416 // If nothing else worked, this is not a valid map clause expression.
21417 if (SemaRef.getLangOpts().OpenMP < 50) {
21418 SemaRef.Diag(ELoc,
21419 diag::err_omp_expected_named_var_member_or_array_expression)
21420 << ERange;
21421 } else {
21422 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21423 << getOpenMPClauseName(CKind) << ERange;
21424 }
21425 }
21426
21427public:
21428 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
21429 if (!isa<VarDecl>(Val: DRE->getDecl())) {
21430 emitErrorMsg();
21431 return false;
21432 }
21433 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21434 RelevantExpr = DRE;
21435 // Record the component.
21436 Components.emplace_back(Args&: DRE, Args: DRE->getDecl(), Args&: IsNonContiguous);
21437 return true;
21438 }
21439
21440 bool VisitMemberExpr(MemberExpr *ME) {
21441 Expr *E = ME;
21442 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
21443
21444 if (isa<CXXThisExpr>(Val: BaseE)) {
21445 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21446 // We found a base expression: this->Val.
21447 RelevantExpr = ME;
21448 } else {
21449 E = BaseE;
21450 }
21451
21452 if (!isa<FieldDecl>(Val: ME->getMemberDecl())) {
21453 if (!NoDiagnose) {
21454 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
21455 << ME->getSourceRange();
21456 return false;
21457 }
21458 if (RelevantExpr)
21459 return false;
21460 return Visit(E);
21461 }
21462
21463 auto *FD = cast<FieldDecl>(Val: ME->getMemberDecl());
21464
21465 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
21466 // A bit-field cannot appear in a map clause.
21467 //
21468 if (FD->isBitField()) {
21469 if (!NoDiagnose) {
21470 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
21471 << ME->getSourceRange() << getOpenMPClauseName(CKind);
21472 return false;
21473 }
21474 if (RelevantExpr)
21475 return false;
21476 return Visit(E);
21477 }
21478
21479 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21480 // If the type of a list item is a reference to a type T then the type
21481 // will be considered to be T for all purposes of this clause.
21482 QualType CurType = BaseE->getType().getNonReferenceType();
21483
21484 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
21485 // A list item cannot be a variable that is a member of a structure with
21486 // a union type.
21487 //
21488 if (CurType->isUnionType()) {
21489 if (!NoDiagnose) {
21490 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
21491 << ME->getSourceRange();
21492 return false;
21493 }
21494 return RelevantExpr || Visit(E);
21495 }
21496
21497 // If we got a member expression, we should not expect any array section
21498 // before that:
21499 //
21500 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
21501 // If a list item is an element of a structure, only the rightmost symbol
21502 // of the variable reference can be an array section.
21503 //
21504 AllowUnitySizeArraySection = false;
21505 AllowWholeSizeArraySection = false;
21506
21507 // Record the component.
21508 Components.emplace_back(Args&: ME, Args&: FD, Args&: IsNonContiguous);
21509 return RelevantExpr || Visit(E);
21510 }
21511
21512 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
21513 Expr *E = AE->getBase()->IgnoreParenImpCasts();
21514
21515 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
21516 if (!NoDiagnose) {
21517 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21518 << 0 << AE->getSourceRange();
21519 return false;
21520 }
21521 return RelevantExpr || Visit(E);
21522 }
21523
21524 // If we got an array subscript that express the whole dimension we
21525 // can have any array expressions before. If it only expressing part of
21526 // the dimension, we can only have unitary-size array expressions.
21527 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, AE, E->getType()))
21528 AllowWholeSizeArraySection = false;
21529
21530 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E->IgnoreParenCasts())) {
21531 Expr::EvalResult Result;
21532 if (!AE->getIdx()->isValueDependent() &&
21533 AE->getIdx()->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()) &&
21534 !Result.Val.getInt().isZero()) {
21535 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21536 diag::err_omp_invalid_map_this_expr);
21537 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21538 diag::note_omp_invalid_subscript_on_this_ptr_map);
21539 }
21540 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21541 RelevantExpr = TE;
21542 }
21543
21544 // Record the component - we don't have any declaration associated.
21545 Components.emplace_back(Args&: AE, Args: nullptr, Args&: IsNonContiguous);
21546
21547 return RelevantExpr || Visit(E);
21548 }
21549
21550 bool VisitOMPArraySectionExpr(OMPArraySectionExpr *OASE) {
21551 // After OMP 5.0 Array section in reduction clause will be implicitly
21552 // mapped
21553 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
21554 "Array sections cannot be implicitly mapped.");
21555 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21556 QualType CurType =
21557 OMPArraySectionExpr::getBaseOriginalType(Base: E).getCanonicalType();
21558
21559 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21560 // If the type of a list item is a reference to a type T then the type
21561 // will be considered to be T for all purposes of this clause.
21562 if (CurType->isReferenceType())
21563 CurType = CurType->getPointeeType();
21564
21565 bool IsPointer = CurType->isAnyPointerType();
21566
21567 if (!IsPointer && !CurType->isArrayType()) {
21568 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21569 << 0 << OASE->getSourceRange();
21570 return false;
21571 }
21572
21573 bool NotWhole =
21574 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
21575 bool NotUnity =
21576 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
21577
21578 if (AllowWholeSizeArraySection) {
21579 // Any array section is currently allowed. Allowing a whole size array
21580 // section implies allowing a unity array section as well.
21581 //
21582 // If this array section refers to the whole dimension we can still
21583 // accept other array sections before this one, except if the base is a
21584 // pointer. Otherwise, only unitary sections are accepted.
21585 if (NotWhole || IsPointer)
21586 AllowWholeSizeArraySection = false;
21587 } else if (DKind == OMPD_target_update &&
21588 SemaRef.getLangOpts().OpenMP >= 50) {
21589 if (IsPointer && !AllowAnotherPtr)
21590 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21591 << /*array of unknown bound */ 1;
21592 else
21593 IsNonContiguous = true;
21594 } else if (AllowUnitySizeArraySection && NotUnity) {
21595 // A unity or whole array section is not allowed and that is not
21596 // compatible with the properties of the current array section.
21597 if (NoDiagnose)
21598 return false;
21599 SemaRef.Diag(ELoc,
21600 diag::err_array_section_does_not_specify_contiguous_storage)
21601 << OASE->getSourceRange();
21602 return false;
21603 }
21604
21605 if (IsPointer)
21606 AllowAnotherPtr = false;
21607
21608 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E)) {
21609 Expr::EvalResult ResultR;
21610 Expr::EvalResult ResultL;
21611 if (!OASE->getLength()->isValueDependent() &&
21612 OASE->getLength()->EvaluateAsInt(Result&: ResultR, Ctx: SemaRef.getASTContext()) &&
21613 !ResultR.Val.getInt().isOne()) {
21614 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21615 diag::err_omp_invalid_map_this_expr);
21616 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21617 diag::note_omp_invalid_length_on_this_ptr_mapping);
21618 }
21619 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
21620 OASE->getLowerBound()->EvaluateAsInt(Result&: ResultL,
21621 Ctx: SemaRef.getASTContext()) &&
21622 !ResultL.Val.getInt().isZero()) {
21623 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21624 diag::err_omp_invalid_map_this_expr);
21625 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21626 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21627 }
21628 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21629 RelevantExpr = TE;
21630 }
21631
21632 // Record the component - we don't have any declaration associated.
21633 Components.emplace_back(Args&: OASE, Args: nullptr, /*IsNonContiguous=*/Args: false);
21634 return RelevantExpr || Visit(E);
21635 }
21636 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21637 Expr *Base = E->getBase();
21638
21639 // Record the component - we don't have any declaration associated.
21640 Components.emplace_back(Args&: E, Args: nullptr, Args&: IsNonContiguous);
21641
21642 return Visit(Base->IgnoreParenImpCasts());
21643 }
21644
21645 bool VisitUnaryOperator(UnaryOperator *UO) {
21646 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
21647 UO->getOpcode() != UO_Deref) {
21648 emitErrorMsg();
21649 return false;
21650 }
21651 if (!RelevantExpr) {
21652 // Record the component if haven't found base decl.
21653 Components.emplace_back(Args&: UO, Args: nullptr, /*IsNonContiguous=*/Args: false);
21654 }
21655 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
21656 }
21657 bool VisitBinaryOperator(BinaryOperator *BO) {
21658 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
21659 emitErrorMsg();
21660 return false;
21661 }
21662
21663 // Pointer arithmetic is the only thing we expect to happen here so after we
21664 // make sure the binary operator is a pointer type, the only thing we need
21665 // to do is to visit the subtree that has the same type as root (so that we
21666 // know the other subtree is just an offset)
21667 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
21668 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
21669 Components.emplace_back(Args&: BO, Args: nullptr, Args: false);
21670 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
21671 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
21672 "Either LHS or RHS have base decl inside");
21673 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
21674 return RelevantExpr || Visit(LE);
21675 return RelevantExpr || Visit(RE);
21676 }
21677 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21678 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21679 RelevantExpr = CTE;
21680 Components.emplace_back(Args&: CTE, Args: nullptr, Args&: IsNonContiguous);
21681 return true;
21682 }
21683 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21684 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21685 Components.emplace_back(Args&: COCE, Args: nullptr, Args&: IsNonContiguous);
21686 return true;
21687 }
21688 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21689 Expr *Source = E->getSourceExpr();
21690 if (!Source) {
21691 emitErrorMsg();
21692 return false;
21693 }
21694 return Visit(Source);
21695 }
21696 bool VisitStmt(Stmt *) {
21697 emitErrorMsg();
21698 return false;
21699 }
21700 const Expr *getFoundBase() const { return RelevantExpr; }
21701 explicit MapBaseChecker(
21702 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
21703 OMPClauseMappableExprCommon::MappableExprComponentList &Components,
21704 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21705 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21706 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21707};
21708} // namespace
21709
21710/// Return the expression of the base of the mappable expression or null if it
21711/// cannot be determined and do all the necessary checks to see if the
21712/// expression is valid as a standalone mappable expression. In the process,
21713/// record all the components of the expression.
21714static const Expr *checkMapClauseExpressionBase(
21715 Sema &SemaRef, Expr *E,
21716 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
21717 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
21718 SourceLocation ELoc = E->getExprLoc();
21719 SourceRange ERange = E->getSourceRange();
21720 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21721 ERange);
21722 if (Checker.Visit(E->IgnoreParens())) {
21723 // Check if the highest dimension array section has length specified
21724 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21725 (CKind == OMPC_to || CKind == OMPC_from)) {
21726 auto CI = CurComponents.rbegin();
21727 auto CE = CurComponents.rend();
21728 for (; CI != CE; ++CI) {
21729 const auto *OASE =
21730 dyn_cast<OMPArraySectionExpr>(Val: CI->getAssociatedExpression());
21731 if (!OASE)
21732 continue;
21733 if (OASE && OASE->getLength())
21734 break;
21735 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
21736 << ERange;
21737 }
21738 }
21739 return Checker.getFoundBase();
21740 }
21741 return nullptr;
21742}
21743
21744// Return true if expression E associated with value VD has conflicts with other
21745// map information.
21746static bool checkMapConflicts(
21747 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21748 bool CurrentRegionOnly,
21749 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
21750 OpenMPClauseKind CKind) {
21751 assert(VD && E);
21752 SourceLocation ELoc = E->getExprLoc();
21753 SourceRange ERange = E->getSourceRange();
21754
21755 // In order to easily check the conflicts we need to match each component of
21756 // the expression under test with the components of the expressions that are
21757 // already in the stack.
21758
21759 assert(!CurComponents.empty() && "Map clause expression with no components!");
21760 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21761 "Map clause expression with unexpected base!");
21762
21763 // Variables to help detecting enclosing problems in data environment nests.
21764 bool IsEnclosedByDataEnvironmentExpr = false;
21765 const Expr *EnclosingExpr = nullptr;
21766
21767 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21768 VD, CurrentRegionOnly,
21769 Check: [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21770 ERange, CKind, &EnclosingExpr,
21771 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
21772 StackComponents,
21773 OpenMPClauseKind Kind) {
21774 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21775 return false;
21776 assert(!StackComponents.empty() &&
21777 "Map clause expression with no components!");
21778 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21779 "Map clause expression with unexpected base!");
21780 (void)VD;
21781
21782 // The whole expression in the stack.
21783 const Expr *RE = StackComponents.front().getAssociatedExpression();
21784
21785 // Expressions must start from the same base. Here we detect at which
21786 // point both expressions diverge from each other and see if we can
21787 // detect if the memory referred to both expressions is contiguous and
21788 // do not overlap.
21789 auto CI = CurComponents.rbegin();
21790 auto CE = CurComponents.rend();
21791 auto SI = StackComponents.rbegin();
21792 auto SE = StackComponents.rend();
21793 for (; CI != CE && SI != SE; ++CI, ++SI) {
21794
21795 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21796 // At most one list item can be an array item derived from a given
21797 // variable in map clauses of the same construct.
21798 if (CurrentRegionOnly &&
21799 (isa<ArraySubscriptExpr>(Val: CI->getAssociatedExpression()) ||
21800 isa<OMPArraySectionExpr>(Val: CI->getAssociatedExpression()) ||
21801 isa<OMPArrayShapingExpr>(Val: CI->getAssociatedExpression())) &&
21802 (isa<ArraySubscriptExpr>(Val: SI->getAssociatedExpression()) ||
21803 isa<OMPArraySectionExpr>(Val: SI->getAssociatedExpression()) ||
21804 isa<OMPArrayShapingExpr>(Val: SI->getAssociatedExpression()))) {
21805 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21806 diag::err_omp_multiple_array_items_in_map_clause)
21807 << CI->getAssociatedExpression()->getSourceRange();
21808 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21809 diag::note_used_here)
21810 << SI->getAssociatedExpression()->getSourceRange();
21811 return true;
21812 }
21813
21814 // Do both expressions have the same kind?
21815 if (CI->getAssociatedExpression()->getStmtClass() !=
21816 SI->getAssociatedExpression()->getStmtClass())
21817 break;
21818
21819 // Are we dealing with different variables/fields?
21820 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21821 break;
21822 }
21823 // Check if the extra components of the expressions in the enclosing
21824 // data environment are redundant for the current base declaration.
21825 // If they are, the maps completely overlap, which is legal.
21826 for (; SI != SE; ++SI) {
21827 QualType Type;
21828 if (const auto *ASE =
21829 dyn_cast<ArraySubscriptExpr>(Val: SI->getAssociatedExpression())) {
21830 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21831 } else if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(
21832 Val: SI->getAssociatedExpression())) {
21833 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21834 Type =
21835 OMPArraySectionExpr::getBaseOriginalType(Base: E).getCanonicalType();
21836 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21837 Val: SI->getAssociatedExpression())) {
21838 Type = OASE->getBase()->getType()->getPointeeType();
21839 }
21840 if (Type.isNull() || Type->isAnyPointerType() ||
21841 checkArrayExpressionDoesNotReferToWholeSize(
21842 SemaRef, E: SI->getAssociatedExpression(), BaseQTy: Type))
21843 break;
21844 }
21845
21846 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21847 // List items of map clauses in the same construct must not share
21848 // original storage.
21849 //
21850 // If the expressions are exactly the same or one is a subset of the
21851 // other, it means they are sharing storage.
21852 if (CI == CE && SI == SE) {
21853 if (CurrentRegionOnly) {
21854 if (CKind == OMPC_map) {
21855 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21856 } else {
21857 assert(CKind == OMPC_to || CKind == OMPC_from);
21858 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21859 << ERange;
21860 }
21861 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21862 << RE->getSourceRange();
21863 return true;
21864 }
21865 // If we find the same expression in the enclosing data environment,
21866 // that is legal.
21867 IsEnclosedByDataEnvironmentExpr = true;
21868 return false;
21869 }
21870
21871 QualType DerivedType =
21872 std::prev(x: CI)->getAssociatedDeclaration()->getType();
21873 SourceLocation DerivedLoc =
21874 std::prev(x: CI)->getAssociatedExpression()->getExprLoc();
21875
21876 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21877 // If the type of a list item is a reference to a type T then the type
21878 // will be considered to be T for all purposes of this clause.
21879 DerivedType = DerivedType.getNonReferenceType();
21880
21881 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21882 // A variable for which the type is pointer and an array section
21883 // derived from that variable must not appear as list items of map
21884 // clauses of the same construct.
21885 //
21886 // Also, cover one of the cases in:
21887 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21888 // If any part of the original storage of a list item has corresponding
21889 // storage in the device data environment, all of the original storage
21890 // must have corresponding storage in the device data environment.
21891 //
21892 if (DerivedType->isAnyPointerType()) {
21893 if (CI == CE || SI == SE) {
21894 SemaRef.Diag(
21895 DerivedLoc,
21896 diag::err_omp_pointer_mapped_along_with_derived_section)
21897 << DerivedLoc;
21898 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21899 << RE->getSourceRange();
21900 return true;
21901 }
21902 if (CI->getAssociatedExpression()->getStmtClass() !=
21903 SI->getAssociatedExpression()->getStmtClass() ||
21904 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21905 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21906 assert(CI != CE && SI != SE);
21907 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21908 << DerivedLoc;
21909 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21910 << RE->getSourceRange();
21911 return true;
21912 }
21913 }
21914
21915 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21916 // List items of map clauses in the same construct must not share
21917 // original storage.
21918 //
21919 // An expression is a subset of the other.
21920 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21921 if (CKind == OMPC_map) {
21922 if (CI != CE || SI != SE) {
21923 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21924 // a pointer.
21925 auto Begin =
21926 CI != CE ? CurComponents.begin() : StackComponents.begin();
21927 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21928 auto It = Begin;
21929 while (It != End && !It->getAssociatedDeclaration())
21930 std::advance(i&: It, n: 1);
21931 assert(It != End &&
21932 "Expected at least one component with the declaration.");
21933 if (It != Begin && It->getAssociatedDeclaration()
21934 ->getType()
21935 .getCanonicalType()
21936 ->isAnyPointerType()) {
21937 IsEnclosedByDataEnvironmentExpr = false;
21938 EnclosingExpr = nullptr;
21939 return false;
21940 }
21941 }
21942 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21943 } else {
21944 assert(CKind == OMPC_to || CKind == OMPC_from);
21945 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21946 << ERange;
21947 }
21948 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21949 << RE->getSourceRange();
21950 return true;
21951 }
21952
21953 // The current expression uses the same base as other expression in the
21954 // data environment but does not contain it completely.
21955 if (!CurrentRegionOnly && SI != SE)
21956 EnclosingExpr = RE;
21957
21958 // The current expression is a subset of the expression in the data
21959 // environment.
21960 IsEnclosedByDataEnvironmentExpr |=
21961 (!CurrentRegionOnly && CI != CE && SI == SE);
21962
21963 return false;
21964 });
21965
21966 if (CurrentRegionOnly)
21967 return FoundError;
21968
21969 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21970 // If any part of the original storage of a list item has corresponding
21971 // storage in the device data environment, all of the original storage must
21972 // have corresponding storage in the device data environment.
21973 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21974 // If a list item is an element of a structure, and a different element of
21975 // the structure has a corresponding list item in the device data environment
21976 // prior to a task encountering the construct associated with the map clause,
21977 // then the list item must also have a corresponding list item in the device
21978 // data environment prior to the task encountering the construct.
21979 //
21980 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21981 SemaRef.Diag(ELoc,
21982 diag::err_omp_original_storage_is_shared_and_does_not_contain)
21983 << ERange;
21984 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
21985 << EnclosingExpr->getSourceRange();
21986 return true;
21987 }
21988
21989 return FoundError;
21990}
21991
21992// Look up the user-defined mapper given the mapper name and mapped type, and
21993// build a reference to it.
21994static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
21995 CXXScopeSpec &MapperIdScopeSpec,
21996 const DeclarationNameInfo &MapperId,
21997 QualType Type,
21998 Expr *UnresolvedMapper) {
21999 if (MapperIdScopeSpec.isInvalid())
22000 return ExprError();
22001 // Get the actual type for the array type.
22002 if (Type->isArrayType()) {
22003 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
22004 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
22005 }
22006 // Find all user-defined mappers with the given MapperId.
22007 SmallVector<UnresolvedSet<8>, 4> Lookups;
22008 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22009 Lookup.suppressDiagnostics();
22010 if (S) {
22011 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &MapperIdScopeSpec)) {
22012 NamedDecl *D = Lookup.getRepresentativeDecl();
22013 while (S && !S->isDeclScope(D))
22014 S = S->getParent();
22015 if (S)
22016 S = S->getParent();
22017 Lookups.emplace_back();
22018 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
22019 Lookup.clear();
22020 }
22021 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(Val: UnresolvedMapper)) {
22022 // Extract the user-defined mappers with the given MapperId.
22023 Lookups.push_back(Elt: UnresolvedSet<8>());
22024 for (NamedDecl *D : ULE->decls()) {
22025 auto *DMD = cast<OMPDeclareMapperDecl>(D);
22026 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
22027 Lookups.back().addDecl(DMD);
22028 }
22029 }
22030 // Defer the lookup for dependent types. The results will be passed through
22031 // UnresolvedMapper on instantiation.
22032 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22033 Type->isInstantiationDependentType() ||
22034 Type->containsUnexpandedParameterPack() ||
22035 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
22036 return !D->isInvalidDecl() &&
22037 (D->getType()->isDependentType() ||
22038 D->getType()->isInstantiationDependentType() ||
22039 D->getType()->containsUnexpandedParameterPack());
22040 })) {
22041 UnresolvedSet<8> URS;
22042 for (const UnresolvedSet<8> &Set : Lookups) {
22043 if (Set.empty())
22044 continue;
22045 URS.append(I: Set.begin(), E: Set.end());
22046 }
22047 return UnresolvedLookupExpr::Create(
22048 Context: SemaRef.Context, /*NamingClass=*/nullptr,
22049 QualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: SemaRef.Context), NameInfo: MapperId,
22050 /*ADL=*/RequiresADL: false, /*Overloaded=*/true, Begin: URS.begin(), End: URS.end());
22051 }
22052 SourceLocation Loc = MapperId.getLoc();
22053 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22054 // The type must be of struct, union or class type in C and C++
22055 if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
22056 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
22057 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
22058 return ExprError();
22059 }
22060 // Perform argument dependent lookup.
22061 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22062 argumentDependentLookup(SemaRef, Id: MapperId, Loc, Ty: Type, Lookups);
22063 // Return the first user-defined mapper with the desired type.
22064 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
22065 Lookups, Gen: [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22066 if (!D->isInvalidDecl() &&
22067 SemaRef.Context.hasSameType(T1: D->getType(), T2: Type))
22068 return D;
22069 return nullptr;
22070 }))
22071 return SemaRef.BuildDeclRefExpr(D: VD, Ty: Type, VK: VK_LValue, Loc);
22072 // Find the first user-defined mapper with a type derived from the desired
22073 // type.
22074 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
22075 Lookups, Gen: [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22076 if (!D->isInvalidDecl() &&
22077 SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: D->getType()) &&
22078 !Type.isMoreQualifiedThan(other: D->getType()))
22079 return D;
22080 return nullptr;
22081 })) {
22082 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22083 /*DetectVirtual=*/false);
22084 if (SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: VD->getType(), Paths)) {
22085 if (!Paths.isAmbiguous(BaseType: SemaRef.Context.getCanonicalType(
22086 T: VD->getType().getUnqualifiedType()))) {
22087 if (SemaRef.CheckBaseClassAccess(
22088 AccessLoc: Loc, Base: VD->getType(), Derived: Type, Path: Paths.front(),
22089 /*DiagID=*/0) != Sema::AR_inaccessible) {
22090 return SemaRef.BuildDeclRefExpr(D: VD, Ty: Type, VK: VK_LValue, Loc);
22091 }
22092 }
22093 }
22094 }
22095 // Report error if a mapper is specified, but cannot be found.
22096 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
22097 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
22098 << Type << MapperId.getName();
22099 return ExprError();
22100 }
22101 return ExprEmpty();
22102}
22103
22104namespace {
22105// Utility struct that gathers all the related lists associated with a mappable
22106// expression.
22107struct MappableVarListInfo {
22108 // The list of expressions.
22109 ArrayRef<Expr *> VarList;
22110 // The list of processed expressions.
22111 SmallVector<Expr *, 16> ProcessedVarList;
22112 // The mappble components for each expression.
22113 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
22114 // The base declaration of the variable.
22115 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22116 // The reference to the user-defined mapper associated with every expression.
22117 SmallVector<Expr *, 16> UDMapperList;
22118
22119 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22120 // We have a list of components and base declarations for each entry in the
22121 // variable list.
22122 VarComponents.reserve(N: VarList.size());
22123 VarBaseDeclarations.reserve(N: VarList.size());
22124 }
22125};
22126} // namespace
22127
22128// Check the validity of the provided variable list for the provided clause kind
22129// \a CKind. In the check process the valid expressions, mappable expression
22130// components, variables, and user-defined mappers are extracted and used to
22131// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
22132// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22133// and \a MapperId are expected to be valid if the clause kind is 'map'.
22134static void checkMappableExpressionList(
22135 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
22136 MappableVarListInfo &MVLI, SourceLocation StartLoc,
22137 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
22138 ArrayRef<Expr *> UnresolvedMappers,
22139 OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
22140 ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt,
22141 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
22142 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
22143 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
22144 "Unexpected clause kind with mappable expressions!");
22145
22146 // If the identifier of user-defined mapper is not specified, it is "default".
22147 // We do not change the actual name in this clause to distinguish whether a
22148 // mapper is specified explicitly, i.e., it is not explicitly specified when
22149 // MapperId.getName() is empty.
22150 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
22151 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
22152 MapperId.setName(DeclNames.getIdentifier(
22153 ID: &SemaRef.getASTContext().Idents.get(Name: "default")));
22154 MapperId.setLoc(StartLoc);
22155 }
22156
22157 // Iterators to find the current unresolved mapper expression.
22158 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
22159 bool UpdateUMIt = false;
22160 Expr *UnresolvedMapper = nullptr;
22161
22162 bool HasHoldModifier =
22163 llvm::is_contained(Range&: Modifiers, Element: OMPC_MAP_MODIFIER_ompx_hold);
22164
22165 // Keep track of the mappable components and base declarations in this clause.
22166 // Each entry in the list is going to have a list of components associated. We
22167 // record each set of the components so that we can build the clause later on.
22168 // In the end we should have the same amount of declarations and component
22169 // lists.
22170
22171 for (Expr *RE : MVLI.VarList) {
22172 assert(RE && "Null expr in omp to/from/map clause");
22173 SourceLocation ELoc = RE->getExprLoc();
22174
22175 // Find the current unresolved mapper expression.
22176 if (UpdateUMIt && UMIt != UMEnd) {
22177 UMIt++;
22178 assert(
22179 UMIt != UMEnd &&
22180 "Expect the size of UnresolvedMappers to match with that of VarList");
22181 }
22182 UpdateUMIt = true;
22183 if (UMIt != UMEnd)
22184 UnresolvedMapper = *UMIt;
22185
22186 const Expr *VE = RE->IgnoreParenLValueCasts();
22187
22188 if (VE->isValueDependent() || VE->isTypeDependent() ||
22189 VE->isInstantiationDependent() ||
22190 VE->containsUnexpandedParameterPack()) {
22191 // Try to find the associated user-defined mapper.
22192 ExprResult ER = buildUserDefinedMapperRef(
22193 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22194 Type: VE->getType().getCanonicalType(), UnresolvedMapper);
22195 if (ER.isInvalid())
22196 continue;
22197 MVLI.UDMapperList.push_back(Elt: ER.get());
22198 // We can only analyze this information once the missing information is
22199 // resolved.
22200 MVLI.ProcessedVarList.push_back(Elt: RE);
22201 continue;
22202 }
22203
22204 Expr *SimpleExpr = RE->IgnoreParenCasts();
22205
22206 if (!RE->isLValue()) {
22207 if (SemaRef.getLangOpts().OpenMP < 50) {
22208 SemaRef.Diag(
22209 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
22210 << RE->getSourceRange();
22211 } else {
22212 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22213 << getOpenMPClauseName(CKind) << RE->getSourceRange();
22214 }
22215 continue;
22216 }
22217
22218 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
22219 ValueDecl *CurDeclaration = nullptr;
22220
22221 // Obtain the array or member expression bases if required. Also, fill the
22222 // components array with all the components identified in the process.
22223 const Expr *BE =
22224 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
22225 DSAS->getCurrentDirective(), NoDiagnose);
22226 if (!BE)
22227 continue;
22228
22229 assert(!CurComponents.empty() &&
22230 "Invalid mappable expression information.");
22231
22232 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: BE)) {
22233 // Add store "this" pointer to class in DSAStackTy for future checking
22234 DSAS->addMappedClassesQualTypes(QT: TE->getType());
22235 // Try to find the associated user-defined mapper.
22236 ExprResult ER = buildUserDefinedMapperRef(
22237 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22238 Type: VE->getType().getCanonicalType(), UnresolvedMapper);
22239 if (ER.isInvalid())
22240 continue;
22241 MVLI.UDMapperList.push_back(Elt: ER.get());
22242 // Skip restriction checking for variable or field declarations
22243 MVLI.ProcessedVarList.push_back(Elt: RE);
22244 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
22245 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
22246 in_end: CurComponents.end());
22247 MVLI.VarBaseDeclarations.push_back(Elt: nullptr);
22248 continue;
22249 }
22250
22251 // For the following checks, we rely on the base declaration which is
22252 // expected to be associated with the last component. The declaration is
22253 // expected to be a variable or a field (if 'this' is being mapped).
22254 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
22255 assert(CurDeclaration && "Null decl on map clause.");
22256 assert(
22257 CurDeclaration->isCanonicalDecl() &&
22258 "Expecting components to have associated only canonical declarations.");
22259
22260 auto *VD = dyn_cast<VarDecl>(Val: CurDeclaration);
22261 const auto *FD = dyn_cast<FieldDecl>(Val: CurDeclaration);
22262
22263 assert((VD || FD) && "Only variables or fields are expected here!");
22264 (void)FD;
22265
22266 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
22267 // threadprivate variables cannot appear in a map clause.
22268 // OpenMP 4.5 [2.10.5, target update Construct]
22269 // threadprivate variables cannot appear in a from clause.
22270 if (VD && DSAS->isThreadPrivate(D: VD)) {
22271 if (NoDiagnose)
22272 continue;
22273 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22274 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
22275 << getOpenMPClauseName(CKind);
22276 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
22277 continue;
22278 }
22279
22280 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22281 // A list item cannot appear in both a map clause and a data-sharing
22282 // attribute clause on the same construct.
22283
22284 // Check conflicts with other map clause expressions. We check the conflicts
22285 // with the current construct separately from the enclosing data
22286 // environment, because the restrictions are different. We only have to
22287 // check conflicts across regions for the map clauses.
22288 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22289 /*CurrentRegionOnly=*/true, CurComponents, CKind))
22290 break;
22291 if (CKind == OMPC_map &&
22292 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
22293 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22294 /*CurrentRegionOnly=*/false, CurComponents, CKind))
22295 break;
22296
22297 // OpenMP 4.5 [2.10.5, target update Construct]
22298 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22299 // If the type of a list item is a reference to a type T then the type will
22300 // be considered to be T for all purposes of this clause.
22301 auto I = llvm::find_if(
22302 Range&: CurComponents,
22303 P: [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
22304 return MC.getAssociatedDeclaration();
22305 });
22306 assert(I != CurComponents.end() && "Null decl on map clause.");
22307 (void)I;
22308 QualType Type;
22309 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: VE->IgnoreParens());
22310 auto *OASE = dyn_cast<OMPArraySectionExpr>(Val: VE->IgnoreParens());
22311 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(Val: VE->IgnoreParens());
22312 if (ASE) {
22313 Type = ASE->getType().getNonReferenceType();
22314 } else if (OASE) {
22315 QualType BaseType =
22316 OMPArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
22317 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22318 Type = ATy->getElementType();
22319 else
22320 Type = BaseType->getPointeeType();
22321 Type = Type.getNonReferenceType();
22322 } else if (OAShE) {
22323 Type = OAShE->getBase()->getType()->getPointeeType();
22324 } else {
22325 Type = VE->getType();
22326 }
22327
22328 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
22329 // A list item in a to or from clause must have a mappable type.
22330 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22331 // A list item must have a mappable type.
22332 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
22333 DSAS, Type, /*FullCheck=*/true))
22334 continue;
22335
22336 if (CKind == OMPC_map) {
22337 // target enter data
22338 // OpenMP [2.10.2, Restrictions, p. 99]
22339 // A map-type must be specified in all map clauses and must be either
22340 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
22341 // no map type is present.
22342 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
22343 if (DKind == OMPD_target_enter_data &&
22344 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
22345 SemaRef.getLangOpts().OpenMP >= 52)) {
22346 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22347 << (IsMapTypeImplicit ? 1 : 0)
22348 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22349 << getOpenMPDirectiveName(DKind);
22350 continue;
22351 }
22352
22353 // target exit_data
22354 // OpenMP [2.10.3, Restrictions, p. 102]
22355 // A map-type must be specified in all map clauses and must be either
22356 // from, release, or delete. Starting with OpenMP 5.2 the default map
22357 // type is `from` if no map type is present.
22358 if (DKind == OMPD_target_exit_data &&
22359 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
22360 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
22361 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22362 << (IsMapTypeImplicit ? 1 : 0)
22363 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22364 << getOpenMPDirectiveName(DKind);
22365 continue;
22366 }
22367
22368 // The 'ompx_hold' modifier is specifically intended to be used on a
22369 // 'target' or 'target data' directive to prevent data from being unmapped
22370 // during the associated statement. It is not permitted on a 'target
22371 // enter data' or 'target exit data' directive, which have no associated
22372 // statement.
22373 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
22374 HasHoldModifier) {
22375 SemaRef.Diag(StartLoc,
22376 diag::err_omp_invalid_map_type_modifier_for_directive)
22377 << getOpenMPSimpleClauseTypeName(OMPC_map,
22378 OMPC_MAP_MODIFIER_ompx_hold)
22379 << getOpenMPDirectiveName(DKind);
22380 continue;
22381 }
22382
22383 // target, target data
22384 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22385 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22386 // A map-type in a map clause must be to, from, tofrom or alloc
22387 if ((DKind == OMPD_target_data ||
22388 isOpenMPTargetExecutionDirective(DKind)) &&
22389 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
22390 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
22391 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22392 << (IsMapTypeImplicit ? 1 : 0)
22393 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22394 << getOpenMPDirectiveName(DKind);
22395 continue;
22396 }
22397
22398 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22399 // A list item cannot appear in both a map clause and a data-sharing
22400 // attribute clause on the same construct
22401 //
22402 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22403 // A list item cannot appear in both a map clause and a data-sharing
22404 // attribute clause on the same construct unless the construct is a
22405 // combined construct.
22406 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
22407 isOpenMPTargetExecutionDirective(DKind)) ||
22408 DKind == OMPD_target)) {
22409 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22410 if (isOpenMPPrivate(DVar.CKind)) {
22411 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22412 << getOpenMPClauseName(DVar.CKind)
22413 << getOpenMPClauseName(OMPC_map)
22414 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
22415 reportOriginalDsa(SemaRef, Stack: DSAS, D: CurDeclaration, DVar);
22416 continue;
22417 }
22418 }
22419 }
22420
22421 // Try to find the associated user-defined mapper.
22422 ExprResult ER = buildUserDefinedMapperRef(
22423 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22424 Type: Type.getCanonicalType(), UnresolvedMapper);
22425 if (ER.isInvalid())
22426 continue;
22427 MVLI.UDMapperList.push_back(Elt: ER.get());
22428
22429 // Save the current expression.
22430 MVLI.ProcessedVarList.push_back(Elt: RE);
22431
22432 // Store the components in the stack so that they can be used to check
22433 // against other clauses later on.
22434 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
22435 /*WhereFoundClauseKind=*/OMPC_map);
22436
22437 // Save the components and declaration to create the clause. For purposes of
22438 // the clause creation, any component list that has base 'this' uses
22439 // null as base declaration.
22440 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
22441 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
22442 in_end: CurComponents.end());
22443 MVLI.VarBaseDeclarations.push_back(Elt: isa<MemberExpr>(Val: BE) ? nullptr
22444 : CurDeclaration);
22445 }
22446}
22447
22448OMPClause *Sema::ActOnOpenMPMapClause(
22449 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
22450 ArrayRef<SourceLocation> MapTypeModifiersLoc,
22451 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22452 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
22453 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22454 const OMPVarListLocTy &Locs, bool NoDiagnose,
22455 ArrayRef<Expr *> UnresolvedMappers) {
22456 OpenMPMapModifierKind Modifiers[] = {
22457 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22458 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22459 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown};
22460 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
22461
22462 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
22463 BuiltinType::OMPIterator))
22464 Diag(IteratorModifier->getExprLoc(),
22465 diag::err_omp_map_modifier_not_iterator);
22466
22467 // Process map-type-modifiers, flag errors for duplicate modifiers.
22468 unsigned Count = 0;
22469 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22470 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
22471 llvm::is_contained(Range&: Modifiers, Element: MapTypeModifiers[I])) {
22472 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22473 continue;
22474 }
22475 assert(Count < NumberOfOMPMapClauseModifiers &&
22476 "Modifiers exceed the allowed number of map type modifiers");
22477 Modifiers[Count] = MapTypeModifiers[I];
22478 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22479 ++Count;
22480 }
22481
22482 MappableVarListInfo MVLI(VarList);
22483 checkMappableExpressionList(*this, DSAStack, OMPC_map, MVLI, Locs.StartLoc,
22484 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22485 MapType, Modifiers, IsMapTypeImplicit,
22486 NoDiagnose);
22487
22488 // We need to produce a map clause even if we don't have variables so that
22489 // other diagnostics related with non-existing map clauses are accurate.
22490 return OMPMapClause::Create(
22491 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22492 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22493 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context), MapperId,
22494 MapType, IsMapTypeImplicit, MapLoc);
22495}
22496
22497QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
22498 TypeResult ParsedType) {
22499 assert(ParsedType.isUsable());
22500
22501 QualType ReductionType = GetTypeFromParser(Ty: ParsedType.get());
22502 if (ReductionType.isNull())
22503 return QualType();
22504
22505 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22506 // A type name in a declare reduction directive cannot be a function type, an
22507 // array type, a reference type, or a type qualified with const, volatile or
22508 // restrict.
22509 if (ReductionType.hasQualifiers()) {
22510 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22511 return QualType();
22512 }
22513
22514 if (ReductionType->isFunctionType()) {
22515 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22516 return QualType();
22517 }
22518 if (ReductionType->isReferenceType()) {
22519 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22520 return QualType();
22521 }
22522 if (ReductionType->isArrayType()) {
22523 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22524 return QualType();
22525 }
22526 return ReductionType;
22527}
22528
22529Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
22530 Scope *S, DeclContext *DC, DeclarationName Name,
22531 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22532 AccessSpecifier AS, Decl *PrevDeclInScope) {
22533 SmallVector<Decl *, 8> Decls;
22534 Decls.reserve(N: ReductionTypes.size());
22535
22536 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPReductionName,
22537 forRedeclarationInCurContext());
22538 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22539 // A reduction-identifier may not be re-declared in the current scope for the
22540 // same type or for a type that is compatible according to the base language
22541 // rules.
22542 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22543 OMPDeclareReductionDecl *PrevDRD = nullptr;
22544 bool InCompoundScope = true;
22545 if (S != nullptr) {
22546 // Find previous declaration with the same name not referenced in other
22547 // declarations.
22548 FunctionScopeInfo *ParentFn = getEnclosingFunction();
22549 InCompoundScope =
22550 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22551 LookupName(R&: Lookup, S);
22552 FilterLookupForScope(R&: Lookup, Ctx: DC, S, /*ConsiderLinkage=*/false,
22553 /*AllowInlineNamespace=*/false);
22554 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22555 LookupResult::Filter Filter = Lookup.makeFilter();
22556 while (Filter.hasNext()) {
22557 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Val: Filter.next());
22558 if (InCompoundScope) {
22559 auto I = UsedAsPrevious.find(Val: PrevDecl);
22560 if (I == UsedAsPrevious.end())
22561 UsedAsPrevious[PrevDecl] = false;
22562 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
22563 UsedAsPrevious[D] = true;
22564 }
22565 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22566 PrevDecl->getLocation();
22567 }
22568 Filter.done();
22569 if (InCompoundScope) {
22570 for (const auto &PrevData : UsedAsPrevious) {
22571 if (!PrevData.second) {
22572 PrevDRD = PrevData.first;
22573 break;
22574 }
22575 }
22576 }
22577 } else if (PrevDeclInScope != nullptr) {
22578 auto *PrevDRDInScope = PrevDRD =
22579 cast<OMPDeclareReductionDecl>(Val: PrevDeclInScope);
22580 do {
22581 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22582 PrevDRDInScope->getLocation();
22583 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22584 } while (PrevDRDInScope != nullptr);
22585 }
22586 for (const auto &TyData : ReductionTypes) {
22587 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22588 bool Invalid = false;
22589 if (I != PreviousRedeclTypes.end()) {
22590 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22591 << TyData.first;
22592 Diag(I->second, diag::note_previous_definition);
22593 Invalid = true;
22594 }
22595 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22596 auto *DRD = OMPDeclareReductionDecl::Create(Context, DC, TyData.second,
22597 Name, TyData.first, PrevDRD);
22598 DC->addDecl(DRD);
22599 DRD->setAccess(AS);
22600 Decls.push_back(DRD);
22601 if (Invalid)
22602 DRD->setInvalidDecl();
22603 else
22604 PrevDRD = DRD;
22605 }
22606
22607 return DeclGroupPtrTy::make(
22608 P: DeclGroupRef::Create(C&: Context, Decls: Decls.begin(), NumDecls: Decls.size()));
22609}
22610
22611void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
22612 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
22613
22614 // Enter new function scope.
22615 PushFunctionScope();
22616 setFunctionHasBranchProtectedScope();
22617 getCurFunction()->setHasOMPDeclareReductionCombiner();
22618
22619 if (S != nullptr)
22620 PushDeclContext(S, DRD);
22621 else
22622 CurContext = DRD;
22623
22624 PushExpressionEvaluationContext(
22625 NewContext: ExpressionEvaluationContext::PotentiallyEvaluated);
22626
22627 QualType ReductionType = DRD->getType();
22628 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22629 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22630 // uses semantics of argument handles by value, but it should be passed by
22631 // reference. C lang does not support references, so pass all parameters as
22632 // pointers.
22633 // Create 'T omp_in;' variable.
22634 VarDecl *OmpInParm =
22635 buildVarDecl(SemaRef&: *this, Loc: D->getLocation(), Type: ReductionType, Name: "omp_in");
22636 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22637 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22638 // uses semantics of argument handles by value, but it should be passed by
22639 // reference. C lang does not support references, so pass all parameters as
22640 // pointers.
22641 // Create 'T omp_out;' variable.
22642 VarDecl *OmpOutParm =
22643 buildVarDecl(SemaRef&: *this, Loc: D->getLocation(), Type: ReductionType, Name: "omp_out");
22644 if (S != nullptr) {
22645 PushOnScopeChains(OmpInParm, S);
22646 PushOnScopeChains(OmpOutParm, S);
22647 } else {
22648 DRD->addDecl(OmpInParm);
22649 DRD->addDecl(OmpOutParm);
22650 }
22651 Expr *InE =
22652 ::buildDeclRefExpr(S&: *this, D: OmpInParm, Ty: ReductionType, Loc: D->getLocation());
22653 Expr *OutE =
22654 ::buildDeclRefExpr(S&: *this, D: OmpOutParm, Ty: ReductionType, Loc: D->getLocation());
22655 DRD->setCombinerData(InE, OutE);
22656}
22657
22658void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner) {
22659 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
22660 DiscardCleanupsInEvaluationContext();
22661 PopExpressionEvaluationContext();
22662
22663 PopDeclContext();
22664 PopFunctionScopeInfo();
22665
22666 if (Combiner != nullptr)
22667 DRD->setCombiner(Combiner);
22668 else
22669 DRD->setInvalidDecl();
22670}
22671
22672VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
22673 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
22674
22675 // Enter new function scope.
22676 PushFunctionScope();
22677 setFunctionHasBranchProtectedScope();
22678
22679 if (S != nullptr)
22680 PushDeclContext(S, DRD);
22681 else
22682 CurContext = DRD;
22683
22684 PushExpressionEvaluationContext(
22685 NewContext: ExpressionEvaluationContext::PotentiallyEvaluated);
22686
22687 QualType ReductionType = DRD->getType();
22688 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22689 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22690 // uses semantics of argument handles by value, but it should be passed by
22691 // reference. C lang does not support references, so pass all parameters as
22692 // pointers.
22693 // Create 'T omp_priv;' variable.
22694 VarDecl *OmpPrivParm =
22695 buildVarDecl(SemaRef&: *this, Loc: D->getLocation(), Type: ReductionType, Name: "omp_priv");
22696 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22697 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22698 // uses semantics of argument handles by value, but it should be passed by
22699 // reference. C lang does not support references, so pass all parameters as
22700 // pointers.
22701 // Create 'T omp_orig;' variable.
22702 VarDecl *OmpOrigParm =
22703 buildVarDecl(SemaRef&: *this, Loc: D->getLocation(), Type: ReductionType, Name: "omp_orig");
22704 if (S != nullptr) {
22705 PushOnScopeChains(OmpPrivParm, S);
22706 PushOnScopeChains(OmpOrigParm, S);
22707 } else {
22708 DRD->addDecl(OmpPrivParm);
22709 DRD->addDecl(OmpOrigParm);
22710 }
22711 Expr *OrigE =
22712 ::buildDeclRefExpr(S&: *this, D: OmpOrigParm, Ty: ReductionType, Loc: D->getLocation());
22713 Expr *PrivE =
22714 ::buildDeclRefExpr(S&: *this, D: OmpPrivParm, Ty: ReductionType, Loc: D->getLocation());
22715 DRD->setInitializerData(OrigE, PrivE);
22716 return OmpPrivParm;
22717}
22718
22719void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer,
22720 VarDecl *OmpPrivParm) {
22721 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
22722 DiscardCleanupsInEvaluationContext();
22723 PopExpressionEvaluationContext();
22724
22725 PopDeclContext();
22726 PopFunctionScopeInfo();
22727
22728 if (Initializer != nullptr) {
22729 DRD->setInitializer(E: Initializer, IK: OMPDeclareReductionInitKind::Call);
22730 } else if (OmpPrivParm->hasInit()) {
22731 DRD->setInitializer(E: OmpPrivParm->getInit(),
22732 IK: OmpPrivParm->isDirectInit()
22733 ? OMPDeclareReductionInitKind::Direct
22734 : OMPDeclareReductionInitKind::Copy);
22735 } else {
22736 DRD->setInvalidDecl();
22737 }
22738}
22739
22740Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveEnd(
22741 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22742 for (Decl *D : DeclReductions.get()) {
22743 if (IsValid) {
22744 if (S)
22745 PushOnScopeChains(cast<OMPDeclareReductionDecl>(Val: D), S,
22746 /*AddToContext=*/false);
22747 } else {
22748 D->setInvalidDecl();
22749 }
22750 }
22751 return DeclReductions;
22752}
22753
22754TypeResult Sema::ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D) {
22755 TypeSourceInfo *TInfo = GetTypeForDeclarator(D);
22756 QualType T = TInfo->getType();
22757 if (D.isInvalidType())
22758 return true;
22759
22760 if (getLangOpts().CPlusPlus) {
22761 // Check that there are no default arguments (C++ only).
22762 CheckExtraCXXDefaultArguments(D);
22763 }
22764
22765 return CreateParsedType(T, TInfo);
22766}
22767
22768QualType Sema::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
22769 TypeResult ParsedType) {
22770 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
22771
22772 QualType MapperType = GetTypeFromParser(Ty: ParsedType.get());
22773 assert(!MapperType.isNull() && "Expect valid mapper type");
22774
22775 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22776 // The type must be of struct, union or class type in C and C++
22777 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22778 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22779 return QualType();
22780 }
22781 return MapperType;
22782}
22783
22784Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareMapperDirective(
22785 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22786 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
22787 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22788 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPMapperName,
22789 forRedeclarationInCurContext());
22790 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22791 // A mapper-identifier may not be redeclared in the current scope for the
22792 // same type or for a type that is compatible according to the base language
22793 // rules.
22794 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22795 OMPDeclareMapperDecl *PrevDMD = nullptr;
22796 bool InCompoundScope = true;
22797 if (S != nullptr) {
22798 // Find previous declaration with the same name not referenced in other
22799 // declarations.
22800 FunctionScopeInfo *ParentFn = getEnclosingFunction();
22801 InCompoundScope =
22802 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22803 LookupName(R&: Lookup, S);
22804 FilterLookupForScope(R&: Lookup, Ctx: DC, S, /*ConsiderLinkage=*/false,
22805 /*AllowInlineNamespace=*/false);
22806 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22807 LookupResult::Filter Filter = Lookup.makeFilter();
22808 while (Filter.hasNext()) {
22809 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Val: Filter.next());
22810 if (InCompoundScope) {
22811 auto I = UsedAsPrevious.find(Val: PrevDecl);
22812 if (I == UsedAsPrevious.end())
22813 UsedAsPrevious[PrevDecl] = false;
22814 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22815 UsedAsPrevious[D] = true;
22816 }
22817 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22818 PrevDecl->getLocation();
22819 }
22820 Filter.done();
22821 if (InCompoundScope) {
22822 for (const auto &PrevData : UsedAsPrevious) {
22823 if (!PrevData.second) {
22824 PrevDMD = PrevData.first;
22825 break;
22826 }
22827 }
22828 }
22829 } else if (PrevDeclInScope) {
22830 auto *PrevDMDInScope = PrevDMD =
22831 cast<OMPDeclareMapperDecl>(Val: PrevDeclInScope);
22832 do {
22833 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22834 PrevDMDInScope->getLocation();
22835 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22836 } while (PrevDMDInScope != nullptr);
22837 }
22838 const auto I = PreviousRedeclTypes.find(Val: MapperType.getCanonicalType());
22839 bool Invalid = false;
22840 if (I != PreviousRedeclTypes.end()) {
22841 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22842 << MapperType << Name;
22843 Diag(I->second, diag::note_previous_definition);
22844 Invalid = true;
22845 }
22846 // Build expressions for implicit maps of data members with 'default'
22847 // mappers.
22848 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(),
22849 Clauses.end());
22850 if (LangOpts.OpenMP >= 50)
22851 processImplicitMapsWithDefaultMappers(S&: *this, DSAStack, Clauses&: ClausesWithImplicit);
22852 auto *DMD =
22853 OMPDeclareMapperDecl::Create(C&: Context, DC, L: StartLoc, Name, T: MapperType, VarName: VN,
22854 Clauses: ClausesWithImplicit, PrevDeclInScope: PrevDMD);
22855 if (S)
22856 PushOnScopeChains(DMD, S);
22857 else
22858 DC->addDecl(DMD);
22859 DMD->setAccess(AS);
22860 if (Invalid)
22861 DMD->setInvalidDecl();
22862
22863 auto *VD = cast<DeclRefExpr>(Val: MapperVarRef)->getDecl();
22864 VD->setDeclContext(DMD);
22865 VD->setLexicalDeclContext(DMD);
22866 DMD->addDecl(VD);
22867 DMD->setMapperVarRef(MapperVarRef);
22868
22869 return DeclGroupPtrTy::make(P: DeclGroupRef(DMD));
22870}
22871
22872ExprResult
22873Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType,
22874 SourceLocation StartLoc,
22875 DeclarationName VN) {
22876 TypeSourceInfo *TInfo =
22877 Context.getTrivialTypeSourceInfo(T: MapperType, Loc: StartLoc);
22878 auto *VD = VarDecl::Create(Context, Context.getTranslationUnitDecl(),
22879 StartLoc, StartLoc, VN.getAsIdentifierInfo(),
22880 MapperType, TInfo, SC_None);
22881 if (S)
22882 PushOnScopeChains(D: VD, S, /*AddToContext=*/false);
22883 Expr *E = buildDeclRefExpr(*this, VD, MapperType, StartLoc);
22884 DSAStack->addDeclareMapperVarRef(Ref: E);
22885 return E;
22886}
22887
22888void Sema::ActOnOpenMPIteratorVarDecl(VarDecl *VD) {
22889 if (DSAStack->getDeclareMapperVarRef())
22890 DSAStack->addIteratorVarDecl(VD);
22891}
22892
22893bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
22894 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22895 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22896 if (const auto *DRE = cast_or_null<DeclRefExpr>(Val: Ref)) {
22897 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22898 return true;
22899 if (VD->isUsableInConstantExpressions(C: Context))
22900 return true;
22901 if (LangOpts.OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22902 return true;
22903 return false;
22904 }
22905 return true;
22906}
22907
22908const ValueDecl *Sema::getOpenMPDeclareMapperVarName() const {
22909 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22910 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22911}
22912
22913OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
22914 SourceLocation StartLoc,
22915 SourceLocation LParenLoc,
22916 SourceLocation EndLoc) {
22917 Expr *ValExpr = NumTeams;
22918 Stmt *HelperValStmt = nullptr;
22919
22920 // OpenMP [teams Constrcut, Restrictions]
22921 // The num_teams expression must evaluate to a positive integer value.
22922 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
22923 /*StrictlyPositive=*/true))
22924 return nullptr;
22925
22926 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22927 OpenMPDirectiveKind CaptureRegion =
22928 getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams, LangOpts.OpenMP);
22929 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22930 ValExpr = MakeFullExpr(Arg: ValExpr).get();
22931 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22932 ValExpr = tryBuildCapture(SemaRef&: *this, Capture: ValExpr, Captures).get();
22933 HelperValStmt = buildPreInits(Context, Captures);
22934 }
22935
22936 return new (Context) OMPNumTeamsClause(ValExpr, HelperValStmt, CaptureRegion,
22937 StartLoc, LParenLoc, EndLoc);
22938}
22939
22940OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
22941 SourceLocation StartLoc,
22942 SourceLocation LParenLoc,
22943 SourceLocation EndLoc) {
22944 Expr *ValExpr = ThreadLimit;
22945 Stmt *HelperValStmt = nullptr;
22946
22947 // OpenMP [teams Constrcut, Restrictions]
22948 // The thread_limit expression must evaluate to a positive integer value.
22949 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
22950 /*StrictlyPositive=*/true))
22951 return nullptr;
22952
22953 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22954 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
22955 DKind, OMPC_thread_limit, LangOpts.OpenMP);
22956 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22957 ValExpr = MakeFullExpr(Arg: ValExpr).get();
22958 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22959 ValExpr = tryBuildCapture(SemaRef&: *this, Capture: ValExpr, Captures).get();
22960 HelperValStmt = buildPreInits(Context, Captures);
22961 }
22962
22963 return new (Context) OMPThreadLimitClause(
22964 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22965}
22966
22967OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority,
22968 SourceLocation StartLoc,
22969 SourceLocation LParenLoc,
22970 SourceLocation EndLoc) {
22971 Expr *ValExpr = Priority;
22972 Stmt *HelperValStmt = nullptr;
22973 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22974
22975 // OpenMP [2.9.1, task Constrcut]
22976 // The priority-value is a non-negative numerical scalar expression.
22977 if (!isNonNegativeIntegerValue(
22978 ValExpr, *this, OMPC_priority,
22979 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22980 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22981 return nullptr;
22982
22983 return new (Context) OMPPriorityClause(ValExpr, HelperValStmt, CaptureRegion,
22984 StartLoc, LParenLoc, EndLoc);
22985}
22986
22987OMPClause *Sema::ActOnOpenMPGrainsizeClause(
22988 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22989 SourceLocation StartLoc, SourceLocation LParenLoc,
22990 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22991 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&
22992 "Unexpected grainsize modifier in OpenMP < 51.");
22993
22994 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22995 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22996 OMPC_GRAINSIZE_unknown);
22997 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22998 << Values << getOpenMPClauseName(OMPC_grainsize);
22999 return nullptr;
23000 }
23001
23002 Expr *ValExpr = Grainsize;
23003 Stmt *HelperValStmt = nullptr;
23004 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23005
23006 // OpenMP [2.9.2, taskloop Constrcut]
23007 // The parameter of the grainsize clause must be a positive integer
23008 // expression.
23009 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize,
23010 /*StrictlyPositive=*/true,
23011 /*BuildCapture=*/true,
23012 DSAStack->getCurrentDirective(),
23013 &CaptureRegion, &HelperValStmt))
23014 return nullptr;
23015
23016 return new (Context)
23017 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23018 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23019}
23020
23021OMPClause *Sema::ActOnOpenMPNumTasksClause(
23022 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
23023 SourceLocation StartLoc, SourceLocation LParenLoc,
23024 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23025 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&
23026 "Unexpected num_tasks modifier in OpenMP < 51.");
23027
23028 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
23029 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
23030 OMPC_NUMTASKS_unknown);
23031 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23032 << Values << getOpenMPClauseName(OMPC_num_tasks);
23033 return nullptr;
23034 }
23035
23036 Expr *ValExpr = NumTasks;
23037 Stmt *HelperValStmt = nullptr;
23038 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23039
23040 // OpenMP [2.9.2, taskloop Constrcut]
23041 // The parameter of the num_tasks clause must be a positive integer
23042 // expression.
23043 if (!isNonNegativeIntegerValue(
23044 ValExpr, *this, OMPC_num_tasks,
23045 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
23046 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23047 return nullptr;
23048
23049 return new (Context)
23050 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23051 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23052}
23053
23054OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
23055 SourceLocation LParenLoc,
23056 SourceLocation EndLoc) {
23057 // OpenMP [2.13.2, critical construct, Description]
23058 // ... where hint-expression is an integer constant expression that evaluates
23059 // to a valid lock hint.
23060 ExprResult HintExpr =
23061 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
23062 if (HintExpr.isInvalid())
23063 return nullptr;
23064 return new (Context)
23065 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
23066}
23067
23068/// Tries to find omp_event_handle_t type.
23069static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
23070 DSAStackTy *Stack) {
23071 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
23072 if (!OMPEventHandleT.isNull())
23073 return true;
23074 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_event_handle_t");
23075 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
23076 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23077 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
23078 return false;
23079 }
23080 Stack->setOMPEventHandleT(PT.get());
23081 return true;
23082}
23083
23084OMPClause *Sema::ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc,
23085 SourceLocation LParenLoc,
23086 SourceLocation EndLoc) {
23087 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
23088 !Evt->isInstantiationDependent() &&
23089 !Evt->containsUnexpandedParameterPack()) {
23090 if (!findOMPEventHandleT(S&: *this, Loc: Evt->getExprLoc(), DSAStack))
23091 return nullptr;
23092 // OpenMP 5.0, 2.10.1 task Construct.
23093 // event-handle is a variable of the omp_event_handle_t type.
23094 auto *Ref = dyn_cast<DeclRefExpr>(Val: Evt->IgnoreParenImpCasts());
23095 if (!Ref) {
23096 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23097 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23098 return nullptr;
23099 }
23100 auto *VD = dyn_cast_or_null<VarDecl>(Val: Ref->getDecl());
23101 if (!VD) {
23102 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23103 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23104 return nullptr;
23105 }
23106 if (!Context.hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
23107 T2: VD->getType()) ||
23108 VD->getType().isConstant(Context)) {
23109 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23110 << "omp_event_handle_t" << 1 << VD->getType()
23111 << Evt->getSourceRange();
23112 return nullptr;
23113 }
23114 // OpenMP 5.0, 2.10.1 task Construct
23115 // [detach clause]... The event-handle will be considered as if it was
23116 // specified on a firstprivate clause.
23117 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
23118 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
23119 DVar.RefExpr) {
23120 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
23121 << getOpenMPClauseName(DVar.CKind)
23122 << getOpenMPClauseName(OMPC_firstprivate);
23123 reportOriginalDsa(*this, DSAStack, VD, DVar);
23124 return nullptr;
23125 }
23126 }
23127
23128 return new (Context) OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
23129}
23130
23131OMPClause *Sema::ActOnOpenMPDistScheduleClause(
23132 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
23133 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
23134 SourceLocation EndLoc) {
23135 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
23136 std::string Values;
23137 Values += "'";
23138 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
23139 Values += "'";
23140 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23141 << Values << getOpenMPClauseName(OMPC_dist_schedule);
23142 return nullptr;
23143 }
23144 Expr *ValExpr = ChunkSize;
23145 Stmt *HelperValStmt = nullptr;
23146 if (ChunkSize) {
23147 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
23148 !ChunkSize->isInstantiationDependent() &&
23149 !ChunkSize->containsUnexpandedParameterPack()) {
23150 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
23151 ExprResult Val =
23152 PerformOpenMPImplicitIntegerConversion(Loc: ChunkSizeLoc, Op: ChunkSize);
23153 if (Val.isInvalid())
23154 return nullptr;
23155
23156 ValExpr = Val.get();
23157
23158 // OpenMP [2.7.1, Restrictions]
23159 // chunk_size must be a loop invariant integer expression with a positive
23160 // value.
23161 if (std::optional<llvm::APSInt> Result =
23162 ValExpr->getIntegerConstantExpr(Ctx: Context)) {
23163 if (Result->isSigned() && !Result->isStrictlyPositive()) {
23164 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
23165 << "dist_schedule" << ChunkSize->getSourceRange();
23166 return nullptr;
23167 }
23168 } else if (getOpenMPCaptureRegionForClause(
23169 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
23170 LangOpts.OpenMP) != OMPD_unknown &&
23171 !CurContext->isDependentContext()) {
23172 ValExpr = MakeFullExpr(Arg: ValExpr).get();
23173 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23174 ValExpr = tryBuildCapture(SemaRef&: *this, Capture: ValExpr, Captures).get();
23175 HelperValStmt = buildPreInits(Context, Captures);
23176 }
23177 }
23178 }
23179
23180 return new (Context)
23181 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
23182 Kind, ValExpr, HelperValStmt);
23183}
23184
23185OMPClause *Sema::ActOnOpenMPDefaultmapClause(
23186 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
23187 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
23188 SourceLocation KindLoc, SourceLocation EndLoc) {
23189 if (getLangOpts().OpenMP < 50) {
23190 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
23191 Kind != OMPC_DEFAULTMAP_scalar) {
23192 std::string Value;
23193 SourceLocation Loc;
23194 Value += "'";
23195 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
23196 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23197 OMPC_DEFAULTMAP_MODIFIER_tofrom);
23198 Loc = MLoc;
23199 } else {
23200 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23201 OMPC_DEFAULTMAP_scalar);
23202 Loc = KindLoc;
23203 }
23204 Value += "'";
23205 Diag(Loc, diag::err_omp_unexpected_clause_value)
23206 << Value << getOpenMPClauseName(OMPC_defaultmap);
23207 return nullptr;
23208 }
23209 } else {
23210 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
23211 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
23212 (LangOpts.OpenMP >= 50 && KindLoc.isInvalid());
23213 if (!isDefaultmapKind || !isDefaultmapModifier) {
23214 StringRef KindValue = "'scalar', 'aggregate', 'pointer'";
23215 if (LangOpts.OpenMP == 50) {
23216 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
23217 "'firstprivate', 'none', 'default'";
23218 if (!isDefaultmapKind && isDefaultmapModifier) {
23219 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23220 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23221 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23222 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23223 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23224 } else {
23225 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23226 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23227 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23228 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23229 }
23230 } else {
23231 StringRef ModifierValue =
23232 "'alloc', 'from', 'to', 'tofrom', "
23233 "'firstprivate', 'none', 'default', 'present'";
23234 if (!isDefaultmapKind && isDefaultmapModifier) {
23235 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23236 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23237 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23238 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23239 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23240 } else {
23241 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23242 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23243 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23244 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23245 }
23246 }
23247 return nullptr;
23248 }
23249
23250 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
23251 // At most one defaultmap clause for each category can appear on the
23252 // directive.
23253 if (DSAStack->checkDefaultmapCategory(VariableCategory: Kind)) {
23254 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
23255 return nullptr;
23256 }
23257 }
23258 if (Kind == OMPC_DEFAULTMAP_unknown) {
23259 // Variable category is not specified - mark all categories.
23260 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_aggregate, Loc: StartLoc);
23261 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_scalar, Loc: StartLoc);
23262 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_pointer, Loc: StartLoc);
23263 } else {
23264 DSAStack->setDefaultDMAAttr(M, Kind, Loc: StartLoc);
23265 }
23266
23267 return new (Context)
23268 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
23269}
23270
23271bool Sema::ActOnStartOpenMPDeclareTargetContext(
23272 DeclareTargetContextInfo &DTCI) {
23273 DeclContext *CurLexicalContext = getCurLexicalContext();
23274 if (!CurLexicalContext->isFileContext() &&
23275 !CurLexicalContext->isExternCContext() &&
23276 !CurLexicalContext->isExternCXXContext() &&
23277 !isa<CXXRecordDecl>(Val: CurLexicalContext) &&
23278 !isa<ClassTemplateDecl>(Val: CurLexicalContext) &&
23279 !isa<ClassTemplatePartialSpecializationDecl>(Val: CurLexicalContext) &&
23280 !isa<ClassTemplateSpecializationDecl>(Val: CurLexicalContext)) {
23281 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
23282 return false;
23283 }
23284
23285 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23286 if (getLangOpts().HIP)
23287 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
23288
23289 DeclareTargetNesting.push_back(Elt: DTCI);
23290 return true;
23291}
23292
23293const Sema::DeclareTargetContextInfo
23294Sema::ActOnOpenMPEndDeclareTargetDirective() {
23295 assert(!DeclareTargetNesting.empty() &&
23296 "check isInOpenMPDeclareTargetContext() first!");
23297 return DeclareTargetNesting.pop_back_val();
23298}
23299
23300void Sema::ActOnFinishedOpenMPDeclareTargetContext(
23301 DeclareTargetContextInfo &DTCI) {
23302 for (auto &It : DTCI.ExplicitlyMapped)
23303 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
23304}
23305
23306void Sema::DiagnoseUnterminatedOpenMPDeclareTarget() {
23307 if (DeclareTargetNesting.empty())
23308 return;
23309 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23310 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
23311 << getOpenMPDirectiveName(DTCI.Kind);
23312}
23313
23314NamedDecl *Sema::lookupOpenMPDeclareTargetName(Scope *CurScope,
23315 CXXScopeSpec &ScopeSpec,
23316 const DeclarationNameInfo &Id) {
23317 LookupResult Lookup(*this, Id, LookupOrdinaryName);
23318 LookupParsedName(R&: Lookup, S: CurScope, SS: &ScopeSpec, AllowBuiltinCreation: true);
23319
23320 if (Lookup.isAmbiguous())
23321 return nullptr;
23322 Lookup.suppressDiagnostics();
23323
23324 if (!Lookup.isSingleResult()) {
23325 VarOrFuncDeclFilterCCC CCC(*this);
23326 if (TypoCorrection Corrected =
23327 CorrectTypo(Typo: Id, LookupKind: LookupOrdinaryName, S: CurScope, SS: nullptr, CCC,
23328 Mode: CTK_ErrorRecovery)) {
23329 diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
23330 << Id.getName());
23331 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
23332 return nullptr;
23333 }
23334
23335 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
23336 return nullptr;
23337 }
23338
23339 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
23340 if (!isa<VarDecl>(Val: ND) && !isa<FunctionDecl>(Val: ND) &&
23341 !isa<FunctionTemplateDecl>(Val: ND)) {
23342 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
23343 return nullptr;
23344 }
23345 return ND;
23346}
23347
23348void Sema::ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
23349 OMPDeclareTargetDeclAttr::MapTypeTy MT,
23350 DeclareTargetContextInfo &DTCI) {
23351 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
23352 isa<FunctionTemplateDecl>(ND)) &&
23353 "Expected variable, function or function template.");
23354
23355 // Diagnose marking after use as it may lead to incorrect diagnosis and
23356 // codegen.
23357 if (LangOpts.OpenMP >= 50 &&
23358 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
23359 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
23360
23361 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23362 if (getLangOpts().HIP)
23363 Diag(Loc, diag::warn_hip_omp_target_directives);
23364
23365 // Explicit declare target lists have precedence.
23366 const unsigned Level = -1;
23367
23368 auto *VD = cast<ValueDecl>(Val: ND);
23369 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23370 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23371 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
23372 (*ActiveAttr)->getLevel() == Level) {
23373 Diag(Loc, diag::err_omp_device_type_mismatch)
23374 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
23375 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23376 (*ActiveAttr)->getDevType());
23377 return;
23378 }
23379 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
23380 (*ActiveAttr)->getLevel() == Level) {
23381 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
23382 return;
23383 }
23384
23385 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
23386 return;
23387
23388 Expr *IndirectE = nullptr;
23389 bool IsIndirect = false;
23390 if (DTCI.Indirect) {
23391 IndirectE = *DTCI.Indirect;
23392 if (!IndirectE)
23393 IsIndirect = true;
23394 }
23395 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23396 Context, MT, DTCI.DT, IndirectE, IsIndirect, Level,
23397 SourceRange(Loc, Loc));
23398 ND->addAttr(A: A);
23399 if (ASTMutationListener *ML = Context.getASTMutationListener())
23400 ML->DeclarationMarkedOpenMPDeclareTarget(D: ND, Attr: A);
23401 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
23402 if (auto *VD = dyn_cast<VarDecl>(Val: ND);
23403 LangOpts.OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
23404 VD->hasGlobalStorage())
23405 ActOnOpenMPDeclareTargetInitializer(ND);
23406}
23407
23408static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
23409 Sema &SemaRef, Decl *D) {
23410 if (!D || !isa<VarDecl>(Val: D))
23411 return;
23412 auto *VD = cast<VarDecl>(Val: D);
23413 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
23414 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
23415 if (SemaRef.LangOpts.OpenMP >= 50 &&
23416 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23417 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
23418 VD->hasGlobalStorage()) {
23419 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
23420 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
23421 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23422 // If a lambda declaration and definition appears between a
23423 // declare target directive and the matching end declare target
23424 // directive, all variables that are captured by the lambda
23425 // expression must also appear in a to clause.
23426 SemaRef.Diag(VD->getLocation(),
23427 diag::err_omp_lambda_capture_in_declare_target_not_to);
23428 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
23429 << VD << 0 << SR;
23430 return;
23431 }
23432 }
23433 if (MapTy)
23434 return;
23435 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
23436 SemaRef.Diag(SL, diag::note_used_here) << SR;
23437}
23438
23439static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
23440 Sema &SemaRef, DSAStackTy *Stack,
23441 ValueDecl *VD) {
23442 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23443 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
23444 /*FullCheck=*/false);
23445}
23446
23447void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
23448 SourceLocation IdLoc) {
23449 if (!D || D->isInvalidDecl())
23450 return;
23451 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
23452 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
23453 if (auto *VD = dyn_cast<VarDecl>(Val: D)) {
23454 // Only global variables can be marked as declare target.
23455 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23456 !VD->isStaticDataMember())
23457 return;
23458 // 2.10.6: threadprivate variable cannot appear in a declare target
23459 // directive.
23460 if (DSAStack->isThreadPrivate(D: VD)) {
23461 Diag(SL, diag::err_omp_threadprivate_in_target);
23462 reportOriginalDsa(*this, DSAStack, VD, DSAStack->getTopDSA(VD, false));
23463 return;
23464 }
23465 }
23466 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: D))
23467 D = FTD->getTemplatedDecl();
23468 if (auto *FD = dyn_cast<FunctionDecl>(Val: D)) {
23469 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23470 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23471 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23472 Diag(IdLoc, diag::err_omp_function_in_link_clause);
23473 Diag(FD->getLocation(), diag::note_defined_here) << FD;
23474 return;
23475 }
23476 }
23477 if (auto *VD = dyn_cast<ValueDecl>(Val: D)) {
23478 // Problem if any with var declared with incomplete type will be reported
23479 // as normal, so no need to check it here.
23480 if ((E || !VD->getType()->isIncompleteType()) &&
23481 !checkValueDeclInTarget(SL, SR, SemaRef&: *this, DSAStack, VD))
23482 return;
23483 if (!E && isInOpenMPDeclareTargetContext()) {
23484 // Checking declaration inside declare target region.
23485 if (isa<VarDecl>(Val: D) || isa<FunctionDecl>(Val: D) ||
23486 isa<FunctionTemplateDecl>(Val: D)) {
23487 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23488 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23489 unsigned Level = DeclareTargetNesting.size();
23490 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23491 return;
23492 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23493 Expr *IndirectE = nullptr;
23494 bool IsIndirect = false;
23495 if (DTCI.Indirect) {
23496 IndirectE = *DTCI.Indirect;
23497 if (!IndirectE)
23498 IsIndirect = true;
23499 }
23500 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23501 Context,
23502 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23503 : OMPDeclareTargetDeclAttr::MT_To,
23504 DTCI.DT, IndirectE, IsIndirect, Level,
23505 SourceRange(DTCI.Loc, DTCI.Loc));
23506 D->addAttr(A: A);
23507 if (ASTMutationListener *ML = Context.getASTMutationListener())
23508 ML->DeclarationMarkedOpenMPDeclareTarget(D, Attr: A);
23509 }
23510 return;
23511 }
23512 }
23513 if (!E)
23514 return;
23515 checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D);
23516}
23517
23518/// This class visits every VarDecl that the initializer references and adds
23519/// OMPDeclareTargetDeclAttr to each of them.
23520class GlobalDeclRefChecker final
23521 : public StmtVisitor<GlobalDeclRefChecker> {
23522 SmallVector<VarDecl *> DeclVector;
23523 Attr *A;
23524
23525public:
23526 /// A StmtVisitor class function that visits all DeclRefExpr and adds
23527 /// OMPDeclareTargetDeclAttr to them.
23528 void VisitDeclRefExpr(DeclRefExpr *Node) {
23529 if (auto *VD = dyn_cast<VarDecl>(Val: Node->getDecl())) {
23530 VD->addAttr(A);
23531 DeclVector.push_back(Elt: VD);
23532 }
23533 }
23534 /// A function that iterates across each of the Expr's children.
23535 void VisitExpr(Expr *Ex) {
23536 for (auto *Child : Ex->children()) {
23537 Visit(Child);
23538 }
23539 }
23540 /// A function that keeps a record of all the Decls that are variables, has
23541 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23542 /// each Decl one at a time and use the inherited 'visit' functions to look
23543 /// for DeclRefExpr.
23544 void declareTargetInitializer(Decl *TD) {
23545 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
23546 DeclVector.push_back(Elt: cast<VarDecl>(Val: TD));
23547 while (!DeclVector.empty()) {
23548 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23549 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
23550 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
23551 if (Expr *Ex = TargetVarDecl->getInit())
23552 Visit(Ex);
23553 }
23554 }
23555 }
23556};
23557
23558/// Adding OMPDeclareTargetDeclAttr to variables with static storage
23559/// duration that are referenced in the initializer expression list of
23560/// variables with static storage duration in declare target directive.
23561void Sema::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) {
23562 GlobalDeclRefChecker Checker;
23563 if (isa<VarDecl>(Val: TargetDecl))
23564 Checker.declareTargetInitializer(TD: TargetDecl);
23565}
23566
23567OMPClause *Sema::ActOnOpenMPToClause(
23568 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23569 ArrayRef<SourceLocation> MotionModifiersLoc,
23570 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23571 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23572 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23573 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23574 OMPC_MOTION_MODIFIER_unknown};
23575 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23576
23577 // Process motion-modifiers, flag errors for duplicate modifiers.
23578 unsigned Count = 0;
23579 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23580 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23581 llvm::is_contained(Range&: Modifiers, Element: MotionModifiers[I])) {
23582 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23583 continue;
23584 }
23585 assert(Count < NumberOfOMPMotionModifiers &&
23586 "Modifiers exceed the allowed number of motion modifiers");
23587 Modifiers[Count] = MotionModifiers[I];
23588 ModifiersLoc[Count] = MotionModifiersLoc[I];
23589 ++Count;
23590 }
23591
23592 MappableVarListInfo MVLI(VarList);
23593 checkMappableExpressionList(*this, DSAStack, OMPC_to, MVLI, Locs.StartLoc,
23594 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23595 if (MVLI.ProcessedVarList.empty())
23596 return nullptr;
23597
23598 return OMPToClause::Create(
23599 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23600 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23601 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
23602}
23603
23604OMPClause *Sema::ActOnOpenMPFromClause(
23605 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23606 ArrayRef<SourceLocation> MotionModifiersLoc,
23607 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23608 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23609 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23610 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23611 OMPC_MOTION_MODIFIER_unknown};
23612 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23613
23614 // Process motion-modifiers, flag errors for duplicate modifiers.
23615 unsigned Count = 0;
23616 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23617 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23618 llvm::is_contained(Range&: Modifiers, Element: MotionModifiers[I])) {
23619 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23620 continue;
23621 }
23622 assert(Count < NumberOfOMPMotionModifiers &&
23623 "Modifiers exceed the allowed number of motion modifiers");
23624 Modifiers[Count] = MotionModifiers[I];
23625 ModifiersLoc[Count] = MotionModifiersLoc[I];
23626 ++Count;
23627 }
23628
23629 MappableVarListInfo MVLI(VarList);
23630 checkMappableExpressionList(*this, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
23631 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23632 if (MVLI.ProcessedVarList.empty())
23633 return nullptr;
23634
23635 return OMPFromClause::Create(
23636 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23637 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23638 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
23639}
23640
23641OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
23642 const OMPVarListLocTy &Locs) {
23643 MappableVarListInfo MVLI(VarList);
23644 SmallVector<Expr *, 8> PrivateCopies;
23645 SmallVector<Expr *, 8> Inits;
23646
23647 for (Expr *RefExpr : VarList) {
23648 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
23649 SourceLocation ELoc;
23650 SourceRange ERange;
23651 Expr *SimpleRefExpr = RefExpr;
23652 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange);
23653 if (Res.second) {
23654 // It will be analyzed later.
23655 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
23656 PrivateCopies.push_back(Elt: nullptr);
23657 Inits.push_back(Elt: nullptr);
23658 }
23659 ValueDecl *D = Res.first;
23660 if (!D)
23661 continue;
23662
23663 QualType Type = D->getType();
23664 Type = Type.getNonReferenceType().getUnqualifiedType();
23665
23666 auto *VD = dyn_cast<VarDecl>(Val: D);
23667
23668 // Item should be a pointer or reference to pointer.
23669 if (!Type->isPointerType()) {
23670 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23671 << 0 << RefExpr->getSourceRange();
23672 continue;
23673 }
23674
23675 // Build the private variable and the expression that refers to it.
23676 auto VDPrivate =
23677 buildVarDecl(*this, ELoc, Type, D->getName(),
23678 D->hasAttrs() ? &D->getAttrs() : nullptr,
23679 VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
23680 if (VDPrivate->isInvalidDecl())
23681 continue;
23682
23683 CurContext->addDecl(D: VDPrivate);
23684 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
23685 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23686
23687 // Add temporary variable to initialize the private copy of the pointer.
23688 VarDecl *VDInit =
23689 buildVarDecl(SemaRef&: *this, Loc: RefExpr->getExprLoc(), Type, Name: ".devptr.temp");
23690 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
23691 S&: *this, D: VDInit, Ty: RefExpr->getType(), Loc: RefExpr->getExprLoc());
23692 AddInitializerToDecl(dcl: VDPrivate,
23693 init: DefaultLvalueConversion(VDInitRefExpr).get(),
23694 /*DirectInit=*/false);
23695
23696 // If required, build a capture to implement the privatization initialized
23697 // with the current list item value.
23698 DeclRefExpr *Ref = nullptr;
23699 if (!VD)
23700 Ref = buildCapture(S&: *this, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
23701 MVLI.ProcessedVarList.push_back(Elt: VD ? RefExpr->IgnoreParens() : Ref);
23702 PrivateCopies.push_back(VDPrivateRefExpr);
23703 Inits.push_back(VDInitRefExpr);
23704
23705 // We need to add a data sharing attribute for this variable to make sure it
23706 // is correctly captured. A variable that shows up in a use_device_ptr has
23707 // similar properties of a first private variable.
23708 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23709
23710 // Create a mappable component for the list item. List items in this clause
23711 // only need a component.
23712 MVLI.VarBaseDeclarations.push_back(Elt: D);
23713 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
23714 MVLI.VarComponents.back().emplace_back(Args&: SimpleRefExpr, Args&: D,
23715 /*IsNonContiguous=*/Args: false);
23716 }
23717
23718 if (MVLI.ProcessedVarList.empty())
23719 return nullptr;
23720
23721 return OMPUseDevicePtrClause::Create(
23722 Context, Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
23723 MVLI.VarBaseDeclarations, MVLI.VarComponents);
23724}
23725
23726OMPClause *Sema::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
23727 const OMPVarListLocTy &Locs) {
23728 MappableVarListInfo MVLI(VarList);
23729
23730 for (Expr *RefExpr : VarList) {
23731 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
23732 SourceLocation ELoc;
23733 SourceRange ERange;
23734 Expr *SimpleRefExpr = RefExpr;
23735 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange,
23736 /*AllowArraySection=*/true);
23737 if (Res.second) {
23738 // It will be analyzed later.
23739 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
23740 }
23741 ValueDecl *D = Res.first;
23742 if (!D)
23743 continue;
23744 auto *VD = dyn_cast<VarDecl>(Val: D);
23745
23746 // If required, build a capture to implement the privatization initialized
23747 // with the current list item value.
23748 DeclRefExpr *Ref = nullptr;
23749 if (!VD)
23750 Ref = buildCapture(S&: *this, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
23751 MVLI.ProcessedVarList.push_back(Elt: VD ? RefExpr->IgnoreParens() : Ref);
23752
23753 // We need to add a data sharing attribute for this variable to make sure it
23754 // is correctly captured. A variable that shows up in a use_device_addr has
23755 // similar properties of a first private variable.
23756 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23757
23758 // Create a mappable component for the list item. List items in this clause
23759 // only need a component.
23760 MVLI.VarBaseDeclarations.push_back(Elt: D);
23761 MVLI.VarComponents.emplace_back();
23762 Expr *Component = SimpleRefExpr;
23763 if (VD && (isa<OMPArraySectionExpr>(Val: RefExpr->IgnoreParenImpCasts()) ||
23764 isa<ArraySubscriptExpr>(Val: RefExpr->IgnoreParenImpCasts())))
23765 Component = DefaultFunctionArrayLvalueConversion(E: SimpleRefExpr).get();
23766 MVLI.VarComponents.back().emplace_back(Args&: Component, Args&: D,
23767 /*IsNonContiguous=*/Args: false);
23768 }
23769
23770 if (MVLI.ProcessedVarList.empty())
23771 return nullptr;
23772
23773 return OMPUseDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23774 MVLI.VarBaseDeclarations,
23775 MVLI.VarComponents);
23776}
23777
23778OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
23779 const OMPVarListLocTy &Locs) {
23780 MappableVarListInfo MVLI(VarList);
23781 for (Expr *RefExpr : VarList) {
23782 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
23783 SourceLocation ELoc;
23784 SourceRange ERange;
23785 Expr *SimpleRefExpr = RefExpr;
23786 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange);
23787 if (Res.second) {
23788 // It will be analyzed later.
23789 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
23790 }
23791 ValueDecl *D = Res.first;
23792 if (!D)
23793 continue;
23794
23795 QualType Type = D->getType();
23796 // item should be a pointer or array or reference to pointer or array
23797 if (!Type.getNonReferenceType()->isPointerType() &&
23798 !Type.getNonReferenceType()->isArrayType()) {
23799 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23800 << 0 << RefExpr->getSourceRange();
23801 continue;
23802 }
23803
23804 // Check if the declaration in the clause does not show up in any data
23805 // sharing attribute.
23806 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23807 if (isOpenMPPrivate(DVar.CKind)) {
23808 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23809 << getOpenMPClauseName(DVar.CKind)
23810 << getOpenMPClauseName(OMPC_is_device_ptr)
23811 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23812 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
23813 continue;
23814 }
23815
23816 const Expr *ConflictExpr;
23817 if (DSAStack->checkMappableExprComponentListsForDecl(
23818 VD: D, /*CurrentRegionOnly=*/true,
23819 Check: [&ConflictExpr](
23820 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23821 OpenMPClauseKind) -> bool {
23822 ConflictExpr = R.front().getAssociatedExpression();
23823 return true;
23824 })) {
23825 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23826 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23827 << ConflictExpr->getSourceRange();
23828 continue;
23829 }
23830
23831 // Store the components in the stack so that they can be used to check
23832 // against other clauses later on.
23833 OMPClauseMappableExprCommon::MappableComponent MC(
23834 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23835 DSAStack->addMappableExpressionComponents(
23836 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23837
23838 // Record the expression we've just processed.
23839 MVLI.ProcessedVarList.push_back(Elt: SimpleRefExpr);
23840
23841 // Create a mappable component for the list item. List items in this clause
23842 // only need a component. We use a null declaration to signal fields in
23843 // 'this'.
23844 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23845 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23846 "Unexpected device pointer expression!");
23847 MVLI.VarBaseDeclarations.push_back(
23848 Elt: isa<DeclRefExpr>(Val: SimpleRefExpr) ? D : nullptr);
23849 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
23850 MVLI.VarComponents.back().push_back(Elt: MC);
23851 }
23852
23853 if (MVLI.ProcessedVarList.empty())
23854 return nullptr;
23855
23856 return OMPIsDevicePtrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23857 MVLI.VarBaseDeclarations,
23858 MVLI.VarComponents);
23859}
23860
23861OMPClause *Sema::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
23862 const OMPVarListLocTy &Locs) {
23863 MappableVarListInfo MVLI(VarList);
23864 for (Expr *RefExpr : VarList) {
23865 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23866 SourceLocation ELoc;
23867 SourceRange ERange;
23868 Expr *SimpleRefExpr = RefExpr;
23869 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange,
23870 /*AllowArraySection=*/true);
23871 if (Res.second) {
23872 // It will be analyzed later.
23873 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
23874 }
23875 ValueDecl *D = Res.first;
23876 if (!D)
23877 continue;
23878
23879 // Check if the declaration in the clause does not show up in any data
23880 // sharing attribute.
23881 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23882 if (isOpenMPPrivate(DVar.CKind)) {
23883 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23884 << getOpenMPClauseName(DVar.CKind)
23885 << getOpenMPClauseName(OMPC_has_device_addr)
23886 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23887 reportOriginalDsa(SemaRef&: *this, DSAStack, D, DVar);
23888 continue;
23889 }
23890
23891 const Expr *ConflictExpr;
23892 if (DSAStack->checkMappableExprComponentListsForDecl(
23893 VD: D, /*CurrentRegionOnly=*/true,
23894 Check: [&ConflictExpr](
23895 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23896 OpenMPClauseKind) -> bool {
23897 ConflictExpr = R.front().getAssociatedExpression();
23898 return true;
23899 })) {
23900 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23901 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23902 << ConflictExpr->getSourceRange();
23903 continue;
23904 }
23905
23906 // Store the components in the stack so that they can be used to check
23907 // against other clauses later on.
23908 Expr *Component = SimpleRefExpr;
23909 auto *VD = dyn_cast<VarDecl>(Val: D);
23910 if (VD && (isa<OMPArraySectionExpr>(Val: RefExpr->IgnoreParenImpCasts()) ||
23911 isa<ArraySubscriptExpr>(Val: RefExpr->IgnoreParenImpCasts())))
23912 Component = DefaultFunctionArrayLvalueConversion(E: SimpleRefExpr).get();
23913 OMPClauseMappableExprCommon::MappableComponent MC(
23914 Component, D, /*IsNonContiguous=*/false);
23915 DSAStack->addMappableExpressionComponents(
23916 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23917
23918 // Record the expression we've just processed.
23919 if (!VD && !CurContext->isDependentContext()) {
23920 DeclRefExpr *Ref =
23921 buildCapture(S&: *this, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
23922 assert(Ref && "has_device_addr capture failed");
23923 MVLI.ProcessedVarList.push_back(Ref);
23924 } else
23925 MVLI.ProcessedVarList.push_back(Elt: RefExpr->IgnoreParens());
23926
23927 // Create a mappable component for the list item. List items in this clause
23928 // only need a component. We use a null declaration to signal fields in
23929 // 'this'.
23930 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23931 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23932 "Unexpected device pointer expression!");
23933 MVLI.VarBaseDeclarations.push_back(
23934 Elt: isa<DeclRefExpr>(Val: SimpleRefExpr) ? D : nullptr);
23935 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
23936 MVLI.VarComponents.back().push_back(Elt: MC);
23937 }
23938
23939 if (MVLI.ProcessedVarList.empty())
23940 return nullptr;
23941
23942 return OMPHasDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23943 MVLI.VarBaseDeclarations,
23944 MVLI.VarComponents);
23945}
23946
23947OMPClause *Sema::ActOnOpenMPAllocateClause(
23948 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23949 SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
23950 if (Allocator) {
23951 // OpenMP [2.11.4 allocate Clause, Description]
23952 // allocator is an expression of omp_allocator_handle_t type.
23953 if (!findOMPAllocatorHandleT(S&: *this, Loc: Allocator->getExprLoc(), DSAStack))
23954 return nullptr;
23955
23956 ExprResult AllocatorRes = DefaultLvalueConversion(E: Allocator);
23957 if (AllocatorRes.isInvalid())
23958 return nullptr;
23959 AllocatorRes = PerformImplicitConversion(From: AllocatorRes.get(),
23960 DSAStack->getOMPAllocatorHandleT(),
23961 Action: Sema::AA_Initializing,
23962 /*AllowExplicit=*/true);
23963 if (AllocatorRes.isInvalid())
23964 return nullptr;
23965 Allocator = AllocatorRes.get();
23966 } else {
23967 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23968 // allocate clauses that appear on a target construct or on constructs in a
23969 // target region must specify an allocator expression unless a requires
23970 // directive with the dynamic_allocators clause is present in the same
23971 // compilation unit.
23972 if (LangOpts.OpenMPIsTargetDevice &&
23973 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23974 targetDiag(StartLoc, diag::err_expected_allocator_expression);
23975 }
23976 // Analyze and build list of variables.
23977 SmallVector<Expr *, 8> Vars;
23978 for (Expr *RefExpr : VarList) {
23979 assert(RefExpr && "NULL expr in OpenMP private clause.");
23980 SourceLocation ELoc;
23981 SourceRange ERange;
23982 Expr *SimpleRefExpr = RefExpr;
23983 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange);
23984 if (Res.second) {
23985 // It will be analyzed later.
23986 Vars.push_back(Elt: RefExpr);
23987 }
23988 ValueDecl *D = Res.first;
23989 if (!D)
23990 continue;
23991
23992 auto *VD = dyn_cast<VarDecl>(Val: D);
23993 DeclRefExpr *Ref = nullptr;
23994 if (!VD && !CurContext->isDependentContext())
23995 Ref = buildCapture(S&: *this, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
23996 Vars.push_back(Elt: (VD || CurContext->isDependentContext())
23997 ? RefExpr->IgnoreParens()
23998 : Ref);
23999 }
24000
24001 if (Vars.empty())
24002 return nullptr;
24003
24004 if (Allocator)
24005 DSAStack->addInnerAllocatorExpr(E: Allocator);
24006 return OMPAllocateClause::Create(C: Context, StartLoc, LParenLoc, Allocator,
24007 ColonLoc, EndLoc, VL: Vars);
24008}
24009
24010OMPClause *Sema::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
24011 SourceLocation StartLoc,
24012 SourceLocation LParenLoc,
24013 SourceLocation EndLoc) {
24014 SmallVector<Expr *, 8> Vars;
24015 for (Expr *RefExpr : VarList) {
24016 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24017 SourceLocation ELoc;
24018 SourceRange ERange;
24019 Expr *SimpleRefExpr = RefExpr;
24020 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange);
24021 if (Res.second)
24022 // It will be analyzed later.
24023 Vars.push_back(Elt: RefExpr);
24024 ValueDecl *D = Res.first;
24025 if (!D)
24026 continue;
24027
24028 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
24029 // A list-item cannot appear in more than one nontemporal clause.
24030 if (const Expr *PrevRef =
24031 DSAStack->addUniqueNontemporal(D, NewDE: SimpleRefExpr)) {
24032 Diag(ELoc, diag::err_omp_used_in_clause_twice)
24033 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
24034 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
24035 << getOpenMPClauseName(OMPC_nontemporal);
24036 continue;
24037 }
24038
24039 Vars.push_back(Elt: RefExpr);
24040 }
24041
24042 if (Vars.empty())
24043 return nullptr;
24044
24045 return OMPNontemporalClause::Create(C: Context, StartLoc, LParenLoc, EndLoc,
24046 VL: Vars);
24047}
24048
24049StmtResult Sema::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
24050 Stmt *AStmt, SourceLocation StartLoc,
24051 SourceLocation EndLoc) {
24052 if (!AStmt)
24053 return StmtError();
24054
24055 setFunctionHasBranchProtectedScope();
24056
24057 return OMPScopeDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt);
24058}
24059
24060OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
24061 SourceLocation StartLoc,
24062 SourceLocation LParenLoc,
24063 SourceLocation EndLoc) {
24064 SmallVector<Expr *, 8> Vars;
24065 for (Expr *RefExpr : VarList) {
24066 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24067 SourceLocation ELoc;
24068 SourceRange ERange;
24069 Expr *SimpleRefExpr = RefExpr;
24070 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange,
24071 /*AllowArraySection=*/true);
24072 if (Res.second)
24073 // It will be analyzed later.
24074 Vars.push_back(Elt: RefExpr);
24075 ValueDecl *D = Res.first;
24076 if (!D)
24077 continue;
24078
24079 const DSAStackTy::DSAVarData DVar =
24080 DSAStack->getTopDSA(D, /*FromParent=*/true);
24081 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24082 // A list item that appears in the inclusive or exclusive clause must appear
24083 // in a reduction clause with the inscan modifier on the enclosing
24084 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24085 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
24086 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24087 << RefExpr->getSourceRange();
24088
24089 if (DSAStack->getParentDirective() != OMPD_unknown)
24090 DSAStack->markDeclAsUsedInScanDirective(D);
24091 Vars.push_back(Elt: RefExpr);
24092 }
24093
24094 if (Vars.empty())
24095 return nullptr;
24096
24097 return OMPInclusiveClause::Create(C: Context, StartLoc, LParenLoc, EndLoc, VL: Vars);
24098}
24099
24100OMPClause *Sema::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
24101 SourceLocation StartLoc,
24102 SourceLocation LParenLoc,
24103 SourceLocation EndLoc) {
24104 SmallVector<Expr *, 8> Vars;
24105 for (Expr *RefExpr : VarList) {
24106 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24107 SourceLocation ELoc;
24108 SourceRange ERange;
24109 Expr *SimpleRefExpr = RefExpr;
24110 auto Res = getPrivateItem(S&: *this, RefExpr&: SimpleRefExpr, ELoc, ERange,
24111 /*AllowArraySection=*/true);
24112 if (Res.second)
24113 // It will be analyzed later.
24114 Vars.push_back(Elt: RefExpr);
24115 ValueDecl *D = Res.first;
24116 if (!D)
24117 continue;
24118
24119 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
24120 DSAStackTy::DSAVarData DVar;
24121 if (ParentDirective != OMPD_unknown)
24122 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
24123 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24124 // A list item that appears in the inclusive or exclusive clause must appear
24125 // in a reduction clause with the inscan modifier on the enclosing
24126 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24127 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
24128 DVar.Modifier != OMPC_REDUCTION_inscan) {
24129 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24130 << RefExpr->getSourceRange();
24131 } else {
24132 DSAStack->markDeclAsUsedInScanDirective(D);
24133 }
24134 Vars.push_back(Elt: RefExpr);
24135 }
24136
24137 if (Vars.empty())
24138 return nullptr;
24139
24140 return OMPExclusiveClause::Create(C: Context, StartLoc, LParenLoc, EndLoc, VL: Vars);
24141}
24142
24143/// Tries to find omp_alloctrait_t type.
24144static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
24145 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
24146 if (!OMPAlloctraitT.isNull())
24147 return true;
24148 IdentifierInfo &II = S.PP.getIdentifierTable().get(Name: "omp_alloctrait_t");
24149 ParsedType PT = S.getTypeName(II, NameLoc: Loc, S: S.getCurScope());
24150 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
24151 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
24152 return false;
24153 }
24154 Stack->setOMPAlloctraitT(PT.get());
24155 return true;
24156}
24157
24158OMPClause *Sema::ActOnOpenMPUsesAllocatorClause(
24159 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
24160 ArrayRef<UsesAllocatorsData> Data) {
24161 // OpenMP [2.12.5, target Construct]
24162 // allocator is an identifier of omp_allocator_handle_t type.
24163 if (!findOMPAllocatorHandleT(S&: *this, Loc: StartLoc, DSAStack))
24164 return nullptr;
24165 // OpenMP [2.12.5, target Construct]
24166 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
24167 if (llvm::any_of(
24168 Range&: Data,
24169 P: [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
24170 !findOMPAlloctraitT(S&: *this, Loc: StartLoc, DSAStack))
24171 return nullptr;
24172 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
24173 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
24174 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
24175 StringRef Allocator =
24176 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
24177 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
24178 PredefinedAllocators.insert(LookupSingleName(
24179 TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
24180 }
24181
24182 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
24183 for (const UsesAllocatorsData &D : Data) {
24184 Expr *AllocatorExpr = nullptr;
24185 // Check allocator expression.
24186 if (D.Allocator->isTypeDependent()) {
24187 AllocatorExpr = D.Allocator;
24188 } else {
24189 // Traits were specified - need to assign new allocator to the specified
24190 // allocator, so it must be an lvalue.
24191 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
24192 auto *DRE = dyn_cast<DeclRefExpr>(Val: AllocatorExpr);
24193 bool IsPredefinedAllocator = false;
24194 if (DRE) {
24195 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
24196 getAllocatorKind(*this, DSAStack, AllocatorExpr);
24197 IsPredefinedAllocator =
24198 AllocatorTy !=
24199 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
24200 }
24201 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
24202 QualType AllocatorExprType = AllocatorExpr->getType();
24203 bool IsTypeCompatible = IsPredefinedAllocator;
24204 IsTypeCompatible = IsTypeCompatible ||
24205 Context.hasSameUnqualifiedType(T1: AllocatorExprType,
24206 T2: OMPAllocatorHandleT);
24207 IsTypeCompatible =
24208 IsTypeCompatible ||
24209 Context.typesAreCompatible(T1: AllocatorExprType, T2: OMPAllocatorHandleT);
24210 bool IsNonConstantLValue =
24211 !AllocatorExprType.isConstant(Ctx: Context) && AllocatorExpr->isLValue();
24212 if (!DRE || !IsTypeCompatible ||
24213 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
24214 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
24215 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
24216 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
24217 continue;
24218 }
24219 // OpenMP [2.12.5, target Construct]
24220 // Predefined allocators appearing in a uses_allocators clause cannot have
24221 // traits specified.
24222 if (IsPredefinedAllocator && D.AllocatorTraits) {
24223 Diag(D.AllocatorTraits->getExprLoc(),
24224 diag::err_omp_predefined_allocator_with_traits)
24225 << D.AllocatorTraits->getSourceRange();
24226 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
24227 << cast<NamedDecl>(DRE->getDecl())->getName()
24228 << D.Allocator->getSourceRange();
24229 continue;
24230 }
24231 // OpenMP [2.12.5, target Construct]
24232 // Non-predefined allocators appearing in a uses_allocators clause must
24233 // have traits specified.
24234 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
24235 Diag(D.Allocator->getExprLoc(),
24236 diag::err_omp_nonpredefined_allocator_without_traits);
24237 continue;
24238 }
24239 // No allocator traits - just convert it to rvalue.
24240 if (!D.AllocatorTraits)
24241 AllocatorExpr = DefaultLvalueConversion(E: AllocatorExpr).get();
24242 DSAStack->addUsesAllocatorsDecl(
24243 DRE->getDecl(),
24244 IsPredefinedAllocator
24245 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24246 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
24247 }
24248 Expr *AllocatorTraitsExpr = nullptr;
24249 if (D.AllocatorTraits) {
24250 if (D.AllocatorTraits->isTypeDependent()) {
24251 AllocatorTraitsExpr = D.AllocatorTraits;
24252 } else {
24253 // OpenMP [2.12.5, target Construct]
24254 // Arrays that contain allocator traits that appear in a uses_allocators
24255 // clause must be constant arrays, have constant values and be defined
24256 // in the same scope as the construct in which the clause appears.
24257 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
24258 // Check that traits expr is a constant array.
24259 QualType TraitTy;
24260 if (const ArrayType *Ty =
24261 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
24262 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
24263 TraitTy = ConstArrayTy->getElementType();
24264 if (TraitTy.isNull() ||
24265 !(Context.hasSameUnqualifiedType(T1: TraitTy,
24266 DSAStack->getOMPAlloctraitT()) ||
24267 Context.typesAreCompatible(T1: TraitTy, DSAStack->getOMPAlloctraitT(),
24268 /*CompareUnqualified=*/true))) {
24269 Diag(D.AllocatorTraits->getExprLoc(),
24270 diag::err_omp_expected_array_alloctraits)
24271 << AllocatorTraitsExpr->getType();
24272 continue;
24273 }
24274 // Do not map by default allocator traits if it is a standalone
24275 // variable.
24276 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: AllocatorTraitsExpr))
24277 DSAStack->addUsesAllocatorsDecl(
24278 DRE->getDecl(),
24279 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
24280 }
24281 }
24282 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
24283 NewD.Allocator = AllocatorExpr;
24284 NewD.AllocatorTraits = AllocatorTraitsExpr;
24285 NewD.LParenLoc = D.LParenLoc;
24286 NewD.RParenLoc = D.RParenLoc;
24287 }
24288 return OMPUsesAllocatorsClause::Create(C: Context, StartLoc, LParenLoc, EndLoc,
24289 Data: NewData);
24290}
24291
24292OMPClause *Sema::ActOnOpenMPAffinityClause(
24293 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24294 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
24295 SmallVector<Expr *, 8> Vars;
24296 for (Expr *RefExpr : Locators) {
24297 assert(RefExpr && "NULL expr in OpenMP shared clause.");
24298 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr) || RefExpr->isTypeDependent()) {
24299 // It will be analyzed later.
24300 Vars.push_back(Elt: RefExpr);
24301 continue;
24302 }
24303
24304 SourceLocation ELoc = RefExpr->getExprLoc();
24305 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
24306
24307 if (!SimpleExpr->isLValue()) {
24308 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24309 << 1 << 0 << RefExpr->getSourceRange();
24310 continue;
24311 }
24312
24313 ExprResult Res;
24314 {
24315 Sema::TentativeAnalysisScope Trap(*this);
24316 Res = CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: SimpleExpr);
24317 }
24318 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(Val: SimpleExpr) &&
24319 !isa<OMPArrayShapingExpr>(Val: SimpleExpr)) {
24320 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24321 << 1 << 0 << RefExpr->getSourceRange();
24322 continue;
24323 }
24324 Vars.push_back(Elt: SimpleExpr);
24325 }
24326
24327 return OMPAffinityClause::Create(C: Context, StartLoc, LParenLoc, ColonLoc,
24328 EndLoc, Modifier, Locators: Vars);
24329}
24330
24331OMPClause *Sema::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
24332 SourceLocation KindLoc,
24333 SourceLocation StartLoc,
24334 SourceLocation LParenLoc,
24335 SourceLocation EndLoc) {
24336 if (Kind == OMPC_BIND_unknown) {
24337 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24338 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
24339 /*Last=*/unsigned(OMPC_BIND_unknown))
24340 << getOpenMPClauseName(OMPC_bind);
24341 return nullptr;
24342 }
24343
24344 return OMPBindClause::Create(C: Context, K: Kind, KLoc: KindLoc, StartLoc, LParenLoc,
24345 EndLoc);
24346}
24347
24348OMPClause *Sema::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
24349 SourceLocation StartLoc,
24350 SourceLocation LParenLoc,
24351 SourceLocation EndLoc) {
24352 Expr *ValExpr = Size;
24353 Stmt *HelperValStmt = nullptr;
24354
24355 // OpenMP [2.5, Restrictions]
24356 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24357 // value.
24358 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_ompx_dyn_cgroup_mem,
24359 /*StrictlyPositive=*/false))
24360 return nullptr;
24361
24362 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24363 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
24364 DKind, OMPC_ompx_dyn_cgroup_mem, LangOpts.OpenMP);
24365 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
24366 ValExpr = MakeFullExpr(Arg: ValExpr).get();
24367 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24368 ValExpr = tryBuildCapture(SemaRef&: *this, Capture: ValExpr, Captures).get();
24369 HelperValStmt = buildPreInits(Context, Captures);
24370 }
24371
24372 return new (Context) OMPXDynCGroupMemClause(
24373 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24374}
24375
24376OMPClause *Sema::ActOnOpenMPDoacrossClause(
24377 OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
24378 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
24379 SourceLocation LParenLoc, SourceLocation EndLoc) {
24380
24381 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
24382 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
24383 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
24384 DepType != OMPC_DOACROSS_source_omp_cur_iteration &&
24385 DepType != OMPC_DOACROSS_source) {
24386 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24387 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
24388 return nullptr;
24389 }
24390
24391 SmallVector<Expr *, 8> Vars;
24392 DSAStackTy::OperatorOffsetTy OpsOffs;
24393 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
24394 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
24395 SemaRef&: *this,
24396 IsSource: DepType == OMPC_DOACROSS_source ||
24397 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
24398 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
24399 VarList, DSAStack, EndLoc);
24400 Vars = VarOffset.Vars;
24401 OpsOffs = VarOffset.OpsOffs;
24402 TotalDepCount = VarOffset.TotalDepCount;
24403 auto *C = OMPDoacrossClause::Create(C: Context, StartLoc, LParenLoc, EndLoc,
24404 DepType, DepLoc, ColonLoc, VL: Vars,
24405 NumLoops: TotalDepCount.getZExtValue());
24406 if (DSAStack->isParentOrderedRegion())
24407 DSAStack->addDoacrossDependClause(C, OpsOffs);
24408 return C;
24409}
24410
24411OMPClause *Sema::ActOnOpenMPXAttributeClause(ArrayRef<const Attr *> Attrs,
24412 SourceLocation StartLoc,
24413 SourceLocation LParenLoc,
24414 SourceLocation EndLoc) {
24415 return new (Context) OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
24416}
24417
24418OMPClause *Sema::ActOnOpenMPXBareClause(SourceLocation StartLoc,
24419 SourceLocation EndLoc) {
24420 return new (Context) OMPXBareClause(StartLoc, EndLoc);
24421}
24422

source code of clang/lib/Sema/SemaOpenMP.cpp