1//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements semantic analysis for OpenMP directives and
10/// clauses.
11///
12//===----------------------------------------------------------------------===//
13
14#include "clang/Sema/SemaOpenMP.h"
15
16#include "TreeTransform.h"
17#include "clang/AST/ASTContext.h"
18#include "clang/AST/ASTMutationListener.h"
19#include "clang/AST/CXXInheritance.h"
20#include "clang/AST/Decl.h"
21#include "clang/AST/DeclCXX.h"
22#include "clang/AST/DeclOpenMP.h"
23#include "clang/AST/DynamicRecursiveASTVisitor.h"
24#include "clang/AST/OpenMPClause.h"
25#include "clang/AST/StmtCXX.h"
26#include "clang/AST/StmtOpenMP.h"
27#include "clang/AST/StmtVisitor.h"
28#include "clang/Basic/DiagnosticSema.h"
29#include "clang/Basic/OpenMPKinds.h"
30#include "clang/Basic/PartialDiagnostic.h"
31#include "clang/Basic/TargetInfo.h"
32#include "clang/Sema/EnterExpressionEvaluationContext.h"
33#include "clang/Sema/Initialization.h"
34#include "clang/Sema/Lookup.h"
35#include "clang/Sema/ParsedAttr.h"
36#include "clang/Sema/Scope.h"
37#include "clang/Sema/ScopeInfo.h"
38#include "clang/Sema/Sema.h"
39#include "llvm/ADT/IndexedMap.h"
40#include "llvm/ADT/PointerEmbeddedInt.h"
41#include "llvm/ADT/STLExtras.h"
42#include "llvm/ADT/Sequence.h"
43#include "llvm/ADT/SetVector.h"
44#include "llvm/ADT/SmallSet.h"
45#include "llvm/ADT/StringExtras.h"
46#include "llvm/Frontend/OpenMP/OMPAssume.h"
47#include "llvm/Frontend/OpenMP/OMPConstants.h"
48#include "llvm/IR/Assumptions.h"
49#include <optional>
50
51using namespace clang;
52using namespace llvm::omp;
53
54//===----------------------------------------------------------------------===//
55// Stack of data-sharing attributes for variables
56//===----------------------------------------------------------------------===//
57
58static const Expr *checkMapClauseExpressionBase(
59 Sema &SemaRef, Expr *E,
60 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
61 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
62
63static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C);
64
65namespace {
66/// Default data sharing attributes, which can be applied to directive.
67enum DefaultDataSharingAttributes {
68 DSA_unspecified = 0, /// Data sharing attribute not specified.
69 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
70 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
71 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
72 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
73};
74
75/// Stack for tracking declarations used in OpenMP directives and
76/// clauses and their data-sharing attributes.
77class DSAStackTy {
78public:
79 struct DSAVarData {
80 OpenMPDirectiveKind DKind = OMPD_unknown;
81 OpenMPClauseKind CKind = OMPC_unknown;
82 unsigned Modifier = 0;
83 const Expr *RefExpr = nullptr;
84 DeclRefExpr *PrivateCopy = nullptr;
85 SourceLocation ImplicitDSALoc;
86 bool AppliedToPointee = false;
87 DSAVarData() = default;
88 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
89 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
90 SourceLocation ImplicitDSALoc, unsigned Modifier,
91 bool AppliedToPointee)
92 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
93 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
94 AppliedToPointee(AppliedToPointee) {}
95 };
96 using OperatorOffsetTy =
97 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
98 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
99 /// Kind of the declaration used in the uses_allocators clauses.
100 enum class UsesAllocatorsDeclKind {
101 /// Predefined allocator
102 PredefinedAllocator,
103 /// User-defined allocator
104 UserDefinedAllocator,
105 /// The declaration that represent allocator trait
106 AllocatorTrait,
107 };
108
109private:
110 struct DSAInfo {
111 OpenMPClauseKind Attributes = OMPC_unknown;
112 unsigned Modifier = 0;
113 /// Pointer to a reference expression and a flag which shows that the
114 /// variable is marked as lastprivate(true) or not (false).
115 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
116 DeclRefExpr *PrivateCopy = nullptr;
117 /// true if the attribute is applied to the pointee, not the variable
118 /// itself.
119 bool AppliedToPointee = false;
120 };
121 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
122 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
123 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
124 using LoopControlVariablesMapTy =
125 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
126 /// Struct that associates a component with the clause kind where they are
127 /// found.
128 struct MappedExprComponentTy {
129 OMPClauseMappableExprCommon::MappableExprComponentLists Components;
130 OpenMPClauseKind Kind = OMPC_unknown;
131 };
132 using MappedExprComponentsTy =
133 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
134 using CriticalsWithHintsTy =
135 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
136 struct ReductionData {
137 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
138 SourceRange ReductionRange;
139 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
140 ReductionData() = default;
141 void set(BinaryOperatorKind BO, SourceRange RR) {
142 ReductionRange = RR;
143 ReductionOp = BO;
144 }
145 void set(const Expr *RefExpr, SourceRange RR) {
146 ReductionRange = RR;
147 ReductionOp = RefExpr;
148 }
149 };
150 using DeclReductionMapTy =
151 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
152 struct DefaultmapInfo {
153 OpenMPDefaultmapClauseModifier ImplicitBehavior =
154 OMPC_DEFAULTMAP_MODIFIER_unknown;
155 SourceLocation SLoc;
156 DefaultmapInfo() = default;
157 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
158 : ImplicitBehavior(M), SLoc(Loc) {}
159 };
160
161 struct SharingMapTy {
162 DeclSAMapTy SharingMap;
163 DeclReductionMapTy ReductionMap;
164 UsedRefMapTy AlignedMap;
165 UsedRefMapTy NontemporalMap;
166 MappedExprComponentsTy MappedExprComponents;
167 LoopControlVariablesMapTy LCVMap;
168 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
169 SourceLocation DefaultAttrLoc;
170 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
171 OpenMPDirectiveKind Directive = OMPD_unknown;
172 DeclarationNameInfo DirectiveName;
173 Scope *CurScope = nullptr;
174 DeclContext *Context = nullptr;
175 SourceLocation ConstructLoc;
176 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
177 /// get the data (loop counters etc.) about enclosing loop-based construct.
178 /// This data is required during codegen.
179 DoacrossClauseMapTy DoacrossDepends;
180 /// First argument (Expr *) contains optional argument of the
181 /// 'ordered' clause, the second one is true if the regions has 'ordered'
182 /// clause, false otherwise.
183 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
184 bool RegionHasOrderConcurrent = false;
185 unsigned AssociatedLoops = 1;
186 bool HasMutipleLoops = false;
187 const Decl *PossiblyLoopCounter = nullptr;
188 bool NowaitRegion = false;
189 bool UntiedRegion = false;
190 bool CancelRegion = false;
191 bool LoopStart = false;
192 bool BodyComplete = false;
193 SourceLocation PrevScanLocation;
194 SourceLocation PrevOrderedLocation;
195 SourceLocation InnerTeamsRegionLoc;
196 /// Reference to the taskgroup task_reduction reference expression.
197 Expr *TaskgroupReductionRef = nullptr;
198 llvm::DenseSet<QualType> MappedClassesQualTypes;
199 SmallVector<Expr *, 4> InnerUsedAllocators;
200 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
201 /// List of globals marked as declare target link in this target region
202 /// (isOpenMPTargetExecutionDirective(Directive) == true).
203 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
204 /// List of decls used in inclusive/exclusive clauses of the scan directive.
205 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
206 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
207 UsesAllocatorsDecls;
208 /// Data is required on creating capture fields for implicit
209 /// default first|private clause.
210 struct ImplicitDefaultFDInfoTy {
211 /// Field decl.
212 const FieldDecl *FD = nullptr;
213 /// Nesting stack level
214 size_t StackLevel = 0;
215 /// Capture variable decl.
216 VarDecl *VD = nullptr;
217 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
218 VarDecl *VD)
219 : FD(FD), StackLevel(StackLevel), VD(VD) {}
220 };
221 /// List of captured fields
222 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
223 ImplicitDefaultFirstprivateFDs;
224 Expr *DeclareMapperVar = nullptr;
225 SmallVector<VarDecl *, 16> IteratorVarDecls;
226 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
227 Scope *CurScope, SourceLocation Loc)
228 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
229 ConstructLoc(Loc) {}
230 SharingMapTy() = default;
231 };
232
233 using StackTy = SmallVector<SharingMapTy, 4>;
234
235 /// Stack of used declaration and their data-sharing attributes.
236 DeclSAMapTy Threadprivates;
237 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
238 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
239 /// true, if check for DSA must be from parent directive, false, if
240 /// from current directive.
241 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
242 Sema &SemaRef;
243 bool ForceCapturing = false;
244 /// true if all the variables in the target executable directives must be
245 /// captured by reference.
246 bool ForceCaptureByReferenceInTargetExecutable = false;
247 CriticalsWithHintsTy Criticals;
248 unsigned IgnoredStackElements = 0;
249
250 /// Iterators over the stack iterate in order from innermost to outermost
251 /// directive.
252 using const_iterator = StackTy::const_reverse_iterator;
253 const_iterator begin() const {
254 return Stack.empty() ? const_iterator()
255 : Stack.back().first.rbegin() + IgnoredStackElements;
256 }
257 const_iterator end() const {
258 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
259 }
260 using iterator = StackTy::reverse_iterator;
261 iterator begin() {
262 return Stack.empty() ? iterator()
263 : Stack.back().first.rbegin() + IgnoredStackElements;
264 }
265 iterator end() {
266 return Stack.empty() ? iterator() : Stack.back().first.rend();
267 }
268
269 // Convenience operations to get at the elements of the stack.
270
271 bool isStackEmpty() const {
272 return Stack.empty() ||
273 Stack.back().second != CurrentNonCapturingFunctionScope ||
274 Stack.back().first.size() <= IgnoredStackElements;
275 }
276 size_t getStackSize() const {
277 return isStackEmpty() ? 0
278 : Stack.back().first.size() - IgnoredStackElements;
279 }
280
281 SharingMapTy *getTopOfStackOrNull() {
282 size_t Size = getStackSize();
283 if (Size == 0)
284 return nullptr;
285 return &Stack.back().first[Size - 1];
286 }
287 const SharingMapTy *getTopOfStackOrNull() const {
288 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
289 }
290 SharingMapTy &getTopOfStack() {
291 assert(!isStackEmpty() && "no current directive");
292 return *getTopOfStackOrNull();
293 }
294 const SharingMapTy &getTopOfStack() const {
295 return const_cast<DSAStackTy &>(*this).getTopOfStack();
296 }
297
298 SharingMapTy *getSecondOnStackOrNull() {
299 size_t Size = getStackSize();
300 if (Size <= 1)
301 return nullptr;
302 return &Stack.back().first[Size - 2];
303 }
304 const SharingMapTy *getSecondOnStackOrNull() const {
305 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
306 }
307
308 /// Get the stack element at a certain level (previously returned by
309 /// \c getNestingLevel).
310 ///
311 /// Note that nesting levels count from outermost to innermost, and this is
312 /// the reverse of our iteration order where new inner levels are pushed at
313 /// the front of the stack.
314 SharingMapTy &getStackElemAtLevel(unsigned Level) {
315 assert(Level < getStackSize() && "no such stack element");
316 return Stack.back().first[Level];
317 }
318 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
319 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
320 }
321
322 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
323
324 /// Checks if the variable is a local for OpenMP region.
325 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
326
327 /// Vector of previously declared requires directives
328 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
329 /// omp_allocator_handle_t type.
330 QualType OMPAllocatorHandleT;
331 /// omp_depend_t type.
332 QualType OMPDependT;
333 /// omp_event_handle_t type.
334 QualType OMPEventHandleT;
335 /// omp_alloctrait_t type.
336 QualType OMPAlloctraitT;
337 /// Expression for the predefined allocators.
338 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
339 nullptr};
340 /// Vector of previously encountered target directives
341 SmallVector<SourceLocation, 2> TargetLocations;
342 SourceLocation AtomicLocation;
343 /// Vector of declare variant construct traits.
344 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
345
346public:
347 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
348
349 /// Sets omp_allocator_handle_t type.
350 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
351 /// Gets omp_allocator_handle_t type.
352 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
353 /// Sets omp_alloctrait_t type.
354 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
355 /// Gets omp_alloctrait_t type.
356 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
357 /// Sets the given default allocator.
358 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
359 Expr *Allocator) {
360 OMPPredefinedAllocators[AllocatorKind] = Allocator;
361 }
362 /// Returns the specified default allocator.
363 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
364 return OMPPredefinedAllocators[AllocatorKind];
365 }
366 /// Sets omp_depend_t type.
367 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
368 /// Gets omp_depend_t type.
369 QualType getOMPDependT() const { return OMPDependT; }
370
371 /// Sets omp_event_handle_t type.
372 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
373 /// Gets omp_event_handle_t type.
374 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
375
376 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
377 OpenMPClauseKind getClauseParsingMode() const {
378 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
379 return ClauseKindMode;
380 }
381 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
382
383 bool isBodyComplete() const {
384 const SharingMapTy *Top = getTopOfStackOrNull();
385 return Top && Top->BodyComplete;
386 }
387 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
388
389 bool isForceVarCapturing() const { return ForceCapturing; }
390 void setForceVarCapturing(bool V) { ForceCapturing = V; }
391
392 void setForceCaptureByReferenceInTargetExecutable(bool V) {
393 ForceCaptureByReferenceInTargetExecutable = V;
394 }
395 bool isForceCaptureByReferenceInTargetExecutable() const {
396 return ForceCaptureByReferenceInTargetExecutable;
397 }
398
399 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
400 Scope *CurScope, SourceLocation Loc) {
401 assert(!IgnoredStackElements &&
402 "cannot change stack while ignoring elements");
403 if (Stack.empty() ||
404 Stack.back().second != CurrentNonCapturingFunctionScope)
405 Stack.emplace_back(Args: StackTy(), Args&: CurrentNonCapturingFunctionScope);
406 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
407 Stack.back().first.back().DefaultAttrLoc = Loc;
408 }
409
410 void pop() {
411 assert(!IgnoredStackElements &&
412 "cannot change stack while ignoring elements");
413 assert(!Stack.back().first.empty() &&
414 "Data-sharing attributes stack is empty!");
415 Stack.back().first.pop_back();
416 }
417
418 /// RAII object to temporarily leave the scope of a directive when we want to
419 /// logically operate in its parent.
420 class ParentDirectiveScope {
421 DSAStackTy &Self;
422 bool Active;
423
424 public:
425 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
426 : Self(Self), Active(false) {
427 if (Activate)
428 enable();
429 }
430 ~ParentDirectiveScope() { disable(); }
431 void disable() {
432 if (Active) {
433 --Self.IgnoredStackElements;
434 Active = false;
435 }
436 }
437 void enable() {
438 if (!Active) {
439 ++Self.IgnoredStackElements;
440 Active = true;
441 }
442 }
443 };
444
445 /// Marks that we're started loop parsing.
446 void loopInit() {
447 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
448 "Expected loop-based directive.");
449 getTopOfStack().LoopStart = true;
450 }
451 /// Start capturing of the variables in the loop context.
452 void loopStart() {
453 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
454 "Expected loop-based directive.");
455 getTopOfStack().LoopStart = false;
456 }
457 /// true, if variables are captured, false otherwise.
458 bool isLoopStarted() const {
459 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
460 "Expected loop-based directive.");
461 return !getTopOfStack().LoopStart;
462 }
463 /// Marks (or clears) declaration as possibly loop counter.
464 void resetPossibleLoopCounter(const Decl *D = nullptr) {
465 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
466 }
467 /// Gets the possible loop counter decl.
468 const Decl *getPossiblyLoopCounter() const {
469 return getTopOfStack().PossiblyLoopCounter;
470 }
471 /// Start new OpenMP region stack in new non-capturing function.
472 void pushFunction() {
473 assert(!IgnoredStackElements &&
474 "cannot change stack while ignoring elements");
475 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
476 assert(!isa<CapturingScopeInfo>(CurFnScope));
477 CurrentNonCapturingFunctionScope = CurFnScope;
478 }
479 /// Pop region stack for non-capturing function.
480 void popFunction(const FunctionScopeInfo *OldFSI) {
481 assert(!IgnoredStackElements &&
482 "cannot change stack while ignoring elements");
483 if (!Stack.empty() && Stack.back().second == OldFSI) {
484 assert(Stack.back().first.empty());
485 Stack.pop_back();
486 }
487 CurrentNonCapturingFunctionScope = nullptr;
488 for (const FunctionScopeInfo *FSI : llvm::reverse(C&: SemaRef.FunctionScopes)) {
489 if (!isa<CapturingScopeInfo>(Val: FSI)) {
490 CurrentNonCapturingFunctionScope = FSI;
491 break;
492 }
493 }
494 }
495
496 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
497 Criticals.try_emplace(Key: D->getDirectiveName().getAsString(), Args&: D, Args&: Hint);
498 }
499 std::pair<const OMPCriticalDirective *, llvm::APSInt>
500 getCriticalWithHint(const DeclarationNameInfo &Name) const {
501 auto I = Criticals.find(Key: Name.getAsString());
502 if (I != Criticals.end())
503 return I->second;
504 return std::make_pair(x: nullptr, y: llvm::APSInt());
505 }
506 /// If 'aligned' declaration for given variable \a D was not seen yet,
507 /// add it and return NULL; otherwise return previous occurrence's expression
508 /// for diagnostics.
509 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
510 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
511 /// add it and return NULL; otherwise return previous occurrence's expression
512 /// for diagnostics.
513 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
514
515 /// Register specified variable as loop control variable.
516 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
517 /// Check if the specified variable is a loop control variable for
518 /// current region.
519 /// \return The index of the loop control variable in the list of associated
520 /// for-loops (from outer to inner).
521 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
522 /// Check if the specified variable is a loop control variable for
523 /// parent region.
524 /// \return The index of the loop control variable in the list of associated
525 /// for-loops (from outer to inner).
526 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
527 /// Check if the specified variable is a loop control variable for
528 /// current region.
529 /// \return The index of the loop control variable in the list of associated
530 /// for-loops (from outer to inner).
531 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
532 unsigned Level) const;
533 /// Get the loop control variable for the I-th loop (or nullptr) in
534 /// parent directive.
535 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
536
537 /// Marks the specified decl \p D as used in scan directive.
538 void markDeclAsUsedInScanDirective(ValueDecl *D) {
539 if (SharingMapTy *Stack = getSecondOnStackOrNull())
540 Stack->UsedInScanDirective.insert(D);
541 }
542
543 /// Checks if the specified declaration was used in the inner scan directive.
544 bool isUsedInScanDirective(ValueDecl *D) const {
545 if (const SharingMapTy *Stack = getTopOfStackOrNull())
546 return Stack->UsedInScanDirective.contains(D);
547 return false;
548 }
549
550 /// Adds explicit data sharing attribute to the specified declaration.
551 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
552 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
553 bool AppliedToPointee = false);
554
555 /// Adds additional information for the reduction items with the reduction id
556 /// represented as an operator.
557 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
558 BinaryOperatorKind BOK);
559 /// Adds additional information for the reduction items with the reduction id
560 /// represented as reduction identifier.
561 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
562 const Expr *ReductionRef);
563 /// Returns the location and reduction operation from the innermost parent
564 /// region for the given \p D.
565 const DSAVarData
566 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
567 BinaryOperatorKind &BOK,
568 Expr *&TaskgroupDescriptor) const;
569 /// Returns the location and reduction operation from the innermost parent
570 /// region for the given \p D.
571 const DSAVarData
572 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
573 const Expr *&ReductionRef,
574 Expr *&TaskgroupDescriptor) const;
575 /// Return reduction reference expression for the current taskgroup or
576 /// parallel/worksharing directives with task reductions.
577 Expr *getTaskgroupReductionRef() const {
578 assert((getTopOfStack().Directive == OMPD_taskgroup ||
579 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
580 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
581 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
582 "taskgroup reference expression requested for non taskgroup or "
583 "parallel/worksharing directive.");
584 return getTopOfStack().TaskgroupReductionRef;
585 }
586 /// Checks if the given \p VD declaration is actually a taskgroup reduction
587 /// descriptor variable at the \p Level of OpenMP regions.
588 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
589 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
590 cast<DeclRefExpr>(Val: getStackElemAtLevel(Level).TaskgroupReductionRef)
591 ->getDecl() == VD;
592 }
593
594 /// Returns data sharing attributes from top of the stack for the
595 /// specified declaration.
596 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
597 /// Returns data-sharing attributes for the specified declaration.
598 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
599 /// Returns data-sharing attributes for the specified declaration.
600 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
601 /// Checks if the specified variables has data-sharing attributes which
602 /// match specified \a CPred predicate in any directive which matches \a DPred
603 /// predicate.
604 const DSAVarData
605 hasDSA(ValueDecl *D,
606 const llvm::function_ref<bool(OpenMPClauseKind, bool,
607 DefaultDataSharingAttributes)>
608 CPred,
609 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
610 bool FromParent) const;
611 /// Checks if the specified variables has data-sharing attributes which
612 /// match specified \a CPred predicate in any innermost directive which
613 /// matches \a DPred predicate.
614 const DSAVarData
615 hasInnermostDSA(ValueDecl *D,
616 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
617 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
618 bool FromParent) const;
619 /// Checks if the specified variables has explicit data-sharing
620 /// attributes which match specified \a CPred predicate at the specified
621 /// OpenMP region.
622 bool
623 hasExplicitDSA(const ValueDecl *D,
624 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
625 unsigned Level, bool NotLastprivate = false) const;
626
627 /// Returns true if the directive at level \Level matches in the
628 /// specified \a DPred predicate.
629 bool hasExplicitDirective(
630 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
631 unsigned Level) const;
632
633 /// Finds a directive which matches specified \a DPred predicate.
634 bool hasDirective(
635 const llvm::function_ref<bool(
636 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
637 DPred,
638 bool FromParent) const;
639
640 /// Returns currently analyzed directive.
641 OpenMPDirectiveKind getCurrentDirective() const {
642 const SharingMapTy *Top = getTopOfStackOrNull();
643 return Top ? Top->Directive : OMPD_unknown;
644 }
645 /// Returns directive kind at specified level.
646 OpenMPDirectiveKind getDirective(unsigned Level) const {
647 assert(!isStackEmpty() && "No directive at specified level.");
648 return getStackElemAtLevel(Level).Directive;
649 }
650 /// Returns the capture region at the specified level.
651 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
652 unsigned OpenMPCaptureLevel) const {
653 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
654 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
655 return CaptureRegions[OpenMPCaptureLevel];
656 }
657 /// Returns parent directive.
658 OpenMPDirectiveKind getParentDirective() const {
659 const SharingMapTy *Parent = getSecondOnStackOrNull();
660 return Parent ? Parent->Directive : OMPD_unknown;
661 }
662
663 /// Add requires decl to internal vector
664 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(Elt: RD); }
665
666 /// Checks if the defined 'requires' directive has specified type of clause.
667 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
668 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
669 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
670 return isa<ClauseType>(C);
671 });
672 });
673 }
674
675 /// Checks for a duplicate clause amongst previously declared requires
676 /// directives
677 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
678 bool IsDuplicate = false;
679 for (OMPClause *CNew : ClauseList) {
680 for (const OMPRequiresDecl *D : RequiresDecls) {
681 for (const OMPClause *CPrev : D->clauselists()) {
682 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
683 SemaRef.Diag(CNew->getBeginLoc(),
684 diag::err_omp_requires_clause_redeclaration)
685 << getOpenMPClauseNameForDiag(CNew->getClauseKind());
686 SemaRef.Diag(CPrev->getBeginLoc(),
687 diag::note_omp_requires_previous_clause)
688 << getOpenMPClauseNameForDiag(CPrev->getClauseKind());
689 IsDuplicate = true;
690 }
691 }
692 }
693 }
694 return IsDuplicate;
695 }
696
697 /// Add location of previously encountered target to internal vector
698 void addTargetDirLocation(SourceLocation LocStart) {
699 TargetLocations.push_back(Elt: LocStart);
700 }
701
702 /// Add location for the first encountered atomic directive.
703 void addAtomicDirectiveLoc(SourceLocation Loc) {
704 if (AtomicLocation.isInvalid())
705 AtomicLocation = Loc;
706 }
707
708 /// Returns the location of the first encountered atomic directive in the
709 /// module.
710 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
711
712 // Return previously encountered target region locations.
713 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
714 return TargetLocations;
715 }
716
717 /// Set default data sharing attribute to none.
718 void setDefaultDSANone(SourceLocation Loc) {
719 getTopOfStack().DefaultAttr = DSA_none;
720 getTopOfStack().DefaultAttrLoc = Loc;
721 }
722 /// Set default data sharing attribute to shared.
723 void setDefaultDSAShared(SourceLocation Loc) {
724 getTopOfStack().DefaultAttr = DSA_shared;
725 getTopOfStack().DefaultAttrLoc = Loc;
726 }
727 /// Set default data sharing attribute to private.
728 void setDefaultDSAPrivate(SourceLocation Loc) {
729 getTopOfStack().DefaultAttr = DSA_private;
730 getTopOfStack().DefaultAttrLoc = Loc;
731 }
732 /// Set default data sharing attribute to firstprivate.
733 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
734 getTopOfStack().DefaultAttr = DSA_firstprivate;
735 getTopOfStack().DefaultAttrLoc = Loc;
736 }
737 /// Set default data mapping attribute to Modifier:Kind
738 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
739 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
740 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
741 DMI.ImplicitBehavior = M;
742 DMI.SLoc = Loc;
743 }
744 /// Check whether the implicit-behavior has been set in defaultmap
745 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
746 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
747 return getTopOfStack()
748 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
749 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
750 getTopOfStack()
751 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
752 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
753 getTopOfStack()
754 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
755 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
756 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
757 OMPC_DEFAULTMAP_MODIFIER_unknown;
758 }
759
760 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
761 return ConstructTraits;
762 }
763 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
764 bool ScopeEntry) {
765 if (ScopeEntry)
766 ConstructTraits.append(in_start: Traits.begin(), in_end: Traits.end());
767 else
768 for (llvm::omp::TraitProperty Trait : llvm::reverse(C&: Traits)) {
769 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
770 assert(Top == Trait && "Something left a trait on the stack!");
771 (void)Trait;
772 (void)Top;
773 }
774 }
775
776 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
777 return getStackSize() <= Level ? DSA_unspecified
778 : getStackElemAtLevel(Level).DefaultAttr;
779 }
780 DefaultDataSharingAttributes getDefaultDSA() const {
781 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
782 }
783 SourceLocation getDefaultDSALocation() const {
784 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
785 }
786 OpenMPDefaultmapClauseModifier
787 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
788 return isStackEmpty()
789 ? OMPC_DEFAULTMAP_MODIFIER_unknown
790 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
791 }
792 OpenMPDefaultmapClauseModifier
793 getDefaultmapModifierAtLevel(unsigned Level,
794 OpenMPDefaultmapClauseKind Kind) const {
795 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
796 }
797 bool isDefaultmapCapturedByRef(unsigned Level,
798 OpenMPDefaultmapClauseKind Kind) const {
799 OpenMPDefaultmapClauseModifier M =
800 getDefaultmapModifierAtLevel(Level, Kind);
801 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
802 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
803 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
804 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
805 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
806 (M == OMPC_DEFAULTMAP_MODIFIER_present);
807 }
808 return true;
809 }
810 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
811 OpenMPDefaultmapClauseKind Kind) {
812 switch (Kind) {
813 case OMPC_DEFAULTMAP_scalar:
814 case OMPC_DEFAULTMAP_pointer:
815 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
816 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
817 (M == OMPC_DEFAULTMAP_MODIFIER_default);
818 case OMPC_DEFAULTMAP_aggregate:
819 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
820 default:
821 break;
822 }
823 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
824 }
825 bool mustBeFirstprivateAtLevel(unsigned Level,
826 OpenMPDefaultmapClauseKind Kind) const {
827 OpenMPDefaultmapClauseModifier M =
828 getDefaultmapModifierAtLevel(Level, Kind);
829 return mustBeFirstprivateBase(M, Kind);
830 }
831 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
832 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
833 return mustBeFirstprivateBase(M, Kind);
834 }
835
836 /// Checks if the specified variable is a threadprivate.
837 bool isThreadPrivate(VarDecl *D) {
838 const DSAVarData DVar = getTopDSA(D, false);
839 return isOpenMPThreadPrivate(DVar.CKind);
840 }
841
842 /// Marks current region as ordered (it has an 'ordered' clause).
843 void setOrderedRegion(bool IsOrdered, const Expr *Param,
844 OMPOrderedClause *Clause) {
845 if (IsOrdered)
846 getTopOfStack().OrderedRegion.emplace(args&: Param, args&: Clause);
847 else
848 getTopOfStack().OrderedRegion.reset();
849 }
850 /// Returns true, if region is ordered (has associated 'ordered' clause),
851 /// false - otherwise.
852 bool isOrderedRegion() const {
853 if (const SharingMapTy *Top = getTopOfStackOrNull())
854 return Top->OrderedRegion.has_value();
855 return false;
856 }
857 /// Returns optional parameter for the ordered region.
858 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
859 if (const SharingMapTy *Top = getTopOfStackOrNull())
860 if (Top->OrderedRegion)
861 return *Top->OrderedRegion;
862 return std::make_pair(x: nullptr, y: nullptr);
863 }
864 /// Returns true, if parent region is ordered (has associated
865 /// 'ordered' clause), false - otherwise.
866 bool isParentOrderedRegion() const {
867 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
868 return Parent->OrderedRegion.has_value();
869 return false;
870 }
871 /// Returns optional parameter for the ordered region.
872 std::pair<const Expr *, OMPOrderedClause *>
873 getParentOrderedRegionParam() const {
874 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
875 if (Parent->OrderedRegion)
876 return *Parent->OrderedRegion;
877 return std::make_pair(x: nullptr, y: nullptr);
878 }
879 /// Marks current region as having an 'order' clause.
880 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
881 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
882 }
883 /// Returns true, if parent region is order (has associated
884 /// 'order' clause), false - otherwise.
885 bool isParentOrderConcurrent() const {
886 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
887 return Parent->RegionHasOrderConcurrent;
888 return false;
889 }
890 /// Marks current region as nowait (it has a 'nowait' clause).
891 void setNowaitRegion(bool IsNowait = true) {
892 getTopOfStack().NowaitRegion = IsNowait;
893 }
894 /// Returns true, if parent region is nowait (has associated
895 /// 'nowait' clause), false - otherwise.
896 bool isParentNowaitRegion() const {
897 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
898 return Parent->NowaitRegion;
899 return false;
900 }
901 /// Marks current region as untied (it has a 'untied' clause).
902 void setUntiedRegion(bool IsUntied = true) {
903 getTopOfStack().UntiedRegion = IsUntied;
904 }
905 /// Return true if current region is untied.
906 bool isUntiedRegion() const {
907 const SharingMapTy *Top = getTopOfStackOrNull();
908 return Top ? Top->UntiedRegion : false;
909 }
910 /// Marks parent region as cancel region.
911 void setParentCancelRegion(bool Cancel = true) {
912 if (SharingMapTy *Parent = getSecondOnStackOrNull())
913 Parent->CancelRegion |= Cancel;
914 }
915 /// Return true if current region has inner cancel construct.
916 bool isCancelRegion() const {
917 const SharingMapTy *Top = getTopOfStackOrNull();
918 return Top ? Top->CancelRegion : false;
919 }
920
921 /// Mark that parent region already has scan directive.
922 void setParentHasScanDirective(SourceLocation Loc) {
923 if (SharingMapTy *Parent = getSecondOnStackOrNull())
924 Parent->PrevScanLocation = Loc;
925 }
926 /// Return true if current region has inner cancel construct.
927 bool doesParentHasScanDirective() const {
928 const SharingMapTy *Top = getSecondOnStackOrNull();
929 return Top ? Top->PrevScanLocation.isValid() : false;
930 }
931 /// Return true if current region has inner cancel construct.
932 SourceLocation getParentScanDirectiveLoc() const {
933 const SharingMapTy *Top = getSecondOnStackOrNull();
934 return Top ? Top->PrevScanLocation : SourceLocation();
935 }
936 /// Mark that parent region already has ordered directive.
937 void setParentHasOrderedDirective(SourceLocation Loc) {
938 if (SharingMapTy *Parent = getSecondOnStackOrNull())
939 Parent->PrevOrderedLocation = Loc;
940 }
941 /// Return true if current region has inner ordered construct.
942 bool doesParentHasOrderedDirective() const {
943 const SharingMapTy *Top = getSecondOnStackOrNull();
944 return Top ? Top->PrevOrderedLocation.isValid() : false;
945 }
946 /// Returns the location of the previously specified ordered directive.
947 SourceLocation getParentOrderedDirectiveLoc() const {
948 const SharingMapTy *Top = getSecondOnStackOrNull();
949 return Top ? Top->PrevOrderedLocation : SourceLocation();
950 }
951
952 /// Set collapse value for the region.
953 void setAssociatedLoops(unsigned Val) {
954 getTopOfStack().AssociatedLoops = Val;
955 if (Val > 1)
956 getTopOfStack().HasMutipleLoops = true;
957 }
958 /// Return collapse value for region.
959 unsigned getAssociatedLoops() const {
960 const SharingMapTy *Top = getTopOfStackOrNull();
961 return Top ? Top->AssociatedLoops : 0;
962 }
963 /// Returns true if the construct is associated with multiple loops.
964 bool hasMutipleLoops() const {
965 const SharingMapTy *Top = getTopOfStackOrNull();
966 return Top ? Top->HasMutipleLoops : false;
967 }
968
969 /// Marks current target region as one with closely nested teams
970 /// region.
971 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
972 if (SharingMapTy *Parent = getSecondOnStackOrNull())
973 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
974 }
975 /// Returns true, if current region has closely nested teams region.
976 bool hasInnerTeamsRegion() const {
977 return getInnerTeamsRegionLoc().isValid();
978 }
979 /// Returns location of the nested teams region (if any).
980 SourceLocation getInnerTeamsRegionLoc() const {
981 const SharingMapTy *Top = getTopOfStackOrNull();
982 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
983 }
984
985 Scope *getCurScope() const {
986 const SharingMapTy *Top = getTopOfStackOrNull();
987 return Top ? Top->CurScope : nullptr;
988 }
989 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
990 SourceLocation getConstructLoc() const {
991 const SharingMapTy *Top = getTopOfStackOrNull();
992 return Top ? Top->ConstructLoc : SourceLocation();
993 }
994
995 /// Do the check specified in \a Check to all component lists and return true
996 /// if any issue is found.
997 bool checkMappableExprComponentListsForDecl(
998 const ValueDecl *VD, bool CurrentRegionOnly,
999 const llvm::function_ref<
1000 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1001 OpenMPClauseKind)>
1002 Check) const {
1003 if (isStackEmpty())
1004 return false;
1005 auto SI = begin();
1006 auto SE = end();
1007
1008 if (SI == SE)
1009 return false;
1010
1011 if (CurrentRegionOnly)
1012 SE = std::next(x: SI);
1013 else
1014 std::advance(i&: SI, n: 1);
1015
1016 for (; SI != SE; ++SI) {
1017 auto MI = SI->MappedExprComponents.find(Val: VD);
1018 if (MI != SI->MappedExprComponents.end())
1019 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1020 MI->second.Components)
1021 if (Check(L, MI->second.Kind))
1022 return true;
1023 }
1024 return false;
1025 }
1026
1027 /// Do the check specified in \a Check to all component lists at a given level
1028 /// and return true if any issue is found.
1029 bool checkMappableExprComponentListsForDeclAtLevel(
1030 const ValueDecl *VD, unsigned Level,
1031 const llvm::function_ref<
1032 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1033 OpenMPClauseKind)>
1034 Check) const {
1035 if (getStackSize() <= Level)
1036 return false;
1037
1038 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1039 auto MI = StackElem.MappedExprComponents.find(Val: VD);
1040 if (MI != StackElem.MappedExprComponents.end())
1041 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1042 MI->second.Components)
1043 if (Check(L, MI->second.Kind))
1044 return true;
1045 return false;
1046 }
1047
1048 /// Create a new mappable expression component list associated with a given
1049 /// declaration and initialize it with the provided list of components.
1050 void addMappableExpressionComponents(
1051 const ValueDecl *VD,
1052 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
1053 OpenMPClauseKind WhereFoundClauseKind) {
1054 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1055 // Create new entry and append the new components there.
1056 MEC.Components.resize(N: MEC.Components.size() + 1);
1057 MEC.Components.back().append(in_start: Components.begin(), in_end: Components.end());
1058 MEC.Kind = WhereFoundClauseKind;
1059 }
1060
1061 unsigned getNestingLevel() const {
1062 assert(!isStackEmpty());
1063 return getStackSize() - 1;
1064 }
1065 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1066 SharingMapTy *Parent = getSecondOnStackOrNull();
1067 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1068 Parent->DoacrossDepends.try_emplace(Key: C, Args: OpsOffs);
1069 }
1070 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1071 getDoacrossDependClauses() const {
1072 const SharingMapTy &StackElem = getTopOfStack();
1073 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1074 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1075 return llvm::make_range(x: Ref.begin(), y: Ref.end());
1076 }
1077 return llvm::make_range(x: StackElem.DoacrossDepends.end(),
1078 y: StackElem.DoacrossDepends.end());
1079 }
1080
1081 // Store types of classes which have been explicitly mapped
1082 void addMappedClassesQualTypes(QualType QT) {
1083 SharingMapTy &StackElem = getTopOfStack();
1084 StackElem.MappedClassesQualTypes.insert(V: QT);
1085 }
1086
1087 // Return set of mapped classes types
1088 bool isClassPreviouslyMapped(QualType QT) const {
1089 const SharingMapTy &StackElem = getTopOfStack();
1090 return StackElem.MappedClassesQualTypes.contains(V: QT);
1091 }
1092
1093 /// Adds global declare target to the parent target region.
1094 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1095 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1096 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1097 "Expected declare target link global.");
1098 for (auto &Elem : *this) {
1099 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1100 Elem.DeclareTargetLinkVarDecls.push_back(Elt: E);
1101 return;
1102 }
1103 }
1104 }
1105
1106 /// Returns the list of globals with declare target link if current directive
1107 /// is target.
1108 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1109 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1110 "Expected target executable directive.");
1111 return getTopOfStack().DeclareTargetLinkVarDecls;
1112 }
1113
1114 /// Adds list of allocators expressions.
1115 void addInnerAllocatorExpr(Expr *E) {
1116 getTopOfStack().InnerUsedAllocators.push_back(Elt: E);
1117 }
1118 /// Return list of used allocators.
1119 ArrayRef<Expr *> getInnerAllocators() const {
1120 return getTopOfStack().InnerUsedAllocators;
1121 }
1122 /// Marks the declaration as implicitly firstprivate nin the task-based
1123 /// regions.
1124 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1125 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(V: D);
1126 }
1127 /// Checks if the decl is implicitly firstprivate in the task-based region.
1128 bool isImplicitTaskFirstprivate(Decl *D) const {
1129 return getTopOfStack().ImplicitTaskFirstprivates.contains(V: D);
1130 }
1131
1132 /// Marks decl as used in uses_allocators clause as the allocator.
1133 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1134 getTopOfStack().UsesAllocatorsDecls.try_emplace(Key: D, Args&: Kind);
1135 }
1136 /// Checks if specified decl is used in uses allocator clause as the
1137 /// allocator.
1138 std::optional<UsesAllocatorsDeclKind>
1139 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1140 const SharingMapTy &StackElem = getTopOfStack();
1141 auto I = StackElem.UsesAllocatorsDecls.find(Val: D);
1142 if (I == StackElem.UsesAllocatorsDecls.end())
1143 return std::nullopt;
1144 return I->getSecond();
1145 }
1146 std::optional<UsesAllocatorsDeclKind>
1147 isUsesAllocatorsDecl(const Decl *D) const {
1148 const SharingMapTy &StackElem = getTopOfStack();
1149 auto I = StackElem.UsesAllocatorsDecls.find(Val: D);
1150 if (I == StackElem.UsesAllocatorsDecls.end())
1151 return std::nullopt;
1152 return I->getSecond();
1153 }
1154
1155 void addDeclareMapperVarRef(Expr *Ref) {
1156 SharingMapTy &StackElem = getTopOfStack();
1157 StackElem.DeclareMapperVar = Ref;
1158 }
1159 const Expr *getDeclareMapperVarRef() const {
1160 const SharingMapTy *Top = getTopOfStackOrNull();
1161 return Top ? Top->DeclareMapperVar : nullptr;
1162 }
1163
1164 /// Add a new iterator variable.
1165 void addIteratorVarDecl(VarDecl *VD) {
1166 SharingMapTy &StackElem = getTopOfStack();
1167 StackElem.IteratorVarDecls.push_back(Elt: VD->getCanonicalDecl());
1168 }
1169 /// Check if variable declaration is an iterator VarDecl.
1170 bool isIteratorVarDecl(const VarDecl *VD) const {
1171 const SharingMapTy *Top = getTopOfStackOrNull();
1172 if (!Top)
1173 return false;
1174
1175 return llvm::is_contained(Range: Top->IteratorVarDecls, Element: VD->getCanonicalDecl());
1176 }
1177 /// get captured field from ImplicitDefaultFirstprivateFDs
1178 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1179 const_iterator I = begin();
1180 const_iterator EndI = end();
1181 size_t StackLevel = getStackSize();
1182 for (; I != EndI; ++I) {
1183 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1184 break;
1185 StackLevel--;
1186 }
1187 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1188 if (I == EndI)
1189 return nullptr;
1190 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1191 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1192 return IFD.VD;
1193 return nullptr;
1194 }
1195 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1196 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1197 const_iterator I = begin();
1198 const_iterator EndI = end();
1199 for (; I != EndI; ++I)
1200 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1201 break;
1202 if (I == EndI)
1203 return false;
1204 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1205 if (IFD.VD == VD)
1206 return true;
1207 return false;
1208 }
1209 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1210 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1211 iterator I = begin();
1212 const_iterator EndI = end();
1213 size_t StackLevel = getStackSize();
1214 for (; I != EndI; ++I) {
1215 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1216 I->ImplicitDefaultFirstprivateFDs.emplace_back(Args&: FD, Args&: StackLevel, Args&: VD);
1217 break;
1218 }
1219 StackLevel--;
1220 }
1221 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1222 }
1223};
1224
1225bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1226 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1227}
1228
1229bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1230 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1231 DKind == OMPD_unknown;
1232}
1233
1234} // namespace
1235
1236static const Expr *getExprAsWritten(const Expr *E) {
1237 if (const auto *FE = dyn_cast<FullExpr>(Val: E))
1238 E = FE->getSubExpr();
1239
1240 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Val: E))
1241 E = MTE->getSubExpr();
1242
1243 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(Val: E))
1244 E = Binder->getSubExpr();
1245
1246 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(Val: E))
1247 E = ICE->getSubExprAsWritten();
1248 return E->IgnoreParens();
1249}
1250
1251static Expr *getExprAsWritten(Expr *E) {
1252 return const_cast<Expr *>(getExprAsWritten(E: const_cast<const Expr *>(E)));
1253}
1254
1255static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1256 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: D))
1257 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1258 D = ME->getMemberDecl();
1259
1260 D = cast<ValueDecl>(D->getCanonicalDecl());
1261 return D;
1262}
1263
1264static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1265 return const_cast<ValueDecl *>(
1266 getCanonicalDecl(D: const_cast<const ValueDecl *>(D)));
1267}
1268
1269static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C) {
1270 if (C == OMPC_threadprivate)
1271 return getOpenMPClauseName(C).str() + " or thread local";
1272 return getOpenMPClauseName(C).str();
1273}
1274
1275DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1276 ValueDecl *D) const {
1277 D = getCanonicalDecl(D);
1278 auto *VD = dyn_cast<VarDecl>(Val: D);
1279 const auto *FD = dyn_cast<FieldDecl>(Val: D);
1280 DSAVarData DVar;
1281 if (Iter == end()) {
1282 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1283 // in a region but not in construct]
1284 // File-scope or namespace-scope variables referenced in called routines
1285 // in the region are shared unless they appear in a threadprivate
1286 // directive.
1287 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1288 DVar.CKind = OMPC_shared;
1289
1290 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1291 // in a region but not in construct]
1292 // Variables with static storage duration that are declared in called
1293 // routines in the region are shared.
1294 if (VD && VD->hasGlobalStorage())
1295 DVar.CKind = OMPC_shared;
1296
1297 // Non-static data members are shared by default.
1298 if (FD)
1299 DVar.CKind = OMPC_shared;
1300
1301 return DVar;
1302 }
1303
1304 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1305 // in a Construct, C/C++, predetermined, p.1]
1306 // Variables with automatic storage duration that are declared in a scope
1307 // inside the construct are private.
1308 if (VD && isOpenMPLocal(D: VD, Iter) && VD->isLocalVarDecl() &&
1309 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1310 DVar.CKind = OMPC_private;
1311 return DVar;
1312 }
1313
1314 DVar.DKind = Iter->Directive;
1315 // Explicitly specified attributes and local variables with predetermined
1316 // attributes.
1317 if (Iter->SharingMap.count(D)) {
1318 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1319 DVar.RefExpr = Data.RefExpr.getPointer();
1320 DVar.PrivateCopy = Data.PrivateCopy;
1321 DVar.CKind = Data.Attributes;
1322 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1323 DVar.Modifier = Data.Modifier;
1324 DVar.AppliedToPointee = Data.AppliedToPointee;
1325 return DVar;
1326 }
1327
1328 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1329 // in a Construct, C/C++, implicitly determined, p.1]
1330 // In a parallel or task construct, the data-sharing attributes of these
1331 // variables are determined by the default clause, if present.
1332 switch (Iter->DefaultAttr) {
1333 case DSA_shared:
1334 DVar.CKind = OMPC_shared;
1335 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1336 return DVar;
1337 case DSA_none:
1338 return DVar;
1339 case DSA_firstprivate:
1340 if (VD && VD->getStorageDuration() == SD_Static &&
1341 VD->getDeclContext()->isFileContext()) {
1342 DVar.CKind = OMPC_unknown;
1343 } else {
1344 DVar.CKind = OMPC_firstprivate;
1345 }
1346 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1347 return DVar;
1348 case DSA_private:
1349 // each variable with static storage duration that is declared
1350 // in a namespace or global scope and referenced in the construct,
1351 // and that does not have a predetermined data-sharing attribute
1352 if (VD && VD->getStorageDuration() == SD_Static &&
1353 VD->getDeclContext()->isFileContext()) {
1354 DVar.CKind = OMPC_unknown;
1355 } else {
1356 DVar.CKind = OMPC_private;
1357 }
1358 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1359 return DVar;
1360 case DSA_unspecified:
1361 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1362 // in a Construct, implicitly determined, p.2]
1363 // In a parallel construct, if no default clause is present, these
1364 // variables are shared.
1365 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1366 if ((isOpenMPParallelDirective(DVar.DKind) &&
1367 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1368 isOpenMPTeamsDirective(DVar.DKind)) {
1369 DVar.CKind = OMPC_shared;
1370 return DVar;
1371 }
1372
1373 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1374 // in a Construct, implicitly determined, p.4]
1375 // In a task construct, if no default clause is present, a variable that in
1376 // the enclosing context is determined to be shared by all implicit tasks
1377 // bound to the current team is shared.
1378 if (isOpenMPTaskingDirective(DVar.DKind)) {
1379 DSAVarData DVarTemp;
1380 const_iterator I = Iter, E = end();
1381 do {
1382 ++I;
1383 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1384 // Referenced in a Construct, implicitly determined, p.6]
1385 // In a task construct, if no default clause is present, a variable
1386 // whose data-sharing attribute is not determined by the rules above is
1387 // firstprivate.
1388 DVarTemp = getDSA(Iter&: I, D);
1389 if (DVarTemp.CKind != OMPC_shared) {
1390 DVar.RefExpr = nullptr;
1391 DVar.CKind = OMPC_firstprivate;
1392 return DVar;
1393 }
1394 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1395 DVar.CKind =
1396 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1397 return DVar;
1398 }
1399 }
1400 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1401 // in a Construct, implicitly determined, p.3]
1402 // For constructs other than task, if no default clause is present, these
1403 // variables inherit their data-sharing attributes from the enclosing
1404 // context.
1405 return getDSA(Iter&: ++Iter, D);
1406}
1407
1408const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1409 const Expr *NewDE) {
1410 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1411 D = getCanonicalDecl(D);
1412 SharingMapTy &StackElem = getTopOfStack();
1413 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(Key: D, Args&: NewDE);
1414 if (Inserted) {
1415 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1416 return nullptr;
1417 }
1418 assert(It->second && "Unexpected nullptr expr in the aligned map");
1419 return It->second;
1420}
1421
1422const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1423 const Expr *NewDE) {
1424 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1425 D = getCanonicalDecl(D);
1426 SharingMapTy &StackElem = getTopOfStack();
1427 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(Key: D, Args&: NewDE);
1428 if (Inserted) {
1429 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1430 return nullptr;
1431 }
1432 assert(It->second && "Unexpected nullptr expr in the aligned map");
1433 return It->second;
1434}
1435
1436void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1437 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1438 D = getCanonicalDecl(D);
1439 SharingMapTy &StackElem = getTopOfStack();
1440 StackElem.LCVMap.try_emplace(
1441 Key: D, Args: LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1442}
1443
1444const DSAStackTy::LCDeclInfo
1445DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1446 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1447 D = getCanonicalDecl(D);
1448 const SharingMapTy &StackElem = getTopOfStack();
1449 auto It = StackElem.LCVMap.find(Val: D);
1450 if (It != StackElem.LCVMap.end())
1451 return It->second;
1452 return {0, nullptr};
1453}
1454
1455const DSAStackTy::LCDeclInfo
1456DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1457 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1458 D = getCanonicalDecl(D);
1459 for (unsigned I = Level + 1; I > 0; --I) {
1460 const SharingMapTy &StackElem = getStackElemAtLevel(Level: I - 1);
1461 auto It = StackElem.LCVMap.find(Val: D);
1462 if (It != StackElem.LCVMap.end())
1463 return It->second;
1464 }
1465 return {0, nullptr};
1466}
1467
1468const DSAStackTy::LCDeclInfo
1469DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1470 const SharingMapTy *Parent = getSecondOnStackOrNull();
1471 assert(Parent && "Data-sharing attributes stack is empty");
1472 D = getCanonicalDecl(D);
1473 auto It = Parent->LCVMap.find(Val: D);
1474 if (It != Parent->LCVMap.end())
1475 return It->second;
1476 return {0, nullptr};
1477}
1478
1479const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1480 const SharingMapTy *Parent = getSecondOnStackOrNull();
1481 assert(Parent && "Data-sharing attributes stack is empty");
1482 if (Parent->LCVMap.size() < I)
1483 return nullptr;
1484 for (const auto &Pair : Parent->LCVMap)
1485 if (Pair.second.first == I)
1486 return Pair.first;
1487 return nullptr;
1488}
1489
1490void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1491 DeclRefExpr *PrivateCopy, unsigned Modifier,
1492 bool AppliedToPointee) {
1493 D = getCanonicalDecl(D);
1494 if (A == OMPC_threadprivate) {
1495 DSAInfo &Data = Threadprivates[D];
1496 Data.Attributes = A;
1497 Data.RefExpr.setPointer(E);
1498 Data.PrivateCopy = nullptr;
1499 Data.Modifier = Modifier;
1500 } else {
1501 DSAInfo &Data = getTopOfStack().SharingMap[D];
1502 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1503 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1504 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1505 (isLoopControlVariable(D).first && A == OMPC_private));
1506 Data.Modifier = Modifier;
1507 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1508 Data.RefExpr.setInt(/*IntVal=*/true);
1509 return;
1510 }
1511 const bool IsLastprivate =
1512 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1513 Data.Attributes = A;
1514 Data.RefExpr.setPointerAndInt(PtrVal: E, IntVal: IsLastprivate);
1515 Data.PrivateCopy = PrivateCopy;
1516 Data.AppliedToPointee = AppliedToPointee;
1517 if (PrivateCopy) {
1518 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1519 Data.Modifier = Modifier;
1520 Data.Attributes = A;
1521 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1522 Data.PrivateCopy = nullptr;
1523 Data.AppliedToPointee = AppliedToPointee;
1524 }
1525 }
1526}
1527
1528/// Build a variable declaration for OpenMP loop iteration variable.
1529static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
1530 StringRef Name, const AttrVec *Attrs = nullptr,
1531 DeclRefExpr *OrigRef = nullptr) {
1532 DeclContext *DC = SemaRef.CurContext;
1533 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1534 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(T: Type, Loc);
1535 auto *Decl =
1536 VarDecl::Create(C&: SemaRef.Context, DC, StartLoc: Loc, IdLoc: Loc, Id: II, T: Type, TInfo, S: SC_None);
1537 if (Attrs) {
1538 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1539 I != E; ++I)
1540 Decl->addAttr(*I);
1541 }
1542 Decl->setImplicit();
1543 if (OrigRef) {
1544 Decl->addAttr(
1545 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1546 }
1547 return Decl;
1548}
1549
1550static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
1551 SourceLocation Loc,
1552 bool RefersToCapture = false) {
1553 D->setReferenced();
1554 D->markUsed(S.Context);
1555 return DeclRefExpr::Create(S.getASTContext(), NestedNameSpecifierLoc(),
1556 SourceLocation(), D, RefersToCapture, Loc, Ty,
1557 VK_LValue);
1558}
1559
1560void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1561 BinaryOperatorKind BOK) {
1562 D = getCanonicalDecl(D);
1563 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1564 assert(
1565 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1566 "Additional reduction info may be specified only for reduction items.");
1567 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1568 assert(ReductionData.ReductionRange.isInvalid() &&
1569 (getTopOfStack().Directive == OMPD_taskgroup ||
1570 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1571 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1572 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1573 "Additional reduction info may be specified only once for reduction "
1574 "items.");
1575 ReductionData.set(BO: BOK, RR: SR);
1576 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1577 if (!TaskgroupReductionRef) {
1578 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1579 SemaRef.Context.VoidPtrTy, ".task_red.");
1580 TaskgroupReductionRef =
1581 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1582 }
1583}
1584
1585void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1586 const Expr *ReductionRef) {
1587 D = getCanonicalDecl(D);
1588 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1589 assert(
1590 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1591 "Additional reduction info may be specified only for reduction items.");
1592 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1593 assert(ReductionData.ReductionRange.isInvalid() &&
1594 (getTopOfStack().Directive == OMPD_taskgroup ||
1595 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1596 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1597 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1598 "Additional reduction info may be specified only once for reduction "
1599 "items.");
1600 ReductionData.set(RefExpr: ReductionRef, RR: SR);
1601 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1602 if (!TaskgroupReductionRef) {
1603 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1604 SemaRef.Context.VoidPtrTy, ".task_red.");
1605 TaskgroupReductionRef =
1606 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1607 }
1608}
1609
1610const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1611 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1612 Expr *&TaskgroupDescriptor) const {
1613 D = getCanonicalDecl(D);
1614 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1615 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1616 const DSAInfo &Data = I->SharingMap.lookup(D);
1617 if (Data.Attributes != OMPC_reduction ||
1618 Data.Modifier != OMPC_REDUCTION_task)
1619 continue;
1620 const ReductionData &ReductionData = I->ReductionMap.lookup(Val: D);
1621 if (!ReductionData.ReductionOp ||
1622 isa<const Expr *>(Val: ReductionData.ReductionOp))
1623 return DSAVarData();
1624 SR = ReductionData.ReductionRange;
1625 BOK = cast<ReductionData::BOKPtrType>(Val: ReductionData.ReductionOp);
1626 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1627 "expression for the descriptor is not "
1628 "set.");
1629 TaskgroupDescriptor = I->TaskgroupReductionRef;
1630 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1631 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1632 /*AppliedToPointee=*/false);
1633 }
1634 return DSAVarData();
1635}
1636
1637const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1638 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1639 Expr *&TaskgroupDescriptor) const {
1640 D = getCanonicalDecl(D);
1641 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1642 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1643 const DSAInfo &Data = I->SharingMap.lookup(D);
1644 if (Data.Attributes != OMPC_reduction ||
1645 Data.Modifier != OMPC_REDUCTION_task)
1646 continue;
1647 const ReductionData &ReductionData = I->ReductionMap.lookup(Val: D);
1648 if (!ReductionData.ReductionOp ||
1649 !isa<const Expr *>(Val: ReductionData.ReductionOp))
1650 return DSAVarData();
1651 SR = ReductionData.ReductionRange;
1652 ReductionRef = cast<const Expr *>(Val: ReductionData.ReductionOp);
1653 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1654 "expression for the descriptor is not "
1655 "set.");
1656 TaskgroupDescriptor = I->TaskgroupReductionRef;
1657 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1658 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1659 /*AppliedToPointee=*/false);
1660 }
1661 return DSAVarData();
1662}
1663
1664bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1665 D = D->getCanonicalDecl();
1666 for (const_iterator E = end(); I != E; ++I) {
1667 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1668 isOpenMPTargetExecutionDirective(I->Directive)) {
1669 if (I->CurScope) {
1670 Scope *TopScope = I->CurScope->getParent();
1671 Scope *CurScope = getCurScope();
1672 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1673 CurScope = CurScope->getParent();
1674 return CurScope != TopScope;
1675 }
1676 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1677 if (I->Context == DC)
1678 return true;
1679 return false;
1680 }
1681 }
1682 return false;
1683}
1684
1685static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
1686 bool AcceptIfMutable = true,
1687 bool *IsClassType = nullptr) {
1688 ASTContext &Context = SemaRef.getASTContext();
1689 Type = Type.getNonReferenceType().getCanonicalType();
1690 bool IsConstant = Type.isConstant(Ctx: Context);
1691 Type = Context.getBaseElementType(QT: Type);
1692 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1693 ? Type->getAsCXXRecordDecl()
1694 : nullptr;
1695 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(Val: RD))
1696 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1697 RD = CTD->getTemplatedDecl();
1698 if (IsClassType)
1699 *IsClassType = RD;
1700 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1701 RD->hasDefinition() && RD->hasMutableFields());
1702}
1703
1704static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1705 QualType Type, OpenMPClauseKind CKind,
1706 SourceLocation ELoc,
1707 bool AcceptIfMutable = true,
1708 bool ListItemNotVar = false) {
1709 ASTContext &Context = SemaRef.getASTContext();
1710 bool IsClassType;
1711 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, IsClassType: &IsClassType)) {
1712 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1713 : IsClassType ? diag::err_omp_const_not_mutable_variable
1714 : diag::err_omp_const_variable;
1715 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseNameForDiag(CKind);
1716 if (!ListItemNotVar && D) {
1717 const VarDecl *VD = dyn_cast<VarDecl>(Val: D);
1718 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1719 VarDecl::DeclarationOnly;
1720 SemaRef.Diag(D->getLocation(),
1721 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1722 << D;
1723 }
1724 return true;
1725 }
1726 return false;
1727}
1728
1729const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1730 bool FromParent) {
1731 D = getCanonicalDecl(D);
1732 DSAVarData DVar;
1733
1734 auto *VD = dyn_cast<VarDecl>(Val: D);
1735 auto TI = Threadprivates.find(D);
1736 if (TI != Threadprivates.end()) {
1737 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1738 DVar.CKind = OMPC_threadprivate;
1739 DVar.Modifier = TI->getSecond().Modifier;
1740 return DVar;
1741 }
1742 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1743 DVar.RefExpr = buildDeclRefExpr(
1744 SemaRef, VD, D->getType().getNonReferenceType(),
1745 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1746 DVar.CKind = OMPC_threadprivate;
1747 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1748 return DVar;
1749 }
1750 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1751 // in a Construct, C/C++, predetermined, p.1]
1752 // Variables appearing in threadprivate directives are threadprivate.
1753 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1754 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1755 SemaRef.getLangOpts().OpenMPUseTLS &&
1756 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1757 (VD && VD->getStorageClass() == SC_Register &&
1758 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1759 DVar.RefExpr = buildDeclRefExpr(
1760 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1761 DVar.CKind = OMPC_threadprivate;
1762 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1763 return DVar;
1764 }
1765 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1766 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1767 !isLoopControlVariable(D).first) {
1768 const_iterator IterTarget =
1769 std::find_if(first: begin(), last: end(), pred: [](const SharingMapTy &Data) {
1770 return isOpenMPTargetExecutionDirective(Data.Directive);
1771 });
1772 if (IterTarget != end()) {
1773 const_iterator ParentIterTarget = IterTarget + 1;
1774 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1775 if (isOpenMPLocal(D: VD, I: Iter)) {
1776 DVar.RefExpr =
1777 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1778 D->getLocation());
1779 DVar.CKind = OMPC_threadprivate;
1780 return DVar;
1781 }
1782 }
1783 if (!isClauseParsingMode() || IterTarget != begin()) {
1784 auto DSAIter = IterTarget->SharingMap.find(D);
1785 if (DSAIter != IterTarget->SharingMap.end() &&
1786 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1787 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1788 DVar.CKind = OMPC_threadprivate;
1789 return DVar;
1790 }
1791 const_iterator End = end();
1792 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1793 D, Level: std::distance(first: ParentIterTarget, last: End),
1794 /*OpenMPCaptureLevel=*/0)) {
1795 DVar.RefExpr =
1796 buildDeclRefExpr(S&: SemaRef, D: VD, Ty: D->getType().getNonReferenceType(),
1797 Loc: IterTarget->ConstructLoc);
1798 DVar.CKind = OMPC_threadprivate;
1799 return DVar;
1800 }
1801 }
1802 }
1803 }
1804
1805 if (isStackEmpty())
1806 // Not in OpenMP execution region and top scope was already checked.
1807 return DVar;
1808
1809 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1810 // in a Construct, C/C++, predetermined, p.4]
1811 // Static data members are shared.
1812 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1813 // in a Construct, C/C++, predetermined, p.7]
1814 // Variables with static storage duration that are declared in a scope
1815 // inside the construct are shared.
1816 if (VD && VD->isStaticDataMember()) {
1817 // Check for explicitly specified attributes.
1818 const_iterator I = begin();
1819 const_iterator EndI = end();
1820 if (FromParent && I != EndI)
1821 ++I;
1822 if (I != EndI) {
1823 auto It = I->SharingMap.find(D);
1824 if (It != I->SharingMap.end()) {
1825 const DSAInfo &Data = It->getSecond();
1826 DVar.RefExpr = Data.RefExpr.getPointer();
1827 DVar.PrivateCopy = Data.PrivateCopy;
1828 DVar.CKind = Data.Attributes;
1829 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1830 DVar.DKind = I->Directive;
1831 DVar.Modifier = Data.Modifier;
1832 DVar.AppliedToPointee = Data.AppliedToPointee;
1833 return DVar;
1834 }
1835 }
1836
1837 DVar.CKind = OMPC_shared;
1838 return DVar;
1839 }
1840
1841 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1842 // The predetermined shared attribute for const-qualified types having no
1843 // mutable members was removed after OpenMP 3.1.
1844 if (SemaRef.LangOpts.OpenMP <= 31) {
1845 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1846 // in a Construct, C/C++, predetermined, p.6]
1847 // Variables with const qualified type having no mutable member are
1848 // shared.
1849 if (isConstNotMutableType(SemaRef, Type: D->getType())) {
1850 // Variables with const-qualified type having no mutable member may be
1851 // listed in a firstprivate clause, even if they are static data members.
1852 DSAVarData DVarTemp = hasInnermostDSA(
1853 D,
1854 [](OpenMPClauseKind C, bool) {
1855 return C == OMPC_firstprivate || C == OMPC_shared;
1856 },
1857 MatchesAlways, FromParent);
1858 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1859 return DVarTemp;
1860
1861 DVar.CKind = OMPC_shared;
1862 return DVar;
1863 }
1864 }
1865
1866 // Explicitly specified attributes and local variables with predetermined
1867 // attributes.
1868 const_iterator I = begin();
1869 const_iterator EndI = end();
1870 if (FromParent && I != EndI)
1871 ++I;
1872 if (I == EndI)
1873 return DVar;
1874 auto It = I->SharingMap.find(D);
1875 if (It != I->SharingMap.end()) {
1876 const DSAInfo &Data = It->getSecond();
1877 DVar.RefExpr = Data.RefExpr.getPointer();
1878 DVar.PrivateCopy = Data.PrivateCopy;
1879 DVar.CKind = Data.Attributes;
1880 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1881 DVar.DKind = I->Directive;
1882 DVar.Modifier = Data.Modifier;
1883 DVar.AppliedToPointee = Data.AppliedToPointee;
1884 }
1885
1886 return DVar;
1887}
1888
1889const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1890 bool FromParent) const {
1891 if (isStackEmpty()) {
1892 const_iterator I;
1893 return getDSA(Iter&: I, D);
1894 }
1895 D = getCanonicalDecl(D);
1896 const_iterator StartI = begin();
1897 const_iterator EndI = end();
1898 if (FromParent && StartI != EndI)
1899 ++StartI;
1900 return getDSA(Iter&: StartI, D);
1901}
1902
1903const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1904 unsigned Level) const {
1905 if (getStackSize() <= Level)
1906 return DSAVarData();
1907 D = getCanonicalDecl(D);
1908 const_iterator StartI = std::next(x: begin(), n: getStackSize() - 1 - Level);
1909 return getDSA(Iter&: StartI, D);
1910}
1911
1912const DSAStackTy::DSAVarData
1913DSAStackTy::hasDSA(ValueDecl *D,
1914 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1915 DefaultDataSharingAttributes)>
1916 CPred,
1917 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1918 bool FromParent) const {
1919 if (isStackEmpty())
1920 return {};
1921 D = getCanonicalDecl(D);
1922 const_iterator I = begin();
1923 const_iterator EndI = end();
1924 if (FromParent && I != EndI)
1925 ++I;
1926 for (; I != EndI; ++I) {
1927 if (!DPred(I->Directive) &&
1928 !isImplicitOrExplicitTaskingRegion(I->Directive))
1929 continue;
1930 const_iterator NewI = I;
1931 DSAVarData DVar = getDSA(Iter&: NewI, D);
1932 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1933 return DVar;
1934 }
1935 return {};
1936}
1937
1938const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1939 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1940 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1941 bool FromParent) const {
1942 if (isStackEmpty())
1943 return {};
1944 D = getCanonicalDecl(D);
1945 const_iterator StartI = begin();
1946 const_iterator EndI = end();
1947 if (FromParent && StartI != EndI)
1948 ++StartI;
1949 if (StartI == EndI || !DPred(StartI->Directive))
1950 return {};
1951 const_iterator NewI = StartI;
1952 DSAVarData DVar = getDSA(Iter&: NewI, D);
1953 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1954 ? DVar
1955 : DSAVarData();
1956}
1957
1958bool DSAStackTy::hasExplicitDSA(
1959 const ValueDecl *D,
1960 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1961 unsigned Level, bool NotLastprivate) const {
1962 if (getStackSize() <= Level)
1963 return false;
1964 D = getCanonicalDecl(D);
1965 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1966 auto I = StackElem.SharingMap.find(D);
1967 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1968 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1969 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1970 return true;
1971 // Check predetermined rules for the loop control variables.
1972 auto LI = StackElem.LCVMap.find(Val: D);
1973 if (LI != StackElem.LCVMap.end())
1974 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1975 return false;
1976}
1977
1978bool DSAStackTy::hasExplicitDirective(
1979 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1980 unsigned Level) const {
1981 if (getStackSize() <= Level)
1982 return false;
1983 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1984 return DPred(StackElem.Directive);
1985}
1986
1987bool DSAStackTy::hasDirective(
1988 const llvm::function_ref<bool(OpenMPDirectiveKind,
1989 const DeclarationNameInfo &, SourceLocation)>
1990 DPred,
1991 bool FromParent) const {
1992 // We look only in the enclosing region.
1993 size_t Skip = FromParent ? 2 : 1;
1994 for (const_iterator I = begin() + std::min(a: Skip, b: getStackSize()), E = end();
1995 I != E; ++I) {
1996 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
1997 return true;
1998 }
1999 return false;
2000}
2001
2002void SemaOpenMP::InitDataSharingAttributesStack() {
2003 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2004}
2005
2006#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2007
2008void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2009
2010void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2011 DSAStack->popFunction(OldFSI);
2012}
2013
2014static bool isOpenMPDeviceDelayedContext(Sema &S) {
2015 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2016 "Expected OpenMP device compilation.");
2017 return !S.OpenMP().isInOpenMPTargetExecutionDirective();
2018}
2019
2020namespace {
2021/// Status of the function emission on the host/device.
2022enum class FunctionEmissionStatus {
2023 Emitted,
2024 Discarded,
2025 Unknown,
2026};
2027} // anonymous namespace
2028
2029SemaBase::SemaDiagnosticBuilder
2030SemaOpenMP::diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID,
2031 const FunctionDecl *FD) {
2032 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2033 "Expected OpenMP device compilation.");
2034
2035 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2036 if (FD) {
2037 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(Decl: FD);
2038 switch (FES) {
2039 case Sema::FunctionEmissionStatus::Emitted:
2040 Kind = SemaDiagnosticBuilder::K_Immediate;
2041 break;
2042 case Sema::FunctionEmissionStatus::Unknown:
2043 // TODO: We should always delay diagnostics here in case a target
2044 // region is in a function we do not emit. However, as the
2045 // current diagnostics are associated with the function containing
2046 // the target region and we do not emit that one, we would miss out
2047 // on diagnostics for the target region itself. We need to anchor
2048 // the diagnostics with the new generated function *or* ensure we
2049 // emit diagnostics associated with the surrounding function.
2050 Kind = isOpenMPDeviceDelayedContext(S&: SemaRef)
2051 ? SemaDiagnosticBuilder::K_Deferred
2052 : SemaDiagnosticBuilder::K_Immediate;
2053 break;
2054 case Sema::FunctionEmissionStatus::TemplateDiscarded:
2055 case Sema::FunctionEmissionStatus::OMPDiscarded:
2056 Kind = SemaDiagnosticBuilder::K_Nop;
2057 break;
2058 case Sema::FunctionEmissionStatus::CUDADiscarded:
2059 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2060 break;
2061 }
2062 }
2063
2064 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2065}
2066
2067SemaBase::SemaDiagnosticBuilder
2068SemaOpenMP::diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID,
2069 const FunctionDecl *FD) {
2070 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2071 "Expected OpenMP host compilation.");
2072
2073 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2074 if (FD) {
2075 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(Decl: FD);
2076 switch (FES) {
2077 case Sema::FunctionEmissionStatus::Emitted:
2078 Kind = SemaDiagnosticBuilder::K_Immediate;
2079 break;
2080 case Sema::FunctionEmissionStatus::Unknown:
2081 Kind = SemaDiagnosticBuilder::K_Deferred;
2082 break;
2083 case Sema::FunctionEmissionStatus::TemplateDiscarded:
2084 case Sema::FunctionEmissionStatus::OMPDiscarded:
2085 case Sema::FunctionEmissionStatus::CUDADiscarded:
2086 Kind = SemaDiagnosticBuilder::K_Nop;
2087 break;
2088 }
2089 }
2090
2091 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2092}
2093
2094static OpenMPDefaultmapClauseKind
2095getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) {
2096 if (LO.OpenMP <= 45) {
2097 if (VD->getType().getNonReferenceType()->isScalarType())
2098 return OMPC_DEFAULTMAP_scalar;
2099 return OMPC_DEFAULTMAP_aggregate;
2100 }
2101 if (VD->getType().getNonReferenceType()->isAnyPointerType())
2102 return OMPC_DEFAULTMAP_pointer;
2103 if (VD->getType().getNonReferenceType()->isScalarType())
2104 return OMPC_DEFAULTMAP_scalar;
2105 return OMPC_DEFAULTMAP_aggregate;
2106}
2107
2108bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2109 unsigned OpenMPCaptureLevel) const {
2110 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2111
2112 ASTContext &Ctx = getASTContext();
2113 bool IsByRef = true;
2114
2115 // Find the directive that is associated with the provided scope.
2116 D = cast<ValueDecl>(D->getCanonicalDecl());
2117 QualType Ty = D->getType();
2118
2119 bool IsVariableUsedInMapClause = false;
2120 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2121 // This table summarizes how a given variable should be passed to the device
2122 // given its type and the clauses where it appears. This table is based on
2123 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2124 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2125 //
2126 // =========================================================================
2127 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2128 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2129 // =========================================================================
2130 // | scl | | | | - | | bycopy|
2131 // | scl | | - | x | - | - | bycopy|
2132 // | scl | | x | - | - | - | null |
2133 // | scl | x | | | - | | byref |
2134 // | scl | x | - | x | - | - | bycopy|
2135 // | scl | x | x | - | - | - | null |
2136 // | scl | | - | - | - | x | byref |
2137 // | scl | x | - | - | - | x | byref |
2138 //
2139 // | agg | n.a. | | | - | | byref |
2140 // | agg | n.a. | - | x | - | - | byref |
2141 // | agg | n.a. | x | - | - | - | null |
2142 // | agg | n.a. | - | - | - | x | byref |
2143 // | agg | n.a. | - | - | - | x[] | byref |
2144 //
2145 // | ptr | n.a. | | | - | | bycopy|
2146 // | ptr | n.a. | - | x | - | - | bycopy|
2147 // | ptr | n.a. | x | - | - | - | null |
2148 // | ptr | n.a. | - | - | - | x | byref |
2149 // | ptr | n.a. | - | - | - | x[] | bycopy|
2150 // | ptr | n.a. | - | - | x | | bycopy|
2151 // | ptr | n.a. | - | - | x | x | bycopy|
2152 // | ptr | n.a. | - | - | x | x[] | bycopy|
2153 // =========================================================================
2154 // Legend:
2155 // scl - scalar
2156 // ptr - pointer
2157 // agg - aggregate
2158 // x - applies
2159 // - - invalid in this combination
2160 // [] - mapped with an array section
2161 // byref - should be mapped by reference
2162 // byval - should be mapped by value
2163 // null - initialize a local variable to null on the device
2164 //
2165 // Observations:
2166 // - All scalar declarations that show up in a map clause have to be passed
2167 // by reference, because they may have been mapped in the enclosing data
2168 // environment.
2169 // - If the scalar value does not fit the size of uintptr, it has to be
2170 // passed by reference, regardless the result in the table above.
2171 // - For pointers mapped by value that have either an implicit map or an
2172 // array section, the runtime library may pass the NULL value to the
2173 // device instead of the value passed to it by the compiler.
2174
2175 if (Ty->isReferenceType())
2176 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2177
2178 // Locate map clauses and see if the variable being captured is referred to
2179 // in any of those clauses. Here we only care about variables, not fields,
2180 // because fields are part of aggregates.
2181 bool IsVariableAssociatedWithSection = false;
2182
2183 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2184 VD: D, Level,
2185 Check: [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2186 D](OMPClauseMappableExprCommon::MappableExprComponentListRef
2187 MapExprComponents,
2188 OpenMPClauseKind WhereFoundClauseKind) {
2189 // Both map and has_device_addr clauses information influences how a
2190 // variable is captured. E.g. is_device_ptr does not require changing
2191 // the default behavior.
2192 if (WhereFoundClauseKind != OMPC_map &&
2193 WhereFoundClauseKind != OMPC_has_device_addr)
2194 return false;
2195
2196 auto EI = MapExprComponents.rbegin();
2197 auto EE = MapExprComponents.rend();
2198
2199 assert(EI != EE && "Invalid map expression!");
2200
2201 if (isa<DeclRefExpr>(Val: EI->getAssociatedExpression()))
2202 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2203
2204 ++EI;
2205 if (EI == EE)
2206 return false;
2207 auto Last = std::prev(x: EE);
2208 const auto *UO =
2209 dyn_cast<UnaryOperator>(Val: Last->getAssociatedExpression());
2210 if ((UO && UO->getOpcode() == UO_Deref) ||
2211 isa<ArraySubscriptExpr>(Val: Last->getAssociatedExpression()) ||
2212 isa<ArraySectionExpr>(Val: Last->getAssociatedExpression()) ||
2213 isa<MemberExpr>(Val: EI->getAssociatedExpression()) ||
2214 isa<OMPArrayShapingExpr>(Val: Last->getAssociatedExpression())) {
2215 IsVariableAssociatedWithSection = true;
2216 // There is nothing more we need to know about this variable.
2217 return true;
2218 }
2219
2220 // Keep looking for more map info.
2221 return false;
2222 });
2223
2224 if (IsVariableUsedInMapClause) {
2225 // If variable is identified in a map clause it is always captured by
2226 // reference except if it is a pointer that is dereferenced somehow.
2227 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2228 } else {
2229 // By default, all the data that has a scalar type is mapped by copy
2230 // (except for reduction variables).
2231 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2232 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2233 !Ty->isAnyPointerType()) ||
2234 !Ty->isScalarType() ||
2235 DSAStack->isDefaultmapCapturedByRef(
2236 Level, Kind: getVariableCategoryFromDecl(getLangOpts(), D)) ||
2237 DSAStack->hasExplicitDSA(
2238 D,
2239 [](OpenMPClauseKind K, bool AppliedToPointee) {
2240 return K == OMPC_reduction && !AppliedToPointee;
2241 },
2242 Level);
2243 }
2244 }
2245
2246 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2247 IsByRef =
2248 ((IsVariableUsedInMapClause &&
2249 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2250 OMPD_target) ||
2251 !(DSAStack->hasExplicitDSA(
2252 D,
2253 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2254 return K == OMPC_firstprivate ||
2255 (K == OMPC_reduction && AppliedToPointee);
2256 },
2257 Level, /*NotLastprivate=*/true) ||
2258 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2259 // If the variable is artificial and must be captured by value - try to
2260 // capture by value.
2261 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2262 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2263 // If the variable is implicitly firstprivate and scalar - capture by
2264 // copy
2265 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2266 DSAStack->getDefaultDSA() == DSA_private) &&
2267 !DSAStack->hasExplicitDSA(
2268 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2269 Level) &&
2270 !DSAStack->isLoopControlVariable(D, Level).first);
2271 }
2272
2273 // When passing data by copy, we need to make sure it fits the uintptr size
2274 // and alignment, because the runtime library only deals with uintptr types.
2275 // If it does not fit the uintptr size, we need to pass the data by reference
2276 // instead.
2277 if (!IsByRef && (Ctx.getTypeSizeInChars(T: Ty) >
2278 Ctx.getTypeSizeInChars(T: Ctx.getUIntPtrType()) ||
2279 Ctx.getAlignOfGlobalVarInChars(T: Ty, VD: dyn_cast<VarDecl>(Val: D)) >
2280 Ctx.getTypeAlignInChars(T: Ctx.getUIntPtrType()))) {
2281 IsByRef = true;
2282 }
2283
2284 return IsByRef;
2285}
2286
2287unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2288 assert(getLangOpts().OpenMP);
2289 return DSAStack->getNestingLevel();
2290}
2291
2292bool SemaOpenMP::isInOpenMPTaskUntiedContext() const {
2293 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2294 DSAStack->isUntiedRegion();
2295}
2296
2297bool SemaOpenMP::isInOpenMPTargetExecutionDirective() const {
2298 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2299 !DSAStack->isClauseParsingMode()) ||
2300 DSAStack->hasDirective(
2301 [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2302 SourceLocation) -> bool {
2303 return isOpenMPTargetExecutionDirective(K);
2304 },
2305 false);
2306}
2307
2308bool SemaOpenMP::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2309 // Only rebuild for Field.
2310 if (!isa<FieldDecl>(Val: D))
2311 return false;
2312 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2313 D,
2314 [](OpenMPClauseKind C, bool AppliedToPointee,
2315 DefaultDataSharingAttributes DefaultAttr) {
2316 return isOpenMPPrivate(C) && !AppliedToPointee &&
2317 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2318 },
2319 [](OpenMPDirectiveKind) { return true; },
2320 DSAStack->isClauseParsingMode());
2321 if (DVarPrivate.CKind != OMPC_unknown)
2322 return true;
2323 return false;
2324}
2325
2326static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
2327 Expr *CaptureExpr, bool WithInit,
2328 DeclContext *CurContext,
2329 bool AsExpression);
2330
2331VarDecl *SemaOpenMP::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2332 unsigned StopAt) {
2333 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2334 D = getCanonicalDecl(D);
2335
2336 auto *VD = dyn_cast<VarDecl>(Val: D);
2337 // Do not capture constexpr variables.
2338 if (VD && VD->isConstexpr())
2339 return nullptr;
2340
2341 // If we want to determine whether the variable should be captured from the
2342 // perspective of the current capturing scope, and we've already left all the
2343 // capturing scopes of the top directive on the stack, check from the
2344 // perspective of its parent directive (if any) instead.
2345 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2346 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2347
2348 // If we are attempting to capture a global variable in a directive with
2349 // 'target' we return true so that this global is also mapped to the device.
2350 //
2351 if (VD && !VD->hasLocalStorage() &&
2352 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2353 SemaRef.getCurLambda())) {
2354 if (isInOpenMPTargetExecutionDirective()) {
2355 DSAStackTy::DSAVarData DVarTop =
2356 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2357 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2358 return VD;
2359 // If the declaration is enclosed in a 'declare target' directive,
2360 // then it should not be captured.
2361 //
2362 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2363 return nullptr;
2364 CapturedRegionScopeInfo *CSI = nullptr;
2365 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2366 RangeOrContainer: llvm::reverse(C&: SemaRef.FunctionScopes),
2367 N: CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2368 : 0)) {
2369 if (!isa<CapturingScopeInfo>(Val: FSI))
2370 return nullptr;
2371 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(Val: FSI))
2372 if (RSI->CapRegionKind == CR_OpenMP) {
2373 CSI = RSI;
2374 break;
2375 }
2376 }
2377 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2378 SmallVector<OpenMPDirectiveKind, 4> Regions;
2379 getOpenMPCaptureRegions(Regions,
2380 DSAStack->getDirective(CSI->OpenMPLevel));
2381 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2382 return VD;
2383 }
2384 if (isInOpenMPDeclareTargetContext()) {
2385 // Try to mark variable as declare target if it is used in capturing
2386 // regions.
2387 if (getLangOpts().OpenMP <= 45 &&
2388 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2389 checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
2390 return nullptr;
2391 }
2392 }
2393
2394 if (CheckScopeInfo) {
2395 bool OpenMPFound = false;
2396 for (unsigned I = StopAt + 1; I > 0; --I) {
2397 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2398 if (!isa<CapturingScopeInfo>(Val: FSI))
2399 return nullptr;
2400 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(Val: FSI))
2401 if (RSI->CapRegionKind == CR_OpenMP) {
2402 OpenMPFound = true;
2403 break;
2404 }
2405 }
2406 if (!OpenMPFound)
2407 return nullptr;
2408 }
2409
2410 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2411 (!DSAStack->isClauseParsingMode() ||
2412 DSAStack->getParentDirective() != OMPD_unknown)) {
2413 auto &&Info = DSAStack->isLoopControlVariable(D);
2414 if (Info.first ||
2415 (VD && VD->hasLocalStorage() &&
2416 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2417 (VD && DSAStack->isForceVarCapturing()))
2418 return VD ? VD : Info.second;
2419 DSAStackTy::DSAVarData DVarTop =
2420 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2421 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2422 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2423 return VD ? VD : cast<VarDecl>(Val: DVarTop.PrivateCopy->getDecl());
2424 // Threadprivate variables must not be captured.
2425 if (isOpenMPThreadPrivate(DVarTop.CKind))
2426 return nullptr;
2427 // The variable is not private or it is the variable in the directive with
2428 // default(none) clause and not used in any clause.
2429 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2430 D,
2431 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2432 return isOpenMPPrivate(C) && !AppliedToPointee;
2433 },
2434 [](OpenMPDirectiveKind) { return true; },
2435 DSAStack->isClauseParsingMode());
2436 // Global shared must not be captured.
2437 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2438 ((DSAStack->getDefaultDSA() != DSA_none &&
2439 DSAStack->getDefaultDSA() != DSA_private &&
2440 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2441 DVarTop.CKind == OMPC_shared))
2442 return nullptr;
2443 auto *FD = dyn_cast<FieldDecl>(Val: D);
2444 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2445 !DVarPrivate.PrivateCopy) {
2446 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2447 D,
2448 [](OpenMPClauseKind C, bool AppliedToPointee,
2449 DefaultDataSharingAttributes DefaultAttr) {
2450 return isOpenMPPrivate(C) && !AppliedToPointee &&
2451 (DefaultAttr == DSA_firstprivate ||
2452 DefaultAttr == DSA_private);
2453 },
2454 [](OpenMPDirectiveKind) { return true; },
2455 DSAStack->isClauseParsingMode());
2456 if (DVarPrivate.CKind == OMPC_unknown)
2457 return nullptr;
2458
2459 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2460 if (VD)
2461 return VD;
2462 if (SemaRef.getCurrentThisType().isNull())
2463 return nullptr;
2464 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(Loc: SourceLocation(),
2465 Type: SemaRef.getCurrentThisType(),
2466 /*IsImplicit=*/true);
2467 const CXXScopeSpec CS = CXXScopeSpec();
2468 Expr *ME = SemaRef.BuildMemberExpr(
2469 Base: ThisExpr, /*IsArrow=*/true, OpLoc: SourceLocation(),
2470 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: FD,
2471 FoundDecl: DeclAccessPair::make(D: FD, AS: FD->getAccess()),
2472 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(), Ty: FD->getType(),
2473 VK: VK_LValue, OK: OK_Ordinary);
2474 OMPCapturedExprDecl *CD = buildCaptureDecl(
2475 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2476 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2477 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2478 SemaRef, CD, CD->getType().getNonReferenceType(), SourceLocation());
2479 VD = cast<VarDecl>(Val: VDPrivateRefExpr->getDecl());
2480 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2481 return VD;
2482 }
2483 if (DVarPrivate.CKind != OMPC_unknown ||
2484 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2485 DSAStack->getDefaultDSA() == DSA_private ||
2486 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2487 return VD ? VD : cast<VarDecl>(Val: DVarPrivate.PrivateCopy->getDecl());
2488 }
2489 return nullptr;
2490}
2491
2492void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2493 unsigned Level) const {
2494 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2495}
2496
2497void SemaOpenMP::startOpenMPLoop() {
2498 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2499 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2500 DSAStack->loopInit();
2501}
2502
2503void SemaOpenMP::startOpenMPCXXRangeFor() {
2504 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2505 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2506 DSAStack->resetPossibleLoopCounter();
2507 DSAStack->loopStart();
2508 }
2509}
2510
2511OpenMPClauseKind SemaOpenMP::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2512 unsigned CapLevel) const {
2513 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2514 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2515 (!DSAStack->isClauseParsingMode() ||
2516 DSAStack->getParentDirective() != OMPD_unknown)) {
2517 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2518 D,
2519 [](OpenMPClauseKind C, bool AppliedToPointee,
2520 DefaultDataSharingAttributes DefaultAttr) {
2521 return isOpenMPPrivate(C) && !AppliedToPointee &&
2522 DefaultAttr == DSA_private;
2523 },
2524 [](OpenMPDirectiveKind) { return true; },
2525 DSAStack->isClauseParsingMode());
2526 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2527 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2528 !DSAStack->isLoopControlVariable(D).first)
2529 return OMPC_private;
2530 }
2531 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2532 bool IsTriviallyCopyable =
2533 D->getType().getNonReferenceType().isTriviallyCopyableType(
2534 Context: getASTContext()) &&
2535 !D->getType()
2536 .getNonReferenceType()
2537 .getCanonicalType()
2538 ->getAsCXXRecordDecl();
2539 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2540 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2541 getOpenMPCaptureRegions(CaptureRegions, DKind);
2542 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2543 (IsTriviallyCopyable ||
2544 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2545 if (DSAStack->hasExplicitDSA(
2546 D,
2547 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2548 Level, /*NotLastprivate=*/true))
2549 return OMPC_firstprivate;
2550 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2551 if (DVar.CKind != OMPC_shared &&
2552 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2553 DSAStack->addImplicitTaskFirstprivate(Level, D);
2554 return OMPC_firstprivate;
2555 }
2556 }
2557 }
2558 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2559 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2560 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2561 DSAStack->resetPossibleLoopCounter(D);
2562 DSAStack->loopStart();
2563 return OMPC_private;
2564 }
2565 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2566 DSAStack->isLoopControlVariable(D).first) &&
2567 !DSAStack->hasExplicitDSA(
2568 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2569 Level) &&
2570 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2571 return OMPC_private;
2572 }
2573 if (const auto *VD = dyn_cast<VarDecl>(Val: D)) {
2574 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2575 DSAStack->isForceVarCapturing() &&
2576 !DSAStack->hasExplicitDSA(
2577 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2578 Level))
2579 return OMPC_private;
2580 }
2581 // User-defined allocators are private since they must be defined in the
2582 // context of target region.
2583 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2584 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2585 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2586 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2587 return OMPC_private;
2588 return (DSAStack->hasExplicitDSA(
2589 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2590 Level) ||
2591 (DSAStack->isClauseParsingMode() &&
2592 DSAStack->getClauseParsingMode() == OMPC_private) ||
2593 // Consider taskgroup reduction descriptor variable a private
2594 // to avoid possible capture in the region.
2595 (DSAStack->hasExplicitDirective(
2596 [](OpenMPDirectiveKind K) {
2597 return K == OMPD_taskgroup ||
2598 ((isOpenMPParallelDirective(K) ||
2599 isOpenMPWorksharingDirective(K)) &&
2600 !isOpenMPSimdDirective(K));
2601 },
2602 Level) &&
2603 DSAStack->isTaskgroupReductionRef(D, Level)))
2604 ? OMPC_private
2605 : OMPC_unknown;
2606}
2607
2608void SemaOpenMP::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2609 unsigned Level) {
2610 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2611 D = getCanonicalDecl(D);
2612 OpenMPClauseKind OMPC = OMPC_unknown;
2613 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2614 const unsigned NewLevel = I - 1;
2615 if (DSAStack->hasExplicitDSA(
2616 D,
2617 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2618 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2619 OMPC = K;
2620 return true;
2621 }
2622 return false;
2623 },
2624 NewLevel))
2625 break;
2626 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2627 VD: D, Level: NewLevel,
2628 Check: [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2629 OpenMPClauseKind) { return true; })) {
2630 OMPC = OMPC_map;
2631 break;
2632 }
2633 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2634 NewLevel)) {
2635 OMPC = OMPC_map;
2636 if (DSAStack->mustBeFirstprivateAtLevel(
2637 NewLevel, getVariableCategoryFromDecl(getLangOpts(), D)))
2638 OMPC = OMPC_firstprivate;
2639 break;
2640 }
2641 }
2642 if (OMPC != OMPC_unknown)
2643 FD->addAttr(
2644 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2645}
2646
2647bool SemaOpenMP::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2648 unsigned CaptureLevel) const {
2649 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2650 // Return true if the current level is no longer enclosed in a target region.
2651
2652 SmallVector<OpenMPDirectiveKind, 4> Regions;
2653 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2654 const auto *VD = dyn_cast<VarDecl>(Val: D);
2655 return VD && !VD->hasLocalStorage() &&
2656 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2657 Level) &&
2658 Regions[CaptureLevel] != OMPD_task;
2659}
2660
2661bool SemaOpenMP::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2662 unsigned CaptureLevel) const {
2663 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2664 // Return true if the current level is no longer enclosed in a target region.
2665
2666 if (const auto *VD = dyn_cast<VarDecl>(Val: D)) {
2667 if (!VD->hasLocalStorage()) {
2668 if (isInOpenMPTargetExecutionDirective())
2669 return true;
2670 DSAStackTy::DSAVarData TopDVar =
2671 DSAStack->getTopDSA(D, /*FromParent=*/false);
2672 unsigned NumLevels =
2673 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2674 if (Level == 0)
2675 // non-file scope static variable with default(firstprivate)
2676 // should be global captured.
2677 return (NumLevels == CaptureLevel + 1 &&
2678 (TopDVar.CKind != OMPC_shared ||
2679 DSAStack->getDefaultDSA() == DSA_firstprivate));
2680 do {
2681 --Level;
2682 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2683 if (DVar.CKind != OMPC_shared)
2684 return true;
2685 } while (Level > 0);
2686 }
2687 }
2688 return true;
2689}
2690
2691void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2692
2693void SemaOpenMP::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2694 OMPTraitInfo &TI) {
2695 OMPDeclareVariantScopes.push_back(Elt: OMPDeclareVariantScope(TI));
2696}
2697
2698void SemaOpenMP::ActOnOpenMPEndDeclareVariant() {
2699 assert(isInOpenMPDeclareVariantScope() &&
2700 "Not in OpenMP declare variant scope!");
2701
2702 OMPDeclareVariantScopes.pop_back();
2703}
2704
2705void SemaOpenMP::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2706 const FunctionDecl *Callee,
2707 SourceLocation Loc) {
2708 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2709 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2710 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2711 // Ignore host functions during device analysis.
2712 if (getLangOpts().OpenMPIsTargetDevice &&
2713 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2714 return;
2715 // Ignore nohost functions during host analysis.
2716 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2717 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2718 return;
2719 const FunctionDecl *FD = Callee->getMostRecentDecl();
2720 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2721 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2722 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2723 // Diagnose host function called during device codegen.
2724 StringRef HostDevTy =
2725 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2726 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2727 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2728 diag::note_omp_marked_device_type_here)
2729 << HostDevTy;
2730 return;
2731 }
2732 if (!getLangOpts().OpenMPIsTargetDevice &&
2733 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2734 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2735 // In OpenMP 5.2 or later, if the function has a host variant then allow
2736 // that to be called instead
2737 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2738 for (OMPDeclareVariantAttr *A :
2739 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2740 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2741 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2742 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2743 OMPDeclareTargetDeclAttr::getDeviceType(
2744 VariantFD->getMostRecentDecl());
2745 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2746 return true;
2747 }
2748 return false;
2749 };
2750 if (getLangOpts().OpenMP >= 52 &&
2751 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2752 return;
2753 // Diagnose nohost function called during host codegen.
2754 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2755 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2756 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2757 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2758 diag::note_omp_marked_device_type_here)
2759 << NoHostDevTy;
2760 }
2761}
2762
2763void SemaOpenMP::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2764 const DeclarationNameInfo &DirName,
2765 Scope *CurScope, SourceLocation Loc) {
2766 DSAStack->push(DKind, DirName, CurScope, Loc);
2767 SemaRef.PushExpressionEvaluationContext(
2768 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
2769}
2770
2771void SemaOpenMP::StartOpenMPClause(OpenMPClauseKind K) {
2772 DSAStack->setClauseParsingMode(K);
2773}
2774
2775void SemaOpenMP::EndOpenMPClause() {
2776 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2777 SemaRef.CleanupVarDeclMarking();
2778}
2779
2780static std::pair<ValueDecl *, bool>
2781getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2782 SourceRange &ERange, bool AllowArraySection = false,
2783 StringRef DiagType = "");
2784
2785/// Check consistency of the reduction clauses.
2786static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2787 ArrayRef<OMPClause *> Clauses) {
2788 bool InscanFound = false;
2789 SourceLocation InscanLoc;
2790 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2791 // A reduction clause without the inscan reduction-modifier may not appear on
2792 // a construct on which a reduction clause with the inscan reduction-modifier
2793 // appears.
2794 for (OMPClause *C : Clauses) {
2795 if (C->getClauseKind() != OMPC_reduction)
2796 continue;
2797 auto *RC = cast<OMPReductionClause>(Val: C);
2798 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2799 InscanFound = true;
2800 InscanLoc = RC->getModifierLoc();
2801 continue;
2802 }
2803 if (RC->getModifier() == OMPC_REDUCTION_task) {
2804 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2805 // A reduction clause with the task reduction-modifier may only appear on
2806 // a parallel construct, a worksharing construct or a combined or
2807 // composite construct for which any of the aforementioned constructs is a
2808 // constituent construct and simd or loop are not constituent constructs.
2809 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2810 if (!(isOpenMPParallelDirective(CurDir) ||
2811 isOpenMPWorksharingDirective(CurDir)) ||
2812 isOpenMPSimdDirective(CurDir))
2813 S.Diag(RC->getModifierLoc(),
2814 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2815 continue;
2816 }
2817 }
2818 if (InscanFound) {
2819 for (OMPClause *C : Clauses) {
2820 if (C->getClauseKind() != OMPC_reduction)
2821 continue;
2822 auto *RC = cast<OMPReductionClause>(Val: C);
2823 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2824 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2825 ? RC->getBeginLoc()
2826 : RC->getModifierLoc(),
2827 diag::err_omp_inscan_reduction_expected);
2828 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2829 continue;
2830 }
2831 for (Expr *Ref : RC->varlist()) {
2832 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2833 SourceLocation ELoc;
2834 SourceRange ERange;
2835 Expr *SimpleRefExpr = Ref;
2836 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2837 /*AllowArraySection=*/true);
2838 ValueDecl *D = Res.first;
2839 if (!D)
2840 continue;
2841 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2842 S.Diag(Ref->getExprLoc(),
2843 diag::err_omp_reduction_not_inclusive_exclusive)
2844 << Ref->getSourceRange();
2845 }
2846 }
2847 }
2848 }
2849}
2850
2851static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2852 ArrayRef<OMPClause *> Clauses);
2853static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2854 bool WithInit);
2855
2856static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2857 const ValueDecl *D,
2858 const DSAStackTy::DSAVarData &DVar,
2859 bool IsLoopIterVar = false);
2860
2861void SemaOpenMP::EndOpenMPDSABlock(Stmt *CurDirective) {
2862 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2863 // A variable of class type (or array thereof) that appears in a lastprivate
2864 // clause requires an accessible, unambiguous default constructor for the
2865 // class type, unless the list item is also specified in a firstprivate
2866 // clause.
2867
2868 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2869 SmallVector<Expr *, 8> PrivateCopies;
2870 for (Expr *DE : Clause->varlist()) {
2871 if (DE->isValueDependent() || DE->isTypeDependent()) {
2872 PrivateCopies.push_back(nullptr);
2873 continue;
2874 }
2875 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2876 auto *VD = cast<VarDecl>(DRE->getDecl());
2877 QualType Type = VD->getType().getNonReferenceType();
2878 const DSAStackTy::DSAVarData DVar =
2879 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2880 if (DVar.CKind != OMPC_lastprivate) {
2881 // The variable is also a firstprivate, so initialization sequence
2882 // for private copy is generated already.
2883 PrivateCopies.push_back(nullptr);
2884 continue;
2885 }
2886 // Generate helper private variable and initialize it with the
2887 // default value. The address of the original variable is replaced
2888 // by the address of the new private variable in CodeGen. This new
2889 // variable is not added to IdResolver, so the code in the OpenMP
2890 // region uses original variable for proper diagnostics.
2891 VarDecl *VDPrivate = buildVarDecl(
2892 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(),
2893 VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2894 SemaRef.ActOnUninitializedDecl(VDPrivate);
2895 if (VDPrivate->isInvalidDecl()) {
2896 PrivateCopies.push_back(nullptr);
2897 continue;
2898 }
2899 PrivateCopies.push_back(buildDeclRefExpr(
2900 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2901 }
2902 Clause->setPrivateCopies(PrivateCopies);
2903 };
2904
2905 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
2906 // Finalize nontemporal clause by handling private copies, if any.
2907 SmallVector<Expr *, 8> PrivateRefs;
2908 for (Expr *RefExpr : Clause->varlist()) {
2909 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2910 SourceLocation ELoc;
2911 SourceRange ERange;
2912 Expr *SimpleRefExpr = RefExpr;
2913 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
2914 if (Res.second)
2915 // It will be analyzed later.
2916 PrivateRefs.push_back(RefExpr);
2917 ValueDecl *D = Res.first;
2918 if (!D)
2919 continue;
2920
2921 const DSAStackTy::DSAVarData DVar =
2922 DSAStack->getTopDSA(D, /*FromParent=*/false);
2923 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2924 : SimpleRefExpr);
2925 }
2926 Clause->setPrivateRefs(PrivateRefs);
2927 };
2928
2929 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
2930 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2931 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2932 auto *DRE = dyn_cast<DeclRefExpr>(Val: D.Allocator->IgnoreParenImpCasts());
2933 if (!DRE)
2934 continue;
2935 ValueDecl *VD = DRE->getDecl();
2936 if (!VD || !isa<VarDecl>(Val: VD))
2937 continue;
2938 DSAStackTy::DSAVarData DVar =
2939 DSAStack->getTopDSA(D: VD, /*FromParent=*/false);
2940 // OpenMP [2.12.5, target Construct]
2941 // Memory allocators that appear in a uses_allocators clause cannot
2942 // appear in other data-sharing attribute clauses or data-mapping
2943 // attribute clauses in the same construct.
2944 Expr *MapExpr = nullptr;
2945 if (DVar.RefExpr ||
2946 DSAStack->checkMappableExprComponentListsForDecl(
2947 VD, /*CurrentRegionOnly=*/true,
2948 Check: [VD, &MapExpr](
2949 OMPClauseMappableExprCommon::MappableExprComponentListRef
2950 MapExprComponents,
2951 OpenMPClauseKind C) {
2952 auto MI = MapExprComponents.rbegin();
2953 auto ME = MapExprComponents.rend();
2954 if (MI != ME &&
2955 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2956 VD->getCanonicalDecl()) {
2957 MapExpr = MI->getAssociatedExpression();
2958 return true;
2959 }
2960 return false;
2961 })) {
2962 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
2963 << D.Allocator->getSourceRange();
2964 if (DVar.RefExpr)
2965 reportOriginalDsa(SemaRef, DSAStack, D: VD, DVar);
2966 else
2967 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2968 << MapExpr->getSourceRange();
2969 }
2970 }
2971 };
2972
2973 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(Val: CurDirective)) {
2974 for (OMPClause *C : D->clauses()) {
2975 if (auto *Clause = dyn_cast<OMPLastprivateClause>(Val: C)) {
2976 FinalizeLastprivate(Clause);
2977 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(Val: C)) {
2978 FinalizeNontemporal(Clause);
2979 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(Val: C)) {
2980 FinalizeAllocators(Clause);
2981 }
2982 }
2983 // Check allocate clauses.
2984 if (!SemaRef.CurContext->isDependentContext())
2985 checkAllocateClauses(S&: SemaRef, DSAStack, Clauses: D->clauses());
2986 checkReductionClauses(S&: SemaRef, DSAStack, Clauses: D->clauses());
2987 }
2988
2989 DSAStack->pop();
2990 SemaRef.DiscardCleanupsInEvaluationContext();
2991 SemaRef.PopExpressionEvaluationContext();
2992}
2993
2994static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
2995 Expr *NumIterations, Sema &SemaRef,
2996 Scope *S, DSAStackTy *Stack);
2997
2998static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
2999 OMPLoopBasedDirective::HelperExprs &B,
3000 DSAStackTy *Stack) {
3001 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3002 "loop exprs were not built");
3003
3004 if (SemaRef.CurContext->isDependentContext())
3005 return false;
3006
3007 // Finalize the clauses that need pre-built expressions for CodeGen.
3008 for (OMPClause *C : Clauses) {
3009 auto *LC = dyn_cast<OMPLinearClause>(Val: C);
3010 if (!LC)
3011 continue;
3012 if (FinishOpenMPLinearClause(Clause&: *LC, IV: cast<DeclRefExpr>(Val: B.IterationVarRef),
3013 NumIterations: B.NumIterations, SemaRef,
3014 S: SemaRef.getCurScope(), Stack))
3015 return true;
3016 }
3017
3018 return false;
3019}
3020
3021namespace {
3022
3023class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3024private:
3025 Sema &SemaRef;
3026
3027public:
3028 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3029 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3030 NamedDecl *ND = Candidate.getCorrectionDecl();
3031 if (const auto *VD = dyn_cast_or_null<VarDecl>(Val: ND)) {
3032 return VD->hasGlobalStorage() &&
3033 SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(),
3034 S: SemaRef.getCurScope());
3035 }
3036 return false;
3037 }
3038
3039 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3040 return std::make_unique<VarDeclFilterCCC>(args&: *this);
3041 }
3042};
3043
3044class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3045private:
3046 Sema &SemaRef;
3047
3048public:
3049 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3050 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3051 NamedDecl *ND = Candidate.getCorrectionDecl();
3052 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3053 isa<FunctionDecl>(ND))) {
3054 return SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(),
3055 S: SemaRef.getCurScope());
3056 }
3057 return false;
3058 }
3059
3060 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3061 return std::make_unique<VarOrFuncDeclFilterCCC>(args&: *this);
3062 }
3063};
3064
3065} // namespace
3066
3067ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope,
3068 CXXScopeSpec &ScopeSpec,
3069 const DeclarationNameInfo &Id,
3070 OpenMPDirectiveKind Kind) {
3071 ASTContext &Context = getASTContext();
3072 unsigned OMPVersion = getLangOpts().OpenMP;
3073 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
3074 SemaRef.LookupParsedName(R&: Lookup, S: CurScope, SS: &ScopeSpec,
3075 /*ObjectType=*/QualType(),
3076 /*AllowBuiltinCreation=*/true);
3077
3078 if (Lookup.isAmbiguous())
3079 return ExprError();
3080
3081 VarDecl *VD;
3082 if (!Lookup.isSingleResult()) {
3083 VarDeclFilterCCC CCC(SemaRef);
3084 if (TypoCorrection Corrected =
3085 SemaRef.CorrectTypo(Typo: Id, LookupKind: Sema::LookupOrdinaryName, S: CurScope, SS: nullptr,
3086 CCC, Mode: CorrectTypoKind::ErrorRecovery)) {
3087 SemaRef.diagnoseTypo(
3088 Corrected,
3089 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3090 : diag::err_omp_expected_var_arg_suggest)
3091 << Id.getName());
3092 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3093 } else {
3094 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3095 : diag::err_omp_expected_var_arg)
3096 << Id.getName();
3097 return ExprError();
3098 }
3099 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3100 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3101 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3102 return ExprError();
3103 }
3104 Lookup.suppressDiagnostics();
3105
3106 // OpenMP [2.9.2, Syntax, C/C++]
3107 // Variables must be file-scope, namespace-scope, or static block-scope.
3108 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3109 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3110 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->isStaticLocal();
3111 bool IsDecl =
3112 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3113 Diag(VD->getLocation(),
3114 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3115 << VD;
3116 return ExprError();
3117 }
3118
3119 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3120 NamedDecl *ND = CanonicalVD;
3121 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3122 // A threadprivate directive for file-scope variables must appear outside
3123 // any definition or declaration.
3124 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3125 !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3126 Diag(Id.getLoc(), diag::err_omp_var_scope)
3127 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3128 bool IsDecl =
3129 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3130 Diag(VD->getLocation(),
3131 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3132 << VD;
3133 return ExprError();
3134 }
3135 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3136 // A threadprivate directive for static class member variables must appear
3137 // in the class definition, in the same scope in which the member
3138 // variables are declared.
3139 if (CanonicalVD->isStaticDataMember() &&
3140 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3141 Diag(Id.getLoc(), diag::err_omp_var_scope)
3142 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3143 bool IsDecl =
3144 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3145 Diag(VD->getLocation(),
3146 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3147 << VD;
3148 return ExprError();
3149 }
3150 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3151 // A threadprivate directive for namespace-scope variables must appear
3152 // outside any definition or declaration other than the namespace
3153 // definition itself.
3154 if (CanonicalVD->getDeclContext()->isNamespace() &&
3155 (!SemaRef.getCurLexicalContext()->isFileContext() ||
3156 !SemaRef.getCurLexicalContext()->Encloses(
3157 DC: CanonicalVD->getDeclContext()))) {
3158 Diag(Id.getLoc(), diag::err_omp_var_scope)
3159 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3160 bool IsDecl =
3161 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3162 Diag(VD->getLocation(),
3163 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3164 << VD;
3165 return ExprError();
3166 }
3167 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3168 // A threadprivate directive for static block-scope variables must appear
3169 // in the scope of the variable and not in a nested scope.
3170 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3171 !SemaRef.isDeclInScope(D: ND, Ctx: SemaRef.getCurLexicalContext(), S: CurScope)) {
3172 Diag(Id.getLoc(), diag::err_omp_var_scope)
3173 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3174 bool IsDecl =
3175 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3176 Diag(VD->getLocation(),
3177 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3178 << VD;
3179 return ExprError();
3180 }
3181
3182 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3183 // A threadprivate directive must lexically precede all references to any
3184 // of the variables in its list.
3185 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3186 !DSAStack->isThreadPrivate(VD)) {
3187 Diag(Id.getLoc(), diag::err_omp_var_used)
3188 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3189 return ExprError();
3190 }
3191
3192 QualType ExprType = VD->getType().getNonReferenceType();
3193 return DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
3194 SourceLocation(), VD,
3195 /*RefersToEnclosingVariableOrCapture=*/false,
3196 Id.getLoc(), ExprType, VK_LValue);
3197}
3198
3199SemaOpenMP::DeclGroupPtrTy
3200SemaOpenMP::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3201 ArrayRef<Expr *> VarList) {
3202 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3203 SemaRef.CurContext->addDecl(D);
3204 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3205 }
3206 return nullptr;
3207}
3208
3209namespace {
3210class LocalVarRefChecker final
3211 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3212 Sema &SemaRef;
3213
3214public:
3215 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3216 if (const auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
3217 if (VD->hasLocalStorage()) {
3218 SemaRef.Diag(E->getBeginLoc(),
3219 diag::err_omp_local_var_in_threadprivate_init)
3220 << E->getSourceRange();
3221 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3222 << VD << VD->getSourceRange();
3223 return true;
3224 }
3225 }
3226 return false;
3227 }
3228 bool VisitStmt(const Stmt *S) {
3229 for (const Stmt *Child : S->children()) {
3230 if (Child && Visit(Child))
3231 return true;
3232 }
3233 return false;
3234 }
3235 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3236};
3237} // namespace
3238
3239OMPThreadPrivateDecl *
3240SemaOpenMP::CheckOMPThreadPrivateDecl(SourceLocation Loc,
3241 ArrayRef<Expr *> VarList) {
3242 ASTContext &Context = getASTContext();
3243 SmallVector<Expr *, 8> Vars;
3244 for (Expr *RefExpr : VarList) {
3245 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3246 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3247 SourceLocation ILoc = DE->getExprLoc();
3248
3249 // Mark variable as used.
3250 VD->setReferenced();
3251 VD->markUsed(Context);
3252
3253 QualType QType = VD->getType();
3254 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3255 // It will be analyzed later.
3256 Vars.push_back(DE);
3257 continue;
3258 }
3259
3260 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3261 // A threadprivate variable must not have an incomplete type.
3262 if (SemaRef.RequireCompleteType(
3263 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3264 continue;
3265 }
3266
3267 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3268 // A threadprivate variable must not have a reference type.
3269 if (VD->getType()->isReferenceType()) {
3270 unsigned OMPVersion = getLangOpts().OpenMP;
3271 Diag(ILoc, diag::err_omp_ref_type_arg)
3272 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3273 << VD->getType();
3274 bool IsDecl =
3275 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3276 Diag(VD->getLocation(),
3277 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3278 << VD;
3279 continue;
3280 }
3281
3282 // Check if this is a TLS variable. If TLS is not being supported, produce
3283 // the corresponding diagnostic.
3284 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3285 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3286 getLangOpts().OpenMPUseTLS &&
3287 getASTContext().getTargetInfo().isTLSSupported())) ||
3288 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3289 !VD->isLocalVarDecl())) {
3290 Diag(ILoc, diag::err_omp_var_thread_local)
3291 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3292 bool IsDecl =
3293 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3294 Diag(VD->getLocation(),
3295 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3296 << VD;
3297 continue;
3298 }
3299
3300 // Check if initial value of threadprivate variable reference variable with
3301 // local storage (it is not supported by runtime).
3302 if (const Expr *Init = VD->getAnyInitializer()) {
3303 LocalVarRefChecker Checker(SemaRef);
3304 if (Checker.Visit(Init))
3305 continue;
3306 }
3307
3308 Vars.push_back(Elt: RefExpr);
3309 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3310 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3311 Context, SourceRange(Loc, Loc)));
3312 if (ASTMutationListener *ML = Context.getASTMutationListener())
3313 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3314 }
3315 OMPThreadPrivateDecl *D = nullptr;
3316 if (!Vars.empty()) {
3317 D = OMPThreadPrivateDecl::Create(C&: Context, DC: SemaRef.getCurLexicalContext(),
3318 L: Loc, VL: Vars);
3319 D->setAccess(AS_public);
3320 }
3321 return D;
3322}
3323
3324static OMPAllocateDeclAttr::AllocatorTypeTy
3325getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3326 if (!Allocator)
3327 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3328 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3329 Allocator->isInstantiationDependent() ||
3330 Allocator->containsUnexpandedParameterPack())
3331 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3332 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3333 llvm::FoldingSetNodeID AEId;
3334 const Expr *AE = Allocator->IgnoreParenImpCasts();
3335 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3336 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3337 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3338 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3339 llvm::FoldingSetNodeID DAEId;
3340 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3341 /*Canonical=*/true);
3342 if (AEId == DAEId) {
3343 AllocatorKindRes = AllocatorKind;
3344 break;
3345 }
3346 }
3347 return AllocatorKindRes;
3348}
3349
3350static bool checkPreviousOMPAllocateAttribute(
3351 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3352 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3353 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3354 return false;
3355 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3356 Expr *PrevAllocator = A->getAllocator();
3357 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3358 getAllocatorKind(S, Stack, PrevAllocator);
3359 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3360 if (AllocatorsMatch &&
3361 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3362 Allocator && PrevAllocator) {
3363 const Expr *AE = Allocator->IgnoreParenImpCasts();
3364 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3365 llvm::FoldingSetNodeID AEId, PAEId;
3366 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3367 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3368 AllocatorsMatch = AEId == PAEId;
3369 }
3370 if (!AllocatorsMatch) {
3371 SmallString<256> AllocatorBuffer;
3372 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3373 if (Allocator)
3374 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3375 SmallString<256> PrevAllocatorBuffer;
3376 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3377 if (PrevAllocator)
3378 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3379 S.getPrintingPolicy());
3380
3381 SourceLocation AllocatorLoc =
3382 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3383 SourceRange AllocatorRange =
3384 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3385 SourceLocation PrevAllocatorLoc =
3386 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3387 SourceRange PrevAllocatorRange =
3388 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3389 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3390 << (Allocator ? 1 : 0) << AllocatorStream.str()
3391 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3392 << AllocatorRange;
3393 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3394 << PrevAllocatorRange;
3395 return true;
3396 }
3397 return false;
3398}
3399
3400static void
3401applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3402 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3403 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3404 if (VD->hasAttr<OMPAllocateDeclAttr>())
3405 return;
3406 if (Alignment &&
3407 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3408 Alignment->isInstantiationDependent() ||
3409 Alignment->containsUnexpandedParameterPack()))
3410 // Apply later when we have a usable value.
3411 return;
3412 if (Allocator &&
3413 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3414 Allocator->isInstantiationDependent() ||
3415 Allocator->containsUnexpandedParameterPack()))
3416 return;
3417 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3418 Allocator, Alignment, SR);
3419 VD->addAttr(A: A);
3420 if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3421 ML->DeclarationMarkedOpenMPAllocate(D: VD, A: A);
3422}
3423
3424SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPAllocateDirective(
3425 SourceLocation Loc, ArrayRef<Expr *> VarList, ArrayRef<OMPClause *> Clauses,
3426 DeclContext *Owner) {
3427 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3428 Expr *Alignment = nullptr;
3429 Expr *Allocator = nullptr;
3430 if (Clauses.empty()) {
3431 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3432 // allocate directives that appear in a target region must specify an
3433 // allocator clause unless a requires directive with the dynamic_allocators
3434 // clause is present in the same compilation unit.
3435 if (getLangOpts().OpenMPIsTargetDevice &&
3436 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3437 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3438 } else {
3439 for (const OMPClause *C : Clauses)
3440 if (const auto *AC = dyn_cast<OMPAllocatorClause>(Val: C))
3441 Allocator = AC->getAllocator();
3442 else if (const auto *AC = dyn_cast<OMPAlignClause>(Val: C))
3443 Alignment = AC->getAlignment();
3444 else
3445 llvm_unreachable("Unexpected clause on allocate directive");
3446 }
3447 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3448 getAllocatorKind(SemaRef, DSAStack, Allocator);
3449 SmallVector<Expr *, 8> Vars;
3450 for (Expr *RefExpr : VarList) {
3451 auto *DE = cast<DeclRefExpr>(Val: RefExpr);
3452 auto *VD = cast<VarDecl>(Val: DE->getDecl());
3453
3454 // Check if this is a TLS variable or global register.
3455 if (VD->getTLSKind() != VarDecl::TLS_None ||
3456 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3457 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3458 !VD->isLocalVarDecl()))
3459 continue;
3460
3461 // If the used several times in the allocate directive, the same allocator
3462 // must be used.
3463 if (checkPreviousOMPAllocateAttribute(SemaRef, DSAStack, RefExpr, VD,
3464 AllocatorKind, Allocator))
3465 continue;
3466
3467 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3468 // If a list item has a static storage type, the allocator expression in the
3469 // allocator clause must be a constant expression that evaluates to one of
3470 // the predefined memory allocator values.
3471 if (Allocator && VD->hasGlobalStorage()) {
3472 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3473 Diag(Allocator->getExprLoc(),
3474 diag::err_omp_expected_predefined_allocator)
3475 << Allocator->getSourceRange();
3476 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3477 VarDecl::DeclarationOnly;
3478 Diag(VD->getLocation(),
3479 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3480 << VD;
3481 continue;
3482 }
3483 }
3484
3485 Vars.push_back(Elt: RefExpr);
3486 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3487 DE->getSourceRange());
3488 }
3489 if (Vars.empty())
3490 return nullptr;
3491 if (!Owner)
3492 Owner = SemaRef.getCurLexicalContext();
3493 auto *D = OMPAllocateDecl::Create(C&: getASTContext(), DC: Owner, L: Loc, VL: Vars, CL: Clauses);
3494 D->setAccess(AS_public);
3495 Owner->addDecl(D: D);
3496 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3497}
3498
3499SemaOpenMP::DeclGroupPtrTy
3500SemaOpenMP::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3501 ArrayRef<OMPClause *> ClauseList) {
3502 OMPRequiresDecl *D = nullptr;
3503 if (!SemaRef.CurContext->isFileContext()) {
3504 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3505 } else {
3506 D = CheckOMPRequiresDecl(Loc, ClauseList);
3507 if (D) {
3508 SemaRef.CurContext->addDecl(D);
3509 DSAStack->addRequiresDecl(RD: D);
3510 }
3511 }
3512 return DeclGroupPtrTy::make(P: DeclGroupRef(D));
3513}
3514
3515void SemaOpenMP::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3516 OpenMPDirectiveKind DKind,
3517 ArrayRef<std::string> Assumptions,
3518 bool SkippedClauses) {
3519 if (!SkippedClauses && Assumptions.empty()) {
3520 unsigned OMPVersion = getLangOpts().OpenMP;
3521 Diag(Loc, diag::err_omp_no_clause_for_directive)
3522 << llvm::omp::getAllAssumeClauseOptions()
3523 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3524 }
3525
3526 auto *AA =
3527 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3528 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3529 OMPAssumeScoped.push_back(AA);
3530 return;
3531 }
3532
3533 // Global assumes without assumption clauses are ignored.
3534 if (Assumptions.empty())
3535 return;
3536
3537 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3538 "Unexpected omp assumption directive!");
3539 OMPAssumeGlobal.push_back(AA);
3540
3541 // The OMPAssumeGlobal scope above will take care of new declarations but
3542 // we also want to apply the assumption to existing ones, e.g., to
3543 // declarations in included headers. To this end, we traverse all existing
3544 // declaration contexts and annotate function declarations here.
3545 SmallVector<DeclContext *, 8> DeclContexts;
3546 auto *Ctx = SemaRef.CurContext;
3547 while (Ctx->getLexicalParent())
3548 Ctx = Ctx->getLexicalParent();
3549 DeclContexts.push_back(Elt: Ctx);
3550 while (!DeclContexts.empty()) {
3551 DeclContext *DC = DeclContexts.pop_back_val();
3552 for (auto *SubDC : DC->decls()) {
3553 if (SubDC->isInvalidDecl())
3554 continue;
3555 if (auto *CTD = dyn_cast<ClassTemplateDecl>(Val: SubDC)) {
3556 DeclContexts.push_back(CTD->getTemplatedDecl());
3557 llvm::append_range(C&: DeclContexts, R: CTD->specializations());
3558 continue;
3559 }
3560 if (auto *DC = dyn_cast<DeclContext>(Val: SubDC))
3561 DeclContexts.push_back(Elt: DC);
3562 if (auto *F = dyn_cast<FunctionDecl>(Val: SubDC)) {
3563 F->addAttr(A: AA);
3564 continue;
3565 }
3566 }
3567 }
3568}
3569
3570void SemaOpenMP::ActOnOpenMPEndAssumesDirective() {
3571 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3572 OMPAssumeScoped.pop_back();
3573}
3574
3575StmtResult SemaOpenMP::ActOnOpenMPAssumeDirective(ArrayRef<OMPClause *> Clauses,
3576 Stmt *AStmt,
3577 SourceLocation StartLoc,
3578 SourceLocation EndLoc) {
3579 if (!AStmt)
3580 return StmtError();
3581
3582 return OMPAssumeDirective::Create(Ctx: getASTContext(), StartLoc, EndLoc, Clauses,
3583 AStmt);
3584}
3585
3586OMPRequiresDecl *
3587SemaOpenMP::CheckOMPRequiresDecl(SourceLocation Loc,
3588 ArrayRef<OMPClause *> ClauseList) {
3589 /// For target specific clauses, the requires directive cannot be
3590 /// specified after the handling of any of the target regions in the
3591 /// current compilation unit.
3592 ArrayRef<SourceLocation> TargetLocations =
3593 DSAStack->getEncounteredTargetLocs();
3594 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3595 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3596 for (const OMPClause *CNew : ClauseList) {
3597 // Check if any of the requires clauses affect target regions.
3598 if (isa<OMPUnifiedSharedMemoryClause>(Val: CNew) ||
3599 isa<OMPUnifiedAddressClause>(Val: CNew) ||
3600 isa<OMPReverseOffloadClause>(Val: CNew) ||
3601 isa<OMPDynamicAllocatorsClause>(Val: CNew)) {
3602 Diag(Loc, diag::err_omp_directive_before_requires)
3603 << "target" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3604 for (SourceLocation TargetLoc : TargetLocations) {
3605 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3606 << "target";
3607 }
3608 } else if (!AtomicLoc.isInvalid() &&
3609 isa<OMPAtomicDefaultMemOrderClause>(Val: CNew)) {
3610 Diag(Loc, diag::err_omp_directive_before_requires)
3611 << "atomic" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3612 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3613 << "atomic";
3614 }
3615 }
3616 }
3617
3618 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3619 return OMPRequiresDecl::Create(
3620 C&: getASTContext(), DC: SemaRef.getCurLexicalContext(), L: Loc, CL: ClauseList);
3621 return nullptr;
3622}
3623
3624static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3625 const ValueDecl *D,
3626 const DSAStackTy::DSAVarData &DVar,
3627 bool IsLoopIterVar) {
3628 if (DVar.RefExpr) {
3629 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3630 << getOpenMPClauseNameForDiag(DVar.CKind);
3631 return;
3632 }
3633 enum {
3634 PDSA_StaticMemberShared,
3635 PDSA_StaticLocalVarShared,
3636 PDSA_LoopIterVarPrivate,
3637 PDSA_LoopIterVarLinear,
3638 PDSA_LoopIterVarLastprivate,
3639 PDSA_ConstVarShared,
3640 PDSA_GlobalVarShared,
3641 PDSA_TaskVarFirstprivate,
3642 PDSA_LocalVarPrivate,
3643 PDSA_Implicit
3644 } Reason = PDSA_Implicit;
3645 bool ReportHint = false;
3646 auto ReportLoc = D->getLocation();
3647 auto *VD = dyn_cast<VarDecl>(Val: D);
3648 if (IsLoopIterVar) {
3649 if (DVar.CKind == OMPC_private)
3650 Reason = PDSA_LoopIterVarPrivate;
3651 else if (DVar.CKind == OMPC_lastprivate)
3652 Reason = PDSA_LoopIterVarLastprivate;
3653 else
3654 Reason = PDSA_LoopIterVarLinear;
3655 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3656 DVar.CKind == OMPC_firstprivate) {
3657 Reason = PDSA_TaskVarFirstprivate;
3658 ReportLoc = DVar.ImplicitDSALoc;
3659 } else if (VD && VD->isStaticLocal())
3660 Reason = PDSA_StaticLocalVarShared;
3661 else if (VD && VD->isStaticDataMember())
3662 Reason = PDSA_StaticMemberShared;
3663 else if (VD && VD->isFileVarDecl())
3664 Reason = PDSA_GlobalVarShared;
3665 else if (D->getType().isConstant(Ctx: SemaRef.getASTContext()))
3666 Reason = PDSA_ConstVarShared;
3667 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3668 ReportHint = true;
3669 Reason = PDSA_LocalVarPrivate;
3670 }
3671 if (Reason != PDSA_Implicit) {
3672 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
3673 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3674 << Reason << ReportHint
3675 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3676 } else if (DVar.ImplicitDSALoc.isValid()) {
3677 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3678 << getOpenMPClauseNameForDiag(DVar.CKind);
3679 }
3680}
3681
3682static OpenMPMapClauseKind
3683getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
3684 bool IsAggregateOrDeclareTarget) {
3685 OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
3686 switch (M) {
3687 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3688 Kind = OMPC_MAP_alloc;
3689 break;
3690 case OMPC_DEFAULTMAP_MODIFIER_to:
3691 Kind = OMPC_MAP_to;
3692 break;
3693 case OMPC_DEFAULTMAP_MODIFIER_from:
3694 Kind = OMPC_MAP_from;
3695 break;
3696 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3697 Kind = OMPC_MAP_tofrom;
3698 break;
3699 case OMPC_DEFAULTMAP_MODIFIER_present:
3700 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3701 // If implicit-behavior is present, each variable referenced in the
3702 // construct in the category specified by variable-category is treated as if
3703 // it had been listed in a map clause with the map-type of alloc and
3704 // map-type-modifier of present.
3705 Kind = OMPC_MAP_alloc;
3706 break;
3707 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3708 case OMPC_DEFAULTMAP_MODIFIER_last:
3709 llvm_unreachable("Unexpected defaultmap implicit behavior");
3710 case OMPC_DEFAULTMAP_MODIFIER_none:
3711 case OMPC_DEFAULTMAP_MODIFIER_default:
3712 case OMPC_DEFAULTMAP_MODIFIER_unknown:
3713 // IsAggregateOrDeclareTarget could be true if:
3714 // 1. the implicit behavior for aggregate is tofrom
3715 // 2. it's a declare target link
3716 if (IsAggregateOrDeclareTarget) {
3717 Kind = OMPC_MAP_tofrom;
3718 break;
3719 }
3720 llvm_unreachable("Unexpected defaultmap implicit behavior");
3721 }
3722 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3723 return Kind;
3724}
3725
3726namespace {
3727struct VariableImplicitInfo {
3728 static const unsigned MapKindNum = OMPC_MAP_unknown;
3729 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3730
3731 llvm::SetVector<Expr *> Privates;
3732 llvm::SetVector<Expr *> Firstprivates;
3733 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3734 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3735 MapModifiers[DefaultmapKindNum];
3736};
3737
3738class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3739 DSAStackTy *Stack;
3740 Sema &SemaRef;
3741 OpenMPDirectiveKind DKind = OMPD_unknown;
3742 bool ErrorFound = false;
3743 bool TryCaptureCXXThisMembers = false;
3744 CapturedStmt *CS = nullptr;
3745
3746 VariableImplicitInfo ImpInfo;
3747 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3748 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3749
3750 void VisitSubCaptures(OMPExecutableDirective *S) {
3751 // Check implicitly captured variables.
3752 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3753 return;
3754 if (S->getDirectiveKind() == OMPD_atomic ||
3755 S->getDirectiveKind() == OMPD_critical ||
3756 S->getDirectiveKind() == OMPD_section ||
3757 S->getDirectiveKind() == OMPD_master ||
3758 S->getDirectiveKind() == OMPD_masked ||
3759 S->getDirectiveKind() == OMPD_scope ||
3760 S->getDirectiveKind() == OMPD_assume ||
3761 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3762 Visit(S->getAssociatedStmt());
3763 return;
3764 }
3765 visitSubCaptures(S: S->getInnermostCapturedStmt());
3766 // Try to capture inner this->member references to generate correct mappings
3767 // and diagnostics.
3768 if (TryCaptureCXXThisMembers ||
3769 (isOpenMPTargetExecutionDirective(DKind) &&
3770 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3771 [](const CapturedStmt::Capture &C) {
3772 return C.capturesThis();
3773 }))) {
3774 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3775 TryCaptureCXXThisMembers = true;
3776 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3777 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3778 }
3779 // In tasks firstprivates are not captured anymore, need to analyze them
3780 // explicitly.
3781 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3782 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3783 for (OMPClause *C : S->clauses())
3784 if (auto *FC = dyn_cast<OMPFirstprivateClause>(Val: C)) {
3785 for (Expr *Ref : FC->varlist())
3786 Visit(Ref);
3787 }
3788 }
3789 }
3790
3791public:
3792 void VisitDeclRefExpr(DeclRefExpr *E) {
3793 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3794 E->isValueDependent() || E->containsUnexpandedParameterPack() ||
3795 E->isInstantiationDependent() ||
3796 E->isNonOdrUse() == clang::NOUR_Unevaluated)
3797 return;
3798 if (auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
3799 // Check the datasharing rules for the expressions in the clauses.
3800 if (!CS || (isa<OMPCapturedExprDecl>(Val: VD) && !CS->capturesVariable(Var: VD) &&
3801 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3802 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3803 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: VD))
3804 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3805 Visit(CED->getInit());
3806 return;
3807 }
3808 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(Val: VD))
3809 // Do not analyze internal variables and do not enclose them into
3810 // implicit clauses.
3811 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3812 return;
3813 VD = VD->getCanonicalDecl();
3814 // Skip internally declared variables.
3815 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(Var: VD) &&
3816 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3817 !Stack->isImplicitTaskFirstprivate(VD))
3818 return;
3819 // Skip allocators in uses_allocators clauses.
3820 if (Stack->isUsesAllocatorsDecl(VD))
3821 return;
3822
3823 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3824 // Check if the variable has explicit DSA set and stop analysis if it so.
3825 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3826 return;
3827
3828 // Skip internally declared static variables.
3829 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3830 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3831 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3832 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3833 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3834 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3835 !Stack->isImplicitTaskFirstprivate(VD))
3836 return;
3837
3838 SourceLocation ELoc = E->getExprLoc();
3839 // The default(none) clause requires that each variable that is referenced
3840 // in the construct, and does not have a predetermined data-sharing
3841 // attribute, must have its data-sharing attribute explicitly determined
3842 // by being listed in a data-sharing attribute clause.
3843 if (DVar.CKind == OMPC_unknown &&
3844 (Stack->getDefaultDSA() == DSA_none ||
3845 Stack->getDefaultDSA() == DSA_private ||
3846 Stack->getDefaultDSA() == DSA_firstprivate) &&
3847 isImplicitOrExplicitTaskingRegion(DKind) &&
3848 VarsWithInheritedDSA.count(VD) == 0) {
3849 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3850 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3851 Stack->getDefaultDSA() == DSA_private)) {
3852 DSAStackTy::DSAVarData DVar =
3853 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3854 InheritedDSA = DVar.CKind == OMPC_unknown;
3855 }
3856 if (InheritedDSA)
3857 VarsWithInheritedDSA[VD] = E;
3858 if (Stack->getDefaultDSA() == DSA_none)
3859 return;
3860 }
3861
3862 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3863 // If implicit-behavior is none, each variable referenced in the
3864 // construct that does not have a predetermined data-sharing attribute
3865 // and does not appear in a to or link clause on a declare target
3866 // directive must be listed in a data-mapping attribute clause, a
3867 // data-sharing attribute clause (including a data-sharing attribute
3868 // clause on a combined construct where target. is one of the
3869 // constituent constructs), or an is_device_ptr clause.
3870 OpenMPDefaultmapClauseKind ClauseKind =
3871 getVariableCategoryFromDecl(SemaRef.getLangOpts(), VD);
3872 if (SemaRef.getLangOpts().OpenMP >= 50) {
3873 bool IsModifierNone = Stack->getDefaultmapModifier(Kind: ClauseKind) ==
3874 OMPC_DEFAULTMAP_MODIFIER_none;
3875 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3876 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3877 // Only check for data-mapping attribute and is_device_ptr here
3878 // since we have already make sure that the declaration does not
3879 // have a data-sharing attribute above
3880 if (!Stack->checkMappableExprComponentListsForDecl(
3881 VD, /*CurrentRegionOnly=*/true,
3882 [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
3883 MapExprComponents,
3884 OpenMPClauseKind) {
3885 auto MI = MapExprComponents.rbegin();
3886 auto ME = MapExprComponents.rend();
3887 return MI != ME && MI->getAssociatedDeclaration() == VD;
3888 })) {
3889 VarsWithInheritedDSA[VD] = E;
3890 return;
3891 }
3892 }
3893 }
3894 if (SemaRef.getLangOpts().OpenMP > 50) {
3895 bool IsModifierPresent = Stack->getDefaultmapModifier(Kind: ClauseKind) ==
3896 OMPC_DEFAULTMAP_MODIFIER_present;
3897 if (IsModifierPresent) {
3898 if (!llvm::is_contained(Range&: ImpInfo.MapModifiers[ClauseKind],
3899 Element: OMPC_MAP_MODIFIER_present)) {
3900 ImpInfo.MapModifiers[ClauseKind].push_back(
3901 Elt: OMPC_MAP_MODIFIER_present);
3902 }
3903 }
3904 }
3905
3906 if (isOpenMPTargetExecutionDirective(DKind) &&
3907 !Stack->isLoopControlVariable(VD).first) {
3908 if (!Stack->checkMappableExprComponentListsForDecl(
3909 VD, /*CurrentRegionOnly=*/true,
3910 [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
3911 StackComponents,
3912 OpenMPClauseKind) {
3913 if (SemaRef.LangOpts.OpenMP >= 50)
3914 return !StackComponents.empty();
3915 // Variable is used if it has been marked as an array, array
3916 // section, array shaping or the variable itself.
3917 return StackComponents.size() == 1 ||
3918 llvm::all_of(
3919 Range: llvm::drop_begin(RangeOrContainer: llvm::reverse(C&: StackComponents)),
3920 P: [](const OMPClauseMappableExprCommon::
3921 MappableComponent &MC) {
3922 return MC.getAssociatedDeclaration() ==
3923 nullptr &&
3924 (isa<ArraySectionExpr>(
3925 Val: MC.getAssociatedExpression()) ||
3926 isa<OMPArrayShapingExpr>(
3927 Val: MC.getAssociatedExpression()) ||
3928 isa<ArraySubscriptExpr>(
3929 Val: MC.getAssociatedExpression()));
3930 });
3931 })) {
3932 bool IsFirstprivate = false;
3933 // By default lambdas are captured as firstprivates.
3934 if (const auto *RD =
3935 VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
3936 IsFirstprivate = RD->isLambda();
3937 IsFirstprivate =
3938 IsFirstprivate || (Stack->mustBeFirstprivate(Kind: ClauseKind) && !Res);
3939 if (IsFirstprivate) {
3940 ImpInfo.Firstprivates.insert(E);
3941 } else {
3942 OpenMPDefaultmapClauseModifier M =
3943 Stack->getDefaultmapModifier(Kind: ClauseKind);
3944 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3945 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3946 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
3947 }
3948 return;
3949 }
3950 }
3951
3952 // OpenMP [2.9.3.6, Restrictions, p.2]
3953 // A list item that appears in a reduction clause of the innermost
3954 // enclosing worksharing or parallel construct may not be accessed in an
3955 // explicit task.
3956 DVar = Stack->hasInnermostDSA(
3957 VD,
3958 [](OpenMPClauseKind C, bool AppliedToPointee) {
3959 return C == OMPC_reduction && !AppliedToPointee;
3960 },
3961 [](OpenMPDirectiveKind K) {
3962 return isOpenMPParallelDirective(K) ||
3963 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
3964 },
3965 /*FromParent=*/true);
3966 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3967 ErrorFound = true;
3968 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3969 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3970 return;
3971 }
3972
3973 // Define implicit data-sharing attributes for task.
3974 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3975 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3976 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3977 DVar.CKind == OMPC_firstprivate) ||
3978 (Stack->getDefaultDSA() == DSA_private &&
3979 DVar.CKind == OMPC_private)) &&
3980 !DVar.RefExpr)) &&
3981 !Stack->isLoopControlVariable(VD).first) {
3982 if (Stack->getDefaultDSA() == DSA_private)
3983 ImpInfo.Privates.insert(E);
3984 else
3985 ImpInfo.Firstprivates.insert(E);
3986 return;
3987 }
3988
3989 // Store implicitly used globals with declare target link for parent
3990 // target.
3991 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3992 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3993 Stack->addToParentTargetRegionLinkGlobals(E);
3994 return;
3995 }
3996 }
3997 }
3998 void VisitMemberExpr(MemberExpr *E) {
3999 if (E->isTypeDependent() || E->isValueDependent() ||
4000 E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
4001 return;
4002 auto *FD = dyn_cast<FieldDecl>(Val: E->getMemberDecl());
4003 if (auto *TE = dyn_cast<CXXThisExpr>(Val: E->getBase()->IgnoreParenCasts())) {
4004 if (!FD)
4005 return;
4006 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
4007 // Check if the variable has explicit DSA set and stop analysis if it
4008 // so.
4009 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4010 return;
4011
4012 if (isOpenMPTargetExecutionDirective(DKind) &&
4013 !Stack->isLoopControlVariable(FD).first &&
4014 !Stack->checkMappableExprComponentListsForDecl(
4015 FD, /*CurrentRegionOnly=*/true,
4016 [](OMPClauseMappableExprCommon::MappableExprComponentListRef
4017 StackComponents,
4018 OpenMPClauseKind) {
4019 return isa<CXXThisExpr>(
4020 cast<MemberExpr>(
4021 StackComponents.back().getAssociatedExpression())
4022 ->getBase()
4023 ->IgnoreParens());
4024 })) {
4025 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4026 // A bit-field cannot appear in a map clause.
4027 //
4028 if (FD->isBitField())
4029 return;
4030
4031 // Check to see if the member expression is referencing a class that
4032 // has already been explicitly mapped
4033 if (Stack->isClassPreviouslyMapped(QT: TE->getType()))
4034 return;
4035
4036 OpenMPDefaultmapClauseModifier Modifier =
4037 Stack->getDefaultmapModifier(Kind: OMPC_DEFAULTMAP_aggregate);
4038 OpenMPDefaultmapClauseKind ClauseKind =
4039 getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD);
4040 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
4041 M: Modifier, /*IsAggregateOrDeclareTarget=*/true);
4042 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4043 return;
4044 }
4045
4046 SourceLocation ELoc = E->getExprLoc();
4047 // OpenMP [2.9.3.6, Restrictions, p.2]
4048 // A list item that appears in a reduction clause of the innermost
4049 // enclosing worksharing or parallel construct may not be accessed in
4050 // an explicit task.
4051 DVar = Stack->hasInnermostDSA(
4052 FD,
4053 [](OpenMPClauseKind C, bool AppliedToPointee) {
4054 return C == OMPC_reduction && !AppliedToPointee;
4055 },
4056 [](OpenMPDirectiveKind K) {
4057 return isOpenMPParallelDirective(K) ||
4058 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
4059 },
4060 /*FromParent=*/true);
4061 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4062 ErrorFound = true;
4063 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4064 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4065 return;
4066 }
4067
4068 // Define implicit data-sharing attributes for task.
4069 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4070 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4071 !Stack->isLoopControlVariable(FD).first) {
4072 // Check if there is a captured expression for the current field in the
4073 // region. Do not mark it as firstprivate unless there is no captured
4074 // expression.
4075 // TODO: try to make it firstprivate.
4076 if (DVar.CKind != OMPC_unknown)
4077 ImpInfo.Firstprivates.insert(E);
4078 }
4079 return;
4080 }
4081 if (isOpenMPTargetExecutionDirective(DKind)) {
4082 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
4083 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4084 DKind, /*NoDiagnose=*/true))
4085 return;
4086 const auto *VD = cast<ValueDecl>(
4087 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4088 if (!Stack->checkMappableExprComponentListsForDecl(
4089 VD: VD, /*CurrentRegionOnly=*/true,
4090 Check: [&CurComponents](
4091 OMPClauseMappableExprCommon::MappableExprComponentListRef
4092 StackComponents,
4093 OpenMPClauseKind) {
4094 auto CCI = CurComponents.rbegin();
4095 auto CCE = CurComponents.rend();
4096 for (const auto &SC : llvm::reverse(C&: StackComponents)) {
4097 // Do both expressions have the same kind?
4098 if (CCI->getAssociatedExpression()->getStmtClass() !=
4099 SC.getAssociatedExpression()->getStmtClass())
4100 if (!((isa<ArraySectionExpr>(
4101 Val: SC.getAssociatedExpression()) ||
4102 isa<OMPArrayShapingExpr>(
4103 Val: SC.getAssociatedExpression())) &&
4104 isa<ArraySubscriptExpr>(
4105 Val: CCI->getAssociatedExpression())))
4106 return false;
4107
4108 const Decl *CCD = CCI->getAssociatedDeclaration();
4109 const Decl *SCD = SC.getAssociatedDeclaration();
4110 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4111 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4112 if (SCD != CCD)
4113 return false;
4114 std::advance(i&: CCI, n: 1);
4115 if (CCI == CCE)
4116 break;
4117 }
4118 return true;
4119 })) {
4120 Visit(E->getBase());
4121 }
4122 } else if (!TryCaptureCXXThisMembers) {
4123 Visit(E->getBase());
4124 }
4125 }
4126 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4127 for (OMPClause *C : S->clauses()) {
4128 // Skip analysis of arguments of private clauses for task|target
4129 // directives.
4130 if (isa_and_nonnull<OMPPrivateClause>(Val: C))
4131 continue;
4132 // Skip analysis of arguments of implicitly defined firstprivate clause
4133 // for task|target directives.
4134 // Skip analysis of arguments of implicitly defined map clause for target
4135 // directives.
4136 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4137 C->isImplicit() && !isOpenMPTaskingDirective(DKind))) {
4138 for (Stmt *CC : C->children()) {
4139 if (CC)
4140 Visit(CC);
4141 }
4142 }
4143 }
4144 // Check implicitly captured variables.
4145 VisitSubCaptures(S);
4146 }
4147
4148 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4149 // Loop transformation directives do not introduce data sharing
4150 VisitStmt(S);
4151 }
4152
4153 void VisitCallExpr(CallExpr *S) {
4154 for (Stmt *C : S->arguments()) {
4155 if (C) {
4156 // Check implicitly captured variables in the task-based directives to
4157 // check if they must be firstprivatized.
4158 Visit(C);
4159 }
4160 }
4161 if (Expr *Callee = S->getCallee()) {
4162 auto *CI = Callee->IgnoreParenImpCasts();
4163 if (auto *CE = dyn_cast<MemberExpr>(Val: CI))
4164 Visit(CE->getBase());
4165 else if (auto *CE = dyn_cast<DeclRefExpr>(Val: CI))
4166 Visit(CE);
4167 }
4168 }
4169 void VisitStmt(Stmt *S) {
4170 for (Stmt *C : S->children()) {
4171 if (C) {
4172 // Check implicitly captured variables in the task-based directives to
4173 // check if they must be firstprivatized.
4174 Visit(C);
4175 }
4176 }
4177 }
4178
4179 void visitSubCaptures(CapturedStmt *S) {
4180 for (const CapturedStmt::Capture &Cap : S->captures()) {
4181 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4182 continue;
4183 VarDecl *VD = Cap.getCapturedVar();
4184 // Do not try to map the variable if it or its sub-component was mapped
4185 // already.
4186 if (isOpenMPTargetExecutionDirective(DKind) &&
4187 Stack->checkMappableExprComponentListsForDecl(
4188 VD, /*CurrentRegionOnly=*/true,
4189 [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4190 OpenMPClauseKind) { return true; }))
4191 continue;
4192 DeclRefExpr *DRE = buildDeclRefExpr(
4193 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4194 Cap.getLocation(), /*RefersToCapture=*/true);
4195 Visit(DRE);
4196 }
4197 }
4198 bool isErrorFound() const { return ErrorFound; }
4199 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4200 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4201 return VarsWithInheritedDSA;
4202 }
4203
4204 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4205 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4206 DKind = S->getCurrentDirective();
4207 // Process declare target link variables for the target directives.
4208 if (isOpenMPTargetExecutionDirective(DKind)) {
4209 for (DeclRefExpr *E : Stack->getLinkGlobals())
4210 Visit(E);
4211 }
4212 }
4213};
4214} // namespace
4215
4216static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4217 OpenMPDirectiveKind DKind,
4218 bool ScopeEntry) {
4219 SmallVector<llvm::omp::TraitProperty, 8> Traits;
4220 if (isOpenMPTargetExecutionDirective(DKind))
4221 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_target_target);
4222 if (isOpenMPTeamsDirective(DKind))
4223 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_teams_teams);
4224 if (isOpenMPParallelDirective(DKind))
4225 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_parallel_parallel);
4226 if (isOpenMPWorksharingDirective(DKind))
4227 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_for_for);
4228 if (isOpenMPSimdDirective(DKind))
4229 Traits.emplace_back(Args: llvm::omp::TraitProperty::construct_simd_simd);
4230 Stack->handleConstructTrait(Traits, ScopeEntry);
4231}
4232
4233static SmallVector<SemaOpenMP::CapturedParamNameType>
4234getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4235 ASTContext &Context = SemaRef.getASTContext();
4236 QualType KmpInt32Ty =
4237 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4238 QualType KmpInt32PtrTy =
4239 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4240 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4241 std::make_pair(x: ".global_tid.", y&: KmpInt32PtrTy),
4242 std::make_pair(x: ".bound_tid.", y&: KmpInt32PtrTy),
4243 };
4244 if (LoopBoundSharing) {
4245 QualType KmpSizeTy = Context.getSizeType().withConst();
4246 Params.push_back(Elt: std::make_pair(x: ".previous.lb.", y&: KmpSizeTy));
4247 Params.push_back(Elt: std::make_pair(x: ".previous.ub.", y&: KmpSizeTy));
4248 }
4249
4250 // __context with shared vars
4251 Params.push_back(Elt: std::make_pair(x: StringRef(), y: QualType()));
4252 return Params;
4253}
4254
4255static SmallVector<SemaOpenMP::CapturedParamNameType>
4256getTeamsRegionParams(Sema &SemaRef) {
4257 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4258}
4259
4260static SmallVector<SemaOpenMP::CapturedParamNameType>
4261getTaskRegionParams(Sema &SemaRef) {
4262 ASTContext &Context = SemaRef.getASTContext();
4263 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(DestWidth: 32, Signed: 1).withConst();
4264 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4265 QualType KmpInt32PtrTy =
4266 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4267 QualType Args[] = {VoidPtrTy};
4268 FunctionProtoType::ExtProtoInfo EPI;
4269 EPI.Variadic = true;
4270 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4271 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4272 std::make_pair(".global_tid.", KmpInt32Ty),
4273 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4274 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4275 std::make_pair(
4276 x: ".copy_fn.",
4277 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4278 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4279 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4280 };
4281 return Params;
4282}
4283
4284static SmallVector<SemaOpenMP::CapturedParamNameType>
4285getTargetRegionParams(Sema &SemaRef) {
4286 ASTContext &Context = SemaRef.getASTContext();
4287 SmallVector<SemaOpenMP::CapturedParamNameType> Params;
4288 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4289 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4290 Params.push_back(Elt: std::make_pair(x: StringRef("dyn_ptr"), y&: VoidPtrTy));
4291 }
4292 // __context with shared vars
4293 Params.push_back(Elt: std::make_pair(x: StringRef(), y: QualType()));
4294 return Params;
4295}
4296
4297static SmallVector<SemaOpenMP::CapturedParamNameType>
4298getUnknownRegionParams(Sema &SemaRef) {
4299 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4300 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4301 };
4302 return Params;
4303}
4304
4305static SmallVector<SemaOpenMP::CapturedParamNameType>
4306getTaskloopRegionParams(Sema &SemaRef) {
4307 ASTContext &Context = SemaRef.getASTContext();
4308 QualType KmpInt32Ty =
4309 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4310 QualType KmpUInt64Ty =
4311 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4312 QualType KmpInt64Ty =
4313 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4314 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4315 QualType KmpInt32PtrTy =
4316 Context.getPointerType(T: KmpInt32Ty).withConst().withRestrict();
4317 QualType Args[] = {VoidPtrTy};
4318 FunctionProtoType::ExtProtoInfo EPI;
4319 EPI.Variadic = true;
4320 QualType CopyFnType = Context.getFunctionType(ResultTy: Context.VoidTy, Args, EPI);
4321 SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4322 std::make_pair(".global_tid.", KmpInt32Ty),
4323 std::make_pair(x: ".part_id.", y&: KmpInt32PtrTy),
4324 std::make_pair(x: ".privates.", y&: VoidPtrTy),
4325 std::make_pair(
4326 x: ".copy_fn.",
4327 y: Context.getPointerType(T: CopyFnType).withConst().withRestrict()),
4328 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4329 std::make_pair(x: ".lb.", y&: KmpUInt64Ty),
4330 std::make_pair(x: ".ub.", y&: KmpUInt64Ty),
4331 std::make_pair(x: ".st.", y&: KmpInt64Ty),
4332 std::make_pair(x: ".liter.", y&: KmpInt32Ty),
4333 std::make_pair(".reductions.", VoidPtrTy),
4334 std::make_pair(x: StringRef(), y: QualType()) // __context with shared vars
4335 };
4336 return Params;
4337}
4338
4339static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind,
4340 Scope *CurScope, SourceLocation Loc) {
4341 SmallVector<OpenMPDirectiveKind> Regions;
4342 getOpenMPCaptureRegions(Regions, DKind);
4343
4344 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4345
4346 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4347 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4348 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4349 };
4350
4351 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4352 switch (RKind) {
4353 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4354 // are listed here.
4355 case OMPD_parallel:
4356 SemaRef.ActOnCapturedRegionStart(
4357 Loc, CurScope, CR_OpenMP,
4358 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4359 break;
4360 case OMPD_teams:
4361 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4362 getTeamsRegionParams(SemaRef), Level);
4363 break;
4364 case OMPD_task:
4365 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4366 getTaskRegionParams(SemaRef), Level);
4367 // Mark this captured region as inlined, because we don't use outlined
4368 // function directly.
4369 MarkAsInlined(SemaRef.getCurCapturedRegion());
4370 break;
4371 case OMPD_taskloop:
4372 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4373 getTaskloopRegionParams(SemaRef), Level);
4374 // Mark this captured region as inlined, because we don't use outlined
4375 // function directly.
4376 MarkAsInlined(SemaRef.getCurCapturedRegion());
4377 break;
4378 case OMPD_target:
4379 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4380 getTargetRegionParams(SemaRef), Level);
4381 break;
4382 case OMPD_unknown:
4383 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4384 getUnknownRegionParams(SemaRef));
4385 break;
4386 case OMPD_metadirective:
4387 case OMPD_nothing:
4388 default:
4389 llvm_unreachable("Unexpected capture region");
4390 }
4391 }
4392}
4393
4394void SemaOpenMP::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,
4395 Scope *CurScope) {
4396 switch (DKind) {
4397 case OMPD_atomic:
4398 case OMPD_critical:
4399 case OMPD_masked:
4400 case OMPD_master:
4401 case OMPD_section:
4402 case OMPD_tile:
4403 case OMPD_stripe:
4404 case OMPD_unroll:
4405 case OMPD_reverse:
4406 case OMPD_interchange:
4407 case OMPD_assume:
4408 break;
4409 default:
4410 processCapturedRegions(SemaRef, DKind, CurScope,
4411 DSAStack->getConstructLoc());
4412 break;
4413 }
4414
4415 DSAStack->setContext(SemaRef.CurContext);
4416 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4417}
4418
4419int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4420 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4421}
4422
4423int SemaOpenMP::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4424 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4425 getOpenMPCaptureRegions(CaptureRegions, DKind);
4426 return CaptureRegions.size();
4427}
4428
4429static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
4430 Expr *CaptureExpr, bool WithInit,
4431 DeclContext *CurContext,
4432 bool AsExpression) {
4433 assert(CaptureExpr);
4434 ASTContext &C = S.getASTContext();
4435 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4436 QualType Ty = Init->getType();
4437 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4438 if (S.getLangOpts().CPlusPlus) {
4439 Ty = C.getLValueReferenceType(T: Ty);
4440 } else {
4441 Ty = C.getPointerType(T: Ty);
4442 ExprResult Res =
4443 S.CreateBuiltinUnaryOp(OpLoc: CaptureExpr->getExprLoc(), Opc: UO_AddrOf, InputExpr: Init);
4444 if (!Res.isUsable())
4445 return nullptr;
4446 Init = Res.get();
4447 }
4448 WithInit = true;
4449 }
4450 auto *CED = OMPCapturedExprDecl::Create(C, DC: CurContext, Id, T: Ty,
4451 StartLoc: CaptureExpr->getBeginLoc());
4452 if (!WithInit)
4453 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4454 CurContext->addHiddenDecl(D: CED);
4455 Sema::TentativeAnalysisScope Trap(S);
4456 S.AddInitializerToDecl(dcl: CED, init: Init, /*DirectInit=*/false);
4457 return CED;
4458}
4459
4460static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4461 bool WithInit) {
4462 OMPCapturedExprDecl *CD;
4463 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4464 CD = cast<OMPCapturedExprDecl>(Val: VD);
4465 else
4466 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4467 S.CurContext,
4468 /*AsExpression=*/false);
4469 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4470 CaptureExpr->getExprLoc());
4471}
4472
4473static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4474 StringRef Name) {
4475 CaptureExpr = S.DefaultLvalueConversion(E: CaptureExpr).get();
4476 if (!Ref) {
4477 OMPCapturedExprDecl *CD = buildCaptureDecl(
4478 S, Id: &S.getASTContext().Idents.get(Name), CaptureExpr,
4479 /*WithInit=*/true, CurContext: S.CurContext, /*AsExpression=*/true);
4480 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4481 CaptureExpr->getExprLoc());
4482 }
4483 ExprResult Res = Ref;
4484 if (!S.getLangOpts().CPlusPlus &&
4485 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4486 Ref->getType()->isPointerType()) {
4487 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4488 if (!Res.isUsable())
4489 return ExprError();
4490 }
4491 return S.DefaultLvalueConversion(E: Res.get());
4492}
4493
4494namespace {
4495// OpenMP directives parsed in this section are represented as a
4496// CapturedStatement with an associated statement. If a syntax error
4497// is detected during the parsing of the associated statement, the
4498// compiler must abort processing and close the CapturedStatement.
4499//
4500// Combined directives such as 'target parallel' have more than one
4501// nested CapturedStatements. This RAII ensures that we unwind out
4502// of all the nested CapturedStatements when an error is found.
4503class CaptureRegionUnwinderRAII {
4504private:
4505 Sema &S;
4506 bool &ErrorFound;
4507 OpenMPDirectiveKind DKind = OMPD_unknown;
4508
4509public:
4510 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4511 OpenMPDirectiveKind DKind)
4512 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4513 ~CaptureRegionUnwinderRAII() {
4514 if (ErrorFound) {
4515 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4516 while (--ThisCaptureLevel >= 0)
4517 S.ActOnCapturedRegionError();
4518 }
4519 }
4520};
4521} // namespace
4522
4523void SemaOpenMP::tryCaptureOpenMPLambdas(ValueDecl *V) {
4524 // Capture variables captured by reference in lambdas for target-based
4525 // directives.
4526 if (!SemaRef.CurContext->isDependentContext() &&
4527 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4528 isOpenMPTargetDataManagementDirective(
4529 DSAStack->getCurrentDirective()))) {
4530 QualType Type = V->getType();
4531 if (const auto *RD = Type.getCanonicalType()
4532 .getNonReferenceType()
4533 ->getAsCXXRecordDecl()) {
4534 bool SavedForceCaptureByReferenceInTargetExecutable =
4535 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4536 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4537 /*V=*/true);
4538 if (RD->isLambda()) {
4539 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4540 FieldDecl *ThisCapture;
4541 RD->getCaptureFields(Captures, ThisCapture);
4542 for (const LambdaCapture &LC : RD->captures()) {
4543 if (LC.getCaptureKind() == LCK_ByRef) {
4544 VarDecl *VD = cast<VarDecl>(Val: LC.getCapturedVar());
4545 DeclContext *VDC = VD->getDeclContext();
4546 if (!VDC->Encloses(DC: SemaRef.CurContext))
4547 continue;
4548 SemaRef.MarkVariableReferenced(Loc: LC.getLocation(), Var: VD);
4549 } else if (LC.getCaptureKind() == LCK_This) {
4550 QualType ThisTy = SemaRef.getCurrentThisType();
4551 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4552 ThisTy, ThisCapture->getType()))
4553 SemaRef.CheckCXXThisCapture(Loc: LC.getLocation());
4554 }
4555 }
4556 }
4557 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4558 SavedForceCaptureByReferenceInTargetExecutable);
4559 }
4560 }
4561}
4562
4563static bool checkOrderedOrderSpecified(Sema &S,
4564 const ArrayRef<OMPClause *> Clauses) {
4565 const OMPOrderedClause *Ordered = nullptr;
4566 const OMPOrderClause *Order = nullptr;
4567
4568 for (const OMPClause *Clause : Clauses) {
4569 if (Clause->getClauseKind() == OMPC_ordered)
4570 Ordered = cast<OMPOrderedClause>(Val: Clause);
4571 else if (Clause->getClauseKind() == OMPC_order) {
4572 Order = cast<OMPOrderClause>(Val: Clause);
4573 if (Order->getKind() != OMPC_ORDER_concurrent)
4574 Order = nullptr;
4575 }
4576 if (Ordered && Order)
4577 break;
4578 }
4579
4580 if (Ordered && Order) {
4581 S.Diag(Order->getKindKwLoc(),
4582 diag::err_omp_simple_clause_incompatible_with_ordered)
4583 << getOpenMPClauseNameForDiag(OMPC_order)
4584 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4585 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4586 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4587 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4588 return true;
4589 }
4590 return false;
4591}
4592
4593StmtResult SemaOpenMP::ActOnOpenMPRegionEnd(StmtResult S,
4594 ArrayRef<OMPClause *> Clauses) {
4595 handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(),
4596 /*ScopeEntry=*/false);
4597 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4598 return S;
4599
4600 bool ErrorFound = false;
4601 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4602 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4603 if (!S.isUsable()) {
4604 ErrorFound = true;
4605 return StmtError();
4606 }
4607
4608 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4609 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4610 OMPOrderedClause *OC = nullptr;
4611 OMPScheduleClause *SC = nullptr;
4612 SmallVector<const OMPLinearClause *, 4> LCs;
4613 SmallVector<const OMPClauseWithPreInit *, 4> PICs;
4614 // This is required for proper codegen.
4615 for (OMPClause *Clause : Clauses) {
4616 if (!getLangOpts().OpenMPSimd &&
4617 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4618 DSAStack->getCurrentDirective() == OMPD_target) &&
4619 Clause->getClauseKind() == OMPC_in_reduction) {
4620 // Capture taskgroup task_reduction descriptors inside the tasking regions
4621 // with the corresponding in_reduction items.
4622 auto *IRC = cast<OMPInReductionClause>(Val: Clause);
4623 for (Expr *E : IRC->taskgroup_descriptors())
4624 if (E)
4625 SemaRef.MarkDeclarationsReferencedInExpr(E);
4626 }
4627 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4628 Clause->getClauseKind() == OMPC_copyprivate ||
4629 (getLangOpts().OpenMPUseTLS &&
4630 getASTContext().getTargetInfo().isTLSSupported() &&
4631 Clause->getClauseKind() == OMPC_copyin)) {
4632 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4633 // Mark all variables in private list clauses as used in inner region.
4634 for (Stmt *VarRef : Clause->children()) {
4635 if (auto *E = cast_or_null<Expr>(Val: VarRef)) {
4636 SemaRef.MarkDeclarationsReferencedInExpr(E);
4637 }
4638 }
4639 DSAStack->setForceVarCapturing(/*V=*/false);
4640 } else if (CaptureRegions.size() > 1 ||
4641 CaptureRegions.back() != OMPD_unknown) {
4642 if (auto *C = OMPClauseWithPreInit::get(C: Clause))
4643 PICs.push_back(Elt: C);
4644 if (auto *C = OMPClauseWithPostUpdate::get(C: Clause)) {
4645 if (Expr *E = C->getPostUpdateExpr())
4646 SemaRef.MarkDeclarationsReferencedInExpr(E);
4647 }
4648 }
4649 if (Clause->getClauseKind() == OMPC_schedule)
4650 SC = cast<OMPScheduleClause>(Val: Clause);
4651 else if (Clause->getClauseKind() == OMPC_ordered)
4652 OC = cast<OMPOrderedClause>(Val: Clause);
4653 else if (Clause->getClauseKind() == OMPC_linear)
4654 LCs.push_back(Elt: cast<OMPLinearClause>(Val: Clause));
4655 }
4656 // Capture allocator expressions if used.
4657 for (Expr *E : DSAStack->getInnerAllocators())
4658 SemaRef.MarkDeclarationsReferencedInExpr(E);
4659 // OpenMP, 2.7.1 Loop Construct, Restrictions
4660 // The nonmonotonic modifier cannot be specified if an ordered clause is
4661 // specified.
4662 if (SC &&
4663 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4664 SC->getSecondScheduleModifier() ==
4665 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4666 OC) {
4667 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4668 ? SC->getFirstScheduleModifierLoc()
4669 : SC->getSecondScheduleModifierLoc(),
4670 diag::err_omp_simple_clause_incompatible_with_ordered)
4671 << getOpenMPClauseNameForDiag(OMPC_schedule)
4672 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4673 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4674 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4675 ErrorFound = true;
4676 }
4677 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4678 // If an order(concurrent) clause is present, an ordered clause may not appear
4679 // on the same directive.
4680 if (checkOrderedOrderSpecified(S&: SemaRef, Clauses))
4681 ErrorFound = true;
4682 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4683 for (const OMPLinearClause *C : LCs) {
4684 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4685 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4686 }
4687 ErrorFound = true;
4688 }
4689 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4690 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4691 OC->getNumForLoops()) {
4692 unsigned OMPVersion = getLangOpts().OpenMP;
4693 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4694 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), OMPVersion);
4695 ErrorFound = true;
4696 }
4697 if (ErrorFound) {
4698 return StmtError();
4699 }
4700 StmtResult SR = S;
4701 unsigned CompletedRegions = 0;
4702 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4703 // Mark all variables in private list clauses as used in inner region.
4704 // Required for proper codegen of combined directives.
4705 // TODO: add processing for other clauses.
4706 if (ThisCaptureRegion != OMPD_unknown) {
4707 for (const clang::OMPClauseWithPreInit *C : PICs) {
4708 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4709 // Find the particular capture region for the clause if the
4710 // directive is a combined one with multiple capture regions.
4711 // If the directive is not a combined one, the capture region
4712 // associated with the clause is OMPD_unknown and is generated
4713 // only once.
4714 if (CaptureRegion == ThisCaptureRegion ||
4715 CaptureRegion == OMPD_unknown) {
4716 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4717 for (Decl *D : DS->decls())
4718 SemaRef.MarkVariableReferenced(D->getLocation(),
4719 cast<VarDecl>(D));
4720 }
4721 }
4722 }
4723 }
4724 if (ThisCaptureRegion == OMPD_target) {
4725 // Capture allocator traits in the target region. They are used implicitly
4726 // and, thus, are not captured by default.
4727 for (OMPClause *C : Clauses) {
4728 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4729 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4730 ++I) {
4731 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4732 if (Expr *E = D.AllocatorTraits)
4733 SemaRef.MarkDeclarationsReferencedInExpr(E);
4734 }
4735 continue;
4736 }
4737 }
4738 }
4739 if (ThisCaptureRegion == OMPD_parallel) {
4740 // Capture temp arrays for inscan reductions and locals in aligned
4741 // clauses.
4742 for (OMPClause *C : Clauses) {
4743 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4744 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4745 continue;
4746 for (Expr *E : RC->copy_array_temps())
4747 if (E)
4748 SemaRef.MarkDeclarationsReferencedInExpr(E);
4749 }
4750 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4751 for (Expr *E : AC->varlist())
4752 SemaRef.MarkDeclarationsReferencedInExpr(E);
4753 }
4754 }
4755 }
4756 if (++CompletedRegions == CaptureRegions.size())
4757 DSAStack->setBodyComplete();
4758 SR = SemaRef.ActOnCapturedRegionEnd(SR.get());
4759 }
4760 return SR;
4761}
4762
4763static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4764 OpenMPDirectiveKind CancelRegion,
4765 SourceLocation StartLoc) {
4766 // CancelRegion is only needed for cancel and cancellation_point.
4767 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4768 return false;
4769
4770 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4771 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4772 return false;
4773
4774 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4775 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4776 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
4777 return true;
4778}
4779
4780static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4781 OpenMPDirectiveKind CurrentRegion,
4782 const DeclarationNameInfo &CurrentName,
4783 OpenMPDirectiveKind CancelRegion,
4784 OpenMPBindClauseKind BindKind,
4785 SourceLocation StartLoc) {
4786 if (!Stack->getCurScope())
4787 return false;
4788
4789 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4790 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4791 bool NestingProhibited = false;
4792 bool CloseNesting = true;
4793 bool OrphanSeen = false;
4794 enum {
4795 NoRecommend,
4796 ShouldBeInParallelRegion,
4797 ShouldBeInOrderedRegion,
4798 ShouldBeInTargetRegion,
4799 ShouldBeInTeamsRegion,
4800 ShouldBeInLoopSimdRegion,
4801 } Recommend = NoRecommend;
4802
4803 SmallVector<OpenMPDirectiveKind, 4> LeafOrComposite;
4804 ArrayRef<OpenMPDirectiveKind> ParentLOC =
4805 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4806 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4807 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4808
4809 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
4810 !isOpenMPOrderConcurrentNestableDirective(CurrentRegion,
4811 SemaRef.LangOpts)) {
4812 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
4813 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
4814 return true;
4815 }
4816 if (isOpenMPSimdDirective(ParentRegion) &&
4817 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
4818 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
4819 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4820 CurrentRegion != OMPD_scan))) {
4821 // OpenMP [2.16, Nesting of Regions]
4822 // OpenMP constructs may not be nested inside a simd region.
4823 // OpenMP [2.8.1,simd Construct, Restrictions]
4824 // An ordered construct with the simd clause is the only OpenMP
4825 // construct that can appear in the simd region.
4826 // Allowing a SIMD construct nested in another SIMD construct is an
4827 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4828 // message.
4829 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4830 // The only OpenMP constructs that can be encountered during execution of
4831 // a simd region are the atomic construct, the loop construct, the simd
4832 // construct and the ordered construct with the simd clause.
4833 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4834 ? diag::err_omp_prohibited_region_simd
4835 : diag::warn_omp_nesting_simd)
4836 << (OMPVersion >= 50 ? 1 : 0);
4837 return CurrentRegion != OMPD_simd;
4838 }
4839 if (EnclosingConstruct == OMPD_atomic) {
4840 // OpenMP [2.16, Nesting of Regions]
4841 // OpenMP constructs may not be nested inside an atomic region.
4842 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4843 return true;
4844 }
4845 if (CurrentRegion == OMPD_section) {
4846 // OpenMP [2.7.2, sections Construct, Restrictions]
4847 // Orphaned section directives are prohibited. That is, the section
4848 // directives must appear within the sections construct and must not be
4849 // encountered elsewhere in the sections region.
4850 if (EnclosingConstruct != OMPD_sections) {
4851 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4852 << (ParentRegion != OMPD_unknown)
4853 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
4854 return true;
4855 }
4856 return false;
4857 }
4858 // Allow some constructs (except teams and cancellation constructs) to be
4859 // orphaned (they could be used in functions, called from OpenMP regions
4860 // with the required preconditions).
4861 if (ParentRegion == OMPD_unknown &&
4862 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
4863 CurrentRegion != OMPD_cancellation_point &&
4864 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4865 return false;
4866 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
4867 // for a detailed explanation
4868 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
4869 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4870 (isOpenMPWorksharingDirective(ParentRegion) ||
4871 EnclosingConstruct == OMPD_loop)) {
4872 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4873 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
4874 << true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
4875 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
4876 return true;
4877 }
4878 if (CurrentRegion == OMPD_cancellation_point ||
4879 CurrentRegion == OMPD_cancel) {
4880 // OpenMP [2.16, Nesting of Regions]
4881 // A cancellation point construct for which construct-type-clause is
4882 // taskgroup must be nested inside a task construct. A cancellation
4883 // point construct for which construct-type-clause is not taskgroup must
4884 // be closely nested inside an OpenMP construct that matches the type
4885 // specified in construct-type-clause.
4886 // A cancel construct for which construct-type-clause is taskgroup must be
4887 // nested inside a task construct. A cancel construct for which
4888 // construct-type-clause is not taskgroup must be closely nested inside an
4889 // OpenMP construct that matches the type specified in
4890 // construct-type-clause.
4891 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
4892 if (CancelRegion == OMPD_taskgroup) {
4893 NestingProhibited =
4894 EnclosingConstruct != OMPD_task &&
4895 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
4896 } else if (CancelRegion == OMPD_sections) {
4897 NestingProhibited = EnclosingConstruct != OMPD_section &&
4898 EnclosingConstruct != OMPD_sections;
4899 } else {
4900 NestingProhibited = CancelRegion != Leafs.back();
4901 }
4902 OrphanSeen = ParentRegion == OMPD_unknown;
4903 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4904 // OpenMP 5.1 [2.22, Nesting of Regions]
4905 // A masked region may not be closely nested inside a worksharing, loop,
4906 // atomic, task, or taskloop region.
4907 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4908 isOpenMPGenericLoopDirective(ParentRegion) ||
4909 isOpenMPTaskingDirective(ParentRegion);
4910 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
4911 // OpenMP [2.16, Nesting of Regions]
4912 // A critical region may not be nested (closely or otherwise) inside a
4913 // critical region with the same name. Note that this restriction is not
4914 // sufficient to prevent deadlock.
4915 SourceLocation PreviousCriticalLoc;
4916 bool DeadLock = Stack->hasDirective(
4917 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
4918 const DeclarationNameInfo &DNI,
4919 SourceLocation Loc) {
4920 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
4921 PreviousCriticalLoc = Loc;
4922 return true;
4923 }
4924 return false;
4925 },
4926 false /* skip top directive */);
4927 if (DeadLock) {
4928 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
4929 << CurrentName.getName();
4930 if (PreviousCriticalLoc.isValid())
4931 SemaRef.Diag(PreviousCriticalLoc,
4932 diag::note_omp_previous_critical_region);
4933 return true;
4934 }
4935 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4936 // OpenMP 5.1 [2.22, Nesting of Regions]
4937 // A scope region may not be closely nested inside a worksharing, loop,
4938 // task, taskloop, critical, ordered, atomic, or masked region.
4939 // OpenMP 5.1 [2.22, Nesting of Regions]
4940 // A barrier region may not be closely nested inside a worksharing, loop,
4941 // task, taskloop, critical, ordered, atomic, or masked region.
4942 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4943 isOpenMPGenericLoopDirective(ParentRegion) ||
4944 isOpenMPTaskingDirective(ParentRegion) ||
4945 llvm::is_contained({OMPD_masked, OMPD_master,
4946 OMPD_critical, OMPD_ordered},
4947 EnclosingConstruct);
4948 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
4949 !isOpenMPParallelDirective(CurrentRegion) &&
4950 !isOpenMPTeamsDirective(CurrentRegion)) {
4951 // OpenMP 5.1 [2.22, Nesting of Regions]
4952 // A loop region that binds to a parallel region or a worksharing region
4953 // may not be closely nested inside a worksharing, loop, task, taskloop,
4954 // critical, ordered, atomic, or masked region.
4955 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4956 isOpenMPGenericLoopDirective(ParentRegion) ||
4957 isOpenMPTaskingDirective(ParentRegion) ||
4958 llvm::is_contained({OMPD_masked, OMPD_master,
4959 OMPD_critical, OMPD_ordered},
4960 EnclosingConstruct);
4961 Recommend = ShouldBeInParallelRegion;
4962 } else if (CurrentRegion == OMPD_ordered) {
4963 // OpenMP [2.16, Nesting of Regions]
4964 // An ordered region may not be closely nested inside a critical,
4965 // atomic, or explicit task region.
4966 // An ordered region must be closely nested inside a loop region (or
4967 // parallel loop region) with an ordered clause.
4968 // OpenMP [2.8.1,simd Construct, Restrictions]
4969 // An ordered construct with the simd clause is the only OpenMP construct
4970 // that can appear in the simd region.
4971 NestingProhibited = EnclosingConstruct == OMPD_critical ||
4972 isOpenMPTaskingDirective(ParentRegion) ||
4973 !(isOpenMPSimdDirective(ParentRegion) ||
4974 Stack->isParentOrderedRegion());
4975 Recommend = ShouldBeInOrderedRegion;
4976 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
4977 // OpenMP [2.16, Nesting of Regions]
4978 // If specified, a teams construct must be contained within a target
4979 // construct.
4980 NestingProhibited =
4981 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
4982 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
4983 EnclosingConstruct != OMPD_target);
4984 OrphanSeen = ParentRegion == OMPD_unknown;
4985 Recommend = ShouldBeInTargetRegion;
4986 } else if (CurrentRegion == OMPD_scan) {
4987 if (OMPVersion >= 50) {
4988 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
4989 // simd, or for simd. This has to take into account combined directives.
4990 // In 5.2 this seems to be implied by the fact that the specified
4991 // separated constructs are do, for, and simd.
4992 NestingProhibited = !llvm::is_contained(
4993 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
4994 } else {
4995 NestingProhibited = true;
4996 }
4997 OrphanSeen = ParentRegion == OMPD_unknown;
4998 Recommend = ShouldBeInLoopSimdRegion;
4999 }
5000 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5001 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5002 EnclosingConstruct == OMPD_teams) {
5003 // OpenMP [5.1, 2.22, Nesting of Regions]
5004 // distribute, distribute simd, distribute parallel worksharing-loop,
5005 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5006 // including any parallel regions arising from combined constructs,
5007 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5008 // only OpenMP regions that may be strictly nested inside the teams
5009 // region.
5010 //
5011 // As an extension, we permit atomic within teams as well.
5012 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5013 !isOpenMPDistributeDirective(CurrentRegion) &&
5014 CurrentRegion != OMPD_loop &&
5015 !(SemaRef.getLangOpts().OpenMPExtensions &&
5016 CurrentRegion == OMPD_atomic);
5017 Recommend = ShouldBeInParallelRegion;
5018 }
5019 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5020 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5021 // If the bind clause is present on the loop construct and binding is
5022 // teams then the corresponding loop region must be strictly nested inside
5023 // a teams region.
5024 NestingProhibited =
5025 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5026 Recommend = ShouldBeInTeamsRegion;
5027 }
5028 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5029 // OpenMP 4.5 [2.17 Nesting of Regions]
5030 // The region associated with the distribute construct must be strictly
5031 // nested inside a teams region
5032 NestingProhibited = EnclosingConstruct != OMPD_teams;
5033 Recommend = ShouldBeInTeamsRegion;
5034 }
5035 if (!NestingProhibited &&
5036 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5037 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5038 // OpenMP 4.5 [2.17 Nesting of Regions]
5039 // If a target, target update, target data, target enter data, or
5040 // target exit data construct is encountered during execution of a
5041 // target region, the behavior is unspecified.
5042 NestingProhibited = Stack->hasDirective(
5043 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5044 SourceLocation) {
5045 if (isOpenMPTargetExecutionDirective(K)) {
5046 OffendingRegion = K;
5047 return true;
5048 }
5049 return false;
5050 },
5051 false /* don't skip top directive */);
5052 CloseNesting = false;
5053 }
5054 if (NestingProhibited) {
5055 if (OrphanSeen) {
5056 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5057 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5058 } else {
5059 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5060 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5061 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5062 }
5063 return true;
5064 }
5065 return false;
5066}
5067
5068struct Kind2Unsigned {
5069 using argument_type = OpenMPDirectiveKind;
5070 unsigned operator()(argument_type DK) { return unsigned(DK); }
5071};
5072static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5073 ArrayRef<OMPClause *> Clauses,
5074 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5075 bool ErrorFound = false;
5076 unsigned NamedModifiersNumber = 0;
5077 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5078 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5079 SmallVector<SourceLocation, 4> NameModifierLoc;
5080 unsigned OMPVersion = S.getLangOpts().OpenMP;
5081 for (const OMPClause *C : Clauses) {
5082 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(Val: C)) {
5083 // At most one if clause without a directive-name-modifier can appear on
5084 // the directive.
5085 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5086 auto &FNM = FoundNameModifiers[CurNM];
5087 if (FNM) {
5088 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5089 << getOpenMPDirectiveName(Kind, OMPVersion)
5090 << getOpenMPClauseNameForDiag(OMPC_if) << (CurNM != OMPD_unknown)
5091 << getOpenMPDirectiveName(CurNM, OMPVersion);
5092 ErrorFound = true;
5093 } else if (CurNM != OMPD_unknown) {
5094 NameModifierLoc.push_back(Elt: IC->getNameModifierLoc());
5095 ++NamedModifiersNumber;
5096 }
5097 FNM = IC;
5098 if (CurNM == OMPD_unknown)
5099 continue;
5100 // Check if the specified name modifier is allowed for the current
5101 // directive.
5102 // At most one if clause with the particular directive-name-modifier can
5103 // appear on the directive.
5104 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5105 S.Diag(IC->getNameModifierLoc(),
5106 diag::err_omp_wrong_if_directive_name_modifier)
5107 << getOpenMPDirectiveName(CurNM, OMPVersion)
5108 << getOpenMPDirectiveName(Kind, OMPVersion);
5109 ErrorFound = true;
5110 }
5111 }
5112 }
5113 // If any if clause on the directive includes a directive-name-modifier then
5114 // all if clauses on the directive must include a directive-name-modifier.
5115 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5116 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5117 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5118 diag::err_omp_no_more_if_clause);
5119 } else {
5120 std::string Values;
5121 std::string Sep(", ");
5122 unsigned AllowedCnt = 0;
5123 unsigned TotalAllowedNum =
5124 AllowedNameModifiers.size() - NamedModifiersNumber;
5125 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5126 ++Cnt) {
5127 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5128 if (!FoundNameModifiers[NM]) {
5129 Values += "'";
5130 Values += getOpenMPDirectiveName(NM, OMPVersion);
5131 Values += "'";
5132 if (AllowedCnt + 2 == TotalAllowedNum)
5133 Values += " or ";
5134 else if (AllowedCnt + 1 != TotalAllowedNum)
5135 Values += Sep;
5136 ++AllowedCnt;
5137 }
5138 }
5139 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5140 diag::err_omp_unnamed_if_clause)
5141 << (TotalAllowedNum > 1) << Values;
5142 }
5143 for (SourceLocation Loc : NameModifierLoc) {
5144 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5145 }
5146 ErrorFound = true;
5147 }
5148 return ErrorFound;
5149}
5150
5151static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5152 SourceLocation &ELoc,
5153 SourceRange &ERange,
5154 bool AllowArraySection,
5155 StringRef DiagType) {
5156 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5157 RefExpr->containsUnexpandedParameterPack())
5158 return std::make_pair(x: nullptr, y: true);
5159
5160 // OpenMP [3.1, C/C++]
5161 // A list item is a variable name.
5162 // OpenMP [2.9.3.3, Restrictions, p.1]
5163 // A variable that is part of another variable (as an array or
5164 // structure element) cannot appear in a private clause.
5165 RefExpr = RefExpr->IgnoreParens();
5166 enum {
5167 NoArrayExpr = -1,
5168 ArraySubscript = 0,
5169 OMPArraySection = 1
5170 } IsArrayExpr = NoArrayExpr;
5171 if (AllowArraySection) {
5172 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(Val: RefExpr)) {
5173 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5174 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base))
5175 Base = TempASE->getBase()->IgnoreParenImpCasts();
5176 RefExpr = Base;
5177 IsArrayExpr = ArraySubscript;
5178 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(Val: RefExpr)) {
5179 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5180 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Val: Base))
5181 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5182 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base))
5183 Base = TempASE->getBase()->IgnoreParenImpCasts();
5184 RefExpr = Base;
5185 IsArrayExpr = OMPArraySection;
5186 }
5187 }
5188 ELoc = RefExpr->getExprLoc();
5189 ERange = RefExpr->getSourceRange();
5190 RefExpr = RefExpr->IgnoreParenImpCasts();
5191 auto *DE = dyn_cast_or_null<DeclRefExpr>(Val: RefExpr);
5192 auto *ME = dyn_cast_or_null<MemberExpr>(Val: RefExpr);
5193 if ((!DE || !isa<VarDecl>(Val: DE->getDecl())) &&
5194 (S.getCurrentThisType().isNull() || !ME ||
5195 !isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()) ||
5196 !isa<FieldDecl>(Val: ME->getMemberDecl()))) {
5197 if (IsArrayExpr != NoArrayExpr) {
5198 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5199 << IsArrayExpr << ERange;
5200 } else if (!DiagType.empty()) {
5201 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5202 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5203 : 0;
5204 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5205 << DiagSelect << DiagType << ERange;
5206 } else {
5207 S.Diag(ELoc,
5208 AllowArraySection
5209 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5210 : diag::err_omp_expected_var_name_member_expr)
5211 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5212 }
5213 return std::make_pair(x: nullptr, y: false);
5214 }
5215 return std::make_pair(
5216 x: getCanonicalDecl(D: DE ? DE->getDecl() : ME->getMemberDecl()), y: false);
5217}
5218
5219namespace {
5220/// Checks if the allocator is used in uses_allocators clause to be allowed in
5221/// target regions.
5222class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5223 DSAStackTy *S = nullptr;
5224
5225public:
5226 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5227 return S->isUsesAllocatorsDecl(E->getDecl())
5228 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5229 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5230 }
5231 bool VisitStmt(const Stmt *S) {
5232 for (const Stmt *Child : S->children()) {
5233 if (Child && Visit(Child))
5234 return true;
5235 }
5236 return false;
5237 }
5238 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5239};
5240} // namespace
5241
5242static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5243 ArrayRef<OMPClause *> Clauses) {
5244 assert(!S.CurContext->isDependentContext() &&
5245 "Expected non-dependent context.");
5246 auto AllocateRange =
5247 llvm::make_filter_range(Range&: Clauses, Pred: OMPAllocateClause::classof);
5248 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5249 auto PrivateRange = llvm::make_filter_range(Range&: Clauses, Pred: [](const OMPClause *C) {
5250 return isOpenMPPrivate(C->getClauseKind());
5251 });
5252 for (OMPClause *Cl : PrivateRange) {
5253 MutableArrayRef<Expr *>::iterator I, It, Et;
5254 if (Cl->getClauseKind() == OMPC_private) {
5255 auto *PC = cast<OMPPrivateClause>(Val: Cl);
5256 I = PC->private_copies().begin();
5257 It = PC->varlist_begin();
5258 Et = PC->varlist_end();
5259 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5260 auto *PC = cast<OMPFirstprivateClause>(Val: Cl);
5261 I = PC->private_copies().begin();
5262 It = PC->varlist_begin();
5263 Et = PC->varlist_end();
5264 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5265 auto *PC = cast<OMPLastprivateClause>(Val: Cl);
5266 I = PC->private_copies().begin();
5267 It = PC->varlist_begin();
5268 Et = PC->varlist_end();
5269 } else if (Cl->getClauseKind() == OMPC_linear) {
5270 auto *PC = cast<OMPLinearClause>(Val: Cl);
5271 I = PC->privates().begin();
5272 It = PC->varlist_begin();
5273 Et = PC->varlist_end();
5274 } else if (Cl->getClauseKind() == OMPC_reduction) {
5275 auto *PC = cast<OMPReductionClause>(Val: Cl);
5276 I = PC->privates().begin();
5277 It = PC->varlist_begin();
5278 Et = PC->varlist_end();
5279 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5280 auto *PC = cast<OMPTaskReductionClause>(Val: Cl);
5281 I = PC->privates().begin();
5282 It = PC->varlist_begin();
5283 Et = PC->varlist_end();
5284 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5285 auto *PC = cast<OMPInReductionClause>(Val: Cl);
5286 I = PC->privates().begin();
5287 It = PC->varlist_begin();
5288 Et = PC->varlist_end();
5289 } else {
5290 llvm_unreachable("Expected private clause.");
5291 }
5292 for (Expr *E : llvm::make_range(x: It, y: Et)) {
5293 if (!*I) {
5294 ++I;
5295 continue;
5296 }
5297 SourceLocation ELoc;
5298 SourceRange ERange;
5299 Expr *SimpleRefExpr = E;
5300 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
5301 /*AllowArraySection=*/true);
5302 DeclToCopy.try_emplace(Res.first,
5303 cast<VarDecl>(Val: cast<DeclRefExpr>(Val: *I)->getDecl()));
5304 ++I;
5305 }
5306 }
5307 for (OMPClause *C : AllocateRange) {
5308 auto *AC = cast<OMPAllocateClause>(Val: C);
5309 if (S.getLangOpts().OpenMP >= 50 &&
5310 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5311 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5312 AC->getAllocator()) {
5313 Expr *Allocator = AC->getAllocator();
5314 // OpenMP, 2.12.5 target Construct
5315 // Memory allocators that do not appear in a uses_allocators clause cannot
5316 // appear as an allocator in an allocate clause or be used in the target
5317 // region unless a requires directive with the dynamic_allocators clause
5318 // is present in the same compilation unit.
5319 AllocatorChecker Checker(Stack);
5320 if (Checker.Visit(Allocator))
5321 S.Diag(Allocator->getExprLoc(),
5322 diag::err_omp_allocator_not_in_uses_allocators)
5323 << Allocator->getSourceRange();
5324 }
5325 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5326 getAllocatorKind(S, Stack, AC->getAllocator());
5327 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5328 // For task, taskloop or target directives, allocation requests to memory
5329 // allocators with the trait access set to thread result in unspecified
5330 // behavior.
5331 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5332 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5333 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5334 unsigned OMPVersion = S.getLangOpts().OpenMP;
5335 S.Diag(AC->getAllocator()->getExprLoc(),
5336 diag::warn_omp_allocate_thread_on_task_target_directive)
5337 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5338 }
5339 for (Expr *E : AC->varlist()) {
5340 SourceLocation ELoc;
5341 SourceRange ERange;
5342 Expr *SimpleRefExpr = E;
5343 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5344 ValueDecl *VD = Res.first;
5345 if (!VD)
5346 continue;
5347 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5348 if (!isOpenMPPrivate(Data.CKind)) {
5349 S.Diag(E->getExprLoc(),
5350 diag::err_omp_expected_private_copy_for_allocate);
5351 continue;
5352 }
5353 VarDecl *PrivateVD = DeclToCopy[VD];
5354 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5355 AllocatorKind, AC->getAllocator()))
5356 continue;
5357 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5358 AC->getAlignment(), E->getSourceRange());
5359 }
5360 }
5361}
5362
5363namespace {
5364/// Rewrite statements and expressions for Sema \p Actions CurContext.
5365///
5366/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5367/// context. DeclRefExpr used inside the new context are changed to refer to the
5368/// captured variable instead.
5369class CaptureVars : public TreeTransform<CaptureVars> {
5370 using BaseTransform = TreeTransform<CaptureVars>;
5371
5372public:
5373 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5374
5375 bool AlwaysRebuild() { return true; }
5376};
5377} // namespace
5378
5379static VarDecl *precomputeExpr(Sema &Actions,
5380 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5381 StringRef Name) {
5382 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5383 VarDecl *NewVar = buildVarDecl(SemaRef&: Actions, Loc: {}, Type: NewE->getType(), Name, Attrs: nullptr,
5384 OrigRef: dyn_cast<DeclRefExpr>(Val: E->IgnoreImplicit()));
5385 auto *NewDeclStmt = cast<DeclStmt>(Val: AssertSuccess(
5386 R: Actions.ActOnDeclStmt(Decl: Actions.ConvertDeclToDeclGroup(NewVar), StartLoc: {}, EndLoc: {})));
5387 Actions.AddInitializerToDecl(dcl: NewDeclStmt->getSingleDecl(), init: NewE, DirectInit: false);
5388 BodyStmts.push_back(Elt: NewDeclStmt);
5389 return NewVar;
5390}
5391
5392/// Create a closure that computes the number of iterations of a loop.
5393///
5394/// \param Actions The Sema object.
5395/// \param LogicalTy Type for the logical iteration number.
5396/// \param Rel Comparison operator of the loop condition.
5397/// \param StartExpr Value of the loop counter at the first iteration.
5398/// \param StopExpr Expression the loop counter is compared against in the loop
5399/// condition. \param StepExpr Amount of increment after each iteration.
5400///
5401/// \return Closure (CapturedStmt) of the distance calculation.
5402static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5403 BinaryOperator::Opcode Rel,
5404 Expr *StartExpr, Expr *StopExpr,
5405 Expr *StepExpr) {
5406 ASTContext &Ctx = Actions.getASTContext();
5407 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(T: LogicalTy);
5408
5409 // Captured regions currently don't support return values, we use an
5410 // out-parameter instead. All inputs are implicit captures.
5411 // TODO: Instead of capturing each DeclRefExpr occurring in
5412 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5413 QualType ResultTy = Ctx.getLValueReferenceType(T: LogicalTy);
5414 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5415 {StringRef(), QualType()}};
5416 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5417
5418 Stmt *Body;
5419 {
5420 Sema::CompoundScopeRAII CompoundScope(Actions);
5421 CapturedDecl *CS = cast<CapturedDecl>(Val: Actions.CurContext);
5422
5423 // Get the LValue expression for the result.
5424 ImplicitParamDecl *DistParam = CS->getParam(i: 0);
5425 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5426 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5427
5428 SmallVector<Stmt *, 4> BodyStmts;
5429
5430 // Capture all referenced variable references.
5431 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5432 // CapturedStmt, we could compute them before and capture the result, to be
5433 // used jointly with the LoopVar function.
5434 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, E: StartExpr, Name: ".start");
5435 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, E: StopExpr, Name: ".stop");
5436 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, E: StepExpr, Name: ".step");
5437 auto BuildVarRef = [&](VarDecl *VD) {
5438 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5439 };
5440
5441 IntegerLiteral *Zero = IntegerLiteral::Create(
5442 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 0), type: LogicalTy, l: {});
5443 IntegerLiteral *One = IntegerLiteral::Create(
5444 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 1), type: LogicalTy, l: {});
5445 Expr *Dist;
5446 if (Rel == BO_NE) {
5447 // When using a != comparison, the increment can be +1 or -1. This can be
5448 // dynamic at runtime, so we need to check for the direction.
5449 Expr *IsNegStep = AssertSuccess(
5450 Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_LT, LHSExpr: BuildVarRef(NewStep), RHSExpr: Zero));
5451
5452 // Positive increment.
5453 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5454 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStop), RHSExpr: BuildVarRef(NewStart)));
5455 ForwardRange = AssertSuccess(
5456 R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: ForwardRange));
5457 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5458 S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: ForwardRange, RHSExpr: BuildVarRef(NewStep)));
5459
5460 // Negative increment.
5461 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5462 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5463 BackwardRange = AssertSuccess(
5464 R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: BackwardRange));
5465 Expr *NegIncAmount = AssertSuccess(
5466 Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: BuildVarRef(NewStep)));
5467 Expr *BackwardDist = AssertSuccess(
5468 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: BackwardRange, RHSExpr: NegIncAmount));
5469
5470 // Use the appropriate case.
5471 Dist = AssertSuccess(R: Actions.ActOnConditionalOp(
5472 QuestionLoc: {}, ColonLoc: {}, CondExpr: IsNegStep, LHSExpr: BackwardDist, RHSExpr: ForwardDist));
5473 } else {
5474 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5475 "Expected one of these relational operators");
5476
5477 // We can derive the direction from any other comparison operator. It is
5478 // non well-formed OpenMP if Step increments/decrements in the other
5479 // directions. Whether at least the first iteration passes the loop
5480 // condition.
5481 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5482 S: nullptr, OpLoc: {}, Opc: Rel, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5483
5484 // Compute the range between first and last counter value.
5485 Expr *Range;
5486 if (Rel == BO_GE || Rel == BO_GT)
5487 Range = AssertSuccess(Actions.BuildBinOp(
5488 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStart), RHSExpr: BuildVarRef(NewStop)));
5489 else
5490 Range = AssertSuccess(Actions.BuildBinOp(
5491 S: nullptr, OpLoc: {}, Opc: BO_Sub, LHSExpr: BuildVarRef(NewStop), RHSExpr: BuildVarRef(NewStart)));
5492
5493 // Ensure unsigned range space.
5494 Range =
5495 AssertSuccess(R: Actions.BuildCStyleCastExpr(LParenLoc: {}, Ty: LogicalTSI, RParenLoc: {}, Op: Range));
5496
5497 if (Rel == BO_LE || Rel == BO_GE) {
5498 // Add one to the range if the relational operator is inclusive.
5499 Range =
5500 AssertSuccess(R: Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5501 }
5502
5503 // Divide by the absolute step amount. If the range is not a multiple of
5504 // the step size, rounding-up the effective upper bound ensures that the
5505 // last iteration is included.
5506 // Note that the rounding-up may cause an overflow in a temporary that
5507 // could be avoided, but would have occurred in a C-style for-loop as
5508 // well.
5509 Expr *Divisor = BuildVarRef(NewStep);
5510 if (Rel == BO_GE || Rel == BO_GT)
5511 Divisor =
5512 AssertSuccess(R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: Divisor));
5513 Expr *DivisorMinusOne =
5514 AssertSuccess(R: Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5515 Expr *RangeRoundUp = AssertSuccess(
5516 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: Range, RHSExpr: DivisorMinusOne));
5517 Dist = AssertSuccess(
5518 R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Div, LHSExpr: RangeRoundUp, RHSExpr: Divisor));
5519
5520 // If there is not at least one iteration, the range contains garbage. Fix
5521 // to zero in this case.
5522 Dist = AssertSuccess(
5523 R: Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5524 }
5525
5526 // Assign the result to the out-parameter.
5527 Stmt *ResultAssign = AssertSuccess(R: Actions.BuildBinOp(
5528 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5529 BodyStmts.push_back(Elt: ResultAssign);
5530
5531 Body = AssertSuccess(R: Actions.ActOnCompoundStmt(L: {}, R: {}, Elts: BodyStmts, isStmtExpr: false));
5532 }
5533
5534 return cast<CapturedStmt>(
5535 Val: AssertSuccess(R: Actions.ActOnCapturedRegionEnd(S: Body)));
5536}
5537
5538/// Create a closure that computes the loop variable from the logical iteration
5539/// number.
5540///
5541/// \param Actions The Sema object.
5542/// \param LoopVarTy Type for the loop variable used for result value.
5543/// \param LogicalTy Type for the logical iteration number.
5544/// \param StartExpr Value of the loop counter at the first iteration.
5545/// \param Step Amount of increment after each iteration.
5546/// \param Deref Whether the loop variable is a dereference of the loop
5547/// counter variable.
5548///
5549/// \return Closure (CapturedStmt) of the loop value calculation.
5550static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5551 QualType LogicalTy,
5552 DeclRefExpr *StartExpr, Expr *Step,
5553 bool Deref) {
5554 ASTContext &Ctx = Actions.getASTContext();
5555
5556 // Pass the result as an out-parameter. Passing as return value would require
5557 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5558 // invoke a copy constructor.
5559 QualType TargetParamTy = Ctx.getLValueReferenceType(T: LoopVarTy);
5560 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5561 {"Logical", LogicalTy},
5562 {StringRef(), QualType()}};
5563 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5564
5565 // Capture the initial iterator which represents the LoopVar value at the
5566 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5567 // it in every iteration, capture it by value before it is modified.
5568 VarDecl *StartVar = cast<VarDecl>(Val: StartExpr->getDecl());
5569 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5570 TryCaptureKind::ExplicitByVal, {});
5571 (void)Invalid;
5572 assert(!Invalid && "Expecting capture-by-value to work.");
5573
5574 Expr *Body;
5575 {
5576 Sema::CompoundScopeRAII CompoundScope(Actions);
5577 auto *CS = cast<CapturedDecl>(Val: Actions.CurContext);
5578
5579 ImplicitParamDecl *TargetParam = CS->getParam(i: 0);
5580 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5581 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5582 ImplicitParamDecl *IndvarParam = CS->getParam(i: 1);
5583 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5584 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5585
5586 // Capture the Start expression.
5587 CaptureVars Recap(Actions);
5588 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5589 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5590
5591 Expr *Skip = AssertSuccess(
5592 R: Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5593 // TODO: Explicitly cast to the iterator's difference_type instead of
5594 // relying on implicit conversion.
5595 Expr *Advanced =
5596 AssertSuccess(R: Actions.BuildBinOp(S: nullptr, OpLoc: {}, Opc: BO_Add, LHSExpr: NewStart, RHSExpr: Skip));
5597
5598 if (Deref) {
5599 // For range-based for-loops convert the loop counter value to a concrete
5600 // loop variable value by dereferencing the iterator.
5601 Advanced =
5602 AssertSuccess(R: Actions.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Deref, Input: Advanced));
5603 }
5604
5605 // Assign the result to the output parameter.
5606 Body = AssertSuccess(R: Actions.BuildBinOp(Actions.getCurScope(), {},
5607 BO_Assign, TargetRef, Advanced));
5608 }
5609 return cast<CapturedStmt>(
5610 Val: AssertSuccess(R: Actions.ActOnCapturedRegionEnd(Body)));
5611}
5612
5613StmtResult SemaOpenMP::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
5614 ASTContext &Ctx = getASTContext();
5615
5616 // Extract the common elements of ForStmt and CXXForRangeStmt:
5617 // Loop variable, repeat condition, increment
5618 Expr *Cond, *Inc;
5619 VarDecl *LIVDecl, *LUVDecl;
5620 if (auto *For = dyn_cast<ForStmt>(Val: AStmt)) {
5621 Stmt *Init = For->getInit();
5622 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Val: Init)) {
5623 // For statement declares loop variable.
5624 LIVDecl = cast<VarDecl>(Val: LCVarDeclStmt->getSingleDecl());
5625 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Val: Init)) {
5626 // For statement reuses variable.
5627 assert(LCAssign->getOpcode() == BO_Assign &&
5628 "init part must be a loop variable assignment");
5629 auto *CounterRef = cast<DeclRefExpr>(Val: LCAssign->getLHS());
5630 LIVDecl = cast<VarDecl>(Val: CounterRef->getDecl());
5631 } else
5632 llvm_unreachable("Cannot determine loop variable");
5633 LUVDecl = LIVDecl;
5634
5635 Cond = For->getCond();
5636 Inc = For->getInc();
5637 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(Val: AStmt)) {
5638 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5639 LIVDecl = cast<VarDecl>(Val: BeginStmt->getSingleDecl());
5640 LUVDecl = RangeFor->getLoopVariable();
5641
5642 Cond = RangeFor->getCond();
5643 Inc = RangeFor->getInc();
5644 } else
5645 llvm_unreachable("unhandled kind of loop");
5646
5647 QualType CounterTy = LIVDecl->getType();
5648 QualType LVTy = LUVDecl->getType();
5649
5650 // Analyze the loop condition.
5651 Expr *LHS, *RHS;
5652 BinaryOperator::Opcode CondRel;
5653 Cond = Cond->IgnoreImplicit();
5654 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Val: Cond)) {
5655 LHS = CondBinExpr->getLHS();
5656 RHS = CondBinExpr->getRHS();
5657 CondRel = CondBinExpr->getOpcode();
5658 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Val: Cond)) {
5659 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5660 LHS = CondCXXOp->getArg(0);
5661 RHS = CondCXXOp->getArg(1);
5662 switch (CondCXXOp->getOperator()) {
5663 case OO_ExclaimEqual:
5664 CondRel = BO_NE;
5665 break;
5666 case OO_Less:
5667 CondRel = BO_LT;
5668 break;
5669 case OO_LessEqual:
5670 CondRel = BO_LE;
5671 break;
5672 case OO_Greater:
5673 CondRel = BO_GT;
5674 break;
5675 case OO_GreaterEqual:
5676 CondRel = BO_GE;
5677 break;
5678 default:
5679 llvm_unreachable("unexpected iterator operator");
5680 }
5681 } else
5682 llvm_unreachable("unexpected loop condition");
5683
5684 // Normalize such that the loop counter is on the LHS.
5685 if (!isa<DeclRefExpr>(Val: LHS->IgnoreImplicit()) ||
5686 cast<DeclRefExpr>(Val: LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5687 std::swap(a&: LHS, b&: RHS);
5688 CondRel = BinaryOperator::reverseComparisonOp(Opc: CondRel);
5689 }
5690 auto *CounterRef = cast<DeclRefExpr>(Val: LHS->IgnoreImplicit());
5691
5692 // Decide the bit width for the logical iteration counter. By default use the
5693 // unsigned ptrdiff_t integer size (for iterators and pointers).
5694 // TODO: For iterators, use iterator::difference_type,
5695 // std::iterator_traits<>::difference_type or decltype(it - end).
5696 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5697 if (CounterTy->isIntegerType()) {
5698 unsigned BitWidth = Ctx.getIntWidth(T: CounterTy);
5699 LogicalTy = Ctx.getIntTypeForBitwidth(DestWidth: BitWidth, Signed: false);
5700 }
5701
5702 // Analyze the loop increment.
5703 Expr *Step;
5704 if (auto *IncUn = dyn_cast<UnaryOperator>(Val: Inc)) {
5705 int Direction;
5706 switch (IncUn->getOpcode()) {
5707 case UO_PreInc:
5708 case UO_PostInc:
5709 Direction = 1;
5710 break;
5711 case UO_PreDec:
5712 case UO_PostDec:
5713 Direction = -1;
5714 break;
5715 default:
5716 llvm_unreachable("unhandled unary increment operator");
5717 }
5718 Step = IntegerLiteral::Create(
5719 C: Ctx,
5720 V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), Direction, /*isSigned=*/true),
5721 type: LogicalTy, l: {});
5722 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Val: Inc)) {
5723 if (IncBin->getOpcode() == BO_AddAssign) {
5724 Step = IncBin->getRHS();
5725 } else if (IncBin->getOpcode() == BO_SubAssign) {
5726 Step = AssertSuccess(
5727 R: SemaRef.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: IncBin->getRHS()));
5728 } else
5729 llvm_unreachable("unhandled binary increment operator");
5730 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Val: Inc)) {
5731 switch (CondCXXOp->getOperator()) {
5732 case OO_PlusPlus:
5733 Step = IntegerLiteral::Create(
5734 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), 1), type: LogicalTy, l: {});
5735 break;
5736 case OO_MinusMinus:
5737 Step = IntegerLiteral::Create(
5738 C: Ctx, V: llvm::APInt(Ctx.getIntWidth(T: LogicalTy), -1), type: LogicalTy, l: {});
5739 break;
5740 case OO_PlusEqual:
5741 Step = CondCXXOp->getArg(1);
5742 break;
5743 case OO_MinusEqual:
5744 Step = AssertSuccess(
5745 SemaRef.BuildUnaryOp(S: nullptr, OpLoc: {}, Opc: UO_Minus, Input: CondCXXOp->getArg(1)));
5746 break;
5747 default:
5748 llvm_unreachable("unhandled overloaded increment operator");
5749 }
5750 } else
5751 llvm_unreachable("unknown increment expression");
5752
5753 CapturedStmt *DistanceFunc =
5754 buildDistanceFunc(Actions&: SemaRef, LogicalTy, Rel: CondRel, StartExpr: LHS, StopExpr: RHS, StepExpr: Step);
5755 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5756 Actions&: SemaRef, LoopVarTy: LVTy, LogicalTy, StartExpr: CounterRef, Step, Deref: isa<CXXForRangeStmt>(Val: AStmt));
5757 DeclRefExpr *LVRef =
5758 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5759 nullptr, nullptr, {}, nullptr);
5760 return OMPCanonicalLoop::create(Ctx: getASTContext(), LoopStmt: AStmt, DistanceFunc,
5761 LoopVarFunc, LoopVarRef: LVRef);
5762}
5763
5764StmtResult SemaOpenMP::ActOnOpenMPLoopnest(Stmt *AStmt) {
5765 // Handle a literal loop.
5766 if (isa<ForStmt>(Val: AStmt) || isa<CXXForRangeStmt>(Val: AStmt))
5767 return ActOnOpenMPCanonicalLoop(AStmt);
5768
5769 // If not a literal loop, it must be the result of a loop transformation.
5770 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(Val: AStmt);
5771 assert(
5772 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5773 "Loop transformation directive expected");
5774 return LoopTransform;
5775}
5776
5777static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
5778 CXXScopeSpec &MapperIdScopeSpec,
5779 const DeclarationNameInfo &MapperId,
5780 QualType Type,
5781 Expr *UnresolvedMapper);
5782
5783/// Perform DFS through the structure/class data members trying to find
5784/// member(s) with user-defined 'default' mapper and generate implicit map
5785/// clauses for such members with the found 'default' mapper.
5786static void
5787processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
5788 SmallVectorImpl<OMPClause *> &Clauses) {
5789 // Check for the default mapper for data members.
5790 if (S.getLangOpts().OpenMP < 50)
5791 return;
5792 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5793 auto *C = dyn_cast<OMPMapClause>(Val: Clauses[Cnt]);
5794 if (!C)
5795 continue;
5796 SmallVector<Expr *, 4> SubExprs;
5797 auto *MI = C->mapperlist_begin();
5798 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5799 ++I, ++MI) {
5800 // Expression is mapped using mapper - skip it.
5801 if (*MI)
5802 continue;
5803 Expr *E = *I;
5804 // Expression is dependent - skip it, build the mapper when it gets
5805 // instantiated.
5806 if (E->isTypeDependent() || E->isValueDependent() ||
5807 E->containsUnexpandedParameterPack())
5808 continue;
5809 // Array section - need to check for the mapping of the array section
5810 // element.
5811 QualType CanonType = E->getType().getCanonicalType();
5812 if (CanonType->isSpecificBuiltinType(K: BuiltinType::ArraySection)) {
5813 const auto *OASE = cast<ArraySectionExpr>(Val: E->IgnoreParenImpCasts());
5814 QualType BaseType =
5815 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
5816 QualType ElemType;
5817 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
5818 ElemType = ATy->getElementType();
5819 else
5820 ElemType = BaseType->getPointeeType();
5821 CanonType = ElemType;
5822 }
5823
5824 // DFS over data members in structures/classes.
5825 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
5826 1, {CanonType, nullptr});
5827 llvm::DenseMap<const Type *, Expr *> Visited;
5828 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
5829 1, {nullptr, 1});
5830 while (!Types.empty()) {
5831 QualType BaseType;
5832 FieldDecl *CurFD;
5833 std::tie(args&: BaseType, args&: CurFD) = Types.pop_back_val();
5834 while (ParentChain.back().second == 0)
5835 ParentChain.pop_back();
5836 --ParentChain.back().second;
5837 if (BaseType.isNull())
5838 continue;
5839 // Only structs/classes are allowed to have mappers.
5840 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
5841 if (!RD)
5842 continue;
5843 auto It = Visited.find(Val: BaseType.getTypePtr());
5844 if (It == Visited.end()) {
5845 // Try to find the associated user-defined mapper.
5846 CXXScopeSpec MapperIdScopeSpec;
5847 DeclarationNameInfo DefaultMapperId;
5848 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
5849 ID: &S.Context.Idents.get(Name: "default")));
5850 DefaultMapperId.setLoc(E->getExprLoc());
5851 ExprResult ER = buildUserDefinedMapperRef(
5852 SemaRef&: S, S: Stack->getCurScope(), MapperIdScopeSpec, MapperId: DefaultMapperId,
5853 Type: BaseType, /*UnresolvedMapper=*/nullptr);
5854 if (ER.isInvalid())
5855 continue;
5856 It = Visited.try_emplace(Key: BaseType.getTypePtr(), Args: ER.get()).first;
5857 }
5858 // Found default mapper.
5859 if (It->second) {
5860 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
5861 VK_LValue, OK_Ordinary, E);
5862 OE->setIsUnique(/*V=*/true);
5863 Expr *BaseExpr = OE;
5864 for (const auto &P : ParentChain) {
5865 if (P.first) {
5866 BaseExpr = S.BuildMemberExpr(
5867 Base: BaseExpr, /*IsArrow=*/false, OpLoc: E->getExprLoc(),
5868 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: P.first,
5869 FoundDecl: DeclAccessPair::make(D: P.first, AS: P.first->getAccess()),
5870 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(),
5871 Ty: P.first->getType(), VK: VK_LValue, OK: OK_Ordinary);
5872 BaseExpr = S.DefaultLvalueConversion(E: BaseExpr).get();
5873 }
5874 }
5875 if (CurFD)
5876 BaseExpr = S.BuildMemberExpr(
5877 Base: BaseExpr, /*IsArrow=*/false, OpLoc: E->getExprLoc(),
5878 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: SourceLocation(), Member: CurFD,
5879 FoundDecl: DeclAccessPair::make(D: CurFD, AS: CurFD->getAccess()),
5880 /*HadMultipleCandidates=*/false, MemberNameInfo: DeclarationNameInfo(),
5881 Ty: CurFD->getType(), VK: VK_LValue, OK: OK_Ordinary);
5882 SubExprs.push_back(Elt: BaseExpr);
5883 continue;
5884 }
5885 // Check for the "default" mapper for data members.
5886 bool FirstIter = true;
5887 for (FieldDecl *FD : RD->fields()) {
5888 if (!FD)
5889 continue;
5890 QualType FieldTy = FD->getType();
5891 if (FieldTy.isNull() ||
5892 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
5893 continue;
5894 if (FirstIter) {
5895 FirstIter = false;
5896 ParentChain.emplace_back(Args&: CurFD, Args: 1);
5897 } else {
5898 ++ParentChain.back().second;
5899 }
5900 Types.emplace_back(Args&: FieldTy, Args&: FD);
5901 }
5902 }
5903 }
5904 if (SubExprs.empty())
5905 continue;
5906 CXXScopeSpec MapperIdScopeSpec;
5907 DeclarationNameInfo MapperId;
5908 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
5909 IteratorModifier: nullptr, MapTypeModifiers: C->getMapTypeModifiers(), MapTypeModifiersLoc: C->getMapTypeModifiersLoc(),
5910 MapperIdScopeSpec, MapperId, MapType: C->getMapType(),
5911 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(),
5912 VarList: SubExprs, Locs: OMPVarListLocTy()))
5913 Clauses.push_back(Elt: NewClause);
5914 }
5915}
5916
5917namespace {
5918/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
5919/// call in the associated loop-nest cannot be a 'parallel for'.
5920class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
5921 Sema &SemaRef;
5922
5923public:
5924 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
5925
5926 // Is there a nested OpenMP loop bind(parallel)
5927 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
5928 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5929 if (const auto *C = D->getSingleClause<OMPBindClause>())
5930 if (C->getBindKind() == OMPC_BIND_parallel) {
5931 TeamsLoopCanBeParallelFor = false;
5932 // No need to continue visiting any more
5933 return;
5934 }
5935 }
5936 for (const Stmt *Child : D->children())
5937 if (Child)
5938 Visit(Child);
5939 }
5940
5941 void VisitCallExpr(const CallExpr *C) {
5942 // Function calls inhibit parallel loop translation of 'target teams loop'
5943 // unless the assume-no-nested-parallelism flag has been specified.
5944 // OpenMP API runtime library calls do not inhibit parallel loop
5945 // translation, regardless of the assume-no-nested-parallelism.
5946 bool IsOpenMPAPI = false;
5947 auto *FD = dyn_cast_or_null<FunctionDecl>(Val: C->getCalleeDecl());
5948 if (FD) {
5949 std::string Name = FD->getNameInfo().getAsString();
5950 IsOpenMPAPI = Name.find(s: "omp_") == 0;
5951 }
5952 TeamsLoopCanBeParallelFor =
5953 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5954 if (!TeamsLoopCanBeParallelFor)
5955 return;
5956
5957 for (const Stmt *Child : C->children())
5958 if (Child)
5959 Visit(Child);
5960 }
5961
5962 void VisitCapturedStmt(const CapturedStmt *S) {
5963 if (!S)
5964 return;
5965 Visit(S->getCapturedDecl()->getBody());
5966 }
5967
5968 void VisitStmt(const Stmt *S) {
5969 if (!S)
5970 return;
5971 for (const Stmt *Child : S->children())
5972 if (Child)
5973 Visit(Child);
5974 }
5975 explicit TeamsLoopChecker(Sema &SemaRef)
5976 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
5977
5978private:
5979 bool TeamsLoopCanBeParallelFor;
5980};
5981} // namespace
5982
5983static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
5984 TeamsLoopChecker Checker(SemaRef);
5985 Checker.Visit(AStmt);
5986 return Checker.teamsLoopCanBeParallelFor();
5987}
5988
5989StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective(
5990 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
5991 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
5992 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
5993 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
5994
5995 StmtResult Res = StmtError();
5996 OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
5997 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
5998
5999 if (const OMPBindClause *BC =
6000 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6001 BindKind = BC->getBindKind();
6002
6003 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6004 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6005
6006 // Setting the enclosing teams or parallel construct for the loop
6007 // directive without bind clause.
6008 // [5.0:129:25-28] If the bind clause is not present on the construct and
6009 // the loop construct is closely nested inside a teams or parallel
6010 // construct, the binding region is the corresponding teams or parallel
6011 // region. If none of those conditions hold, the binding region is not
6012 // defined.
6013 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6014 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6015 getLeafConstructsOrSelf(ParentDirective);
6016
6017 if (ParentDirective == OMPD_unknown) {
6018 Diag(DSAStack->getDefaultDSALocation(),
6019 diag::err_omp_bind_required_on_loop);
6020 } else if (ParentLeafs.back() == OMPD_parallel) {
6021 BindKind = OMPC_BIND_parallel;
6022 } else if (ParentLeafs.back() == OMPD_teams) {
6023 BindKind = OMPC_BIND_teams;
6024 }
6025
6026 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6027
6028 OMPClause *C =
6029 ActOnOpenMPBindClause(Kind: BindKind, KindLoc: SourceLocation(), StartLoc: SourceLocation(),
6030 LParenLoc: SourceLocation(), EndLoc: SourceLocation());
6031 ClausesWithImplicit.push_back(Elt: C);
6032 }
6033
6034 // Diagnose "loop bind(teams)" with "reduction".
6035 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6036 for (OMPClause *C : Clauses) {
6037 if (C->getClauseKind() == OMPC_reduction)
6038 Diag(DSAStack->getDefaultDSALocation(),
6039 diag::err_omp_loop_reduction_clause);
6040 }
6041 }
6042
6043 // First check CancelRegion which is then used in checkNestingOfRegions.
6044 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6045 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6046 BindKind, StartLoc)) {
6047 return StmtError();
6048 }
6049
6050 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6051 if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(Kind) ||
6052 isOpenMPTargetDataManagementDirective(Kind)))
6053 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6054
6055 VarsWithInheritedDSAType VarsWithInheritedDSA;
6056 bool ErrorFound = false;
6057 ClausesWithImplicit.append(in_start: Clauses.begin(), in_end: Clauses.end());
6058
6059 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6060 isOpenMPCapturingDirective(Kind)) {
6061 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6062
6063 // Check default data sharing attributes for referenced variables.
6064 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(Val: AStmt));
6065 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6066 Stmt *S = AStmt;
6067 while (--ThisCaptureLevel >= 0)
6068 S = cast<CapturedStmt>(Val: S)->getCapturedStmt();
6069 DSAChecker.Visit(S);
6070 if (!isOpenMPTargetDataManagementDirective(Kind) &&
6071 !isOpenMPTaskingDirective(Kind)) {
6072 // Visit subcaptures to generate implicit clauses for captured vars.
6073 auto *CS = cast<CapturedStmt>(Val: AStmt);
6074 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
6075 getOpenMPCaptureRegions(CaptureRegions, Kind);
6076 // Ignore outer tasking regions for target directives.
6077 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6078 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
6079 DSAChecker.visitSubCaptures(S: CS);
6080 }
6081 if (DSAChecker.isErrorFound())
6082 return StmtError();
6083 // Generate list of implicitly defined firstprivate variables.
6084 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6085 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6086
6087 SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
6088 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6089 // Get the original location of present modifier from Defaultmap clause.
6090 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6091 for (OMPClause *C : Clauses) {
6092 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(Val: C))
6093 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6094 PresentModifierLocs[DMC->getDefaultmapKind()] =
6095 DMC->getDefaultmapModifierLoc();
6096 }
6097
6098 for (OpenMPDefaultmapClauseKind K :
6099 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6100 Begin: OpenMPDefaultmapClauseKind(), End: OMPC_DEFAULTMAP_unknown)) {
6101 std::fill_n(first: std::back_inserter(x&: ImplicitMapModifiersLoc[K]),
6102 n: ImpInfo.MapModifiers[K].size(), value: PresentModifierLocs[K]);
6103 }
6104 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6105 for (OMPClause *C : Clauses) {
6106 if (auto *IRC = dyn_cast<OMPInReductionClause>(Val: C)) {
6107 for (Expr *E : IRC->taskgroup_descriptors())
6108 if (E)
6109 ImpInfo.Firstprivates.insert(X: E);
6110 }
6111 // OpenMP 5.0, 2.10.1 task Construct
6112 // [detach clause]... The event-handle will be considered as if it was
6113 // specified on a firstprivate clause.
6114 if (auto *DC = dyn_cast<OMPDetachClause>(Val: C))
6115 ImpInfo.Firstprivates.insert(X: DC->getEventHandler());
6116 }
6117 if (!ImpInfo.Firstprivates.empty()) {
6118 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6119 VarList: ImpInfo.Firstprivates.getArrayRef(), StartLoc: SourceLocation(),
6120 LParenLoc: SourceLocation(), EndLoc: SourceLocation())) {
6121 ClausesWithImplicit.push_back(Elt: Implicit);
6122 ErrorFound = cast<OMPFirstprivateClause>(Val: Implicit)->varlist_size() !=
6123 ImpInfo.Firstprivates.size();
6124 } else {
6125 ErrorFound = true;
6126 }
6127 }
6128 if (!ImpInfo.Privates.empty()) {
6129 if (OMPClause *Implicit = ActOnOpenMPPrivateClause(
6130 VarList: ImpInfo.Privates.getArrayRef(), StartLoc: SourceLocation(),
6131 LParenLoc: SourceLocation(), EndLoc: SourceLocation())) {
6132 ClausesWithImplicit.push_back(Elt: Implicit);
6133 ErrorFound = cast<OMPPrivateClause>(Val: Implicit)->varlist_size() !=
6134 ImpInfo.Privates.size();
6135 } else {
6136 ErrorFound = true;
6137 }
6138 }
6139 // OpenMP 5.0 [2.19.7]
6140 // If a list item appears in a reduction, lastprivate or linear
6141 // clause on a combined target construct then it is treated as
6142 // if it also appears in a map clause with a map-type of tofrom
6143 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6144 isOpenMPTargetExecutionDirective(Kind)) {
6145 SmallVector<Expr *, 4> ImplicitExprs;
6146 for (OMPClause *C : Clauses) {
6147 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6148 for (Expr *E : RC->varlist())
6149 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6150 ImplicitExprs.emplace_back(E);
6151 }
6152 if (!ImplicitExprs.empty()) {
6153 ArrayRef<Expr *> Exprs = ImplicitExprs;
6154 CXXScopeSpec MapperIdScopeSpec;
6155 DeclarationNameInfo MapperId;
6156 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6157 IteratorModifier: nullptr, MapTypeModifiers: OMPC_MAP_MODIFIER_unknown, MapTypeModifiersLoc: SourceLocation(),
6158 MapperIdScopeSpec, MapperId, MapType: OMPC_MAP_tofrom,
6159 /*IsMapTypeImplicit=*/true, MapLoc: SourceLocation(), ColonLoc: SourceLocation(),
6160 VarList: Exprs, Locs: OMPVarListLocTy(), /*NoDiagnose=*/true))
6161 ClausesWithImplicit.emplace_back(Args&: Implicit);
6162 }
6163 }
6164 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6165 int ClauseKindCnt = -1;
6166 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6167 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6168 ++ClauseKindCnt;
6169 if (ImplicitMap.empty())
6170 continue;
6171 CXXScopeSpec MapperIdScopeSpec;
6172 DeclarationNameInfo MapperId;
6173 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6174 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6175 IteratorModifier: nullptr, MapTypeModifiers: ImpInfo.MapModifiers[I], MapTypeModifiersLoc: ImplicitMapModifiersLoc[I],
6176 MapperIdScopeSpec, MapperId, MapType: K, /*IsMapTypeImplicit=*/true,
6177 MapLoc: SourceLocation(), ColonLoc: SourceLocation(), VarList: ImplicitMap,
6178 Locs: OMPVarListLocTy())) {
6179 ClausesWithImplicit.emplace_back(Args&: Implicit);
6180 ErrorFound |= cast<OMPMapClause>(Val: Implicit)->varlist_size() !=
6181 ImplicitMap.size();
6182 } else {
6183 ErrorFound = true;
6184 }
6185 }
6186 }
6187 // Build expressions for implicit maps of data members with 'default'
6188 // mappers.
6189 if (getLangOpts().OpenMP >= 50)
6190 processImplicitMapsWithDefaultMappers(S&: SemaRef, DSAStack,
6191 Clauses&: ClausesWithImplicit);
6192 }
6193
6194 switch (Kind) {
6195 case OMPD_parallel:
6196 Res = ActOnOpenMPParallelDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6197 EndLoc);
6198 break;
6199 case OMPD_simd:
6200 Res = ActOnOpenMPSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6201 VarsWithImplicitDSA&: VarsWithInheritedDSA);
6202 break;
6203 case OMPD_tile:
6204 Res =
6205 ActOnOpenMPTileDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6206 break;
6207 case OMPD_stripe:
6208 Res = ActOnOpenMPStripeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6209 EndLoc);
6210 break;
6211 case OMPD_unroll:
6212 Res = ActOnOpenMPUnrollDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6213 EndLoc);
6214 break;
6215 case OMPD_reverse:
6216 assert(ClausesWithImplicit.empty() &&
6217 "reverse directive does not support any clauses");
6218 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6219 break;
6220 case OMPD_interchange:
6221 Res = ActOnOpenMPInterchangeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6222 EndLoc);
6223 break;
6224 case OMPD_for:
6225 Res = ActOnOpenMPForDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6226 VarsWithImplicitDSA&: VarsWithInheritedDSA);
6227 break;
6228 case OMPD_for_simd:
6229 Res = ActOnOpenMPForSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6230 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6231 break;
6232 case OMPD_sections:
6233 Res = ActOnOpenMPSectionsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6234 EndLoc);
6235 break;
6236 case OMPD_section:
6237 assert(ClausesWithImplicit.empty() &&
6238 "No clauses are allowed for 'omp section' directive");
6239 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6240 break;
6241 case OMPD_single:
6242 Res = ActOnOpenMPSingleDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6243 EndLoc);
6244 break;
6245 case OMPD_master:
6246 assert(ClausesWithImplicit.empty() &&
6247 "No clauses are allowed for 'omp master' directive");
6248 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6249 break;
6250 case OMPD_masked:
6251 Res = ActOnOpenMPMaskedDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6252 EndLoc);
6253 break;
6254 case OMPD_critical:
6255 Res = ActOnOpenMPCriticalDirective(DirName, Clauses: ClausesWithImplicit, AStmt,
6256 StartLoc, EndLoc);
6257 break;
6258 case OMPD_parallel_for:
6259 Res = ActOnOpenMPParallelForDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6260 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6261 break;
6262 case OMPD_parallel_for_simd:
6263 Res = ActOnOpenMPParallelForSimdDirective(
6264 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6265 break;
6266 case OMPD_scope:
6267 Res =
6268 ActOnOpenMPScopeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6269 break;
6270 case OMPD_parallel_master:
6271 Res = ActOnOpenMPParallelMasterDirective(Clauses: ClausesWithImplicit, AStmt,
6272 StartLoc, EndLoc);
6273 break;
6274 case OMPD_parallel_masked:
6275 Res = ActOnOpenMPParallelMaskedDirective(Clauses: ClausesWithImplicit, AStmt,
6276 StartLoc, EndLoc);
6277 break;
6278 case OMPD_parallel_sections:
6279 Res = ActOnOpenMPParallelSectionsDirective(Clauses: ClausesWithImplicit, AStmt,
6280 StartLoc, EndLoc);
6281 break;
6282 case OMPD_task:
6283 Res =
6284 ActOnOpenMPTaskDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6285 break;
6286 case OMPD_taskyield:
6287 assert(ClausesWithImplicit.empty() &&
6288 "No clauses are allowed for 'omp taskyield' directive");
6289 assert(AStmt == nullptr &&
6290 "No associated statement allowed for 'omp taskyield' directive");
6291 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6292 break;
6293 case OMPD_error:
6294 assert(AStmt == nullptr &&
6295 "No associated statement allowed for 'omp error' directive");
6296 Res = ActOnOpenMPErrorDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6297 break;
6298 case OMPD_barrier:
6299 assert(ClausesWithImplicit.empty() &&
6300 "No clauses are allowed for 'omp barrier' directive");
6301 assert(AStmt == nullptr &&
6302 "No associated statement allowed for 'omp barrier' directive");
6303 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6304 break;
6305 case OMPD_taskwait:
6306 assert(AStmt == nullptr &&
6307 "No associated statement allowed for 'omp taskwait' directive");
6308 Res = ActOnOpenMPTaskwaitDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6309 break;
6310 case OMPD_taskgroup:
6311 Res = ActOnOpenMPTaskgroupDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6312 EndLoc);
6313 break;
6314 case OMPD_flush:
6315 assert(AStmt == nullptr &&
6316 "No associated statement allowed for 'omp flush' directive");
6317 Res = ActOnOpenMPFlushDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6318 break;
6319 case OMPD_depobj:
6320 assert(AStmt == nullptr &&
6321 "No associated statement allowed for 'omp depobj' directive");
6322 Res = ActOnOpenMPDepobjDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6323 break;
6324 case OMPD_scan:
6325 assert(AStmt == nullptr &&
6326 "No associated statement allowed for 'omp scan' directive");
6327 Res = ActOnOpenMPScanDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6328 break;
6329 case OMPD_ordered:
6330 Res = ActOnOpenMPOrderedDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6331 EndLoc);
6332 break;
6333 case OMPD_atomic:
6334 Res = ActOnOpenMPAtomicDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6335 EndLoc);
6336 break;
6337 case OMPD_teams:
6338 Res =
6339 ActOnOpenMPTeamsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6340 break;
6341 case OMPD_target:
6342 Res = ActOnOpenMPTargetDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6343 EndLoc);
6344 break;
6345 case OMPD_target_parallel:
6346 Res = ActOnOpenMPTargetParallelDirective(Clauses: ClausesWithImplicit, AStmt,
6347 StartLoc, EndLoc);
6348 break;
6349 case OMPD_target_parallel_for:
6350 Res = ActOnOpenMPTargetParallelForDirective(
6351 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6352 break;
6353 case OMPD_cancellation_point:
6354 assert(ClausesWithImplicit.empty() &&
6355 "No clauses are allowed for 'omp cancellation point' directive");
6356 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6357 "cancellation point' directive");
6358 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6359 break;
6360 case OMPD_cancel:
6361 assert(AStmt == nullptr &&
6362 "No associated statement allowed for 'omp cancel' directive");
6363 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6364 CancelRegion);
6365 break;
6366 case OMPD_target_data:
6367 Res = ActOnOpenMPTargetDataDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6368 EndLoc);
6369 break;
6370 case OMPD_target_enter_data:
6371 Res = ActOnOpenMPTargetEnterDataDirective(Clauses: ClausesWithImplicit, StartLoc,
6372 EndLoc, AStmt);
6373 break;
6374 case OMPD_target_exit_data:
6375 Res = ActOnOpenMPTargetExitDataDirective(Clauses: ClausesWithImplicit, StartLoc,
6376 EndLoc, AStmt);
6377 break;
6378 case OMPD_taskloop:
6379 Res = ActOnOpenMPTaskLoopDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6380 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6381 break;
6382 case OMPD_taskloop_simd:
6383 Res = ActOnOpenMPTaskLoopSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6384 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6385 break;
6386 case OMPD_master_taskloop:
6387 Res = ActOnOpenMPMasterTaskLoopDirective(
6388 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6389 break;
6390 case OMPD_masked_taskloop:
6391 Res = ActOnOpenMPMaskedTaskLoopDirective(
6392 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6393 break;
6394 case OMPD_master_taskloop_simd:
6395 Res = ActOnOpenMPMasterTaskLoopSimdDirective(
6396 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6397 break;
6398 case OMPD_masked_taskloop_simd:
6399 Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
6400 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6401 break;
6402 case OMPD_parallel_master_taskloop:
6403 Res = ActOnOpenMPParallelMasterTaskLoopDirective(
6404 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6405 break;
6406 case OMPD_parallel_masked_taskloop:
6407 Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
6408 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6409 break;
6410 case OMPD_parallel_master_taskloop_simd:
6411 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6412 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6413 break;
6414 case OMPD_parallel_masked_taskloop_simd:
6415 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6416 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6417 break;
6418 case OMPD_distribute:
6419 Res = ActOnOpenMPDistributeDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6420 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6421 break;
6422 case OMPD_target_update:
6423 Res = ActOnOpenMPTargetUpdateDirective(Clauses: ClausesWithImplicit, StartLoc,
6424 EndLoc, AStmt);
6425 break;
6426 case OMPD_distribute_parallel_for:
6427 Res = ActOnOpenMPDistributeParallelForDirective(
6428 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6429 break;
6430 case OMPD_distribute_parallel_for_simd:
6431 Res = ActOnOpenMPDistributeParallelForSimdDirective(
6432 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6433 break;
6434 case OMPD_distribute_simd:
6435 Res = ActOnOpenMPDistributeSimdDirective(
6436 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6437 break;
6438 case OMPD_target_parallel_for_simd:
6439 Res = ActOnOpenMPTargetParallelForSimdDirective(
6440 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6441 break;
6442 case OMPD_target_simd:
6443 Res = ActOnOpenMPTargetSimdDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6444 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6445 break;
6446 case OMPD_teams_distribute:
6447 Res = ActOnOpenMPTeamsDistributeDirective(
6448 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6449 break;
6450 case OMPD_teams_distribute_simd:
6451 Res = ActOnOpenMPTeamsDistributeSimdDirective(
6452 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6453 break;
6454 case OMPD_teams_distribute_parallel_for_simd:
6455 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6456 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6457 break;
6458 case OMPD_teams_distribute_parallel_for:
6459 Res = ActOnOpenMPTeamsDistributeParallelForDirective(
6460 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6461 break;
6462 case OMPD_target_teams:
6463 Res = ActOnOpenMPTargetTeamsDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6464 EndLoc);
6465 break;
6466 case OMPD_target_teams_distribute:
6467 Res = ActOnOpenMPTargetTeamsDistributeDirective(
6468 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6469 break;
6470 case OMPD_target_teams_distribute_parallel_for:
6471 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6472 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6473 break;
6474 case OMPD_target_teams_distribute_parallel_for_simd:
6475 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6476 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6477 break;
6478 case OMPD_target_teams_distribute_simd:
6479 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
6480 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6481 break;
6482 case OMPD_interop:
6483 assert(AStmt == nullptr &&
6484 "No associated statement allowed for 'omp interop' directive");
6485 Res = ActOnOpenMPInteropDirective(Clauses: ClausesWithImplicit, StartLoc, EndLoc);
6486 break;
6487 case OMPD_dispatch:
6488 Res = ActOnOpenMPDispatchDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6489 EndLoc);
6490 break;
6491 case OMPD_loop:
6492 Res = ActOnOpenMPGenericLoopDirective(Clauses: ClausesWithImplicit, AStmt, StartLoc,
6493 EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6494 break;
6495 case OMPD_teams_loop:
6496 Res = ActOnOpenMPTeamsGenericLoopDirective(
6497 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6498 break;
6499 case OMPD_target_teams_loop:
6500 Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
6501 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6502 break;
6503 case OMPD_parallel_loop:
6504 Res = ActOnOpenMPParallelGenericLoopDirective(
6505 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6506 break;
6507 case OMPD_target_parallel_loop:
6508 Res = ActOnOpenMPTargetParallelGenericLoopDirective(
6509 Clauses: ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithImplicitDSA&: VarsWithInheritedDSA);
6510 break;
6511 case OMPD_declare_target:
6512 case OMPD_end_declare_target:
6513 case OMPD_threadprivate:
6514 case OMPD_allocate:
6515 case OMPD_declare_reduction:
6516 case OMPD_declare_mapper:
6517 case OMPD_declare_simd:
6518 case OMPD_requires:
6519 case OMPD_declare_variant:
6520 case OMPD_begin_declare_variant:
6521 case OMPD_end_declare_variant:
6522 llvm_unreachable("OpenMP Directive is not allowed");
6523 case OMPD_unknown:
6524 default:
6525 llvm_unreachable("Unknown OpenMP directive");
6526 }
6527
6528 ErrorFound = Res.isInvalid() || ErrorFound;
6529
6530 // Check variables in the clauses if default(none) or
6531 // default(firstprivate) was specified.
6532 if (DSAStack->getDefaultDSA() == DSA_none ||
6533 DSAStack->getDefaultDSA() == DSA_private ||
6534 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6535 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6536 for (OMPClause *C : Clauses) {
6537 switch (C->getClauseKind()) {
6538 case OMPC_num_threads:
6539 case OMPC_dist_schedule:
6540 // Do not analyze if no parent teams directive.
6541 if (isOpenMPTeamsDirective(Kind))
6542 break;
6543 continue;
6544 case OMPC_if:
6545 if (isOpenMPTeamsDirective(Kind) &&
6546 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6547 break;
6548 if (isOpenMPParallelDirective(Kind) &&
6549 isOpenMPTaskLoopDirective(Kind) &&
6550 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6551 break;
6552 continue;
6553 case OMPC_schedule:
6554 case OMPC_detach:
6555 break;
6556 case OMPC_grainsize:
6557 case OMPC_num_tasks:
6558 case OMPC_final:
6559 case OMPC_priority:
6560 case OMPC_novariants:
6561 case OMPC_nocontext:
6562 // Do not analyze if no parent parallel directive.
6563 if (isOpenMPParallelDirective(Kind))
6564 break;
6565 continue;
6566 case OMPC_ordered:
6567 case OMPC_device:
6568 case OMPC_num_teams:
6569 case OMPC_thread_limit:
6570 case OMPC_hint:
6571 case OMPC_collapse:
6572 case OMPC_safelen:
6573 case OMPC_simdlen:
6574 case OMPC_sizes:
6575 case OMPC_default:
6576 case OMPC_proc_bind:
6577 case OMPC_private:
6578 case OMPC_firstprivate:
6579 case OMPC_lastprivate:
6580 case OMPC_shared:
6581 case OMPC_reduction:
6582 case OMPC_task_reduction:
6583 case OMPC_in_reduction:
6584 case OMPC_linear:
6585 case OMPC_aligned:
6586 case OMPC_copyin:
6587 case OMPC_copyprivate:
6588 case OMPC_nowait:
6589 case OMPC_untied:
6590 case OMPC_mergeable:
6591 case OMPC_allocate:
6592 case OMPC_read:
6593 case OMPC_write:
6594 case OMPC_update:
6595 case OMPC_capture:
6596 case OMPC_compare:
6597 case OMPC_seq_cst:
6598 case OMPC_acq_rel:
6599 case OMPC_acquire:
6600 case OMPC_release:
6601 case OMPC_relaxed:
6602 case OMPC_depend:
6603 case OMPC_threads:
6604 case OMPC_simd:
6605 case OMPC_map:
6606 case OMPC_nogroup:
6607 case OMPC_defaultmap:
6608 case OMPC_to:
6609 case OMPC_from:
6610 case OMPC_use_device_ptr:
6611 case OMPC_use_device_addr:
6612 case OMPC_is_device_ptr:
6613 case OMPC_has_device_addr:
6614 case OMPC_nontemporal:
6615 case OMPC_order:
6616 case OMPC_destroy:
6617 case OMPC_inclusive:
6618 case OMPC_exclusive:
6619 case OMPC_uses_allocators:
6620 case OMPC_affinity:
6621 case OMPC_bind:
6622 case OMPC_filter:
6623 continue;
6624 case OMPC_allocator:
6625 case OMPC_flush:
6626 case OMPC_depobj:
6627 case OMPC_threadprivate:
6628 case OMPC_uniform:
6629 case OMPC_unknown:
6630 case OMPC_unified_address:
6631 case OMPC_unified_shared_memory:
6632 case OMPC_reverse_offload:
6633 case OMPC_dynamic_allocators:
6634 case OMPC_atomic_default_mem_order:
6635 case OMPC_self_maps:
6636 case OMPC_device_type:
6637 case OMPC_match:
6638 case OMPC_when:
6639 case OMPC_at:
6640 case OMPC_severity:
6641 case OMPC_message:
6642 default:
6643 llvm_unreachable("Unexpected clause");
6644 }
6645 for (Stmt *CC : C->children()) {
6646 if (CC)
6647 DSAChecker.Visit(CC);
6648 }
6649 }
6650 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6651 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6652 }
6653 for (const auto &P : VarsWithInheritedDSA) {
6654 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(Val: P.getFirst()))
6655 continue;
6656 ErrorFound = true;
6657 if (DSAStack->getDefaultDSA() == DSA_none ||
6658 DSAStack->getDefaultDSA() == DSA_private ||
6659 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6660 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6661 << P.first << P.second->getSourceRange();
6662 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6663 } else if (getLangOpts().OpenMP >= 50) {
6664 Diag(P.second->getExprLoc(),
6665 diag::err_omp_defaultmap_no_attr_for_variable)
6666 << P.first << P.second->getSourceRange();
6667 Diag(DSAStack->getDefaultDSALocation(),
6668 diag::note_omp_defaultmap_attr_none);
6669 }
6670 }
6671
6672 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6673 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6674 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6675 AllowedNameModifiers.push_back(D);
6676 }
6677 if (!AllowedNameModifiers.empty())
6678 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6679 ErrorFound;
6680
6681 if (ErrorFound)
6682 return StmtError();
6683
6684 if (!SemaRef.CurContext->isDependentContext() &&
6685 isOpenMPTargetExecutionDirective(Kind) &&
6686 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6687 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6688 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6689 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6690 // Register target to DSA Stack.
6691 DSAStack->addTargetDirLocation(LocStart: StartLoc);
6692 }
6693
6694 return Res;
6695}
6696
6697SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareSimdDirective(
6698 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6699 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6700 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6701 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6702 assert(Aligneds.size() == Alignments.size());
6703 assert(Linears.size() == LinModifiers.size());
6704 assert(Linears.size() == Steps.size());
6705 if (!DG || DG.get().isNull())
6706 return DeclGroupPtrTy();
6707
6708 const int SimdId = 0;
6709 if (!DG.get().isSingleDecl()) {
6710 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6711 << SimdId;
6712 return DG;
6713 }
6714 Decl *ADecl = DG.get().getSingleDecl();
6715 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: ADecl))
6716 ADecl = FTD->getTemplatedDecl();
6717
6718 auto *FD = dyn_cast<FunctionDecl>(Val: ADecl);
6719 if (!FD) {
6720 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6721 return DeclGroupPtrTy();
6722 }
6723
6724 // OpenMP [2.8.2, declare simd construct, Description]
6725 // The parameter of the simdlen clause must be a constant positive integer
6726 // expression.
6727 ExprResult SL;
6728 if (Simdlen)
6729 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6730 // OpenMP [2.8.2, declare simd construct, Description]
6731 // The special this pointer can be used as if was one of the arguments to the
6732 // function in any of the linear, aligned, or uniform clauses.
6733 // The uniform clause declares one or more arguments to have an invariant
6734 // value for all concurrent invocations of the function in the execution of a
6735 // single SIMD loop.
6736 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6737 const Expr *UniformedLinearThis = nullptr;
6738 for (const Expr *E : Uniforms) {
6739 E = E->IgnoreParenImpCasts();
6740 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
6741 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl()))
6742 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6743 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
6744 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6745 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6746 continue;
6747 }
6748 if (isa<CXXThisExpr>(Val: E)) {
6749 UniformedLinearThis = E;
6750 continue;
6751 }
6752 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6753 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6754 }
6755 // OpenMP [2.8.2, declare simd construct, Description]
6756 // The aligned clause declares that the object to which each list item points
6757 // is aligned to the number of bytes expressed in the optional parameter of
6758 // the aligned clause.
6759 // The special this pointer can be used as if was one of the arguments to the
6760 // function in any of the linear, aligned, or uniform clauses.
6761 // The type of list items appearing in the aligned clause must be array,
6762 // pointer, reference to array, or reference to pointer.
6763 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6764 const Expr *AlignedThis = nullptr;
6765 for (const Expr *E : Aligneds) {
6766 E = E->IgnoreParenImpCasts();
6767 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
6768 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
6769 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6770 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6771 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
6772 ->getCanonicalDecl() == CanonPVD) {
6773 // OpenMP [2.8.1, simd construct, Restrictions]
6774 // A list-item cannot appear in more than one aligned clause.
6775 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
6776 if (!Inserted) {
6777 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6778 << 1 << getOpenMPClauseNameForDiag(OMPC_aligned)
6779 << E->getSourceRange();
6780 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6781 << getOpenMPClauseNameForDiag(OMPC_aligned);
6782 continue;
6783 }
6784 QualType QTy = PVD->getType()
6785 .getNonReferenceType()
6786 .getUnqualifiedType()
6787 .getCanonicalType();
6788 const Type *Ty = QTy.getTypePtrOrNull();
6789 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6790 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6791 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6792 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6793 }
6794 continue;
6795 }
6796 }
6797 if (isa<CXXThisExpr>(Val: E)) {
6798 if (AlignedThis) {
6799 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6800 << 2 << getOpenMPClauseNameForDiag(OMPC_aligned)
6801 << E->getSourceRange();
6802 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6803 << getOpenMPClauseNameForDiag(OMPC_aligned);
6804 }
6805 AlignedThis = E;
6806 continue;
6807 }
6808 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6809 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6810 }
6811 // The optional parameter of the aligned clause, alignment, must be a constant
6812 // positive integer expression. If no optional parameter is specified,
6813 // implementation-defined default alignments for SIMD instructions on the
6814 // target platforms are assumed.
6815 SmallVector<const Expr *, 4> NewAligns;
6816 for (Expr *E : Alignments) {
6817 ExprResult Align;
6818 if (E)
6819 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
6820 NewAligns.push_back(Elt: Align.get());
6821 }
6822 // OpenMP [2.8.2, declare simd construct, Description]
6823 // The linear clause declares one or more list items to be private to a SIMD
6824 // lane and to have a linear relationship with respect to the iteration space
6825 // of a loop.
6826 // The special this pointer can be used as if was one of the arguments to the
6827 // function in any of the linear, aligned, or uniform clauses.
6828 // When a linear-step expression is specified in a linear clause it must be
6829 // either a constant integer expression or an integer-typed parameter that is
6830 // specified in a uniform clause on the directive.
6831 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6832 const bool IsUniformedThis = UniformedLinearThis != nullptr;
6833 auto MI = LinModifiers.begin();
6834 for (const Expr *E : Linears) {
6835 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
6836 ++MI;
6837 E = E->IgnoreParenImpCasts();
6838 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
6839 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
6840 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6841 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6842 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
6843 ->getCanonicalDecl() == CanonPVD) {
6844 // OpenMP [2.15.3.7, linear Clause, Restrictions]
6845 // A list-item cannot appear in more than one linear clause.
6846 if (auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
6847 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6848 << getOpenMPClauseNameForDiag(OMPC_linear)
6849 << getOpenMPClauseNameForDiag(OMPC_linear)
6850 << E->getSourceRange();
6851 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6852 << getOpenMPClauseNameForDiag(OMPC_linear);
6853 continue;
6854 }
6855 // Each argument can appear in at most one uniform or linear clause.
6856 if (auto It = UniformedArgs.find(CanonPVD);
6857 It != UniformedArgs.end()) {
6858 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6859 << getOpenMPClauseNameForDiag(OMPC_linear)
6860 << getOpenMPClauseNameForDiag(OMPC_uniform)
6861 << E->getSourceRange();
6862 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6863 << getOpenMPClauseNameForDiag(OMPC_uniform);
6864 continue;
6865 }
6866 LinearArgs[CanonPVD] = E;
6867 if (E->isValueDependent() || E->isTypeDependent() ||
6868 E->isInstantiationDependent() ||
6869 E->containsUnexpandedParameterPack())
6870 continue;
6871 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
6872 PVD->getOriginalType(),
6873 /*IsDeclareSimd=*/true);
6874 continue;
6875 }
6876 }
6877 if (isa<CXXThisExpr>(Val: E)) {
6878 if (UniformedLinearThis) {
6879 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6880 << getOpenMPClauseNameForDiag(OMPC_linear)
6881 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
6882 : OMPC_linear)
6883 << E->getSourceRange();
6884 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
6885 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
6886 : OMPC_linear);
6887 continue;
6888 }
6889 UniformedLinearThis = E;
6890 if (E->isValueDependent() || E->isTypeDependent() ||
6891 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
6892 continue;
6893 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, ELoc: E->getExprLoc(), LinKind,
6894 Type: E->getType(), /*IsDeclareSimd=*/true);
6895 continue;
6896 }
6897 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6898 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6899 }
6900 Expr *Step = nullptr;
6901 Expr *NewStep = nullptr;
6902 SmallVector<Expr *, 4> NewSteps;
6903 for (Expr *E : Steps) {
6904 // Skip the same step expression, it was checked already.
6905 if (Step == E || !E) {
6906 NewSteps.push_back(Elt: E ? NewStep : nullptr);
6907 continue;
6908 }
6909 Step = E;
6910 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: Step))
6911 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
6912 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6913 if (UniformedArgs.count(CanonPVD) == 0) {
6914 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
6915 << Step->getSourceRange();
6916 } else if (E->isValueDependent() || E->isTypeDependent() ||
6917 E->isInstantiationDependent() ||
6918 E->containsUnexpandedParameterPack() ||
6919 CanonPVD->getType()->hasIntegerRepresentation()) {
6920 NewSteps.push_back(Elt: Step);
6921 } else {
6922 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
6923 << Step->getSourceRange();
6924 }
6925 continue;
6926 }
6927 NewStep = Step;
6928 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
6929 !Step->isInstantiationDependent() &&
6930 !Step->containsUnexpandedParameterPack()) {
6931 NewStep = PerformOpenMPImplicitIntegerConversion(OpLoc: Step->getExprLoc(), Op: Step)
6932 .get();
6933 if (NewStep)
6934 NewStep = SemaRef
6935 .VerifyIntegerConstantExpression(
6936 E: NewStep, /*FIXME*/ CanFold: AllowFoldKind::Allow)
6937 .get();
6938 }
6939 NewSteps.push_back(Elt: NewStep);
6940 }
6941 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
6942 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
6943 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
6944 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
6945 const_cast<Expr **>(Linears.data()), Linears.size(),
6946 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
6947 NewSteps.data(), NewSteps.size(), SR);
6948 ADecl->addAttr(A: NewAttr);
6949 return DG;
6950}
6951
6952StmtResult SemaOpenMP::ActOnOpenMPInformationalDirective(
6953 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6954 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
6955 SourceLocation EndLoc) {
6956 assert(isOpenMPInformationalDirective(Kind) &&
6957 "Unexpected directive category");
6958
6959 StmtResult Res = StmtError();
6960
6961 switch (Kind) {
6962 case OMPD_assume:
6963 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
6964 break;
6965 default:
6966 llvm_unreachable("Unknown OpenMP directive");
6967 }
6968
6969 return Res;
6970}
6971
6972static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
6973 QualType NewType) {
6974 assert(NewType->isFunctionProtoType() &&
6975 "Expected function type with prototype.");
6976 assert(FD->getType()->isFunctionNoProtoType() &&
6977 "Expected function with type with no prototype.");
6978 assert(FDWithProto->getType()->isFunctionProtoType() &&
6979 "Expected function with prototype.");
6980 // Synthesize parameters with the same types.
6981 FD->setType(NewType);
6982 SmallVector<ParmVarDecl *, 16> Params;
6983 for (const ParmVarDecl *P : FDWithProto->parameters()) {
6984 auto *Param = ParmVarDecl::Create(C&: S.getASTContext(), DC: FD, StartLoc: SourceLocation(),
6985 IdLoc: SourceLocation(), Id: nullptr, T: P->getType(),
6986 /*TInfo=*/nullptr, S: SC_None, DefArg: nullptr);
6987 Param->setScopeInfo(0, Params.size());
6988 Param->setImplicit();
6989 Params.push_back(Elt: Param);
6990 }
6991
6992 FD->setParams(Params);
6993}
6994
6995void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
6996 if (D->isInvalidDecl())
6997 return;
6998 FunctionDecl *FD = nullptr;
6999 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(Val: D))
7000 FD = UTemplDecl->getTemplatedDecl();
7001 else
7002 FD = cast<FunctionDecl>(Val: D);
7003 assert(FD && "Expected a function declaration!");
7004
7005 // If we are instantiating templates we do *not* apply scoped assumptions but
7006 // only global ones. We apply scoped assumption to the template definition
7007 // though.
7008 if (!SemaRef.inTemplateInstantiation()) {
7009 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7010 FD->addAttr(AA);
7011 }
7012 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7013 FD->addAttr(AA);
7014}
7015
7016SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7017 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7018
7019void SemaOpenMP::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7020 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7021 SmallVectorImpl<FunctionDecl *> &Bases) {
7022 if (!D.getIdentifier())
7023 return;
7024
7025 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7026
7027 // Template specialization is an extension, check if we do it.
7028 bool IsTemplated = !TemplateParamLists.empty();
7029 if (IsTemplated &&
7030 !DVScope.TI->isExtensionActive(
7031 TP: llvm::omp::TraitProperty::implementation_extension_allow_templates))
7032 return;
7033
7034 const IdentifierInfo *BaseII = D.getIdentifier();
7035 LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(),
7036 Sema::LookupOrdinaryName);
7037 SemaRef.LookupParsedName(R&: Lookup, S, SS: &D.getCXXScopeSpec(),
7038 /*ObjectType=*/QualType());
7039
7040 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7041 QualType FType = TInfo->getType();
7042
7043 bool IsConstexpr =
7044 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7045 bool IsConsteval =
7046 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7047
7048 for (auto *Candidate : Lookup) {
7049 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7050 FunctionDecl *UDecl = nullptr;
7051 if (IsTemplated && isa<FunctionTemplateDecl>(Val: CandidateDecl)) {
7052 auto *FTD = cast<FunctionTemplateDecl>(Val: CandidateDecl);
7053 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7054 UDecl = FTD->getTemplatedDecl();
7055 } else if (!IsTemplated)
7056 UDecl = dyn_cast<FunctionDecl>(Val: CandidateDecl);
7057 if (!UDecl)
7058 continue;
7059
7060 // Don't specialize constexpr/consteval functions with
7061 // non-constexpr/consteval functions.
7062 if (UDecl->isConstexpr() && !IsConstexpr)
7063 continue;
7064 if (UDecl->isConsteval() && !IsConsteval)
7065 continue;
7066
7067 QualType UDeclTy = UDecl->getType();
7068 if (!UDeclTy->isDependentType()) {
7069 QualType NewType = getASTContext().mergeFunctionTypes(
7070 FType, UDeclTy, /*OfBlockPointer=*/false,
7071 /*Unqualified=*/false, /*AllowCXX=*/true);
7072 if (NewType.isNull())
7073 continue;
7074 }
7075
7076 // Found a base!
7077 Bases.push_back(Elt: UDecl);
7078 }
7079
7080 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7081 TP: llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7082 // If no base was found we create a declaration that we use as base.
7083 if (Bases.empty() && UseImplicitBase) {
7084 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7085 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParameterLists: TemplateParamLists);
7086 BaseD->setImplicit(true);
7087 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7088 Bases.push_back(Elt: BaseTemplD->getTemplatedDecl());
7089 else
7090 Bases.push_back(Elt: cast<FunctionDecl>(Val: BaseD));
7091 }
7092
7093 std::string MangledName;
7094 MangledName += D.getIdentifier()->getName();
7095 MangledName += getOpenMPVariantManglingSeparatorStr();
7096 MangledName += DVScope.NameSuffix;
7097 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7098
7099 VariantII.setMangledOpenMPVariantName(true);
7100 D.SetIdentifier(Id: &VariantII, IdLoc: D.getBeginLoc());
7101}
7102
7103void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7104 Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
7105 // Do not mark function as is used to prevent its emission if this is the
7106 // only place where it is used.
7107 EnterExpressionEvaluationContext Unevaluated(
7108 SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);
7109
7110 FunctionDecl *FD = nullptr;
7111 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(Val: D))
7112 FD = UTemplDecl->getTemplatedDecl();
7113 else
7114 FD = cast<FunctionDecl>(Val: D);
7115 auto *VariantFuncRef = DeclRefExpr::Create(
7116 getASTContext(), NestedNameSpecifierLoc(), SourceLocation(), FD,
7117 /*RefersToEnclosingVariableOrCapture=*/false,
7118 /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue);
7119
7120 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7121 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7122 getASTContext(), VariantFuncRef, DVScope.TI,
7123 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7124 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7125 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7126 for (FunctionDecl *BaseFD : Bases)
7127 BaseFD->addAttr(A: OMPDeclareVariantA);
7128}
7129
7130ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
7131 SourceLocation LParenLoc,
7132 MultiExprArg ArgExprs,
7133 SourceLocation RParenLoc,
7134 Expr *ExecConfig) {
7135 // The common case is a regular call we do not want to specialize at all. Try
7136 // to make that case fast by bailing early.
7137 CallExpr *CE = dyn_cast<CallExpr>(Val: Call.get());
7138 if (!CE)
7139 return Call;
7140
7141 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7142 if (!CalleeFnDecl)
7143 return Call;
7144
7145 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7146 CalleeFnDecl->getIdentifier() &&
7147 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7148 // checking for any calls inside an Order region
7149 if (Scope && Scope->isOpenMPOrderClauseScope())
7150 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7151 }
7152
7153 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7154 return Call;
7155
7156 ASTContext &Context = getASTContext();
7157 std::function<void(StringRef)> DiagUnknownTrait = [this,
7158 CE](StringRef ISATrait) {
7159 // TODO Track the selector locations in a way that is accessible here to
7160 // improve the diagnostic location.
7161 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7162 << ISATrait;
7163 };
7164 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7165 SemaRef.getCurFunctionDecl(),
7166 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7167
7168 QualType CalleeFnType = CalleeFnDecl->getType();
7169
7170 SmallVector<Expr *, 4> Exprs;
7171 SmallVector<VariantMatchInfo, 4> VMIs;
7172 while (CalleeFnDecl) {
7173 for (OMPDeclareVariantAttr *A :
7174 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7175 Expr *VariantRef = A->getVariantFuncRef();
7176
7177 VariantMatchInfo VMI;
7178 OMPTraitInfo &TI = A->getTraitInfo();
7179 TI.getAsVariantMatchInfo(Context, VMI);
7180 if (!isVariantApplicableInContext(VMI, OMPCtx,
7181 /*DeviceSetOnly=*/false))
7182 continue;
7183
7184 VMIs.push_back(VMI);
7185 Exprs.push_back(VariantRef);
7186 }
7187
7188 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7189 }
7190
7191 ExprResult NewCall;
7192 do {
7193 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7194 if (BestIdx < 0)
7195 return Call;
7196 Expr *BestExpr = cast<DeclRefExpr>(Val: Exprs[BestIdx]);
7197 Decl *BestDecl = cast<DeclRefExpr>(Val: BestExpr)->getDecl();
7198
7199 {
7200 // Try to build a (member) call expression for the current best applicable
7201 // variant expression. We allow this to fail in which case we continue
7202 // with the next best variant expression. The fail case is part of the
7203 // implementation defined behavior in the OpenMP standard when it talks
7204 // about what differences in the function prototypes: "Any differences
7205 // that the specific OpenMP context requires in the prototype of the
7206 // variant from the base function prototype are implementation defined."
7207 // This wording is there to allow the specialized variant to have a
7208 // different type than the base function. This is intended and OK but if
7209 // we cannot create a call the difference is not in the "implementation
7210 // defined range" we allow.
7211 Sema::TentativeAnalysisScope Trap(SemaRef);
7212
7213 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7214 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(Val: CE);
7215 BestExpr = MemberExpr::CreateImplicit(
7216 C: Context, Base: MemberCall->getImplicitObjectArgument(),
7217 /*IsArrow=*/false, MemberDecl: SpecializedMethod, T: Context.BoundMemberTy,
7218 VK: MemberCall->getValueKind(), OK: MemberCall->getObjectKind());
7219 }
7220 NewCall = SemaRef.BuildCallExpr(S: Scope, Fn: BestExpr, LParenLoc, ArgExprs,
7221 RParenLoc, ExecConfig);
7222 if (NewCall.isUsable()) {
7223 if (CallExpr *NCE = dyn_cast<CallExpr>(Val: NewCall.get())) {
7224 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7225 QualType NewType = getASTContext().mergeFunctionTypes(
7226 CalleeFnType, NewCalleeFnDecl->getType(),
7227 /*OfBlockPointer=*/false,
7228 /*Unqualified=*/false, /*AllowCXX=*/true);
7229 if (!NewType.isNull())
7230 break;
7231 // Don't use the call if the function type was not compatible.
7232 NewCall = nullptr;
7233 }
7234 }
7235 }
7236
7237 VMIs.erase(CI: VMIs.begin() + BestIdx);
7238 Exprs.erase(CI: Exprs.begin() + BestIdx);
7239 } while (!VMIs.empty());
7240
7241 if (!NewCall.isUsable())
7242 return Call;
7243 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7244}
7245
7246std::optional<std::pair<FunctionDecl *, Expr *>>
7247SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG,
7248 Expr *VariantRef,
7249 OMPTraitInfo &TI,
7250 unsigned NumAppendArgs,
7251 SourceRange SR) {
7252 ASTContext &Context = getASTContext();
7253 if (!DG || DG.get().isNull())
7254 return std::nullopt;
7255
7256 const int VariantId = 1;
7257 // Must be applied only to single decl.
7258 if (!DG.get().isSingleDecl()) {
7259 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7260 << VariantId << SR;
7261 return std::nullopt;
7262 }
7263 Decl *ADecl = DG.get().getSingleDecl();
7264 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: ADecl))
7265 ADecl = FTD->getTemplatedDecl();
7266
7267 // Decl must be a function.
7268 auto *FD = dyn_cast<FunctionDecl>(Val: ADecl);
7269 if (!FD) {
7270 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7271 << VariantId << SR;
7272 return std::nullopt;
7273 }
7274
7275 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7276 // The 'target' attribute needs to be separately checked because it does
7277 // not always signify a multiversion function declaration.
7278 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7279 };
7280 // OpenMP is not compatible with multiversion function attributes.
7281 if (HasMultiVersionAttributes(FD)) {
7282 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7283 << SR;
7284 return std::nullopt;
7285 }
7286
7287 // Allow #pragma omp declare variant only if the function is not used.
7288 if (FD->isUsed(false))
7289 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7290 << FD->getLocation();
7291
7292 // Check if the function was emitted already.
7293 const FunctionDecl *Definition;
7294 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7295 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7296 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7297 << FD->getLocation();
7298
7299 // The VariantRef must point to function.
7300 if (!VariantRef) {
7301 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7302 return std::nullopt;
7303 }
7304
7305 auto ShouldDelayChecks = [](Expr *&E, bool) {
7306 return E && (E->isTypeDependent() || E->isValueDependent() ||
7307 E->containsUnexpandedParameterPack() ||
7308 E->isInstantiationDependent());
7309 };
7310 // Do not check templates, wait until instantiation.
7311 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7312 TI.anyScoreOrCondition(Cond: ShouldDelayChecks))
7313 return std::make_pair(x&: FD, y&: VariantRef);
7314
7315 // Deal with non-constant score and user condition expressions.
7316 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7317 bool IsScore) -> bool {
7318 if (!E || E->isIntegerConstantExpr(Ctx: getASTContext()))
7319 return false;
7320
7321 if (IsScore) {
7322 // We warn on non-constant scores and pretend they were not present.
7323 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7324 << E;
7325 E = nullptr;
7326 } else {
7327 // We could replace a non-constant user condition with "false" but we
7328 // will soon need to handle these anyway for the dynamic version of
7329 // OpenMP context selectors.
7330 Diag(E->getExprLoc(),
7331 diag::err_omp_declare_variant_user_condition_not_constant)
7332 << E;
7333 }
7334 return true;
7335 };
7336 if (TI.anyScoreOrCondition(Cond: HandleNonConstantScoresAndConditions))
7337 return std::nullopt;
7338
7339 QualType AdjustedFnType = FD->getType();
7340 if (NumAppendArgs) {
7341 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7342 if (!PTy) {
7343 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7344 << SR;
7345 return std::nullopt;
7346 }
7347 // Adjust the function type to account for an extra omp_interop_t for each
7348 // specified in the append_args clause.
7349 const TypeDecl *TD = nullptr;
7350 LookupResult Result(SemaRef, &Context.Idents.get(Name: "omp_interop_t"),
7351 SR.getBegin(), Sema::LookupOrdinaryName);
7352 if (SemaRef.LookupName(R&: Result, S: SemaRef.getCurScope())) {
7353 NamedDecl *ND = Result.getFoundDecl();
7354 TD = dyn_cast_or_null<TypeDecl>(Val: ND);
7355 }
7356 if (!TD) {
7357 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7358 return std::nullopt;
7359 }
7360 QualType InteropType = Context.getTypeDeclType(Decl: TD);
7361 if (PTy->isVariadic()) {
7362 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7363 return std::nullopt;
7364 }
7365 llvm::SmallVector<QualType, 8> Params;
7366 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7367 Params.insert(I: Params.end(), NumToInsert: NumAppendArgs, Elt: InteropType);
7368 AdjustedFnType = Context.getFunctionType(ResultTy: PTy->getReturnType(), Args: Params,
7369 EPI: PTy->getExtProtoInfo());
7370 }
7371
7372 // Convert VariantRef expression to the type of the original function to
7373 // resolve possible conflicts.
7374 ExprResult VariantRefCast = VariantRef;
7375 if (getLangOpts().CPlusPlus) {
7376 QualType FnPtrType;
7377 auto *Method = dyn_cast<CXXMethodDecl>(Val: FD);
7378 if (Method && !Method->isStatic()) {
7379 FnPtrType = Context.getMemberPointerType(
7380 T: AdjustedFnType, /*Qualifier=*/nullptr, Cls: Method->getParent());
7381 ExprResult ER;
7382 {
7383 // Build addr_of unary op to correctly handle type checks for member
7384 // functions.
7385 Sema::TentativeAnalysisScope Trap(SemaRef);
7386 ER = SemaRef.CreateBuiltinUnaryOp(OpLoc: VariantRef->getBeginLoc(), Opc: UO_AddrOf,
7387 InputExpr: VariantRef);
7388 }
7389 if (!ER.isUsable()) {
7390 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7391 << VariantId << VariantRef->getSourceRange();
7392 return std::nullopt;
7393 }
7394 VariantRef = ER.get();
7395 } else {
7396 FnPtrType = Context.getPointerType(T: AdjustedFnType);
7397 }
7398 QualType VarianPtrType = Context.getPointerType(T: VariantRef->getType());
7399 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7400 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7401 From: VariantRef, ToType: FnPtrType.getUnqualifiedType(),
7402 /*SuppressUserConversions=*/false, AllowExplicit: Sema::AllowedExplicit::None,
7403 /*InOverloadResolution=*/false,
7404 /*CStyle=*/false,
7405 /*AllowObjCWritebackConversion=*/false);
7406 if (ICS.isFailure()) {
7407 Diag(VariantRef->getExprLoc(),
7408 diag::err_omp_declare_variant_incompat_types)
7409 << VariantRef->getType()
7410 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7411 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7412 return std::nullopt;
7413 }
7414 VariantRefCast = SemaRef.PerformImplicitConversion(
7415 From: VariantRef, ToType: FnPtrType.getUnqualifiedType(),
7416 Action: AssignmentAction::Converting);
7417 if (!VariantRefCast.isUsable())
7418 return std::nullopt;
7419 }
7420 // Drop previously built artificial addr_of unary op for member functions.
7421 if (Method && !Method->isStatic()) {
7422 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7423 if (auto *UO = dyn_cast<UnaryOperator>(
7424 Val: PossibleAddrOfVariantRef->IgnoreImplicit()))
7425 VariantRefCast = UO->getSubExpr();
7426 }
7427 }
7428
7429 ExprResult ER = SemaRef.CheckPlaceholderExpr(E: VariantRefCast.get());
7430 if (!ER.isUsable() ||
7431 !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7432 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7433 << VariantId << VariantRef->getSourceRange();
7434 return std::nullopt;
7435 }
7436
7437 // The VariantRef must point to function.
7438 auto *DRE = dyn_cast<DeclRefExpr>(Val: ER.get()->IgnoreParenImpCasts());
7439 if (!DRE) {
7440 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7441 << VariantId << VariantRef->getSourceRange();
7442 return std::nullopt;
7443 }
7444 auto *NewFD = dyn_cast_or_null<FunctionDecl>(Val: DRE->getDecl());
7445 if (!NewFD) {
7446 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7447 << VariantId << VariantRef->getSourceRange();
7448 return std::nullopt;
7449 }
7450
7451 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7452 Diag(VariantRef->getExprLoc(),
7453 diag::err_omp_declare_variant_same_base_function)
7454 << VariantRef->getSourceRange();
7455 return std::nullopt;
7456 }
7457
7458 // Check if function types are compatible in C.
7459 if (!getLangOpts().CPlusPlus) {
7460 QualType NewType =
7461 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7462 if (NewType.isNull()) {
7463 Diag(VariantRef->getExprLoc(),
7464 diag::err_omp_declare_variant_incompat_types)
7465 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7466 << VariantRef->getSourceRange();
7467 return std::nullopt;
7468 }
7469 if (NewType->isFunctionProtoType()) {
7470 if (FD->getType()->isFunctionNoProtoType())
7471 setPrototype(S&: SemaRef, FD, FDWithProto: NewFD, NewType);
7472 else if (NewFD->getType()->isFunctionNoProtoType())
7473 setPrototype(S&: SemaRef, FD: NewFD, FDWithProto: FD, NewType);
7474 }
7475 }
7476
7477 // Check if variant function is not marked with declare variant directive.
7478 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7479 Diag(VariantRef->getExprLoc(),
7480 diag::warn_omp_declare_variant_marked_as_declare_variant)
7481 << VariantRef->getSourceRange();
7482 SourceRange SR =
7483 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7484 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7485 return std::nullopt;
7486 }
7487
7488 enum DoesntSupport {
7489 VirtFuncs = 1,
7490 Constructors = 3,
7491 Destructors = 4,
7492 DeletedFuncs = 5,
7493 DefaultedFuncs = 6,
7494 ConstexprFuncs = 7,
7495 ConstevalFuncs = 8,
7496 };
7497 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(Val: FD)) {
7498 if (CXXFD->isVirtual()) {
7499 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7500 << VirtFuncs;
7501 return std::nullopt;
7502 }
7503
7504 if (isa<CXXConstructorDecl>(Val: FD)) {
7505 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7506 << Constructors;
7507 return std::nullopt;
7508 }
7509
7510 if (isa<CXXDestructorDecl>(Val: FD)) {
7511 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7512 << Destructors;
7513 return std::nullopt;
7514 }
7515 }
7516
7517 if (FD->isDeleted()) {
7518 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7519 << DeletedFuncs;
7520 return std::nullopt;
7521 }
7522
7523 if (FD->isDefaulted()) {
7524 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7525 << DefaultedFuncs;
7526 return std::nullopt;
7527 }
7528
7529 if (FD->isConstexpr()) {
7530 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7531 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7532 return std::nullopt;
7533 }
7534
7535 // Check general compatibility.
7536 if (SemaRef.areMultiversionVariantFunctionsCompatible(
7537 FD, NewFD, PartialDiagnostic::NullDiagnostic(),
7538 PartialDiagnosticAt(SourceLocation(),
7539 PartialDiagnostic::NullDiagnostic()),
7540 PartialDiagnosticAt(
7541 VariantRef->getExprLoc(),
7542 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7543 PartialDiagnosticAt(VariantRef->getExprLoc(),
7544 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7545 << FD->getLocation()),
7546 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7547 /*CLinkageMayDiffer=*/true))
7548 return std::nullopt;
7549 return std::make_pair(x&: FD, y: cast<Expr>(Val: DRE));
7550}
7551
7552void SemaOpenMP::ActOnOpenMPDeclareVariantDirective(
7553 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7554 ArrayRef<Expr *> AdjustArgsNothing,
7555 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7556 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7557 SourceLocation AppendArgsLoc, SourceRange SR) {
7558
7559 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7560 // An adjust_args clause or append_args clause can only be specified if the
7561 // dispatch selector of the construct selector set appears in the match
7562 // clause.
7563
7564 SmallVector<Expr *, 8> AllAdjustArgs;
7565 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNothing);
7566 llvm::append_range(C&: AllAdjustArgs, R&: AdjustArgsNeedDevicePtr);
7567
7568 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7569 VariantMatchInfo VMI;
7570 TI.getAsVariantMatchInfo(ASTCtx&: getASTContext(), VMI);
7571 if (!llvm::is_contained(
7572 Range&: VMI.ConstructTraits,
7573 Element: llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7574 if (!AllAdjustArgs.empty())
7575 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7576 << getOpenMPClauseNameForDiag(OMPC_adjust_args);
7577 if (!AppendArgs.empty())
7578 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7579 << getOpenMPClauseNameForDiag(OMPC_append_args);
7580 return;
7581 }
7582 }
7583
7584 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7585 // Each argument can only appear in a single adjust_args clause for each
7586 // declare variant directive.
7587 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
7588
7589 for (Expr *E : AllAdjustArgs) {
7590 E = E->IgnoreParenImpCasts();
7591 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E)) {
7592 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: DRE->getDecl())) {
7593 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7594 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7595 FD->getParamDecl(i: PVD->getFunctionScopeIndex())
7596 ->getCanonicalDecl() == CanonPVD) {
7597 // It's a parameter of the function, check duplicates.
7598 if (!AdjustVars.insert(Ptr: CanonPVD).second) {
7599 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7600 << PVD;
7601 return;
7602 }
7603 continue;
7604 }
7605 }
7606 }
7607 // Anything that is not a function parameter is an error.
7608 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7609 return;
7610 }
7611
7612 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7613 getASTContext(), VariantRef, &TI,
7614 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7615 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7616 AdjustArgsNeedDevicePtr.size(),
7617 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7618 FD->addAttr(A: NewAttr);
7619}
7620
7621static CapturedStmt *
7622setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt) {
7623 auto *CS = dyn_cast<CapturedStmt>(Val: AStmt);
7624 assert(CS && "Captured statement expected");
7625 // 1.2.2 OpenMP Language Terminology
7626 // Structured block - An executable statement with a single entry at the
7627 // top and a single exit at the bottom.
7628 // The point of exit cannot be a branch out of the structured block.
7629 // longjmp() and throw() must not violate the entry/exit criteria.
7630 CS->getCapturedDecl()->setNothrow();
7631
7632 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7633 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7634 CS = cast<CapturedStmt>(Val: CS->getCapturedStmt());
7635 // 1.2.2 OpenMP Language Terminology
7636 // Structured block - An executable statement with a single entry at the
7637 // top and a single exit at the bottom.
7638 // The point of exit cannot be a branch out of the structured block.
7639 // longjmp() and throw() must not violate the entry/exit criteria.
7640 CS->getCapturedDecl()->setNothrow();
7641 }
7642 SemaRef.setFunctionHasBranchProtectedScope();
7643 return CS;
7644}
7645
7646StmtResult
7647SemaOpenMP::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
7648 Stmt *AStmt, SourceLocation StartLoc,
7649 SourceLocation EndLoc) {
7650 if (!AStmt)
7651 return StmtError();
7652
7653 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7654
7655 return OMPParallelDirective::Create(
7656 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
7657 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7658}
7659
7660namespace {
7661/// Iteration space of a single for loop.
7662struct LoopIterationSpace final {
7663 /// True if the condition operator is the strict compare operator (<, > or
7664 /// !=).
7665 bool IsStrictCompare = false;
7666 /// Condition of the loop.
7667 Expr *PreCond = nullptr;
7668 /// This expression calculates the number of iterations in the loop.
7669 /// It is always possible to calculate it before starting the loop.
7670 Expr *NumIterations = nullptr;
7671 /// The loop counter variable.
7672 Expr *CounterVar = nullptr;
7673 /// Private loop counter variable.
7674 Expr *PrivateCounterVar = nullptr;
7675 /// This is initializer for the initial value of #CounterVar.
7676 Expr *CounterInit = nullptr;
7677 /// This is step for the #CounterVar used to generate its update:
7678 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7679 Expr *CounterStep = nullptr;
7680 /// Should step be subtracted?
7681 bool Subtract = false;
7682 /// Source range of the loop init.
7683 SourceRange InitSrcRange;
7684 /// Source range of the loop condition.
7685 SourceRange CondSrcRange;
7686 /// Source range of the loop increment.
7687 SourceRange IncSrcRange;
7688 /// Minimum value that can have the loop control variable. Used to support
7689 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7690 /// since only such variables can be used in non-loop invariant expressions.
7691 Expr *MinValue = nullptr;
7692 /// Maximum value that can have the loop control variable. Used to support
7693 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7694 /// since only such variables can be used in non-loop invariant expressions.
7695 Expr *MaxValue = nullptr;
7696 /// true, if the lower bound depends on the outer loop control var.
7697 bool IsNonRectangularLB = false;
7698 /// true, if the upper bound depends on the outer loop control var.
7699 bool IsNonRectangularUB = false;
7700 /// Index of the loop this loop depends on and forms non-rectangular loop
7701 /// nest.
7702 unsigned LoopDependentIdx = 0;
7703 /// Final condition for the non-rectangular loop nest support. It is used to
7704 /// check that the number of iterations for this particular counter must be
7705 /// finished.
7706 Expr *FinalCondition = nullptr;
7707};
7708
7709/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
7710/// set are referenced. Used for verifying loop nest structure before
7711/// performing a loop collapse operation.
7712class ForSubExprChecker : public DynamicRecursiveASTVisitor {
7713 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7714 VarDecl *ForbiddenVar = nullptr;
7715 SourceRange ErrLoc;
7716
7717public:
7718 explicit ForSubExprChecker(
7719 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7720 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7721 // We want to visit implicit code, i.e. synthetic initialisation statements
7722 // created during range-for lowering.
7723 ShouldVisitImplicitCode = true;
7724 }
7725
7726 bool VisitDeclRefExpr(DeclRefExpr *E) override {
7727 ValueDecl *VD = E->getDecl();
7728 if (!isa<VarDecl, BindingDecl>(Val: VD))
7729 return true;
7730 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
7731 if (V->getType()->isReferenceType()) {
7732 VarDecl *VD = V->getDefinition();
7733 if (VD->hasInit()) {
7734 Expr *I = VD->getInit();
7735 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Val: I);
7736 if (!DRE)
7737 return true;
7738 V = DRE->getDecl()->getPotentiallyDecomposedVarDecl();
7739 }
7740 }
7741 Decl *Canon = V->getCanonicalDecl();
7742 if (CollapsedLoopVarDecls.contains(Ptr: Canon)) {
7743 ForbiddenVar = V;
7744 ErrLoc = E->getSourceRange();
7745 return false;
7746 }
7747
7748 return true;
7749 }
7750
7751 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
7752 SourceRange getErrRange() const { return ErrLoc; }
7753};
7754
7755/// Helper class for checking canonical form of the OpenMP loops and
7756/// extracting iteration space of each loop in the loop nest, that will be used
7757/// for IR generation.
7758class OpenMPIterationSpaceChecker {
7759 /// Reference to Sema.
7760 Sema &SemaRef;
7761 /// Does the loop associated directive support non-rectangular loops?
7762 bool SupportsNonRectangular;
7763 /// Data-sharing stack.
7764 DSAStackTy &Stack;
7765 /// A location for diagnostics (when there is no some better location).
7766 SourceLocation DefaultLoc;
7767 /// A location for diagnostics (when increment is not compatible).
7768 SourceLocation ConditionLoc;
7769 /// The set of variables declared within the (to be collapsed) loop nest.
7770 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7771 /// A source location for referring to loop init later.
7772 SourceRange InitSrcRange;
7773 /// A source location for referring to condition later.
7774 SourceRange ConditionSrcRange;
7775 /// A source location for referring to increment later.
7776 SourceRange IncrementSrcRange;
7777 /// Loop variable.
7778 ValueDecl *LCDecl = nullptr;
7779 /// Reference to loop variable.
7780 Expr *LCRef = nullptr;
7781 /// Lower bound (initializer for the var).
7782 Expr *LB = nullptr;
7783 /// Upper bound.
7784 Expr *UB = nullptr;
7785 /// Loop step (increment).
7786 Expr *Step = nullptr;
7787 /// This flag is true when condition is one of:
7788 /// Var < UB
7789 /// Var <= UB
7790 /// UB > Var
7791 /// UB >= Var
7792 /// This will have no value when the condition is !=
7793 std::optional<bool> TestIsLessOp;
7794 /// This flag is true when condition is strict ( < or > ).
7795 bool TestIsStrictOp = false;
7796 /// This flag is true when step is subtracted on each iteration.
7797 bool SubtractStep = false;
7798 /// The outer loop counter this loop depends on (if any).
7799 const ValueDecl *DepDecl = nullptr;
7800 /// Contains number of loop (starts from 1) on which loop counter init
7801 /// expression of this loop depends on.
7802 std::optional<unsigned> InitDependOnLC;
7803 /// Contains number of loop (starts from 1) on which loop counter condition
7804 /// expression of this loop depends on.
7805 std::optional<unsigned> CondDependOnLC;
7806 /// Checks if the provide statement depends on the loop counter.
7807 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
7808 bool IsInitializer);
7809 /// Original condition required for checking of the exit condition for
7810 /// non-rectangular loop.
7811 Expr *Condition = nullptr;
7812
7813public:
7814 OpenMPIterationSpaceChecker(
7815 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
7816 SourceLocation DefaultLoc,
7817 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
7818 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7819 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
7820 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
7821 /// Check init-expr for canonical loop form and save loop counter
7822 /// variable - #Var and its initialization value - #LB.
7823 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7824 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7825 /// for less/greater and for strict/non-strict comparison.
7826 bool checkAndSetCond(Expr *S);
7827 /// Check incr-expr for canonical loop form and return true if it
7828 /// does not conform, otherwise save loop step (#Step).
7829 bool checkAndSetInc(Expr *S);
7830 /// Return the loop counter variable.
7831 ValueDecl *getLoopDecl() const { return LCDecl; }
7832 /// Return the reference expression to loop counter variable.
7833 Expr *getLoopDeclRefExpr() const { return LCRef; }
7834 /// Source range of the loop init.
7835 SourceRange getInitSrcRange() const { return InitSrcRange; }
7836 /// Source range of the loop condition.
7837 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7838 /// Source range of the loop increment.
7839 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
7840 /// True if the step should be subtracted.
7841 bool shouldSubtractStep() const { return SubtractStep; }
7842 /// True, if the compare operator is strict (<, > or !=).
7843 bool isStrictTestOp() const { return TestIsStrictOp; }
7844 /// Build the expression to calculate the number of iterations.
7845 Expr *buildNumIterations(
7846 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
7847 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7848 /// Build the precondition expression for the loops.
7849 Expr *
7850 buildPreCond(Scope *S, Expr *Cond,
7851 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7852 /// Build reference expression to the counter be used for codegen.
7853 DeclRefExpr *
7854 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7855 DSAStackTy &DSA) const;
7856 /// Build reference expression to the private counter be used for
7857 /// codegen.
7858 Expr *buildPrivateCounterVar() const;
7859 /// Build initialization of the counter be used for codegen.
7860 Expr *buildCounterInit() const;
7861 /// Build step of the counter be used for codegen.
7862 Expr *buildCounterStep() const;
7863 /// Build loop data with counter value for depend clauses in ordered
7864 /// directives.
7865 Expr *
7866 buildOrderedLoopData(Scope *S, Expr *Counter,
7867 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7868 SourceLocation Loc, Expr *Inc = nullptr,
7869 OverloadedOperatorKind OOK = OO_Amp);
7870 /// Builds the minimum value for the loop counter.
7871 std::pair<Expr *, Expr *> buildMinMaxValues(
7872 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7873 /// Builds final condition for the non-rectangular loops.
7874 Expr *buildFinalCondition(Scope *S) const;
7875 /// Return true if any expression is dependent.
7876 bool dependent() const;
7877 /// Returns true if the initializer forms non-rectangular loop.
7878 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
7879 /// Returns true if the condition forms non-rectangular loop.
7880 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
7881 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
7882 unsigned getLoopDependentIdx() const {
7883 return InitDependOnLC.value_or(u: CondDependOnLC.value_or(u: 0));
7884 }
7885
7886private:
7887 /// Check the right-hand side of an assignment in the increment
7888 /// expression.
7889 bool checkAndSetIncRHS(Expr *RHS);
7890 /// Helper to set loop counter variable and its initializer.
7891 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
7892 bool EmitDiags);
7893 /// Helper to set upper bound.
7894 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
7895 SourceRange SR, SourceLocation SL);
7896 /// Helper to set loop increment.
7897 bool setStep(Expr *NewStep, bool Subtract);
7898};
7899
7900bool OpenMPIterationSpaceChecker::dependent() const {
7901 if (!LCDecl) {
7902 assert(!LB && !UB && !Step);
7903 return false;
7904 }
7905 return LCDecl->getType()->isDependentType() ||
7906 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
7907 (Step && Step->isValueDependent());
7908}
7909
7910bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
7911 Expr *NewLCRefExpr,
7912 Expr *NewLB, bool EmitDiags) {
7913 // State consistency checking to ensure correct usage.
7914 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
7915 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7916 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
7917 return true;
7918 LCDecl = getCanonicalDecl(D: NewLCDecl);
7919 LCRef = NewLCRefExpr;
7920 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(Val: NewLB))
7921 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
7922 if ((Ctor->isCopyOrMoveConstructor() ||
7923 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
7924 CE->getNumArgs() > 0 && CE->getArg(Arg: 0) != nullptr)
7925 NewLB = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
7926 LB = NewLB;
7927 if (EmitDiags)
7928 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
7929 return false;
7930}
7931
7932bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
7933 bool StrictOp, SourceRange SR,
7934 SourceLocation SL) {
7935 // State consistency checking to ensure correct usage.
7936 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
7937 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7938 if (!NewUB || NewUB->containsErrors())
7939 return true;
7940 UB = NewUB;
7941 if (LessOp)
7942 TestIsLessOp = LessOp;
7943 TestIsStrictOp = StrictOp;
7944 ConditionSrcRange = SR;
7945 ConditionLoc = SL;
7946 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
7947 return false;
7948}
7949
7950bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
7951 // State consistency checking to ensure correct usage.
7952 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
7953 if (!NewStep || NewStep->containsErrors())
7954 return true;
7955 if (!NewStep->isValueDependent()) {
7956 // Check that the step is integer expression.
7957 SourceLocation StepLoc = NewStep->getBeginLoc();
7958 ExprResult Val = SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(
7959 OpLoc: StepLoc, Op: getExprAsWritten(E: NewStep));
7960 if (Val.isInvalid())
7961 return true;
7962 NewStep = Val.get();
7963
7964 // OpenMP [2.6, Canonical Loop Form, Restrictions]
7965 // If test-expr is of form var relational-op b and relational-op is < or
7966 // <= then incr-expr must cause var to increase on each iteration of the
7967 // loop. If test-expr is of form var relational-op b and relational-op is
7968 // > or >= then incr-expr must cause var to decrease on each iteration of
7969 // the loop.
7970 // If test-expr is of form b relational-op var and relational-op is < or
7971 // <= then incr-expr must cause var to decrease on each iteration of the
7972 // loop. If test-expr is of form b relational-op var and relational-op is
7973 // > or >= then incr-expr must cause var to increase on each iteration of
7974 // the loop.
7975 std::optional<llvm::APSInt> Result =
7976 NewStep->getIntegerConstantExpr(Ctx: SemaRef.Context);
7977 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
7978 bool IsConstNeg =
7979 Result && Result->isSigned() && (Subtract != Result->isNegative());
7980 bool IsConstPos =
7981 Result && Result->isSigned() && (Subtract == Result->isNegative());
7982 bool IsConstZero = Result && !Result->getBoolValue();
7983
7984 // != with increment is treated as <; != with decrement is treated as >
7985 if (!TestIsLessOp)
7986 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7987 if (UB && (IsConstZero ||
7988 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
7989 : (IsConstPos || (IsUnsigned && !Subtract))))) {
7990 SemaRef.Diag(NewStep->getExprLoc(),
7991 diag::err_omp_loop_incr_not_compatible)
7992 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
7993 SemaRef.Diag(ConditionLoc,
7994 diag::note_omp_loop_cond_requires_compatible_incr)
7995 << *TestIsLessOp << ConditionSrcRange;
7996 return true;
7997 }
7998 if (*TestIsLessOp == Subtract) {
7999 NewStep =
8000 SemaRef.CreateBuiltinUnaryOp(OpLoc: NewStep->getExprLoc(), Opc: UO_Minus, InputExpr: NewStep)
8001 .get();
8002 Subtract = !Subtract;
8003 }
8004 }
8005
8006 Step = NewStep;
8007 SubtractStep = Subtract;
8008 return false;
8009}
8010
8011namespace {
8012/// Checker for the non-rectangular loops. Checks if the initializer or
8013/// condition expression references loop counter variable.
8014class LoopCounterRefChecker final
8015 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8016 Sema &SemaRef;
8017 DSAStackTy &Stack;
8018 const ValueDecl *CurLCDecl = nullptr;
8019 const ValueDecl *DepDecl = nullptr;
8020 const ValueDecl *PrevDepDecl = nullptr;
8021 bool IsInitializer = true;
8022 bool SupportsNonRectangular;
8023 unsigned BaseLoopId = 0;
8024 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8025 if (getCanonicalDecl(D: VD) == getCanonicalDecl(D: CurLCDecl)) {
8026 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8027 << (IsInitializer ? 0 : 1);
8028 return false;
8029 }
8030 const auto &&Data = Stack.isLoopControlVariable(D: VD);
8031 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8032 // The type of the loop iterator on which we depend may not have a random
8033 // access iterator type.
8034 if (Data.first && VD->getType()->isRecordType()) {
8035 SmallString<128> Name;
8036 llvm::raw_svector_ostream OS(Name);
8037 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8038 /*Qualified=*/true);
8039 SemaRef.Diag(E->getExprLoc(),
8040 diag::err_omp_wrong_dependency_iterator_type)
8041 << OS.str();
8042 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8043 return false;
8044 }
8045 if (Data.first && !SupportsNonRectangular) {
8046 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8047 return false;
8048 }
8049 if (Data.first &&
8050 (DepDecl || (PrevDepDecl &&
8051 getCanonicalDecl(D: VD) != getCanonicalDecl(D: PrevDepDecl)))) {
8052 if (!DepDecl && PrevDepDecl)
8053 DepDecl = PrevDepDecl;
8054 SmallString<128> Name;
8055 llvm::raw_svector_ostream OS(Name);
8056 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8057 /*Qualified=*/true);
8058 SemaRef.Diag(E->getExprLoc(),
8059 diag::err_omp_invariant_or_linear_dependency)
8060 << OS.str();
8061 return false;
8062 }
8063 if (Data.first) {
8064 DepDecl = VD;
8065 BaseLoopId = Data.first;
8066 }
8067 return Data.first;
8068 }
8069
8070public:
8071 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8072 const ValueDecl *VD = E->getDecl();
8073 if (isa<VarDecl>(Val: VD))
8074 return checkDecl(E, VD);
8075 return false;
8076 }
8077 bool VisitMemberExpr(const MemberExpr *E) {
8078 if (isa<CXXThisExpr>(Val: E->getBase()->IgnoreParens())) {
8079 const ValueDecl *VD = E->getMemberDecl();
8080 if (isa<VarDecl>(Val: VD) || isa<FieldDecl>(Val: VD))
8081 return checkDecl(E, VD);
8082 }
8083 return false;
8084 }
8085 bool VisitStmt(const Stmt *S) {
8086 bool Res = false;
8087 for (const Stmt *Child : S->children())
8088 Res = (Child && Visit(Child)) || Res;
8089 return Res;
8090 }
8091 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8092 const ValueDecl *CurLCDecl, bool IsInitializer,
8093 const ValueDecl *PrevDepDecl = nullptr,
8094 bool SupportsNonRectangular = true)
8095 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8096 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8097 SupportsNonRectangular(SupportsNonRectangular) {}
8098 unsigned getBaseLoopId() const {
8099 assert(CurLCDecl && "Expected loop dependency.");
8100 return BaseLoopId;
8101 }
8102 const ValueDecl *getDepDecl() const {
8103 assert(CurLCDecl && "Expected loop dependency.");
8104 return DepDecl;
8105 }
8106};
8107} // namespace
8108
8109std::optional<unsigned>
8110OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8111 bool IsInitializer) {
8112 // Check for the non-rectangular loops.
8113 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8114 DepDecl, SupportsNonRectangular);
8115 if (LoopStmtChecker.Visit(S)) {
8116 DepDecl = LoopStmtChecker.getDepDecl();
8117 return LoopStmtChecker.getBaseLoopId();
8118 }
8119 return std::nullopt;
8120}
8121
8122bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8123 // Check init-expr for canonical loop form and save loop counter
8124 // variable - #Var and its initialization value - #LB.
8125 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8126 // var = lb
8127 // integer-type var = lb
8128 // random-access-iterator-type var = lb
8129 // pointer-type var = lb
8130 //
8131 if (!S) {
8132 if (EmitDiags) {
8133 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8134 }
8135 return true;
8136 }
8137 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: S))
8138 if (!ExprTemp->cleanupsHaveSideEffects())
8139 S = ExprTemp->getSubExpr();
8140
8141 if (!CollapsedLoopVarDecls.empty()) {
8142 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8143 if (!FSEC.TraverseStmt(S)) {
8144 SourceRange Range = FSEC.getErrRange();
8145 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8146 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8147 return true;
8148 }
8149 }
8150
8151 InitSrcRange = S->getSourceRange();
8152 if (Expr *E = dyn_cast<Expr>(Val: S))
8153 S = E->IgnoreParens();
8154 if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8155 if (BO->getOpcode() == BO_Assign) {
8156 Expr *LHS = BO->getLHS()->IgnoreParens();
8157 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS)) {
8158 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(Val: DRE->getDecl()))
8159 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8160 return setLCDeclAndLB(NewLCDecl: ME->getMemberDecl(), NewLCRefExpr: ME, NewLB: BO->getRHS(),
8161 EmitDiags);
8162 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8163 }
8164 if (auto *ME = dyn_cast<MemberExpr>(Val: LHS)) {
8165 if (ME->isArrow() &&
8166 isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
8167 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8168 EmitDiags);
8169 }
8170 }
8171 } else if (auto *DS = dyn_cast<DeclStmt>(Val: S)) {
8172 if (DS->isSingleDecl()) {
8173 if (auto *Var = dyn_cast_or_null<VarDecl>(Val: DS->getSingleDecl())) {
8174 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8175 // Accept non-canonical init form here but emit ext. warning.
8176 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8177 SemaRef.Diag(S->getBeginLoc(),
8178 diag::ext_omp_loop_not_canonical_init)
8179 << S->getSourceRange();
8180 return setLCDeclAndLB(
8181 NewLCDecl: Var,
8182 NewLCRefExpr: buildDeclRefExpr(SemaRef, Var,
8183 Var->getType().getNonReferenceType(),
8184 DS->getBeginLoc()),
8185 NewLB: Var->getInit(), EmitDiags);
8186 }
8187 }
8188 }
8189 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8190 if (CE->getOperator() == OO_Equal) {
8191 Expr *LHS = CE->getArg(0);
8192 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8193 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8194 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8195 return setLCDeclAndLB(NewLCDecl: ME->getMemberDecl(), NewLCRefExpr: ME, NewLB: BO->getRHS(),
8196 EmitDiags);
8197 return setLCDeclAndLB(NewLCDecl: DRE->getDecl(), NewLCRefExpr: DRE, NewLB: CE->getArg(1), EmitDiags);
8198 }
8199 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8200 if (ME->isArrow() &&
8201 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8202 return setLCDeclAndLB(NewLCDecl: ME->getMemberDecl(), NewLCRefExpr: ME, NewLB: BO->getRHS(),
8203 EmitDiags);
8204 }
8205 }
8206 }
8207
8208 if (dependent() || SemaRef.CurContext->isDependentContext())
8209 return false;
8210 if (EmitDiags) {
8211 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8212 << S->getSourceRange();
8213 }
8214 return true;
8215}
8216
8217/// Ignore parenthesizes, implicit casts, copy constructor and return the
8218/// variable (which may be the loop variable) if possible.
8219static const ValueDecl *getInitLCDecl(const Expr *E) {
8220 if (!E)
8221 return nullptr;
8222 E = getExprAsWritten(E);
8223 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(Val: E))
8224 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8225 if ((Ctor->isCopyOrMoveConstructor() ||
8226 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8227 CE->getNumArgs() > 0 && CE->getArg(Arg: 0) != nullptr)
8228 E = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
8229 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(Val: E)) {
8230 if (const auto *VD = dyn_cast<VarDecl>(Val: DRE->getDecl()))
8231 return getCanonicalDecl(VD);
8232 }
8233 if (const auto *ME = dyn_cast_or_null<MemberExpr>(Val: E))
8234 if (ME->isArrow() && isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
8235 return getCanonicalDecl(D: ME->getMemberDecl());
8236 return nullptr;
8237}
8238
8239bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8240 // Check test-expr for canonical form, save upper-bound UB, flags for
8241 // less/greater and for strict/non-strict comparison.
8242 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8243 // var relational-op b
8244 // b relational-op var
8245 //
8246 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8247 if (!S) {
8248 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8249 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8250 return true;
8251 }
8252 Condition = S;
8253 S = getExprAsWritten(E: S);
8254
8255 if (!CollapsedLoopVarDecls.empty()) {
8256 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8257 if (!FSEC.TraverseStmt(S)) {
8258 SourceRange Range = FSEC.getErrRange();
8259 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8260 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8261 return true;
8262 }
8263 }
8264
8265 SourceLocation CondLoc = S->getBeginLoc();
8266 auto &&CheckAndSetCond =
8267 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8268 const Expr *RHS, SourceRange SR,
8269 SourceLocation OpLoc) -> std::optional<bool> {
8270 if (BinaryOperator::isRelationalOp(Opc: Opcode)) {
8271 if (getInitLCDecl(E: LHS) == LCDecl)
8272 return setUB(NewUB: const_cast<Expr *>(RHS),
8273 LessOp: (Opcode == BO_LT || Opcode == BO_LE),
8274 StrictOp: (Opcode == BO_LT || Opcode == BO_GT), SR, SL: OpLoc);
8275 if (getInitLCDecl(E: RHS) == LCDecl)
8276 return setUB(NewUB: const_cast<Expr *>(LHS),
8277 LessOp: (Opcode == BO_GT || Opcode == BO_GE),
8278 StrictOp: (Opcode == BO_LT || Opcode == BO_GT), SR, SL: OpLoc);
8279 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8280 return setUB(NewUB: const_cast<Expr *>(getInitLCDecl(E: LHS) == LCDecl ? RHS : LHS),
8281 /*LessOp=*/std::nullopt,
8282 /*StrictOp=*/true, SR, SL: OpLoc);
8283 }
8284 return std::nullopt;
8285 };
8286 std::optional<bool> Res;
8287 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(Val: S)) {
8288 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8289 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8290 RBO->getOperatorLoc());
8291 } else if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8292 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8293 BO->getSourceRange(), BO->getOperatorLoc());
8294 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8295 if (CE->getNumArgs() == 2) {
8296 Res = CheckAndSetCond(
8297 BinaryOperator::getOverloadedOpcode(OO: CE->getOperator()), CE->getArg(0),
8298 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8299 }
8300 }
8301 if (Res)
8302 return *Res;
8303 if (dependent() || SemaRef.CurContext->isDependentContext())
8304 return false;
8305 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8306 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8307 return true;
8308}
8309
8310bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8311 // RHS of canonical loop form increment can be:
8312 // var + incr
8313 // incr + var
8314 // var - incr
8315 //
8316 RHS = RHS->IgnoreParenImpCasts();
8317 if (auto *BO = dyn_cast<BinaryOperator>(Val: RHS)) {
8318 if (BO->isAdditiveOp()) {
8319 bool IsAdd = BO->getOpcode() == BO_Add;
8320 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8321 return setStep(NewStep: BO->getRHS(), Subtract: !IsAdd);
8322 if (IsAdd && getInitLCDecl(E: BO->getRHS()) == LCDecl)
8323 return setStep(NewStep: BO->getLHS(), /*Subtract=*/false);
8324 }
8325 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: RHS)) {
8326 bool IsAdd = CE->getOperator() == OO_Plus;
8327 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8328 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8329 return setStep(NewStep: CE->getArg(1), Subtract: !IsAdd);
8330 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8331 return setStep(NewStep: CE->getArg(0), /*Subtract=*/false);
8332 }
8333 }
8334 if (dependent() || SemaRef.CurContext->isDependentContext())
8335 return false;
8336 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8337 << RHS->getSourceRange() << LCDecl;
8338 return true;
8339}
8340
8341bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8342 // Check incr-expr for canonical loop form and return true if it
8343 // does not conform.
8344 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8345 // ++var
8346 // var++
8347 // --var
8348 // var--
8349 // var += incr
8350 // var -= incr
8351 // var = var + incr
8352 // var = incr + var
8353 // var = var - incr
8354 //
8355 if (!S) {
8356 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8357 return true;
8358 }
8359 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: S))
8360 if (!ExprTemp->cleanupsHaveSideEffects())
8361 S = ExprTemp->getSubExpr();
8362
8363 if (!CollapsedLoopVarDecls.empty()) {
8364 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8365 if (!FSEC.TraverseStmt(S)) {
8366 SourceRange Range = FSEC.getErrRange();
8367 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8368 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8369 return true;
8370 }
8371 }
8372
8373 IncrementSrcRange = S->getSourceRange();
8374 S = S->IgnoreParens();
8375 if (auto *UO = dyn_cast<UnaryOperator>(Val: S)) {
8376 if (UO->isIncrementDecrementOp() &&
8377 getInitLCDecl(E: UO->getSubExpr()) == LCDecl)
8378 return setStep(NewStep: SemaRef
8379 .ActOnIntegerConstant(Loc: UO->getBeginLoc(),
8380 Val: (UO->isDecrementOp() ? -1 : 1))
8381 .get(),
8382 /*Subtract=*/false);
8383 } else if (auto *BO = dyn_cast<BinaryOperator>(Val: S)) {
8384 switch (BO->getOpcode()) {
8385 case BO_AddAssign:
8386 case BO_SubAssign:
8387 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8388 return setStep(NewStep: BO->getRHS(), Subtract: BO->getOpcode() == BO_SubAssign);
8389 break;
8390 case BO_Assign:
8391 if (getInitLCDecl(E: BO->getLHS()) == LCDecl)
8392 return checkAndSetIncRHS(RHS: BO->getRHS());
8393 break;
8394 default:
8395 break;
8396 }
8397 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: S)) {
8398 switch (CE->getOperator()) {
8399 case OO_PlusPlus:
8400 case OO_MinusMinus:
8401 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8402 return setStep(NewStep: SemaRef
8403 .ActOnIntegerConstant(
8404 Loc: CE->getBeginLoc(),
8405 Val: ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8406 .get(),
8407 /*Subtract=*/false);
8408 break;
8409 case OO_PlusEqual:
8410 case OO_MinusEqual:
8411 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8412 return setStep(NewStep: CE->getArg(1), Subtract: CE->getOperator() == OO_MinusEqual);
8413 break;
8414 case OO_Equal:
8415 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8416 return checkAndSetIncRHS(RHS: CE->getArg(1));
8417 break;
8418 default:
8419 break;
8420 }
8421 }
8422 if (dependent() || SemaRef.CurContext->isDependentContext())
8423 return false;
8424 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8425 << S->getSourceRange() << LCDecl;
8426 return true;
8427}
8428
8429static ExprResult
8430tryBuildCapture(Sema &SemaRef, Expr *Capture,
8431 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8432 StringRef Name = ".capture_expr.") {
8433 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8434 return Capture;
8435 if (Capture->isEvaluatable(Ctx: SemaRef.Context, AllowSideEffects: Expr::SE_AllowSideEffects))
8436 return SemaRef.PerformImplicitConversion(From: Capture->IgnoreImpCasts(),
8437 ToType: Capture->getType(),
8438 Action: AssignmentAction::Converting,
8439 /*AllowExplicit=*/true);
8440 auto I = Captures.find(Key: Capture);
8441 if (I != Captures.end())
8442 return buildCapture(S&: SemaRef, CaptureExpr: Capture, Ref&: I->second, Name);
8443 DeclRefExpr *Ref = nullptr;
8444 ExprResult Res = buildCapture(S&: SemaRef, CaptureExpr: Capture, Ref, Name);
8445 Captures[Capture] = Ref;
8446 return Res;
8447}
8448
8449/// Calculate number of iterations, transforming to unsigned, if number of
8450/// iterations may be larger than the original type.
8451static Expr *
8452calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8453 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8454 bool TestIsStrictOp, bool RoundToStep,
8455 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8456 ExprResult NewStep = tryBuildCapture(SemaRef, Capture: Step, Captures, Name: ".new_step");
8457 if (!NewStep.isUsable())
8458 return nullptr;
8459 llvm::APSInt LRes, SRes;
8460 bool IsLowerConst = false, IsStepConst = false;
8461 if (std::optional<llvm::APSInt> Res =
8462 Lower->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8463 LRes = *Res;
8464 IsLowerConst = true;
8465 }
8466 if (std::optional<llvm::APSInt> Res =
8467 Step->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8468 SRes = *Res;
8469 IsStepConst = true;
8470 }
8471 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8472 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8473 (TestIsStrictOp && LRes.isStrictlyPositive()));
8474 bool NeedToReorganize = false;
8475 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8476 if (!NoNeedToConvert && IsLowerConst &&
8477 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8478 NoNeedToConvert = true;
8479 if (RoundToStep) {
8480 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8481 ? LRes.getBitWidth()
8482 : SRes.getBitWidth();
8483 LRes = LRes.extend(width: BW + 1);
8484 LRes.setIsSigned(true);
8485 SRes = SRes.extend(width: BW + 1);
8486 SRes.setIsSigned(true);
8487 LRes -= SRes;
8488 NoNeedToConvert = LRes.trunc(width: BW).extend(width: BW + 1) == LRes;
8489 LRes = LRes.trunc(width: BW);
8490 }
8491 if (TestIsStrictOp) {
8492 unsigned BW = LRes.getBitWidth();
8493 LRes = LRes.extend(width: BW + 1);
8494 LRes.setIsSigned(true);
8495 ++LRes;
8496 NoNeedToConvert =
8497 NoNeedToConvert && LRes.trunc(width: BW).extend(width: BW + 1) == LRes;
8498 // truncate to the original bitwidth.
8499 LRes = LRes.trunc(width: BW);
8500 }
8501 NeedToReorganize = NoNeedToConvert;
8502 }
8503 llvm::APSInt URes;
8504 bool IsUpperConst = false;
8505 if (std::optional<llvm::APSInt> Res =
8506 Upper->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
8507 URes = *Res;
8508 IsUpperConst = true;
8509 }
8510 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8511 (!RoundToStep || IsStepConst)) {
8512 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8513 : URes.getBitWidth();
8514 LRes = LRes.extend(width: BW + 1);
8515 LRes.setIsSigned(true);
8516 URes = URes.extend(width: BW + 1);
8517 URes.setIsSigned(true);
8518 URes -= LRes;
8519 NoNeedToConvert = URes.trunc(width: BW).extend(width: BW + 1) == URes;
8520 NeedToReorganize = NoNeedToConvert;
8521 }
8522 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8523 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8524 // unsigned.
8525 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8526 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8527 QualType LowerTy = Lower->getType();
8528 QualType UpperTy = Upper->getType();
8529 uint64_t LowerSize = SemaRef.Context.getTypeSize(T: LowerTy);
8530 uint64_t UpperSize = SemaRef.Context.getTypeSize(T: UpperTy);
8531 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8532 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8533 QualType CastType = SemaRef.Context.getIntTypeForBitwidth(
8534 DestWidth: LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8535 Upper =
8536 SemaRef
8537 .PerformImplicitConversion(
8538 From: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Upper).get(),
8539 ToType: CastType, Action: AssignmentAction::Converting)
8540 .get();
8541 Lower = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Lower).get();
8542 NewStep = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: NewStep.get());
8543 }
8544 }
8545 if (!Lower || !Upper || NewStep.isInvalid())
8546 return nullptr;
8547
8548 ExprResult Diff;
8549 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8550 // 1]).
8551 if (NeedToReorganize) {
8552 Diff = Lower;
8553
8554 if (RoundToStep) {
8555 // Lower - Step
8556 Diff =
8557 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8558 if (!Diff.isUsable())
8559 return nullptr;
8560 }
8561
8562 // Lower - Step [+ 1]
8563 if (TestIsStrictOp)
8564 Diff = SemaRef.BuildBinOp(
8565 S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(),
8566 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
8567 if (!Diff.isUsable())
8568 return nullptr;
8569
8570 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
8571 if (!Diff.isUsable())
8572 return nullptr;
8573
8574 // Upper - (Lower - Step [+ 1]).
8575 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Diff.get());
8576 if (!Diff.isUsable())
8577 return nullptr;
8578 } else {
8579 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Upper, RHSExpr: Lower);
8580
8581 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8582 // BuildBinOp already emitted error, this one is to point user to upper
8583 // and lower bound, and to tell what is passed to 'operator-'.
8584 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8585 << Upper->getSourceRange() << Lower->getSourceRange();
8586 return nullptr;
8587 }
8588
8589 if (!Diff.isUsable())
8590 return nullptr;
8591
8592 // Upper - Lower [- 1]
8593 if (TestIsStrictOp)
8594 Diff = SemaRef.BuildBinOp(
8595 S, OpLoc: DefaultLoc, Opc: BO_Sub, LHSExpr: Diff.get(),
8596 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
8597 if (!Diff.isUsable())
8598 return nullptr;
8599
8600 if (RoundToStep) {
8601 // Upper - Lower [- 1] + Step
8602 Diff =
8603 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Add, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8604 if (!Diff.isUsable())
8605 return nullptr;
8606 }
8607 }
8608
8609 // Parentheses (for dumping/debugging purposes only).
8610 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
8611 if (!Diff.isUsable())
8612 return nullptr;
8613
8614 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8615 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Div, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8616 if (!Diff.isUsable())
8617 return nullptr;
8618
8619 return Diff.get();
8620}
8621
8622/// Build the expression to calculate the number of iterations.
8623Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8624 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8625 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8626 QualType VarType = LCDecl->getType().getNonReferenceType();
8627 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8628 !SemaRef.getLangOpts().CPlusPlus)
8629 return nullptr;
8630 Expr *LBVal = LB;
8631 Expr *UBVal = UB;
8632 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8633 // max(LB(MinVal), LB(MaxVal)))
8634 if (InitDependOnLC) {
8635 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8636 if (!IS.MinValue || !IS.MaxValue)
8637 return nullptr;
8638 // OuterVar = Min
8639 ExprResult MinValue =
8640 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MinValue);
8641 if (!MinValue.isUsable())
8642 return nullptr;
8643
8644 ExprResult LBMinVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
8645 LHSExpr: IS.CounterVar, RHSExpr: MinValue.get());
8646 if (!LBMinVal.isUsable())
8647 return nullptr;
8648 // OuterVar = Min, LBVal
8649 LBMinVal =
8650 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: LBMinVal.get(), RHSExpr: LBVal);
8651 if (!LBMinVal.isUsable())
8652 return nullptr;
8653 // (OuterVar = Min, LBVal)
8654 LBMinVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: LBMinVal.get());
8655 if (!LBMinVal.isUsable())
8656 return nullptr;
8657
8658 // OuterVar = Max
8659 ExprResult MaxValue =
8660 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MaxValue);
8661 if (!MaxValue.isUsable())
8662 return nullptr;
8663
8664 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
8665 LHSExpr: IS.CounterVar, RHSExpr: MaxValue.get());
8666 if (!LBMaxVal.isUsable())
8667 return nullptr;
8668 // OuterVar = Max, LBVal
8669 LBMaxVal =
8670 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: LBMaxVal.get(), RHSExpr: LBVal);
8671 if (!LBMaxVal.isUsable())
8672 return nullptr;
8673 // (OuterVar = Max, LBVal)
8674 LBMaxVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: LBMaxVal.get());
8675 if (!LBMaxVal.isUsable())
8676 return nullptr;
8677
8678 Expr *LBMin =
8679 tryBuildCapture(SemaRef, Capture: LBMinVal.get(), Captures, Name: ".lb_min").get();
8680 Expr *LBMax =
8681 tryBuildCapture(SemaRef, Capture: LBMaxVal.get(), Captures, Name: ".lb_max").get();
8682 if (!LBMin || !LBMax)
8683 return nullptr;
8684 // LB(MinVal) < LB(MaxVal)
8685 ExprResult MinLessMaxRes =
8686 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_LT, LHSExpr: LBMin, RHSExpr: LBMax);
8687 if (!MinLessMaxRes.isUsable())
8688 return nullptr;
8689 Expr *MinLessMax =
8690 tryBuildCapture(SemaRef, Capture: MinLessMaxRes.get(), Captures, Name: ".min_less_max")
8691 .get();
8692 if (!MinLessMax)
8693 return nullptr;
8694 if (*TestIsLessOp) {
8695 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8696 // LB(MaxVal))
8697 ExprResult MinLB = SemaRef.ActOnConditionalOp(QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc,
8698 CondExpr: MinLessMax, LHSExpr: LBMin, RHSExpr: LBMax);
8699 if (!MinLB.isUsable())
8700 return nullptr;
8701 LBVal = MinLB.get();
8702 } else {
8703 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8704 // LB(MaxVal))
8705 ExprResult MaxLB = SemaRef.ActOnConditionalOp(QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc,
8706 CondExpr: MinLessMax, LHSExpr: LBMax, RHSExpr: LBMin);
8707 if (!MaxLB.isUsable())
8708 return nullptr;
8709 LBVal = MaxLB.get();
8710 }
8711 // OuterVar = LB
8712 LBMinVal =
8713 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign, LHSExpr: IS.CounterVar, RHSExpr: LBVal);
8714 if (!LBMinVal.isUsable())
8715 return nullptr;
8716 LBVal = LBMinVal.get();
8717 }
8718 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8719 // min(UB(MinVal), UB(MaxVal))
8720 if (CondDependOnLC) {
8721 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8722 if (!IS.MinValue || !IS.MaxValue)
8723 return nullptr;
8724 // OuterVar = Min
8725 ExprResult MinValue =
8726 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MinValue);
8727 if (!MinValue.isUsable())
8728 return nullptr;
8729
8730 ExprResult UBMinVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
8731 LHSExpr: IS.CounterVar, RHSExpr: MinValue.get());
8732 if (!UBMinVal.isUsable())
8733 return nullptr;
8734 // OuterVar = Min, UBVal
8735 UBMinVal =
8736 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: UBMinVal.get(), RHSExpr: UBVal);
8737 if (!UBMinVal.isUsable())
8738 return nullptr;
8739 // (OuterVar = Min, UBVal)
8740 UBMinVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: UBMinVal.get());
8741 if (!UBMinVal.isUsable())
8742 return nullptr;
8743
8744 // OuterVar = Max
8745 ExprResult MaxValue =
8746 SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: IS.MaxValue);
8747 if (!MaxValue.isUsable())
8748 return nullptr;
8749
8750 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Assign,
8751 LHSExpr: IS.CounterVar, RHSExpr: MaxValue.get());
8752 if (!UBMaxVal.isUsable())
8753 return nullptr;
8754 // OuterVar = Max, UBVal
8755 UBMaxVal =
8756 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Comma, LHSExpr: UBMaxVal.get(), RHSExpr: UBVal);
8757 if (!UBMaxVal.isUsable())
8758 return nullptr;
8759 // (OuterVar = Max, UBVal)
8760 UBMaxVal = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: UBMaxVal.get());
8761 if (!UBMaxVal.isUsable())
8762 return nullptr;
8763
8764 Expr *UBMin =
8765 tryBuildCapture(SemaRef, Capture: UBMinVal.get(), Captures, Name: ".ub_min").get();
8766 Expr *UBMax =
8767 tryBuildCapture(SemaRef, Capture: UBMaxVal.get(), Captures, Name: ".ub_max").get();
8768 if (!UBMin || !UBMax)
8769 return nullptr;
8770 // UB(MinVal) > UB(MaxVal)
8771 ExprResult MinGreaterMaxRes =
8772 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_GT, LHSExpr: UBMin, RHSExpr: UBMax);
8773 if (!MinGreaterMaxRes.isUsable())
8774 return nullptr;
8775 Expr *MinGreaterMax = tryBuildCapture(SemaRef, Capture: MinGreaterMaxRes.get(),
8776 Captures, Name: ".min_greater_max")
8777 .get();
8778 if (!MinGreaterMax)
8779 return nullptr;
8780 if (*TestIsLessOp) {
8781 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8782 // UB(MaxVal))
8783 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8784 QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc, CondExpr: MinGreaterMax, LHSExpr: UBMin, RHSExpr: UBMax);
8785 if (!MaxUB.isUsable())
8786 return nullptr;
8787 UBVal = MaxUB.get();
8788 } else {
8789 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8790 // UB(MaxVal))
8791 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8792 QuestionLoc: DefaultLoc, ColonLoc: DefaultLoc, CondExpr: MinGreaterMax, LHSExpr: UBMax, RHSExpr: UBMin);
8793 if (!MinUB.isUsable())
8794 return nullptr;
8795 UBVal = MinUB.get();
8796 }
8797 }
8798 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8799 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8800 Expr *Upper = tryBuildCapture(SemaRef, Capture: UBExpr, Captures, Name: ".upper").get();
8801 Expr *Lower = tryBuildCapture(SemaRef, Capture: LBExpr, Captures, Name: ".lower").get();
8802 if (!Upper || !Lower)
8803 return nullptr;
8804
8805 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8806 Step, LCTy: VarType, TestIsStrictOp,
8807 /*RoundToStep=*/true, Captures);
8808 if (!Diff.isUsable())
8809 return nullptr;
8810
8811 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8812 QualType Type = Diff.get()->getType();
8813 ASTContext &C = SemaRef.Context;
8814 bool UseVarType = VarType->hasIntegerRepresentation() &&
8815 C.getTypeSize(T: Type) > C.getTypeSize(T: VarType);
8816 if (!Type->isIntegerType() || UseVarType) {
8817 unsigned NewSize =
8818 UseVarType ? C.getTypeSize(T: VarType) : C.getTypeSize(T: Type);
8819 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8820 : Type->hasSignedIntegerRepresentation();
8821 Type = C.getIntTypeForBitwidth(DestWidth: NewSize, Signed: IsSigned);
8822 if (!SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: Type)) {
8823 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: Type,
8824 Action: AssignmentAction::Converting,
8825 /*AllowExplicit=*/true);
8826 if (!Diff.isUsable())
8827 return nullptr;
8828 }
8829 }
8830 if (LimitedType) {
8831 unsigned NewSize = (C.getTypeSize(T: Type) > 32) ? 64 : 32;
8832 if (NewSize != C.getTypeSize(T: Type)) {
8833 if (NewSize < C.getTypeSize(T: Type)) {
8834 assert(NewSize == 64 && "incorrect loop var size");
8835 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8836 << InitSrcRange << ConditionSrcRange;
8837 }
8838 QualType NewType = C.getIntTypeForBitwidth(
8839 DestWidth: NewSize, Signed: Type->hasSignedIntegerRepresentation() ||
8840 C.getTypeSize(T: Type) < NewSize);
8841 if (!SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: NewType)) {
8842 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: NewType,
8843 Action: AssignmentAction::Converting,
8844 /*AllowExplicit=*/true);
8845 if (!Diff.isUsable())
8846 return nullptr;
8847 }
8848 }
8849 }
8850
8851 return Diff.get();
8852}
8853
8854std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8855 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8856 // Do not build for iterators, they cannot be used in non-rectangular loop
8857 // nests.
8858 if (LCDecl->getType()->isRecordType())
8859 return std::make_pair(x: nullptr, y: nullptr);
8860 // If we subtract, the min is in the condition, otherwise the min is in the
8861 // init value.
8862 Expr *MinExpr = nullptr;
8863 Expr *MaxExpr = nullptr;
8864 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8865 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8866 bool LBNonRect =
8867 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8868 bool UBNonRect =
8869 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8870 Expr *Lower =
8871 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, Capture: LBExpr, Captures).get();
8872 Expr *Upper =
8873 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, Capture: UBExpr, Captures).get();
8874 if (!Upper || !Lower)
8875 return std::make_pair(x: nullptr, y: nullptr);
8876
8877 if (*TestIsLessOp)
8878 MinExpr = Lower;
8879 else
8880 MaxExpr = Upper;
8881
8882 // Build minimum/maximum value based on number of iterations.
8883 QualType VarType = LCDecl->getType().getNonReferenceType();
8884
8885 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8886 Step, LCTy: VarType, TestIsStrictOp,
8887 /*RoundToStep=*/false, Captures);
8888 if (!Diff.isUsable())
8889 return std::make_pair(x: nullptr, y: nullptr);
8890
8891 // ((Upper - Lower [- 1]) / Step) * Step
8892 // Parentheses (for dumping/debugging purposes only).
8893 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
8894 if (!Diff.isUsable())
8895 return std::make_pair(x: nullptr, y: nullptr);
8896
8897 ExprResult NewStep = tryBuildCapture(SemaRef, Capture: Step, Captures, Name: ".new_step");
8898 if (!NewStep.isUsable())
8899 return std::make_pair(x: nullptr, y: nullptr);
8900 Diff = SemaRef.BuildBinOp(S, OpLoc: DefaultLoc, Opc: BO_Mul, LHSExpr: Diff.get(), RHSExpr: NewStep.get());
8901 if (!Diff.isUsable())
8902 return std::make_pair(x: nullptr, y: nullptr);
8903
8904 // Parentheses (for dumping/debugging purposes only).
8905 Diff = SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Diff.get());
8906 if (!Diff.isUsable())
8907 return std::make_pair(x: nullptr, y: nullptr);
8908
8909 // Convert to the ptrdiff_t, if original type is pointer.
8910 if (VarType->isAnyPointerType() &&
8911 !SemaRef.Context.hasSameType(
8912 T1: Diff.get()->getType(),
8913 T2: SemaRef.Context.getUnsignedPointerDiffType())) {
8914 Diff = SemaRef.PerformImplicitConversion(
8915 From: Diff.get(), ToType: SemaRef.Context.getUnsignedPointerDiffType(),
8916 Action: AssignmentAction::Converting, /*AllowExplicit=*/true);
8917 }
8918 if (!Diff.isUsable())
8919 return std::make_pair(x: nullptr, y: nullptr);
8920
8921 if (*TestIsLessOp) {
8922 // MinExpr = Lower;
8923 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
8924 Diff = SemaRef.BuildBinOp(
8925 S, OpLoc: DefaultLoc, Opc: BO_Add,
8926 LHSExpr: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Lower).get(),
8927 RHSExpr: Diff.get());
8928 if (!Diff.isUsable())
8929 return std::make_pair(x: nullptr, y: nullptr);
8930 } else {
8931 // MaxExpr = Upper;
8932 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
8933 Diff = SemaRef.BuildBinOp(
8934 S, OpLoc: DefaultLoc, Opc: BO_Sub,
8935 LHSExpr: SemaRef.ActOnParenExpr(L: DefaultLoc, R: DefaultLoc, E: Upper).get(),
8936 RHSExpr: Diff.get());
8937 if (!Diff.isUsable())
8938 return std::make_pair(x: nullptr, y: nullptr);
8939 }
8940
8941 // Convert to the original type.
8942 if (SemaRef.Context.hasSameType(T1: Diff.get()->getType(), T2: VarType))
8943 Diff = SemaRef.PerformImplicitConversion(From: Diff.get(), ToType: VarType,
8944 Action: AssignmentAction::Converting,
8945 /*AllowExplicit=*/true);
8946 if (!Diff.isUsable())
8947 return std::make_pair(x: nullptr, y: nullptr);
8948
8949 Sema::TentativeAnalysisScope Trap(SemaRef);
8950 Diff = SemaRef.ActOnFinishFullExpr(Expr: Diff.get(), /*DiscardedValue=*/false);
8951 if (!Diff.isUsable())
8952 return std::make_pair(x: nullptr, y: nullptr);
8953
8954 if (*TestIsLessOp)
8955 MaxExpr = Diff.get();
8956 else
8957 MinExpr = Diff.get();
8958
8959 return std::make_pair(x&: MinExpr, y&: MaxExpr);
8960}
8961
8962Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
8963 if (InitDependOnLC || CondDependOnLC)
8964 return Condition;
8965 return nullptr;
8966}
8967
8968Expr *OpenMPIterationSpaceChecker::buildPreCond(
8969 Scope *S, Expr *Cond,
8970 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8971 // Do not build a precondition when the condition/initialization is dependent
8972 // to prevent pessimistic early loop exit.
8973 // TODO: this can be improved by calculating min/max values but not sure that
8974 // it will be very effective.
8975 if (CondDependOnLC || InitDependOnLC)
8976 return SemaRef
8977 .PerformImplicitConversion(
8978 SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get(),
8979 SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
8980 /*AllowExplicit=*/true)
8981 .get();
8982
8983 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
8984 Sema::TentativeAnalysisScope Trap(SemaRef);
8985
8986 ExprResult NewLB = tryBuildCapture(SemaRef, Capture: LB, Captures);
8987 ExprResult NewUB = tryBuildCapture(SemaRef, Capture: UB, Captures);
8988 if (!NewLB.isUsable() || !NewUB.isUsable())
8989 return nullptr;
8990
8991 ExprResult CondExpr =
8992 SemaRef.BuildBinOp(S, OpLoc: DefaultLoc,
8993 Opc: *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
8994 : (TestIsStrictOp ? BO_GT : BO_GE),
8995 LHSExpr: NewLB.get(), RHSExpr: NewUB.get());
8996 if (CondExpr.isUsable()) {
8997 if (!SemaRef.Context.hasSameUnqualifiedType(T1: CondExpr.get()->getType(),
8998 T2: SemaRef.Context.BoolTy))
8999 CondExpr = SemaRef.PerformImplicitConversion(
9000 CondExpr.get(), SemaRef.Context.BoolTy,
9001 /*Action=*/AssignmentAction::Casting,
9002 /*AllowExplicit=*/true);
9003 }
9004
9005 // Otherwise use original loop condition and evaluate it in runtime.
9006 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9007}
9008
9009/// Build reference expression to the counter be used for codegen.
9010DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9011 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9012 DSAStackTy &DSA) const {
9013 auto *VD = dyn_cast<VarDecl>(Val: LCDecl);
9014 if (!VD) {
9015 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(D: LCDecl);
9016 DeclRefExpr *Ref = buildDeclRefExpr(
9017 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9018 const DSAStackTy::DSAVarData Data =
9019 DSA.getTopDSA(D: LCDecl, /*FromParent=*/false);
9020 // If the loop control decl is explicitly marked as private, do not mark it
9021 // as captured again.
9022 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9023 Captures.insert(KV: std::make_pair(x: LCRef, y&: Ref));
9024 return Ref;
9025 }
9026 return cast<DeclRefExpr>(Val: LCRef);
9027}
9028
9029Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9030 if (LCDecl && !LCDecl->isInvalidDecl()) {
9031 QualType Type = LCDecl->getType().getNonReferenceType();
9032 VarDecl *PrivateVar = buildVarDecl(
9033 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9034 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9035 isa<VarDecl>(Val: LCDecl)
9036 ? buildDeclRefExpr(S&: SemaRef, D: cast<VarDecl>(Val: LCDecl), Ty: Type, Loc: DefaultLoc)
9037 : nullptr);
9038 if (PrivateVar->isInvalidDecl())
9039 return nullptr;
9040 return buildDeclRefExpr(S&: SemaRef, D: PrivateVar, Ty: Type, Loc: DefaultLoc);
9041 }
9042 return nullptr;
9043}
9044
9045/// Build initialization of the counter to be used for codegen.
9046Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9047
9048/// Build step of the counter be used for codegen.
9049Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9050
9051Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9052 Scope *S, Expr *Counter,
9053 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9054 Expr *Inc, OverloadedOperatorKind OOK) {
9055 Expr *Cnt = SemaRef.DefaultLvalueConversion(E: Counter).get();
9056 if (!Cnt)
9057 return nullptr;
9058 if (Inc) {
9059 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9060 "Expected only + or - operations for depend clauses.");
9061 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9062 Cnt = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BOK, LHSExpr: Cnt, RHSExpr: Inc).get();
9063 if (!Cnt)
9064 return nullptr;
9065 }
9066 QualType VarType = LCDecl->getType().getNonReferenceType();
9067 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9068 !SemaRef.getLangOpts().CPlusPlus)
9069 return nullptr;
9070 // Upper - Lower
9071 Expr *Upper =
9072 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, Capture: LB, Captures).get();
9073 Expr *Lower =
9074 *TestIsLessOp ? tryBuildCapture(SemaRef, Capture: LB, Captures).get() : Cnt;
9075 if (!Upper || !Lower)
9076 return nullptr;
9077
9078 ExprResult Diff = calculateNumIters(
9079 SemaRef, S, DefaultLoc, Lower, Upper, Step, LCTy: VarType,
9080 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9081 if (!Diff.isUsable())
9082 return nullptr;
9083
9084 return Diff.get();
9085}
9086} // namespace
9087
9088void SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc,
9089 Stmt *Init) {
9090 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9091 assert(Init && "Expected loop in canonical form.");
9092 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9093 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9094 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9095 return;
9096
9097 DSAStack->loopStart();
9098 llvm::SmallPtrSet<const Decl *, 1> EmptyDeclSet;
9099 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9100 *DSAStack, ForLoc, EmptyDeclSet);
9101 if (!ISC.checkAndSetInit(S: Init, /*EmitDiags=*/false)) {
9102 if (ValueDecl *D = ISC.getLoopDecl()) {
9103 auto *VD = dyn_cast<VarDecl>(Val: D);
9104 DeclRefExpr *PrivateRef = nullptr;
9105 if (!VD) {
9106 if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9107 VD = Private;
9108 } else {
9109 PrivateRef = buildCapture(S&: SemaRef, D, CaptureExpr: ISC.getLoopDeclRefExpr(),
9110 /*WithInit=*/false);
9111 VD = cast<VarDecl>(Val: PrivateRef->getDecl());
9112 }
9113 }
9114 DSAStack->addLoopControlVariable(D, Capture: VD);
9115 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9116 if (LD != D->getCanonicalDecl()) {
9117 DSAStack->resetPossibleLoopCounter();
9118 if (auto *Var = dyn_cast_or_null<VarDecl>(Val: LD))
9119 SemaRef.MarkDeclarationsReferencedInExpr(E: buildDeclRefExpr(
9120 SemaRef, const_cast<VarDecl *>(Var),
9121 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9122 /*RefersToCapture=*/true));
9123 }
9124 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9125 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9126 // associated for-loop of a simd construct with just one associated
9127 // for-loop may be listed in a linear clause with a constant-linear-step
9128 // that is the increment of the associated for-loop. The loop iteration
9129 // variable(s) in the associated for-loop(s) of a for or parallel for
9130 // construct may be listed in a private or lastprivate clause.
9131 DSAStackTy::DSAVarData DVar =
9132 DSAStack->getTopDSA(D, /*FromParent=*/false);
9133 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9134 // is declared in the loop and it is predetermined as a private.
9135 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9136 OpenMPClauseKind PredeterminedCKind =
9137 isOpenMPSimdDirective(DKind)
9138 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9139 : OMPC_private;
9140 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9141 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9142 };
9143 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9144 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9145 (getLangOpts().OpenMP <= 45 ||
9146 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9147 ((isOpenMPWorksharingDirective(DKind) ||
9148 IsOpenMPTaskloopDirective(DKind) ||
9149 isOpenMPDistributeDirective(DKind)) &&
9150 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9151 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9152 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9153 unsigned OMPVersion = getLangOpts().OpenMP;
9154 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9155 << getOpenMPClauseNameForDiag(DVar.CKind)
9156 << getOpenMPDirectiveName(DKind, OMPVersion)
9157 << getOpenMPClauseNameForDiag(PredeterminedCKind);
9158 if (DVar.RefExpr == nullptr)
9159 DVar.CKind = PredeterminedCKind;
9160 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9161 } else if (LoopDeclRefExpr) {
9162 // Make the loop iteration variable private (for worksharing
9163 // constructs), linear (for simd directives with the only one
9164 // associated loop) or lastprivate (for simd directives with several
9165 // collapsed or ordered loops).
9166 if (DVar.CKind == OMPC_unknown)
9167 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9168 }
9169 }
9170 }
9171 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9172}
9173
9174namespace {
9175// Utility for OpenMP doacross clause kind
9176class OMPDoacrossKind {
9177public:
9178 bool isSource(const OMPDoacrossClause *C) {
9179 return C->getDependenceType() == OMPC_DOACROSS_source ||
9180 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9181 }
9182 bool isSink(const OMPDoacrossClause *C) {
9183 return C->getDependenceType() == OMPC_DOACROSS_sink;
9184 }
9185 bool isSinkIter(const OMPDoacrossClause *C) {
9186 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9187 }
9188};
9189} // namespace
9190/// Called on a for stmt to check and extract its iteration space
9191/// for further processing (such as collapsing).
9192static bool checkOpenMPIterationSpace(
9193 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9194 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9195 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9196 Expr *OrderedLoopCountExpr,
9197 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9198 llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
9199 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9200 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9201 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9202 // OpenMP [2.9.1, Canonical Loop Form]
9203 // for (init-expr; test-expr; incr-expr) structured-block
9204 // for (range-decl: range-expr) structured-block
9205 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(Val: S))
9206 S = CanonLoop->getLoopStmt();
9207 auto *For = dyn_cast_or_null<ForStmt>(Val: S);
9208 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(Val: S);
9209 // Ranged for is supported only in OpenMP 5.0.
9210 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9211 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
9212 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9213 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9214 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9215 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9216 if (TotalNestedLoopCount > 1) {
9217 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9218 SemaRef.Diag(DSA.getConstructLoc(),
9219 diag::note_omp_collapse_ordered_expr)
9220 << 2 << CollapseLoopCountExpr->getSourceRange()
9221 << OrderedLoopCountExpr->getSourceRange();
9222 else if (CollapseLoopCountExpr)
9223 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9224 diag::note_omp_collapse_ordered_expr)
9225 << 0 << CollapseLoopCountExpr->getSourceRange();
9226 else if (OrderedLoopCountExpr)
9227 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9228 diag::note_omp_collapse_ordered_expr)
9229 << 1 << OrderedLoopCountExpr->getSourceRange();
9230 }
9231 return true;
9232 }
9233 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9234 "No loop body.");
9235 // Postpone analysis in dependent contexts for ranged for loops.
9236 if (CXXFor && SemaRef.CurContext->isDependentContext())
9237 return false;
9238
9239 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9240 For ? For->getForLoc() : CXXFor->getForLoc(),
9241 CollapsedLoopVarDecls);
9242
9243 // Check init.
9244 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9245 if (ISC.checkAndSetInit(S: Init))
9246 return true;
9247
9248 bool HasErrors = false;
9249
9250 // Check loop variable's type.
9251 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9252 // OpenMP [2.6, Canonical Loop Form]
9253 // Var is one of the following:
9254 // A variable of signed or unsigned integer type.
9255 // For C++, a variable of a random access iterator type.
9256 // For C, a variable of a pointer type.
9257 QualType VarType = LCDecl->getType().getNonReferenceType();
9258 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9259 !VarType->isPointerType() &&
9260 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9261 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9262 << SemaRef.getLangOpts().CPlusPlus;
9263 HasErrors = true;
9264 }
9265
9266 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9267 // a Construct
9268 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9269 // parallel for construct is (are) private.
9270 // The loop iteration variable in the associated for-loop of a simd
9271 // construct with just one associated for-loop is linear with a
9272 // constant-linear-step that is the increment of the associated for-loop.
9273 // Exclude loop var from the list of variables with implicitly defined data
9274 // sharing attributes.
9275 VarsWithImplicitDSA.erase(Val: LCDecl);
9276
9277 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9278
9279 // Check test-expr.
9280 HasErrors |= ISC.checkAndSetCond(S: For ? For->getCond() : CXXFor->getCond());
9281
9282 // Check incr-expr.
9283 HasErrors |= ISC.checkAndSetInc(S: For ? For->getInc() : CXXFor->getInc());
9284 }
9285
9286 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9287 return HasErrors;
9288
9289 // Build the loop's iteration space representation.
9290 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9291 S: DSA.getCurScope(), Cond: For ? For->getCond() : CXXFor->getCond(), Captures);
9292 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9293 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9294 (isOpenMPWorksharingDirective(DKind) ||
9295 isOpenMPGenericLoopDirective(DKind) ||
9296 isOpenMPTaskLoopDirective(DKind) ||
9297 isOpenMPDistributeDirective(DKind) ||
9298 isOpenMPLoopTransformationDirective(DKind)),
9299 Captures);
9300 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9301 ISC.buildCounterVar(Captures, DSA);
9302 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9303 ISC.buildPrivateCounterVar();
9304 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9305 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9306 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9307 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9308 ISC.getConditionSrcRange();
9309 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9310 ISC.getIncrementSrcRange();
9311 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9312 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9313 ISC.isStrictTestOp();
9314 std::tie(args&: ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9315 args&: ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9316 ISC.buildMinMaxValues(S: DSA.getCurScope(), Captures);
9317 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9318 ISC.buildFinalCondition(S: DSA.getCurScope());
9319 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9320 ISC.doesInitDependOnLC();
9321 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9322 ISC.doesCondDependOnLC();
9323 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9324 ISC.getLoopDependentIdx();
9325
9326 HasErrors |=
9327 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9328 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9329 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9330 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9331 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9332 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9333 if (!HasErrors && DSA.isOrderedRegion()) {
9334 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9335 if (CurrentNestedLoopCount <
9336 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9337 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9338 NumLoop: CurrentNestedLoopCount,
9339 NumIterations: ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9340 DSA.getOrderedRegionParam().second->setLoopCounter(
9341 NumLoop: CurrentNestedLoopCount,
9342 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9343 }
9344 }
9345 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9346 auto *DependC = dyn_cast<OMPDependClause>(Val: Pair.first);
9347 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Val: Pair.first);
9348 unsigned NumLoops =
9349 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9350 if (CurrentNestedLoopCount >= NumLoops) {
9351 // Erroneous case - clause has some problems.
9352 continue;
9353 }
9354 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9355 Pair.second.size() <= CurrentNestedLoopCount) {
9356 // Erroneous case - clause has some problems.
9357 DependC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: nullptr);
9358 continue;
9359 }
9360 OMPDoacrossKind ODK;
9361 if (DoacrossC && ODK.isSink(C: DoacrossC) &&
9362 Pair.second.size() <= CurrentNestedLoopCount) {
9363 // Erroneous case - clause has some problems.
9364 DoacrossC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: nullptr);
9365 continue;
9366 }
9367 Expr *CntValue;
9368 SourceLocation DepLoc =
9369 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9370 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9371 (DoacrossC && ODK.isSource(C: DoacrossC)))
9372 CntValue = ISC.buildOrderedLoopData(
9373 S: DSA.getCurScope(),
9374 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9375 Loc: DepLoc);
9376 else if (DoacrossC && ODK.isSinkIter(C: DoacrossC)) {
9377 Expr *Cnt = SemaRef
9378 .DefaultLvalueConversion(
9379 E: ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9380 .get();
9381 if (!Cnt)
9382 continue;
9383 // build CounterVar - 1
9384 Expr *Inc =
9385 SemaRef.ActOnIntegerConstant(Loc: DoacrossC->getColonLoc(), /*Val=*/1)
9386 .get();
9387 CntValue = ISC.buildOrderedLoopData(
9388 S: DSA.getCurScope(),
9389 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9390 Loc: DepLoc, Inc, OOK: clang::OO_Minus);
9391 } else
9392 CntValue = ISC.buildOrderedLoopData(
9393 S: DSA.getCurScope(),
9394 Counter: ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9395 Loc: DepLoc, Inc: Pair.second[CurrentNestedLoopCount].first,
9396 OOK: Pair.second[CurrentNestedLoopCount].second);
9397 if (DependC)
9398 DependC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: CntValue);
9399 else
9400 DoacrossC->setLoopData(NumLoop: CurrentNestedLoopCount, Cnt: CntValue);
9401 }
9402 }
9403
9404 return HasErrors;
9405}
9406
9407/// Build 'VarRef = Start.
9408static ExprResult
9409buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9410 ExprResult Start, bool IsNonRectangularLB,
9411 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9412 // Build 'VarRef = Start.
9413 ExprResult NewStart = IsNonRectangularLB
9414 ? Start.get()
9415 : tryBuildCapture(SemaRef, Capture: Start.get(), Captures);
9416 if (!NewStart.isUsable())
9417 return ExprError();
9418 if (!SemaRef.Context.hasSameType(T1: NewStart.get()->getType(),
9419 T2: VarRef.get()->getType())) {
9420 NewStart = SemaRef.PerformImplicitConversion(
9421 From: NewStart.get(), ToType: VarRef.get()->getType(), Action: AssignmentAction::Converting,
9422 /*AllowExplicit=*/true);
9423 if (!NewStart.isUsable())
9424 return ExprError();
9425 }
9426
9427 ExprResult Init =
9428 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: NewStart.get());
9429 return Init;
9430}
9431
9432/// Build 'VarRef = Start + Iter * Step'.
9433static ExprResult buildCounterUpdate(
9434 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9435 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9436 bool IsNonRectangularLB,
9437 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9438 // Add parentheses (for debugging purposes only).
9439 Iter = SemaRef.ActOnParenExpr(L: Loc, R: Loc, E: Iter.get());
9440 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9441 !Step.isUsable())
9442 return ExprError();
9443
9444 ExprResult NewStep = Step;
9445 if (Captures)
9446 NewStep = tryBuildCapture(SemaRef, Capture: Step.get(), Captures&: *Captures);
9447 if (NewStep.isInvalid())
9448 return ExprError();
9449 ExprResult Update =
9450 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Mul, LHSExpr: Iter.get(), RHSExpr: NewStep.get());
9451 if (!Update.isUsable())
9452 return ExprError();
9453
9454 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9455 // 'VarRef = Start (+|-) Iter * Step'.
9456 if (!Start.isUsable())
9457 return ExprError();
9458 ExprResult NewStart = SemaRef.ActOnParenExpr(L: Loc, R: Loc, E: Start.get());
9459 if (!NewStart.isUsable())
9460 return ExprError();
9461 if (Captures && !IsNonRectangularLB)
9462 NewStart = tryBuildCapture(SemaRef, Capture: Start.get(), Captures&: *Captures);
9463 if (NewStart.isInvalid())
9464 return ExprError();
9465
9466 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9467 ExprResult SavedUpdate = Update;
9468 ExprResult UpdateVal;
9469 if (VarRef.get()->getType()->isOverloadableType() ||
9470 NewStart.get()->getType()->isOverloadableType() ||
9471 Update.get()->getType()->isOverloadableType()) {
9472 Sema::TentativeAnalysisScope Trap(SemaRef);
9473
9474 Update =
9475 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: NewStart.get());
9476 if (Update.isUsable()) {
9477 UpdateVal =
9478 SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: Subtract ? BO_SubAssign : BO_AddAssign,
9479 LHSExpr: VarRef.get(), RHSExpr: SavedUpdate.get());
9480 if (UpdateVal.isUsable()) {
9481 Update = SemaRef.CreateBuiltinBinOp(OpLoc: Loc, Opc: BO_Comma, LHSExpr: Update.get(),
9482 RHSExpr: UpdateVal.get());
9483 }
9484 }
9485 }
9486
9487 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9488 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9489 Update = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: Subtract ? BO_Sub : BO_Add,
9490 LHSExpr: NewStart.get(), RHSExpr: SavedUpdate.get());
9491 if (!Update.isUsable())
9492 return ExprError();
9493
9494 if (!SemaRef.Context.hasSameType(T1: Update.get()->getType(),
9495 T2: VarRef.get()->getType())) {
9496 Update = SemaRef.PerformImplicitConversion(
9497 From: Update.get(), ToType: VarRef.get()->getType(), Action: AssignmentAction::Converting,
9498 /*AllowExplicit=*/true);
9499 if (!Update.isUsable())
9500 return ExprError();
9501 }
9502
9503 Update = SemaRef.BuildBinOp(S, OpLoc: Loc, Opc: BO_Assign, LHSExpr: VarRef.get(), RHSExpr: Update.get());
9504 }
9505 return Update;
9506}
9507
9508/// Convert integer expression \a E to make it have at least \a Bits
9509/// bits.
9510static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9511 if (E == nullptr)
9512 return ExprError();
9513 ASTContext &C = SemaRef.Context;
9514 QualType OldType = E->getType();
9515 unsigned HasBits = C.getTypeSize(T: OldType);
9516 if (HasBits >= Bits)
9517 return ExprResult(E);
9518 // OK to convert to signed, because new type has more bits than old.
9519 QualType NewType = C.getIntTypeForBitwidth(DestWidth: Bits, /*Signed=*/true);
9520 return SemaRef.PerformImplicitConversion(
9521 From: E, ToType: NewType, Action: AssignmentAction::Converting, /*AllowExplicit=*/true);
9522}
9523
9524/// Check if the given expression \a E is a constant integer that fits
9525/// into \a Bits bits.
9526static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9527 if (E == nullptr)
9528 return false;
9529 if (std::optional<llvm::APSInt> Result =
9530 E->getIntegerConstantExpr(Ctx: SemaRef.Context))
9531 return Signed ? Result->isSignedIntN(N: Bits) : Result->isIntN(N: Bits);
9532 return false;
9533}
9534
9535/// Build preinits statement for the given declarations.
9536static Stmt *buildPreInits(ASTContext &Context,
9537 MutableArrayRef<Decl *> PreInits) {
9538 if (!PreInits.empty()) {
9539 return new (Context) DeclStmt(
9540 DeclGroupRef::Create(C&: Context, Decls: PreInits.begin(), NumDecls: PreInits.size()),
9541 SourceLocation(), SourceLocation());
9542 }
9543 return nullptr;
9544}
9545
9546/// Append the \p Item or the content of a CompoundStmt to the list \p
9547/// TargetList.
9548///
9549/// A CompoundStmt is used as container in case multiple statements need to be
9550/// stored in lieu of using an explicit list. Flattening is necessary because
9551/// contained DeclStmts need to be visible after the execution of the list. Used
9552/// for OpenMP pre-init declarations/statements.
9553static void appendFlattenedStmtList(SmallVectorImpl<Stmt *> &TargetList,
9554 Stmt *Item) {
9555 // nullptr represents an empty list.
9556 if (!Item)
9557 return;
9558
9559 if (auto *CS = dyn_cast<CompoundStmt>(Val: Item))
9560 llvm::append_range(C&: TargetList, R: CS->body());
9561 else
9562 TargetList.push_back(Elt: Item);
9563}
9564
9565/// Build preinits statement for the given declarations.
9566static Stmt *
9567buildPreInits(ASTContext &Context,
9568 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9569 if (!Captures.empty()) {
9570 SmallVector<Decl *, 16> PreInits;
9571 for (const auto &Pair : Captures)
9572 PreInits.push_back(Pair.second->getDecl());
9573 return buildPreInits(Context, PreInits);
9574 }
9575 return nullptr;
9576}
9577
9578/// Build pre-init statement for the given statements.
9579static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9580 if (PreInits.empty())
9581 return nullptr;
9582
9583 SmallVector<Stmt *> Stmts;
9584 for (Stmt *S : PreInits)
9585 appendFlattenedStmtList(TargetList&: Stmts, Item: S);
9586 return CompoundStmt::Create(C: Context, Stmts: PreInits, FPFeatures: FPOptionsOverride(), LB: {}, RB: {});
9587}
9588
9589/// Build postupdate expression for the given list of postupdates expressions.
9590static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9591 Expr *PostUpdate = nullptr;
9592 if (!PostUpdates.empty()) {
9593 for (Expr *E : PostUpdates) {
9594 Expr *ConvE = S.BuildCStyleCastExpr(
9595 LParenLoc: E->getExprLoc(),
9596 Ty: S.Context.getTrivialTypeSourceInfo(T: S.Context.VoidTy),
9597 RParenLoc: E->getExprLoc(), Op: E)
9598 .get();
9599 PostUpdate = PostUpdate
9600 ? S.CreateBuiltinBinOp(OpLoc: ConvE->getExprLoc(), Opc: BO_Comma,
9601 LHSExpr: PostUpdate, RHSExpr: ConvE)
9602 .get()
9603 : ConvE;
9604 }
9605 }
9606 return PostUpdate;
9607}
9608
9609/// Look for variables declared in the body parts of a for-loop nest. Used
9610/// for verifying loop nest structure before performing a loop collapse
9611/// operation.
9612class ForVarDeclFinder : public DynamicRecursiveASTVisitor {
9613 int NestingDepth = 0;
9614 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9615
9616public:
9617 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
9618 : VarDecls(VD) {}
9619
9620 bool VisitForStmt(ForStmt *F) override {
9621 ++NestingDepth;
9622 TraverseStmt(F->getBody());
9623 --NestingDepth;
9624 return false;
9625 }
9626
9627 bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override {
9628 ++NestingDepth;
9629 TraverseStmt(RF->getBody());
9630 --NestingDepth;
9631 return false;
9632 }
9633
9634 bool VisitVarDecl(VarDecl *D) override {
9635 Decl *C = D->getCanonicalDecl();
9636 if (NestingDepth > 0)
9637 VarDecls.insert(Ptr: C);
9638 return true;
9639 }
9640};
9641
9642/// Called on a for stmt to check itself and nested loops (if any).
9643/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9644/// number of collapsed loops otherwise.
9645static unsigned
9646checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9647 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9648 DSAStackTy &DSA,
9649 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9650 OMPLoopBasedDirective::HelperExprs &Built) {
9651 // If either of the loop expressions exist and contain errors, we bail out
9652 // early because diagnostics have already been emitted and we can't reliably
9653 // check more about the loop.
9654 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
9655 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
9656 return 0;
9657
9658 unsigned NestedLoopCount = 1;
9659 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9660 !isOpenMPLoopTransformationDirective(DKind);
9661 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
9662
9663 if (CollapseLoopCountExpr) {
9664 // Found 'collapse' clause - calculate collapse number.
9665 Expr::EvalResult Result;
9666 if (!CollapseLoopCountExpr->isValueDependent() &&
9667 CollapseLoopCountExpr->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext())) {
9668 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9669
9670 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9671 FVDF.TraverseStmt(AStmt);
9672 } else {
9673 Built.clear(/*Size=*/1);
9674 return 1;
9675 }
9676 }
9677 unsigned OrderedLoopCount = 1;
9678 if (OrderedLoopCountExpr) {
9679 // Found 'ordered' clause - calculate collapse number.
9680 Expr::EvalResult EVResult;
9681 if (!OrderedLoopCountExpr->isValueDependent() &&
9682 OrderedLoopCountExpr->EvaluateAsInt(Result&: EVResult,
9683 Ctx: SemaRef.getASTContext())) {
9684 llvm::APSInt Result = EVResult.Val.getInt();
9685 if (Result.getLimitedValue() < NestedLoopCount) {
9686 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9687 diag::err_omp_wrong_ordered_loop_count)
9688 << OrderedLoopCountExpr->getSourceRange();
9689 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9690 diag::note_collapse_loop_count)
9691 << CollapseLoopCountExpr->getSourceRange();
9692 }
9693 OrderedLoopCount = Result.getLimitedValue();
9694 } else {
9695 Built.clear(/*Size=*/1);
9696 return 1;
9697 }
9698 }
9699 // This is helper routine for loop directives (e.g., 'for', 'simd',
9700 // 'for simd', etc.).
9701 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9702 unsigned NumLoops = std::max(a: OrderedLoopCount, b: NestedLoopCount);
9703 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9704 if (!OMPLoopBasedDirective::doForAllLoops(
9705 AStmt->IgnoreContainers(!isOpenMPLoopTransformationDirective(DKind)),
9706 SupportsNonPerfectlyNested, NumLoops,
9707 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9708 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9709 &IterSpaces, &Captures,
9710 &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
9711 if (checkOpenMPIterationSpace(
9712 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9713 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9714 VarsWithImplicitDSA, IterSpaces, Captures,
9715 CollapsedLoopVarDecls))
9716 return true;
9717 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9718 IterSpaces[Cnt].CounterVar) {
9719 // Handle initialization of captured loop iterator variables.
9720 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9721 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9722 Captures[DRE] = DRE;
9723 }
9724 }
9725 return false;
9726 },
9727 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9728 Stmt *DependentPreInits = Transform->getPreInits();
9729 if (!DependentPreInits)
9730 return;
9731
9732 // Search for pre-init declared variables that need to be captured
9733 // to be referenceable inside the directive.
9734 SmallVector<Stmt *> Constituents;
9735 appendFlattenedStmtList(Constituents, DependentPreInits);
9736 for (Stmt *S : Constituents) {
9737 if (auto *DC = dyn_cast<DeclStmt>(S)) {
9738 for (Decl *C : DC->decls()) {
9739 auto *D = cast<VarDecl>(C);
9740 DeclRefExpr *Ref = buildDeclRefExpr(
9741 SemaRef, D, D->getType().getNonReferenceType(),
9742 Transform->getBeginLoc());
9743 Captures[Ref] = Ref;
9744 }
9745 }
9746 }
9747 }))
9748 return 0;
9749
9750 Built.clear(/*size=*/Size: NestedLoopCount);
9751
9752 if (SemaRef.CurContext->isDependentContext())
9753 return NestedLoopCount;
9754
9755 // An example of what is generated for the following code:
9756 //
9757 // #pragma omp simd collapse(2) ordered(2)
9758 // for (i = 0; i < NI; ++i)
9759 // for (k = 0; k < NK; ++k)
9760 // for (j = J0; j < NJ; j+=2) {
9761 // <loop body>
9762 // }
9763 //
9764 // We generate the code below.
9765 // Note: the loop body may be outlined in CodeGen.
9766 // Note: some counters may be C++ classes, operator- is used to find number of
9767 // iterations and operator+= to calculate counter value.
9768 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9769 // or i64 is currently supported).
9770 //
9771 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9772 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9773 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9774 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9775 // // similar updates for vars in clauses (e.g. 'linear')
9776 // <loop body (using local i and j)>
9777 // }
9778 // i = NI; // assign final values of counters
9779 // j = NJ;
9780 //
9781
9782 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9783 // the iteration counts of the collapsed for loops.
9784 // Precondition tests if there is at least one iteration (all conditions are
9785 // true).
9786 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9787 Expr *N0 = IterSpaces[0].NumIterations;
9788 ExprResult LastIteration32 = widenIterationCount(
9789 /*Bits=*/32,
9790 E: SemaRef
9791 .PerformImplicitConversion(From: N0->IgnoreImpCasts(), ToType: N0->getType(),
9792 Action: AssignmentAction::Converting,
9793 /*AllowExplicit=*/true)
9794 .get(),
9795 SemaRef);
9796 ExprResult LastIteration64 = widenIterationCount(
9797 /*Bits=*/64,
9798 E: SemaRef
9799 .PerformImplicitConversion(From: N0->IgnoreImpCasts(), ToType: N0->getType(),
9800 Action: AssignmentAction::Converting,
9801 /*AllowExplicit=*/true)
9802 .get(),
9803 SemaRef);
9804
9805 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9806 return NestedLoopCount;
9807
9808 ASTContext &C = SemaRef.Context;
9809 bool AllCountsNeedLessThan32Bits = C.getTypeSize(T: N0->getType()) < 32;
9810
9811 Scope *CurScope = DSA.getCurScope();
9812 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9813 if (PreCond.isUsable()) {
9814 PreCond =
9815 SemaRef.BuildBinOp(S: CurScope, OpLoc: PreCond.get()->getExprLoc(), Opc: BO_LAnd,
9816 LHSExpr: PreCond.get(), RHSExpr: IterSpaces[Cnt].PreCond);
9817 }
9818 Expr *N = IterSpaces[Cnt].NumIterations;
9819 SourceLocation Loc = N->getExprLoc();
9820 AllCountsNeedLessThan32Bits &= C.getTypeSize(T: N->getType()) < 32;
9821 if (LastIteration32.isUsable())
9822 LastIteration32 = SemaRef.BuildBinOp(
9823 S: CurScope, OpLoc: Loc, Opc: BO_Mul, LHSExpr: LastIteration32.get(),
9824 RHSExpr: SemaRef
9825 .PerformImplicitConversion(From: N->IgnoreImpCasts(), ToType: N->getType(),
9826 Action: AssignmentAction::Converting,
9827 /*AllowExplicit=*/true)
9828 .get());
9829 if (LastIteration64.isUsable())
9830 LastIteration64 = SemaRef.BuildBinOp(
9831 S: CurScope, OpLoc: Loc, Opc: BO_Mul, LHSExpr: LastIteration64.get(),
9832 RHSExpr: SemaRef
9833 .PerformImplicitConversion(From: N->IgnoreImpCasts(), ToType: N->getType(),
9834 Action: AssignmentAction::Converting,
9835 /*AllowExplicit=*/true)
9836 .get());
9837 }
9838
9839 // Choose either the 32-bit or 64-bit version.
9840 ExprResult LastIteration = LastIteration64;
9841 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9842 (LastIteration32.isUsable() &&
9843 C.getTypeSize(T: LastIteration32.get()->getType()) == 32 &&
9844 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9845 fitsInto(
9846 /*Bits=*/32,
9847 Signed: LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9848 E: LastIteration64.get(), SemaRef))))
9849 LastIteration = LastIteration32;
9850 QualType VType = LastIteration.get()->getType();
9851 QualType RealVType = VType;
9852 QualType StrideVType = VType;
9853 if (isOpenMPTaskLoopDirective(DKind)) {
9854 VType =
9855 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9856 StrideVType =
9857 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9858 }
9859
9860 if (!LastIteration.isUsable())
9861 return 0;
9862
9863 // Save the number of iterations.
9864 ExprResult NumIterations = LastIteration;
9865 {
9866 LastIteration = SemaRef.BuildBinOp(
9867 S: CurScope, OpLoc: LastIteration.get()->getExprLoc(), Opc: BO_Sub,
9868 LHSExpr: LastIteration.get(),
9869 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
9870 if (!LastIteration.isUsable())
9871 return 0;
9872 }
9873
9874 // Calculate the last iteration number beforehand instead of doing this on
9875 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9876 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(Ctx: SemaRef.Context);
9877 ExprResult CalcLastIteration;
9878 if (!IsConstant) {
9879 ExprResult SaveRef =
9880 tryBuildCapture(SemaRef, Capture: LastIteration.get(), Captures);
9881 LastIteration = SaveRef;
9882
9883 // Prepare SaveRef + 1.
9884 NumIterations = SemaRef.BuildBinOp(
9885 S: CurScope, OpLoc: SaveRef.get()->getExprLoc(), Opc: BO_Add, LHSExpr: SaveRef.get(),
9886 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get());
9887 if (!NumIterations.isUsable())
9888 return 0;
9889 }
9890
9891 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9892
9893 // Build variables passed into runtime, necessary for worksharing directives.
9894 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9895 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
9896 isOpenMPDistributeDirective(DKind) ||
9897 isOpenMPGenericLoopDirective(DKind) ||
9898 isOpenMPLoopTransformationDirective(DKind)) {
9899 // Lower bound variable, initialized with zero.
9900 VarDecl *LBDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.lb");
9901 LB = buildDeclRefExpr(S&: SemaRef, D: LBDecl, Ty: VType, Loc: InitLoc);
9902 SemaRef.AddInitializerToDecl(LBDecl,
9903 SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
9904 /*DirectInit=*/false);
9905
9906 // Upper bound variable, initialized with last iteration number.
9907 VarDecl *UBDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.ub");
9908 UB = buildDeclRefExpr(S&: SemaRef, D: UBDecl, Ty: VType, Loc: InitLoc);
9909 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9910 /*DirectInit=*/false);
9911
9912 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9913 // This will be used to implement clause 'lastprivate'.
9914 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(DestWidth: 32, Signed: true);
9915 VarDecl *ILDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: Int32Ty, Name: ".omp.is_last");
9916 IL = buildDeclRefExpr(S&: SemaRef, D: ILDecl, Ty: Int32Ty, Loc: InitLoc);
9917 SemaRef.AddInitializerToDecl(ILDecl,
9918 SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
9919 /*DirectInit=*/false);
9920
9921 // Stride variable returned by runtime (we initialize it to 1 by default).
9922 VarDecl *STDecl =
9923 buildVarDecl(SemaRef, Loc: InitLoc, Type: StrideVType, Name: ".omp.stride");
9924 ST = buildDeclRefExpr(S&: SemaRef, D: STDecl, Ty: StrideVType, Loc: InitLoc);
9925 SemaRef.AddInitializerToDecl(STDecl,
9926 SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 1).get(),
9927 /*DirectInit=*/false);
9928
9929 // Build expression: UB = min(UB, LastIteration)
9930 // It is necessary for CodeGen of directives with static scheduling.
9931 ExprResult IsUBGreater = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_GT,
9932 LHSExpr: UB.get(), RHSExpr: LastIteration.get());
9933 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9934 QuestionLoc: LastIteration.get()->getExprLoc(), ColonLoc: InitLoc, CondExpr: IsUBGreater.get(),
9935 LHSExpr: LastIteration.get(), RHSExpr: UB.get());
9936 EUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: UB.get(),
9937 RHSExpr: CondOp.get());
9938 EUB = SemaRef.ActOnFinishFullExpr(Expr: EUB.get(), /*DiscardedValue=*/false);
9939
9940 // If we have a combined directive that combines 'distribute', 'for' or
9941 // 'simd' we need to be able to access the bounds of the schedule of the
9942 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9943 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9944 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9945 // Lower bound variable, initialized with zero.
9946 VarDecl *CombLBDecl =
9947 buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.comb.lb");
9948 CombLB = buildDeclRefExpr(S&: SemaRef, D: CombLBDecl, Ty: VType, Loc: InitLoc);
9949 SemaRef.AddInitializerToDecl(
9950 CombLBDecl, SemaRef.ActOnIntegerConstant(Loc: InitLoc, Val: 0).get(),
9951 /*DirectInit=*/false);
9952
9953 // Upper bound variable, initialized with last iteration number.
9954 VarDecl *CombUBDecl =
9955 buildVarDecl(SemaRef, Loc: InitLoc, Type: VType, Name: ".omp.comb.ub");
9956 CombUB = buildDeclRefExpr(S&: SemaRef, D: CombUBDecl, Ty: VType, Loc: InitLoc);
9957 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
9958 /*DirectInit=*/false);
9959
9960 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9961 S: CurScope, OpLoc: InitLoc, Opc: BO_GT, LHSExpr: CombUB.get(), RHSExpr: LastIteration.get());
9962 ExprResult CombCondOp =
9963 SemaRef.ActOnConditionalOp(QuestionLoc: InitLoc, ColonLoc: InitLoc, CondExpr: CombIsUBGreater.get(),
9964 LHSExpr: LastIteration.get(), RHSExpr: CombUB.get());
9965 CombEUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: CombUB.get(),
9966 RHSExpr: CombCondOp.get());
9967 CombEUB =
9968 SemaRef.ActOnFinishFullExpr(Expr: CombEUB.get(), /*DiscardedValue=*/false);
9969
9970 const CapturedDecl *CD = cast<CapturedStmt>(Val: AStmt)->getCapturedDecl();
9971 // We expect to have at least 2 more parameters than the 'parallel'
9972 // directive does - the lower and upper bounds of the previous schedule.
9973 assert(CD->getNumParams() >= 4 &&
9974 "Unexpected number of parameters in loop combined directive");
9975
9976 // Set the proper type for the bounds given what we learned from the
9977 // enclosed loops.
9978 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/i: 2);
9979 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/i: 3);
9980
9981 // Previous lower and upper bounds are obtained from the region
9982 // parameters.
9983 PrevLB =
9984 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
9985 PrevUB =
9986 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
9987 }
9988 }
9989
9990 // Build the iteration variable and its initialization before loop.
9991 ExprResult IV;
9992 ExprResult Init, CombInit;
9993 {
9994 VarDecl *IVDecl = buildVarDecl(SemaRef, Loc: InitLoc, Type: RealVType, Name: ".omp.iv");
9995 IV = buildDeclRefExpr(S&: SemaRef, D: IVDecl, Ty: RealVType, Loc: InitLoc);
9996 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
9997 isOpenMPGenericLoopDirective(DKind) ||
9998 isOpenMPTaskLoopDirective(DKind) ||
9999 isOpenMPDistributeDirective(DKind) ||
10000 isOpenMPLoopTransformationDirective(DKind))
10001 ? LB.get()
10002 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10003 Init = SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: RHS);
10004 Init = SemaRef.ActOnFinishFullExpr(Expr: Init.get(), /*DiscardedValue=*/false);
10005
10006 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10007 Expr *CombRHS =
10008 (isOpenMPWorksharingDirective(DKind) ||
10009 isOpenMPGenericLoopDirective(DKind) ||
10010 isOpenMPTaskLoopDirective(DKind) ||
10011 isOpenMPDistributeDirective(DKind))
10012 ? CombLB.get()
10013 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10014 CombInit =
10015 SemaRef.BuildBinOp(S: CurScope, OpLoc: InitLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: CombRHS);
10016 CombInit =
10017 SemaRef.ActOnFinishFullExpr(Expr: CombInit.get(), /*DiscardedValue=*/false);
10018 }
10019 }
10020
10021 bool UseStrictCompare =
10022 RealVType->hasUnsignedIntegerRepresentation() &&
10023 llvm::all_of(Range&: IterSpaces, P: [](const LoopIterationSpace &LIS) {
10024 return LIS.IsStrictCompare;
10025 });
10026 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10027 // unsigned IV)) for worksharing loops.
10028 SourceLocation CondLoc = AStmt->getBeginLoc();
10029 Expr *BoundUB = UB.get();
10030 if (UseStrictCompare) {
10031 BoundUB =
10032 SemaRef
10033 .BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundUB,
10034 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10035 .get();
10036 BoundUB =
10037 SemaRef.ActOnFinishFullExpr(Expr: BoundUB, /*DiscardedValue=*/false).get();
10038 }
10039 ExprResult Cond =
10040 (isOpenMPWorksharingDirective(DKind) ||
10041 isOpenMPGenericLoopDirective(DKind) ||
10042 isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
10043 isOpenMPLoopTransformationDirective(DKind))
10044 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10045 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10046 BoundUB)
10047 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10048 NumIterations.get());
10049 ExprResult CombDistCond;
10050 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10051 CombDistCond = SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: BO_LT, LHSExpr: IV.get(),
10052 RHSExpr: NumIterations.get());
10053 }
10054
10055 ExprResult CombCond;
10056 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10057 Expr *BoundCombUB = CombUB.get();
10058 if (UseStrictCompare) {
10059 BoundCombUB =
10060 SemaRef
10061 .BuildBinOp(
10062 S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundCombUB,
10063 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10064 .get();
10065 BoundCombUB =
10066 SemaRef.ActOnFinishFullExpr(Expr: BoundCombUB, /*DiscardedValue=*/false)
10067 .get();
10068 }
10069 CombCond =
10070 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE,
10071 LHSExpr: IV.get(), RHSExpr: BoundCombUB);
10072 }
10073 // Loop increment (IV = IV + 1)
10074 SourceLocation IncLoc = AStmt->getBeginLoc();
10075 ExprResult Inc =
10076 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: IV.get(),
10077 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: IncLoc, Val: 1).get());
10078 if (!Inc.isUsable())
10079 return 0;
10080 Inc = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: IV.get(), RHSExpr: Inc.get());
10081 Inc = SemaRef.ActOnFinishFullExpr(Expr: Inc.get(), /*DiscardedValue=*/false);
10082 if (!Inc.isUsable())
10083 return 0;
10084
10085 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10086 // Used for directives with static scheduling.
10087 // In combined construct, add combined version that use CombLB and CombUB
10088 // base variables for the update
10089 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10090 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
10091 isOpenMPGenericLoopDirective(DKind) ||
10092 isOpenMPDistributeDirective(DKind) ||
10093 isOpenMPLoopTransformationDirective(DKind)) {
10094 // LB + ST
10095 NextLB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: LB.get(), RHSExpr: ST.get());
10096 if (!NextLB.isUsable())
10097 return 0;
10098 // LB = LB + ST
10099 NextLB =
10100 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: LB.get(), RHSExpr: NextLB.get());
10101 NextLB =
10102 SemaRef.ActOnFinishFullExpr(Expr: NextLB.get(), /*DiscardedValue=*/false);
10103 if (!NextLB.isUsable())
10104 return 0;
10105 // UB + ST
10106 NextUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: UB.get(), RHSExpr: ST.get());
10107 if (!NextUB.isUsable())
10108 return 0;
10109 // UB = UB + ST
10110 NextUB =
10111 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: UB.get(), RHSExpr: NextUB.get());
10112 NextUB =
10113 SemaRef.ActOnFinishFullExpr(Expr: NextUB.get(), /*DiscardedValue=*/false);
10114 if (!NextUB.isUsable())
10115 return 0;
10116 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10117 CombNextLB =
10118 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: CombLB.get(), RHSExpr: ST.get());
10119 if (!NextLB.isUsable())
10120 return 0;
10121 // LB = LB + ST
10122 CombNextLB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: CombLB.get(),
10123 RHSExpr: CombNextLB.get());
10124 CombNextLB = SemaRef.ActOnFinishFullExpr(Expr: CombNextLB.get(),
10125 /*DiscardedValue=*/false);
10126 if (!CombNextLB.isUsable())
10127 return 0;
10128 // UB + ST
10129 CombNextUB =
10130 SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Add, LHSExpr: CombUB.get(), RHSExpr: ST.get());
10131 if (!CombNextUB.isUsable())
10132 return 0;
10133 // UB = UB + ST
10134 CombNextUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: IncLoc, Opc: BO_Assign, LHSExpr: CombUB.get(),
10135 RHSExpr: CombNextUB.get());
10136 CombNextUB = SemaRef.ActOnFinishFullExpr(Expr: CombNextUB.get(),
10137 /*DiscardedValue=*/false);
10138 if (!CombNextUB.isUsable())
10139 return 0;
10140 }
10141 }
10142
10143 // Create increment expression for distribute loop when combined in a same
10144 // directive with for as IV = IV + ST; ensure upper bound expression based
10145 // on PrevUB instead of NumIterations - used to implement 'for' when found
10146 // in combination with 'distribute', like in 'distribute parallel for'
10147 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10148 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10149 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10150 DistCond = SemaRef.BuildBinOp(
10151 S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE, LHSExpr: IV.get(), RHSExpr: BoundUB);
10152 assert(DistCond.isUsable() && "distribute cond expr was not built");
10153
10154 DistInc =
10155 SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Add, LHSExpr: IV.get(), RHSExpr: ST.get());
10156 assert(DistInc.isUsable() && "distribute inc expr was not built");
10157 DistInc = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Assign, LHSExpr: IV.get(),
10158 RHSExpr: DistInc.get());
10159 DistInc =
10160 SemaRef.ActOnFinishFullExpr(Expr: DistInc.get(), /*DiscardedValue=*/false);
10161 assert(DistInc.isUsable() && "distribute inc expr was not built");
10162
10163 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10164 // construct
10165 ExprResult NewPrevUB = PrevUB;
10166 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10167 if (!SemaRef.Context.hasSameType(T1: UB.get()->getType(),
10168 T2: PrevUB.get()->getType())) {
10169 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10170 LParenLoc: DistEUBLoc,
10171 Ty: SemaRef.Context.getTrivialTypeSourceInfo(T: UB.get()->getType()),
10172 RParenLoc: DistEUBLoc, Op: NewPrevUB.get());
10173 if (!NewPrevUB.isUsable())
10174 return 0;
10175 }
10176 ExprResult IsUBGreater = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistEUBLoc, Opc: BO_GT,
10177 LHSExpr: UB.get(), RHSExpr: NewPrevUB.get());
10178 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10179 QuestionLoc: DistEUBLoc, ColonLoc: DistEUBLoc, CondExpr: IsUBGreater.get(), LHSExpr: NewPrevUB.get(), RHSExpr: UB.get());
10180 PrevEUB = SemaRef.BuildBinOp(S: CurScope, OpLoc: DistIncLoc, Opc: BO_Assign, LHSExpr: UB.get(),
10181 RHSExpr: CondOp.get());
10182 PrevEUB =
10183 SemaRef.ActOnFinishFullExpr(Expr: PrevEUB.get(), /*DiscardedValue=*/false);
10184
10185 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10186 // parallel for is in combination with a distribute directive with
10187 // schedule(static, 1)
10188 Expr *BoundPrevUB = PrevUB.get();
10189 if (UseStrictCompare) {
10190 BoundPrevUB =
10191 SemaRef
10192 .BuildBinOp(
10193 S: CurScope, OpLoc: CondLoc, Opc: BO_Add, LHSExpr: BoundPrevUB,
10194 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get())
10195 .get();
10196 BoundPrevUB =
10197 SemaRef.ActOnFinishFullExpr(Expr: BoundPrevUB, /*DiscardedValue=*/false)
10198 .get();
10199 }
10200 ParForInDistCond =
10201 SemaRef.BuildBinOp(S: CurScope, OpLoc: CondLoc, Opc: UseStrictCompare ? BO_LT : BO_LE,
10202 LHSExpr: IV.get(), RHSExpr: BoundPrevUB);
10203 }
10204
10205 // Build updates and final values of the loop counters.
10206 bool HasErrors = false;
10207 Built.Counters.resize(N: NestedLoopCount);
10208 Built.Inits.resize(N: NestedLoopCount);
10209 Built.Updates.resize(N: NestedLoopCount);
10210 Built.Finals.resize(N: NestedLoopCount);
10211 Built.DependentCounters.resize(N: NestedLoopCount);
10212 Built.DependentInits.resize(N: NestedLoopCount);
10213 Built.FinalsConditions.resize(N: NestedLoopCount);
10214 {
10215 // We implement the following algorithm for obtaining the
10216 // original loop iteration variable values based on the
10217 // value of the collapsed loop iteration variable IV.
10218 //
10219 // Let n+1 be the number of collapsed loops in the nest.
10220 // Iteration variables (I0, I1, .... In)
10221 // Iteration counts (N0, N1, ... Nn)
10222 //
10223 // Acc = IV;
10224 //
10225 // To compute Ik for loop k, 0 <= k <= n, generate:
10226 // Prod = N(k+1) * N(k+2) * ... * Nn;
10227 // Ik = Acc / Prod;
10228 // Acc -= Ik * Prod;
10229 //
10230 ExprResult Acc = IV;
10231 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10232 LoopIterationSpace &IS = IterSpaces[Cnt];
10233 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10234 ExprResult Iter;
10235
10236 // Compute prod
10237 ExprResult Prod = SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get();
10238 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10239 Prod = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Mul, LHSExpr: Prod.get(),
10240 RHSExpr: IterSpaces[K].NumIterations);
10241
10242 // Iter = Acc / Prod
10243 // If there is at least one more inner loop to avoid
10244 // multiplication by 1.
10245 if (Cnt + 1 < NestedLoopCount)
10246 Iter =
10247 SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Div, LHSExpr: Acc.get(), RHSExpr: Prod.get());
10248 else
10249 Iter = Acc;
10250 if (!Iter.isUsable()) {
10251 HasErrors = true;
10252 break;
10253 }
10254
10255 // Update Acc:
10256 // Acc -= Iter * Prod
10257 // Check if there is at least one more inner loop to avoid
10258 // multiplication by 1.
10259 if (Cnt + 1 < NestedLoopCount)
10260 Prod = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Mul, LHSExpr: Iter.get(),
10261 RHSExpr: Prod.get());
10262 else
10263 Prod = Iter;
10264 Acc = SemaRef.BuildBinOp(S: CurScope, OpLoc: UpdLoc, Opc: BO_Sub, LHSExpr: Acc.get(), RHSExpr: Prod.get());
10265
10266 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10267 auto *VD = cast<VarDecl>(Val: cast<DeclRefExpr>(Val: IS.CounterVar)->getDecl());
10268 DeclRefExpr *CounterVar = buildDeclRefExpr(
10269 S&: SemaRef, D: VD, Ty: IS.CounterVar->getType(), Loc: IS.CounterVar->getExprLoc(),
10270 /*RefersToCapture=*/true);
10271 ExprResult Init =
10272 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10273 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10274 if (!Init.isUsable()) {
10275 HasErrors = true;
10276 break;
10277 }
10278 ExprResult Update = buildCounterUpdate(
10279 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10280 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10281 if (!Update.isUsable()) {
10282 HasErrors = true;
10283 break;
10284 }
10285
10286 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10287 ExprResult Final =
10288 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10289 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10290 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10291 if (!Final.isUsable()) {
10292 HasErrors = true;
10293 break;
10294 }
10295
10296 if (!Update.isUsable() || !Final.isUsable()) {
10297 HasErrors = true;
10298 break;
10299 }
10300 // Save results
10301 Built.Counters[Cnt] = IS.CounterVar;
10302 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10303 Built.Inits[Cnt] = Init.get();
10304 Built.Updates[Cnt] = Update.get();
10305 Built.Finals[Cnt] = Final.get();
10306 Built.DependentCounters[Cnt] = nullptr;
10307 Built.DependentInits[Cnt] = nullptr;
10308 Built.FinalsConditions[Cnt] = nullptr;
10309 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10310 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10311 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10312 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10313 }
10314 }
10315 }
10316
10317 if (HasErrors)
10318 return 0;
10319
10320 // Save results
10321 Built.IterationVarRef = IV.get();
10322 Built.LastIteration = LastIteration.get();
10323 Built.NumIterations = NumIterations.get();
10324 Built.CalcLastIteration = SemaRef
10325 .ActOnFinishFullExpr(Expr: CalcLastIteration.get(),
10326 /*DiscardedValue=*/false)
10327 .get();
10328 Built.PreCond = PreCond.get();
10329 Built.PreInits = buildPreInits(Context&: C, Captures);
10330 Built.Cond = Cond.get();
10331 Built.Init = Init.get();
10332 Built.Inc = Inc.get();
10333 Built.LB = LB.get();
10334 Built.UB = UB.get();
10335 Built.IL = IL.get();
10336 Built.ST = ST.get();
10337 Built.EUB = EUB.get();
10338 Built.NLB = NextLB.get();
10339 Built.NUB = NextUB.get();
10340 Built.PrevLB = PrevLB.get();
10341 Built.PrevUB = PrevUB.get();
10342 Built.DistInc = DistInc.get();
10343 Built.PrevEUB = PrevEUB.get();
10344 Built.DistCombinedFields.LB = CombLB.get();
10345 Built.DistCombinedFields.UB = CombUB.get();
10346 Built.DistCombinedFields.EUB = CombEUB.get();
10347 Built.DistCombinedFields.Init = CombInit.get();
10348 Built.DistCombinedFields.Cond = CombCond.get();
10349 Built.DistCombinedFields.NLB = CombNextLB.get();
10350 Built.DistCombinedFields.NUB = CombNextUB.get();
10351 Built.DistCombinedFields.DistCond = CombDistCond.get();
10352 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10353
10354 return NestedLoopCount;
10355}
10356
10357static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
10358 auto CollapseClauses =
10359 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10360 if (CollapseClauses.begin() != CollapseClauses.end())
10361 return (*CollapseClauses.begin())->getNumForLoops();
10362 return nullptr;
10363}
10364
10365static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
10366 auto OrderedClauses =
10367 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10368 if (OrderedClauses.begin() != OrderedClauses.end())
10369 return (*OrderedClauses.begin())->getNumForLoops();
10370 return nullptr;
10371}
10372
10373static bool checkSimdlenSafelenSpecified(Sema &S,
10374 const ArrayRef<OMPClause *> Clauses) {
10375 const OMPSafelenClause *Safelen = nullptr;
10376 const OMPSimdlenClause *Simdlen = nullptr;
10377
10378 for (const OMPClause *Clause : Clauses) {
10379 if (Clause->getClauseKind() == OMPC_safelen)
10380 Safelen = cast<OMPSafelenClause>(Val: Clause);
10381 else if (Clause->getClauseKind() == OMPC_simdlen)
10382 Simdlen = cast<OMPSimdlenClause>(Val: Clause);
10383 if (Safelen && Simdlen)
10384 break;
10385 }
10386
10387 if (Simdlen && Safelen) {
10388 const Expr *SimdlenLength = Simdlen->getSimdlen();
10389 const Expr *SafelenLength = Safelen->getSafelen();
10390 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10391 SimdlenLength->isInstantiationDependent() ||
10392 SimdlenLength->containsUnexpandedParameterPack())
10393 return false;
10394 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10395 SafelenLength->isInstantiationDependent() ||
10396 SafelenLength->containsUnexpandedParameterPack())
10397 return false;
10398 Expr::EvalResult SimdlenResult, SafelenResult;
10399 SimdlenLength->EvaluateAsInt(Result&: SimdlenResult, Ctx: S.Context);
10400 SafelenLength->EvaluateAsInt(Result&: SafelenResult, Ctx: S.Context);
10401 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10402 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10403 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10404 // If both simdlen and safelen clauses are specified, the value of the
10405 // simdlen parameter must be less than or equal to the value of the safelen
10406 // parameter.
10407 if (SimdlenRes > SafelenRes) {
10408 S.Diag(SimdlenLength->getExprLoc(),
10409 diag::err_omp_wrong_simdlen_safelen_values)
10410 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10411 return true;
10412 }
10413 }
10414 return false;
10415}
10416
10417StmtResult SemaOpenMP::ActOnOpenMPSimdDirective(
10418 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10419 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10420 if (!AStmt)
10421 return StmtError();
10422
10423 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10424
10425 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10426 OMPLoopBasedDirective::HelperExprs B;
10427 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10428 // define the nested loops number.
10429 unsigned NestedLoopCount = checkOpenMPLoop(
10430 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10431 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10432 if (NestedLoopCount == 0)
10433 return StmtError();
10434
10435 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10436 return StmtError();
10437
10438 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
10439 return StmtError();
10440
10441 auto *SimdDirective = OMPSimdDirective::Create(
10442 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10443 return SimdDirective;
10444}
10445
10446StmtResult SemaOpenMP::ActOnOpenMPForDirective(
10447 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10448 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10449 if (!AStmt)
10450 return StmtError();
10451
10452 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10453 OMPLoopBasedDirective::HelperExprs B;
10454 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10455 // define the nested loops number.
10456 unsigned NestedLoopCount = checkOpenMPLoop(
10457 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10458 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10459 if (NestedLoopCount == 0)
10460 return StmtError();
10461
10462 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10463 return StmtError();
10464
10465 auto *ForDirective = OMPForDirective::Create(
10466 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
10467 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10468 return ForDirective;
10469}
10470
10471StmtResult SemaOpenMP::ActOnOpenMPForSimdDirective(
10472 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10473 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10474 if (!AStmt)
10475 return StmtError();
10476
10477 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10478
10479 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10480 OMPLoopBasedDirective::HelperExprs B;
10481 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10482 // define the nested loops number.
10483 unsigned NestedLoopCount =
10484 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10485 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10486 VarsWithImplicitDSA, B);
10487 if (NestedLoopCount == 0)
10488 return StmtError();
10489
10490 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10491 return StmtError();
10492
10493 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
10494 return StmtError();
10495
10496 return OMPForSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
10497 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10498}
10499
10500static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind,
10501 Stmt *AStmt, DSAStackTy *Stack) {
10502 if (!AStmt)
10503 return true;
10504
10505 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10506 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
10507 auto BaseStmt = AStmt;
10508 while (auto *CS = dyn_cast_or_null<CapturedStmt>(Val: BaseStmt))
10509 BaseStmt = CS->getCapturedStmt();
10510 if (auto *C = dyn_cast_or_null<CompoundStmt>(Val: BaseStmt)) {
10511 auto S = C->children();
10512 if (S.begin() == S.end())
10513 return true;
10514 // All associated statements must be '#pragma omp section' except for
10515 // the first one.
10516 for (Stmt *SectionStmt : llvm::drop_begin(RangeOrContainer&: S)) {
10517 if (!SectionStmt || !isa<OMPSectionDirective>(Val: SectionStmt)) {
10518 if (SectionStmt)
10519 SemaRef.Diag(SectionStmt->getBeginLoc(),
10520 diag::err_omp_sections_substmt_not_section)
10521 << getOpenMPDirectiveName(DKind, OMPVersion);
10522 return true;
10523 }
10524 cast<OMPSectionDirective>(Val: SectionStmt)
10525 ->setHasCancel(Stack->isCancelRegion());
10526 }
10527 } else {
10528 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10529 << getOpenMPDirectiveName(DKind, OMPVersion);
10530 return true;
10531 }
10532 return false;
10533}
10534
10535StmtResult
10536SemaOpenMP::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
10537 Stmt *AStmt, SourceLocation StartLoc,
10538 SourceLocation EndLoc) {
10539 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10540 return StmtError();
10541
10542 SemaRef.setFunctionHasBranchProtectedScope();
10543
10544 return OMPSectionsDirective::Create(
10545 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
10546 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10547}
10548
10549StmtResult SemaOpenMP::ActOnOpenMPSectionDirective(Stmt *AStmt,
10550 SourceLocation StartLoc,
10551 SourceLocation EndLoc) {
10552 if (!AStmt)
10553 return StmtError();
10554
10555 SemaRef.setFunctionHasBranchProtectedScope();
10556 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10557
10558 return OMPSectionDirective::Create(C: getASTContext(), StartLoc, EndLoc, AssociatedStmt: AStmt,
10559 DSAStack->isCancelRegion());
10560}
10561
10562static Expr *getDirectCallExpr(Expr *E) {
10563 E = E->IgnoreParenCasts()->IgnoreImplicit();
10564 if (auto *CE = dyn_cast<CallExpr>(Val: E))
10565 if (CE->getDirectCallee())
10566 return E;
10567 return nullptr;
10568}
10569
10570StmtResult
10571SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
10572 Stmt *AStmt, SourceLocation StartLoc,
10573 SourceLocation EndLoc) {
10574 if (!AStmt)
10575 return StmtError();
10576
10577 Stmt *S = cast<CapturedStmt>(Val: AStmt)->getCapturedStmt();
10578
10579 // 5.1 OpenMP
10580 // expression-stmt : an expression statement with one of the following forms:
10581 // expression = target-call ( [expression-list] );
10582 // target-call ( [expression-list] );
10583
10584 SourceLocation TargetCallLoc;
10585
10586 if (!SemaRef.CurContext->isDependentContext()) {
10587 Expr *TargetCall = nullptr;
10588
10589 auto *E = dyn_cast<Expr>(Val: S);
10590 if (!E) {
10591 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10592 return StmtError();
10593 }
10594
10595 E = E->IgnoreParenCasts()->IgnoreImplicit();
10596
10597 if (auto *BO = dyn_cast<BinaryOperator>(Val: E)) {
10598 if (BO->getOpcode() == BO_Assign)
10599 TargetCall = getDirectCallExpr(E: BO->getRHS());
10600 } else {
10601 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(Val: E))
10602 if (COCE->getOperator() == OO_Equal)
10603 TargetCall = getDirectCallExpr(COCE->getArg(1));
10604 if (!TargetCall)
10605 TargetCall = getDirectCallExpr(E);
10606 }
10607 if (!TargetCall) {
10608 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10609 return StmtError();
10610 }
10611 TargetCallLoc = TargetCall->getExprLoc();
10612 }
10613
10614 SemaRef.setFunctionHasBranchProtectedScope();
10615
10616 return OMPDispatchDirective::Create(C: getASTContext(), StartLoc, EndLoc,
10617 Clauses, AssociatedStmt: AStmt, TargetCallLoc);
10618}
10619
10620static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
10621 OpenMPDirectiveKind K,
10622 DSAStackTy *Stack) {
10623 bool ErrorFound = false;
10624 for (OMPClause *C : Clauses) {
10625 if (auto *LPC = dyn_cast<OMPLastprivateClause>(Val: C)) {
10626 for (Expr *RefExpr : LPC->varlist()) {
10627 SourceLocation ELoc;
10628 SourceRange ERange;
10629 Expr *SimpleRefExpr = RefExpr;
10630 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10631 if (ValueDecl *D = Res.first) {
10632 auto &&Info = Stack->isLoopControlVariable(D);
10633 if (!Info.first) {
10634 unsigned OMPVersion = S.getLangOpts().OpenMP;
10635 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10636 << getOpenMPDirectiveName(K, OMPVersion);
10637 ErrorFound = true;
10638 }
10639 }
10640 }
10641 }
10642 }
10643 return ErrorFound;
10644}
10645
10646StmtResult SemaOpenMP::ActOnOpenMPGenericLoopDirective(
10647 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10648 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10649 if (!AStmt)
10650 return StmtError();
10651
10652 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10653 // A list item may not appear in a lastprivate clause unless it is the
10654 // loop iteration variable of a loop that is associated with the construct.
10655 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10656 return StmtError();
10657
10658 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10659
10660 OMPLoopDirective::HelperExprs B;
10661 // In presence of clause 'collapse', it will define the nested loops number.
10662 unsigned NestedLoopCount = checkOpenMPLoop(
10663 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10664 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10665 if (NestedLoopCount == 0)
10666 return StmtError();
10667
10668 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10669 "omp loop exprs were not built");
10670
10671 return OMPGenericLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
10672 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10673}
10674
10675StmtResult SemaOpenMP::ActOnOpenMPTeamsGenericLoopDirective(
10676 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10677 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10678 if (!AStmt)
10679 return StmtError();
10680
10681 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10682 // A list item may not appear in a lastprivate clause unless it is the
10683 // loop iteration variable of a loop that is associated with the construct.
10684 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10685 return StmtError();
10686
10687 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10688
10689 OMPLoopDirective::HelperExprs B;
10690 // In presence of clause 'collapse', it will define the nested loops number.
10691 unsigned NestedLoopCount =
10692 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10693 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10694 VarsWithImplicitDSA, B);
10695 if (NestedLoopCount == 0)
10696 return StmtError();
10697
10698 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10699 "omp loop exprs were not built");
10700
10701 DSAStack->setParentTeamsRegionLoc(StartLoc);
10702
10703 return OMPTeamsGenericLoopDirective::Create(
10704 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10705}
10706
10707StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsGenericLoopDirective(
10708 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10709 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10710 if (!AStmt)
10711 return StmtError();
10712
10713 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10714 // A list item may not appear in a lastprivate clause unless it is the
10715 // loop iteration variable of a loop that is associated with the construct.
10716 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10717 DSAStack))
10718 return StmtError();
10719
10720 CapturedStmt *CS =
10721 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10722
10723 OMPLoopDirective::HelperExprs B;
10724 // In presence of clause 'collapse', it will define the nested loops number.
10725 unsigned NestedLoopCount =
10726 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10727 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10728 VarsWithImplicitDSA, B);
10729 if (NestedLoopCount == 0)
10730 return StmtError();
10731
10732 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10733 "omp loop exprs were not built");
10734
10735 return OMPTargetTeamsGenericLoopDirective::Create(
10736 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
10737 CanBeParallelFor: teamsLoopCanBeParallelFor(AStmt, SemaRef));
10738}
10739
10740StmtResult SemaOpenMP::ActOnOpenMPParallelGenericLoopDirective(
10741 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10742 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10743 if (!AStmt)
10744 return StmtError();
10745
10746 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10747 // A list item may not appear in a lastprivate clause unless it is the
10748 // loop iteration variable of a loop that is associated with the construct.
10749 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
10750 DSAStack))
10751 return StmtError();
10752
10753 CapturedStmt *CS =
10754 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
10755
10756 OMPLoopDirective::HelperExprs B;
10757 // In presence of clause 'collapse', it will define the nested loops number.
10758 unsigned NestedLoopCount =
10759 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10760 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10761 VarsWithImplicitDSA, B);
10762 if (NestedLoopCount == 0)
10763 return StmtError();
10764
10765 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10766 "omp loop exprs were not built");
10767
10768 return OMPParallelGenericLoopDirective::Create(
10769 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10770}
10771
10772StmtResult SemaOpenMP::ActOnOpenMPTargetParallelGenericLoopDirective(
10773 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10774 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10775 if (!AStmt)
10776 return StmtError();
10777
10778 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10779 // A list item may not appear in a lastprivate clause unless it is the
10780 // loop iteration variable of a loop that is associated with the construct.
10781 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
10782 DSAStack))
10783 return StmtError();
10784
10785 CapturedStmt *CS =
10786 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
10787
10788 OMPLoopDirective::HelperExprs B;
10789 // In presence of clause 'collapse', it will define the nested loops number.
10790 unsigned NestedLoopCount =
10791 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10792 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10793 VarsWithImplicitDSA, B);
10794 if (NestedLoopCount == 0)
10795 return StmtError();
10796
10797 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10798 "omp loop exprs were not built");
10799
10800 return OMPTargetParallelGenericLoopDirective::Create(
10801 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10802}
10803
10804StmtResult SemaOpenMP::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
10805 Stmt *AStmt,
10806 SourceLocation StartLoc,
10807 SourceLocation EndLoc) {
10808 if (!AStmt)
10809 return StmtError();
10810
10811 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10812
10813 SemaRef.setFunctionHasBranchProtectedScope();
10814
10815 // OpenMP [2.7.3, single Construct, Restrictions]
10816 // The copyprivate clause must not be used with the nowait clause.
10817 const OMPClause *Nowait = nullptr;
10818 const OMPClause *Copyprivate = nullptr;
10819 for (const OMPClause *Clause : Clauses) {
10820 if (Clause->getClauseKind() == OMPC_nowait)
10821 Nowait = Clause;
10822 else if (Clause->getClauseKind() == OMPC_copyprivate)
10823 Copyprivate = Clause;
10824 if (Copyprivate && Nowait) {
10825 Diag(Copyprivate->getBeginLoc(),
10826 diag::err_omp_single_copyprivate_with_nowait);
10827 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10828 return StmtError();
10829 }
10830 }
10831
10832 return OMPSingleDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
10833 AssociatedStmt: AStmt);
10834}
10835
10836StmtResult SemaOpenMP::ActOnOpenMPMasterDirective(Stmt *AStmt,
10837 SourceLocation StartLoc,
10838 SourceLocation EndLoc) {
10839 if (!AStmt)
10840 return StmtError();
10841
10842 SemaRef.setFunctionHasBranchProtectedScope();
10843
10844 return OMPMasterDirective::Create(C: getASTContext(), StartLoc, EndLoc, AssociatedStmt: AStmt);
10845}
10846
10847StmtResult SemaOpenMP::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
10848 Stmt *AStmt,
10849 SourceLocation StartLoc,
10850 SourceLocation EndLoc) {
10851 if (!AStmt)
10852 return StmtError();
10853
10854 SemaRef.setFunctionHasBranchProtectedScope();
10855
10856 return OMPMaskedDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
10857 AssociatedStmt: AStmt);
10858}
10859
10860StmtResult SemaOpenMP::ActOnOpenMPCriticalDirective(
10861 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
10862 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
10863 if (!AStmt)
10864 return StmtError();
10865
10866 bool ErrorFound = false;
10867 llvm::APSInt Hint;
10868 SourceLocation HintLoc;
10869 bool DependentHint = false;
10870 for (const OMPClause *C : Clauses) {
10871 if (C->getClauseKind() == OMPC_hint) {
10872 if (!DirName.getName()) {
10873 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10874 ErrorFound = true;
10875 }
10876 Expr *E = cast<OMPHintClause>(Val: C)->getHint();
10877 if (E->isTypeDependent() || E->isValueDependent() ||
10878 E->isInstantiationDependent()) {
10879 DependentHint = true;
10880 } else {
10881 Hint = E->EvaluateKnownConstInt(Ctx: getASTContext());
10882 HintLoc = C->getBeginLoc();
10883 }
10884 }
10885 }
10886 if (ErrorFound)
10887 return StmtError();
10888 const auto Pair = DSAStack->getCriticalWithHint(Name: DirName);
10889 if (Pair.first && DirName.getName() && !DependentHint) {
10890 if (llvm::APSInt::compareValues(I1: Hint, I2: Pair.second) != 0) {
10891 Diag(StartLoc, diag::err_omp_critical_with_hint);
10892 if (HintLoc.isValid())
10893 Diag(HintLoc, diag::note_omp_critical_hint_here)
10894 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
10895 else
10896 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10897 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
10898 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
10899 << 1
10900 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
10901 /*Radix=*/10, /*Signed=*/false);
10902 } else {
10903 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10904 }
10905 }
10906 }
10907
10908 SemaRef.setFunctionHasBranchProtectedScope();
10909
10910 auto *Dir = OMPCriticalDirective::Create(C: getASTContext(), Name: DirName, StartLoc,
10911 EndLoc, Clauses, AssociatedStmt: AStmt);
10912 if (!Pair.first && DirName.getName() && !DependentHint)
10913 DSAStack->addCriticalWithHint(D: Dir, Hint);
10914 return Dir;
10915}
10916
10917StmtResult SemaOpenMP::ActOnOpenMPParallelForDirective(
10918 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10919 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10920 if (!AStmt)
10921 return StmtError();
10922
10923 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
10924
10925 OMPLoopBasedDirective::HelperExprs B;
10926 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10927 // define the nested loops number.
10928 unsigned NestedLoopCount =
10929 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
10930 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
10931 VarsWithImplicitDSA, B);
10932 if (NestedLoopCount == 0)
10933 return StmtError();
10934
10935 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10936 return StmtError();
10937
10938 return OMPParallelForDirective::Create(
10939 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
10940 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10941}
10942
10943StmtResult SemaOpenMP::ActOnOpenMPParallelForSimdDirective(
10944 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10945 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10946 if (!AStmt)
10947 return StmtError();
10948
10949 CapturedStmt *CS =
10950 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
10951
10952 OMPLoopBasedDirective::HelperExprs B;
10953 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10954 // define the nested loops number.
10955 unsigned NestedLoopCount =
10956 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
10957 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10958 VarsWithImplicitDSA, B);
10959 if (NestedLoopCount == 0)
10960 return StmtError();
10961
10962 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10963 return StmtError();
10964
10965 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
10966 return StmtError();
10967
10968 return OMPParallelForSimdDirective::Create(
10969 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
10970}
10971
10972StmtResult SemaOpenMP::ActOnOpenMPParallelMasterDirective(
10973 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10974 SourceLocation EndLoc) {
10975 if (!AStmt)
10976 return StmtError();
10977
10978 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
10979
10980 return OMPParallelMasterDirective::Create(
10981 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
10982 DSAStack->getTaskgroupReductionRef());
10983}
10984
10985StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedDirective(
10986 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10987 SourceLocation EndLoc) {
10988 if (!AStmt)
10989 return StmtError();
10990
10991 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
10992
10993 return OMPParallelMaskedDirective::Create(
10994 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
10995 DSAStack->getTaskgroupReductionRef());
10996}
10997
10998StmtResult SemaOpenMP::ActOnOpenMPParallelSectionsDirective(
10999 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11000 SourceLocation EndLoc) {
11001 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
11002 return StmtError();
11003
11004 SemaRef.setFunctionHasBranchProtectedScope();
11005
11006 return OMPParallelSectionsDirective::Create(
11007 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
11008 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11009}
11010
11011/// Find and diagnose mutually exclusive clause kinds.
11012static bool checkMutuallyExclusiveClauses(
11013 Sema &S, ArrayRef<OMPClause *> Clauses,
11014 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11015 const OMPClause *PrevClause = nullptr;
11016 bool ErrorFound = false;
11017 for (const OMPClause *C : Clauses) {
11018 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11019 if (!PrevClause) {
11020 PrevClause = C;
11021 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11022 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11023 << getOpenMPClauseNameForDiag(C->getClauseKind())
11024 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11025 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11026 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11027 ErrorFound = true;
11028 }
11029 }
11030 }
11031 return ErrorFound;
11032}
11033
11034StmtResult SemaOpenMP::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
11035 Stmt *AStmt,
11036 SourceLocation StartLoc,
11037 SourceLocation EndLoc) {
11038 if (!AStmt)
11039 return StmtError();
11040
11041 // OpenMP 5.0, 2.10.1 task Construct
11042 // If a detach clause appears on the directive, then a mergeable clause cannot
11043 // appear on the same directive.
11044 if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
11045 {OMPC_detach, OMPC_mergeable}))
11046 return StmtError();
11047
11048 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
11049
11050 return OMPTaskDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11051 AssociatedStmt: AStmt, DSAStack->isCancelRegion());
11052}
11053
11054StmtResult SemaOpenMP::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
11055 SourceLocation EndLoc) {
11056 return OMPTaskyieldDirective::Create(C: getASTContext(), StartLoc, EndLoc);
11057}
11058
11059StmtResult SemaOpenMP::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
11060 SourceLocation EndLoc) {
11061 return OMPBarrierDirective::Create(C: getASTContext(), StartLoc, EndLoc);
11062}
11063
11064StmtResult SemaOpenMP::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
11065 SourceLocation StartLoc,
11066 SourceLocation EndLoc,
11067 bool InExContext) {
11068 const OMPAtClause *AtC =
11069 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11070
11071 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11072 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11073 return StmtError();
11074 }
11075
11076 const OMPSeverityClause *SeverityC =
11077 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11078 const OMPMessageClause *MessageC =
11079 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11080 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11081
11082 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11083 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11084 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11085 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
11086 else
11087 Diag(StartLoc, diag::err_diagnose_if_succeeded)
11088 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
11089 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11090 return StmtError();
11091 }
11092 return OMPErrorDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11093}
11094
11095StmtResult
11096SemaOpenMP::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
11097 SourceLocation StartLoc,
11098 SourceLocation EndLoc) {
11099 const OMPNowaitClause *NowaitC =
11100 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11101 bool HasDependC =
11102 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11103 .empty();
11104 if (NowaitC && !HasDependC) {
11105 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11106 return StmtError();
11107 }
11108
11109 return OMPTaskwaitDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11110 Clauses);
11111}
11112
11113StmtResult
11114SemaOpenMP::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
11115 Stmt *AStmt, SourceLocation StartLoc,
11116 SourceLocation EndLoc) {
11117 if (!AStmt)
11118 return StmtError();
11119
11120 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11121
11122 SemaRef.setFunctionHasBranchProtectedScope();
11123
11124 return OMPTaskgroupDirective::Create(C: getASTContext(), StartLoc, EndLoc,
11125 Clauses, AssociatedStmt: AStmt,
11126 DSAStack->getTaskgroupReductionRef());
11127}
11128
11129StmtResult SemaOpenMP::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
11130 SourceLocation StartLoc,
11131 SourceLocation EndLoc) {
11132 OMPFlushClause *FC = nullptr;
11133 OMPClause *OrderClause = nullptr;
11134 for (OMPClause *C : Clauses) {
11135 if (C->getClauseKind() == OMPC_flush)
11136 FC = cast<OMPFlushClause>(Val: C);
11137 else
11138 OrderClause = C;
11139 }
11140 unsigned OMPVersion = getLangOpts().OpenMP;
11141 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11142 SourceLocation MemOrderLoc;
11143 for (const OMPClause *C : Clauses) {
11144 if (C->getClauseKind() == OMPC_acq_rel ||
11145 C->getClauseKind() == OMPC_acquire ||
11146 C->getClauseKind() == OMPC_release ||
11147 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11148 if (MemOrderKind != OMPC_unknown) {
11149 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11150 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11151 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11152 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11153 << getOpenMPClauseNameForDiag(MemOrderKind);
11154 } else {
11155 MemOrderKind = C->getClauseKind();
11156 MemOrderLoc = C->getBeginLoc();
11157 }
11158 }
11159 }
11160 if (FC && OrderClause) {
11161 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11162 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11163 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11164 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11165 return StmtError();
11166 }
11167 return OMPFlushDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11168}
11169
11170StmtResult SemaOpenMP::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
11171 SourceLocation StartLoc,
11172 SourceLocation EndLoc) {
11173 if (Clauses.empty()) {
11174 Diag(StartLoc, diag::err_omp_depobj_expected);
11175 return StmtError();
11176 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11177 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11178 return StmtError();
11179 }
11180 // Only depobj expression and another single clause is allowed.
11181 if (Clauses.size() > 2) {
11182 Diag(Clauses[2]->getBeginLoc(),
11183 diag::err_omp_depobj_single_clause_expected);
11184 return StmtError();
11185 } else if (Clauses.size() < 1) {
11186 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11187 return StmtError();
11188 }
11189 return OMPDepobjDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11190}
11191
11192StmtResult SemaOpenMP::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
11193 SourceLocation StartLoc,
11194 SourceLocation EndLoc) {
11195 // Check that exactly one clause is specified.
11196 if (Clauses.size() != 1) {
11197 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11198 diag::err_omp_scan_single_clause_expected);
11199 return StmtError();
11200 }
11201 // Check that scan directive is used in the scope of the OpenMP loop body.
11202 if (Scope *S = DSAStack->getCurScope()) {
11203 Scope *ParentS = S->getParent();
11204 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11205 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11206 unsigned OMPVersion = getLangOpts().OpenMP;
11207 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11208 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11209 }
11210 }
11211 // Check that only one instance of scan directives is used in the same outer
11212 // region.
11213 if (DSAStack->doesParentHasScanDirective()) {
11214 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11215 Diag(DSAStack->getParentScanDirectiveLoc(),
11216 diag::note_omp_previous_directive)
11217 << "scan";
11218 return StmtError();
11219 }
11220 DSAStack->setParentHasScanDirective(StartLoc);
11221 return OMPScanDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses);
11222}
11223
11224StmtResult
11225SemaOpenMP::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
11226 Stmt *AStmt, SourceLocation StartLoc,
11227 SourceLocation EndLoc) {
11228 const OMPClause *DependFound = nullptr;
11229 const OMPClause *DependSourceClause = nullptr;
11230 const OMPClause *DependSinkClause = nullptr;
11231 const OMPClause *DoacrossFound = nullptr;
11232 const OMPClause *DoacrossSourceClause = nullptr;
11233 const OMPClause *DoacrossSinkClause = nullptr;
11234 bool ErrorFound = false;
11235 const OMPThreadsClause *TC = nullptr;
11236 const OMPSIMDClause *SC = nullptr;
11237 for (const OMPClause *C : Clauses) {
11238 auto DOC = dyn_cast<OMPDoacrossClause>(Val: C);
11239 auto DC = dyn_cast<OMPDependClause>(Val: C);
11240 if (DC || DOC) {
11241 DependFound = DC ? C : nullptr;
11242 DoacrossFound = DOC ? C : nullptr;
11243 OMPDoacrossKind ODK;
11244 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11245 (DOC && (ODK.isSource(C: DOC)))) {
11246 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11247 unsigned OMPVersion = getLangOpts().OpenMP;
11248 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11249 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11250 << getOpenMPClauseNameForDiag(DC ? OMPC_depend : OMPC_doacross)
11251 << 2;
11252 ErrorFound = true;
11253 } else {
11254 if (DC)
11255 DependSourceClause = C;
11256 else
11257 DoacrossSourceClause = C;
11258 }
11259 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11260 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11261 << (DC ? "depend" : "doacross") << 0;
11262 ErrorFound = true;
11263 }
11264 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11265 (DOC && (ODK.isSink(C: DOC) || ODK.isSinkIter(C: DOC)))) {
11266 if (DependSourceClause || DoacrossSourceClause) {
11267 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11268 << (DC ? "depend" : "doacross") << 1;
11269 ErrorFound = true;
11270 }
11271 if (DC)
11272 DependSinkClause = C;
11273 else
11274 DoacrossSinkClause = C;
11275 }
11276 } else if (C->getClauseKind() == OMPC_threads) {
11277 TC = cast<OMPThreadsClause>(Val: C);
11278 } else if (C->getClauseKind() == OMPC_simd) {
11279 SC = cast<OMPSIMDClause>(Val: C);
11280 }
11281 }
11282 if (!ErrorFound && !SC &&
11283 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11284 // OpenMP [2.8.1,simd Construct, Restrictions]
11285 // An ordered construct with the simd clause is the only OpenMP construct
11286 // that can appear in the simd region.
11287 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11288 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11289 ErrorFound = true;
11290 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11291 SourceLocation Loc =
11292 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11293 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11294 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend : OMPC_doacross)
11295 << getOpenMPClauseNameForDiag(TC ? TC->getClauseKind()
11296 : SC->getClauseKind());
11297 ErrorFound = true;
11298 } else if ((DependFound || DoacrossFound) &&
11299 !DSAStack->getParentOrderedRegionParam().first) {
11300 SourceLocation Loc =
11301 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11302 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11303 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend
11304 : OMPC_doacross);
11305 ErrorFound = true;
11306 } else if (TC || Clauses.empty()) {
11307 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11308 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11309 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11310 << (TC != nullptr);
11311 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11312 ErrorFound = true;
11313 }
11314 }
11315 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11316 return StmtError();
11317
11318 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11319 // During execution of an iteration of a worksharing-loop or a loop nest
11320 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11321 // must not execute more than one ordered region corresponding to an ordered
11322 // construct without a depend clause.
11323 if (!DependFound && !DoacrossFound) {
11324 if (DSAStack->doesParentHasOrderedDirective()) {
11325 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11326 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11327 diag::note_omp_previous_directive)
11328 << "ordered";
11329 return StmtError();
11330 }
11331 DSAStack->setParentHasOrderedDirective(StartLoc);
11332 }
11333
11334 if (AStmt) {
11335 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11336
11337 SemaRef.setFunctionHasBranchProtectedScope();
11338 }
11339
11340 return OMPOrderedDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
11341 AssociatedStmt: AStmt);
11342}
11343
11344namespace {
11345/// Helper class for checking expression in 'omp atomic [update]'
11346/// construct.
11347class OpenMPAtomicUpdateChecker {
11348 /// Error results for atomic update expressions.
11349 enum ExprAnalysisErrorCode {
11350 /// A statement is not an expression statement.
11351 NotAnExpression,
11352 /// Expression is not builtin binary or unary operation.
11353 NotABinaryOrUnaryExpression,
11354 /// Unary operation is not post-/pre- increment/decrement operation.
11355 NotAnUnaryIncDecExpression,
11356 /// An expression is not of scalar type.
11357 NotAScalarType,
11358 /// A binary operation is not an assignment operation.
11359 NotAnAssignmentOp,
11360 /// RHS part of the binary operation is not a binary expression.
11361 NotABinaryExpression,
11362 /// RHS part is not additive/multiplicative/shift/bitwise binary
11363 /// expression.
11364 NotABinaryOperator,
11365 /// RHS binary operation does not have reference to the updated LHS
11366 /// part.
11367 NotAnUpdateExpression,
11368 /// An expression contains semantical error not related to
11369 /// 'omp atomic [update]'
11370 NotAValidExpression,
11371 /// No errors is found.
11372 NoError
11373 };
11374 /// Reference to Sema.
11375 Sema &SemaRef;
11376 /// A location for note diagnostics (when error is found).
11377 SourceLocation NoteLoc;
11378 /// 'x' lvalue part of the source atomic expression.
11379 Expr *X;
11380 /// 'expr' rvalue part of the source atomic expression.
11381 Expr *E;
11382 /// Helper expression of the form
11383 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11384 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11385 Expr *UpdateExpr;
11386 /// Is 'x' a LHS in a RHS part of full update expression. It is
11387 /// important for non-associative operations.
11388 bool IsXLHSInRHSPart;
11389 BinaryOperatorKind Op;
11390 SourceLocation OpLoc;
11391 /// true if the source expression is a postfix unary operation, false
11392 /// if it is a prefix unary operation.
11393 bool IsPostfixUpdate;
11394
11395public:
11396 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11397 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11398 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11399 /// Check specified statement that it is suitable for 'atomic update'
11400 /// constructs and extract 'x', 'expr' and Operation from the original
11401 /// expression. If DiagId and NoteId == 0, then only check is performed
11402 /// without error notification.
11403 /// \param DiagId Diagnostic which should be emitted if error is found.
11404 /// \param NoteId Diagnostic note for the main error message.
11405 /// \return true if statement is not an update expression, false otherwise.
11406 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11407 /// Return the 'x' lvalue part of the source atomic expression.
11408 Expr *getX() const { return X; }
11409 /// Return the 'expr' rvalue part of the source atomic expression.
11410 Expr *getExpr() const { return E; }
11411 /// Return the update expression used in calculation of the updated
11412 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11413 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11414 Expr *getUpdateExpr() const { return UpdateExpr; }
11415 /// Return true if 'x' is LHS in RHS part of full update expression,
11416 /// false otherwise.
11417 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11418
11419 /// true if the source expression is a postfix unary operation, false
11420 /// if it is a prefix unary operation.
11421 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11422
11423private:
11424 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11425 unsigned NoteId = 0);
11426};
11427
11428bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11429 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11430 ExprAnalysisErrorCode ErrorFound = NoError;
11431 SourceLocation ErrorLoc, NoteLoc;
11432 SourceRange ErrorRange, NoteRange;
11433 // Allowed constructs are:
11434 // x = x binop expr;
11435 // x = expr binop x;
11436 if (AtomicBinOp->getOpcode() == BO_Assign) {
11437 X = AtomicBinOp->getLHS();
11438 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11439 Val: AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11440 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11441 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11442 AtomicInnerBinOp->isBitwiseOp()) {
11443 Op = AtomicInnerBinOp->getOpcode();
11444 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11445 Expr *LHS = AtomicInnerBinOp->getLHS();
11446 Expr *RHS = AtomicInnerBinOp->getRHS();
11447 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11448 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11449 /*Canonical=*/true);
11450 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11451 /*Canonical=*/true);
11452 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11453 /*Canonical=*/true);
11454 if (XId == LHSId) {
11455 E = RHS;
11456 IsXLHSInRHSPart = true;
11457 } else if (XId == RHSId) {
11458 E = LHS;
11459 IsXLHSInRHSPart = false;
11460 } else {
11461 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11462 ErrorRange = AtomicInnerBinOp->getSourceRange();
11463 NoteLoc = X->getExprLoc();
11464 NoteRange = X->getSourceRange();
11465 ErrorFound = NotAnUpdateExpression;
11466 }
11467 } else {
11468 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11469 ErrorRange = AtomicInnerBinOp->getSourceRange();
11470 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11471 NoteRange = SourceRange(NoteLoc, NoteLoc);
11472 ErrorFound = NotABinaryOperator;
11473 }
11474 } else {
11475 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11476 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11477 ErrorFound = NotABinaryExpression;
11478 }
11479 } else {
11480 ErrorLoc = AtomicBinOp->getExprLoc();
11481 ErrorRange = AtomicBinOp->getSourceRange();
11482 NoteLoc = AtomicBinOp->getOperatorLoc();
11483 NoteRange = SourceRange(NoteLoc, NoteLoc);
11484 ErrorFound = NotAnAssignmentOp;
11485 }
11486 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11487 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11488 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11489 return true;
11490 }
11491 if (SemaRef.CurContext->isDependentContext())
11492 E = X = UpdateExpr = nullptr;
11493 return ErrorFound != NoError;
11494}
11495
11496bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11497 unsigned NoteId) {
11498 ExprAnalysisErrorCode ErrorFound = NoError;
11499 SourceLocation ErrorLoc, NoteLoc;
11500 SourceRange ErrorRange, NoteRange;
11501 // Allowed constructs are:
11502 // x++;
11503 // x--;
11504 // ++x;
11505 // --x;
11506 // x binop= expr;
11507 // x = x binop expr;
11508 // x = expr binop x;
11509 if (auto *AtomicBody = dyn_cast<Expr>(Val: S)) {
11510 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11511 if (AtomicBody->getType()->isScalarType() ||
11512 AtomicBody->isInstantiationDependent()) {
11513 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11514 Val: AtomicBody->IgnoreParenImpCasts())) {
11515 // Check for Compound Assignment Operation
11516 Op = BinaryOperator::getOpForCompoundAssignment(
11517 Opc: AtomicCompAssignOp->getOpcode());
11518 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11519 E = AtomicCompAssignOp->getRHS();
11520 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11521 IsXLHSInRHSPart = true;
11522 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11523 Val: AtomicBody->IgnoreParenImpCasts())) {
11524 // Check for Binary Operation
11525 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11526 return true;
11527 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11528 Val: AtomicBody->IgnoreParenImpCasts())) {
11529 // Check for Unary Operation
11530 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11531 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11532 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11533 OpLoc = AtomicUnaryOp->getOperatorLoc();
11534 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11535 E = SemaRef.ActOnIntegerConstant(Loc: OpLoc, /*uint64_t Val=*/Val: 1).get();
11536 IsXLHSInRHSPart = true;
11537 } else {
11538 ErrorFound = NotAnUnaryIncDecExpression;
11539 ErrorLoc = AtomicUnaryOp->getExprLoc();
11540 ErrorRange = AtomicUnaryOp->getSourceRange();
11541 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11542 NoteRange = SourceRange(NoteLoc, NoteLoc);
11543 }
11544 } else if (!AtomicBody->isInstantiationDependent()) {
11545 ErrorFound = NotABinaryOrUnaryExpression;
11546 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11547 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11548 } else if (AtomicBody->containsErrors()) {
11549 ErrorFound = NotAValidExpression;
11550 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11551 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11552 }
11553 } else {
11554 ErrorFound = NotAScalarType;
11555 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11556 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11557 }
11558 } else {
11559 ErrorFound = NotAnExpression;
11560 NoteLoc = ErrorLoc = S->getBeginLoc();
11561 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11562 }
11563 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11564 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11565 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11566 return true;
11567 }
11568 if (SemaRef.CurContext->isDependentContext())
11569 E = X = UpdateExpr = nullptr;
11570 if (ErrorFound == NoError && E && X) {
11571 // Build an update expression of form 'OpaqueValueExpr(x) binop
11572 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11573 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11574 auto *OVEX = new (SemaRef.getASTContext())
11575 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11576 auto *OVEExpr = new (SemaRef.getASTContext())
11577 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
11578 ExprResult Update =
11579 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11580 IsXLHSInRHSPart ? OVEExpr : OVEX);
11581 if (Update.isInvalid())
11582 return true;
11583 Update = SemaRef.PerformImplicitConversion(From: Update.get(), ToType: X->getType(),
11584 Action: AssignmentAction::Casting);
11585 if (Update.isInvalid())
11586 return true;
11587 UpdateExpr = Update.get();
11588 }
11589 return ErrorFound != NoError;
11590}
11591
11592/// Get the node id of the fixed point of an expression \a S.
11593llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11594 llvm::FoldingSetNodeID Id;
11595 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11596 return Id;
11597}
11598
11599/// Check if two expressions are same.
11600bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11601 const Expr *RHS) {
11602 return getNodeId(Context, S: LHS) == getNodeId(Context, S: RHS);
11603}
11604
11605class OpenMPAtomicCompareChecker {
11606public:
11607 /// All kinds of errors that can occur in `atomic compare`
11608 enum ErrorTy {
11609 /// Empty compound statement.
11610 NoStmt = 0,
11611 /// More than one statement in a compound statement.
11612 MoreThanOneStmt,
11613 /// Not an assignment binary operator.
11614 NotAnAssignment,
11615 /// Not a conditional operator.
11616 NotCondOp,
11617 /// Wrong false expr. According to the spec, 'x' should be at the false
11618 /// expression of a conditional expression.
11619 WrongFalseExpr,
11620 /// The condition of a conditional expression is not a binary operator.
11621 NotABinaryOp,
11622 /// Invalid binary operator (not <, >, or ==).
11623 InvalidBinaryOp,
11624 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11625 InvalidComparison,
11626 /// X is not a lvalue.
11627 XNotLValue,
11628 /// Not a scalar.
11629 NotScalar,
11630 /// Not an integer.
11631 NotInteger,
11632 /// 'else' statement is not expected.
11633 UnexpectedElse,
11634 /// Not an equality operator.
11635 NotEQ,
11636 /// Invalid assignment (not v == x).
11637 InvalidAssignment,
11638 /// Not if statement
11639 NotIfStmt,
11640 /// More than two statements in a compound statement.
11641 MoreThanTwoStmts,
11642 /// Not a compound statement.
11643 NotCompoundStmt,
11644 /// No else statement.
11645 NoElse,
11646 /// Not 'if (r)'.
11647 InvalidCondition,
11648 /// No error.
11649 NoError,
11650 };
11651
11652 struct ErrorInfoTy {
11653 ErrorTy Error;
11654 SourceLocation ErrorLoc;
11655 SourceRange ErrorRange;
11656 SourceLocation NoteLoc;
11657 SourceRange NoteRange;
11658 };
11659
11660 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11661
11662 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11663 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11664
11665 Expr *getX() const { return X; }
11666 Expr *getE() const { return E; }
11667 Expr *getD() const { return D; }
11668 Expr *getCond() const { return C; }
11669 bool isXBinopExpr() const { return IsXBinopExpr; }
11670
11671protected:
11672 /// Reference to ASTContext
11673 ASTContext &ContextRef;
11674 /// 'x' lvalue part of the source atomic expression.
11675 Expr *X = nullptr;
11676 /// 'expr' or 'e' rvalue part of the source atomic expression.
11677 Expr *E = nullptr;
11678 /// 'd' rvalue part of the source atomic expression.
11679 Expr *D = nullptr;
11680 /// 'cond' part of the source atomic expression. It is in one of the following
11681 /// forms:
11682 /// expr ordop x
11683 /// x ordop expr
11684 /// x == e
11685 /// e == x
11686 Expr *C = nullptr;
11687 /// True if the cond expr is in the form of 'x ordop expr'.
11688 bool IsXBinopExpr = true;
11689
11690 /// Check if it is a valid conditional update statement (cond-update-stmt).
11691 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11692
11693 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11694 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11695
11696 /// Check if all captured values have right type.
11697 bool checkType(ErrorInfoTy &ErrorInfo) const;
11698
11699 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11700 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11701 if (E->isInstantiationDependent())
11702 return true;
11703
11704 if (ShouldBeLValue && !E->isLValue()) {
11705 ErrorInfo.Error = ErrorTy::XNotLValue;
11706 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11707 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11708 return false;
11709 }
11710
11711 QualType QTy = E->getType();
11712 if (!QTy->isScalarType()) {
11713 ErrorInfo.Error = ErrorTy::NotScalar;
11714 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11715 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11716 return false;
11717 }
11718 if (ShouldBeInteger && !QTy->isIntegerType()) {
11719 ErrorInfo.Error = ErrorTy::NotInteger;
11720 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11721 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11722 return false;
11723 }
11724
11725 return true;
11726 }
11727};
11728
11729bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11730 ErrorInfoTy &ErrorInfo) {
11731 auto *Then = S->getThen();
11732 if (auto *CS = dyn_cast<CompoundStmt>(Val: Then)) {
11733 if (CS->body_empty()) {
11734 ErrorInfo.Error = ErrorTy::NoStmt;
11735 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11736 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11737 return false;
11738 }
11739 if (CS->size() > 1) {
11740 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11741 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11742 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11743 return false;
11744 }
11745 Then = CS->body_front();
11746 }
11747
11748 auto *BO = dyn_cast<BinaryOperator>(Val: Then);
11749 if (!BO) {
11750 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11751 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11752 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11753 return false;
11754 }
11755 if (BO->getOpcode() != BO_Assign) {
11756 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11757 ErrorInfo.ErrorLoc = BO->getExprLoc();
11758 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11759 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11760 return false;
11761 }
11762
11763 X = BO->getLHS();
11764
11765 auto *Cond = dyn_cast<BinaryOperator>(Val: S->getCond());
11766 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: S->getCond());
11767 Expr *LHS = nullptr;
11768 Expr *RHS = nullptr;
11769 if (Cond) {
11770 LHS = Cond->getLHS();
11771 RHS = Cond->getRHS();
11772 } else if (Call) {
11773 LHS = Call->getArg(0);
11774 RHS = Call->getArg(1);
11775 } else {
11776 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11777 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11778 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11779 return false;
11780 }
11781
11782 if ((Cond && Cond->getOpcode() == BO_EQ) ||
11783 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
11784 C = S->getCond();
11785 D = BO->getRHS();
11786 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
11787 E = RHS;
11788 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
11789 E = LHS;
11790 } else {
11791 ErrorInfo.Error = ErrorTy::InvalidComparison;
11792 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11793 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11794 S->getCond()->getSourceRange();
11795 return false;
11796 }
11797 } else if ((Cond &&
11798 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
11799 (Call &&
11800 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
11801 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
11802 E = BO->getRHS();
11803 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS) &&
11804 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS)) {
11805 C = S->getCond();
11806 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: LHS) &&
11807 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
11808 C = S->getCond();
11809 IsXBinopExpr = false;
11810 } else {
11811 ErrorInfo.Error = ErrorTy::InvalidComparison;
11812 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11813 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11814 S->getCond()->getSourceRange();
11815 return false;
11816 }
11817 } else {
11818 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11819 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11820 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11821 return false;
11822 }
11823
11824 if (S->getElse()) {
11825 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11826 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11827 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11828 return false;
11829 }
11830
11831 return true;
11832}
11833
11834bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
11835 ErrorInfoTy &ErrorInfo) {
11836 auto *BO = dyn_cast<BinaryOperator>(Val: S);
11837 if (!BO) {
11838 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11839 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11840 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11841 return false;
11842 }
11843 if (BO->getOpcode() != BO_Assign) {
11844 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11845 ErrorInfo.ErrorLoc = BO->getExprLoc();
11846 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11847 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11848 return false;
11849 }
11850
11851 X = BO->getLHS();
11852
11853 auto *CO = dyn_cast<ConditionalOperator>(Val: BO->getRHS()->IgnoreParenImpCasts());
11854 if (!CO) {
11855 ErrorInfo.Error = ErrorTy::NotCondOp;
11856 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11857 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11858 return false;
11859 }
11860
11861 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: CO->getFalseExpr())) {
11862 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11863 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11864 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11865 CO->getFalseExpr()->getSourceRange();
11866 return false;
11867 }
11868
11869 auto *Cond = dyn_cast<BinaryOperator>(Val: CO->getCond());
11870 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: CO->getCond());
11871 Expr *LHS = nullptr;
11872 Expr *RHS = nullptr;
11873 if (Cond) {
11874 LHS = Cond->getLHS();
11875 RHS = Cond->getRHS();
11876 } else if (Call) {
11877 LHS = Call->getArg(0);
11878 RHS = Call->getArg(1);
11879 } else {
11880 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11881 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11882 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11883 CO->getCond()->getSourceRange();
11884 return false;
11885 }
11886
11887 if ((Cond && Cond->getOpcode() == BO_EQ) ||
11888 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
11889 C = CO->getCond();
11890 D = CO->getTrueExpr();
11891 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
11892 E = RHS;
11893 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
11894 E = LHS;
11895 } else {
11896 ErrorInfo.Error = ErrorTy::InvalidComparison;
11897 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11898 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11899 CO->getCond()->getSourceRange();
11900 return false;
11901 }
11902 } else if ((Cond &&
11903 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
11904 (Call &&
11905 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
11906 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
11907
11908 E = CO->getTrueExpr();
11909 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS) &&
11910 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS)) {
11911 C = CO->getCond();
11912 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: E, RHS: LHS) &&
11913 checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
11914 C = CO->getCond();
11915 IsXBinopExpr = false;
11916 } else {
11917 ErrorInfo.Error = ErrorTy::InvalidComparison;
11918 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11919 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11920 CO->getCond()->getSourceRange();
11921 return false;
11922 }
11923 } else {
11924 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11925 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11926 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11927 CO->getCond()->getSourceRange();
11928 return false;
11929 }
11930
11931 return true;
11932}
11933
11934bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
11935 // 'x' and 'e' cannot be nullptr
11936 assert(X && E && "X and E cannot be nullptr");
11937
11938 if (!CheckValue(E: X, ErrorInfo, ShouldBeLValue: true))
11939 return false;
11940
11941 if (!CheckValue(E, ErrorInfo, ShouldBeLValue: false))
11942 return false;
11943
11944 if (D && !CheckValue(E: D, ErrorInfo, ShouldBeLValue: false))
11945 return false;
11946
11947 return true;
11948}
11949
11950bool OpenMPAtomicCompareChecker::checkStmt(
11951 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11952 auto *CS = dyn_cast<CompoundStmt>(Val: S);
11953 if (CS) {
11954 if (CS->body_empty()) {
11955 ErrorInfo.Error = ErrorTy::NoStmt;
11956 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11957 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11958 return false;
11959 }
11960
11961 if (CS->size() != 1) {
11962 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11963 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11964 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11965 return false;
11966 }
11967 S = CS->body_front();
11968 }
11969
11970 auto Res = false;
11971
11972 if (auto *IS = dyn_cast<IfStmt>(Val: S)) {
11973 // Check if the statement is in one of the following forms
11974 // (cond-update-stmt):
11975 // if (expr ordop x) { x = expr; }
11976 // if (x ordop expr) { x = expr; }
11977 // if (x == e) { x = d; }
11978 Res = checkCondUpdateStmt(S: IS, ErrorInfo);
11979 } else {
11980 // Check if the statement is in one of the following forms (cond-expr-stmt):
11981 // x = expr ordop x ? expr : x;
11982 // x = x ordop expr ? expr : x;
11983 // x = x == e ? d : x;
11984 Res = checkCondExprStmt(S, ErrorInfo);
11985 }
11986
11987 if (!Res)
11988 return false;
11989
11990 return checkType(ErrorInfo);
11991}
11992
11993class OpenMPAtomicCompareCaptureChecker final
11994 : public OpenMPAtomicCompareChecker {
11995public:
11996 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
11997
11998 Expr *getV() const { return V; }
11999 Expr *getR() const { return R; }
12000 bool isFailOnly() const { return IsFailOnly; }
12001 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12002
12003 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12004 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12005
12006private:
12007 bool checkType(ErrorInfoTy &ErrorInfo);
12008
12009 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12010 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12011 // spec p.p. 82:
12012 // (1) { v = x; cond-update-stmt }
12013 // (2) { cond-update-stmt v = x; }
12014 // (3) if(x == e) { x = d; } else { v = x; }
12015 // (4) { r = x == e; if(r) { x = d; } }
12016 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12017
12018 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12019 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12020
12021 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12022 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12023 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12024
12025 /// 'v' lvalue part of the source atomic expression.
12026 Expr *V = nullptr;
12027 /// 'r' lvalue part of the source atomic expression.
12028 Expr *R = nullptr;
12029 /// If 'v' is only updated when the comparison fails.
12030 bool IsFailOnly = false;
12031 /// If original value of 'x' must be stored in 'v', not an updated one.
12032 bool IsPostfixUpdate = false;
12033};
12034
12035bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12036 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12037 return false;
12038
12039 if (V && !CheckValue(E: V, ErrorInfo, ShouldBeLValue: true))
12040 return false;
12041
12042 if (R && !CheckValue(E: R, ErrorInfo, ShouldBeLValue: true, ShouldBeInteger: true))
12043 return false;
12044
12045 return true;
12046}
12047
12048bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12049 ErrorInfoTy &ErrorInfo) {
12050 IsFailOnly = true;
12051
12052 auto *Then = S->getThen();
12053 if (auto *CS = dyn_cast<CompoundStmt>(Val: Then)) {
12054 if (CS->body_empty()) {
12055 ErrorInfo.Error = ErrorTy::NoStmt;
12056 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12057 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12058 return false;
12059 }
12060 if (CS->size() > 1) {
12061 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12062 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12063 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12064 return false;
12065 }
12066 Then = CS->body_front();
12067 }
12068
12069 auto *BO = dyn_cast<BinaryOperator>(Val: Then);
12070 if (!BO) {
12071 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12072 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12073 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12074 return false;
12075 }
12076 if (BO->getOpcode() != BO_Assign) {
12077 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12078 ErrorInfo.ErrorLoc = BO->getExprLoc();
12079 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12080 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12081 return false;
12082 }
12083
12084 X = BO->getLHS();
12085 D = BO->getRHS();
12086
12087 auto *Cond = dyn_cast<BinaryOperator>(Val: S->getCond());
12088 auto *Call = dyn_cast<CXXOperatorCallExpr>(Val: S->getCond());
12089 Expr *LHS = nullptr;
12090 Expr *RHS = nullptr;
12091 if (Cond) {
12092 LHS = Cond->getLHS();
12093 RHS = Cond->getRHS();
12094 } else if (Call) {
12095 LHS = Call->getArg(0);
12096 RHS = Call->getArg(1);
12097 } else {
12098 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12099 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12100 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12101 return false;
12102 }
12103 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12104 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12105 ErrorInfo.Error = ErrorTy::NotEQ;
12106 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12107 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12108 return false;
12109 }
12110
12111 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: LHS)) {
12112 E = RHS;
12113 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS)) {
12114 E = LHS;
12115 } else {
12116 ErrorInfo.Error = ErrorTy::InvalidComparison;
12117 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12118 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12119 return false;
12120 }
12121
12122 C = S->getCond();
12123
12124 if (!S->getElse()) {
12125 ErrorInfo.Error = ErrorTy::NoElse;
12126 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12127 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12128 return false;
12129 }
12130
12131 auto *Else = S->getElse();
12132 if (auto *CS = dyn_cast<CompoundStmt>(Val: Else)) {
12133 if (CS->body_empty()) {
12134 ErrorInfo.Error = ErrorTy::NoStmt;
12135 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12136 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12137 return false;
12138 }
12139 if (CS->size() > 1) {
12140 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12141 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12142 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12143 return false;
12144 }
12145 Else = CS->body_front();
12146 }
12147
12148 auto *ElseBO = dyn_cast<BinaryOperator>(Val: Else);
12149 if (!ElseBO) {
12150 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12151 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12152 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12153 return false;
12154 }
12155 if (ElseBO->getOpcode() != BO_Assign) {
12156 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12157 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12158 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12159 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12160 return false;
12161 }
12162
12163 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: ElseBO->getRHS())) {
12164 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12165 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12166 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12167 ElseBO->getRHS()->getSourceRange();
12168 return false;
12169 }
12170
12171 V = ElseBO->getLHS();
12172
12173 return checkType(ErrorInfo);
12174}
12175
12176bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12177 ErrorInfoTy &ErrorInfo) {
12178 // We don't check here as they should be already done before call this
12179 // function.
12180 auto *CS = cast<CompoundStmt>(Val: S);
12181 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12182 auto *S1 = cast<BinaryOperator>(Val: CS->body_front());
12183 auto *S2 = cast<IfStmt>(Val: CS->body_back());
12184 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12185
12186 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: S1->getLHS(), RHS: S2->getCond())) {
12187 ErrorInfo.Error = ErrorTy::InvalidCondition;
12188 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12189 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12190 return false;
12191 }
12192
12193 R = S1->getLHS();
12194
12195 auto *Then = S2->getThen();
12196 if (auto *ThenCS = dyn_cast<CompoundStmt>(Val: Then)) {
12197 if (ThenCS->body_empty()) {
12198 ErrorInfo.Error = ErrorTy::NoStmt;
12199 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12200 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12201 return false;
12202 }
12203 if (ThenCS->size() > 1) {
12204 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12205 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12206 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12207 return false;
12208 }
12209 Then = ThenCS->body_front();
12210 }
12211
12212 auto *ThenBO = dyn_cast<BinaryOperator>(Val: Then);
12213 if (!ThenBO) {
12214 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12215 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12216 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12217 return false;
12218 }
12219 if (ThenBO->getOpcode() != BO_Assign) {
12220 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12221 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12222 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12223 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12224 return false;
12225 }
12226
12227 X = ThenBO->getLHS();
12228 D = ThenBO->getRHS();
12229
12230 auto *BO = cast<BinaryOperator>(Val: S1->getRHS()->IgnoreImpCasts());
12231 if (BO->getOpcode() != BO_EQ) {
12232 ErrorInfo.Error = ErrorTy::NotEQ;
12233 ErrorInfo.ErrorLoc = BO->getExprLoc();
12234 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12235 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12236 return false;
12237 }
12238
12239 C = BO;
12240
12241 if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: BO->getLHS())) {
12242 E = BO->getRHS();
12243 } else if (checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: BO->getRHS())) {
12244 E = BO->getLHS();
12245 } else {
12246 ErrorInfo.Error = ErrorTy::InvalidComparison;
12247 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12248 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12249 return false;
12250 }
12251
12252 if (S2->getElse()) {
12253 IsFailOnly = true;
12254
12255 auto *Else = S2->getElse();
12256 if (auto *ElseCS = dyn_cast<CompoundStmt>(Val: Else)) {
12257 if (ElseCS->body_empty()) {
12258 ErrorInfo.Error = ErrorTy::NoStmt;
12259 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12260 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12261 return false;
12262 }
12263 if (ElseCS->size() > 1) {
12264 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12265 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12266 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12267 return false;
12268 }
12269 Else = ElseCS->body_front();
12270 }
12271
12272 auto *ElseBO = dyn_cast<BinaryOperator>(Val: Else);
12273 if (!ElseBO) {
12274 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12275 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12276 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12277 return false;
12278 }
12279 if (ElseBO->getOpcode() != BO_Assign) {
12280 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12281 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12282 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12283 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12284 return false;
12285 }
12286 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: X, RHS: ElseBO->getRHS())) {
12287 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12288 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12289 ErrorInfo.NoteLoc = X->getExprLoc();
12290 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12291 ErrorInfo.NoteRange = X->getSourceRange();
12292 return false;
12293 }
12294
12295 V = ElseBO->getLHS();
12296 }
12297
12298 return checkType(ErrorInfo);
12299}
12300
12301bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12302 ErrorInfoTy &ErrorInfo) {
12303 // if(x == e) { x = d; } else { v = x; }
12304 if (auto *IS = dyn_cast<IfStmt>(Val: S))
12305 return checkForm3(S: IS, ErrorInfo);
12306
12307 auto *CS = dyn_cast<CompoundStmt>(Val: S);
12308 if (!CS) {
12309 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12310 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12311 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12312 return false;
12313 }
12314 if (CS->body_empty()) {
12315 ErrorInfo.Error = ErrorTy::NoStmt;
12316 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12317 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12318 return false;
12319 }
12320
12321 // { if(x == e) { x = d; } else { v = x; } }
12322 if (CS->size() == 1) {
12323 auto *IS = dyn_cast<IfStmt>(Val: CS->body_front());
12324 if (!IS) {
12325 ErrorInfo.Error = ErrorTy::NotIfStmt;
12326 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12327 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12328 CS->body_front()->getSourceRange();
12329 return false;
12330 }
12331
12332 return checkForm3(S: IS, ErrorInfo);
12333 } else if (CS->size() == 2) {
12334 auto *S1 = CS->body_front();
12335 auto *S2 = CS->body_back();
12336
12337 Stmt *UpdateStmt = nullptr;
12338 Stmt *CondUpdateStmt = nullptr;
12339 Stmt *CondExprStmt = nullptr;
12340
12341 if (auto *BO = dyn_cast<BinaryOperator>(Val: S1)) {
12342 // It could be one of the following cases:
12343 // { v = x; cond-update-stmt }
12344 // { v = x; cond-expr-stmt }
12345 // { cond-expr-stmt; v = x; }
12346 // form 45
12347 if (isa<BinaryOperator>(Val: BO->getRHS()->IgnoreImpCasts()) ||
12348 isa<ConditionalOperator>(Val: BO->getRHS()->IgnoreImpCasts())) {
12349 // check if form 45
12350 if (isa<IfStmt>(Val: S2))
12351 return checkForm45(CS, ErrorInfo);
12352 // { cond-expr-stmt; v = x; }
12353 CondExprStmt = S1;
12354 UpdateStmt = S2;
12355 } else {
12356 IsPostfixUpdate = true;
12357 UpdateStmt = S1;
12358 if (isa<IfStmt>(Val: S2)) {
12359 // { v = x; cond-update-stmt }
12360 CondUpdateStmt = S2;
12361 } else {
12362 // { v = x; cond-expr-stmt }
12363 CondExprStmt = S2;
12364 }
12365 }
12366 } else {
12367 // { cond-update-stmt v = x; }
12368 UpdateStmt = S2;
12369 CondUpdateStmt = S1;
12370 }
12371
12372 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12373 auto *IS = dyn_cast<IfStmt>(Val: CUS);
12374 if (!IS) {
12375 ErrorInfo.Error = ErrorTy::NotIfStmt;
12376 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12377 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12378 return false;
12379 }
12380
12381 return checkCondUpdateStmt(S: IS, ErrorInfo);
12382 };
12383
12384 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12385 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12386 auto *BO = dyn_cast<BinaryOperator>(Val: US);
12387 if (!BO) {
12388 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12389 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12390 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12391 return false;
12392 }
12393 if (BO->getOpcode() != BO_Assign) {
12394 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12395 ErrorInfo.ErrorLoc = BO->getExprLoc();
12396 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12397 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12398 return false;
12399 }
12400 if (!checkIfTwoExprsAreSame(Context&: ContextRef, LHS: this->X, RHS: BO->getRHS())) {
12401 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12402 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12403 ErrorInfo.NoteLoc = this->X->getExprLoc();
12404 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12405 ErrorInfo.NoteRange = this->X->getSourceRange();
12406 return false;
12407 }
12408
12409 this->V = BO->getLHS();
12410
12411 return true;
12412 };
12413
12414 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12415 return false;
12416 if (CondExprStmt && !checkCondExprStmt(S: CondExprStmt, ErrorInfo))
12417 return false;
12418 if (!CheckUpdateStmt(UpdateStmt))
12419 return false;
12420 } else {
12421 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12422 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12423 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12424 return false;
12425 }
12426
12427 return checkType(ErrorInfo);
12428}
12429} // namespace
12430
12431StmtResult SemaOpenMP::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
12432 Stmt *AStmt,
12433 SourceLocation StartLoc,
12434 SourceLocation EndLoc) {
12435 ASTContext &Context = getASTContext();
12436 unsigned OMPVersion = getLangOpts().OpenMP;
12437 // Register location of the first atomic directive.
12438 DSAStack->addAtomicDirectiveLoc(Loc: StartLoc);
12439 if (!AStmt)
12440 return StmtError();
12441
12442 // 1.2.2 OpenMP Language Terminology
12443 // Structured block - An executable statement with a single entry at the
12444 // top and a single exit at the bottom.
12445 // The point of exit cannot be a branch out of the structured block.
12446 // longjmp() and throw() must not violate the entry/exit criteria.
12447 OpenMPClauseKind AtomicKind = OMPC_unknown;
12448 SourceLocation AtomicKindLoc;
12449 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12450 SourceLocation MemOrderLoc;
12451 bool MutexClauseEncountered = false;
12452 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12453 for (const OMPClause *C : Clauses) {
12454 switch (C->getClauseKind()) {
12455 case OMPC_read:
12456 case OMPC_write:
12457 case OMPC_update:
12458 MutexClauseEncountered = true;
12459 [[fallthrough]];
12460 case OMPC_capture:
12461 case OMPC_compare: {
12462 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12463 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12464 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12465 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12466 << getOpenMPClauseNameForDiag(AtomicKind);
12467 } else {
12468 AtomicKind = C->getClauseKind();
12469 AtomicKindLoc = C->getBeginLoc();
12470 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12471 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12472 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12473 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12474 << getOpenMPClauseNameForDiag(AtomicKind);
12475 }
12476 }
12477 break;
12478 }
12479 case OMPC_weak:
12480 case OMPC_fail: {
12481 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12482 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12483 << getOpenMPClauseNameForDiag(C->getClauseKind())
12484 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12485 return StmtError();
12486 }
12487 break;
12488 }
12489 case OMPC_seq_cst:
12490 case OMPC_acq_rel:
12491 case OMPC_acquire:
12492 case OMPC_release:
12493 case OMPC_relaxed: {
12494 if (MemOrderKind != OMPC_unknown) {
12495 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12496 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12497 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12498 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12499 << getOpenMPClauseNameForDiag(MemOrderKind);
12500 } else {
12501 MemOrderKind = C->getClauseKind();
12502 MemOrderLoc = C->getBeginLoc();
12503 }
12504 break;
12505 }
12506 // The following clauses are allowed, but we don't need to do anything here.
12507 case OMPC_hint:
12508 break;
12509 default:
12510 llvm_unreachable("unknown clause is encountered");
12511 }
12512 }
12513 bool IsCompareCapture = false;
12514 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12515 EncounteredAtomicKinds.contains(OMPC_capture)) {
12516 IsCompareCapture = true;
12517 AtomicKind = OMPC_compare;
12518 }
12519 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12520 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12521 // release.
12522 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12523 // acquire.
12524 // If atomic-clause is update or not present then memory-order-clause must not
12525 // be acq_rel or acquire.
12526 if ((AtomicKind == OMPC_read &&
12527 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12528 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12529 AtomicKind == OMPC_unknown) &&
12530 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12531 SourceLocation Loc = AtomicKindLoc;
12532 if (AtomicKind == OMPC_unknown)
12533 Loc = StartLoc;
12534 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12535 << getOpenMPClauseNameForDiag(AtomicKind)
12536 << (AtomicKind == OMPC_unknown ? 1 : 0)
12537 << getOpenMPClauseNameForDiag(MemOrderKind);
12538 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12539 << getOpenMPClauseNameForDiag(MemOrderKind);
12540 }
12541
12542 Stmt *Body = AStmt;
12543 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: Body))
12544 Body = EWC->getSubExpr();
12545
12546 Expr *X = nullptr;
12547 Expr *V = nullptr;
12548 Expr *E = nullptr;
12549 Expr *UE = nullptr;
12550 Expr *D = nullptr;
12551 Expr *CE = nullptr;
12552 Expr *R = nullptr;
12553 bool IsXLHSInRHSPart = false;
12554 bool IsPostfixUpdate = false;
12555 bool IsFailOnly = false;
12556 // OpenMP [2.12.6, atomic Construct]
12557 // In the next expressions:
12558 // * x and v (as applicable) are both l-value expressions with scalar type.
12559 // * During the execution of an atomic region, multiple syntactic
12560 // occurrences of x must designate the same storage location.
12561 // * Neither of v and expr (as applicable) may access the storage location
12562 // designated by x.
12563 // * Neither of x and expr (as applicable) may access the storage location
12564 // designated by v.
12565 // * expr is an expression with scalar type.
12566 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12567 // * binop, binop=, ++, and -- are not overloaded operators.
12568 // * The expression x binop expr must be numerically equivalent to x binop
12569 // (expr). This requirement is satisfied if the operators in expr have
12570 // precedence greater than binop, or by using parentheses around expr or
12571 // subexpressions of expr.
12572 // * The expression expr binop x must be numerically equivalent to (expr)
12573 // binop x. This requirement is satisfied if the operators in expr have
12574 // precedence equal to or greater than binop, or by using parentheses around
12575 // expr or subexpressions of expr.
12576 // * For forms that allow multiple occurrences of x, the number of times
12577 // that x is evaluated is unspecified.
12578 if (AtomicKind == OMPC_read) {
12579 enum {
12580 NotAnExpression,
12581 NotAnAssignmentOp,
12582 NotAScalarType,
12583 NotAnLValue,
12584 NoError
12585 } ErrorFound = NoError;
12586 SourceLocation ErrorLoc, NoteLoc;
12587 SourceRange ErrorRange, NoteRange;
12588 // If clause is read:
12589 // v = x;
12590 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
12591 const auto *AtomicBinOp =
12592 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
12593 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12594 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12595 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12596 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12597 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12598 if (!X->isLValue() || !V->isLValue()) {
12599 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12600 ErrorFound = NotAnLValue;
12601 ErrorLoc = AtomicBinOp->getExprLoc();
12602 ErrorRange = AtomicBinOp->getSourceRange();
12603 NoteLoc = NotLValueExpr->getExprLoc();
12604 NoteRange = NotLValueExpr->getSourceRange();
12605 }
12606 } else if (!X->isInstantiationDependent() ||
12607 !V->isInstantiationDependent()) {
12608 const Expr *NotScalarExpr =
12609 (X->isInstantiationDependent() || X->getType()->isScalarType())
12610 ? V
12611 : X;
12612 ErrorFound = NotAScalarType;
12613 ErrorLoc = AtomicBinOp->getExprLoc();
12614 ErrorRange = AtomicBinOp->getSourceRange();
12615 NoteLoc = NotScalarExpr->getExprLoc();
12616 NoteRange = NotScalarExpr->getSourceRange();
12617 }
12618 } else if (!AtomicBody->isInstantiationDependent()) {
12619 ErrorFound = NotAnAssignmentOp;
12620 ErrorLoc = AtomicBody->getExprLoc();
12621 ErrorRange = AtomicBody->getSourceRange();
12622 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12623 : AtomicBody->getExprLoc();
12624 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12625 : AtomicBody->getSourceRange();
12626 }
12627 } else {
12628 ErrorFound = NotAnExpression;
12629 NoteLoc = ErrorLoc = Body->getBeginLoc();
12630 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12631 }
12632 if (ErrorFound != NoError) {
12633 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12634 << ErrorRange;
12635 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12636 << ErrorFound << NoteRange;
12637 return StmtError();
12638 }
12639 if (SemaRef.CurContext->isDependentContext())
12640 V = X = nullptr;
12641 } else if (AtomicKind == OMPC_write) {
12642 enum {
12643 NotAnExpression,
12644 NotAnAssignmentOp,
12645 NotAScalarType,
12646 NotAnLValue,
12647 NoError
12648 } ErrorFound = NoError;
12649 SourceLocation ErrorLoc, NoteLoc;
12650 SourceRange ErrorRange, NoteRange;
12651 // If clause is write:
12652 // x = expr;
12653 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
12654 const auto *AtomicBinOp =
12655 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
12656 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12657 X = AtomicBinOp->getLHS();
12658 E = AtomicBinOp->getRHS();
12659 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12660 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12661 if (!X->isLValue()) {
12662 ErrorFound = NotAnLValue;
12663 ErrorLoc = AtomicBinOp->getExprLoc();
12664 ErrorRange = AtomicBinOp->getSourceRange();
12665 NoteLoc = X->getExprLoc();
12666 NoteRange = X->getSourceRange();
12667 }
12668 } else if (!X->isInstantiationDependent() ||
12669 !E->isInstantiationDependent()) {
12670 const Expr *NotScalarExpr =
12671 (X->isInstantiationDependent() || X->getType()->isScalarType())
12672 ? E
12673 : X;
12674 ErrorFound = NotAScalarType;
12675 ErrorLoc = AtomicBinOp->getExprLoc();
12676 ErrorRange = AtomicBinOp->getSourceRange();
12677 NoteLoc = NotScalarExpr->getExprLoc();
12678 NoteRange = NotScalarExpr->getSourceRange();
12679 }
12680 } else if (!AtomicBody->isInstantiationDependent()) {
12681 ErrorFound = NotAnAssignmentOp;
12682 ErrorLoc = AtomicBody->getExprLoc();
12683 ErrorRange = AtomicBody->getSourceRange();
12684 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12685 : AtomicBody->getExprLoc();
12686 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12687 : AtomicBody->getSourceRange();
12688 }
12689 } else {
12690 ErrorFound = NotAnExpression;
12691 NoteLoc = ErrorLoc = Body->getBeginLoc();
12692 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12693 }
12694 if (ErrorFound != NoError) {
12695 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12696 << ErrorRange;
12697 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12698 << ErrorFound << NoteRange;
12699 return StmtError();
12700 }
12701 if (SemaRef.CurContext->isDependentContext())
12702 E = X = nullptr;
12703 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12704 // If clause is update:
12705 // x++;
12706 // x--;
12707 // ++x;
12708 // --x;
12709 // x binop= expr;
12710 // x = x binop expr;
12711 // x = expr binop x;
12712 OpenMPAtomicUpdateChecker Checker(SemaRef);
12713 if (Checker.checkStatement(
12714 Body,
12715 (AtomicKind == OMPC_update)
12716 ? diag::err_omp_atomic_update_not_expression_statement
12717 : diag::err_omp_atomic_not_expression_statement,
12718 diag::note_omp_atomic_update))
12719 return StmtError();
12720 if (!SemaRef.CurContext->isDependentContext()) {
12721 E = Checker.getExpr();
12722 X = Checker.getX();
12723 UE = Checker.getUpdateExpr();
12724 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12725 }
12726 } else if (AtomicKind == OMPC_capture) {
12727 enum {
12728 NotAnAssignmentOp,
12729 NotACompoundStatement,
12730 NotTwoSubstatements,
12731 NotASpecificExpression,
12732 NoError
12733 } ErrorFound = NoError;
12734 SourceLocation ErrorLoc, NoteLoc;
12735 SourceRange ErrorRange, NoteRange;
12736 if (const auto *AtomicBody = dyn_cast<Expr>(Val: Body)) {
12737 // If clause is a capture:
12738 // v = x++;
12739 // v = x--;
12740 // v = ++x;
12741 // v = --x;
12742 // v = x binop= expr;
12743 // v = x = x binop expr;
12744 // v = x = expr binop x;
12745 const auto *AtomicBinOp =
12746 dyn_cast<BinaryOperator>(Val: AtomicBody->IgnoreParenImpCasts());
12747 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12748 V = AtomicBinOp->getLHS();
12749 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12750 OpenMPAtomicUpdateChecker Checker(SemaRef);
12751 if (Checker.checkStatement(
12752 Body, diag::err_omp_atomic_capture_not_expression_statement,
12753 diag::note_omp_atomic_update))
12754 return StmtError();
12755 E = Checker.getExpr();
12756 X = Checker.getX();
12757 UE = Checker.getUpdateExpr();
12758 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12759 IsPostfixUpdate = Checker.isPostfixUpdate();
12760 } else if (!AtomicBody->isInstantiationDependent()) {
12761 ErrorLoc = AtomicBody->getExprLoc();
12762 ErrorRange = AtomicBody->getSourceRange();
12763 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12764 : AtomicBody->getExprLoc();
12765 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12766 : AtomicBody->getSourceRange();
12767 ErrorFound = NotAnAssignmentOp;
12768 }
12769 if (ErrorFound != NoError) {
12770 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12771 << ErrorRange;
12772 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12773 return StmtError();
12774 }
12775 if (SemaRef.CurContext->isDependentContext())
12776 UE = V = E = X = nullptr;
12777 } else {
12778 // If clause is a capture:
12779 // { v = x; x = expr; }
12780 // { v = x; x++; }
12781 // { v = x; x--; }
12782 // { v = x; ++x; }
12783 // { v = x; --x; }
12784 // { v = x; x binop= expr; }
12785 // { v = x; x = x binop expr; }
12786 // { v = x; x = expr binop x; }
12787 // { x++; v = x; }
12788 // { x--; v = x; }
12789 // { ++x; v = x; }
12790 // { --x; v = x; }
12791 // { x binop= expr; v = x; }
12792 // { x = x binop expr; v = x; }
12793 // { x = expr binop x; v = x; }
12794 if (auto *CS = dyn_cast<CompoundStmt>(Val: Body)) {
12795 // Check that this is { expr1; expr2; }
12796 if (CS->size() == 2) {
12797 Stmt *First = CS->body_front();
12798 Stmt *Second = CS->body_back();
12799 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: First))
12800 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12801 if (auto *EWC = dyn_cast<ExprWithCleanups>(Val: Second))
12802 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12803 // Need to find what subexpression is 'v' and what is 'x'.
12804 OpenMPAtomicUpdateChecker Checker(SemaRef);
12805 bool IsUpdateExprFound = !Checker.checkStatement(S: Second);
12806 BinaryOperator *BinOp = nullptr;
12807 if (IsUpdateExprFound) {
12808 BinOp = dyn_cast<BinaryOperator>(Val: First);
12809 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12810 }
12811 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
12812 // { v = x; x++; }
12813 // { v = x; x--; }
12814 // { v = x; ++x; }
12815 // { v = x; --x; }
12816 // { v = x; x binop= expr; }
12817 // { v = x; x = x binop expr; }
12818 // { v = x; x = expr binop x; }
12819 // Check that the first expression has form v = x.
12820 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12821 llvm::FoldingSetNodeID XId, PossibleXId;
12822 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12823 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12824 IsUpdateExprFound = XId == PossibleXId;
12825 if (IsUpdateExprFound) {
12826 V = BinOp->getLHS();
12827 X = Checker.getX();
12828 E = Checker.getExpr();
12829 UE = Checker.getUpdateExpr();
12830 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12831 IsPostfixUpdate = true;
12832 }
12833 }
12834 if (!IsUpdateExprFound) {
12835 IsUpdateExprFound = !Checker.checkStatement(S: First);
12836 BinOp = nullptr;
12837 if (IsUpdateExprFound) {
12838 BinOp = dyn_cast<BinaryOperator>(Val: Second);
12839 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12840 }
12841 if (IsUpdateExprFound &&
12842 !SemaRef.CurContext->isDependentContext()) {
12843 // { x++; v = x; }
12844 // { x--; v = x; }
12845 // { ++x; v = x; }
12846 // { --x; v = x; }
12847 // { x binop= expr; v = x; }
12848 // { x = x binop expr; v = x; }
12849 // { x = expr binop x; v = x; }
12850 // Check that the second expression has form v = x.
12851 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12852 llvm::FoldingSetNodeID XId, PossibleXId;
12853 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12854 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12855 IsUpdateExprFound = XId == PossibleXId;
12856 if (IsUpdateExprFound) {
12857 V = BinOp->getLHS();
12858 X = Checker.getX();
12859 E = Checker.getExpr();
12860 UE = Checker.getUpdateExpr();
12861 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12862 IsPostfixUpdate = false;
12863 }
12864 }
12865 }
12866 if (!IsUpdateExprFound) {
12867 // { v = x; x = expr; }
12868 auto *FirstExpr = dyn_cast<Expr>(Val: First);
12869 auto *SecondExpr = dyn_cast<Expr>(Val: Second);
12870 if (!FirstExpr || !SecondExpr ||
12871 !(FirstExpr->isInstantiationDependent() ||
12872 SecondExpr->isInstantiationDependent())) {
12873 auto *FirstBinOp = dyn_cast<BinaryOperator>(Val: First);
12874 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12875 ErrorFound = NotAnAssignmentOp;
12876 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12877 : First->getBeginLoc();
12878 NoteRange = ErrorRange = FirstBinOp
12879 ? FirstBinOp->getSourceRange()
12880 : SourceRange(ErrorLoc, ErrorLoc);
12881 } else {
12882 auto *SecondBinOp = dyn_cast<BinaryOperator>(Val: Second);
12883 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12884 ErrorFound = NotAnAssignmentOp;
12885 NoteLoc = ErrorLoc = SecondBinOp
12886 ? SecondBinOp->getOperatorLoc()
12887 : Second->getBeginLoc();
12888 NoteRange = ErrorRange =
12889 SecondBinOp ? SecondBinOp->getSourceRange()
12890 : SourceRange(ErrorLoc, ErrorLoc);
12891 } else {
12892 Expr *PossibleXRHSInFirst =
12893 FirstBinOp->getRHS()->IgnoreParenImpCasts();
12894 Expr *PossibleXLHSInSecond =
12895 SecondBinOp->getLHS()->IgnoreParenImpCasts();
12896 llvm::FoldingSetNodeID X1Id, X2Id;
12897 PossibleXRHSInFirst->Profile(X1Id, Context,
12898 /*Canonical=*/true);
12899 PossibleXLHSInSecond->Profile(X2Id, Context,
12900 /*Canonical=*/true);
12901 IsUpdateExprFound = X1Id == X2Id;
12902 if (IsUpdateExprFound) {
12903 V = FirstBinOp->getLHS();
12904 X = SecondBinOp->getLHS();
12905 E = SecondBinOp->getRHS();
12906 UE = nullptr;
12907 IsXLHSInRHSPart = false;
12908 IsPostfixUpdate = true;
12909 } else {
12910 ErrorFound = NotASpecificExpression;
12911 ErrorLoc = FirstBinOp->getExprLoc();
12912 ErrorRange = FirstBinOp->getSourceRange();
12913 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12914 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12915 }
12916 }
12917 }
12918 }
12919 }
12920 } else {
12921 NoteLoc = ErrorLoc = Body->getBeginLoc();
12922 NoteRange = ErrorRange =
12923 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12924 ErrorFound = NotTwoSubstatements;
12925 }
12926 } else {
12927 NoteLoc = ErrorLoc = Body->getBeginLoc();
12928 NoteRange = ErrorRange =
12929 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12930 ErrorFound = NotACompoundStatement;
12931 }
12932 }
12933 if (ErrorFound != NoError) {
12934 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12935 << ErrorRange;
12936 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12937 return StmtError();
12938 }
12939 if (SemaRef.CurContext->isDependentContext())
12940 UE = V = E = X = nullptr;
12941 } else if (AtomicKind == OMPC_compare) {
12942 if (IsCompareCapture) {
12943 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12944 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
12945 if (!Checker.checkStmt(S: Body, ErrorInfo)) {
12946 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12947 << ErrorInfo.ErrorRange;
12948 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12949 << ErrorInfo.Error << ErrorInfo.NoteRange;
12950 return StmtError();
12951 }
12952 X = Checker.getX();
12953 E = Checker.getE();
12954 D = Checker.getD();
12955 CE = Checker.getCond();
12956 V = Checker.getV();
12957 R = Checker.getR();
12958 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12959 IsXLHSInRHSPart = Checker.isXBinopExpr();
12960 IsFailOnly = Checker.isFailOnly();
12961 IsPostfixUpdate = Checker.isPostfixUpdate();
12962 } else {
12963 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12964 OpenMPAtomicCompareChecker Checker(SemaRef);
12965 if (!Checker.checkStmt(S: Body, ErrorInfo)) {
12966 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12967 << ErrorInfo.ErrorRange;
12968 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12969 << ErrorInfo.Error << ErrorInfo.NoteRange;
12970 return StmtError();
12971 }
12972 X = Checker.getX();
12973 E = Checker.getE();
12974 D = Checker.getD();
12975 CE = Checker.getCond();
12976 // The weak clause may only appear if the resulting atomic operation is
12977 // an atomic conditional update for which the comparison tests for
12978 // equality. It was not possible to do this check in
12979 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
12980 // could not be performed (Clauses are not available).
12981 auto *It = find_if(Range&: Clauses, P: [](OMPClause *C) {
12982 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
12983 });
12984 if (It != Clauses.end()) {
12985 auto *Cond = dyn_cast<BinaryOperator>(Val: CE);
12986 if (Cond->getOpcode() != BO_EQ) {
12987 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
12988 ErrorInfo.ErrorLoc = Cond->getExprLoc();
12989 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
12990 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12991
12992 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
12993 << ErrorInfo.ErrorRange;
12994 return StmtError();
12995 }
12996 }
12997 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12998 IsXLHSInRHSPart = Checker.isXBinopExpr();
12999 }
13000 }
13001
13002 SemaRef.setFunctionHasBranchProtectedScope();
13003
13004 return OMPAtomicDirective::Create(
13005 C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
13006 Exprs: {.X: X, .V: V, .R: R, .E: E, .UE: UE, .D: D, .Cond: CE, .IsXLHSInRHSPart: IsXLHSInRHSPart, .IsPostfixUpdate: IsPostfixUpdate, .IsFailOnly: IsFailOnly});
13007}
13008
13009StmtResult SemaOpenMP::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
13010 Stmt *AStmt,
13011 SourceLocation StartLoc,
13012 SourceLocation EndLoc) {
13013 if (!AStmt)
13014 return StmtError();
13015
13016 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
13017
13018 // OpenMP [2.16, Nesting of Regions]
13019 // If specified, a teams construct must be contained within a target
13020 // construct. That target construct must contain no statements or directives
13021 // outside of the teams construct.
13022 if (DSAStack->hasInnerTeamsRegion()) {
13023 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13024 bool OMPTeamsFound = true;
13025 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13026 auto I = CS->body_begin();
13027 while (I != CS->body_end()) {
13028 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13029 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13030 if (!IsTeams || I != CS->body_begin()) {
13031 OMPTeamsFound = false;
13032 if (IsTeams && I != CS->body_begin()) {
13033 // This is the two teams case. Since the InnerTeamsRegionLoc will
13034 // point to this second one reset the iterator to the other teams.
13035 --I;
13036 }
13037 break;
13038 }
13039 ++I;
13040 }
13041 assert(I != CS->body_end() && "Not found statement");
13042 S = *I;
13043 } else {
13044 const auto *OED = dyn_cast<OMPExecutableDirective>(Val: S);
13045 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13046 }
13047 if (!OMPTeamsFound) {
13048 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13049 Diag(DSAStack->getInnerTeamsRegionLoc(),
13050 diag::note_omp_nested_teams_construct_here);
13051 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13052 << isa<OMPExecutableDirective>(S);
13053 return StmtError();
13054 }
13055 }
13056
13057 return OMPTargetDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
13058 AssociatedStmt: AStmt);
13059}
13060
13061StmtResult SemaOpenMP::ActOnOpenMPTargetParallelDirective(
13062 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13063 SourceLocation EndLoc) {
13064 if (!AStmt)
13065 return StmtError();
13066
13067 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
13068
13069 return OMPTargetParallelDirective::Create(
13070 C: getASTContext(), StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
13071 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13072}
13073
13074StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForDirective(
13075 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13076 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13077 if (!AStmt)
13078 return StmtError();
13079
13080 CapturedStmt *CS =
13081 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
13082
13083 OMPLoopBasedDirective::HelperExprs B;
13084 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13085 // define the nested loops number.
13086 unsigned NestedLoopCount =
13087 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13088 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13089 VarsWithImplicitDSA, B);
13090 if (NestedLoopCount == 0)
13091 return StmtError();
13092
13093 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13094 return StmtError();
13095
13096 return OMPTargetParallelForDirective::Create(
13097 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13098 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13099}
13100
13101/// Check for existence of a map clause in the list of clauses.
13102static bool hasClauses(ArrayRef<OMPClause *> Clauses,
13103 const OpenMPClauseKind K) {
13104 return llvm::any_of(
13105 Range&: Clauses, P: [K](const OMPClause *C) { return C->getClauseKind() == K; });
13106}
13107
13108template <typename... Params>
13109static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
13110 const Params... ClauseTypes) {
13111 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13112}
13113
13114/// Check if the variables in the mapping clause are externally visible.
13115static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
13116 for (const OMPClause *C : Clauses) {
13117 if (auto *TC = dyn_cast<OMPToClause>(Val: C))
13118 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13119 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13120 (VD->isExternallyVisible() &&
13121 VD->getVisibility() != HiddenVisibility);
13122 });
13123 else if (auto *FC = dyn_cast<OMPFromClause>(Val: C))
13124 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13125 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13126 (VD->isExternallyVisible() &&
13127 VD->getVisibility() != HiddenVisibility);
13128 });
13129 }
13130
13131 return true;
13132}
13133
13134StmtResult
13135SemaOpenMP::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
13136 Stmt *AStmt, SourceLocation StartLoc,
13137 SourceLocation EndLoc) {
13138 if (!AStmt)
13139 return StmtError();
13140
13141 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13142
13143 // OpenMP [2.12.2, target data Construct, Restrictions]
13144 // At least one map, use_device_addr or use_device_ptr clause must appear on
13145 // the directive.
13146 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13147 (getLangOpts().OpenMP < 50 ||
13148 !hasClauses(Clauses, OMPC_use_device_addr))) {
13149 StringRef Expected;
13150 if (getLangOpts().OpenMP < 50)
13151 Expected = "'map' or 'use_device_ptr'";
13152 else
13153 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13154 unsigned OMPVersion = getLangOpts().OpenMP;
13155 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13156 << Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13157 return StmtError();
13158 }
13159
13160 SemaRef.setFunctionHasBranchProtectedScope();
13161
13162 return OMPTargetDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13163 Clauses, AssociatedStmt: AStmt);
13164}
13165
13166StmtResult SemaOpenMP::ActOnOpenMPTargetEnterDataDirective(
13167 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13168 SourceLocation EndLoc, Stmt *AStmt) {
13169 if (!AStmt)
13170 return StmtError();
13171
13172 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13173
13174 // OpenMP [2.10.2, Restrictions, p. 99]
13175 // At least one map clause must appear on the directive.
13176 if (!hasClauses(Clauses, OMPC_map)) {
13177 unsigned OMPVersion = getLangOpts().OpenMP;
13178 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13179 << "'map'"
13180 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13181 return StmtError();
13182 }
13183
13184 return OMPTargetEnterDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13185 Clauses, AssociatedStmt: AStmt);
13186}
13187
13188StmtResult SemaOpenMP::ActOnOpenMPTargetExitDataDirective(
13189 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13190 SourceLocation EndLoc, Stmt *AStmt) {
13191 if (!AStmt)
13192 return StmtError();
13193
13194 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13195
13196 // OpenMP [2.10.3, Restrictions, p. 102]
13197 // At least one map clause must appear on the directive.
13198 if (!hasClauses(Clauses, OMPC_map)) {
13199 unsigned OMPVersion = getLangOpts().OpenMP;
13200 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13201 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13202 return StmtError();
13203 }
13204
13205 return OMPTargetExitDataDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13206 Clauses, AssociatedStmt: AStmt);
13207}
13208
13209StmtResult SemaOpenMP::ActOnOpenMPTargetUpdateDirective(
13210 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13211 SourceLocation EndLoc, Stmt *AStmt) {
13212 if (!AStmt)
13213 return StmtError();
13214
13215 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13216
13217 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13218 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13219 return StmtError();
13220 }
13221
13222 if (!isClauseMappable(Clauses)) {
13223 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13224 return StmtError();
13225 }
13226
13227 return OMPTargetUpdateDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13228 Clauses, AssociatedStmt: AStmt);
13229}
13230
13231/// This checks whether a \p ClauseType clause \p C has at most \p Max
13232/// expression. If not, a diag of number \p Diag will be emitted.
13233template <typename ClauseType>
13234static bool checkNumExprsInClause(SemaBase &SemaRef,
13235 ArrayRef<OMPClause *> Clauses,
13236 unsigned MaxNum, unsigned Diag) {
13237 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13238 if (ClauseItr == Clauses.end())
13239 return true;
13240 const auto *C = cast<ClauseType>(*ClauseItr);
13241 auto VarList = C->getVarRefs();
13242 if (VarList.size() > MaxNum) {
13243 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13244 << getOpenMPClauseNameForDiag(C->getClauseKind());
13245 return false;
13246 }
13247 return true;
13248}
13249
13250StmtResult SemaOpenMP::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
13251 Stmt *AStmt,
13252 SourceLocation StartLoc,
13253 SourceLocation EndLoc) {
13254 if (!AStmt)
13255 return StmtError();
13256
13257 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13258 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13259 !checkNumExprsInClause<OMPThreadLimitClause>(
13260 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13261 return StmtError();
13262
13263 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13264 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13265 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13266
13267 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13268
13269 DSAStack->setParentTeamsRegionLoc(StartLoc);
13270
13271 return OMPTeamsDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
13272 AssociatedStmt: AStmt);
13273}
13274
13275StmtResult SemaOpenMP::ActOnOpenMPCancellationPointDirective(
13276 SourceLocation StartLoc, SourceLocation EndLoc,
13277 OpenMPDirectiveKind CancelRegion) {
13278 if (DSAStack->isParentNowaitRegion()) {
13279 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13280 return StmtError();
13281 }
13282 if (DSAStack->isParentOrderedRegion()) {
13283 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13284 return StmtError();
13285 }
13286 return OMPCancellationPointDirective::Create(getASTContext(), StartLoc,
13287 EndLoc, CancelRegion);
13288}
13289
13290StmtResult SemaOpenMP::ActOnOpenMPCancelDirective(
13291 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13292 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13293 if (DSAStack->isParentNowaitRegion()) {
13294 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13295 return StmtError();
13296 }
13297 if (DSAStack->isParentOrderedRegion()) {
13298 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13299 return StmtError();
13300 }
13301 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13302 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13303 CancelRegion);
13304}
13305
13306static bool checkReductionClauseWithNogroup(Sema &S,
13307 ArrayRef<OMPClause *> Clauses) {
13308 const OMPClause *ReductionClause = nullptr;
13309 const OMPClause *NogroupClause = nullptr;
13310 for (const OMPClause *C : Clauses) {
13311 if (C->getClauseKind() == OMPC_reduction) {
13312 ReductionClause = C;
13313 if (NogroupClause)
13314 break;
13315 continue;
13316 }
13317 if (C->getClauseKind() == OMPC_nogroup) {
13318 NogroupClause = C;
13319 if (ReductionClause)
13320 break;
13321 continue;
13322 }
13323 }
13324 if (ReductionClause && NogroupClause) {
13325 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13326 << SourceRange(NogroupClause->getBeginLoc(),
13327 NogroupClause->getEndLoc());
13328 return true;
13329 }
13330 return false;
13331}
13332
13333StmtResult SemaOpenMP::ActOnOpenMPTaskLoopDirective(
13334 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13335 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13336 if (!AStmt)
13337 return StmtError();
13338
13339 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13340 OMPLoopBasedDirective::HelperExprs B;
13341 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13342 // define the nested loops number.
13343 unsigned NestedLoopCount =
13344 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13345 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13346 *DSAStack, VarsWithImplicitDSA, B);
13347 if (NestedLoopCount == 0)
13348 return StmtError();
13349
13350 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13351 "omp for loop exprs were not built");
13352
13353 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13354 // The grainsize clause and num_tasks clause are mutually exclusive and may
13355 // not appear on the same taskloop directive.
13356 if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13357 {OMPC_grainsize, OMPC_num_tasks}))
13358 return StmtError();
13359 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13360 // If a reduction clause is present on the taskloop directive, the nogroup
13361 // clause must not be specified.
13362 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13363 return StmtError();
13364
13365 SemaRef.setFunctionHasBranchProtectedScope();
13366 return OMPTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13367 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13368 DSAStack->isCancelRegion());
13369}
13370
13371StmtResult SemaOpenMP::ActOnOpenMPTaskLoopSimdDirective(
13372 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13373 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13374 if (!AStmt)
13375 return StmtError();
13376
13377 CapturedStmt *CS =
13378 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13379
13380 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13381 OMPLoopBasedDirective::HelperExprs B;
13382 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13383 // define the nested loops number.
13384 unsigned NestedLoopCount =
13385 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13386 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13387 VarsWithImplicitDSA, B);
13388 if (NestedLoopCount == 0)
13389 return StmtError();
13390
13391 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13392 return StmtError();
13393
13394 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13395 // The grainsize clause and num_tasks clause are mutually exclusive and may
13396 // not appear on the same taskloop directive.
13397 if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13398 {OMPC_grainsize, OMPC_num_tasks}))
13399 return StmtError();
13400 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13401 // If a reduction clause is present on the taskloop directive, the nogroup
13402 // clause must not be specified.
13403 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13404 return StmtError();
13405 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13406 return StmtError();
13407
13408 return OMPTaskLoopSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13409 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13410}
13411
13412StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopDirective(
13413 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13414 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13415 if (!AStmt)
13416 return StmtError();
13417
13418 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13419 OMPLoopBasedDirective::HelperExprs B;
13420 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13421 // define the nested loops number.
13422 unsigned NestedLoopCount =
13423 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13424 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13425 *DSAStack, VarsWithImplicitDSA, B);
13426 if (NestedLoopCount == 0)
13427 return StmtError();
13428
13429 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13430 "omp for loop exprs were not built");
13431
13432 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13433 // The grainsize clause and num_tasks clause are mutually exclusive and may
13434 // not appear on the same taskloop directive.
13435 if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13436 {OMPC_grainsize, OMPC_num_tasks}))
13437 return StmtError();
13438 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13439 // If a reduction clause is present on the taskloop directive, the nogroup
13440 // clause must not be specified.
13441 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13442 return StmtError();
13443
13444 SemaRef.setFunctionHasBranchProtectedScope();
13445 return OMPMasterTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13446 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13447 DSAStack->isCancelRegion());
13448}
13449
13450StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopDirective(
13451 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13452 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13453 if (!AStmt)
13454 return StmtError();
13455
13456 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13457 OMPLoopBasedDirective::HelperExprs B;
13458 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13459 // define the nested loops number.
13460 unsigned NestedLoopCount =
13461 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13462 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13463 *DSAStack, VarsWithImplicitDSA, B);
13464 if (NestedLoopCount == 0)
13465 return StmtError();
13466
13467 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13468 "omp for loop exprs were not built");
13469
13470 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13471 // The grainsize clause and num_tasks clause are mutually exclusive and may
13472 // not appear on the same taskloop directive.
13473 if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13474 {OMPC_grainsize, OMPC_num_tasks}))
13475 return StmtError();
13476 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13477 // If a reduction clause is present on the taskloop directive, the nogroup
13478 // clause must not be specified.
13479 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13480 return StmtError();
13481
13482 SemaRef.setFunctionHasBranchProtectedScope();
13483 return OMPMaskedTaskLoopDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13484 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13485 DSAStack->isCancelRegion());
13486}
13487
13488StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopSimdDirective(
13489 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13490 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13491 if (!AStmt)
13492 return StmtError();
13493
13494 CapturedStmt *CS =
13495 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13496
13497 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13498 OMPLoopBasedDirective::HelperExprs B;
13499 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13500 // define the nested loops number.
13501 unsigned NestedLoopCount =
13502 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13503 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13504 VarsWithImplicitDSA, B);
13505 if (NestedLoopCount == 0)
13506 return StmtError();
13507
13508 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13509 return StmtError();
13510
13511 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13512 // The grainsize clause and num_tasks clause are mutually exclusive and may
13513 // not appear on the same taskloop directive.
13514 if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13515 {OMPC_grainsize, OMPC_num_tasks}))
13516 return StmtError();
13517 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13518 // If a reduction clause is present on the taskloop directive, the nogroup
13519 // clause must not be specified.
13520 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13521 return StmtError();
13522 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13523 return StmtError();
13524
13525 return OMPMasterTaskLoopSimdDirective::Create(
13526 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13527}
13528
13529StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopSimdDirective(
13530 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13531 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13532 if (!AStmt)
13533 return StmtError();
13534
13535 CapturedStmt *CS =
13536 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13537
13538 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13539 OMPLoopBasedDirective::HelperExprs B;
13540 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13541 // define the nested loops number.
13542 unsigned NestedLoopCount =
13543 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13544 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13545 VarsWithImplicitDSA, B);
13546 if (NestedLoopCount == 0)
13547 return StmtError();
13548
13549 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13550 return StmtError();
13551
13552 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13553 // The grainsize clause and num_tasks clause are mutually exclusive and may
13554 // not appear on the same taskloop directive.
13555 if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13556 {OMPC_grainsize, OMPC_num_tasks}))
13557 return StmtError();
13558 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13559 // If a reduction clause is present on the taskloop directive, the nogroup
13560 // clause must not be specified.
13561 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13562 return StmtError();
13563 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13564 return StmtError();
13565
13566 return OMPMaskedTaskLoopSimdDirective::Create(
13567 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13568}
13569
13570StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopDirective(
13571 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13572 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13573 if (!AStmt)
13574 return StmtError();
13575
13576 CapturedStmt *CS =
13577 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13578
13579 OMPLoopBasedDirective::HelperExprs B;
13580 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13581 // define the nested loops number.
13582 unsigned NestedLoopCount = checkOpenMPLoop(
13583 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13584 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13585 VarsWithImplicitDSA, B);
13586 if (NestedLoopCount == 0)
13587 return StmtError();
13588
13589 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13590 "omp for loop exprs were not built");
13591
13592 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13593 // The grainsize clause and num_tasks clause are mutually exclusive and may
13594 // not appear on the same taskloop directive.
13595 if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13596 {OMPC_grainsize, OMPC_num_tasks}))
13597 return StmtError();
13598 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13599 // If a reduction clause is present on the taskloop directive, the nogroup
13600 // clause must not be specified.
13601 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13602 return StmtError();
13603
13604 return OMPParallelMasterTaskLoopDirective::Create(
13605 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13606 DSAStack->isCancelRegion());
13607}
13608
13609StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopDirective(
13610 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13611 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13612 if (!AStmt)
13613 return StmtError();
13614
13615 CapturedStmt *CS =
13616 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13617
13618 OMPLoopBasedDirective::HelperExprs B;
13619 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13620 // define the nested loops number.
13621 unsigned NestedLoopCount = checkOpenMPLoop(
13622 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13623 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13624 VarsWithImplicitDSA, B);
13625 if (NestedLoopCount == 0)
13626 return StmtError();
13627
13628 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13629 "omp for loop exprs were not built");
13630
13631 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13632 // The grainsize clause and num_tasks clause are mutually exclusive and may
13633 // not appear on the same taskloop directive.
13634 if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13635 {OMPC_grainsize, OMPC_num_tasks}))
13636 return StmtError();
13637 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13638 // If a reduction clause is present on the taskloop directive, the nogroup
13639 // clause must not be specified.
13640 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13641 return StmtError();
13642
13643 return OMPParallelMaskedTaskLoopDirective::Create(
13644 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13645 DSAStack->isCancelRegion());
13646}
13647
13648StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
13649 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13650 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13651 if (!AStmt)
13652 return StmtError();
13653
13654 CapturedStmt *CS = setBranchProtectedScope(
13655 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13656
13657 OMPLoopBasedDirective::HelperExprs B;
13658 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13659 // define the nested loops number.
13660 unsigned NestedLoopCount = checkOpenMPLoop(
13661 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13662 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13663 VarsWithImplicitDSA, B);
13664 if (NestedLoopCount == 0)
13665 return StmtError();
13666
13667 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13668 return StmtError();
13669
13670 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13671 // The grainsize clause and num_tasks clause are mutually exclusive and may
13672 // not appear on the same taskloop directive.
13673 if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13674 {OMPC_grainsize, OMPC_num_tasks}))
13675 return StmtError();
13676 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13677 // If a reduction clause is present on the taskloop directive, the nogroup
13678 // clause must not be specified.
13679 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13680 return StmtError();
13681 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13682 return StmtError();
13683
13684 return OMPParallelMasterTaskLoopSimdDirective::Create(
13685 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13686}
13687
13688StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
13689 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13690 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13691 if (!AStmt)
13692 return StmtError();
13693
13694 CapturedStmt *CS = setBranchProtectedScope(
13695 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13696
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 = checkOpenMPLoop(
13701 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13702 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13703 VarsWithImplicitDSA, B);
13704 if (NestedLoopCount == 0)
13705 return StmtError();
13706
13707 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13708 return StmtError();
13709
13710 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13711 // The grainsize clause and num_tasks clause are mutually exclusive and may
13712 // not appear on the same taskloop directive.
13713 if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13714 {OMPC_grainsize, OMPC_num_tasks}))
13715 return StmtError();
13716 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13717 // If a reduction clause is present on the taskloop directive, the nogroup
13718 // clause must not be specified.
13719 if (checkReductionClauseWithNogroup(S&: SemaRef, Clauses))
13720 return StmtError();
13721 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13722 return StmtError();
13723
13724 return OMPParallelMaskedTaskLoopSimdDirective::Create(
13725 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13726}
13727
13728StmtResult SemaOpenMP::ActOnOpenMPDistributeDirective(
13729 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13730 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13731 if (!AStmt)
13732 return StmtError();
13733
13734 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13735 OMPLoopBasedDirective::HelperExprs B;
13736 // In presence of clause 'collapse' with number of loops, it will
13737 // define the nested loops number.
13738 unsigned NestedLoopCount =
13739 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13740 nullptr /*ordered not a clause on distribute*/, AStmt,
13741 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13742 if (NestedLoopCount == 0)
13743 return StmtError();
13744
13745 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13746 "omp for loop exprs were not built");
13747
13748 SemaRef.setFunctionHasBranchProtectedScope();
13749 auto *DistributeDirective = OMPDistributeDirective::Create(
13750 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13751 return DistributeDirective;
13752}
13753
13754StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForDirective(
13755 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13756 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13757 if (!AStmt)
13758 return StmtError();
13759
13760 CapturedStmt *CS =
13761 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
13762
13763 OMPLoopBasedDirective::HelperExprs B;
13764 // In presence of clause 'collapse' with number of loops, it will
13765 // define the nested loops number.
13766 unsigned NestedLoopCount = checkOpenMPLoop(
13767 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13768 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13769 VarsWithImplicitDSA, B);
13770 if (NestedLoopCount == 0)
13771 return StmtError();
13772
13773 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13774 "omp for loop exprs were not built");
13775
13776 return OMPDistributeParallelForDirective::Create(
13777 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
13778 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13779}
13780
13781StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForSimdDirective(
13782 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13783 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13784 if (!AStmt)
13785 return StmtError();
13786
13787 CapturedStmt *CS = setBranchProtectedScope(
13788 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
13789
13790 OMPLoopBasedDirective::HelperExprs B;
13791 // In presence of clause 'collapse' with number of loops, it will
13792 // define the nested loops number.
13793 unsigned NestedLoopCount = checkOpenMPLoop(
13794 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13795 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13796 VarsWithImplicitDSA, B);
13797 if (NestedLoopCount == 0)
13798 return StmtError();
13799
13800 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13801 return StmtError();
13802
13803 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13804 return StmtError();
13805
13806 return OMPDistributeParallelForSimdDirective::Create(
13807 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13808}
13809
13810StmtResult SemaOpenMP::ActOnOpenMPDistributeSimdDirective(
13811 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13812 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13813 if (!AStmt)
13814 return StmtError();
13815
13816 CapturedStmt *CS =
13817 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
13818
13819 OMPLoopBasedDirective::HelperExprs B;
13820 // In presence of clause 'collapse' with number of loops, it will
13821 // define the nested loops number.
13822 unsigned NestedLoopCount =
13823 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
13824 nullptr /*ordered not a clause on distribute*/, CS,
13825 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13826 if (NestedLoopCount == 0)
13827 return StmtError();
13828
13829 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13830 return StmtError();
13831
13832 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13833 return StmtError();
13834
13835 return OMPDistributeSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13836 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13837}
13838
13839StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForSimdDirective(
13840 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13841 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13842 if (!AStmt)
13843 return StmtError();
13844
13845 CapturedStmt *CS =
13846 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
13847
13848 OMPLoopBasedDirective::HelperExprs B;
13849 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13850 // define the nested loops number.
13851 unsigned NestedLoopCount = checkOpenMPLoop(
13852 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
13853 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13854 VarsWithImplicitDSA, B);
13855 if (NestedLoopCount == 0)
13856 return StmtError();
13857
13858 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13859 return StmtError();
13860
13861 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13862 return StmtError();
13863
13864 return OMPTargetParallelForSimdDirective::Create(
13865 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13866}
13867
13868StmtResult SemaOpenMP::ActOnOpenMPTargetSimdDirective(
13869 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13870 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13871 if (!AStmt)
13872 return StmtError();
13873
13874 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
13875
13876 OMPLoopBasedDirective::HelperExprs B;
13877 // In presence of clause 'collapse' with number of loops, it will define the
13878 // nested loops number.
13879 unsigned NestedLoopCount =
13880 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
13881 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13882 VarsWithImplicitDSA, B);
13883 if (NestedLoopCount == 0)
13884 return StmtError();
13885
13886 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13887 return StmtError();
13888
13889 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13890 return StmtError();
13891
13892 return OMPTargetSimdDirective::Create(C: getASTContext(), StartLoc, EndLoc,
13893 CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13894}
13895
13896StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeDirective(
13897 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13898 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13899 if (!AStmt)
13900 return StmtError();
13901
13902 CapturedStmt *CS =
13903 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
13904
13905 OMPLoopBasedDirective::HelperExprs B;
13906 // In presence of clause 'collapse' with number of loops, it will
13907 // define the nested loops number.
13908 unsigned NestedLoopCount =
13909 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
13910 nullptr /*ordered not a clause on distribute*/, CS,
13911 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13912 if (NestedLoopCount == 0)
13913 return StmtError();
13914
13915 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13916 "omp teams distribute loop exprs were not built");
13917
13918 DSAStack->setParentTeamsRegionLoc(StartLoc);
13919
13920 return OMPTeamsDistributeDirective::Create(
13921 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13922}
13923
13924StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeSimdDirective(
13925 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13926 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13927 if (!AStmt)
13928 return StmtError();
13929
13930 CapturedStmt *CS =
13931 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
13932
13933 OMPLoopBasedDirective::HelperExprs B;
13934 // In presence of clause 'collapse' with number of loops, it will
13935 // define the nested loops number.
13936 unsigned NestedLoopCount = checkOpenMPLoop(
13937 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
13938 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13939 VarsWithImplicitDSA, B);
13940 if (NestedLoopCount == 0)
13941 return StmtError();
13942
13943 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13944 return StmtError();
13945
13946 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13947 return StmtError();
13948
13949 DSAStack->setParentTeamsRegionLoc(StartLoc);
13950
13951 return OMPTeamsDistributeSimdDirective::Create(
13952 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13953}
13954
13955StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
13956 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13957 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13958 if (!AStmt)
13959 return StmtError();
13960
13961 CapturedStmt *CS = setBranchProtectedScope(
13962 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
13963
13964 OMPLoopBasedDirective::HelperExprs B;
13965 // In presence of clause 'collapse' with number of loops, it will
13966 // define the nested loops number.
13967 unsigned NestedLoopCount = checkOpenMPLoop(
13968 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13969 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13970 VarsWithImplicitDSA, B);
13971 if (NestedLoopCount == 0)
13972 return StmtError();
13973
13974 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13975 return StmtError();
13976
13977 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
13978 return StmtError();
13979
13980 DSAStack->setParentTeamsRegionLoc(StartLoc);
13981
13982 return OMPTeamsDistributeParallelForSimdDirective::Create(
13983 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
13984}
13985
13986StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForDirective(
13987 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13988 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13989 if (!AStmt)
13990 return StmtError();
13991
13992 CapturedStmt *CS = setBranchProtectedScope(
13993 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
13994
13995 OMPLoopBasedDirective::HelperExprs B;
13996 // In presence of clause 'collapse' with number of loops, it will
13997 // define the nested loops number.
13998 unsigned NestedLoopCount = checkOpenMPLoop(
13999 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14000 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14001 VarsWithImplicitDSA, B);
14002
14003 if (NestedLoopCount == 0)
14004 return StmtError();
14005
14006 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14007 "omp for loop exprs were not built");
14008
14009 DSAStack->setParentTeamsRegionLoc(StartLoc);
14010
14011 return OMPTeamsDistributeParallelForDirective::Create(
14012 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14013 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14014}
14015
14016StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDirective(
14017 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14018 SourceLocation EndLoc) {
14019 if (!AStmt)
14020 return StmtError();
14021
14022 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
14023
14024 const OMPClause *BareClause = nullptr;
14025 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14026 hasClauses(Clauses, OMPC_thread_limit);
14027 bool HasBareClause = llvm::any_of(Range&: Clauses, P: [&](const OMPClause *C) {
14028 BareClause = C;
14029 return C->getClauseKind() == OMPC_ompx_bare;
14030 });
14031
14032 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14033 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14034 return StmtError();
14035 }
14036
14037 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14038 unsigned DiagNo = HasBareClause
14039 ? diag::err_ompx_more_than_three_expr_not_allowed
14040 : diag::err_omp_multi_expr_not_allowed;
14041 if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses,
14042 ClauseMaxNumExprs, DiagNo) ||
14043 !checkNumExprsInClause<OMPThreadLimitClause>(*this, Clauses,
14044 ClauseMaxNumExprs, DiagNo))
14045 return StmtError();
14046
14047 return OMPTargetTeamsDirective::Create(C: getASTContext(), StartLoc, EndLoc,
14048 Clauses, AssociatedStmt: AStmt);
14049}
14050
14051StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeDirective(
14052 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14053 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14054 if (!AStmt)
14055 return StmtError();
14056
14057 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14058 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14059 !checkNumExprsInClause<OMPThreadLimitClause>(
14060 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14061 return StmtError();
14062
14063 CapturedStmt *CS =
14064 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
14065
14066 OMPLoopBasedDirective::HelperExprs B;
14067 // In presence of clause 'collapse' with number of loops, it will
14068 // define the nested loops number.
14069 unsigned NestedLoopCount = checkOpenMPLoop(
14070 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14071 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14072 VarsWithImplicitDSA, B);
14073 if (NestedLoopCount == 0)
14074 return StmtError();
14075
14076 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14077 "omp target teams distribute loop exprs were not built");
14078
14079 return OMPTargetTeamsDistributeDirective::Create(
14080 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14081}
14082
14083StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14084 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14085 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14086 if (!AStmt)
14087 return StmtError();
14088
14089 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14090 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14091 !checkNumExprsInClause<OMPThreadLimitClause>(
14092 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14093 return StmtError();
14094
14095 CapturedStmt *CS = setBranchProtectedScope(
14096 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14097
14098 OMPLoopBasedDirective::HelperExprs B;
14099 // In presence of clause 'collapse' with number of loops, it will
14100 // define the nested loops number.
14101 unsigned NestedLoopCount = checkOpenMPLoop(
14102 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14103 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14104 VarsWithImplicitDSA, B);
14105 if (NestedLoopCount == 0)
14106 return StmtError();
14107
14108 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14109 return StmtError();
14110
14111 return OMPTargetTeamsDistributeParallelForDirective::Create(
14112 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B,
14113 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14114}
14115
14116StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14117 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14118 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14119 if (!AStmt)
14120 return StmtError();
14121
14122 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14123 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14124 !checkNumExprsInClause<OMPThreadLimitClause>(
14125 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14126 return StmtError();
14127
14128 CapturedStmt *CS = setBranchProtectedScope(
14129 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14130
14131 OMPLoopBasedDirective::HelperExprs B;
14132 // In presence of clause 'collapse' with number of loops, it will
14133 // define the nested loops number.
14134 unsigned NestedLoopCount =
14135 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14136 getCollapseNumberExpr(Clauses),
14137 nullptr /*ordered not a clause on distribute*/, CS,
14138 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14139 if (NestedLoopCount == 0)
14140 return StmtError();
14141
14142 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14143 return StmtError();
14144
14145 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14146 return StmtError();
14147
14148 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14149 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14150}
14151
14152StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14153 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14154 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14155 if (!AStmt)
14156 return StmtError();
14157
14158 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14159 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14160 !checkNumExprsInClause<OMPThreadLimitClause>(
14161 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14162 return StmtError();
14163
14164 CapturedStmt *CS = setBranchProtectedScope(
14165 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14166
14167 OMPLoopBasedDirective::HelperExprs B;
14168 // In presence of clause 'collapse' with number of loops, it will
14169 // define the nested loops number.
14170 unsigned NestedLoopCount = checkOpenMPLoop(
14171 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14172 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14173 VarsWithImplicitDSA, B);
14174 if (NestedLoopCount == 0)
14175 return StmtError();
14176
14177 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14178 return StmtError();
14179
14180 if (checkSimdlenSafelenSpecified(S&: SemaRef, Clauses))
14181 return StmtError();
14182
14183 return OMPTargetTeamsDistributeSimdDirective::Create(
14184 C: getASTContext(), StartLoc, EndLoc, CollapsedNum: NestedLoopCount, Clauses, AssociatedStmt: AStmt, Exprs: B);
14185}
14186
14187bool SemaOpenMP::checkTransformableLoopNest(
14188 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14189 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14190 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits) {
14191 OriginalInits.emplace_back();
14192 bool Result = OMPLoopBasedDirective::doForAllLoops(
14193 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14194 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14195 Stmt *CurStmt) {
14196 VarsWithInheritedDSAType TmpDSA;
14197 unsigned SingleNumLoops =
14198 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14199 TmpDSA, LoopHelpers[Cnt]);
14200 if (SingleNumLoops == 0)
14201 return true;
14202 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14203 if (auto *For = dyn_cast<ForStmt>(Val: CurStmt)) {
14204 OriginalInits.back().push_back(Elt: For->getInit());
14205 Body = For->getBody();
14206 } else {
14207 assert(isa<CXXForRangeStmt>(CurStmt) &&
14208 "Expected canonical for or range-based for loops.");
14209 auto *CXXFor = cast<CXXForRangeStmt>(Val: CurStmt);
14210 OriginalInits.back().push_back(Elt: CXXFor->getBeginStmt());
14211 Body = CXXFor->getBody();
14212 }
14213 OriginalInits.emplace_back();
14214 return false;
14215 },
14216 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14217 Stmt *DependentPreInits;
14218 if (auto *Dir = dyn_cast<OMPTileDirective>(Val: Transform))
14219 DependentPreInits = Dir->getPreInits();
14220 else if (auto *Dir = dyn_cast<OMPStripeDirective>(Val: Transform))
14221 DependentPreInits = Dir->getPreInits();
14222 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Val: Transform))
14223 DependentPreInits = Dir->getPreInits();
14224 else if (auto *Dir = dyn_cast<OMPReverseDirective>(Val: Transform))
14225 DependentPreInits = Dir->getPreInits();
14226 else if (auto *Dir = dyn_cast<OMPInterchangeDirective>(Val: Transform))
14227 DependentPreInits = Dir->getPreInits();
14228 else
14229 llvm_unreachable("Unhandled loop transformation");
14230
14231 appendFlattenedStmtList(TargetList&: OriginalInits.back(), Item: DependentPreInits);
14232 });
14233 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14234 OriginalInits.pop_back();
14235 return Result;
14236}
14237
14238/// Add preinit statements that need to be propageted from the selected loop.
14239static void addLoopPreInits(ASTContext &Context,
14240 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14241 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14242 SmallVectorImpl<Stmt *> &PreInits) {
14243
14244 // For range-based for-statements, ensure that their syntactic sugar is
14245 // executed by adding them as pre-init statements.
14246 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt)) {
14247 Stmt *RangeInit = CXXRangeFor->getInit();
14248 if (RangeInit)
14249 PreInits.push_back(Elt: RangeInit);
14250
14251 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14252 PreInits.push_back(Elt: new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14253 RangeStmt->getBeginLoc(),
14254 RangeStmt->getEndLoc()));
14255
14256 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14257 PreInits.push_back(Elt: new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14258 RangeEnd->getBeginLoc(),
14259 RangeEnd->getEndLoc()));
14260 }
14261
14262 llvm::append_range(C&: PreInits, R&: OriginalInit);
14263
14264 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14265 if (auto *PI = cast_or_null<DeclStmt>(Val: LoopHelper.PreInits)) {
14266 PreInits.push_back(Elt: new (Context) DeclStmt(
14267 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14268 }
14269
14270 // Gather declarations for the data members used as counters.
14271 for (Expr *CounterRef : LoopHelper.Counters) {
14272 auto *CounterDecl = cast<DeclRefExpr>(Val: CounterRef)->getDecl();
14273 if (isa<OMPCapturedExprDecl>(Val: CounterDecl))
14274 PreInits.push_back(Elt: new (Context) DeclStmt(
14275 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14276 }
14277}
14278
14279/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14280/// loop of a construct.
14281static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14282 size_t NumLoops = LoopStmts.size();
14283 OMPLoopBasedDirective::doForAllLoops(
14284 CurStmt: AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14285 Callback: [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14286 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14287 LoopStmts[Cnt] = CurStmt;
14288 return false;
14289 });
14290 assert(!is_contained(LoopStmts, nullptr) &&
14291 "Expecting a loop statement for each affected loop");
14292}
14293
14294/// Build and return a DeclRefExpr for the floor induction variable using the
14295/// SemaRef and the provided parameters.
14296static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
14297 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
14298 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14299 OrigCntVar->getExprLoc());
14300}
14301
14302StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
14303 Stmt *AStmt,
14304 SourceLocation StartLoc,
14305 SourceLocation EndLoc) {
14306 ASTContext &Context = getASTContext();
14307 Scope *CurScope = SemaRef.getCurScope();
14308
14309 const auto *SizesClause =
14310 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14311 if (!SizesClause ||
14312 llvm::any_of(Range: SizesClause->getSizesRefs(), P: [](Expr *E) { return !E; }))
14313 return StmtError();
14314 unsigned NumLoops = SizesClause->getNumSizes();
14315
14316 // Empty statement should only be possible if there already was an error.
14317 if (!AStmt)
14318 return StmtError();
14319
14320 // Verify and diagnose loop nest.
14321 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14322 Stmt *Body = nullptr;
14323 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14324 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14325 OriginalInits))
14326 return StmtError();
14327
14328 // Delay tiling to when template is completely instantiated.
14329 if (SemaRef.CurContext->isDependentContext())
14330 return OMPTileDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
14331 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
14332
14333 assert(LoopHelpers.size() == NumLoops &&
14334 "Expecting loop iteration space dimensionality to match number of "
14335 "affected loops");
14336 assert(OriginalInits.size() == NumLoops &&
14337 "Expecting loop iteration space dimensionality to match number of "
14338 "affected loops");
14339
14340 // Collect all affected loop statements.
14341 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14342 collectLoopStmts(AStmt, LoopStmts);
14343
14344 SmallVector<Stmt *, 4> PreInits;
14345 CaptureVars CopyTransformer(SemaRef);
14346
14347 // Create iteration variables for the generated loops.
14348 SmallVector<VarDecl *, 4> FloorIndVars;
14349 SmallVector<VarDecl *, 4> TileIndVars;
14350 FloorIndVars.resize(N: NumLoops);
14351 TileIndVars.resize(N: NumLoops);
14352 for (unsigned I = 0; I < NumLoops; ++I) {
14353 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14354
14355 assert(LoopHelper.Counters.size() == 1 &&
14356 "Expect single-dimensional loop iteration space");
14357 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
14358 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14359 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
14360 QualType CntTy = IterVarRef->getType();
14361
14362 // Iteration variable for the floor (i.e. outer) loop.
14363 {
14364 std::string FloorCntName =
14365 (Twine(".floor_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
14366 VarDecl *FloorCntDecl =
14367 buildVarDecl(SemaRef, Loc: {}, Type: CntTy, Name: FloorCntName, Attrs: nullptr, OrigRef: OrigCntVar);
14368 FloorIndVars[I] = FloorCntDecl;
14369 }
14370
14371 // Iteration variable for the tile (i.e. inner) loop.
14372 {
14373 std::string TileCntName =
14374 (Twine(".tile_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
14375
14376 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14377 // used by the expressions to derive the original iteration variable's
14378 // value from the logical iteration number.
14379 auto *TileCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
14380 TileCntDecl->setDeclName(
14381 &SemaRef.PP.getIdentifierTable().get(Name: TileCntName));
14382 TileIndVars[I] = TileCntDecl;
14383 }
14384
14385 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
14386 PreInits);
14387 }
14388
14389 // Once the original iteration values are set, append the innermost body.
14390 Stmt *Inner = Body;
14391
14392 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14393 SizesClause, CurScope](int I) -> Expr * {
14394 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14395
14396 if (DimTileSizeExpr->containsErrors())
14397 return nullptr;
14398
14399 if (isa<ConstantExpr>(Val: DimTileSizeExpr))
14400 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14401
14402 // When the tile size is not a constant but a variable, it is possible to
14403 // pass non-positive numbers. For instance:
14404 // \code{c}
14405 // int a = 0;
14406 // #pragma omp tile sizes(a)
14407 // for (int i = 0; i < 42; ++i)
14408 // body(i);
14409 // \endcode
14410 // Although there is no meaningful interpretation of the tile size, the body
14411 // should still be executed 42 times to avoid surprises. To preserve the
14412 // invariant that every loop iteration is executed exactly once and not
14413 // cause an infinite loop, apply a minimum tile size of one.
14414 // Build expr:
14415 // \code{c}
14416 // (TS <= 0) ? 1 : TS
14417 // \endcode
14418 QualType DimTy = DimTileSizeExpr->getType();
14419 uint64_t DimWidth = Context.getTypeSize(T: DimTy);
14420 IntegerLiteral *Zero = IntegerLiteral::Create(
14421 C: Context, V: llvm::APInt::getZero(numBits: DimWidth), type: DimTy, l: {});
14422 IntegerLiteral *One =
14423 IntegerLiteral::Create(C: Context, V: llvm::APInt(DimWidth, 1), type: DimTy, l: {});
14424 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
14425 S: CurScope, OpLoc: {}, Opc: BO_LE,
14426 LHSExpr: AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), RHSExpr: Zero));
14427 Expr *MinOne = new (Context) ConditionalOperator(
14428 Cond, {}, One, {},
14429 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14430 VK_PRValue, OK_Ordinary);
14431 return MinOne;
14432 };
14433
14434 // Create tile loops from the inside to the outside.
14435 for (int I = NumLoops - 1; I >= 0; --I) {
14436 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14437 Expr *NumIterations = LoopHelper.NumIterations;
14438 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
14439 QualType IVTy = NumIterations->getType();
14440 Stmt *LoopStmt = LoopStmts[I];
14441
14442 // Commonly used variables. One of the constraints of an AST is that every
14443 // node object must appear at most once, hence we define a lambda that
14444 // creates a new AST node at every use.
14445 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14446 OrigCntVar]() {
14447 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14448 OrigCntVar->getExprLoc());
14449 };
14450
14451 // For init-statement: auto .tile.iv = .floor.iv
14452 SemaRef.AddInitializerToDecl(
14453 TileIndVars[I],
14454 SemaRef
14455 .DefaultLvalueConversion(
14456 E: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14457 .get(),
14458 /*DirectInit=*/false);
14459 Decl *CounterDecl = TileIndVars[I];
14460 StmtResult InitStmt = new (Context)
14461 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
14462 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14463 if (!InitStmt.isUsable())
14464 return StmtError();
14465
14466 // For cond-expression:
14467 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14468 Expr *DimTileSize = MakeDimTileSize(I);
14469 if (!DimTileSize)
14470 return StmtError();
14471 ExprResult EndOfTile = SemaRef.BuildBinOp(
14472 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
14473 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14474 RHSExpr: DimTileSize);
14475 if (!EndOfTile.isUsable())
14476 return StmtError();
14477 ExprResult IsPartialTile =
14478 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
14479 LHSExpr: NumIterations, RHSExpr: EndOfTile.get());
14480 if (!IsPartialTile.isUsable())
14481 return StmtError();
14482 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14483 QuestionLoc: LoopHelper.Cond->getBeginLoc(), ColonLoc: LoopHelper.Cond->getEndLoc(),
14484 CondExpr: IsPartialTile.get(), LHSExpr: NumIterations, RHSExpr: EndOfTile.get());
14485 if (!MinTileAndIterSpace.isUsable())
14486 return StmtError();
14487 ExprResult CondExpr =
14488 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
14489 LHSExpr: MakeTileIVRef(), RHSExpr: MinTileAndIterSpace.get());
14490 if (!CondExpr.isUsable())
14491 return StmtError();
14492
14493 // For incr-statement: ++.tile.iv
14494 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14495 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeTileIVRef());
14496 if (!IncrStmt.isUsable())
14497 return StmtError();
14498
14499 // Statements to set the original iteration variable's value from the
14500 // logical iteration number.
14501 // Generated for loop is:
14502 // \code
14503 // Original_for_init;
14504 // for (auto .tile.iv = .floor.iv;
14505 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
14506 // ++.tile.iv) {
14507 // Original_Body;
14508 // Original_counter_update;
14509 // }
14510 // \endcode
14511 // FIXME: If the innermost body is an loop itself, inserting these
14512 // statements stops it being recognized as a perfectly nested loop (e.g.
14513 // for applying tiling again). If this is the case, sink the expressions
14514 // further into the inner loop.
14515 SmallVector<Stmt *, 4> BodyParts;
14516 BodyParts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
14517 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
14518 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
14519 BodyParts.push_back(Elt: Inner);
14520 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
14521 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
14522 Inner = new (Context)
14523 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14524 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14525 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14526 }
14527
14528 // Create floor loops from the inside to the outside.
14529 for (int I = NumLoops - 1; I >= 0; --I) {
14530 auto &LoopHelper = LoopHelpers[I];
14531 Expr *NumIterations = LoopHelper.NumIterations;
14532 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
14533 QualType IVTy = NumIterations->getType();
14534
14535 // For init-statement: auto .floor.iv = 0
14536 SemaRef.AddInitializerToDecl(
14537 FloorIndVars[I],
14538 SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
14539 /*DirectInit=*/false);
14540 Decl *CounterDecl = FloorIndVars[I];
14541 StmtResult InitStmt = new (Context)
14542 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
14543 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14544 if (!InitStmt.isUsable())
14545 return StmtError();
14546
14547 // For cond-expression: .floor.iv < NumIterations
14548 ExprResult CondExpr = SemaRef.BuildBinOp(
14549 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
14550 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14551 RHSExpr: NumIterations);
14552 if (!CondExpr.isUsable())
14553 return StmtError();
14554
14555 // For incr-statement: .floor.iv += DimTileSize
14556 Expr *DimTileSize = MakeDimTileSize(I);
14557 if (!DimTileSize)
14558 return StmtError();
14559 ExprResult IncrStmt = SemaRef.BuildBinOp(
14560 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
14561 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14562 RHSExpr: DimTileSize);
14563 if (!IncrStmt.isUsable())
14564 return StmtError();
14565
14566 Inner = new (Context)
14567 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14568 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14569 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14570 }
14571
14572 return OMPTileDirective::Create(C: Context, StartLoc, EndLoc, Clauses, NumLoops,
14573 AssociatedStmt: AStmt, TransformedStmt: Inner,
14574 PreInits: buildPreInits(Context, PreInits));
14575}
14576
14577StmtResult SemaOpenMP::ActOnOpenMPStripeDirective(ArrayRef<OMPClause *> Clauses,
14578 Stmt *AStmt,
14579 SourceLocation StartLoc,
14580 SourceLocation EndLoc) {
14581 ASTContext &Context = getASTContext();
14582 Scope *CurScope = SemaRef.getCurScope();
14583
14584 const auto *SizesClause =
14585 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14586 if (!SizesClause ||
14587 llvm::any_of(Range: SizesClause->getSizesRefs(), P: [](const Expr *SizeExpr) {
14588 return !SizeExpr || SizeExpr->containsErrors();
14589 }))
14590 return StmtError();
14591 unsigned NumLoops = SizesClause->getNumSizes();
14592
14593 // Empty statement should only be possible if there already was an error.
14594 if (!AStmt)
14595 return StmtError();
14596
14597 // Verify and diagnose loop nest.
14598 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14599 Stmt *Body = nullptr;
14600 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14601 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
14602 Body, OriginalInits))
14603 return StmtError();
14604
14605 // Delay striping to when template is completely instantiated.
14606 if (SemaRef.CurContext->isDependentContext())
14607 return OMPStripeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
14608 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
14609
14610 assert(LoopHelpers.size() == NumLoops &&
14611 "Expecting loop iteration space dimensionality to match number of "
14612 "affected loops");
14613 assert(OriginalInits.size() == NumLoops &&
14614 "Expecting loop iteration space dimensionality to match number of "
14615 "affected loops");
14616
14617 // Collect all affected loop statements.
14618 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14619 collectLoopStmts(AStmt, LoopStmts);
14620
14621 SmallVector<Stmt *, 4> PreInits;
14622 CaptureVars CopyTransformer(SemaRef);
14623
14624 // Create iteration variables for the generated loops.
14625 SmallVector<VarDecl *, 4> FloorIndVars;
14626 SmallVector<VarDecl *, 4> StripeIndVars;
14627 FloorIndVars.resize(N: NumLoops);
14628 StripeIndVars.resize(N: NumLoops);
14629 for (unsigned I : llvm::seq<unsigned>(Size: NumLoops)) {
14630 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14631
14632 assert(LoopHelper.Counters.size() == 1 &&
14633 "Expect single-dimensional loop iteration space");
14634 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
14635 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14636 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
14637 QualType CntTy = IterVarRef->getType();
14638
14639 // Iteration variable for the stripe (i.e. outer) loop.
14640 {
14641 std::string FloorCntName =
14642 (Twine(".floor_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
14643 VarDecl *FloorCntDecl =
14644 buildVarDecl(SemaRef, Loc: {}, Type: CntTy, Name: FloorCntName, Attrs: nullptr, OrigRef: OrigCntVar);
14645 FloorIndVars[I] = FloorCntDecl;
14646 }
14647
14648 // Iteration variable for the stripe (i.e. inner) loop.
14649 {
14650 std::string StripeCntName =
14651 (Twine(".stripe_") + llvm::utostr(X: I) + ".iv." + OrigVarName).str();
14652
14653 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14654 // used by the expressions to derive the original iteration variable's
14655 // value from the logical iteration number.
14656 auto *StripeCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
14657 StripeCntDecl->setDeclName(
14658 &SemaRef.PP.getIdentifierTable().get(Name: StripeCntName));
14659 StripeIndVars[I] = StripeCntDecl;
14660 }
14661
14662 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
14663 PreInits);
14664 }
14665
14666 // Once the original iteration values are set, append the innermost body.
14667 Stmt *Inner = Body;
14668
14669 auto MakeDimStripeSize = [&](int I) -> Expr * {
14670 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
14671 if (isa<ConstantExpr>(Val: DimStripeSizeExpr))
14672 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
14673
14674 // When the stripe size is not a constant but a variable, it is possible to
14675 // pass non-positive numbers. For instance:
14676 // \code{c}
14677 // int a = 0;
14678 // #pragma omp stripe sizes(a)
14679 // for (int i = 0; i < 42; ++i)
14680 // body(i);
14681 // \endcode
14682 // Although there is no meaningful interpretation of the stripe size, the
14683 // body should still be executed 42 times to avoid surprises. To preserve
14684 // the invariant that every loop iteration is executed exactly once and not
14685 // cause an infinite loop, apply a minimum stripe size of one.
14686 // Build expr:
14687 // \code{c}
14688 // (TS <= 0) ? 1 : TS
14689 // \endcode
14690 QualType DimTy = DimStripeSizeExpr->getType();
14691 uint64_t DimWidth = Context.getTypeSize(T: DimTy);
14692 IntegerLiteral *Zero = IntegerLiteral::Create(
14693 C: Context, V: llvm::APInt::getZero(numBits: DimWidth), type: DimTy, l: {});
14694 IntegerLiteral *One =
14695 IntegerLiteral::Create(C: Context, V: llvm::APInt(DimWidth, 1), type: DimTy, l: {});
14696 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
14697 S: CurScope, OpLoc: {}, Opc: BO_LE,
14698 LHSExpr: AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), RHSExpr: Zero));
14699 Expr *MinOne = new (Context) ConditionalOperator(
14700 Cond, {}, One, {},
14701 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
14702 VK_PRValue, OK_Ordinary);
14703 return MinOne;
14704 };
14705
14706 // Create stripe loops from the inside to the outside.
14707 for (int I = NumLoops - 1; I >= 0; --I) {
14708 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14709 Expr *NumIterations = LoopHelper.NumIterations;
14710 auto *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
14711 QualType IVTy = NumIterations->getType();
14712 Stmt *LoopStmt = LoopStmts[I];
14713
14714 // For init-statement: auto .stripe.iv = .floor.iv
14715 SemaRef.AddInitializerToDecl(
14716 StripeIndVars[I],
14717 SemaRef
14718 .DefaultLvalueConversion(
14719 E: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14720 .get(),
14721 /*DirectInit=*/false);
14722 Decl *CounterDecl = StripeIndVars[I];
14723 StmtResult InitStmt = new (Context)
14724 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
14725 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14726 if (!InitStmt.isUsable())
14727 return StmtError();
14728
14729 // For cond-expression:
14730 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
14731 ExprResult EndOfStripe = SemaRef.BuildBinOp(
14732 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
14733 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14734 RHSExpr: MakeDimStripeSize(I));
14735 if (!EndOfStripe.isUsable())
14736 return StmtError();
14737 ExprResult IsPartialStripe =
14738 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
14739 LHSExpr: NumIterations, RHSExpr: EndOfStripe.get());
14740 if (!IsPartialStripe.isUsable())
14741 return StmtError();
14742 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
14743 QuestionLoc: LoopHelper.Cond->getBeginLoc(), ColonLoc: LoopHelper.Cond->getEndLoc(),
14744 CondExpr: IsPartialStripe.get(), LHSExpr: NumIterations, RHSExpr: EndOfStripe.get());
14745 if (!MinStripeAndIterSpace.isUsable())
14746 return StmtError();
14747 ExprResult CondExpr = SemaRef.BuildBinOp(
14748 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
14749 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars: StripeIndVars, I, IVTy, OrigCntVar),
14750 RHSExpr: MinStripeAndIterSpace.get());
14751 if (!CondExpr.isUsable())
14752 return StmtError();
14753
14754 // For incr-statement: ++.stripe.iv
14755 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14756 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc,
14757 Input: makeFloorIVRef(SemaRef, FloorIndVars: StripeIndVars, I, IVTy, OrigCntVar));
14758 if (!IncrStmt.isUsable())
14759 return StmtError();
14760
14761 // Statements to set the original iteration variable's value from the
14762 // logical iteration number.
14763 // Generated for loop is:
14764 // \code
14765 // Original_for_init;
14766 // for (auto .stripe.iv = .floor.iv;
14767 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
14768 // ++.stripe.iv) {
14769 // Original_Body;
14770 // Original_counter_update;
14771 // }
14772 // \endcode
14773 // FIXME: If the innermost body is a loop itself, inserting these
14774 // statements stops it being recognized as a perfectly nested loop (e.g.
14775 // for applying another loop transformation). If this is the case, sink the
14776 // expressions further into the inner loop.
14777 SmallVector<Stmt *, 4> BodyParts;
14778 BodyParts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
14779 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
14780 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
14781 BodyParts.push_back(Elt: Inner);
14782 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
14783 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
14784 Inner = new (Context)
14785 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14786 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14787 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14788 }
14789
14790 // Create grid loops from the inside to the outside.
14791 for (int I = NumLoops - 1; I >= 0; --I) {
14792 auto &LoopHelper = LoopHelpers[I];
14793 Expr *NumIterations = LoopHelper.NumIterations;
14794 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(Val: LoopHelper.Counters[0]);
14795 QualType IVTy = NumIterations->getType();
14796
14797 // For init-statement: auto .grid.iv = 0
14798 SemaRef.AddInitializerToDecl(
14799 FloorIndVars[I],
14800 SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
14801 /*DirectInit=*/false);
14802 Decl *CounterDecl = FloorIndVars[I];
14803 StmtResult InitStmt = new (Context)
14804 DeclStmt(DeclGroupRef::Create(C&: Context, Decls: &CounterDecl, NumDecls: 1),
14805 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14806 if (!InitStmt.isUsable())
14807 return StmtError();
14808
14809 // For cond-expression: .floor.iv < NumIterations
14810 ExprResult CondExpr = SemaRef.BuildBinOp(
14811 S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
14812 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14813 RHSExpr: NumIterations);
14814 if (!CondExpr.isUsable())
14815 return StmtError();
14816
14817 // For incr-statement: .floor.iv += DimStripeSize
14818 ExprResult IncrStmt = SemaRef.BuildBinOp(
14819 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
14820 LHSExpr: makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14821 RHSExpr: MakeDimStripeSize(I));
14822 if (!IncrStmt.isUsable())
14823 return StmtError();
14824
14825 Inner = new (Context)
14826 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14827 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14828 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14829 }
14830
14831 return OMPStripeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
14832 NumLoops, AssociatedStmt: AStmt, TransformedStmt: Inner,
14833 PreInits: buildPreInits(Context, PreInits));
14834}
14835
14836StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
14837 Stmt *AStmt,
14838 SourceLocation StartLoc,
14839 SourceLocation EndLoc) {
14840 ASTContext &Context = getASTContext();
14841 Scope *CurScope = SemaRef.getCurScope();
14842 // Empty statement should only be possible if there already was an error.
14843 if (!AStmt)
14844 return StmtError();
14845
14846 if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
14847 {OMPC_partial, OMPC_full}))
14848 return StmtError();
14849
14850 const OMPFullClause *FullClause =
14851 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14852 const OMPPartialClause *PartialClause =
14853 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14854 assert(!(FullClause && PartialClause) &&
14855 "mutual exclusivity must have been checked before");
14856
14857 constexpr unsigned NumLoops = 1;
14858 Stmt *Body = nullptr;
14859 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
14860 NumLoops);
14861 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14862 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14863 Body, OriginalInits))
14864 return StmtError();
14865
14866 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14867
14868 // Delay unrolling to when template is completely instantiated.
14869 if (SemaRef.CurContext->isDependentContext())
14870 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
14871 NumGeneratedLoops, TransformedStmt: nullptr, PreInits: nullptr);
14872
14873 assert(LoopHelpers.size() == NumLoops &&
14874 "Expecting a single-dimensional loop iteration space");
14875 assert(OriginalInits.size() == NumLoops &&
14876 "Expecting a single-dimensional loop iteration space");
14877 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14878
14879 if (FullClause) {
14880 if (!VerifyPositiveIntegerConstantInClause(
14881 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
14882 /*SuppressExprDiags=*/true)
14883 .isUsable()) {
14884 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14885 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
14886 << "#pragma omp unroll full";
14887 return StmtError();
14888 }
14889 }
14890
14891 // The generated loop may only be passed to other loop-associated directive
14892 // when a partial clause is specified. Without the requirement it is
14893 // sufficient to generate loop unroll metadata at code-generation.
14894 if (NumGeneratedLoops == 0)
14895 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
14896 NumGeneratedLoops, TransformedStmt: nullptr, PreInits: nullptr);
14897
14898 // Otherwise, we need to provide a de-sugared/transformed AST that can be
14899 // associated with another loop directive.
14900 //
14901 // The canonical loop analysis return by checkTransformableLoopNest assumes
14902 // the following structure to be the same loop without transformations or
14903 // directives applied: \code OriginalInits; LoopHelper.PreInits;
14904 // LoopHelper.Counters;
14905 // for (; IV < LoopHelper.NumIterations; ++IV) {
14906 // LoopHelper.Updates;
14907 // Body;
14908 // }
14909 // \endcode
14910 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
14911 // and referenced by LoopHelper.IterationVarRef.
14912 //
14913 // The unrolling directive transforms this into the following loop:
14914 // \code
14915 // OriginalInits; \
14916 // LoopHelper.PreInits; > NewPreInits
14917 // LoopHelper.Counters; /
14918 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
14919 // #pragma clang loop unroll_count(Factor)
14920 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
14921 // {
14922 // LoopHelper.Updates;
14923 // Body;
14924 // }
14925 // }
14926 // \endcode
14927 // where UIV is a new logical iteration counter. IV must be the same VarDecl
14928 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
14929 // references it. If the partially unrolled loop is associated with another
14930 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
14931 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
14932 // OpenMP canonical loop. The inner loop is not an associable canonical loop
14933 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
14934 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
14935 // property of the OMPLoopBasedDirective instead of statements in
14936 // CompoundStatement. This is to allow the loop to become a non-outermost loop
14937 // of a canonical loop nest where these PreInits are emitted before the
14938 // outermost directive.
14939
14940 // Find the loop statement.
14941 Stmt *LoopStmt = nullptr;
14942 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
14943
14944 // Determine the PreInit declarations.
14945 SmallVector<Stmt *, 4> PreInits;
14946 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
14947
14948 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
14949 QualType IVTy = IterationVarRef->getType();
14950 assert(LoopHelper.Counters.size() == 1 &&
14951 "Expecting a single-dimensional loop iteration space");
14952 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
14953
14954 // Determine the unroll factor.
14955 uint64_t Factor;
14956 SourceLocation FactorLoc;
14957 if (Expr *FactorVal = PartialClause->getFactor();
14958 FactorVal && !FactorVal->containsErrors()) {
14959 Factor = FactorVal->getIntegerConstantExpr(Ctx: Context)->getZExtValue();
14960 FactorLoc = FactorVal->getExprLoc();
14961 } else {
14962 // TODO: Use a better profitability model.
14963 Factor = 2;
14964 }
14965 assert(Factor > 0 && "Expected positive unroll factor");
14966 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
14967 return IntegerLiteral::Create(
14968 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
14969 IVTy, FactorLoc);
14970 };
14971
14972 // Iteration variable SourceLocations.
14973 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14974 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14975 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14976
14977 // Internal variable names.
14978 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14979 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
14980 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
14981
14982 // Create the iteration variable for the unrolled loop.
14983 VarDecl *OuterIVDecl =
14984 buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: OuterIVName, Attrs: nullptr, OrigRef: OrigVar);
14985 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
14986 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
14987 };
14988
14989 // Iteration variable for the inner loop: Reuse the iteration variable created
14990 // by checkOpenMPLoop.
14991 auto *InnerIVDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
14992 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name: InnerIVName));
14993 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
14994 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
14995 };
14996
14997 // Make a copy of the NumIterations expression for each use: By the AST
14998 // constraints, every expression object in a DeclContext must be unique.
14999 CaptureVars CopyTransformer(SemaRef);
15000 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15001 return AssertSuccess(
15002 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15003 };
15004
15005 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15006 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(E: MakeOuterRef());
15007 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
15008 /*DirectInit=*/false);
15009 StmtResult InnerInit = new (Context)
15010 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15011 if (!InnerInit.isUsable())
15012 return StmtError();
15013
15014 // Inner For cond-expression:
15015 // \code
15016 // .unroll_inner.iv < .unrolled.iv + Factor &&
15017 // .unroll_inner.iv < NumIterations
15018 // \endcode
15019 // This conjunction of two conditions allows ScalarEvolution to derive the
15020 // maximum trip count of the inner loop.
15021 ExprResult EndOfTile =
15022 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_Add,
15023 LHSExpr: MakeOuterRef(), RHSExpr: MakeFactorExpr());
15024 if (!EndOfTile.isUsable())
15025 return StmtError();
15026 ExprResult InnerCond1 =
15027 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15028 LHSExpr: MakeInnerRef(), RHSExpr: EndOfTile.get());
15029 if (!InnerCond1.isUsable())
15030 return StmtError();
15031 ExprResult InnerCond2 =
15032 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15033 LHSExpr: MakeInnerRef(), RHSExpr: MakeNumIterations());
15034 if (!InnerCond2.isUsable())
15035 return StmtError();
15036 ExprResult InnerCond =
15037 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LAnd,
15038 LHSExpr: InnerCond1.get(), RHSExpr: InnerCond2.get());
15039 if (!InnerCond.isUsable())
15040 return StmtError();
15041
15042 // Inner For incr-statement: ++.unroll_inner.iv
15043 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15044 S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakeInnerRef());
15045 if (!InnerIncr.isUsable())
15046 return StmtError();
15047
15048 // Inner For statement.
15049 SmallVector<Stmt *> InnerBodyStmts;
15050 InnerBodyStmts.append(in_start: LoopHelper.Updates.begin(), in_end: LoopHelper.Updates.end());
15051 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
15052 InnerBodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
15053 InnerBodyStmts.push_back(Elt: Body);
15054 CompoundStmt *InnerBody =
15055 CompoundStmt::Create(C: getASTContext(), Stmts: InnerBodyStmts, FPFeatures: FPOptionsOverride(),
15056 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
15057 ForStmt *InnerFor = new (Context)
15058 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15059 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15060 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15061
15062 // Unroll metadata for the inner loop.
15063 // This needs to take into account the remainder portion of the unrolled loop,
15064 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15065 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15066 // the maximum trip count, which will also generate a remainder loop. Just
15067 // `unroll(enable)` (which could have been useful if the user has not
15068 // specified a concrete factor; even though the outer loop cannot be
15069 // influenced anymore, would avoid more code bloat than necessary) will refuse
15070 // the loop because "Won't unroll; remainder loop could not be generated when
15071 // assuming runtime trip count". Even if it did work, it must not choose a
15072 // larger unroll factor than the maximum loop length, or it would always just
15073 // execute the remainder loop.
15074 LoopHintAttr *UnrollHintAttr =
15075 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15076 LoopHintAttr::Numeric, MakeFactorExpr());
15077 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15078 C: getASTContext(), Loc: StartLoc, Attrs: {UnrollHintAttr}, SubStmt: InnerFor);
15079
15080 // Outer For init-statement: auto .unrolled.iv = 0
15081 SemaRef.AddInitializerToDecl(
15082 OuterIVDecl,
15083 SemaRef.ActOnIntegerConstant(Loc: LoopHelper.Init->getExprLoc(), Val: 0).get(),
15084 /*DirectInit=*/false);
15085 StmtResult OuterInit = new (Context)
15086 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15087 if (!OuterInit.isUsable())
15088 return StmtError();
15089
15090 // Outer For cond-expression: .unrolled.iv < NumIterations
15091 ExprResult OuterConde =
15092 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15093 LHSExpr: MakeOuterRef(), RHSExpr: MakeNumIterations());
15094 if (!OuterConde.isUsable())
15095 return StmtError();
15096
15097 // Outer For incr-statement: .unrolled.iv += Factor
15098 ExprResult OuterIncr =
15099 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(), Opc: BO_AddAssign,
15100 LHSExpr: MakeOuterRef(), RHSExpr: MakeFactorExpr());
15101 if (!OuterIncr.isUsable())
15102 return StmtError();
15103
15104 // Outer For statement.
15105 ForStmt *OuterFor = new (Context)
15106 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15107 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15108 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15109
15110 return OMPUnrollDirective::Create(C: Context, StartLoc, EndLoc, Clauses, AssociatedStmt: AStmt,
15111 NumGeneratedLoops, TransformedStmt: OuterFor,
15112 PreInits: buildPreInits(Context, PreInits));
15113}
15114
15115StmtResult SemaOpenMP::ActOnOpenMPReverseDirective(Stmt *AStmt,
15116 SourceLocation StartLoc,
15117 SourceLocation EndLoc) {
15118 ASTContext &Context = getASTContext();
15119 Scope *CurScope = SemaRef.getCurScope();
15120
15121 // Empty statement should only be possible if there already was an error.
15122 if (!AStmt)
15123 return StmtError();
15124
15125 constexpr unsigned NumLoops = 1;
15126 Stmt *Body = nullptr;
15127 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
15128 NumLoops);
15129 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
15130 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15131 Body, OriginalInits))
15132 return StmtError();
15133
15134 // Delay applying the transformation to when template is completely
15135 // instantiated.
15136 if (SemaRef.CurContext->isDependentContext())
15137 return OMPReverseDirective::Create(C: Context, StartLoc, EndLoc, AssociatedStmt: AStmt,
15138 TransformedStmt: nullptr, PreInits: nullptr);
15139
15140 assert(LoopHelpers.size() == NumLoops &&
15141 "Expecting a single-dimensional loop iteration space");
15142 assert(OriginalInits.size() == NumLoops &&
15143 "Expecting a single-dimensional loop iteration space");
15144 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15145
15146 // Find the loop statement.
15147 Stmt *LoopStmt = nullptr;
15148 collectLoopStmts(AStmt, LoopStmts: {LoopStmt});
15149
15150 // Determine the PreInit declarations.
15151 SmallVector<Stmt *> PreInits;
15152 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInit: OriginalInits[0], PreInits);
15153
15154 auto *IterationVarRef = cast<DeclRefExpr>(Val: LoopHelper.IterationVarRef);
15155 QualType IVTy = IterationVarRef->getType();
15156 uint64_t IVWidth = Context.getTypeSize(T: IVTy);
15157 auto *OrigVar = cast<DeclRefExpr>(Val: LoopHelper.Counters.front());
15158
15159 // Iteration variable SourceLocations.
15160 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15161 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15162 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15163
15164 // Locations pointing to the transformation.
15165 SourceLocation TransformLoc = StartLoc;
15166 SourceLocation TransformLocBegin = StartLoc;
15167 SourceLocation TransformLocEnd = EndLoc;
15168
15169 // Internal variable names.
15170 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15171 SmallString<64> ForwardIVName(".forward.iv.");
15172 ForwardIVName += OrigVarName;
15173 SmallString<64> ReversedIVName(".reversed.iv.");
15174 ReversedIVName += OrigVarName;
15175
15176 // LoopHelper.Updates will read the logical iteration number from
15177 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
15178 // that logical iteration from it, then assign it to the user loop counter
15179 // variable. We cannot directly use LoopHelper.IterationVarRef as the
15180 // induction variable of the generated loop because it may cause an underflow:
15181 // \code{.c}
15182 // for (unsigned i = 0; i < n; ++i)
15183 // body(i);
15184 // \endcode
15185 //
15186 // Naive reversal:
15187 // \code{.c}
15188 // for (unsigned i = n-1; i >= 0; --i)
15189 // body(i);
15190 // \endcode
15191 //
15192 // Instead, we introduce a new iteration variable representing the logical
15193 // iteration counter of the original loop, convert it to the logical iteration
15194 // number of the reversed loop, then let LoopHelper.Updates compute the user's
15195 // loop iteration variable from it.
15196 // \code{.cpp}
15197 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
15198 // auto .reversed.iv = n - .forward.iv - 1;
15199 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
15200 // body(i); // Body
15201 // }
15202 // \endcode
15203
15204 // Subexpressions with more than one use. One of the constraints of an AST is
15205 // that every node object must appear at most once, hence we define a lambda
15206 // that creates a new AST node at every use.
15207 CaptureVars CopyTransformer(SemaRef);
15208 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15209 return AssertSuccess(
15210 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15211 };
15212
15213 // Create the iteration variable for the forward loop (from 0 to n-1).
15214 VarDecl *ForwardIVDecl =
15215 buildVarDecl(SemaRef, Loc: {}, Type: IVTy, Name: ForwardIVName, Attrs: nullptr, OrigRef: OrigVar);
15216 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15217 OrigVarLoc]() {
15218 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
15219 };
15220
15221 // Iteration variable for the reversed induction variable (from n-1 downto 0):
15222 // Reuse the iteration variable created by checkOpenMPLoop.
15223 auto *ReversedIVDecl = cast<VarDecl>(Val: IterationVarRef->getDecl());
15224 ReversedIVDecl->setDeclName(
15225 &SemaRef.PP.getIdentifierTable().get(Name: ReversedIVName));
15226
15227 // For init-statement:
15228 // \code{.cpp}
15229 // auto .forward.iv = 0;
15230 // \endcode
15231 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(numBits: IVWidth),
15232 ForwardIVDecl->getType(), OrigVarLoc);
15233 SemaRef.AddInitializerToDecl(dcl: ForwardIVDecl, init: Zero, /*DirectInit=*/false);
15234 StmtResult Init = new (Context)
15235 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15236 if (!Init.isUsable())
15237 return StmtError();
15238
15239 // Forward iv cond-expression:
15240 // \code{.cpp}
15241 // .forward.iv < MakeNumIterations()
15242 // \endcode
15243 ExprResult Cond =
15244 SemaRef.BuildBinOp(S: CurScope, OpLoc: LoopHelper.Cond->getExprLoc(), Opc: BO_LT,
15245 LHSExpr: MakeForwardRef(), RHSExpr: MakeNumIterations());
15246 if (!Cond.isUsable())
15247 return StmtError();
15248
15249 // Forward incr-statement:
15250 // \code{.c}
15251 // ++.forward.iv
15252 // \endcode
15253 ExprResult Incr = SemaRef.BuildUnaryOp(S: CurScope, OpLoc: LoopHelper.Inc->getExprLoc(),
15254 Opc: UO_PreInc, Input: MakeForwardRef());
15255 if (!Incr.isUsable())
15256 return StmtError();
15257
15258 // Reverse the forward-iv:
15259 // \code{.cpp}
15260 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
15261 // \endcode
15262 auto *One = IntegerLiteral::Create(C: Context, V: llvm::APInt(IVWidth, 1), type: IVTy,
15263 l: TransformLoc);
15264 ExprResult Minus = SemaRef.BuildBinOp(S: CurScope, OpLoc: TransformLoc, Opc: BO_Sub,
15265 LHSExpr: MakeNumIterations(), RHSExpr: One);
15266 if (!Minus.isUsable())
15267 return StmtError();
15268 Minus = SemaRef.BuildBinOp(S: CurScope, OpLoc: TransformLoc, Opc: BO_Sub, LHSExpr: Minus.get(),
15269 RHSExpr: MakeForwardRef());
15270 if (!Minus.isUsable())
15271 return StmtError();
15272 StmtResult InitReversed = new (Context) DeclStmt(
15273 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15274 if (!InitReversed.isUsable())
15275 return StmtError();
15276 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
15277 /*DirectInit=*/false);
15278
15279 // The new loop body.
15280 SmallVector<Stmt *, 4> BodyStmts;
15281 BodyStmts.reserve(N: LoopHelper.Updates.size() + 2 +
15282 (isa<CXXForRangeStmt>(Val: LoopStmt) ? 1 : 0));
15283 BodyStmts.push_back(Elt: InitReversed.get());
15284 llvm::append_range(C&: BodyStmts, R&: LoopHelper.Updates);
15285 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(Val: LoopStmt))
15286 BodyStmts.push_back(Elt: CXXRangeFor->getLoopVarStmt());
15287 BodyStmts.push_back(Elt: Body);
15288 auto *ReversedBody =
15289 CompoundStmt::Create(C: Context, Stmts: BodyStmts, FPFeatures: FPOptionsOverride(),
15290 LB: Body->getBeginLoc(), RB: Body->getEndLoc());
15291
15292 // Finally create the reversed For-statement.
15293 auto *ReversedFor = new (Context)
15294 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
15295 ReversedBody, LoopHelper.Init->getBeginLoc(),
15296 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15297 return OMPReverseDirective::Create(C: Context, StartLoc, EndLoc, AssociatedStmt: AStmt,
15298 TransformedStmt: ReversedFor,
15299 PreInits: buildPreInits(Context, PreInits));
15300}
15301
15302StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
15303 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15304 SourceLocation EndLoc) {
15305 ASTContext &Context = getASTContext();
15306 DeclContext *CurContext = SemaRef.CurContext;
15307 Scope *CurScope = SemaRef.getCurScope();
15308
15309 // Empty statement should only be possible if there already was an error.
15310 if (!AStmt)
15311 return StmtError();
15312
15313 // interchange without permutation clause swaps two loops.
15314 const OMPPermutationClause *PermutationClause =
15315 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15316 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
15317
15318 // Verify and diagnose loop nest.
15319 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
15320 Stmt *Body = nullptr;
15321 SmallVector<SmallVector<Stmt *, 0>, 2> OriginalInits;
15322 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15323 LoopHelpers, Body, OriginalInits))
15324 return StmtError();
15325
15326 // Delay interchange to when template is completely instantiated.
15327 if (CurContext->isDependentContext())
15328 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15329 NumLoops, AssociatedStmt: AStmt, TransformedStmt: nullptr, PreInits: nullptr);
15330
15331 // An invalid expression in the permutation clause is set to nullptr in
15332 // ActOnOpenMPPermutationClause.
15333 if (PermutationClause &&
15334 llvm::is_contained(Range: PermutationClause->getArgsRefs(), Element: nullptr))
15335 return StmtError();
15336
15337 assert(LoopHelpers.size() == NumLoops &&
15338 "Expecting loop iteration space dimensionaly to match number of "
15339 "affected loops");
15340 assert(OriginalInits.size() == NumLoops &&
15341 "Expecting loop iteration space dimensionaly to match number of "
15342 "affected loops");
15343
15344 // Decode the permutation clause.
15345 SmallVector<uint64_t, 2> Permutation;
15346 if (!PermutationClause) {
15347 Permutation = {1, 0};
15348 } else {
15349 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
15350 llvm::BitVector Flags(PermArgs.size());
15351 for (Expr *PermArg : PermArgs) {
15352 std::optional<llvm::APSInt> PermCstExpr =
15353 PermArg->getIntegerConstantExpr(Ctx: Context);
15354 if (!PermCstExpr)
15355 continue;
15356 uint64_t PermInt = PermCstExpr->getZExtValue();
15357 assert(1 <= PermInt && PermInt <= NumLoops &&
15358 "Must be a permutation; diagnostic emitted in "
15359 "ActOnOpenMPPermutationClause");
15360 if (Flags[PermInt - 1]) {
15361 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15362 Diag(PermArg->getExprLoc(),
15363 diag::err_omp_interchange_permutation_value_repeated)
15364 << PermInt << ExprRange;
15365 continue;
15366 }
15367 Flags[PermInt - 1] = true;
15368
15369 Permutation.push_back(Elt: PermInt - 1);
15370 }
15371
15372 if (Permutation.size() != NumLoops)
15373 return StmtError();
15374 }
15375
15376 // Nothing to transform with trivial permutation.
15377 if (NumLoops <= 1 || llvm::all_of(Range: llvm::enumerate(First&: Permutation), P: [](auto P) {
15378 auto [Idx, Arg] = P;
15379 return Idx == Arg;
15380 }))
15381 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15382 NumLoops, AssociatedStmt: AStmt, TransformedStmt: AStmt, PreInits: nullptr);
15383
15384 // Find the affected loops.
15385 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15386 collectLoopStmts(AStmt, LoopStmts);
15387
15388 // Collect pre-init statements on the order before the permuation.
15389 SmallVector<Stmt *> PreInits;
15390 for (auto I : llvm::seq<int>(Size: NumLoops)) {
15391 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15392
15393 assert(LoopHelper.Counters.size() == 1 &&
15394 "Single-dimensional loop iteration space expected");
15395
15396 addLoopPreInits(Context, LoopHelper, LoopStmt: LoopStmts[I], OriginalInit: OriginalInits[I],
15397 PreInits);
15398 }
15399
15400 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
15401 CaptureVars CopyTransformer(SemaRef);
15402
15403 // Create the permuted loops from the inside to the outside of the
15404 // interchanged loop nest. Body of the innermost new loop is the original
15405 // innermost body.
15406 Stmt *Inner = Body;
15407 for (auto TargetIdx : llvm::reverse(C: llvm::seq<int>(Size: NumLoops))) {
15408 // Get the original loop that belongs to this new position.
15409 uint64_t SourceIdx = Permutation[TargetIdx];
15410 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15411 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15412 assert(SourceHelper.Counters.size() == 1 &&
15413 "Single-dimensional loop iteration space expected");
15414 auto *OrigCntVar = cast<DeclRefExpr>(Val: SourceHelper.Counters.front());
15415
15416 // Normalized loop counter variable: From 0 to n-1, always an integer type.
15417 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(Val: SourceHelper.IterationVarRef);
15418 QualType IVTy = IterVarRef->getType();
15419 assert(IVTy->isIntegerType() &&
15420 "Expected the logical iteration counter to be an integer");
15421
15422 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15423 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
15424
15425 // Make a copy of the NumIterations expression for each use: By the AST
15426 // constraints, every expression object in a DeclContext must be unique.
15427 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
15428 return AssertSuccess(
15429 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15430 };
15431
15432 // Iteration variable for the permuted loop. Reuse the one from
15433 // checkOpenMPLoop which will also be used to update the original loop
15434 // variable.
15435 SmallString<64> PermutedCntName(".permuted_");
15436 PermutedCntName.append(Refs: {llvm::utostr(X: TargetIdx), ".iv.", OrigVarName});
15437 auto *PermutedCntDecl = cast<VarDecl>(Val: IterVarRef->getDecl());
15438 PermutedCntDecl->setDeclName(
15439 &SemaRef.PP.getIdentifierTable().get(Name: PermutedCntName));
15440 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15441 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15442 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
15443 };
15444
15445 // For init-statement:
15446 // \code
15447 // auto .permuted_{target}.iv = 0
15448 // \endcode
15449 ExprResult Zero = SemaRef.ActOnIntegerConstant(Loc: OrigVarLoc, Val: 0);
15450 if (!Zero.isUsable())
15451 return StmtError();
15452 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
15453 /*DirectInit=*/false);
15454 StmtResult InitStmt = new (Context)
15455 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
15456 OrigCntVar->getEndLoc());
15457 if (!InitStmt.isUsable())
15458 return StmtError();
15459
15460 // For cond-expression:
15461 // \code
15462 // .permuted_{target}.iv < MakeNumIterations()
15463 // \endcode
15464 ExprResult CondExpr =
15465 SemaRef.BuildBinOp(S: CurScope, OpLoc: SourceHelper.Cond->getExprLoc(), Opc: BO_LT,
15466 LHSExpr: MakePermutedRef(), RHSExpr: MakeNumIterations());
15467 if (!CondExpr.isUsable())
15468 return StmtError();
15469
15470 // For incr-statement:
15471 // \code
15472 // ++.tile.iv
15473 // \endcode
15474 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15475 S: CurScope, OpLoc: SourceHelper.Inc->getExprLoc(), Opc: UO_PreInc, Input: MakePermutedRef());
15476 if (!IncrStmt.isUsable())
15477 return StmtError();
15478
15479 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
15480 SourceHelper.Updates.end());
15481 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(Val: SourceLoopStmt))
15482 BodyParts.push_back(Elt: SourceCXXFor->getLoopVarStmt());
15483 BodyParts.push_back(Elt: Inner);
15484 Inner = CompoundStmt::Create(C: Context, Stmts: BodyParts, FPFeatures: FPOptionsOverride(),
15485 LB: Inner->getBeginLoc(), RB: Inner->getEndLoc());
15486 Inner = new (Context) ForStmt(
15487 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
15488 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
15489 SourceHelper.Inc->getEndLoc());
15490 }
15491
15492 return OMPInterchangeDirective::Create(C: Context, StartLoc, EndLoc, Clauses,
15493 NumLoops, AssociatedStmt: AStmt, TransformedStmt: Inner,
15494 PreInits: buildPreInits(Context, PreInits));
15495}
15496
15497OMPClause *SemaOpenMP::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
15498 Expr *Expr,
15499 SourceLocation StartLoc,
15500 SourceLocation LParenLoc,
15501 SourceLocation EndLoc) {
15502 OMPClause *Res = nullptr;
15503 switch (Kind) {
15504 case OMPC_final:
15505 Res = ActOnOpenMPFinalClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
15506 break;
15507 case OMPC_num_threads:
15508 Res = ActOnOpenMPNumThreadsClause(NumThreads: Expr, StartLoc, LParenLoc, EndLoc);
15509 break;
15510 case OMPC_safelen:
15511 Res = ActOnOpenMPSafelenClause(Length: Expr, StartLoc, LParenLoc, EndLoc);
15512 break;
15513 case OMPC_simdlen:
15514 Res = ActOnOpenMPSimdlenClause(Length: Expr, StartLoc, LParenLoc, EndLoc);
15515 break;
15516 case OMPC_allocator:
15517 Res = ActOnOpenMPAllocatorClause(Allocator: Expr, StartLoc, LParenLoc, EndLoc);
15518 break;
15519 case OMPC_collapse:
15520 Res = ActOnOpenMPCollapseClause(NumForLoops: Expr, StartLoc, LParenLoc, EndLoc);
15521 break;
15522 case OMPC_ordered:
15523 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, NumForLoops: Expr);
15524 break;
15525 case OMPC_priority:
15526 Res = ActOnOpenMPPriorityClause(Priority: Expr, StartLoc, LParenLoc, EndLoc);
15527 break;
15528 case OMPC_hint:
15529 Res = ActOnOpenMPHintClause(Hint: Expr, StartLoc, LParenLoc, EndLoc);
15530 break;
15531 case OMPC_depobj:
15532 Res = ActOnOpenMPDepobjClause(Depobj: Expr, StartLoc, LParenLoc, EndLoc);
15533 break;
15534 case OMPC_detach:
15535 Res = ActOnOpenMPDetachClause(Evt: Expr, StartLoc, LParenLoc, EndLoc);
15536 break;
15537 case OMPC_novariants:
15538 Res = ActOnOpenMPNovariantsClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
15539 break;
15540 case OMPC_nocontext:
15541 Res = ActOnOpenMPNocontextClause(Condition: Expr, StartLoc, LParenLoc, EndLoc);
15542 break;
15543 case OMPC_filter:
15544 Res = ActOnOpenMPFilterClause(ThreadID: Expr, StartLoc, LParenLoc, EndLoc);
15545 break;
15546 case OMPC_partial:
15547 Res = ActOnOpenMPPartialClause(FactorExpr: Expr, StartLoc, LParenLoc, EndLoc);
15548 break;
15549 case OMPC_message:
15550 Res = ActOnOpenMPMessageClause(MS: Expr, StartLoc, LParenLoc, EndLoc);
15551 break;
15552 case OMPC_align:
15553 Res = ActOnOpenMPAlignClause(Alignment: Expr, StartLoc, LParenLoc, EndLoc);
15554 break;
15555 case OMPC_ompx_dyn_cgroup_mem:
15556 Res = ActOnOpenMPXDynCGroupMemClause(Size: Expr, StartLoc, LParenLoc, EndLoc);
15557 break;
15558 case OMPC_holds:
15559 Res = ActOnOpenMPHoldsClause(E: Expr, StartLoc, LParenLoc, EndLoc);
15560 break;
15561 case OMPC_grainsize:
15562 case OMPC_num_tasks:
15563 case OMPC_device:
15564 case OMPC_if:
15565 case OMPC_default:
15566 case OMPC_proc_bind:
15567 case OMPC_schedule:
15568 case OMPC_private:
15569 case OMPC_firstprivate:
15570 case OMPC_lastprivate:
15571 case OMPC_shared:
15572 case OMPC_reduction:
15573 case OMPC_task_reduction:
15574 case OMPC_in_reduction:
15575 case OMPC_linear:
15576 case OMPC_aligned:
15577 case OMPC_copyin:
15578 case OMPC_copyprivate:
15579 case OMPC_nowait:
15580 case OMPC_untied:
15581 case OMPC_mergeable:
15582 case OMPC_threadprivate:
15583 case OMPC_sizes:
15584 case OMPC_allocate:
15585 case OMPC_flush:
15586 case OMPC_read:
15587 case OMPC_write:
15588 case OMPC_update:
15589 case OMPC_capture:
15590 case OMPC_compare:
15591 case OMPC_seq_cst:
15592 case OMPC_acq_rel:
15593 case OMPC_acquire:
15594 case OMPC_release:
15595 case OMPC_relaxed:
15596 case OMPC_depend:
15597 case OMPC_threads:
15598 case OMPC_simd:
15599 case OMPC_map:
15600 case OMPC_nogroup:
15601 case OMPC_dist_schedule:
15602 case OMPC_defaultmap:
15603 case OMPC_unknown:
15604 case OMPC_uniform:
15605 case OMPC_to:
15606 case OMPC_from:
15607 case OMPC_use_device_ptr:
15608 case OMPC_use_device_addr:
15609 case OMPC_is_device_ptr:
15610 case OMPC_unified_address:
15611 case OMPC_unified_shared_memory:
15612 case OMPC_reverse_offload:
15613 case OMPC_dynamic_allocators:
15614 case OMPC_atomic_default_mem_order:
15615 case OMPC_self_maps:
15616 case OMPC_device_type:
15617 case OMPC_match:
15618 case OMPC_nontemporal:
15619 case OMPC_order:
15620 case OMPC_at:
15621 case OMPC_severity:
15622 case OMPC_destroy:
15623 case OMPC_inclusive:
15624 case OMPC_exclusive:
15625 case OMPC_uses_allocators:
15626 case OMPC_affinity:
15627 case OMPC_when:
15628 case OMPC_bind:
15629 case OMPC_num_teams:
15630 case OMPC_thread_limit:
15631 default:
15632 llvm_unreachable("Clause is not allowed.");
15633 }
15634 return Res;
15635}
15636
15637// An OpenMP directive such as 'target parallel' has two captured regions:
15638// for the 'target' and 'parallel' respectively. This function returns
15639// the region in which to capture expressions associated with a clause.
15640// A return value of OMPD_unknown signifies that the expression should not
15641// be captured.
15642static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
15643 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15644 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15645 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15646 "Invalid directive with CKind-clause");
15647
15648 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
15649 if (NameModifier != OMPD_unknown &&
15650 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15651 return OMPD_unknown;
15652
15653 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
15654
15655 // [5.2:341:24-30]
15656 // If the clauses have expressions on them, such as for various clauses where
15657 // the argument of the clause is an expression, or lower-bound, length, or
15658 // stride expressions inside array sections (or subscript and stride
15659 // expressions in subscript-triplet for Fortran), or linear-step or alignment
15660 // expressions, the expressions are evaluated immediately before the construct
15661 // to which the clause has been split or duplicated per the above rules
15662 // (therefore inside of the outer leaf constructs). However, the expressions
15663 // inside the num_teams and thread_limit clauses are always evaluated before
15664 // the outermost leaf construct.
15665
15666 // Process special cases first.
15667 switch (CKind) {
15668 case OMPC_if:
15669 switch (DKind) {
15670 case OMPD_teams_loop:
15671 case OMPD_target_teams_loop:
15672 // For [target] teams loop, assume capture region is 'teams' so it's
15673 // available for codegen later to use if/when necessary.
15674 return OMPD_teams;
15675 case OMPD_target_update:
15676 case OMPD_target_enter_data:
15677 case OMPD_target_exit_data:
15678 return OMPD_task;
15679 default:
15680 break;
15681 }
15682 break;
15683 case OMPC_num_teams:
15684 case OMPC_thread_limit:
15685 case OMPC_ompx_dyn_cgroup_mem:
15686 if (Leafs[0] == OMPD_target)
15687 return OMPD_target;
15688 break;
15689 case OMPC_device:
15690 if (Leafs[0] == OMPD_target ||
15691 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15692 OMPD_target_enter_data, OMPD_target_exit_data},
15693 DKind))
15694 return OMPD_task;
15695 break;
15696 case OMPC_novariants:
15697 case OMPC_nocontext:
15698 if (DKind == OMPD_dispatch)
15699 return OMPD_task;
15700 break;
15701 case OMPC_when:
15702 if (DKind == OMPD_metadirective)
15703 return OMPD_metadirective;
15704 break;
15705 case OMPC_filter:
15706 return OMPD_unknown;
15707 default:
15708 break;
15709 }
15710
15711 // If none of the special cases above applied, and DKind is a capturing
15712 // directive, find the innermost enclosing leaf construct that allows the
15713 // clause, and returns the corresponding capture region.
15714
15715 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
15716 // Find the index in "Leafs" of the last leaf that allows the given
15717 // clause. The search will only include indexes [0, EndIdx).
15718 // EndIdx may be set to the index of the NameModifier, if present.
15719 int InnermostIdx = [&]() {
15720 for (int I = EndIdx - 1; I >= 0; --I) {
15721 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15722 return I;
15723 }
15724 return -1;
15725 }();
15726
15727 // Find the nearest enclosing capture region.
15728 SmallVector<OpenMPDirectiveKind, 2> Regions;
15729 for (int I = InnermostIdx - 1; I >= 0; --I) {
15730 if (!isOpenMPCapturingDirective(Leafs[I]))
15731 continue;
15732 Regions.clear();
15733 getOpenMPCaptureRegions(Regions, Leafs[I]);
15734 if (Regions[0] != OMPD_unknown)
15735 return Regions.back();
15736 }
15737 return OMPD_unknown;
15738 };
15739
15740 if (isOpenMPCapturingDirective(DKind)) {
15741 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
15742 for (int I = 0, E = Leafs.size(); I != E; ++I) {
15743 if (Leafs[I] == Dir)
15744 return I + 1;
15745 }
15746 return 0;
15747 };
15748
15749 int End = NameModifier == OMPD_unknown ? Leafs.size()
15750 : GetLeafIndex(NameModifier);
15751 return GetEnclosingRegion(End, CKind);
15752 }
15753
15754 return OMPD_unknown;
15755}
15756
15757OMPClause *SemaOpenMP::ActOnOpenMPIfClause(
15758 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
15759 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
15760 SourceLocation ColonLoc, SourceLocation EndLoc) {
15761 Expr *ValExpr = Condition;
15762 Stmt *HelperValStmt = nullptr;
15763 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15764 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15765 !Condition->isInstantiationDependent() &&
15766 !Condition->containsUnexpandedParameterPack()) {
15767 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
15768 if (Val.isInvalid())
15769 return nullptr;
15770
15771 ValExpr = Val.get();
15772
15773 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15774 CaptureRegion = getOpenMPCaptureRegionForClause(
15775 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
15776 if (CaptureRegion != OMPD_unknown &&
15777 !SemaRef.CurContext->isDependentContext()) {
15778 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
15779 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15780 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
15781 HelperValStmt = buildPreInits(getASTContext(), Captures);
15782 }
15783 }
15784
15785 return new (getASTContext())
15786 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15787 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15788}
15789
15790OMPClause *SemaOpenMP::ActOnOpenMPFinalClause(Expr *Condition,
15791 SourceLocation StartLoc,
15792 SourceLocation LParenLoc,
15793 SourceLocation EndLoc) {
15794 Expr *ValExpr = Condition;
15795 Stmt *HelperValStmt = nullptr;
15796 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15797 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15798 !Condition->isInstantiationDependent() &&
15799 !Condition->containsUnexpandedParameterPack()) {
15800 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
15801 if (Val.isInvalid())
15802 return nullptr;
15803
15804 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
15805
15806 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15807 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
15808 getLangOpts().OpenMP);
15809 if (CaptureRegion != OMPD_unknown &&
15810 !SemaRef.CurContext->isDependentContext()) {
15811 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
15812 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15813 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
15814 HelperValStmt = buildPreInits(getASTContext(), Captures);
15815 }
15816 }
15817
15818 return new (getASTContext()) OMPFinalClause(
15819 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15820}
15821
15822ExprResult
15823SemaOpenMP::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
15824 Expr *Op) {
15825 if (!Op)
15826 return ExprError();
15827
15828 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
15829 public:
15830 IntConvertDiagnoser()
15831 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
15832 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
15833 QualType T) override {
15834 return S.Diag(Loc, diag::err_omp_not_integral) << T;
15835 }
15836 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
15837 QualType T) override {
15838 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
15839 }
15840 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
15841 QualType T,
15842 QualType ConvTy) override {
15843 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
15844 }
15845 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
15846 QualType ConvTy) override {
15847 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15848 << ConvTy->isEnumeralType() << ConvTy;
15849 }
15850 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
15851 QualType T) override {
15852 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
15853 }
15854 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
15855 QualType ConvTy) override {
15856 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15857 << ConvTy->isEnumeralType() << ConvTy;
15858 }
15859 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
15860 QualType) override {
15861 llvm_unreachable("conversion functions are permitted");
15862 }
15863 } ConvertDiagnoser;
15864 return SemaRef.PerformContextualImplicitConversion(Loc, FromE: Op, Converter&: ConvertDiagnoser);
15865}
15866
15867static bool
15868isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
15869 bool StrictlyPositive, bool BuildCapture = false,
15870 OpenMPDirectiveKind DKind = OMPD_unknown,
15871 OpenMPDirectiveKind *CaptureRegion = nullptr,
15872 Stmt **HelperValStmt = nullptr) {
15873 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
15874 !ValExpr->isInstantiationDependent()) {
15875 SourceLocation Loc = ValExpr->getExprLoc();
15876 ExprResult Value =
15877 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, Op: ValExpr);
15878 if (Value.isInvalid())
15879 return false;
15880
15881 ValExpr = Value.get();
15882 // The expression must evaluate to a non-negative integer value.
15883 if (std::optional<llvm::APSInt> Result =
15884 ValExpr->getIntegerConstantExpr(Ctx: SemaRef.Context)) {
15885 if (Result->isSigned() &&
15886 !((!StrictlyPositive && Result->isNonNegative()) ||
15887 (StrictlyPositive && Result->isStrictlyPositive()))) {
15888 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
15889 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
15890 << ValExpr->getSourceRange();
15891 return false;
15892 }
15893 }
15894 if (!BuildCapture)
15895 return true;
15896 *CaptureRegion =
15897 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
15898 if (*CaptureRegion != OMPD_unknown &&
15899 !SemaRef.CurContext->isDependentContext()) {
15900 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
15901 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15902 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
15903 *HelperValStmt = buildPreInits(Context&: SemaRef.Context, Captures);
15904 }
15905 }
15906 return true;
15907}
15908
15909OMPClause *SemaOpenMP::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
15910 SourceLocation StartLoc,
15911 SourceLocation LParenLoc,
15912 SourceLocation EndLoc) {
15913 Expr *ValExpr = NumThreads;
15914 Stmt *HelperValStmt = nullptr;
15915
15916 // OpenMP [2.5, Restrictions]
15917 // The num_threads expression must evaluate to a positive integer value.
15918 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
15919 /*StrictlyPositive=*/true))
15920 return nullptr;
15921
15922 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15923 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
15924 DKind, OMPC_num_threads, getLangOpts().OpenMP);
15925 if (CaptureRegion != OMPD_unknown &&
15926 !SemaRef.CurContext->isDependentContext()) {
15927 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
15928 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15929 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
15930 HelperValStmt = buildPreInits(getASTContext(), Captures);
15931 }
15932
15933 return new (getASTContext()) OMPNumThreadsClause(
15934 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15935}
15936
15937ExprResult SemaOpenMP::VerifyPositiveIntegerConstantInClause(
15938 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
15939 bool SuppressExprDiags) {
15940 if (!E)
15941 return ExprError();
15942 if (E->isValueDependent() || E->isTypeDependent() ||
15943 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
15944 return E;
15945
15946 llvm::APSInt Result;
15947 ExprResult ICE;
15948 if (SuppressExprDiags) {
15949 // Use a custom diagnoser that suppresses 'note' diagnostics about the
15950 // expression.
15951 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
15952 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
15953 SemaBase::SemaDiagnosticBuilder
15954 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
15955 llvm_unreachable("Diagnostic suppressed");
15956 }
15957 } Diagnoser;
15958 ICE = SemaRef.VerifyIntegerConstantExpression(E, Result: &Result, Diagnoser,
15959 CanFold: AllowFoldKind::Allow);
15960 } else {
15961 ICE =
15962 SemaRef.VerifyIntegerConstantExpression(E, Result: &Result,
15963 /*FIXME*/ CanFold: AllowFoldKind::Allow);
15964 }
15965 if (ICE.isInvalid())
15966 return ExprError();
15967
15968 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
15969 (!StrictlyPositive && !Result.isNonNegative())) {
15970 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
15971 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
15972 << E->getSourceRange();
15973 return ExprError();
15974 }
15975 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
15976 CKind == OMPC_allocate) &&
15977 !Result.isPowerOf2()) {
15978 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
15979 << E->getSourceRange();
15980 return ExprError();
15981 }
15982
15983 if (!Result.isRepresentableByInt64()) {
15984 Diag(E->getExprLoc(), diag::err_omp_large_expression_in_clause)
15985 << getOpenMPClauseNameForDiag(CKind) << E->getSourceRange();
15986 return ExprError();
15987 }
15988
15989 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
15990 DSAStack->setAssociatedLoops(Result.getExtValue());
15991 else if (CKind == OMPC_ordered)
15992 DSAStack->setAssociatedLoops(Result.getExtValue());
15993 return ICE;
15994}
15995
15996void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
15997
15998void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
15999
16000int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
16001
16002void SemaOpenMP::ActOnOpenMPDeviceNum(Expr *DeviceNumExpr) {
16003 llvm::APSInt Result;
16004 Expr::EvalResult EvalResult;
16005 // Evaluate the expression to an integer value
16006 if (!DeviceNumExpr->isValueDependent() &&
16007 DeviceNumExpr->EvaluateAsInt(Result&: EvalResult, Ctx: SemaRef.Context)) {
16008 // The device expression must evaluate to a non-negative integer value.
16009 Result = EvalResult.Val.getInt();
16010 if (Result.isNonNegative()) {
16011 setOpenMPDeviceNum(Result.getZExtValue());
16012 } else {
16013 Diag(DeviceNumExpr->getExprLoc(),
16014 diag::err_omp_negative_expression_in_clause)
16015 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
16016 }
16017 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(Val: DeviceNumExpr)) {
16018 // Check if the expression is an identifier
16019 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
16020 if (IdInfo) {
16021 setOpenMPDeviceNumID(IdInfo->getName());
16022 }
16023 } else {
16024 Diag(DeviceNumExpr->getExprLoc(), diag::err_expected_expression);
16025 }
16026}
16027
16028OMPClause *SemaOpenMP::ActOnOpenMPSafelenClause(Expr *Len,
16029 SourceLocation StartLoc,
16030 SourceLocation LParenLoc,
16031 SourceLocation EndLoc) {
16032 // OpenMP [2.8.1, simd construct, Description]
16033 // The parameter of the safelen clause must be a constant
16034 // positive integer expression.
16035 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16036 if (Safelen.isInvalid())
16037 return nullptr;
16038 return new (getASTContext())
16039 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16040}
16041
16042OMPClause *SemaOpenMP::ActOnOpenMPSimdlenClause(Expr *Len,
16043 SourceLocation StartLoc,
16044 SourceLocation LParenLoc,
16045 SourceLocation EndLoc) {
16046 // OpenMP [2.8.1, simd construct, Description]
16047 // The parameter of the simdlen clause must be a constant
16048 // positive integer expression.
16049 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
16050 if (Simdlen.isInvalid())
16051 return nullptr;
16052 return new (getASTContext())
16053 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16054}
16055
16056/// Tries to find omp_allocator_handle_t type.
16057static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
16058 DSAStackTy *Stack) {
16059 if (!Stack->getOMPAllocatorHandleT().isNull())
16060 return true;
16061
16062 // Set the allocator handle type.
16063 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_allocator_handle_t");
16064 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
16065 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
16066 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16067 << "omp_allocator_handle_t";
16068 return false;
16069 }
16070 QualType AllocatorHandleEnumTy = PT.get();
16071 AllocatorHandleEnumTy.addConst();
16072 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16073
16074 // Fill the predefined allocator map.
16075 bool ErrorFound = false;
16076 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16077 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16078 StringRef Allocator =
16079 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16080 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
16081 auto *VD = dyn_cast_or_null<ValueDecl>(
16082 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
16083 if (!VD) {
16084 ErrorFound = true;
16085 break;
16086 }
16087 QualType AllocatorType =
16088 VD->getType().getNonLValueExprType(S.getASTContext());
16089 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
16090 if (!Res.isUsable()) {
16091 ErrorFound = true;
16092 break;
16093 }
16094 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
16095 AssignmentAction::Initializing,
16096 /*AllowExplicit=*/true);
16097 if (!Res.isUsable()) {
16098 ErrorFound = true;
16099 break;
16100 }
16101 Stack->setAllocator(AllocatorKind, Res.get());
16102 }
16103 if (ErrorFound) {
16104 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16105 << "omp_allocator_handle_t";
16106 return false;
16107 }
16108
16109 return true;
16110}
16111
16112OMPClause *SemaOpenMP::ActOnOpenMPAllocatorClause(Expr *A,
16113 SourceLocation StartLoc,
16114 SourceLocation LParenLoc,
16115 SourceLocation EndLoc) {
16116 // OpenMP [2.11.3, allocate Directive, Description]
16117 // allocator is an expression of omp_allocator_handle_t type.
16118 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: A->getExprLoc(), DSAStack))
16119 return nullptr;
16120
16121 ExprResult Allocator = SemaRef.DefaultLvalueConversion(E: A);
16122 if (Allocator.isInvalid())
16123 return nullptr;
16124 Allocator = SemaRef.PerformImplicitConversion(
16125 From: Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
16126 Action: AssignmentAction::Initializing,
16127 /*AllowExplicit=*/true);
16128 if (Allocator.isInvalid())
16129 return nullptr;
16130 return new (getASTContext())
16131 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
16132}
16133
16134OMPClause *SemaOpenMP::ActOnOpenMPCollapseClause(Expr *NumForLoops,
16135 SourceLocation StartLoc,
16136 SourceLocation LParenLoc,
16137 SourceLocation EndLoc) {
16138 // OpenMP [2.7.1, loop construct, Description]
16139 // OpenMP [2.8.1, simd construct, Description]
16140 // OpenMP [2.9.6, distribute construct, Description]
16141 // The parameter of the collapse clause must be a constant
16142 // positive integer expression.
16143 ExprResult NumForLoopsResult =
16144 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
16145 if (NumForLoopsResult.isInvalid())
16146 return nullptr;
16147 return new (getASTContext())
16148 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
16149}
16150
16151OMPClause *SemaOpenMP::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
16152 SourceLocation EndLoc,
16153 SourceLocation LParenLoc,
16154 Expr *NumForLoops) {
16155 // OpenMP [2.7.1, loop construct, Description]
16156 // OpenMP [2.8.1, simd construct, Description]
16157 // OpenMP [2.9.6, distribute construct, Description]
16158 // The parameter of the ordered clause must be a constant
16159 // positive integer expression if any.
16160 if (NumForLoops && LParenLoc.isValid()) {
16161 ExprResult NumForLoopsResult =
16162 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
16163 if (NumForLoopsResult.isInvalid())
16164 return nullptr;
16165 NumForLoops = NumForLoopsResult.get();
16166 } else {
16167 NumForLoops = nullptr;
16168 }
16169 auto *Clause =
16170 OMPOrderedClause::Create(C: getASTContext(), Num: NumForLoops,
16171 NumLoops: NumForLoops ? DSAStack->getAssociatedLoops() : 0,
16172 StartLoc, LParenLoc, EndLoc);
16173 DSAStack->setOrderedRegion(/*IsOrdered=*/true, Param: NumForLoops, Clause: Clause);
16174 return Clause;
16175}
16176
16177OMPClause *SemaOpenMP::ActOnOpenMPSimpleClause(
16178 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
16179 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16180 OMPClause *Res = nullptr;
16181 switch (Kind) {
16182 case OMPC_default:
16183 Res = ActOnOpenMPDefaultClause(Kind: static_cast<DefaultKind>(Argument),
16184 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16185 break;
16186 case OMPC_proc_bind:
16187 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
16188 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16189 break;
16190 case OMPC_atomic_default_mem_order:
16191 Res = ActOnOpenMPAtomicDefaultMemOrderClause(
16192 Kind: static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
16193 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16194 break;
16195 case OMPC_fail:
16196 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
16197 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16198 break;
16199 case OMPC_update:
16200 Res = ActOnOpenMPUpdateClause(Kind: static_cast<OpenMPDependClauseKind>(Argument),
16201 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16202 break;
16203 case OMPC_bind:
16204 Res = ActOnOpenMPBindClause(Kind: static_cast<OpenMPBindClauseKind>(Argument),
16205 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16206 break;
16207 case OMPC_at:
16208 Res = ActOnOpenMPAtClause(Kind: static_cast<OpenMPAtClauseKind>(Argument),
16209 KindLoc: ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16210 break;
16211 case OMPC_severity:
16212 Res = ActOnOpenMPSeverityClause(
16213 Kind: static_cast<OpenMPSeverityClauseKind>(Argument), KindLoc: ArgumentLoc, StartLoc,
16214 LParenLoc, EndLoc);
16215 break;
16216 case OMPC_if:
16217 case OMPC_final:
16218 case OMPC_num_threads:
16219 case OMPC_safelen:
16220 case OMPC_simdlen:
16221 case OMPC_sizes:
16222 case OMPC_allocator:
16223 case OMPC_collapse:
16224 case OMPC_schedule:
16225 case OMPC_private:
16226 case OMPC_firstprivate:
16227 case OMPC_lastprivate:
16228 case OMPC_shared:
16229 case OMPC_reduction:
16230 case OMPC_task_reduction:
16231 case OMPC_in_reduction:
16232 case OMPC_linear:
16233 case OMPC_aligned:
16234 case OMPC_copyin:
16235 case OMPC_copyprivate:
16236 case OMPC_ordered:
16237 case OMPC_nowait:
16238 case OMPC_untied:
16239 case OMPC_mergeable:
16240 case OMPC_threadprivate:
16241 case OMPC_allocate:
16242 case OMPC_flush:
16243 case OMPC_depobj:
16244 case OMPC_read:
16245 case OMPC_write:
16246 case OMPC_capture:
16247 case OMPC_compare:
16248 case OMPC_seq_cst:
16249 case OMPC_acq_rel:
16250 case OMPC_acquire:
16251 case OMPC_release:
16252 case OMPC_relaxed:
16253 case OMPC_depend:
16254 case OMPC_device:
16255 case OMPC_threads:
16256 case OMPC_simd:
16257 case OMPC_map:
16258 case OMPC_num_teams:
16259 case OMPC_thread_limit:
16260 case OMPC_priority:
16261 case OMPC_grainsize:
16262 case OMPC_nogroup:
16263 case OMPC_num_tasks:
16264 case OMPC_hint:
16265 case OMPC_dist_schedule:
16266 case OMPC_defaultmap:
16267 case OMPC_unknown:
16268 case OMPC_uniform:
16269 case OMPC_to:
16270 case OMPC_from:
16271 case OMPC_use_device_ptr:
16272 case OMPC_use_device_addr:
16273 case OMPC_is_device_ptr:
16274 case OMPC_has_device_addr:
16275 case OMPC_unified_address:
16276 case OMPC_unified_shared_memory:
16277 case OMPC_reverse_offload:
16278 case OMPC_dynamic_allocators:
16279 case OMPC_self_maps:
16280 case OMPC_device_type:
16281 case OMPC_match:
16282 case OMPC_nontemporal:
16283 case OMPC_destroy:
16284 case OMPC_novariants:
16285 case OMPC_nocontext:
16286 case OMPC_detach:
16287 case OMPC_inclusive:
16288 case OMPC_exclusive:
16289 case OMPC_uses_allocators:
16290 case OMPC_affinity:
16291 case OMPC_when:
16292 case OMPC_message:
16293 default:
16294 llvm_unreachable("Clause is not allowed.");
16295 }
16296 return Res;
16297}
16298
16299static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
16300 unsigned Last,
16301 ArrayRef<unsigned> Exclude = {}) {
16302 SmallString<256> Buffer;
16303 llvm::raw_svector_ostream Out(Buffer);
16304 unsigned Skipped = Exclude.size();
16305 for (unsigned I = First; I < Last; ++I) {
16306 if (llvm::is_contained(Range&: Exclude, Element: I)) {
16307 --Skipped;
16308 continue;
16309 }
16310 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
16311 if (I + Skipped + 2 == Last)
16312 Out << " or ";
16313 else if (I + Skipped + 1 != Last)
16314 Out << ", ";
16315 }
16316 return std::string(Out.str());
16317}
16318
16319OMPClause *SemaOpenMP::ActOnOpenMPDefaultClause(DefaultKind Kind,
16320 SourceLocation KindKwLoc,
16321 SourceLocation StartLoc,
16322 SourceLocation LParenLoc,
16323 SourceLocation EndLoc) {
16324 if (Kind == OMP_DEFAULT_unknown) {
16325 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16326 << getListOfPossibleValues(OMPC_default, /*First=*/0,
16327 /*Last=*/unsigned(OMP_DEFAULT_unknown))
16328 << getOpenMPClauseNameForDiag(OMPC_default);
16329 return nullptr;
16330 }
16331
16332 switch (Kind) {
16333 case OMP_DEFAULT_none:
16334 DSAStack->setDefaultDSANone(KindKwLoc);
16335 break;
16336 case OMP_DEFAULT_shared:
16337 DSAStack->setDefaultDSAShared(KindKwLoc);
16338 break;
16339 case OMP_DEFAULT_firstprivate:
16340 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
16341 break;
16342 case OMP_DEFAULT_private:
16343 DSAStack->setDefaultDSAPrivate(KindKwLoc);
16344 break;
16345 default:
16346 llvm_unreachable("DSA unexpected in OpenMP default clause");
16347 }
16348
16349 return new (getASTContext())
16350 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16351}
16352
16353OMPClause *SemaOpenMP::ActOnOpenMPProcBindClause(ProcBindKind Kind,
16354 SourceLocation KindKwLoc,
16355 SourceLocation StartLoc,
16356 SourceLocation LParenLoc,
16357 SourceLocation EndLoc) {
16358 if (Kind == OMP_PROC_BIND_unknown) {
16359 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16360 << getListOfPossibleValues(OMPC_proc_bind,
16361 /*First=*/unsigned(OMP_PROC_BIND_master),
16362 /*Last=*/
16363 unsigned(getLangOpts().OpenMP > 50
16364 ? OMP_PROC_BIND_primary
16365 : OMP_PROC_BIND_spread) +
16366 1)
16367 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
16368 return nullptr;
16369 }
16370 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
16371 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16372 << getListOfPossibleValues(OMPC_proc_bind,
16373 /*First=*/unsigned(OMP_PROC_BIND_master),
16374 /*Last=*/
16375 unsigned(OMP_PROC_BIND_spread) + 1)
16376 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
16377 return new (getASTContext())
16378 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16379}
16380
16381OMPClause *SemaOpenMP::ActOnOpenMPAtomicDefaultMemOrderClause(
16382 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
16383 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16384 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
16385 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16386 << getListOfPossibleValues(
16387 OMPC_atomic_default_mem_order, /*First=*/0,
16388 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
16389 << getOpenMPClauseNameForDiag(OMPC_atomic_default_mem_order);
16390 return nullptr;
16391 }
16392 return new (getASTContext()) OMPAtomicDefaultMemOrderClause(
16393 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16394}
16395
16396OMPClause *SemaOpenMP::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
16397 SourceLocation KindKwLoc,
16398 SourceLocation StartLoc,
16399 SourceLocation LParenLoc,
16400 SourceLocation EndLoc) {
16401 if (Kind == OMPC_AT_unknown) {
16402 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16403 << getListOfPossibleValues(OMPC_at, /*First=*/0,
16404 /*Last=*/OMPC_AT_unknown)
16405 << getOpenMPClauseNameForDiag(OMPC_at);
16406 return nullptr;
16407 }
16408 return new (getASTContext())
16409 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16410}
16411
16412OMPClause *SemaOpenMP::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
16413 SourceLocation KindKwLoc,
16414 SourceLocation StartLoc,
16415 SourceLocation LParenLoc,
16416 SourceLocation EndLoc) {
16417 if (Kind == OMPC_SEVERITY_unknown) {
16418 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16419 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
16420 /*Last=*/OMPC_SEVERITY_unknown)
16421 << getOpenMPClauseNameForDiag(OMPC_severity);
16422 return nullptr;
16423 }
16424 return new (getASTContext())
16425 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16426}
16427
16428OMPClause *SemaOpenMP::ActOnOpenMPMessageClause(Expr *ME,
16429 SourceLocation StartLoc,
16430 SourceLocation LParenLoc,
16431 SourceLocation EndLoc) {
16432 assert(ME && "NULL expr in Message clause");
16433 if (!isa<StringLiteral>(Val: ME)) {
16434 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
16435 << getOpenMPClauseNameForDiag(OMPC_message);
16436 return nullptr;
16437 }
16438 return new (getASTContext())
16439 OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
16440}
16441
16442OMPClause *SemaOpenMP::ActOnOpenMPOrderClause(
16443 OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind,
16444 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
16445 SourceLocation KindLoc, SourceLocation EndLoc) {
16446 if (Kind != OMPC_ORDER_concurrent ||
16447 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
16448 // Kind should be concurrent,
16449 // Modifiers introduced in OpenMP 5.1
16450 static_assert(OMPC_ORDER_unknown > 0,
16451 "OMPC_ORDER_unknown not greater than 0");
16452
16453 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16454 << getListOfPossibleValues(OMPC_order,
16455 /*First=*/0,
16456 /*Last=*/OMPC_ORDER_unknown)
16457 << getOpenMPClauseNameForDiag(OMPC_order);
16458 return nullptr;
16459 }
16460 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
16461 MLoc.isValid()) {
16462 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16463 << getListOfPossibleValues(OMPC_order,
16464 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
16465 /*Last=*/OMPC_ORDER_MODIFIER_last)
16466 << getOpenMPClauseNameForDiag(OMPC_order);
16467 } else if (getLangOpts().OpenMP >= 50) {
16468 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
16469 if (DSAStack->getCurScope()) {
16470 // mark the current scope with 'order' flag
16471 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
16472 DSAStack->getCurScope()->setFlags(existingFlags |
16473 Scope::OpenMPOrderClauseScope);
16474 }
16475 }
16476 return new (getASTContext()) OMPOrderClause(
16477 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
16478}
16479
16480OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,
16481 SourceLocation KindKwLoc,
16482 SourceLocation StartLoc,
16483 SourceLocation LParenLoc,
16484 SourceLocation EndLoc) {
16485 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
16486 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16487 SmallVector<unsigned> Except = {
16488 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16489 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16490 if (getLangOpts().OpenMP < 51)
16491 Except.push_back(Elt: OMPC_DEPEND_inoutset);
16492 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16493 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
16494 /*Last=*/OMPC_DEPEND_unknown, Except)
16495 << getOpenMPClauseNameForDiag(OMPC_update);
16496 return nullptr;
16497 }
16498 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
16499 KindKwLoc, Kind, EndLoc);
16500}
16501
16502OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
16503 SourceLocation StartLoc,
16504 SourceLocation LParenLoc,
16505 SourceLocation EndLoc) {
16506 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
16507
16508 for (Expr *&SizeExpr : SanitizedSizeExprs) {
16509 // Skip if already sanitized, e.g. during a partial template instantiation.
16510 if (!SizeExpr)
16511 continue;
16512
16513 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
16514 /*StrictlyPositive=*/true);
16515
16516 // isNonNegativeIntegerValue returns true for non-integral types (but still
16517 // emits error diagnostic), so check for the expected type explicitly.
16518 QualType SizeTy = SizeExpr->getType();
16519 if (!SizeTy->isIntegerType())
16520 IsValid = false;
16521
16522 // Handling in templates is tricky. There are four possibilities to
16523 // consider:
16524 //
16525 // 1a. The expression is valid and we are in a instantiated template or not
16526 // in a template:
16527 // Pass valid expression to be further analysed later in Sema.
16528 // 1b. The expression is valid and we are in a template (including partial
16529 // instantiation):
16530 // isNonNegativeIntegerValue skipped any checks so there is no
16531 // guarantee it will be correct after instantiation.
16532 // ActOnOpenMPSizesClause will be called again at instantiation when
16533 // it is not in a dependent context anymore. This may cause warnings
16534 // to be emitted multiple times.
16535 // 2a. The expression is invalid and we are in an instantiated template or
16536 // not in a template:
16537 // Invalidate the expression with a clearly wrong value (nullptr) so
16538 // later in Sema we do not have to do the same validity analysis again
16539 // or crash from unexpected data. Error diagnostics have already been
16540 // emitted.
16541 // 2b. The expression is invalid and we are in a template (including partial
16542 // instantiation):
16543 // Pass the invalid expression as-is, template instantiation may
16544 // replace unexpected types/values with valid ones. The directives
16545 // with this clause must not try to use these expressions in dependent
16546 // contexts, but delay analysis until full instantiation.
16547 if (!SizeExpr->isInstantiationDependent() && !IsValid)
16548 SizeExpr = nullptr;
16549 }
16550
16551 return OMPSizesClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
16552 Sizes: SanitizedSizeExprs);
16553}
16554
16555OMPClause *SemaOpenMP::ActOnOpenMPPermutationClause(ArrayRef<Expr *> PermExprs,
16556 SourceLocation StartLoc,
16557 SourceLocation LParenLoc,
16558 SourceLocation EndLoc) {
16559 size_t NumLoops = PermExprs.size();
16560 SmallVector<Expr *> SanitizedPermExprs;
16561 llvm::append_range(C&: SanitizedPermExprs, R&: PermExprs);
16562
16563 for (Expr *&PermExpr : SanitizedPermExprs) {
16564 // Skip if template-dependent or already sanitized, e.g. during a partial
16565 // template instantiation.
16566 if (!PermExpr || PermExpr->isInstantiationDependent())
16567 continue;
16568
16569 llvm::APSInt PermVal;
16570 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
16571 E: PermExpr, Result: &PermVal, CanFold: AllowFoldKind::Allow);
16572 bool IsValid = PermEvalExpr.isUsable();
16573 if (IsValid)
16574 PermExpr = PermEvalExpr.get();
16575
16576 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
16577 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
16578 PermEvalExpr.get()->getEndLoc());
16579 Diag(PermEvalExpr.get()->getExprLoc(),
16580 diag::err_omp_interchange_permutation_value_range)
16581 << NumLoops << ExprRange;
16582 IsValid = false;
16583 }
16584
16585 if (!PermExpr->isInstantiationDependent() && !IsValid)
16586 PermExpr = nullptr;
16587 }
16588
16589 return OMPPermutationClause::Create(C: getASTContext(), StartLoc, LParenLoc,
16590 EndLoc, Args: SanitizedPermExprs);
16591}
16592
16593OMPClause *SemaOpenMP::ActOnOpenMPFullClause(SourceLocation StartLoc,
16594 SourceLocation EndLoc) {
16595 return OMPFullClause::Create(C: getASTContext(), StartLoc, EndLoc);
16596}
16597
16598OMPClause *SemaOpenMP::ActOnOpenMPPartialClause(Expr *FactorExpr,
16599 SourceLocation StartLoc,
16600 SourceLocation LParenLoc,
16601 SourceLocation EndLoc) {
16602 if (FactorExpr) {
16603 // If an argument is specified, it must be a constant (or an unevaluated
16604 // template expression).
16605 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
16606 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
16607 if (FactorResult.isInvalid())
16608 return nullptr;
16609 FactorExpr = FactorResult.get();
16610 }
16611
16612 return OMPPartialClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
16613 Factor: FactorExpr);
16614}
16615
16616OMPClause *SemaOpenMP::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
16617 SourceLocation LParenLoc,
16618 SourceLocation EndLoc) {
16619 ExprResult AlignVal;
16620 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
16621 if (AlignVal.isInvalid())
16622 return nullptr;
16623 return OMPAlignClause::Create(C: getASTContext(), A: AlignVal.get(), StartLoc,
16624 LParenLoc, EndLoc);
16625}
16626
16627OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause(
16628 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
16629 SourceLocation StartLoc, SourceLocation LParenLoc,
16630 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
16631 SourceLocation EndLoc) {
16632 OMPClause *Res = nullptr;
16633 switch (Kind) {
16634 case OMPC_schedule:
16635 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16636 assert(Argument.size() == NumberOfElements &&
16637 ArgumentLoc.size() == NumberOfElements);
16638 Res = ActOnOpenMPScheduleClause(
16639 M1: static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
16640 M2: static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
16641 Kind: static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), ChunkSize: Expr,
16642 StartLoc, LParenLoc, M1Loc: ArgumentLoc[Modifier1], M2Loc: ArgumentLoc[Modifier2],
16643 KindLoc: ArgumentLoc[ScheduleKind], CommaLoc: DelimLoc, EndLoc);
16644 break;
16645 case OMPC_if:
16646 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16647 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
16648 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16649 DelimLoc, EndLoc);
16650 break;
16651 case OMPC_dist_schedule:
16652 Res = ActOnOpenMPDistScheduleClause(
16653 Kind: static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), ChunkSize: Expr,
16654 StartLoc, LParenLoc, KindLoc: ArgumentLoc.back(), CommaLoc: DelimLoc, EndLoc);
16655 break;
16656 case OMPC_defaultmap:
16657 enum { Modifier, DefaultmapKind };
16658 Res = ActOnOpenMPDefaultmapClause(
16659 M: static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
16660 Kind: static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
16661 StartLoc, LParenLoc, MLoc: ArgumentLoc[Modifier], KindLoc: ArgumentLoc[DefaultmapKind],
16662 EndLoc);
16663 break;
16664 case OMPC_order:
16665 enum { OrderModifier, OrderKind };
16666 Res = ActOnOpenMPOrderClause(
16667 Modifier: static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
16668 Kind: static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
16669 LParenLoc, MLoc: ArgumentLoc[OrderModifier], KindLoc: ArgumentLoc[OrderKind], EndLoc);
16670 break;
16671 case OMPC_device:
16672 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16673 Res = ActOnOpenMPDeviceClause(
16674 Modifier: static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Device: Expr,
16675 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
16676 break;
16677 case OMPC_grainsize:
16678 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16679 "Modifier for grainsize clause and its location are expected.");
16680 Res = ActOnOpenMPGrainsizeClause(
16681 Modifier: static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Size: Expr,
16682 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
16683 break;
16684 case OMPC_num_tasks:
16685 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16686 "Modifier for num_tasks clause and its location are expected.");
16687 Res = ActOnOpenMPNumTasksClause(
16688 Modifier: static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), NumTasks: Expr,
16689 StartLoc, LParenLoc, ModifierLoc: ArgumentLoc.back(), EndLoc);
16690 break;
16691 case OMPC_final:
16692 case OMPC_num_threads:
16693 case OMPC_safelen:
16694 case OMPC_simdlen:
16695 case OMPC_sizes:
16696 case OMPC_allocator:
16697 case OMPC_collapse:
16698 case OMPC_default:
16699 case OMPC_proc_bind:
16700 case OMPC_private:
16701 case OMPC_firstprivate:
16702 case OMPC_lastprivate:
16703 case OMPC_shared:
16704 case OMPC_reduction:
16705 case OMPC_task_reduction:
16706 case OMPC_in_reduction:
16707 case OMPC_linear:
16708 case OMPC_aligned:
16709 case OMPC_copyin:
16710 case OMPC_copyprivate:
16711 case OMPC_ordered:
16712 case OMPC_nowait:
16713 case OMPC_untied:
16714 case OMPC_mergeable:
16715 case OMPC_threadprivate:
16716 case OMPC_allocate:
16717 case OMPC_flush:
16718 case OMPC_depobj:
16719 case OMPC_read:
16720 case OMPC_write:
16721 case OMPC_update:
16722 case OMPC_capture:
16723 case OMPC_compare:
16724 case OMPC_seq_cst:
16725 case OMPC_acq_rel:
16726 case OMPC_acquire:
16727 case OMPC_release:
16728 case OMPC_relaxed:
16729 case OMPC_depend:
16730 case OMPC_threads:
16731 case OMPC_simd:
16732 case OMPC_map:
16733 case OMPC_num_teams:
16734 case OMPC_thread_limit:
16735 case OMPC_priority:
16736 case OMPC_nogroup:
16737 case OMPC_hint:
16738 case OMPC_unknown:
16739 case OMPC_uniform:
16740 case OMPC_to:
16741 case OMPC_from:
16742 case OMPC_use_device_ptr:
16743 case OMPC_use_device_addr:
16744 case OMPC_is_device_ptr:
16745 case OMPC_has_device_addr:
16746 case OMPC_unified_address:
16747 case OMPC_unified_shared_memory:
16748 case OMPC_reverse_offload:
16749 case OMPC_dynamic_allocators:
16750 case OMPC_atomic_default_mem_order:
16751 case OMPC_self_maps:
16752 case OMPC_device_type:
16753 case OMPC_match:
16754 case OMPC_nontemporal:
16755 case OMPC_at:
16756 case OMPC_severity:
16757 case OMPC_message:
16758 case OMPC_destroy:
16759 case OMPC_novariants:
16760 case OMPC_nocontext:
16761 case OMPC_detach:
16762 case OMPC_inclusive:
16763 case OMPC_exclusive:
16764 case OMPC_uses_allocators:
16765 case OMPC_affinity:
16766 case OMPC_when:
16767 case OMPC_bind:
16768 default:
16769 llvm_unreachable("Clause is not allowed.");
16770 }
16771 return Res;
16772}
16773
16774static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
16775 OpenMPScheduleClauseModifier M2,
16776 SourceLocation M1Loc, SourceLocation M2Loc) {
16777 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
16778 SmallVector<unsigned, 2> Excluded;
16779 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
16780 Excluded.push_back(Elt: M2);
16781 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16782 Excluded.push_back(Elt: OMPC_SCHEDULE_MODIFIER_monotonic);
16783 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16784 Excluded.push_back(Elt: OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16785 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16786 << getListOfPossibleValues(OMPC_schedule,
16787 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
16788 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
16789 Excluded)
16790 << getOpenMPClauseNameForDiag(OMPC_schedule);
16791 return true;
16792 }
16793 return false;
16794}
16795
16796OMPClause *SemaOpenMP::ActOnOpenMPScheduleClause(
16797 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
16798 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
16799 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
16800 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
16801 if (checkScheduleModifiers(S&: SemaRef, M1, M2, M1Loc, M2Loc) ||
16802 checkScheduleModifiers(S&: SemaRef, M1: M2, M2: M1, M1Loc: M2Loc, M2Loc: M1Loc))
16803 return nullptr;
16804 // OpenMP, 2.7.1, Loop Construct, Restrictions
16805 // Either the monotonic modifier or the nonmonotonic modifier can be specified
16806 // but not both.
16807 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
16808 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16809 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16810 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16811 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16812 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16813 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
16814 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
16815 return nullptr;
16816 }
16817 if (Kind == OMPC_SCHEDULE_unknown) {
16818 std::string Values;
16819 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
16820 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
16821 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16822 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
16823 Exclude);
16824 } else {
16825 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16826 /*Last=*/OMPC_SCHEDULE_unknown);
16827 }
16828 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16829 << Values << getOpenMPClauseNameForDiag(OMPC_schedule);
16830 return nullptr;
16831 }
16832 // OpenMP, 2.7.1, Loop Construct, Restrictions
16833 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
16834 // schedule(guided).
16835 // OpenMP 5.0 does not have this restriction.
16836 if (getLangOpts().OpenMP < 50 &&
16837 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16838 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16839 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16840 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16841 diag::err_omp_schedule_nonmonotonic_static);
16842 return nullptr;
16843 }
16844 Expr *ValExpr = ChunkSize;
16845 Stmt *HelperValStmt = nullptr;
16846 if (ChunkSize) {
16847 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
16848 !ChunkSize->isInstantiationDependent() &&
16849 !ChunkSize->containsUnexpandedParameterPack()) {
16850 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
16851 ExprResult Val =
16852 PerformOpenMPImplicitIntegerConversion(Loc: ChunkSizeLoc, Op: ChunkSize);
16853 if (Val.isInvalid())
16854 return nullptr;
16855
16856 ValExpr = Val.get();
16857
16858 // OpenMP [2.7.1, Restrictions]
16859 // chunk_size must be a loop invariant integer expression with a positive
16860 // value.
16861 if (std::optional<llvm::APSInt> Result =
16862 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
16863 if (Result->isSigned() && !Result->isStrictlyPositive()) {
16864 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16865 << "schedule" << 1 << ChunkSize->getSourceRange();
16866 return nullptr;
16867 }
16868 } else if (getOpenMPCaptureRegionForClause(
16869 DSAStack->getCurrentDirective(), OMPC_schedule,
16870 getLangOpts().OpenMP) != OMPD_unknown &&
16871 !SemaRef.CurContext->isDependentContext()) {
16872 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
16873 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16874 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
16875 HelperValStmt = buildPreInits(getASTContext(), Captures);
16876 }
16877 }
16878 }
16879
16880 return new (getASTContext())
16881 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
16882 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16883}
16884
16885OMPClause *SemaOpenMP::ActOnOpenMPClause(OpenMPClauseKind Kind,
16886 SourceLocation StartLoc,
16887 SourceLocation EndLoc) {
16888 OMPClause *Res = nullptr;
16889 switch (Kind) {
16890 case OMPC_ordered:
16891 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
16892 break;
16893 case OMPC_nowait:
16894 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
16895 break;
16896 case OMPC_untied:
16897 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
16898 break;
16899 case OMPC_mergeable:
16900 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
16901 break;
16902 case OMPC_read:
16903 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
16904 break;
16905 case OMPC_write:
16906 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
16907 break;
16908 case OMPC_update:
16909 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
16910 break;
16911 case OMPC_capture:
16912 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
16913 break;
16914 case OMPC_compare:
16915 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
16916 break;
16917 case OMPC_fail:
16918 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
16919 break;
16920 case OMPC_seq_cst:
16921 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
16922 break;
16923 case OMPC_acq_rel:
16924 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
16925 break;
16926 case OMPC_acquire:
16927 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
16928 break;
16929 case OMPC_release:
16930 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
16931 break;
16932 case OMPC_relaxed:
16933 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
16934 break;
16935 case OMPC_weak:
16936 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
16937 break;
16938 case OMPC_threads:
16939 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
16940 break;
16941 case OMPC_simd:
16942 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
16943 break;
16944 case OMPC_nogroup:
16945 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
16946 break;
16947 case OMPC_unified_address:
16948 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
16949 break;
16950 case OMPC_unified_shared_memory:
16951 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16952 break;
16953 case OMPC_reverse_offload:
16954 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
16955 break;
16956 case OMPC_dynamic_allocators:
16957 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
16958 break;
16959 case OMPC_self_maps:
16960 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
16961 break;
16962 case OMPC_destroy:
16963 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
16964 /*LParenLoc=*/SourceLocation(),
16965 /*VarLoc=*/SourceLocation(), EndLoc);
16966 break;
16967 case OMPC_full:
16968 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
16969 break;
16970 case OMPC_partial:
16971 Res = ActOnOpenMPPartialClause(FactorExpr: nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
16972 break;
16973 case OMPC_ompx_bare:
16974 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
16975 break;
16976 case OMPC_if:
16977 case OMPC_final:
16978 case OMPC_num_threads:
16979 case OMPC_safelen:
16980 case OMPC_simdlen:
16981 case OMPC_sizes:
16982 case OMPC_allocator:
16983 case OMPC_collapse:
16984 case OMPC_schedule:
16985 case OMPC_private:
16986 case OMPC_firstprivate:
16987 case OMPC_lastprivate:
16988 case OMPC_shared:
16989 case OMPC_reduction:
16990 case OMPC_task_reduction:
16991 case OMPC_in_reduction:
16992 case OMPC_linear:
16993 case OMPC_aligned:
16994 case OMPC_copyin:
16995 case OMPC_copyprivate:
16996 case OMPC_default:
16997 case OMPC_proc_bind:
16998 case OMPC_threadprivate:
16999 case OMPC_allocate:
17000 case OMPC_flush:
17001 case OMPC_depobj:
17002 case OMPC_depend:
17003 case OMPC_device:
17004 case OMPC_map:
17005 case OMPC_num_teams:
17006 case OMPC_thread_limit:
17007 case OMPC_priority:
17008 case OMPC_grainsize:
17009 case OMPC_num_tasks:
17010 case OMPC_hint:
17011 case OMPC_dist_schedule:
17012 case OMPC_defaultmap:
17013 case OMPC_unknown:
17014 case OMPC_uniform:
17015 case OMPC_to:
17016 case OMPC_from:
17017 case OMPC_use_device_ptr:
17018 case OMPC_use_device_addr:
17019 case OMPC_is_device_ptr:
17020 case OMPC_has_device_addr:
17021 case OMPC_atomic_default_mem_order:
17022 case OMPC_device_type:
17023 case OMPC_match:
17024 case OMPC_nontemporal:
17025 case OMPC_order:
17026 case OMPC_at:
17027 case OMPC_severity:
17028 case OMPC_message:
17029 case OMPC_novariants:
17030 case OMPC_nocontext:
17031 case OMPC_detach:
17032 case OMPC_inclusive:
17033 case OMPC_exclusive:
17034 case OMPC_uses_allocators:
17035 case OMPC_affinity:
17036 case OMPC_when:
17037 case OMPC_ompx_dyn_cgroup_mem:
17038 default:
17039 llvm_unreachable("Clause is not allowed.");
17040 }
17041 return Res;
17042}
17043
17044OMPClause *SemaOpenMP::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
17045 SourceLocation EndLoc) {
17046 DSAStack->setNowaitRegion();
17047 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
17048}
17049
17050OMPClause *SemaOpenMP::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
17051 SourceLocation EndLoc) {
17052 DSAStack->setUntiedRegion();
17053 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
17054}
17055
17056OMPClause *SemaOpenMP::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
17057 SourceLocation EndLoc) {
17058 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
17059}
17060
17061OMPClause *SemaOpenMP::ActOnOpenMPReadClause(SourceLocation StartLoc,
17062 SourceLocation EndLoc) {
17063 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
17064}
17065
17066OMPClause *SemaOpenMP::ActOnOpenMPWriteClause(SourceLocation StartLoc,
17067 SourceLocation EndLoc) {
17068 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
17069}
17070
17071OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
17072 SourceLocation EndLoc) {
17073 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
17074}
17075
17076OMPClause *SemaOpenMP::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
17077 SourceLocation EndLoc) {
17078 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
17079}
17080
17081OMPClause *SemaOpenMP::ActOnOpenMPCompareClause(SourceLocation StartLoc,
17082 SourceLocation EndLoc) {
17083 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
17084}
17085
17086OMPClause *SemaOpenMP::ActOnOpenMPFailClause(SourceLocation StartLoc,
17087 SourceLocation EndLoc) {
17088 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
17089}
17090
17091OMPClause *SemaOpenMP::ActOnOpenMPFailClause(OpenMPClauseKind Parameter,
17092 SourceLocation KindLoc,
17093 SourceLocation StartLoc,
17094 SourceLocation LParenLoc,
17095 SourceLocation EndLoc) {
17096
17097 if (!checkFailClauseParameter(Parameter)) {
17098 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
17099 return nullptr;
17100 }
17101 return new (getASTContext())
17102 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
17103}
17104
17105OMPClause *SemaOpenMP::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
17106 SourceLocation EndLoc) {
17107 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
17108}
17109
17110OMPClause *SemaOpenMP::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
17111 SourceLocation EndLoc) {
17112 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
17113}
17114
17115OMPClause *SemaOpenMP::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
17116 SourceLocation EndLoc) {
17117 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
17118}
17119
17120OMPClause *SemaOpenMP::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
17121 SourceLocation EndLoc) {
17122 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
17123}
17124
17125OMPClause *SemaOpenMP::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
17126 SourceLocation EndLoc) {
17127 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
17128}
17129
17130OMPClause *SemaOpenMP::ActOnOpenMPWeakClause(SourceLocation StartLoc,
17131 SourceLocation EndLoc) {
17132 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
17133}
17134
17135OMPClause *SemaOpenMP::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
17136 SourceLocation EndLoc) {
17137 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
17138}
17139
17140OMPClause *SemaOpenMP::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
17141 SourceLocation EndLoc) {
17142 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
17143}
17144
17145OMPClause *SemaOpenMP::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
17146 SourceLocation EndLoc) {
17147 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
17148}
17149
17150OMPClause *SemaOpenMP::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
17151 SourceLocation EndLoc) {
17152 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
17153}
17154
17155OMPClause *
17156SemaOpenMP::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
17157 SourceLocation EndLoc) {
17158 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17159}
17160
17161OMPClause *SemaOpenMP::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
17162 SourceLocation EndLoc) {
17163 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
17164}
17165
17166OMPClause *
17167SemaOpenMP::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
17168 SourceLocation EndLoc) {
17169 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17170}
17171
17172OMPClause *SemaOpenMP::ActOnOpenMPSelfMapsClause(SourceLocation StartLoc,
17173 SourceLocation EndLoc) {
17174 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
17175}
17176
17177StmtResult
17178SemaOpenMP::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
17179 SourceLocation StartLoc,
17180 SourceLocation EndLoc) {
17181
17182 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17183 // At least one action-clause must appear on a directive.
17184 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17185 unsigned OMPVersion = getLangOpts().OpenMP;
17186 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
17187 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17188 << Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
17189 return StmtError();
17190 }
17191
17192 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17193 // A depend clause can only appear on the directive if a targetsync
17194 // interop-type is present or the interop-var was initialized with
17195 // the targetsync interop-type.
17196
17197 // If there is any 'init' clause diagnose if there is no 'init' clause with
17198 // interop-type of 'targetsync'. Cases involving other directives cannot be
17199 // diagnosed.
17200 const OMPDependClause *DependClause = nullptr;
17201 bool HasInitClause = false;
17202 bool IsTargetSync = false;
17203 for (const OMPClause *C : Clauses) {
17204 if (IsTargetSync)
17205 break;
17206 if (const auto *InitClause = dyn_cast<OMPInitClause>(Val: C)) {
17207 HasInitClause = true;
17208 if (InitClause->getIsTargetSync())
17209 IsTargetSync = true;
17210 } else if (const auto *DC = dyn_cast<OMPDependClause>(Val: C)) {
17211 DependClause = DC;
17212 }
17213 }
17214 if (DependClause && HasInitClause && !IsTargetSync) {
17215 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17216 return StmtError();
17217 }
17218
17219 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17220 // Each interop-var may be specified for at most one action-clause of each
17221 // interop construct.
17222 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
17223 for (OMPClause *C : Clauses) {
17224 OpenMPClauseKind ClauseKind = C->getClauseKind();
17225 std::pair<ValueDecl *, bool> DeclResult;
17226 SourceLocation ELoc;
17227 SourceRange ERange;
17228
17229 if (ClauseKind == OMPC_init) {
17230 auto *E = cast<OMPInitClause>(Val: C)->getInteropVar();
17231 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
17232 } else if (ClauseKind == OMPC_use) {
17233 auto *E = cast<OMPUseClause>(Val: C)->getInteropVar();
17234 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
17235 } else if (ClauseKind == OMPC_destroy) {
17236 auto *E = cast<OMPDestroyClause>(Val: C)->getInteropVar();
17237 DeclResult = getPrivateItem(S&: SemaRef, RefExpr&: E, ELoc, ERange);
17238 }
17239
17240 if (DeclResult.first) {
17241 if (!InteropVars.insert(Ptr: DeclResult.first).second) {
17242 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
17243 << DeclResult.first;
17244 return StmtError();
17245 }
17246 }
17247 }
17248
17249 return OMPInteropDirective::Create(C: getASTContext(), StartLoc, EndLoc,
17250 Clauses);
17251}
17252
17253static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
17254 SourceLocation VarLoc,
17255 OpenMPClauseKind Kind) {
17256 SourceLocation ELoc;
17257 SourceRange ERange;
17258 Expr *RefExpr = InteropVarExpr;
17259 auto Res =
17260 getPrivateItem(S&: SemaRef, RefExpr, ELoc, ERange,
17261 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17262
17263 if (Res.second) {
17264 // It will be analyzed later.
17265 return true;
17266 }
17267
17268 if (!Res.first)
17269 return false;
17270
17271 // Interop variable should be of type omp_interop_t.
17272 bool HasError = false;
17273 QualType InteropType;
17274 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get(Name: "omp_interop_t"),
17275 VarLoc, Sema::LookupOrdinaryName);
17276 if (SemaRef.LookupName(R&: Result, S: SemaRef.getCurScope())) {
17277 NamedDecl *ND = Result.getFoundDecl();
17278 if (const auto *TD = dyn_cast<TypeDecl>(Val: ND)) {
17279 InteropType = QualType(TD->getTypeForDecl(), 0);
17280 } else {
17281 HasError = true;
17282 }
17283 } else {
17284 HasError = true;
17285 }
17286
17287 if (HasError) {
17288 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
17289 << "omp_interop_t";
17290 return false;
17291 }
17292
17293 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
17294 if (!SemaRef.Context.hasSameType(T1: InteropType, T2: VarType)) {
17295 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17296 return false;
17297 }
17298
17299 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17300 // The interop-var passed to init or destroy must be non-const.
17301 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17302 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
17303 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
17304 << /*non-const*/ 1;
17305 return false;
17306 }
17307 return true;
17308}
17309
17310OMPClause *SemaOpenMP::ActOnOpenMPInitClause(
17311 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
17312 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
17313
17314 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
17315 return nullptr;
17316
17317 // Check prefer_type values. These foreign-runtime-id values are either
17318 // string literals or constant integral expressions.
17319 for (const Expr *E : InteropInfo.PreferTypes) {
17320 if (E->isValueDependent() || E->isTypeDependent() ||
17321 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
17322 continue;
17323 if (E->isIntegerConstantExpr(Ctx: getASTContext()))
17324 continue;
17325 if (isa<StringLiteral>(Val: E))
17326 continue;
17327 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
17328 return nullptr;
17329 }
17330
17331 return OMPInitClause::Create(C: getASTContext(), InteropVar, InteropInfo,
17332 StartLoc, LParenLoc, VarLoc, EndLoc);
17333}
17334
17335OMPClause *SemaOpenMP::ActOnOpenMPUseClause(Expr *InteropVar,
17336 SourceLocation StartLoc,
17337 SourceLocation LParenLoc,
17338 SourceLocation VarLoc,
17339 SourceLocation EndLoc) {
17340
17341 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
17342 return nullptr;
17343
17344 return new (getASTContext())
17345 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17346}
17347
17348OMPClause *SemaOpenMP::ActOnOpenMPDestroyClause(Expr *InteropVar,
17349 SourceLocation StartLoc,
17350 SourceLocation LParenLoc,
17351 SourceLocation VarLoc,
17352 SourceLocation EndLoc) {
17353 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
17354 DSAStack->getCurrentDirective() == OMPD_depobj) {
17355 unsigned OMPVersion = getLangOpts().OpenMP;
17356 Diag(StartLoc, diag::err_omp_expected_clause_argument)
17357 << getOpenMPClauseNameForDiag(OMPC_destroy)
17358 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
17359 return nullptr;
17360 }
17361 if (InteropVar &&
17362 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
17363 return nullptr;
17364
17365 return new (getASTContext())
17366 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17367}
17368
17369OMPClause *SemaOpenMP::ActOnOpenMPNovariantsClause(Expr *Condition,
17370 SourceLocation StartLoc,
17371 SourceLocation LParenLoc,
17372 SourceLocation EndLoc) {
17373 Expr *ValExpr = Condition;
17374 Stmt *HelperValStmt = nullptr;
17375 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17376 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17377 !Condition->isInstantiationDependent() &&
17378 !Condition->containsUnexpandedParameterPack()) {
17379 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
17380 if (Val.isInvalid())
17381 return nullptr;
17382
17383 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
17384
17385 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17386 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
17387 getLangOpts().OpenMP);
17388 if (CaptureRegion != OMPD_unknown &&
17389 !SemaRef.CurContext->isDependentContext()) {
17390 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17391 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17392 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17393 HelperValStmt = buildPreInits(getASTContext(), Captures);
17394 }
17395 }
17396
17397 return new (getASTContext()) OMPNovariantsClause(
17398 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17399}
17400
17401OMPClause *SemaOpenMP::ActOnOpenMPNocontextClause(Expr *Condition,
17402 SourceLocation StartLoc,
17403 SourceLocation LParenLoc,
17404 SourceLocation EndLoc) {
17405 Expr *ValExpr = Condition;
17406 Stmt *HelperValStmt = nullptr;
17407 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17408 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17409 !Condition->isInstantiationDependent() &&
17410 !Condition->containsUnexpandedParameterPack()) {
17411 ExprResult Val = SemaRef.CheckBooleanCondition(Loc: StartLoc, E: Condition);
17412 if (Val.isInvalid())
17413 return nullptr;
17414
17415 ValExpr = SemaRef.MakeFullExpr(Arg: Val.get()).get();
17416
17417 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17418 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
17419 getLangOpts().OpenMP);
17420 if (CaptureRegion != OMPD_unknown &&
17421 !SemaRef.CurContext->isDependentContext()) {
17422 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17423 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17424 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17425 HelperValStmt = buildPreInits(getASTContext(), Captures);
17426 }
17427 }
17428
17429 return new (getASTContext()) OMPNocontextClause(
17430 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17431}
17432
17433OMPClause *SemaOpenMP::ActOnOpenMPFilterClause(Expr *ThreadID,
17434 SourceLocation StartLoc,
17435 SourceLocation LParenLoc,
17436 SourceLocation EndLoc) {
17437 Expr *ValExpr = ThreadID;
17438 Stmt *HelperValStmt = nullptr;
17439
17440 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17441 OpenMPDirectiveKind CaptureRegion =
17442 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
17443 if (CaptureRegion != OMPD_unknown &&
17444 !SemaRef.CurContext->isDependentContext()) {
17445 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
17446 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17447 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
17448 HelperValStmt = buildPreInits(getASTContext(), Captures);
17449 }
17450
17451 return new (getASTContext()) OMPFilterClause(
17452 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17453}
17454
17455OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
17456 ArrayRef<Expr *> VarList,
17457 const OMPVarListLocTy &Locs,
17458 OpenMPVarListDataTy &Data) {
17459 SourceLocation StartLoc = Locs.StartLoc;
17460 SourceLocation LParenLoc = Locs.LParenLoc;
17461 SourceLocation EndLoc = Locs.EndLoc;
17462 OMPClause *Res = nullptr;
17463 int ExtraModifier = Data.ExtraModifier;
17464 int OriginalSharingModifier = Data.OriginalSharingModifier;
17465 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
17466 SourceLocation ColonLoc = Data.ColonLoc;
17467 switch (Kind) {
17468 case OMPC_private:
17469 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17470 break;
17471 case OMPC_firstprivate:
17472 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17473 break;
17474 case OMPC_lastprivate:
17475 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
17476 "Unexpected lastprivate modifier.");
17477 Res = ActOnOpenMPLastprivateClause(
17478 VarList, LPKind: static_cast<OpenMPLastprivateModifier>(ExtraModifier),
17479 LPKindLoc: ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17480 break;
17481 case OMPC_shared:
17482 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
17483 break;
17484 case OMPC_reduction:
17485 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
17486 "Unexpected lastprivate modifier.");
17487 Res = ActOnOpenMPReductionClause(
17488 VarList,
17489 Modifiers: OpenMPVarListDataTy::OpenMPReductionClauseModifiers(
17490 ExtraModifier, OriginalSharingModifier),
17491 StartLoc, LParenLoc, ModifierLoc: ExtraModifierLoc, ColonLoc, EndLoc,
17492 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
17493 break;
17494 case OMPC_task_reduction:
17495 Res = ActOnOpenMPTaskReductionClause(
17496 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17497 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
17498 break;
17499 case OMPC_in_reduction:
17500 Res = ActOnOpenMPInReductionClause(
17501 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17502 ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId: Data.ReductionOrMapperId);
17503 break;
17504 case OMPC_linear:
17505 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
17506 "Unexpected linear modifier.");
17507 Res = ActOnOpenMPLinearClause(
17508 VarList, Step: Data.DepModOrTailExpr, StartLoc, LParenLoc,
17509 LinKind: static_cast<OpenMPLinearClauseKind>(ExtraModifier), LinLoc: ExtraModifierLoc,
17510 ColonLoc, StepModifierLoc: Data.StepModifierLoc, EndLoc);
17511 break;
17512 case OMPC_aligned:
17513 Res = ActOnOpenMPAlignedClause(VarList, Alignment: Data.DepModOrTailExpr, StartLoc,
17514 LParenLoc, ColonLoc, EndLoc);
17515 break;
17516 case OMPC_copyin:
17517 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
17518 break;
17519 case OMPC_copyprivate:
17520 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17521 break;
17522 case OMPC_flush:
17523 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
17524 break;
17525 case OMPC_depend:
17526 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
17527 "Unexpected depend modifier.");
17528 Res = ActOnOpenMPDependClause(
17529 Data: {.DepKind: static_cast<OpenMPDependClauseKind>(ExtraModifier), .DepLoc: ExtraModifierLoc,
17530 .ColonLoc: ColonLoc, .OmpAllMemoryLoc: Data.OmpAllMemoryLoc},
17531 DepModifier: Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17532 break;
17533 case OMPC_map:
17534 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
17535 "Unexpected map modifier.");
17536 Res = ActOnOpenMPMapClause(
17537 IteratorModifier: Data.IteratorExpr, MapTypeModifiers: Data.MapTypeModifiers, MapTypeModifiersLoc: Data.MapTypeModifiersLoc,
17538 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, MapperId&: Data.ReductionOrMapperId,
17539 MapType: static_cast<OpenMPMapClauseKind>(ExtraModifier), IsMapTypeImplicit: Data.IsMapTypeImplicit,
17540 MapLoc: ExtraModifierLoc, ColonLoc, VarList, Locs);
17541 break;
17542 case OMPC_to:
17543 Res =
17544 ActOnOpenMPToClause(MotionModifiers: Data.MotionModifiers, MotionModifiersLoc: Data.MotionModifiersLoc,
17545 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec,
17546 MapperId&: Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17547 break;
17548 case OMPC_from:
17549 Res = ActOnOpenMPFromClause(MotionModifiers: Data.MotionModifiers, MotionModifiersLoc: Data.MotionModifiersLoc,
17550 MapperIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec,
17551 MapperId&: Data.ReductionOrMapperId, ColonLoc, VarList,
17552 Locs);
17553 break;
17554 case OMPC_use_device_ptr:
17555 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
17556 break;
17557 case OMPC_use_device_addr:
17558 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
17559 break;
17560 case OMPC_is_device_ptr:
17561 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
17562 break;
17563 case OMPC_has_device_addr:
17564 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
17565 break;
17566 case OMPC_allocate: {
17567 OpenMPAllocateClauseModifier Modifier1 = OMPC_ALLOCATE_unknown;
17568 OpenMPAllocateClauseModifier Modifier2 = OMPC_ALLOCATE_unknown;
17569 SourceLocation Modifier1Loc, Modifier2Loc;
17570 if (!Data.AllocClauseModifiers.empty()) {
17571 assert(Data.AllocClauseModifiers.size() <= 2 &&
17572 "More allocate modifiers than expected");
17573 Modifier1 = Data.AllocClauseModifiers[0];
17574 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
17575 if (Data.AllocClauseModifiers.size() == 2) {
17576 Modifier2 = Data.AllocClauseModifiers[1];
17577 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
17578 }
17579 }
17580 Res = ActOnOpenMPAllocateClause(
17581 Allocator: Data.DepModOrTailExpr, Alignment: Data.AllocateAlignment, FirstModifier: Modifier1, FirstModifierLoc: Modifier1Loc,
17582 SecondModifier: Modifier2, SecondModifierLoc: Modifier2Loc, VarList, StartLoc, ColonLoc: LParenLoc, LParenLoc: ColonLoc,
17583 EndLoc);
17584 break;
17585 }
17586 case OMPC_nontemporal:
17587 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
17588 break;
17589 case OMPC_inclusive:
17590 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17591 break;
17592 case OMPC_exclusive:
17593 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17594 break;
17595 case OMPC_affinity:
17596 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
17597 Modifier: Data.DepModOrTailExpr, Locators: VarList);
17598 break;
17599 case OMPC_doacross:
17600 Res = ActOnOpenMPDoacrossClause(
17601 DepType: static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
17602 DepLoc: ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17603 break;
17604 case OMPC_num_teams:
17605 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
17606 break;
17607 case OMPC_thread_limit:
17608 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
17609 break;
17610 case OMPC_if:
17611 case OMPC_depobj:
17612 case OMPC_final:
17613 case OMPC_num_threads:
17614 case OMPC_safelen:
17615 case OMPC_simdlen:
17616 case OMPC_sizes:
17617 case OMPC_allocator:
17618 case OMPC_collapse:
17619 case OMPC_default:
17620 case OMPC_proc_bind:
17621 case OMPC_schedule:
17622 case OMPC_ordered:
17623 case OMPC_nowait:
17624 case OMPC_untied:
17625 case OMPC_mergeable:
17626 case OMPC_threadprivate:
17627 case OMPC_read:
17628 case OMPC_write:
17629 case OMPC_update:
17630 case OMPC_capture:
17631 case OMPC_compare:
17632 case OMPC_seq_cst:
17633 case OMPC_acq_rel:
17634 case OMPC_acquire:
17635 case OMPC_release:
17636 case OMPC_relaxed:
17637 case OMPC_device:
17638 case OMPC_threads:
17639 case OMPC_simd:
17640 case OMPC_priority:
17641 case OMPC_grainsize:
17642 case OMPC_nogroup:
17643 case OMPC_num_tasks:
17644 case OMPC_hint:
17645 case OMPC_dist_schedule:
17646 case OMPC_defaultmap:
17647 case OMPC_unknown:
17648 case OMPC_uniform:
17649 case OMPC_unified_address:
17650 case OMPC_unified_shared_memory:
17651 case OMPC_reverse_offload:
17652 case OMPC_dynamic_allocators:
17653 case OMPC_atomic_default_mem_order:
17654 case OMPC_self_maps:
17655 case OMPC_device_type:
17656 case OMPC_match:
17657 case OMPC_order:
17658 case OMPC_at:
17659 case OMPC_severity:
17660 case OMPC_message:
17661 case OMPC_destroy:
17662 case OMPC_novariants:
17663 case OMPC_nocontext:
17664 case OMPC_detach:
17665 case OMPC_uses_allocators:
17666 case OMPC_when:
17667 case OMPC_bind:
17668 default:
17669 llvm_unreachable("Clause is not allowed.");
17670 }
17671 return Res;
17672}
17673
17674ExprResult SemaOpenMP::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
17675 ExprObjectKind OK,
17676 SourceLocation Loc) {
17677 ExprResult Res = SemaRef.BuildDeclRefExpr(
17678 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
17679 if (!Res.isUsable())
17680 return ExprError();
17681 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17682 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: Loc, Opc: UO_Deref, InputExpr: Res.get());
17683 if (!Res.isUsable())
17684 return ExprError();
17685 }
17686 if (VK != VK_LValue && Res.get()->isGLValue()) {
17687 Res = SemaRef.DefaultLvalueConversion(E: Res.get());
17688 if (!Res.isUsable())
17689 return ExprError();
17690 }
17691 return Res;
17692}
17693
17694OMPClause *SemaOpenMP::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
17695 SourceLocation StartLoc,
17696 SourceLocation LParenLoc,
17697 SourceLocation EndLoc) {
17698 SmallVector<Expr *, 8> Vars;
17699 SmallVector<Expr *, 8> PrivateCopies;
17700 unsigned OMPVersion = getLangOpts().OpenMP;
17701 bool IsImplicitClause =
17702 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17703 for (Expr *RefExpr : VarList) {
17704 assert(RefExpr && "NULL expr in OpenMP private clause.");
17705 SourceLocation ELoc;
17706 SourceRange ERange;
17707 Expr *SimpleRefExpr = RefExpr;
17708 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
17709 if (Res.second) {
17710 // It will be analyzed later.
17711 Vars.push_back(Elt: RefExpr);
17712 PrivateCopies.push_back(Elt: nullptr);
17713 }
17714 ValueDecl *D = Res.first;
17715 if (!D)
17716 continue;
17717
17718 QualType Type = D->getType();
17719 auto *VD = dyn_cast<VarDecl>(Val: D);
17720
17721 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17722 // A variable that appears in a private clause must not have an incomplete
17723 // type or a reference type.
17724 if (SemaRef.RequireCompleteType(ELoc, Type,
17725 diag::err_omp_private_incomplete_type))
17726 continue;
17727 Type = Type.getNonReferenceType();
17728
17729 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17730 // A variable that is privatized must not have a const-qualified type
17731 // unless it is of class type with a mutable member. This restriction does
17732 // not apply to the firstprivate clause.
17733 //
17734 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
17735 // A variable that appears in a private clause must not have a
17736 // const-qualified type unless it is of class type with a mutable member.
17737 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
17738 continue;
17739
17740 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17741 // in a Construct]
17742 // Variables with the predetermined data-sharing attributes may not be
17743 // listed in data-sharing attributes clauses, except for the cases
17744 // listed below. For these exceptions only, listing a predetermined
17745 // variable in a data-sharing attribute clause is allowed and overrides
17746 // the variable's predetermined data-sharing attributes.
17747 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17748 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17749 Diag(ELoc, diag::err_omp_wrong_dsa)
17750 << getOpenMPClauseNameForDiag(DVar.CKind)
17751 << getOpenMPClauseNameForDiag(OMPC_private);
17752 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17753 continue;
17754 }
17755
17756 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17757 // Variably modified types are not supported for tasks.
17758 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
17759 isOpenMPTaskingDirective(CurrDir)) {
17760 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17761 << getOpenMPClauseNameForDiag(OMPC_private) << Type
17762 << getOpenMPDirectiveName(CurrDir, OMPVersion);
17763 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17764 VarDecl::DeclarationOnly;
17765 Diag(D->getLocation(),
17766 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17767 << D;
17768 continue;
17769 }
17770
17771 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17772 // A list item cannot appear in both a map clause and a data-sharing
17773 // attribute clause on the same construct
17774 //
17775 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17776 // A list item cannot appear in both a map clause and a data-sharing
17777 // attribute clause on the same construct unless the construct is a
17778 // combined construct.
17779 if ((getLangOpts().OpenMP <= 45 &&
17780 isOpenMPTargetExecutionDirective(CurrDir)) ||
17781 CurrDir == OMPD_target) {
17782 OpenMPClauseKind ConflictKind;
17783 if (DSAStack->checkMappableExprComponentListsForDecl(
17784 VD, /*CurrentRegionOnly=*/true,
17785 [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
17786 OpenMPClauseKind WhereFoundClauseKind) -> bool {
17787 ConflictKind = WhereFoundClauseKind;
17788 return true;
17789 })) {
17790 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17791 << getOpenMPClauseNameForDiag(OMPC_private)
17792 << getOpenMPClauseNameForDiag(ConflictKind)
17793 << getOpenMPDirectiveName(CurrDir, OMPVersion);
17794 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17795 continue;
17796 }
17797 }
17798
17799 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
17800 // A variable of class type (or array thereof) that appears in a private
17801 // clause requires an accessible, unambiguous default constructor for the
17802 // class type.
17803 // Generate helper private variable and initialize it with the default
17804 // value. The address of the original variable is replaced by the address of
17805 // the new private variable in CodeGen. This new variable is not added to
17806 // IdResolver, so the code in the OpenMP region uses original variable for
17807 // proper diagnostics.
17808 Type = Type.getUnqualifiedType();
17809 VarDecl *VDPrivate =
17810 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17811 D->hasAttrs() ? &D->getAttrs() : nullptr,
17812 VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
17813 SemaRef.ActOnUninitializedDecl(VDPrivate);
17814 if (VDPrivate->isInvalidDecl())
17815 continue;
17816 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17817 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(), Loc: ELoc);
17818
17819 DeclRefExpr *Ref = nullptr;
17820 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17821 auto *FD = dyn_cast<FieldDecl>(Val: D);
17822 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17823 if (VD)
17824 Ref = buildDeclRefExpr(SemaRef, VD, VD->getType().getNonReferenceType(),
17825 RefExpr->getExprLoc());
17826 else
17827 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
17828 }
17829 if (!IsImplicitClause)
17830 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17831 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
17832 ? RefExpr->IgnoreParens()
17833 : Ref);
17834 PrivateCopies.push_back(VDPrivateRefExpr);
17835 }
17836
17837 if (Vars.empty())
17838 return nullptr;
17839
17840 return OMPPrivateClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
17841 VL: Vars, PrivateVL: PrivateCopies);
17842}
17843
17844OMPClause *SemaOpenMP::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
17845 SourceLocation StartLoc,
17846 SourceLocation LParenLoc,
17847 SourceLocation EndLoc) {
17848 SmallVector<Expr *, 8> Vars;
17849 SmallVector<Expr *, 8> PrivateCopies;
17850 SmallVector<Expr *, 8> Inits;
17851 SmallVector<Decl *, 4> ExprCaptures;
17852 bool IsImplicitClause =
17853 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17854 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
17855 unsigned OMPVersion = getLangOpts().OpenMP;
17856
17857 for (Expr *RefExpr : VarList) {
17858 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
17859 SourceLocation ELoc;
17860 SourceRange ERange;
17861 Expr *SimpleRefExpr = RefExpr;
17862 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
17863 if (Res.second) {
17864 // It will be analyzed later.
17865 Vars.push_back(Elt: RefExpr);
17866 PrivateCopies.push_back(Elt: nullptr);
17867 Inits.push_back(Elt: nullptr);
17868 }
17869 ValueDecl *D = Res.first;
17870 if (!D)
17871 continue;
17872
17873 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17874 QualType Type = D->getType();
17875 auto *VD = dyn_cast<VarDecl>(Val: D);
17876
17877 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17878 // A variable that appears in a private clause must not have an incomplete
17879 // type or a reference type.
17880 if (SemaRef.RequireCompleteType(ELoc, Type,
17881 diag::err_omp_firstprivate_incomplete_type))
17882 continue;
17883 Type = Type.getNonReferenceType();
17884
17885 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
17886 // A variable of class type (or array thereof) that appears in a private
17887 // clause requires an accessible, unambiguous copy constructor for the
17888 // class type.
17889 QualType ElemType =
17890 getASTContext().getBaseElementType(Type).getNonReferenceType();
17891
17892 // If an implicit firstprivate variable found it was checked already.
17893 DSAStackTy::DSAVarData TopDVar;
17894 if (!IsImplicitClause) {
17895 DSAStackTy::DSAVarData DVar =
17896 DSAStack->getTopDSA(D, /*FromParent=*/false);
17897 TopDVar = DVar;
17898 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17899 bool IsConstant = ElemType.isConstant(getASTContext());
17900 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
17901 // A list item that specifies a given variable may not appear in more
17902 // than one clause on the same directive, except that a variable may be
17903 // specified in both firstprivate and lastprivate clauses.
17904 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17905 // A list item may appear in a firstprivate or lastprivate clause but not
17906 // both.
17907 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17908 (isOpenMPDistributeDirective(CurrDir) ||
17909 DVar.CKind != OMPC_lastprivate) &&
17910 DVar.RefExpr) {
17911 Diag(ELoc, diag::err_omp_wrong_dsa)
17912 << getOpenMPClauseNameForDiag(DVar.CKind)
17913 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
17914 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17915 continue;
17916 }
17917
17918 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17919 // in a Construct]
17920 // Variables with the predetermined data-sharing attributes may not be
17921 // listed in data-sharing attributes clauses, except for the cases
17922 // listed below. For these exceptions only, listing a predetermined
17923 // variable in a data-sharing attribute clause is allowed and overrides
17924 // the variable's predetermined data-sharing attributes.
17925 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17926 // in a Construct, C/C++, p.2]
17927 // Variables with const-qualified type having no mutable member may be
17928 // listed in a firstprivate clause, even if they are static data members.
17929 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17930 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17931 Diag(ELoc, diag::err_omp_wrong_dsa)
17932 << getOpenMPClauseNameForDiag(DVar.CKind)
17933 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
17934 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17935 continue;
17936 }
17937
17938 // OpenMP [2.9.3.4, Restrictions, p.2]
17939 // A list item that is private within a parallel region must not appear
17940 // in a firstprivate clause on a worksharing construct if any of the
17941 // worksharing regions arising from the worksharing construct ever bind
17942 // to any of the parallel regions arising from the parallel construct.
17943 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17944 // A list item that is private within a teams region must not appear in a
17945 // firstprivate clause on a distribute construct if any of the distribute
17946 // regions arising from the distribute construct ever bind to any of the
17947 // teams regions arising from the teams construct.
17948 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17949 // A list item that appears in a reduction clause of a teams construct
17950 // must not appear in a firstprivate clause on a distribute construct if
17951 // any of the distribute regions arising from the distribute construct
17952 // ever bind to any of the teams regions arising from the teams construct.
17953 if ((isOpenMPWorksharingDirective(CurrDir) ||
17954 isOpenMPDistributeDirective(CurrDir)) &&
17955 !isOpenMPParallelDirective(CurrDir) &&
17956 !isOpenMPTeamsDirective(CurrDir)) {
17957 DVar = DSAStack->getImplicitDSA(D, FromParent: true);
17958 if (DVar.CKind != OMPC_shared &&
17959 (isOpenMPParallelDirective(DVar.DKind) ||
17960 isOpenMPTeamsDirective(DVar.DKind) ||
17961 DVar.DKind == OMPD_unknown)) {
17962 Diag(ELoc, diag::err_omp_required_access)
17963 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
17964 << getOpenMPClauseNameForDiag(OMPC_shared);
17965 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17966 continue;
17967 }
17968 }
17969 // OpenMP [2.9.3.4, Restrictions, p.3]
17970 // A list item that appears in a reduction clause of a parallel construct
17971 // must not appear in a firstprivate clause on a worksharing or task
17972 // construct if any of the worksharing or task regions arising from the
17973 // worksharing or task construct ever bind to any of the parallel regions
17974 // arising from the parallel construct.
17975 // OpenMP [2.9.3.4, Restrictions, p.4]
17976 // A list item that appears in a reduction clause in worksharing
17977 // construct must not appear in a firstprivate clause in a task construct
17978 // encountered during execution of any of the worksharing regions arising
17979 // from the worksharing construct.
17980 if (isOpenMPTaskingDirective(CurrDir)) {
17981 DVar = DSAStack->hasInnermostDSA(
17982 D,
17983 [](OpenMPClauseKind C, bool AppliedToPointee) {
17984 return C == OMPC_reduction && !AppliedToPointee;
17985 },
17986 [](OpenMPDirectiveKind K) {
17987 return isOpenMPParallelDirective(K) ||
17988 isOpenMPWorksharingDirective(K) ||
17989 isOpenMPTeamsDirective(K);
17990 },
17991 /*FromParent=*/true);
17992 if (DVar.CKind == OMPC_reduction &&
17993 (isOpenMPParallelDirective(DVar.DKind) ||
17994 isOpenMPWorksharingDirective(DVar.DKind) ||
17995 isOpenMPTeamsDirective(DVar.DKind))) {
17996 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17997 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
17998 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17999 continue;
18000 }
18001 }
18002
18003 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18004 // A list item cannot appear in both a map clause and a data-sharing
18005 // attribute clause on the same construct
18006 //
18007 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18008 // A list item cannot appear in both a map clause and a data-sharing
18009 // attribute clause on the same construct unless the construct is a
18010 // combined construct.
18011 if ((getLangOpts().OpenMP <= 45 &&
18012 isOpenMPTargetExecutionDirective(CurrDir)) ||
18013 CurrDir == OMPD_target) {
18014 OpenMPClauseKind ConflictKind;
18015 if (DSAStack->checkMappableExprComponentListsForDecl(
18016 VD, /*CurrentRegionOnly=*/true,
18017 [&ConflictKind](
18018 OMPClauseMappableExprCommon::MappableExprComponentListRef,
18019 OpenMPClauseKind WhereFoundClauseKind) {
18020 ConflictKind = WhereFoundClauseKind;
18021 return true;
18022 })) {
18023 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18024 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
18025 << getOpenMPClauseNameForDiag(ConflictKind)
18026 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
18027 OMPVersion);
18028 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
18029 continue;
18030 }
18031 }
18032 }
18033
18034 // Variably modified types are not supported for tasks.
18035 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18036 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18037 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18038 << getOpenMPClauseNameForDiag(OMPC_firstprivate) << Type
18039 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
18040 OMPVersion);
18041 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18042 VarDecl::DeclarationOnly;
18043 Diag(D->getLocation(),
18044 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18045 << D;
18046 continue;
18047 }
18048
18049 Type = Type.getUnqualifiedType();
18050 VarDecl *VDPrivate =
18051 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
18052 D->hasAttrs() ? &D->getAttrs() : nullptr,
18053 VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
18054 // Generate helper private variable and initialize it with the value of the
18055 // original variable. The address of the original variable is replaced by
18056 // the address of the new private variable in the CodeGen. This new variable
18057 // is not added to IdResolver, so the code in the OpenMP region uses
18058 // original variable for proper diagnostics and variable capturing.
18059 Expr *VDInitRefExpr = nullptr;
18060 // For arrays generate initializer for single element and replace it by the
18061 // original array element in CodeGen.
18062 if (Type->isArrayType()) {
18063 VarDecl *VDInit =
18064 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
18065 VDInitRefExpr = buildDeclRefExpr(S&: SemaRef, D: VDInit, Ty: ElemType, Loc: ELoc);
18066 Expr *Init = SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get();
18067 ElemType = ElemType.getUnqualifiedType();
18068 VarDecl *VDInitTemp = buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(),
18069 Type: ElemType, Name: ".firstprivate.temp");
18070 InitializedEntity Entity =
18071 InitializedEntity::InitializeVariable(Var: VDInitTemp);
18072 InitializationKind Kind = InitializationKind::CreateCopy(InitLoc: ELoc, EqualLoc: ELoc);
18073
18074 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
18075 ExprResult Result = InitSeq.Perform(S&: SemaRef, Entity, Kind, Args: Init);
18076 if (Result.isInvalid())
18077 VDPrivate->setInvalidDecl();
18078 else
18079 VDPrivate->setInit(Result.getAs<Expr>());
18080 // Remove temp variable declaration.
18081 getASTContext().Deallocate(VDInitTemp);
18082 } else {
18083 VarDecl *VDInit = buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type,
18084 Name: ".firstprivate.temp");
18085 VDInitRefExpr = buildDeclRefExpr(S&: SemaRef, D: VDInit, Ty: RefExpr->getType(),
18086 Loc: RefExpr->getExprLoc());
18087 SemaRef.AddInitializerToDecl(
18088 VDPrivate, SemaRef.DefaultLvalueConversion(E: VDInitRefExpr).get(),
18089 /*DirectInit=*/false);
18090 }
18091 if (VDPrivate->isInvalidDecl()) {
18092 if (IsImplicitClause) {
18093 Diag(RefExpr->getExprLoc(),
18094 diag::note_omp_task_predetermined_firstprivate_here);
18095 }
18096 continue;
18097 }
18098 SemaRef.CurContext->addDecl(VDPrivate);
18099 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18100 S&: SemaRef, D: VDPrivate, Ty: RefExpr->getType().getUnqualifiedType(),
18101 Loc: RefExpr->getExprLoc());
18102 DeclRefExpr *Ref = nullptr;
18103 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18104 if (TopDVar.CKind == OMPC_lastprivate) {
18105 Ref = TopDVar.PrivateCopy;
18106 } else {
18107 auto *FD = dyn_cast<FieldDecl>(Val: D);
18108 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18109 if (VD)
18110 Ref =
18111 buildDeclRefExpr(SemaRef, VD, VD->getType().getNonReferenceType(),
18112 RefExpr->getExprLoc());
18113 else
18114 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
18115 if (VD || !isOpenMPCapturedDecl(D))
18116 ExprCaptures.push_back(Ref->getDecl());
18117 }
18118 }
18119 if (!IsImplicitClause)
18120 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18121 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
18122 ? RefExpr->IgnoreParens()
18123 : Ref);
18124 PrivateCopies.push_back(VDPrivateRefExpr);
18125 Inits.push_back(Elt: VDInitRefExpr);
18126 }
18127
18128 if (Vars.empty())
18129 return nullptr;
18130
18131 return OMPFirstprivateClause::Create(
18132 C: getASTContext(), StartLoc, LParenLoc, EndLoc, VL: Vars, PrivateVL: PrivateCopies, InitVL: Inits,
18133 PreInit: buildPreInits(getASTContext(), ExprCaptures));
18134}
18135
18136OMPClause *SemaOpenMP::ActOnOpenMPLastprivateClause(
18137 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
18138 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18139 SourceLocation LParenLoc, SourceLocation EndLoc) {
18140 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18141 assert(ColonLoc.isValid() && "Colon location must be valid.");
18142 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18143 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
18144 /*Last=*/OMPC_LASTPRIVATE_unknown)
18145 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
18146 return nullptr;
18147 }
18148
18149 SmallVector<Expr *, 8> Vars;
18150 SmallVector<Expr *, 8> SrcExprs;
18151 SmallVector<Expr *, 8> DstExprs;
18152 SmallVector<Expr *, 8> AssignmentOps;
18153 SmallVector<Decl *, 4> ExprCaptures;
18154 SmallVector<Expr *, 4> ExprPostUpdates;
18155 for (Expr *RefExpr : VarList) {
18156 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18157 SourceLocation ELoc;
18158 SourceRange ERange;
18159 Expr *SimpleRefExpr = RefExpr;
18160 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
18161 if (Res.second) {
18162 // It will be analyzed later.
18163 Vars.push_back(Elt: RefExpr);
18164 SrcExprs.push_back(Elt: nullptr);
18165 DstExprs.push_back(Elt: nullptr);
18166 AssignmentOps.push_back(Elt: nullptr);
18167 }
18168 ValueDecl *D = Res.first;
18169 if (!D)
18170 continue;
18171
18172 QualType Type = D->getType();
18173 auto *VD = dyn_cast<VarDecl>(Val: D);
18174
18175 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18176 // A variable that appears in a lastprivate clause must not have an
18177 // incomplete type or a reference type.
18178 if (SemaRef.RequireCompleteType(ELoc, Type,
18179 diag::err_omp_lastprivate_incomplete_type))
18180 continue;
18181 Type = Type.getNonReferenceType();
18182
18183 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18184 // A variable that is privatized must not have a const-qualified type
18185 // unless it is of class type with a mutable member. This restriction does
18186 // not apply to the firstprivate clause.
18187 //
18188 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18189 // A variable that appears in a lastprivate clause must not have a
18190 // const-qualified type unless it is of class type with a mutable member.
18191 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
18192 continue;
18193
18194 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18195 // A list item that appears in a lastprivate clause with the conditional
18196 // modifier must be a scalar variable.
18197 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18198 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18199 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18200 VarDecl::DeclarationOnly;
18201 Diag(D->getLocation(),
18202 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18203 << D;
18204 continue;
18205 }
18206
18207 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18208 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18209 // in a Construct]
18210 // Variables with the predetermined data-sharing attributes may not be
18211 // listed in data-sharing attributes clauses, except for the cases
18212 // listed below.
18213 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18214 // A list item may appear in a firstprivate or lastprivate clause but not
18215 // both.
18216 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18217 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18218 (isOpenMPDistributeDirective(CurrDir) ||
18219 DVar.CKind != OMPC_firstprivate) &&
18220 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
18221 Diag(ELoc, diag::err_omp_wrong_dsa)
18222 << getOpenMPClauseNameForDiag(DVar.CKind)
18223 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
18224 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
18225 continue;
18226 }
18227
18228 // OpenMP [2.14.3.5, Restrictions, p.2]
18229 // A list item that is private within a parallel region, or that appears in
18230 // the reduction clause of a parallel construct, must not appear in a
18231 // lastprivate clause on a worksharing construct if any of the corresponding
18232 // worksharing regions ever binds to any of the corresponding parallel
18233 // regions.
18234 DSAStackTy::DSAVarData TopDVar = DVar;
18235 if (isOpenMPWorksharingDirective(CurrDir) &&
18236 !isOpenMPParallelDirective(CurrDir) &&
18237 !isOpenMPTeamsDirective(CurrDir)) {
18238 DVar = DSAStack->getImplicitDSA(D, FromParent: true);
18239 if (DVar.CKind != OMPC_shared) {
18240 Diag(ELoc, diag::err_omp_required_access)
18241 << getOpenMPClauseNameForDiag(OMPC_lastprivate)
18242 << getOpenMPClauseNameForDiag(OMPC_shared);
18243 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
18244 continue;
18245 }
18246 }
18247
18248 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18249 // A variable of class type (or array thereof) that appears in a
18250 // lastprivate clause requires an accessible, unambiguous default
18251 // constructor for the class type, unless the list item is also specified
18252 // in a firstprivate clause.
18253 // A variable of class type (or array thereof) that appears in a
18254 // lastprivate clause requires an accessible, unambiguous copy assignment
18255 // operator for the class type.
18256 Type = getASTContext().getBaseElementType(Type).getNonReferenceType();
18257 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
18258 Type.getUnqualifiedType(), ".lastprivate.src",
18259 D->hasAttrs() ? &D->getAttrs() : nullptr);
18260 DeclRefExpr *PseudoSrcExpr =
18261 buildDeclRefExpr(S&: SemaRef, D: SrcVD, Ty: Type.getUnqualifiedType(), Loc: ELoc);
18262 VarDecl *DstVD =
18263 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
18264 D->hasAttrs() ? &D->getAttrs() : nullptr);
18265 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: Type, Loc: ELoc);
18266 // For arrays generate assignment operation for single element and replace
18267 // it by the original array element in CodeGen.
18268 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
18269 PseudoDstExpr, PseudoSrcExpr);
18270 if (AssignmentOp.isInvalid())
18271 continue;
18272 AssignmentOp = SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: ELoc,
18273 /*DiscardedValue=*/false);
18274 if (AssignmentOp.isInvalid())
18275 continue;
18276
18277 DeclRefExpr *Ref = nullptr;
18278 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18279 if (TopDVar.CKind == OMPC_firstprivate) {
18280 Ref = TopDVar.PrivateCopy;
18281 } else {
18282 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
18283 if (!isOpenMPCapturedDecl(D))
18284 ExprCaptures.push_back(Ref->getDecl());
18285 }
18286 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18287 (!isOpenMPCapturedDecl(D) &&
18288 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
18289 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
18290 if (!RefRes.isUsable())
18291 continue;
18292 ExprResult PostUpdateRes =
18293 SemaRef.BuildBinOp(DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign,
18294 LHSExpr: SimpleRefExpr, RHSExpr: RefRes.get());
18295 if (!PostUpdateRes.isUsable())
18296 continue;
18297 ExprPostUpdates.push_back(
18298 Elt: SemaRef.IgnoredValueConversions(E: PostUpdateRes.get()).get());
18299 }
18300 }
18301 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18302 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
18303 ? RefExpr->IgnoreParens()
18304 : Ref);
18305 SrcExprs.push_back(PseudoSrcExpr);
18306 DstExprs.push_back(PseudoDstExpr);
18307 AssignmentOps.push_back(Elt: AssignmentOp.get());
18308 }
18309
18310 if (Vars.empty())
18311 return nullptr;
18312
18313 return OMPLastprivateClause::Create(
18314 C: getASTContext(), StartLoc, LParenLoc, EndLoc, VL: Vars, SrcExprs, DstExprs,
18315 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
18316 PreInit: buildPreInits(getASTContext(), ExprCaptures),
18317 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: ExprPostUpdates));
18318}
18319
18320OMPClause *SemaOpenMP::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
18321 SourceLocation StartLoc,
18322 SourceLocation LParenLoc,
18323 SourceLocation EndLoc) {
18324 SmallVector<Expr *, 8> Vars;
18325 for (Expr *RefExpr : VarList) {
18326 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18327 SourceLocation ELoc;
18328 SourceRange ERange;
18329 Expr *SimpleRefExpr = RefExpr;
18330 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
18331 if (Res.second) {
18332 // It will be analyzed later.
18333 Vars.push_back(Elt: RefExpr);
18334 }
18335 ValueDecl *D = Res.first;
18336 if (!D)
18337 continue;
18338
18339 auto *VD = dyn_cast<VarDecl>(Val: D);
18340 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18341 // in a Construct]
18342 // Variables with the predetermined data-sharing attributes may not be
18343 // listed in data-sharing attributes clauses, except for the cases
18344 // listed below. For these exceptions only, listing a predetermined
18345 // variable in a data-sharing attribute clause is allowed and overrides
18346 // the variable's predetermined data-sharing attributes.
18347 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18348 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18349 DVar.RefExpr) {
18350 Diag(ELoc, diag::err_omp_wrong_dsa)
18351 << getOpenMPClauseNameForDiag(DVar.CKind)
18352 << getOpenMPClauseNameForDiag(OMPC_shared);
18353 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
18354 continue;
18355 }
18356
18357 DeclRefExpr *Ref = nullptr;
18358 if (!VD && isOpenMPCapturedDecl(D) &&
18359 !SemaRef.CurContext->isDependentContext())
18360 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
18361 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18362 Vars.push_back(Elt: (VD || !Ref || SemaRef.CurContext->isDependentContext())
18363 ? RefExpr->IgnoreParens()
18364 : Ref);
18365 }
18366
18367 if (Vars.empty())
18368 return nullptr;
18369
18370 return OMPSharedClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
18371 VL: Vars);
18372}
18373
18374namespace {
18375class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
18376 DSAStackTy *Stack;
18377
18378public:
18379 bool VisitDeclRefExpr(DeclRefExpr *E) {
18380 if (auto *VD = dyn_cast<VarDecl>(Val: E->getDecl())) {
18381 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
18382 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
18383 return false;
18384 if (DVar.CKind != OMPC_unknown)
18385 return true;
18386 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
18387 VD,
18388 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
18389 return isOpenMPPrivate(C) && !AppliedToPointee;
18390 },
18391 [](OpenMPDirectiveKind) { return true; },
18392 /*FromParent=*/true);
18393 return DVarPrivate.CKind != OMPC_unknown;
18394 }
18395 return false;
18396 }
18397 bool VisitStmt(Stmt *S) {
18398 for (Stmt *Child : S->children()) {
18399 if (Child && Visit(Child))
18400 return true;
18401 }
18402 return false;
18403 }
18404 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
18405};
18406} // namespace
18407
18408namespace {
18409// Transform MemberExpression for specified FieldDecl of current class to
18410// DeclRefExpr to specified OMPCapturedExprDecl.
18411class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
18412 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
18413 ValueDecl *Field = nullptr;
18414 DeclRefExpr *CapturedExpr = nullptr;
18415
18416public:
18417 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18418 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
18419
18420 ExprResult TransformMemberExpr(MemberExpr *E) {
18421 if (isa<CXXThisExpr>(Val: E->getBase()->IgnoreParenImpCasts()) &&
18422 E->getMemberDecl() == Field) {
18423 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
18424 return CapturedExpr;
18425 }
18426 return BaseTransform::TransformMemberExpr(E);
18427 }
18428 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
18429};
18430} // namespace
18431
18432template <typename T, typename U>
18433static T filterLookupForUDReductionAndMapper(
18434 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
18435 for (U &Set : Lookups) {
18436 for (auto *D : Set) {
18437 if (T Res = Gen(cast<ValueDecl>(D)))
18438 return Res;
18439 }
18440 }
18441 return T();
18442}
18443
18444static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
18445 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
18446
18447 for (auto *RD : D->redecls()) {
18448 // Don't bother with extra checks if we already know this one isn't visible.
18449 if (RD == D)
18450 continue;
18451
18452 auto ND = cast<NamedDecl>(RD);
18453 if (LookupResult::isVisible(SemaRef, ND))
18454 return ND;
18455 }
18456
18457 return nullptr;
18458}
18459
18460static void
18461argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
18462 SourceLocation Loc, QualType Ty,
18463 SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
18464 // Find all of the associated namespaces and classes based on the
18465 // arguments we have.
18466 Sema::AssociatedNamespaceSet AssociatedNamespaces;
18467 Sema::AssociatedClassSet AssociatedClasses;
18468 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
18469 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
18470 AssociatedClasses);
18471
18472 // C++ [basic.lookup.argdep]p3:
18473 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18474 // and let Y be the lookup set produced by argument dependent
18475 // lookup (defined as follows). If X contains [...] then Y is
18476 // empty. Otherwise Y is the set of declarations found in the
18477 // namespaces associated with the argument types as described
18478 // below. The set of declarations found by the lookup of the name
18479 // is the union of X and Y.
18480 //
18481 // Here, we compute Y and add its members to the overloaded
18482 // candidate set.
18483 for (auto *NS : AssociatedNamespaces) {
18484 // When considering an associated namespace, the lookup is the
18485 // same as the lookup performed when the associated namespace is
18486 // used as a qualifier (3.4.3.2) except that:
18487 //
18488 // -- Any using-directives in the associated namespace are
18489 // ignored.
18490 //
18491 // -- Any namespace-scope friend functions declared in
18492 // associated classes are visible within their respective
18493 // namespaces even if they are not visible during an ordinary
18494 // lookup (11.4).
18495 DeclContext::lookup_result R = NS->lookup(Name: Id.getName());
18496 for (auto *D : R) {
18497 auto *Underlying = D;
18498 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
18499 Underlying = USD->getTargetDecl();
18500
18501 if (!isa<OMPDeclareReductionDecl>(Val: Underlying) &&
18502 !isa<OMPDeclareMapperDecl>(Val: Underlying))
18503 continue;
18504
18505 if (!SemaRef.isVisible(D)) {
18506 D = findAcceptableDecl(SemaRef, D);
18507 if (!D)
18508 continue;
18509 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
18510 Underlying = USD->getTargetDecl();
18511 }
18512 Lookups.emplace_back();
18513 Lookups.back().addDecl(D: Underlying);
18514 }
18515 }
18516}
18517
18518static ExprResult
18519buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
18520 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
18521 const DeclarationNameInfo &ReductionId, QualType Ty,
18522 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
18523 if (ReductionIdScopeSpec.isInvalid())
18524 return ExprError();
18525 SmallVector<UnresolvedSet<8>, 4> Lookups;
18526 if (S) {
18527 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18528 Lookup.suppressDiagnostics();
18529 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &ReductionIdScopeSpec,
18530 /*ObjectType=*/QualType())) {
18531 NamedDecl *D = Lookup.getRepresentativeDecl();
18532 do {
18533 S = S->getParent();
18534 } while (S && !S->isDeclScope(D));
18535 if (S)
18536 S = S->getParent();
18537 Lookups.emplace_back();
18538 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
18539 Lookup.clear();
18540 }
18541 } else if (auto *ULE =
18542 cast_or_null<UnresolvedLookupExpr>(Val: UnresolvedReduction)) {
18543 Lookups.push_back(Elt: UnresolvedSet<8>());
18544 Decl *PrevD = nullptr;
18545 for (NamedDecl *D : ULE->decls()) {
18546 if (D == PrevD)
18547 Lookups.push_back(UnresolvedSet<8>());
18548 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
18549 Lookups.back().addDecl(DRD);
18550 PrevD = D;
18551 }
18552 }
18553 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
18554 Ty->isInstantiationDependentType() ||
18555 Ty->containsUnexpandedParameterPack() ||
18556 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
18557 return !D->isInvalidDecl() &&
18558 (D->getType()->isDependentType() ||
18559 D->getType()->isInstantiationDependentType() ||
18560 D->getType()->containsUnexpandedParameterPack());
18561 })) {
18562 UnresolvedSet<8> ResSet;
18563 for (const UnresolvedSet<8> &Set : Lookups) {
18564 if (Set.empty())
18565 continue;
18566 ResSet.append(I: Set.begin(), E: Set.end());
18567 // The last item marks the end of all declarations at the specified scope.
18568 ResSet.addDecl(D: Set[Set.size() - 1]);
18569 }
18570 return UnresolvedLookupExpr::Create(
18571 Context: SemaRef.Context, /*NamingClass=*/nullptr,
18572 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: SemaRef.Context), NameInfo: ReductionId,
18573 /*ADL=*/RequiresADL: true, Begin: ResSet.begin(), End: ResSet.end(), /*KnownDependent=*/false,
18574 /*KnownInstantiationDependent=*/false);
18575 }
18576 // Lookup inside the classes.
18577 // C++ [over.match.oper]p3:
18578 // For a unary operator @ with an operand of a type whose
18579 // cv-unqualified version is T1, and for a binary operator @ with
18580 // a left operand of a type whose cv-unqualified version is T1 and
18581 // a right operand of a type whose cv-unqualified version is T2,
18582 // three sets of candidate functions, designated member
18583 // candidates, non-member candidates and built-in candidates, are
18584 // constructed as follows:
18585 // -- If T1 is a complete class type or a class currently being
18586 // defined, the set of member candidates is the result of the
18587 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
18588 // the set of member candidates is empty.
18589 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18590 Lookup.suppressDiagnostics();
18591 if (const auto *TyRec = Ty->getAs<RecordType>()) {
18592 // Complete the type if it can be completed.
18593 // If the type is neither complete nor being defined, bail out now.
18594 if (SemaRef.isCompleteType(Loc, T: Ty) || TyRec->isBeingDefined() ||
18595 TyRec->getDecl()->getDefinition()) {
18596 Lookup.clear();
18597 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
18598 if (Lookup.empty()) {
18599 Lookups.emplace_back();
18600 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
18601 }
18602 }
18603 }
18604 // Perform ADL.
18605 if (SemaRef.getLangOpts().CPlusPlus)
18606 argumentDependentLookup(SemaRef, Id: ReductionId, Loc, Ty, Lookups);
18607 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18608 Lookups, Gen: [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
18609 if (!D->isInvalidDecl() &&
18610 SemaRef.Context.hasSameType(T1: D->getType(), T2: Ty))
18611 return D;
18612 return nullptr;
18613 }))
18614 return SemaRef.BuildDeclRefExpr(D: VD, Ty: VD->getType().getNonReferenceType(),
18615 VK: VK_LValue, Loc);
18616 if (SemaRef.getLangOpts().CPlusPlus) {
18617 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18618 Lookups, Gen: [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
18619 if (!D->isInvalidDecl() &&
18620 SemaRef.IsDerivedFrom(Loc, Derived: Ty, Base: D->getType()) &&
18621 !Ty.isMoreQualifiedThan(other: D->getType(),
18622 Ctx: SemaRef.getASTContext()))
18623 return D;
18624 return nullptr;
18625 })) {
18626 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18627 /*DetectVirtual=*/false);
18628 if (SemaRef.IsDerivedFrom(Loc, Derived: Ty, Base: VD->getType(), Paths)) {
18629 if (!Paths.isAmbiguous(BaseType: SemaRef.Context.getCanonicalType(
18630 T: VD->getType().getUnqualifiedType()))) {
18631 if (SemaRef.CheckBaseClassAccess(
18632 AccessLoc: Loc, Base: VD->getType(), Derived: Ty, Path: Paths.front(),
18633 /*DiagID=*/0) != Sema::AR_inaccessible) {
18634 SemaRef.BuildBasePathArray(Paths, BasePath);
18635 return SemaRef.BuildDeclRefExpr(
18636 D: VD, Ty: VD->getType().getNonReferenceType(), VK: VK_LValue, Loc);
18637 }
18638 }
18639 }
18640 }
18641 }
18642 if (ReductionIdScopeSpec.isSet()) {
18643 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18644 << Ty << Range;
18645 return ExprError();
18646 }
18647 return ExprEmpty();
18648}
18649
18650namespace {
18651/// Data for the reduction-based clauses.
18652struct ReductionData {
18653 /// List of original reduction items.
18654 SmallVector<Expr *, 8> Vars;
18655 /// List of private copies of the reduction items.
18656 SmallVector<Expr *, 8> Privates;
18657 /// LHS expressions for the reduction_op expressions.
18658 SmallVector<Expr *, 8> LHSs;
18659 /// RHS expressions for the reduction_op expressions.
18660 SmallVector<Expr *, 8> RHSs;
18661 /// Reduction operation expression.
18662 SmallVector<Expr *, 8> ReductionOps;
18663 /// inscan copy operation expressions.
18664 SmallVector<Expr *, 8> InscanCopyOps;
18665 /// inscan copy temp array expressions for prefix sums.
18666 SmallVector<Expr *, 8> InscanCopyArrayTemps;
18667 /// inscan copy temp array element expressions for prefix sums.
18668 SmallVector<Expr *, 8> InscanCopyArrayElems;
18669 /// Taskgroup descriptors for the corresponding reduction items in
18670 /// in_reduction clauses.
18671 SmallVector<Expr *, 8> TaskgroupDescriptors;
18672 /// List of captures for clause.
18673 SmallVector<Decl *, 4> ExprCaptures;
18674 /// List of postupdate expressions.
18675 SmallVector<Expr *, 4> ExprPostUpdates;
18676 /// Reduction modifier.
18677 unsigned RedModifier = 0;
18678 /// Original modifier.
18679 unsigned OrigSharingModifier = 0;
18680 /// Private Variable Reduction
18681 SmallVector<bool, 8> IsPrivateVarReduction;
18682 ReductionData() = delete;
18683 /// Reserves required memory for the reduction data.
18684 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
18685 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
18686 Vars.reserve(N: Size);
18687 Privates.reserve(N: Size);
18688 LHSs.reserve(N: Size);
18689 RHSs.reserve(N: Size);
18690 ReductionOps.reserve(N: Size);
18691 IsPrivateVarReduction.reserve(N: Size);
18692 if (RedModifier == OMPC_REDUCTION_inscan) {
18693 InscanCopyOps.reserve(N: Size);
18694 InscanCopyArrayTemps.reserve(N: Size);
18695 InscanCopyArrayElems.reserve(N: Size);
18696 }
18697 TaskgroupDescriptors.reserve(N: Size);
18698 ExprCaptures.reserve(N: Size);
18699 ExprPostUpdates.reserve(N: Size);
18700 }
18701 /// Stores reduction item and reduction operation only (required for dependent
18702 /// reduction item).
18703 void push(Expr *Item, Expr *ReductionOp) {
18704 Vars.emplace_back(Args&: Item);
18705 Privates.emplace_back(Args: nullptr);
18706 LHSs.emplace_back(Args: nullptr);
18707 RHSs.emplace_back(Args: nullptr);
18708 ReductionOps.emplace_back(Args&: ReductionOp);
18709 IsPrivateVarReduction.emplace_back(Args: false);
18710 TaskgroupDescriptors.emplace_back(Args: nullptr);
18711 if (RedModifier == OMPC_REDUCTION_inscan) {
18712 InscanCopyOps.push_back(Elt: nullptr);
18713 InscanCopyArrayTemps.push_back(Elt: nullptr);
18714 InscanCopyArrayElems.push_back(Elt: nullptr);
18715 }
18716 }
18717 /// Stores reduction data.
18718 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
18719 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
18720 Expr *CopyArrayElem, bool IsPrivate) {
18721 Vars.emplace_back(Args&: Item);
18722 Privates.emplace_back(Args&: Private);
18723 LHSs.emplace_back(Args&: LHS);
18724 RHSs.emplace_back(Args&: RHS);
18725 ReductionOps.emplace_back(Args&: ReductionOp);
18726 TaskgroupDescriptors.emplace_back(Args&: TaskgroupDescriptor);
18727 if (RedModifier == OMPC_REDUCTION_inscan) {
18728 InscanCopyOps.push_back(Elt: CopyOp);
18729 InscanCopyArrayTemps.push_back(Elt: CopyArrayTemp);
18730 InscanCopyArrayElems.push_back(Elt: CopyArrayElem);
18731 } else {
18732 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
18733 CopyArrayElem == nullptr &&
18734 "Copy operation must be used for inscan reductions only.");
18735 }
18736 IsPrivateVarReduction.emplace_back(Args&: IsPrivate);
18737 }
18738};
18739} // namespace
18740
18741static bool checkOMPArraySectionConstantForReduction(
18742 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
18743 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
18744 const Expr *Length = OASE->getLength();
18745 if (Length == nullptr) {
18746 // For array sections of the form [1:] or [:], we would need to analyze
18747 // the lower bound...
18748 if (OASE->getColonLocFirst().isValid())
18749 return false;
18750
18751 // This is an array subscript which has implicit length 1!
18752 SingleElement = true;
18753 ArraySizes.push_back(Elt: llvm::APSInt::get(X: 1));
18754 } else {
18755 Expr::EvalResult Result;
18756 if (!Length->EvaluateAsInt(Result, Ctx: Context))
18757 return false;
18758
18759 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18760 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18761 ArraySizes.push_back(Elt: ConstantLengthValue);
18762 }
18763
18764 // Get the base of this array section and walk up from there.
18765 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
18766
18767 // We require length = 1 for all array sections except the right-most to
18768 // guarantee that the memory region is contiguous and has no holes in it.
18769 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Val: Base)) {
18770 Length = TempOASE->getLength();
18771 if (Length == nullptr) {
18772 // For array sections of the form [1:] or [:], we would need to analyze
18773 // the lower bound...
18774 if (OASE->getColonLocFirst().isValid())
18775 return false;
18776
18777 // This is an array subscript which has implicit length 1!
18778 llvm::APSInt ConstantOne = llvm::APSInt::get(X: 1);
18779 ArraySizes.push_back(Elt: ConstantOne);
18780 } else {
18781 Expr::EvalResult Result;
18782 if (!Length->EvaluateAsInt(Result, Ctx: Context))
18783 return false;
18784
18785 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18786 if (ConstantLengthValue.getSExtValue() != 1)
18787 return false;
18788
18789 ArraySizes.push_back(Elt: ConstantLengthValue);
18790 }
18791 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18792 }
18793
18794 // If we have a single element, we don't need to add the implicit lengths.
18795 if (!SingleElement) {
18796 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Val: Base)) {
18797 // Has implicit length 1!
18798 llvm::APSInt ConstantOne = llvm::APSInt::get(X: 1);
18799 ArraySizes.push_back(Elt: ConstantOne);
18800 Base = TempASE->getBase()->IgnoreParenImpCasts();
18801 }
18802 }
18803
18804 // This array section can be privatized as a single value or as a constant
18805 // sized array.
18806 return true;
18807}
18808
18809static BinaryOperatorKind
18810getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
18811 if (BOK == BO_Add)
18812 return BO_AddAssign;
18813 if (BOK == BO_Mul)
18814 return BO_MulAssign;
18815 if (BOK == BO_And)
18816 return BO_AndAssign;
18817 if (BOK == BO_Or)
18818 return BO_OrAssign;
18819 if (BOK == BO_Xor)
18820 return BO_XorAssign;
18821 return BOK;
18822}
18823
18824static bool actOnOMPReductionKindClause(
18825 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
18826 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18827 SourceLocation ColonLoc, SourceLocation EndLoc,
18828 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18829 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
18830 DeclarationName DN = ReductionId.getName();
18831 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
18832 BinaryOperatorKind BOK = BO_Comma;
18833
18834 ASTContext &Context = S.Context;
18835 // OpenMP [2.14.3.6, reduction clause]
18836 // C
18837 // reduction-identifier is either an identifier or one of the following
18838 // operators: +, -, *, &, |, ^, && and ||
18839 // C++
18840 // reduction-identifier is either an id-expression or one of the following
18841 // operators: +, -, *, &, |, ^, && and ||
18842 switch (OOK) {
18843 case OO_Plus:
18844 BOK = BO_Add;
18845 break;
18846 case OO_Minus:
18847 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
18848 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
18849 // reduction identifier.
18850 if (S.LangOpts.OpenMP > 52)
18851 BOK = BO_Comma;
18852 else
18853 BOK = BO_Add;
18854 break;
18855 case OO_Star:
18856 BOK = BO_Mul;
18857 break;
18858 case OO_Amp:
18859 BOK = BO_And;
18860 break;
18861 case OO_Pipe:
18862 BOK = BO_Or;
18863 break;
18864 case OO_Caret:
18865 BOK = BO_Xor;
18866 break;
18867 case OO_AmpAmp:
18868 BOK = BO_LAnd;
18869 break;
18870 case OO_PipePipe:
18871 BOK = BO_LOr;
18872 break;
18873 case OO_New:
18874 case OO_Delete:
18875 case OO_Array_New:
18876 case OO_Array_Delete:
18877 case OO_Slash:
18878 case OO_Percent:
18879 case OO_Tilde:
18880 case OO_Exclaim:
18881 case OO_Equal:
18882 case OO_Less:
18883 case OO_Greater:
18884 case OO_LessEqual:
18885 case OO_GreaterEqual:
18886 case OO_PlusEqual:
18887 case OO_MinusEqual:
18888 case OO_StarEqual:
18889 case OO_SlashEqual:
18890 case OO_PercentEqual:
18891 case OO_CaretEqual:
18892 case OO_AmpEqual:
18893 case OO_PipeEqual:
18894 case OO_LessLess:
18895 case OO_GreaterGreater:
18896 case OO_LessLessEqual:
18897 case OO_GreaterGreaterEqual:
18898 case OO_EqualEqual:
18899 case OO_ExclaimEqual:
18900 case OO_Spaceship:
18901 case OO_PlusPlus:
18902 case OO_MinusMinus:
18903 case OO_Comma:
18904 case OO_ArrowStar:
18905 case OO_Arrow:
18906 case OO_Call:
18907 case OO_Subscript:
18908 case OO_Conditional:
18909 case OO_Coawait:
18910 case NUM_OVERLOADED_OPERATORS:
18911 llvm_unreachable("Unexpected reduction identifier");
18912 case OO_None:
18913 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
18914 if (II->isStr(Str: "max"))
18915 BOK = BO_GT;
18916 else if (II->isStr(Str: "min"))
18917 BOK = BO_LT;
18918 }
18919 break;
18920 }
18921
18922 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
18923 // A reduction clause with the minus (-) operator was deprecated
18924 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
18925 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18926
18927 SourceRange ReductionIdRange;
18928 if (ReductionIdScopeSpec.isValid())
18929 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
18930 else
18931 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
18932 ReductionIdRange.setEnd(ReductionId.getEndLoc());
18933
18934 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18935 bool FirstIter = true;
18936 for (Expr *RefExpr : VarList) {
18937 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
18938 // OpenMP [2.1, C/C++]
18939 // A list item is a variable or array section, subject to the restrictions
18940 // specified in Section 2.4 on page 42 and in each of the sections
18941 // describing clauses and directives for which a list appears.
18942 // OpenMP [2.14.3.3, Restrictions, p.1]
18943 // A variable that is part of another variable (as an array or
18944 // structure element) cannot appear in a private clause.
18945 if (!FirstIter && IR != ER)
18946 ++IR;
18947 FirstIter = false;
18948 SourceLocation ELoc;
18949 SourceRange ERange;
18950 bool IsPrivate = false;
18951 Expr *SimpleRefExpr = RefExpr;
18952 auto Res = getPrivateItem(S, RefExpr&: SimpleRefExpr, ELoc, ERange,
18953 /*AllowArraySection=*/true);
18954 if (Res.second) {
18955 // Try to find 'declare reduction' corresponding construct before using
18956 // builtin/overloaded operators.
18957 QualType Type = Context.DependentTy;
18958 CXXCastPath BasePath;
18959 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18960 SemaRef&: S, Loc: ELoc, Range: ERange, S: Stack->getCurScope(), ReductionIdScopeSpec,
18961 ReductionId, Ty: Type, BasePath, UnresolvedReduction: IR == ER ? nullptr : *IR);
18962 Expr *ReductionOp = nullptr;
18963 if (S.CurContext->isDependentContext() &&
18964 (DeclareReductionRef.isUnset() ||
18965 isa<UnresolvedLookupExpr>(Val: DeclareReductionRef.get())))
18966 ReductionOp = DeclareReductionRef.get();
18967 // It will be analyzed later.
18968 RD.push(Item: RefExpr, ReductionOp);
18969 }
18970 ValueDecl *D = Res.first;
18971 if (!D)
18972 continue;
18973
18974 Expr *TaskgroupDescriptor = nullptr;
18975 QualType Type;
18976 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: RefExpr->IgnoreParens());
18977 auto *OASE = dyn_cast<ArraySectionExpr>(Val: RefExpr->IgnoreParens());
18978 if (ASE) {
18979 Type = ASE->getType().getNonReferenceType();
18980 } else if (OASE) {
18981 QualType BaseType =
18982 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
18983 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
18984 Type = ATy->getElementType();
18985 else
18986 Type = BaseType->getPointeeType();
18987 Type = Type.getNonReferenceType();
18988 } else {
18989 Type = Context.getBaseElementType(QT: D->getType().getNonReferenceType());
18990 }
18991 auto *VD = dyn_cast<VarDecl>(Val: D);
18992
18993 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18994 // A variable that appears in a private clause must not have an incomplete
18995 // type or a reference type.
18996 if (S.RequireCompleteType(ELoc, D->getType(),
18997 diag::err_omp_reduction_incomplete_type))
18998 continue;
18999 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19000 // A list item that appears in a reduction clause must not be
19001 // const-qualified.
19002 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
19003 /*AcceptIfMutable=*/false, ASE || OASE))
19004 continue;
19005
19006 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
19007 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19008 // If a list-item is a reference type then it must bind to the same object
19009 // for all threads of the team.
19010 if (!ASE && !OASE) {
19011 if (VD) {
19012 VarDecl *VDDef = VD->getDefinition();
19013 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
19014 DSARefChecker Check(Stack);
19015 if (Check.Visit(VDDef->getInit())) {
19016 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19017 << getOpenMPClauseNameForDiag(ClauseKind) << ERange;
19018 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
19019 continue;
19020 }
19021 }
19022 }
19023
19024 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19025 // in a Construct]
19026 // Variables with the predetermined data-sharing attributes may not be
19027 // listed in data-sharing attributes clauses, except for the cases
19028 // listed below. For these exceptions only, listing a predetermined
19029 // variable in a data-sharing attribute clause is allowed and overrides
19030 // the variable's predetermined data-sharing attributes.
19031 // OpenMP [2.14.3.6, Restrictions, p.3]
19032 // Any number of reduction clauses can be specified on the directive,
19033 // but a list item can appear only once in the reduction clauses for that
19034 // directive.
19035 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19036 if (DVar.CKind == OMPC_reduction) {
19037 S.Diag(ELoc, diag::err_omp_once_referenced)
19038 << getOpenMPClauseNameForDiag(ClauseKind);
19039 if (DVar.RefExpr)
19040 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
19041 continue;
19042 }
19043 if (DVar.CKind != OMPC_unknown) {
19044 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19045 << getOpenMPClauseNameForDiag(DVar.CKind)
19046 << getOpenMPClauseNameForDiag(OMPC_reduction);
19047 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
19048 continue;
19049 }
19050
19051 // OpenMP [2.14.3.6, Restrictions, p.1]
19052 // A list item that appears in a reduction clause of a worksharing
19053 // construct must be shared in the parallel regions to which any of the
19054 // worksharing regions arising from the worksharing construct bind.
19055
19056 if (S.getLangOpts().OpenMP <= 52 &&
19057 isOpenMPWorksharingDirective(CurrDir) &&
19058 !isOpenMPParallelDirective(CurrDir) &&
19059 !isOpenMPTeamsDirective(CurrDir)) {
19060 DVar = Stack->getImplicitDSA(D, FromParent: true);
19061 if (DVar.CKind != OMPC_shared) {
19062 S.Diag(ELoc, diag::err_omp_required_access)
19063 << getOpenMPClauseNameForDiag(OMPC_reduction)
19064 << getOpenMPClauseNameForDiag(OMPC_shared);
19065 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
19066 continue;
19067 }
19068 } else if (isOpenMPWorksharingDirective(CurrDir) &&
19069 !isOpenMPParallelDirective(CurrDir) &&
19070 !isOpenMPTeamsDirective(CurrDir)) {
19071 // OpenMP 6.0 [ 7.6.10 ]
19072 // Support Reduction over private variables with reduction clause.
19073 // A list item in a reduction clause can now be private in the enclosing
19074 // context. For orphaned constructs it is assumed to be shared unless
19075 // the original(private) modifier appears in the clause.
19076 DVar = Stack->getImplicitDSA(D, FromParent: true);
19077 // Determine if the variable should be considered private
19078 IsPrivate = DVar.CKind != OMPC_shared;
19079 bool IsOrphaned = false;
19080 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
19081 IsOrphaned = ParentDir == OMPD_unknown;
19082 if ((IsOrphaned &&
19083 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
19084 IsPrivate = true;
19085 }
19086 } else {
19087 // Threadprivates cannot be shared between threads, so dignose if the base
19088 // is a threadprivate variable.
19089 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19090 if (DVar.CKind == OMPC_threadprivate) {
19091 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19092 << getOpenMPClauseNameForDiag(DVar.CKind)
19093 << getOpenMPClauseNameForDiag(OMPC_reduction);
19094 reportOriginalDsa(SemaRef&: S, Stack, D, DVar);
19095 continue;
19096 }
19097 }
19098
19099 // Try to find 'declare reduction' corresponding construct before using
19100 // builtin/overloaded operators.
19101 CXXCastPath BasePath;
19102 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19103 SemaRef&: S, Loc: ELoc, Range: ERange, S: Stack->getCurScope(), ReductionIdScopeSpec,
19104 ReductionId, Ty: Type, BasePath, UnresolvedReduction: IR == ER ? nullptr : *IR);
19105 if (DeclareReductionRef.isInvalid())
19106 continue;
19107 if (S.CurContext->isDependentContext() &&
19108 (DeclareReductionRef.isUnset() ||
19109 isa<UnresolvedLookupExpr>(Val: DeclareReductionRef.get()))) {
19110 RD.push(Item: RefExpr, ReductionOp: DeclareReductionRef.get());
19111 continue;
19112 }
19113 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19114 // Not allowed reduction identifier is found.
19115 if (S.LangOpts.OpenMP > 52)
19116 S.Diag(ReductionId.getBeginLoc(),
19117 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
19118 << Type << ReductionIdRange;
19119 else
19120 S.Diag(ReductionId.getBeginLoc(),
19121 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
19122 << Type << ReductionIdRange;
19123 continue;
19124 }
19125
19126 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19127 // The type of a list item that appears in a reduction clause must be valid
19128 // for the reduction-identifier. For a max or min reduction in C, the type
19129 // of the list item must be an allowed arithmetic data type: char, int,
19130 // float, double, or _Bool, possibly modified with long, short, signed, or
19131 // unsigned. For a max or min reduction in C++, the type of the list item
19132 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19133 // double, or bool, possibly modified with long, short, signed, or unsigned.
19134 if (DeclareReductionRef.isUnset()) {
19135 if ((BOK == BO_GT || BOK == BO_LT) &&
19136 !(Type->isScalarType() ||
19137 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19138 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19139 << getOpenMPClauseNameForDiag(ClauseKind)
19140 << S.getLangOpts().CPlusPlus;
19141 if (!ASE && !OASE) {
19142 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19143 VarDecl::DeclarationOnly;
19144 S.Diag(D->getLocation(),
19145 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19146 << D;
19147 }
19148 continue;
19149 }
19150 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19151 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19152 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19153 << getOpenMPClauseNameForDiag(ClauseKind);
19154 if (!ASE && !OASE) {
19155 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19156 VarDecl::DeclarationOnly;
19157 S.Diag(D->getLocation(),
19158 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19159 << D;
19160 }
19161 continue;
19162 }
19163 }
19164
19165 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19166 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
19167 D->hasAttrs() ? &D->getAttrs() : nullptr);
19168 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
19169 D->hasAttrs() ? &D->getAttrs() : nullptr);
19170 QualType PrivateTy = Type;
19171
19172 // Try if we can determine constant lengths for all array sections and avoid
19173 // the VLA.
19174 bool ConstantLengthOASE = false;
19175 if (OASE) {
19176 bool SingleElement;
19177 llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
19178 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19179 Context, OASE, SingleElement, ArraySizes);
19180
19181 // If we don't have a single element, we must emit a constant array type.
19182 if (ConstantLengthOASE && !SingleElement) {
19183 for (llvm::APSInt &Size : ArraySizes)
19184 PrivateTy = Context.getConstantArrayType(EltTy: PrivateTy, ArySize: Size, SizeExpr: nullptr,
19185 ASM: ArraySizeModifier::Normal,
19186 /*IndexTypeQuals=*/0);
19187 }
19188 }
19189
19190 if ((OASE && !ConstantLengthOASE) ||
19191 (!OASE && !ASE &&
19192 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
19193 if (!Context.getTargetInfo().isVLASupported()) {
19194 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
19195 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19196 S.Diag(ELoc, diag::note_vla_unsupported);
19197 continue;
19198 } else {
19199 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19200 S.targetDiag(ELoc, diag::note_vla_unsupported);
19201 }
19202 }
19203 // For arrays/array sections only:
19204 // Create pseudo array type for private copy. The size for this array will
19205 // be generated during codegen.
19206 // For array subscripts or single variables Private Ty is the same as Type
19207 // (type of the variable or single array element).
19208 PrivateTy = Context.getVariableArrayType(
19209 Type,
19210 new (Context)
19211 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19212 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
19213 } else if (!ASE && !OASE &&
19214 Context.getAsArrayType(T: D->getType().getNonReferenceType())) {
19215 PrivateTy = D->getType().getNonReferenceType();
19216 }
19217 // Private copy.
19218 VarDecl *PrivateVD =
19219 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19220 D->hasAttrs() ? &D->getAttrs() : nullptr,
19221 VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
19222 // Add initializer for private variable.
19223 Expr *Init = nullptr;
19224 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, D: LHSVD, Ty: Type, Loc: ELoc);
19225 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, D: RHSVD, Ty: Type, Loc: ELoc);
19226 if (DeclareReductionRef.isUsable()) {
19227 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19228 auto *DRD = cast<OMPDeclareReductionDecl>(Val: DRDRef->getDecl());
19229 if (DRD->getInitializer()) {
19230 Init = DRDRef;
19231 RHSVD->setInit(DRDRef);
19232 RHSVD->setInitStyle(VarDecl::CallInit);
19233 }
19234 } else {
19235 switch (BOK) {
19236 case BO_Add:
19237 case BO_Xor:
19238 case BO_Or:
19239 case BO_LOr:
19240 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19241 if (Type->isScalarType() || Type->isAnyComplexType())
19242 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/0).get();
19243 break;
19244 case BO_Mul:
19245 case BO_LAnd:
19246 if (Type->isScalarType() || Type->isAnyComplexType()) {
19247 // '*' and '&&' reduction ops - initializer is '1'.
19248 Init = S.ActOnIntegerConstant(Loc: ELoc, /*Val=*/1).get();
19249 }
19250 break;
19251 case BO_And: {
19252 // '&' reduction op - initializer is '~0'.
19253 QualType OrigType = Type;
19254 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
19255 Type = ComplexTy->getElementType();
19256 if (Type->isRealFloatingType()) {
19257 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19258 Semantics: Context.getFloatTypeSemantics(T: Type));
19259 Init = FloatingLiteral::Create(C: Context, V: InitValue, /*isexact=*/true,
19260 Type, L: ELoc);
19261 } else if (Type->isScalarType()) {
19262 uint64_t Size = Context.getTypeSize(T: Type);
19263 QualType IntTy = Context.getIntTypeForBitwidth(DestWidth: Size, /*Signed=*/0);
19264 llvm::APInt InitValue = llvm::APInt::getAllOnes(numBits: Size);
19265 Init = IntegerLiteral::Create(C: Context, V: InitValue, type: IntTy, l: ELoc);
19266 }
19267 if (Init && OrigType->isAnyComplexType()) {
19268 // Init = 0xFFFF + 0xFFFFi;
19269 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
19270 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
19271 }
19272 Type = OrigType;
19273 break;
19274 }
19275 case BO_LT:
19276 case BO_GT: {
19277 // 'min' reduction op - initializer is 'Largest representable number in
19278 // the reduction list item type'.
19279 // 'max' reduction op - initializer is 'Least representable number in
19280 // the reduction list item type'.
19281 if (Type->isIntegerType() || Type->isPointerType()) {
19282 bool IsSigned = Type->hasSignedIntegerRepresentation();
19283 uint64_t Size = Context.getTypeSize(T: Type);
19284 QualType IntTy =
19285 Context.getIntTypeForBitwidth(DestWidth: Size, /*Signed=*/IsSigned);
19286 llvm::APInt InitValue =
19287 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(numBits: Size)
19288 : llvm::APInt::getMinValue(numBits: Size)
19289 : IsSigned ? llvm::APInt::getSignedMaxValue(numBits: Size)
19290 : llvm::APInt::getMaxValue(numBits: Size);
19291 Init = IntegerLiteral::Create(C: Context, V: InitValue, type: IntTy, l: ELoc);
19292 if (Type->isPointerType()) {
19293 // Cast to pointer type.
19294 ExprResult CastExpr = S.BuildCStyleCastExpr(
19295 LParenLoc: ELoc, Ty: Context.getTrivialTypeSourceInfo(T: Type, Loc: ELoc), RParenLoc: ELoc, Op: Init);
19296 if (CastExpr.isInvalid())
19297 continue;
19298 Init = CastExpr.get();
19299 }
19300 } else if (Type->isRealFloatingType()) {
19301 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19302 Sem: Context.getFloatTypeSemantics(T: Type), Negative: BOK != BO_LT);
19303 Init = FloatingLiteral::Create(C: Context, V: InitValue, /*isexact=*/true,
19304 Type, L: ELoc);
19305 }
19306 break;
19307 }
19308 case BO_PtrMemD:
19309 case BO_PtrMemI:
19310 case BO_MulAssign:
19311 case BO_Div:
19312 case BO_Rem:
19313 case BO_Sub:
19314 case BO_Shl:
19315 case BO_Shr:
19316 case BO_LE:
19317 case BO_GE:
19318 case BO_EQ:
19319 case BO_NE:
19320 case BO_Cmp:
19321 case BO_AndAssign:
19322 case BO_XorAssign:
19323 case BO_OrAssign:
19324 case BO_Assign:
19325 case BO_AddAssign:
19326 case BO_SubAssign:
19327 case BO_DivAssign:
19328 case BO_RemAssign:
19329 case BO_ShlAssign:
19330 case BO_ShrAssign:
19331 case BO_Comma:
19332 llvm_unreachable("Unexpected reduction operation");
19333 }
19334 }
19335 if (Init && DeclareReductionRef.isUnset()) {
19336 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
19337 // Store initializer for single element in private copy. Will be used
19338 // during codegen.
19339 PrivateVD->setInit(RHSVD->getInit());
19340 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19341 } else if (!Init) {
19342 S.ActOnUninitializedDecl(RHSVD);
19343 // Store initializer for single element in private copy. Will be used
19344 // during codegen.
19345 PrivateVD->setInit(RHSVD->getInit());
19346 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19347 }
19348 if (RHSVD->isInvalidDecl())
19349 continue;
19350 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
19351 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19352 << Type << ReductionIdRange;
19353 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19354 VarDecl::DeclarationOnly;
19355 S.Diag(D->getLocation(),
19356 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19357 << D;
19358 continue;
19359 }
19360 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, D: PrivateVD, Ty: PrivateTy, Loc: ELoc);
19361 ExprResult ReductionOp;
19362 if (DeclareReductionRef.isUsable()) {
19363 QualType RedTy = DeclareReductionRef.get()->getType();
19364 QualType PtrRedTy = Context.getPointerType(T: RedTy);
19365 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
19366 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
19367 if (!BasePath.empty()) {
19368 LHS = S.DefaultLvalueConversion(E: LHS.get());
19369 RHS = S.DefaultLvalueConversion(E: RHS.get());
19370 LHS = ImplicitCastExpr::Create(
19371 Context, T: PtrRedTy, Kind: CK_UncheckedDerivedToBase, Operand: LHS.get(), BasePath: &BasePath,
19372 Cat: LHS.get()->getValueKind(), FPO: FPOptionsOverride());
19373 RHS = ImplicitCastExpr::Create(
19374 Context, T: PtrRedTy, Kind: CK_UncheckedDerivedToBase, Operand: RHS.get(), BasePath: &BasePath,
19375 Cat: RHS.get()->getValueKind(), FPO: FPOptionsOverride());
19376 }
19377 FunctionProtoType::ExtProtoInfo EPI;
19378 QualType Params[] = {PtrRedTy, PtrRedTy};
19379 QualType FnTy = Context.getFunctionType(ResultTy: Context.VoidTy, Args: Params, EPI);
19380 auto *OVE = new (Context) OpaqueValueExpr(
19381 ELoc, Context.getPointerType(T: FnTy), VK_PRValue, OK_Ordinary,
19382 S.DefaultLvalueConversion(E: DeclareReductionRef.get()).get());
19383 Expr *Args[] = {LHS.get(), RHS.get()};
19384 ReductionOp =
19385 CallExpr::Create(Ctx: Context, Fn: OVE, Args, Ty: Context.VoidTy, VK: VK_PRValue, RParenLoc: ELoc,
19386 FPFeatures: S.CurFPFeatureOverrides());
19387 } else {
19388 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
19389 if (Type->isRecordType() && CombBOK != BOK) {
19390 Sema::TentativeAnalysisScope Trap(S);
19391 ReductionOp =
19392 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19393 CombBOK, LHSDRE, RHSDRE);
19394 }
19395 if (!ReductionOp.isUsable()) {
19396 ReductionOp =
19397 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
19398 LHSDRE, RHSDRE);
19399 if (ReductionOp.isUsable()) {
19400 if (BOK != BO_LT && BOK != BO_GT) {
19401 ReductionOp =
19402 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19403 BO_Assign, LHSDRE, ReductionOp.get());
19404 } else {
19405 auto *ConditionalOp = new (Context)
19406 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
19407 RHSDRE, Type, VK_LValue, OK_Ordinary);
19408 ReductionOp =
19409 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ReductionId.getBeginLoc(),
19410 Opc: BO_Assign, LHSExpr: LHSDRE, RHSExpr: ConditionalOp);
19411 }
19412 }
19413 }
19414 if (ReductionOp.isUsable())
19415 ReductionOp = S.ActOnFinishFullExpr(Expr: ReductionOp.get(),
19416 /*DiscardedValue=*/false);
19417 if (!ReductionOp.isUsable())
19418 continue;
19419 }
19420
19421 // Add copy operations for inscan reductions.
19422 // LHS = RHS;
19423 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
19424 if (ClauseKind == OMPC_reduction &&
19425 RD.RedModifier == OMPC_REDUCTION_inscan) {
19426 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
19427 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
19428 RHS.get());
19429 if (!CopyOpRes.isUsable())
19430 continue;
19431 CopyOpRes =
19432 S.ActOnFinishFullExpr(Expr: CopyOpRes.get(), /*DiscardedValue=*/true);
19433 if (!CopyOpRes.isUsable())
19434 continue;
19435 // For simd directive and simd-based directives in simd mode no need to
19436 // construct temp array, need just a single temp element.
19437 if (Stack->getCurrentDirective() == OMPD_simd ||
19438 (S.getLangOpts().OpenMPSimd &&
19439 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
19440 VarDecl *TempArrayVD =
19441 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19442 D->hasAttrs() ? &D->getAttrs() : nullptr);
19443 // Add a constructor to the temp decl.
19444 S.ActOnUninitializedDecl(TempArrayVD);
19445 TempArrayRes = buildDeclRefExpr(S, D: TempArrayVD, Ty: PrivateTy, Loc: ELoc);
19446 } else {
19447 // Build temp array for prefix sum.
19448 auto *Dim = new (S.Context)
19449 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19450 QualType ArrayTy = S.Context.getVariableArrayType(
19451 PrivateTy, Dim, ArraySizeModifier::Normal,
19452 /*IndexTypeQuals=*/0);
19453 VarDecl *TempArrayVD =
19454 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
19455 D->hasAttrs() ? &D->getAttrs() : nullptr);
19456 // Add a constructor to the temp decl.
19457 S.ActOnUninitializedDecl(TempArrayVD);
19458 TempArrayRes = buildDeclRefExpr(S, D: TempArrayVD, Ty: ArrayTy, Loc: ELoc);
19459 TempArrayElem =
19460 S.DefaultFunctionArrayLvalueConversion(E: TempArrayRes.get());
19461 auto *Idx = new (S.Context)
19462 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19463 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
19464 ELoc, Idx, ELoc);
19465 }
19466 }
19467
19468 // OpenMP [2.15.4.6, Restrictions, p.2]
19469 // A list item that appears in an in_reduction clause of a task construct
19470 // must appear in a task_reduction clause of a construct associated with a
19471 // taskgroup region that includes the participating task in its taskgroup
19472 // set. The construct associated with the innermost region that meets this
19473 // condition must specify the same reduction-identifier as the in_reduction
19474 // clause.
19475 if (ClauseKind == OMPC_in_reduction) {
19476 SourceRange ParentSR;
19477 BinaryOperatorKind ParentBOK;
19478 const Expr *ParentReductionOp = nullptr;
19479 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
19480 DSAStackTy::DSAVarData ParentBOKDSA =
19481 Stack->getTopMostTaskgroupReductionData(D, SR&: ParentSR, BOK&: ParentBOK,
19482 TaskgroupDescriptor&: ParentBOKTD);
19483 DSAStackTy::DSAVarData ParentReductionOpDSA =
19484 Stack->getTopMostTaskgroupReductionData(
19485 D, SR&: ParentSR, ReductionRef&: ParentReductionOp, TaskgroupDescriptor&: ParentReductionOpTD);
19486 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19487 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19488 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
19489 (DeclareReductionRef.isUsable() && IsParentBOK) ||
19490 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19491 bool EmitError = true;
19492 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
19493 llvm::FoldingSetNodeID RedId, ParentRedId;
19494 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
19495 DeclareReductionRef.get()->Profile(RedId, Context,
19496 /*Canonical=*/true);
19497 EmitError = RedId != ParentRedId;
19498 }
19499 if (EmitError) {
19500 S.Diag(ReductionId.getBeginLoc(),
19501 diag::err_omp_reduction_identifier_mismatch)
19502 << ReductionIdRange << RefExpr->getSourceRange();
19503 S.Diag(ParentSR.getBegin(),
19504 diag::note_omp_previous_reduction_identifier)
19505 << ParentSR
19506 << (IsParentBOK ? ParentBOKDSA.RefExpr
19507 : ParentReductionOpDSA.RefExpr)
19508 ->getSourceRange();
19509 continue;
19510 }
19511 }
19512 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19513 }
19514
19515 DeclRefExpr *Ref = nullptr;
19516 Expr *VarsExpr = RefExpr->IgnoreParens();
19517 if (!VD && !S.CurContext->isDependentContext()) {
19518 if (ASE || OASE) {
19519 TransformExprToCaptures RebuildToCapture(S, D);
19520 VarsExpr =
19521 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19522 Ref = RebuildToCapture.getCapturedExpr();
19523 } else {
19524 VarsExpr = Ref = buildCapture(S, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
19525 }
19526 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
19527 RD.ExprCaptures.emplace_back(Args: Ref->getDecl());
19528 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19529 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
19530 if (!RefRes.isUsable())
19531 continue;
19532 ExprResult PostUpdateRes =
19533 S.BuildBinOp(S: Stack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign, LHSExpr: SimpleRefExpr,
19534 RHSExpr: RefRes.get());
19535 if (!PostUpdateRes.isUsable())
19536 continue;
19537 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
19538 Stack->getCurrentDirective() == OMPD_taskgroup) {
19539 S.Diag(RefExpr->getExprLoc(),
19540 diag::err_omp_reduction_non_addressable_expression)
19541 << RefExpr->getSourceRange();
19542 continue;
19543 }
19544 RD.ExprPostUpdates.emplace_back(
19545 Args: S.IgnoredValueConversions(E: PostUpdateRes.get()).get());
19546 }
19547 }
19548 }
19549 // All reduction items are still marked as reduction (to do not increase
19550 // code base size).
19551 unsigned Modifier = RD.RedModifier;
19552 // Consider task_reductions as reductions with task modifier. Required for
19553 // correct analysis of in_reduction clauses.
19554 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19555 Modifier = OMPC_REDUCTION_task;
19556 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19557 ASE || OASE);
19558 if (Modifier == OMPC_REDUCTION_task &&
19559 (CurrDir == OMPD_taskgroup ||
19560 ((isOpenMPParallelDirective(CurrDir) ||
19561 isOpenMPWorksharingDirective(CurrDir)) &&
19562 !isOpenMPSimdDirective(CurrDir)))) {
19563 if (DeclareReductionRef.isUsable())
19564 Stack->addTaskgroupReductionData(D, SR: ReductionIdRange,
19565 ReductionRef: DeclareReductionRef.get());
19566 else
19567 Stack->addTaskgroupReductionData(D, SR: ReductionIdRange, BOK);
19568 }
19569 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
19570 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
19571 TempArrayElem.get(), IsPrivate);
19572 }
19573 return RD.Vars.empty();
19574}
19575
19576OMPClause *SemaOpenMP::ActOnOpenMPReductionClause(
19577 ArrayRef<Expr *> VarList,
19578 OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers,
19579 SourceLocation StartLoc, SourceLocation LParenLoc,
19580 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
19581 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19582 ArrayRef<Expr *> UnresolvedReductions) {
19583 OpenMPReductionClauseModifier Modifier =
19584 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
19585 OpenMPOriginalSharingModifier OriginalSharingModifier =
19586 static_cast<OpenMPOriginalSharingModifier>(
19587 Modifiers.OriginalSharingModifier);
19588 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
19589 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19590 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
19591 /*Last=*/OMPC_REDUCTION_unknown)
19592 << getOpenMPClauseNameForDiag(OMPC_reduction);
19593 return nullptr;
19594 }
19595 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
19596 // A reduction clause with the inscan reduction-modifier may only appear on a
19597 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
19598 // construct, a parallel worksharing-loop construct or a parallel
19599 // worksharing-loop SIMD construct.
19600 if (Modifier == OMPC_REDUCTION_inscan &&
19601 (DSAStack->getCurrentDirective() != OMPD_for &&
19602 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19603 DSAStack->getCurrentDirective() != OMPD_simd &&
19604 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19605 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19606 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19607 return nullptr;
19608 }
19609 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
19610 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
19611 StartLoc, LParenLoc, ColonLoc, EndLoc,
19612 ReductionIdScopeSpec, ReductionId,
19613 UnresolvedReductions, RD))
19614 return nullptr;
19615
19616 return OMPReductionClause::Create(
19617 C: getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
19618 Modifier, VL: RD.Vars,
19619 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
19620 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps, CopyOps: RD.InscanCopyOps,
19621 CopyArrayTemps: RD.InscanCopyArrayTemps, CopyArrayElems: RD.InscanCopyArrayElems,
19622 PreInit: buildPreInits(getASTContext(), RD.ExprCaptures),
19623 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates), IsPrivateVarReduction: RD.IsPrivateVarReduction,
19624 OriginalSharingModifier);
19625}
19626
19627OMPClause *SemaOpenMP::ActOnOpenMPTaskReductionClause(
19628 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19629 SourceLocation ColonLoc, SourceLocation EndLoc,
19630 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19631 ArrayRef<Expr *> UnresolvedReductions) {
19632 ReductionData RD(VarList.size());
19633 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
19634 VarList, StartLoc, LParenLoc, ColonLoc,
19635 EndLoc, ReductionIdScopeSpec, ReductionId,
19636 UnresolvedReductions, RD))
19637 return nullptr;
19638
19639 return OMPTaskReductionClause::Create(
19640 C: getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, VL: RD.Vars,
19641 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
19642 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps,
19643 PreInit: buildPreInits(getASTContext(), RD.ExprCaptures),
19644 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates));
19645}
19646
19647OMPClause *SemaOpenMP::ActOnOpenMPInReductionClause(
19648 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19649 SourceLocation ColonLoc, SourceLocation EndLoc,
19650 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19651 ArrayRef<Expr *> UnresolvedReductions) {
19652 ReductionData RD(VarList.size());
19653 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
19654 StartLoc, LParenLoc, ColonLoc, EndLoc,
19655 ReductionIdScopeSpec, ReductionId,
19656 UnresolvedReductions, RD))
19657 return nullptr;
19658
19659 return OMPInReductionClause::Create(
19660 C: getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, VL: RD.Vars,
19661 QualifierLoc: ReductionIdScopeSpec.getWithLocInContext(Context&: getASTContext()), NameInfo: ReductionId,
19662 Privates: RD.Privates, LHSExprs: RD.LHSs, RHSExprs: RD.RHSs, ReductionOps: RD.ReductionOps, TaskgroupDescriptors: RD.TaskgroupDescriptors,
19663 PreInit: buildPreInits(getASTContext(), RD.ExprCaptures),
19664 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: RD.ExprPostUpdates));
19665}
19666
19667bool SemaOpenMP::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
19668 SourceLocation LinLoc) {
19669 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19670 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
19671 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19672 << getLangOpts().CPlusPlus;
19673 return true;
19674 }
19675 return false;
19676}
19677
19678bool SemaOpenMP::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
19679 OpenMPLinearClauseKind LinKind,
19680 QualType Type, bool IsDeclareSimd) {
19681 const auto *VD = dyn_cast_or_null<VarDecl>(Val: D);
19682 // A variable must not have an incomplete type or a reference type.
19683 if (SemaRef.RequireCompleteType(ELoc, Type,
19684 diag::err_omp_linear_incomplete_type))
19685 return true;
19686 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19687 !Type->isReferenceType()) {
19688 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19689 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
19690 return true;
19691 }
19692 Type = Type.getNonReferenceType();
19693
19694 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19695 // A variable that is privatized must not have a const-qualified type
19696 // unless it is of class type with a mutable member. This restriction does
19697 // not apply to the firstprivate clause, nor to the linear clause on
19698 // declarative directives (like declare simd).
19699 if (!IsDeclareSimd &&
19700 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
19701 return true;
19702
19703 // A list item must be of integral or pointer type.
19704 Type = Type.getUnqualifiedType().getCanonicalType();
19705 const auto *Ty = Type.getTypePtrOrNull();
19706 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19707 !Ty->isIntegralType(Ctx: getASTContext()) && !Ty->isPointerType())) {
19708 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
19709 if (D) {
19710 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19711 VarDecl::DeclarationOnly;
19712 Diag(D->getLocation(),
19713 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19714 << D;
19715 }
19716 return true;
19717 }
19718 return false;
19719}
19720
19721OMPClause *SemaOpenMP::ActOnOpenMPLinearClause(
19722 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
19723 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
19724 SourceLocation LinLoc, SourceLocation ColonLoc,
19725 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
19726 SmallVector<Expr *, 8> Vars;
19727 SmallVector<Expr *, 8> Privates;
19728 SmallVector<Expr *, 8> Inits;
19729 SmallVector<Decl *, 4> ExprCaptures;
19730 SmallVector<Expr *, 4> ExprPostUpdates;
19731 // OpenMP 5.2 [Section 5.4.6, linear clause]
19732 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
19733 // 'ref'
19734 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
19735 getLangOpts().OpenMP >= 52)
19736 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
19737 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
19738 LinKind = OMPC_LINEAR_val;
19739 for (Expr *RefExpr : VarList) {
19740 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19741 SourceLocation ELoc;
19742 SourceRange ERange;
19743 Expr *SimpleRefExpr = RefExpr;
19744 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
19745 if (Res.second) {
19746 // It will be analyzed later.
19747 Vars.push_back(Elt: RefExpr);
19748 Privates.push_back(Elt: nullptr);
19749 Inits.push_back(Elt: nullptr);
19750 }
19751 ValueDecl *D = Res.first;
19752 if (!D)
19753 continue;
19754
19755 QualType Type = D->getType();
19756 auto *VD = dyn_cast<VarDecl>(Val: D);
19757
19758 // OpenMP [2.14.3.7, linear clause]
19759 // A list-item cannot appear in more than one linear clause.
19760 // A list-item that appears in a linear clause cannot appear in any
19761 // other data-sharing attribute clause.
19762 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19763 if (DVar.RefExpr) {
19764 Diag(ELoc, diag::err_omp_wrong_dsa)
19765 << getOpenMPClauseNameForDiag(DVar.CKind)
19766 << getOpenMPClauseNameForDiag(OMPC_linear);
19767 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19768 continue;
19769 }
19770
19771 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19772 continue;
19773 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19774
19775 // Build private copy of original var.
19776 VarDecl *Private =
19777 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19778 D->hasAttrs() ? &D->getAttrs() : nullptr,
19779 VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
19780 DeclRefExpr *PrivateRef = buildDeclRefExpr(S&: SemaRef, D: Private, Ty: Type, Loc: ELoc);
19781 // Build var to save initial value.
19782 VarDecl *Init = buildVarDecl(SemaRef, Loc: ELoc, Type, Name: ".linear.start");
19783 Expr *InitExpr;
19784 DeclRefExpr *Ref = nullptr;
19785 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19786 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
19787 if (!isOpenMPCapturedDecl(D)) {
19788 ExprCaptures.push_back(Ref->getDecl());
19789 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19790 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
19791 if (!RefRes.isUsable())
19792 continue;
19793 ExprResult PostUpdateRes =
19794 SemaRef.BuildBinOp(DSAStack->getCurScope(), OpLoc: ELoc, Opc: BO_Assign,
19795 LHSExpr: SimpleRefExpr, RHSExpr: RefRes.get());
19796 if (!PostUpdateRes.isUsable())
19797 continue;
19798 ExprPostUpdates.push_back(
19799 Elt: SemaRef.IgnoredValueConversions(E: PostUpdateRes.get()).get());
19800 }
19801 }
19802 }
19803 if (LinKind == OMPC_LINEAR_uval)
19804 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19805 else
19806 InitExpr = VD ? SimpleRefExpr : Ref;
19807 SemaRef.AddInitializerToDecl(
19808 Init, SemaRef.DefaultLvalueConversion(E: InitExpr).get(),
19809 /*DirectInit=*/false);
19810 DeclRefExpr *InitRef = buildDeclRefExpr(S&: SemaRef, D: Init, Ty: Type, Loc: ELoc);
19811
19812 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19813 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
19814 ? RefExpr->IgnoreParens()
19815 : Ref);
19816 Privates.push_back(PrivateRef);
19817 Inits.push_back(InitRef);
19818 }
19819
19820 if (Vars.empty())
19821 return nullptr;
19822
19823 Expr *StepExpr = Step;
19824 Expr *CalcStepExpr = nullptr;
19825 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
19826 !Step->isInstantiationDependent() &&
19827 !Step->containsUnexpandedParameterPack()) {
19828 SourceLocation StepLoc = Step->getBeginLoc();
19829 ExprResult Val = PerformOpenMPImplicitIntegerConversion(Loc: StepLoc, Op: Step);
19830 if (Val.isInvalid())
19831 return nullptr;
19832 StepExpr = Val.get();
19833
19834 // Build var to save the step value.
19835 VarDecl *SaveVar =
19836 buildVarDecl(SemaRef, Loc: StepLoc, Type: StepExpr->getType(), Name: ".linear.step");
19837 ExprResult SaveRef =
19838 buildDeclRefExpr(S&: SemaRef, D: SaveVar, Ty: StepExpr->getType(), Loc: StepLoc);
19839 ExprResult CalcStep = SemaRef.BuildBinOp(
19840 S: SemaRef.getCurScope(), OpLoc: StepLoc, Opc: BO_Assign, LHSExpr: SaveRef.get(), RHSExpr: StepExpr);
19841 CalcStep =
19842 SemaRef.ActOnFinishFullExpr(Expr: CalcStep.get(), /*DiscardedValue=*/false);
19843
19844 // Warn about zero linear step (it would be probably better specified as
19845 // making corresponding variables 'const').
19846 if (std::optional<llvm::APSInt> Result =
19847 StepExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
19848 if (!Result->isNegative() && !Result->isStrictlyPositive())
19849 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19850 << Vars[0] << (Vars.size() > 1);
19851 } else if (CalcStep.isUsable()) {
19852 // Calculate the step beforehand instead of doing this on each iteration.
19853 // (This is not used if the number of iterations may be kfold-ed).
19854 CalcStepExpr = CalcStep.get();
19855 }
19856 }
19857
19858 return OMPLinearClause::Create(C: getASTContext(), StartLoc, LParenLoc, Modifier: LinKind,
19859 ModifierLoc: LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19860 VL: Vars, PL: Privates, IL: Inits, Step: StepExpr, CalcStep: CalcStepExpr,
19861 PreInit: buildPreInits(getASTContext(), ExprCaptures),
19862 PostUpdate: buildPostUpdate(S&: SemaRef, PostUpdates: ExprPostUpdates));
19863}
19864
19865static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
19866 Expr *NumIterations, Sema &SemaRef,
19867 Scope *S, DSAStackTy *Stack) {
19868 // Walk the vars and build update/final expressions for the CodeGen.
19869 SmallVector<Expr *, 8> Updates;
19870 SmallVector<Expr *, 8> Finals;
19871 SmallVector<Expr *, 8> UsedExprs;
19872 Expr *Step = Clause.getStep();
19873 Expr *CalcStep = Clause.getCalcStep();
19874 // OpenMP [2.14.3.7, linear clause]
19875 // If linear-step is not specified it is assumed to be 1.
19876 if (!Step)
19877 Step = SemaRef.ActOnIntegerConstant(Loc: SourceLocation(), Val: 1).get();
19878 else if (CalcStep)
19879 Step = cast<BinaryOperator>(Val: CalcStep)->getLHS();
19880 bool HasErrors = false;
19881 auto CurInit = Clause.inits().begin();
19882 auto CurPrivate = Clause.privates().begin();
19883 OpenMPLinearClauseKind LinKind = Clause.getModifier();
19884 for (Expr *RefExpr : Clause.varlist()) {
19885 SourceLocation ELoc;
19886 SourceRange ERange;
19887 Expr *SimpleRefExpr = RefExpr;
19888 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19889 ValueDecl *D = Res.first;
19890 if (Res.second || !D) {
19891 Updates.push_back(nullptr);
19892 Finals.push_back(nullptr);
19893 HasErrors = true;
19894 continue;
19895 }
19896 auto &&Info = Stack->isLoopControlVariable(D);
19897 // OpenMP [2.15.11, distribute simd Construct]
19898 // A list item may not appear in a linear clause, unless it is the loop
19899 // iteration variable.
19900 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
19901 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
19902 SemaRef.Diag(ELoc,
19903 diag::err_omp_linear_distribute_var_non_loop_iteration);
19904 Updates.push_back(nullptr);
19905 Finals.push_back(nullptr);
19906 HasErrors = true;
19907 continue;
19908 }
19909 Expr *InitExpr = *CurInit;
19910
19911 // Build privatized reference to the current linear var.
19912 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19913 Expr *CapturedRef;
19914 if (LinKind == OMPC_LINEAR_uval)
19915 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19916 else
19917 CapturedRef =
19918 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
19919 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19920 /*RefersToCapture=*/true);
19921
19922 // Build update: Var = InitExpr + IV * Step
19923 ExprResult Update;
19924 if (!Info.first)
19925 Update = buildCounterUpdate(
19926 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19927 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
19928 else
19929 Update = *CurPrivate;
19930 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
19931 /*DiscardedValue=*/false);
19932
19933 // Build final: Var = PrivCopy;
19934 ExprResult Final;
19935 if (!Info.first)
19936 Final = SemaRef.BuildBinOp(
19937 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19938 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
19939 else
19940 Final = *CurPrivate;
19941 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
19942 /*DiscardedValue=*/false);
19943
19944 if (!Update.isUsable() || !Final.isUsable()) {
19945 Updates.push_back(nullptr);
19946 Finals.push_back(nullptr);
19947 UsedExprs.push_back(nullptr);
19948 HasErrors = true;
19949 } else {
19950 Updates.push_back(Update.get());
19951 Finals.push_back(Final.get());
19952 if (!Info.first)
19953 UsedExprs.push_back(SimpleRefExpr);
19954 }
19955 ++CurInit;
19956 ++CurPrivate;
19957 }
19958 if (Expr *S = Clause.getStep())
19959 UsedExprs.push_back(Elt: S);
19960 // Fill the remaining part with the nullptr.
19961 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
19962 Clause.setUpdates(Updates);
19963 Clause.setFinals(Finals);
19964 Clause.setUsedExprs(UsedExprs);
19965 return HasErrors;
19966}
19967
19968OMPClause *SemaOpenMP::ActOnOpenMPAlignedClause(
19969 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
19970 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19971 SmallVector<Expr *, 8> Vars;
19972 for (Expr *RefExpr : VarList) {
19973 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19974 SourceLocation ELoc;
19975 SourceRange ERange;
19976 Expr *SimpleRefExpr = RefExpr;
19977 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
19978 if (Res.second) {
19979 // It will be analyzed later.
19980 Vars.push_back(Elt: RefExpr);
19981 }
19982 ValueDecl *D = Res.first;
19983 if (!D)
19984 continue;
19985
19986 QualType QType = D->getType();
19987 auto *VD = dyn_cast<VarDecl>(Val: D);
19988
19989 // OpenMP [2.8.1, simd construct, Restrictions]
19990 // The type of list items appearing in the aligned clause must be
19991 // array, pointer, reference to array, or reference to pointer.
19992 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19993 const Type *Ty = QType.getTypePtrOrNull();
19994 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
19995 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19996 << QType << getLangOpts().CPlusPlus << ERange;
19997 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19998 VarDecl::DeclarationOnly;
19999 Diag(D->getLocation(),
20000 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20001 << D;
20002 continue;
20003 }
20004
20005 // OpenMP [2.8.1, simd construct, Restrictions]
20006 // A list-item cannot appear in more than one aligned clause.
20007 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, NewDE: SimpleRefExpr)) {
20008 Diag(ELoc, diag::err_omp_used_in_clause_twice)
20009 << 0 << getOpenMPClauseNameForDiag(OMPC_aligned) << ERange;
20010 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20011 << getOpenMPClauseNameForDiag(OMPC_aligned);
20012 continue;
20013 }
20014
20015 DeclRefExpr *Ref = nullptr;
20016 if (!VD && isOpenMPCapturedDecl(D))
20017 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
20018 Vars.push_back(Elt: SemaRef
20019 .DefaultFunctionArrayConversion(
20020 E: (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20021 .get());
20022 }
20023
20024 // OpenMP [2.8.1, simd construct, Description]
20025 // The parameter of the aligned clause, alignment, must be a constant
20026 // positive integer expression.
20027 // If no optional parameter is specified, implementation-defined default
20028 // alignments for SIMD instructions on the target platforms are assumed.
20029 if (Alignment != nullptr) {
20030 ExprResult AlignResult =
20031 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
20032 if (AlignResult.isInvalid())
20033 return nullptr;
20034 Alignment = AlignResult.get();
20035 }
20036 if (Vars.empty())
20037 return nullptr;
20038
20039 return OMPAlignedClause::Create(C: getASTContext(), StartLoc, LParenLoc,
20040 ColonLoc, EndLoc, VL: Vars, A: Alignment);
20041}
20042
20043OMPClause *SemaOpenMP::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
20044 SourceLocation StartLoc,
20045 SourceLocation LParenLoc,
20046 SourceLocation EndLoc) {
20047 SmallVector<Expr *, 8> Vars;
20048 SmallVector<Expr *, 8> SrcExprs;
20049 SmallVector<Expr *, 8> DstExprs;
20050 SmallVector<Expr *, 8> AssignmentOps;
20051 for (Expr *RefExpr : VarList) {
20052 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
20053 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
20054 // It will be analyzed later.
20055 Vars.push_back(Elt: RefExpr);
20056 SrcExprs.push_back(Elt: nullptr);
20057 DstExprs.push_back(Elt: nullptr);
20058 AssignmentOps.push_back(Elt: nullptr);
20059 continue;
20060 }
20061
20062 SourceLocation ELoc = RefExpr->getExprLoc();
20063 // OpenMP [2.1, C/C++]
20064 // A list item is a variable name.
20065 // OpenMP [2.14.4.1, Restrictions, p.1]
20066 // A list item that appears in a copyin clause must be threadprivate.
20067 auto *DE = dyn_cast<DeclRefExpr>(Val: RefExpr);
20068 if (!DE || !isa<VarDecl>(Val: DE->getDecl())) {
20069 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20070 << 0 << RefExpr->getSourceRange();
20071 continue;
20072 }
20073
20074 Decl *D = DE->getDecl();
20075 auto *VD = cast<VarDecl>(Val: D);
20076
20077 QualType Type = VD->getType();
20078 if (Type->isDependentType() || Type->isInstantiationDependentType()) {
20079 // It will be analyzed later.
20080 Vars.push_back(DE);
20081 SrcExprs.push_back(Elt: nullptr);
20082 DstExprs.push_back(Elt: nullptr);
20083 AssignmentOps.push_back(Elt: nullptr);
20084 continue;
20085 }
20086
20087 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20088 // A list item that appears in a copyin clause must be threadprivate.
20089 if (!DSAStack->isThreadPrivate(D: VD)) {
20090 unsigned OMPVersion = getLangOpts().OpenMP;
20091 Diag(ELoc, diag::err_omp_required_access)
20092 << getOpenMPClauseNameForDiag(OMPC_copyin)
20093 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
20094 continue;
20095 }
20096
20097 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20098 // A variable of class type (or array thereof) that appears in a
20099 // copyin clause requires an accessible, unambiguous copy assignment
20100 // operator for the class type.
20101 QualType ElemType =
20102 getASTContext().getBaseElementType(Type).getNonReferenceType();
20103 VarDecl *SrcVD =
20104 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20105 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20106 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20107 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20108 VarDecl *DstVD =
20109 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
20110 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20111 DeclRefExpr *PseudoDstExpr =
20112 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
20113 // For arrays generate assignment operation for single element and replace
20114 // it by the original array element in CodeGen.
20115 ExprResult AssignmentOp =
20116 SemaRef.BuildBinOp(/*S=*/nullptr, OpLoc: DE->getExprLoc(), Opc: BO_Assign,
20117 LHSExpr: PseudoDstExpr, RHSExpr: PseudoSrcExpr);
20118 if (AssignmentOp.isInvalid())
20119 continue;
20120 AssignmentOp =
20121 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20122 /*DiscardedValue=*/false);
20123 if (AssignmentOp.isInvalid())
20124 continue;
20125
20126 DSAStack->addDSA(VD, DE, OMPC_copyin);
20127 Vars.push_back(DE);
20128 SrcExprs.push_back(PseudoSrcExpr);
20129 DstExprs.push_back(PseudoDstExpr);
20130 AssignmentOps.push_back(Elt: AssignmentOp.get());
20131 }
20132
20133 if (Vars.empty())
20134 return nullptr;
20135
20136 return OMPCopyinClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
20137 VL: Vars, SrcExprs, DstExprs, AssignmentOps);
20138}
20139
20140OMPClause *SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
20141 SourceLocation StartLoc,
20142 SourceLocation LParenLoc,
20143 SourceLocation EndLoc) {
20144 SmallVector<Expr *, 8> Vars;
20145 SmallVector<Expr *, 8> SrcExprs;
20146 SmallVector<Expr *, 8> DstExprs;
20147 SmallVector<Expr *, 8> AssignmentOps;
20148 for (Expr *RefExpr : VarList) {
20149 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20150 SourceLocation ELoc;
20151 SourceRange ERange;
20152 Expr *SimpleRefExpr = RefExpr;
20153 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
20154 if (Res.second) {
20155 // It will be analyzed later.
20156 Vars.push_back(Elt: RefExpr);
20157 SrcExprs.push_back(Elt: nullptr);
20158 DstExprs.push_back(Elt: nullptr);
20159 AssignmentOps.push_back(Elt: nullptr);
20160 }
20161 ValueDecl *D = Res.first;
20162 if (!D)
20163 continue;
20164
20165 QualType Type = D->getType();
20166 auto *VD = dyn_cast<VarDecl>(Val: D);
20167
20168 // OpenMP [2.14.4.2, Restrictions, p.2]
20169 // A list item that appears in a copyprivate clause may not appear in a
20170 // private or firstprivate clause on the single construct.
20171 if (!VD || !DSAStack->isThreadPrivate(D: VD)) {
20172 DSAStackTy::DSAVarData DVar =
20173 DSAStack->getTopDSA(D, /*FromParent=*/false);
20174 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20175 DVar.RefExpr) {
20176 Diag(ELoc, diag::err_omp_wrong_dsa)
20177 << getOpenMPClauseNameForDiag(DVar.CKind)
20178 << getOpenMPClauseNameForDiag(OMPC_copyprivate);
20179 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20180 continue;
20181 }
20182
20183 // OpenMP [2.11.4.2, Restrictions, p.1]
20184 // All list items that appear in a copyprivate clause must be either
20185 // threadprivate or private in the enclosing context.
20186 if (DVar.CKind == OMPC_unknown) {
20187 DVar = DSAStack->getImplicitDSA(D, FromParent: false);
20188 if (DVar.CKind == OMPC_shared) {
20189 Diag(ELoc, diag::err_omp_required_access)
20190 << getOpenMPClauseNameForDiag(OMPC_copyprivate)
20191 << "threadprivate or private in the enclosing context";
20192 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20193 continue;
20194 }
20195 }
20196 }
20197
20198 // Variably modified types are not supported.
20199 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
20200 unsigned OMPVersion = getLangOpts().OpenMP;
20201 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20202 << getOpenMPClauseNameForDiag(OMPC_copyprivate) << Type
20203 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
20204 OMPVersion);
20205 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20206 VarDecl::DeclarationOnly;
20207 Diag(D->getLocation(),
20208 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20209 << D;
20210 continue;
20211 }
20212
20213 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20214 // A variable of class type (or array thereof) that appears in a
20215 // copyin clause requires an accessible, unambiguous copy assignment
20216 // operator for the class type.
20217 Type = getASTContext()
20218 .getBaseElementType(Type.getNonReferenceType())
20219 .getUnqualifiedType();
20220 VarDecl *SrcVD =
20221 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
20222 D->hasAttrs() ? &D->getAttrs() : nullptr);
20223 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(S&: SemaRef, D: SrcVD, Ty: Type, Loc: ELoc);
20224 VarDecl *DstVD =
20225 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
20226 D->hasAttrs() ? &D->getAttrs() : nullptr);
20227 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(S&: SemaRef, D: DstVD, Ty: Type, Loc: ELoc);
20228 ExprResult AssignmentOp = SemaRef.BuildBinOp(
20229 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20230 if (AssignmentOp.isInvalid())
20231 continue;
20232 AssignmentOp = SemaRef.ActOnFinishFullExpr(Expr: AssignmentOp.get(), CC: ELoc,
20233 /*DiscardedValue=*/false);
20234 if (AssignmentOp.isInvalid())
20235 continue;
20236
20237 // No need to mark vars as copyprivate, they are already threadprivate or
20238 // implicitly private.
20239 assert(VD || isOpenMPCapturedDecl(D));
20240 Vars.push_back(
20241 Elt: VD ? RefExpr->IgnoreParens()
20242 : buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false));
20243 SrcExprs.push_back(PseudoSrcExpr);
20244 DstExprs.push_back(PseudoDstExpr);
20245 AssignmentOps.push_back(Elt: AssignmentOp.get());
20246 }
20247
20248 if (Vars.empty())
20249 return nullptr;
20250
20251 return OMPCopyprivateClause::Create(C: getASTContext(), StartLoc, LParenLoc,
20252 EndLoc, VL: Vars, SrcExprs, DstExprs,
20253 AssignmentOps);
20254}
20255
20256OMPClause *SemaOpenMP::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
20257 SourceLocation StartLoc,
20258 SourceLocation LParenLoc,
20259 SourceLocation EndLoc) {
20260 if (VarList.empty())
20261 return nullptr;
20262
20263 return OMPFlushClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
20264 VL: VarList);
20265}
20266
20267/// Tries to find omp_depend_t. type.
20268static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
20269 bool Diagnose = true) {
20270 QualType OMPDependT = Stack->getOMPDependT();
20271 if (!OMPDependT.isNull())
20272 return true;
20273 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_depend_t");
20274 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
20275 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
20276 if (Diagnose)
20277 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
20278 return false;
20279 }
20280 Stack->setOMPDependT(PT.get());
20281 return true;
20282}
20283
20284OMPClause *SemaOpenMP::ActOnOpenMPDepobjClause(Expr *Depobj,
20285 SourceLocation StartLoc,
20286 SourceLocation LParenLoc,
20287 SourceLocation EndLoc) {
20288 if (!Depobj)
20289 return nullptr;
20290
20291 bool OMPDependTFound = findOMPDependT(S&: SemaRef, Loc: StartLoc, DSAStack);
20292
20293 // OpenMP 5.0, 2.17.10.1 depobj Construct
20294 // depobj is an lvalue expression of type omp_depend_t.
20295 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
20296 !Depobj->isInstantiationDependent() &&
20297 !Depobj->containsUnexpandedParameterPack() &&
20298 (OMPDependTFound && !getASTContext().typesAreCompatible(
20299 DSAStack->getOMPDependT(), Depobj->getType(),
20300 /*CompareUnqualified=*/true))) {
20301 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20302 << 0 << Depobj->getType() << Depobj->getSourceRange();
20303 }
20304
20305 if (!Depobj->isLValue()) {
20306 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20307 << 1 << Depobj->getSourceRange();
20308 }
20309
20310 return OMPDepobjClause::Create(C: getASTContext(), StartLoc, LParenLoc, EndLoc,
20311 Depobj);
20312}
20313
20314namespace {
20315// Utility struct that gathers the related info for doacross clause.
20316struct DoacrossDataInfoTy {
20317 // The list of expressions.
20318 SmallVector<Expr *, 8> Vars;
20319 // The OperatorOffset for doacross loop.
20320 DSAStackTy::OperatorOffsetTy OpsOffs;
20321 // The depended loop count.
20322 llvm::APSInt TotalDepCount;
20323};
20324} // namespace
20325static DoacrossDataInfoTy
20326ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource,
20327 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
20328 SourceLocation EndLoc) {
20329
20330 SmallVector<Expr *, 8> Vars;
20331 DSAStackTy::OperatorOffsetTy OpsOffs;
20332 llvm::APSInt DepCounter(/*BitWidth=*/32);
20333 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20334
20335 if (const Expr *OrderedCountExpr =
20336 Stack->getParentOrderedRegionParam().first) {
20337 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Ctx: SemaRef.Context);
20338 TotalDepCount.setIsUnsigned(/*Val=*/true);
20339 }
20340
20341 for (Expr *RefExpr : VarList) {
20342 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
20343 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
20344 // It will be analyzed later.
20345 Vars.push_back(Elt: RefExpr);
20346 continue;
20347 }
20348
20349 SourceLocation ELoc = RefExpr->getExprLoc();
20350 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20351 if (!IsSource) {
20352 if (Stack->getParentOrderedRegionParam().first &&
20353 DepCounter >= TotalDepCount) {
20354 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20355 continue;
20356 }
20357 ++DepCounter;
20358 // OpenMP [2.13.9, Summary]
20359 // depend(dependence-type : vec), where dependence-type is:
20360 // 'sink' and where vec is the iteration vector, which has the form:
20361 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20362 // where n is the value specified by the ordered clause in the loop
20363 // directive, xi denotes the loop iteration variable of the i-th nested
20364 // loop associated with the loop directive, and di is a constant
20365 // non-negative integer.
20366 if (SemaRef.CurContext->isDependentContext()) {
20367 // It will be analyzed later.
20368 Vars.push_back(Elt: RefExpr);
20369 continue;
20370 }
20371 SimpleExpr = SimpleExpr->IgnoreImplicit();
20372 OverloadedOperatorKind OOK = OO_None;
20373 SourceLocation OOLoc;
20374 Expr *LHS = SimpleExpr;
20375 Expr *RHS = nullptr;
20376 if (auto *BO = dyn_cast<BinaryOperator>(Val: SimpleExpr)) {
20377 OOK = BinaryOperator::getOverloadedOperator(Opc: BO->getOpcode());
20378 OOLoc = BO->getOperatorLoc();
20379 LHS = BO->getLHS()->IgnoreParenImpCasts();
20380 RHS = BO->getRHS()->IgnoreParenImpCasts();
20381 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Val: SimpleExpr)) {
20382 OOK = OCE->getOperator();
20383 OOLoc = OCE->getOperatorLoc();
20384 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20385 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20386 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Val: SimpleExpr)) {
20387 OOK = MCE->getMethodDecl()
20388 ->getNameInfo()
20389 .getName()
20390 .getCXXOverloadedOperator();
20391 OOLoc = MCE->getCallee()->getExprLoc();
20392 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
20393 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20394 }
20395 SourceLocation ELoc;
20396 SourceRange ERange;
20397 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: LHS, ELoc, ERange);
20398 if (Res.second) {
20399 // It will be analyzed later.
20400 Vars.push_back(Elt: RefExpr);
20401 }
20402 ValueDecl *D = Res.first;
20403 if (!D)
20404 continue;
20405
20406 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
20407 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20408 continue;
20409 }
20410 if (RHS) {
20411 ExprResult RHSRes =
20412 SemaRef.OpenMP().VerifyPositiveIntegerConstantInClause(
20413 RHS, OMPC_depend, /*StrictlyPositive=*/false);
20414 if (RHSRes.isInvalid())
20415 continue;
20416 }
20417 if (!SemaRef.CurContext->isDependentContext() &&
20418 Stack->getParentOrderedRegionParam().first &&
20419 DepCounter != Stack->isParentLoopControlVariable(D).first) {
20420 const ValueDecl *VD =
20421 Stack->getParentLoopControlVariable(I: DepCounter.getZExtValue());
20422 if (VD)
20423 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20424 << 1 << VD;
20425 else
20426 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20427 << 0;
20428 continue;
20429 }
20430 OpsOffs.emplace_back(Args&: RHS, Args&: OOK);
20431 }
20432 Vars.push_back(Elt: RefExpr->IgnoreParenImpCasts());
20433 }
20434 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
20435 TotalDepCount > VarList.size() &&
20436 Stack->getParentOrderedRegionParam().first &&
20437 Stack->getParentLoopControlVariable(I: VarList.size() + 1)) {
20438 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
20439 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
20440 }
20441 return {.Vars: Vars, .OpsOffs: OpsOffs, .TotalDepCount: TotalDepCount};
20442}
20443
20444OMPClause *SemaOpenMP::ActOnOpenMPDependClause(
20445 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
20446 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20447 SourceLocation EndLoc) {
20448 OpenMPDependClauseKind DepKind = Data.DepKind;
20449 SourceLocation DepLoc = Data.DepLoc;
20450 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
20451 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
20452 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20453 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_depend);
20454 return nullptr;
20455 }
20456 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
20457 DepKind == OMPC_DEPEND_mutexinoutset) {
20458 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20459 return nullptr;
20460 }
20461 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
20462 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20463 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
20464 DepKind == OMPC_DEPEND_sink ||
20465 ((getLangOpts().OpenMP < 50 ||
20466 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20467 DepKind == OMPC_DEPEND_depobj))) {
20468 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
20469 OMPC_DEPEND_outallmemory,
20470 OMPC_DEPEND_inoutallmemory};
20471 if (getLangOpts().OpenMP < 50 ||
20472 DSAStack->getCurrentDirective() == OMPD_depobj)
20473 Except.push_back(Elt: OMPC_DEPEND_depobj);
20474 if (getLangOpts().OpenMP < 51)
20475 Except.push_back(Elt: OMPC_DEPEND_inoutset);
20476 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
20477 ? "depend modifier(iterator) or "
20478 : "";
20479 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20480 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
20481 /*Last=*/OMPC_DEPEND_unknown,
20482 Except)
20483 << getOpenMPClauseNameForDiag(OMPC_depend);
20484 return nullptr;
20485 }
20486 if (DepModifier &&
20487 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20488 Diag(DepModifier->getExprLoc(),
20489 diag::err_omp_depend_sink_source_with_modifier);
20490 return nullptr;
20491 }
20492 if (DepModifier &&
20493 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
20494 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20495
20496 SmallVector<Expr *, 8> Vars;
20497 DSAStackTy::OperatorOffsetTy OpsOffs;
20498 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20499
20500 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20501 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
20502 SemaRef, IsSource: DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
20503 Vars = VarOffset.Vars;
20504 OpsOffs = VarOffset.OpsOffs;
20505 TotalDepCount = VarOffset.TotalDepCount;
20506 } else {
20507 for (Expr *RefExpr : VarList) {
20508 assert(RefExpr && "NULL expr in OpenMP shared clause.");
20509 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr)) {
20510 // It will be analyzed later.
20511 Vars.push_back(Elt: RefExpr);
20512 continue;
20513 }
20514
20515 SourceLocation ELoc = RefExpr->getExprLoc();
20516 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20517 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
20518 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
20519 if (OMPDependTFound)
20520 OMPDependTFound = findOMPDependT(S&: SemaRef, Loc: StartLoc, DSAStack,
20521 Diagnose: DepKind == OMPC_DEPEND_depobj);
20522 if (DepKind == OMPC_DEPEND_depobj) {
20523 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20524 // List items used in depend clauses with the depobj dependence type
20525 // must be expressions of the omp_depend_t type.
20526 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20527 !RefExpr->isInstantiationDependent() &&
20528 !RefExpr->containsUnexpandedParameterPack() &&
20529 (OMPDependTFound &&
20530 !getASTContext().hasSameUnqualifiedType(
20531 DSAStack->getOMPDependT(), RefExpr->getType()))) {
20532 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20533 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20534 continue;
20535 }
20536 if (!RefExpr->isLValue()) {
20537 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20538 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20539 continue;
20540 }
20541 } else {
20542 // OpenMP 5.0 [2.17.11, Restrictions]
20543 // List items used in depend clauses cannot be zero-length array
20544 // sections.
20545 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20546 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: SimpleExpr);
20547 if (OASE) {
20548 QualType BaseType =
20549 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
20550 if (BaseType.isNull())
20551 return nullptr;
20552 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20553 ExprTy = ATy->getElementType();
20554 else
20555 ExprTy = BaseType->getPointeeType();
20556 if (BaseType.isNull() || ExprTy.isNull())
20557 return nullptr;
20558 ExprTy = ExprTy.getNonReferenceType();
20559 const Expr *Length = OASE->getLength();
20560 Expr::EvalResult Result;
20561 if (Length && !Length->isValueDependent() &&
20562 Length->EvaluateAsInt(Result, Ctx: getASTContext()) &&
20563 Result.Val.getInt().isZero()) {
20564 Diag(ELoc,
20565 diag::err_omp_depend_zero_length_array_section_not_allowed)
20566 << SimpleExpr->getSourceRange();
20567 continue;
20568 }
20569 }
20570
20571 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20572 // List items used in depend clauses with the in, out, inout,
20573 // inoutset, or mutexinoutset dependence types cannot be
20574 // expressions of the omp_depend_t type.
20575 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20576 !RefExpr->isInstantiationDependent() &&
20577 !RefExpr->containsUnexpandedParameterPack() &&
20578 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20579 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
20580 ExprTy.getTypePtr()))) {
20581 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20582 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20583 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20584 << RefExpr->getSourceRange();
20585 continue;
20586 }
20587
20588 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: SimpleExpr);
20589 if (ASE && !ASE->getBase()->isTypeDependent() &&
20590 !ASE->getBase()
20591 ->getType()
20592 .getNonReferenceType()
20593 ->isPointerType() &&
20594 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20595 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20596 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20597 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20598 << RefExpr->getSourceRange();
20599 continue;
20600 }
20601
20602 ExprResult Res;
20603 {
20604 Sema::TentativeAnalysisScope Trap(SemaRef);
20605 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf,
20606 InputExpr: RefExpr->IgnoreParenImpCasts());
20607 }
20608 if (!Res.isUsable() && !isa<ArraySectionExpr>(Val: SimpleExpr) &&
20609 !isa<OMPArrayShapingExpr>(Val: SimpleExpr)) {
20610 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20611 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20612 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20613 << RefExpr->getSourceRange();
20614 continue;
20615 }
20616 }
20617 }
20618 Vars.push_back(Elt: RefExpr->IgnoreParenImpCasts());
20619 }
20620 }
20621
20622 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20623 DepKind != OMPC_DEPEND_outallmemory &&
20624 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20625 return nullptr;
20626
20627 auto *C = OMPDependClause::Create(
20628 C: getASTContext(), StartLoc, LParenLoc, EndLoc,
20629 Data: {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, VL: Vars,
20630 NumLoops: TotalDepCount.getZExtValue());
20631 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20632 DSAStack->isParentOrderedRegion())
20633 DSAStack->addDoacrossDependClause(C: C, OpsOffs);
20634 return C;
20635}
20636
20637OMPClause *SemaOpenMP::ActOnOpenMPDeviceClause(
20638 OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc,
20639 SourceLocation LParenLoc, SourceLocation ModifierLoc,
20640 SourceLocation EndLoc) {
20641 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
20642 "Unexpected device modifier in OpenMP < 50.");
20643
20644 bool ErrorFound = false;
20645 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
20646 std::string Values =
20647 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
20648 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20649 << Values << getOpenMPClauseNameForDiag(OMPC_device);
20650 ErrorFound = true;
20651 }
20652
20653 Expr *ValExpr = Device;
20654 Stmt *HelperValStmt = nullptr;
20655
20656 // OpenMP [2.9.1, Restrictions]
20657 // The device expression must evaluate to a non-negative integer value.
20658 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
20659 /*StrictlyPositive=*/false) ||
20660 ErrorFound;
20661 if (ErrorFound)
20662 return nullptr;
20663
20664 // OpenMP 5.0 [2.12.5, Restrictions]
20665 // In case of ancestor device-modifier, a requires directive with
20666 // the reverse_offload clause must be specified.
20667 if (Modifier == OMPC_DEVICE_ancestor) {
20668 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20669 SemaRef.targetDiag(
20670 StartLoc,
20671 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20672 ErrorFound = true;
20673 }
20674 }
20675
20676 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20677 OpenMPDirectiveKind CaptureRegion =
20678 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
20679 if (CaptureRegion != OMPD_unknown &&
20680 !SemaRef.CurContext->isDependentContext()) {
20681 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
20682 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20683 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
20684 HelperValStmt = buildPreInits(getASTContext(), Captures);
20685 }
20686
20687 return new (getASTContext())
20688 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20689 LParenLoc, ModifierLoc, EndLoc);
20690}
20691
20692static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
20693 DSAStackTy *Stack, QualType QTy,
20694 bool FullCheck = true) {
20695 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
20696 return false;
20697 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20698 !QTy.isTriviallyCopyableType(SemaRef.Context))
20699 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20700 return true;
20701}
20702
20703/// Return true if it can be proven that the provided array expression
20704/// (array section or array subscript) does NOT specify the whole size of the
20705/// array whose base type is \a BaseQTy.
20706static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
20707 const Expr *E,
20708 QualType BaseQTy) {
20709 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: E);
20710
20711 // If this is an array subscript, it refers to the whole size if the size of
20712 // the dimension is constant and equals 1. Also, an array section assumes the
20713 // format of an array subscript if no colon is used.
20714 if (isa<ArraySubscriptExpr>(Val: E) ||
20715 (OASE && OASE->getColonLocFirst().isInvalid())) {
20716 if (const auto *ATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr()))
20717 return ATy->getSExtSize() != 1;
20718 // Size can't be evaluated statically.
20719 return false;
20720 }
20721
20722 assert(OASE && "Expecting array section if not an array subscript.");
20723 const Expr *LowerBound = OASE->getLowerBound();
20724 const Expr *Length = OASE->getLength();
20725
20726 // If there is a lower bound that does not evaluates to zero, we are not
20727 // covering the whole dimension.
20728 if (LowerBound) {
20729 Expr::EvalResult Result;
20730 if (!LowerBound->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
20731 return false; // Can't get the integer value as a constant.
20732
20733 llvm::APSInt ConstLowerBound = Result.Val.getInt();
20734 if (ConstLowerBound.getSExtValue())
20735 return true;
20736 }
20737
20738 // If we don't have a length we covering the whole dimension.
20739 if (!Length)
20740 return false;
20741
20742 // If the base is a pointer, we don't have a way to get the size of the
20743 // pointee.
20744 if (BaseQTy->isPointerType())
20745 return false;
20746
20747 // We can only check if the length is the same as the size of the dimension
20748 // if we have a constant array.
20749 const auto *CATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr());
20750 if (!CATy)
20751 return false;
20752
20753 Expr::EvalResult Result;
20754 if (!Length->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
20755 return false; // Can't get the integer value as a constant.
20756
20757 llvm::APSInt ConstLength = Result.Val.getInt();
20758 return CATy->getSExtSize() != ConstLength.getSExtValue();
20759}
20760
20761// Return true if it can be proven that the provided array expression (array
20762// section or array subscript) does NOT specify a single element of the array
20763// whose base type is \a BaseQTy.
20764static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
20765 const Expr *E,
20766 QualType BaseQTy) {
20767 const auto *OASE = dyn_cast<ArraySectionExpr>(Val: E);
20768
20769 // An array subscript always refer to a single element. Also, an array section
20770 // assumes the format of an array subscript if no colon is used.
20771 if (isa<ArraySubscriptExpr>(Val: E) ||
20772 (OASE && OASE->getColonLocFirst().isInvalid()))
20773 return false;
20774
20775 assert(OASE && "Expecting array section if not an array subscript.");
20776 const Expr *Length = OASE->getLength();
20777
20778 // If we don't have a length we have to check if the array has unitary size
20779 // for this dimension. Also, we should always expect a length if the base type
20780 // is pointer.
20781 if (!Length) {
20782 if (const auto *ATy = dyn_cast<ConstantArrayType>(Val: BaseQTy.getTypePtr()))
20783 return ATy->getSExtSize() != 1;
20784 // We cannot assume anything.
20785 return false;
20786 }
20787
20788 // Check if the length evaluates to 1.
20789 Expr::EvalResult Result;
20790 if (!Length->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()))
20791 return false; // Can't get the integer value as a constant.
20792
20793 llvm::APSInt ConstLength = Result.Val.getInt();
20794 return ConstLength.getSExtValue() != 1;
20795}
20796
20797// The base of elements of list in a map clause have to be either:
20798// - a reference to variable or field.
20799// - a member expression.
20800// - an array expression.
20801//
20802// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20803// reference to 'r'.
20804//
20805// If we have:
20806//
20807// struct SS {
20808// Bla S;
20809// foo() {
20810// #pragma omp target map (S.Arr[:12]);
20811// }
20812// }
20813//
20814// We want to retrieve the member expression 'this->S';
20815
20816// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20817// If a list item is an array section, it must specify contiguous storage.
20818//
20819// For this restriction it is sufficient that we make sure only references
20820// to variables or fields and array expressions, and that no array sections
20821// exist except in the rightmost expression (unless they cover the whole
20822// dimension of the array). E.g. these would be invalid:
20823//
20824// r.ArrS[3:5].Arr[6:7]
20825//
20826// r.ArrS[3:5].x
20827//
20828// but these would be valid:
20829// r.ArrS[3].Arr[6:7]
20830//
20831// r.ArrS[3].x
20832namespace {
20833class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20834 Sema &SemaRef;
20835 OpenMPClauseKind CKind = OMPC_unknown;
20836 OpenMPDirectiveKind DKind = OMPD_unknown;
20837 OMPClauseMappableExprCommon::MappableExprComponentList &Components;
20838 bool IsNonContiguous = false;
20839 bool NoDiagnose = false;
20840 const Expr *RelevantExpr = nullptr;
20841 bool AllowUnitySizeArraySection = true;
20842 bool AllowWholeSizeArraySection = true;
20843 bool AllowAnotherPtr = true;
20844 SourceLocation ELoc;
20845 SourceRange ERange;
20846
20847 void emitErrorMsg() {
20848 // If nothing else worked, this is not a valid map clause expression.
20849 if (SemaRef.getLangOpts().OpenMP < 50) {
20850 SemaRef.Diag(ELoc,
20851 diag::err_omp_expected_named_var_member_or_array_expression)
20852 << ERange;
20853 } else {
20854 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20855 << getOpenMPClauseNameForDiag(CKind) << ERange;
20856 }
20857 }
20858
20859public:
20860 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
20861 if (!isa<VarDecl>(Val: DRE->getDecl())) {
20862 emitErrorMsg();
20863 return false;
20864 }
20865 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20866 RelevantExpr = DRE;
20867 // Record the component.
20868 Components.emplace_back(Args&: DRE, Args: DRE->getDecl(), Args&: IsNonContiguous);
20869 return true;
20870 }
20871
20872 bool VisitMemberExpr(MemberExpr *ME) {
20873 Expr *E = ME;
20874 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
20875
20876 if (isa<CXXThisExpr>(Val: BaseE)) {
20877 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20878 // We found a base expression: this->Val.
20879 RelevantExpr = ME;
20880 } else {
20881 E = BaseE;
20882 }
20883
20884 if (!isa<FieldDecl>(Val: ME->getMemberDecl())) {
20885 if (!NoDiagnose) {
20886 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20887 << ME->getSourceRange();
20888 return false;
20889 }
20890 if (RelevantExpr)
20891 return false;
20892 return Visit(E);
20893 }
20894
20895 auto *FD = cast<FieldDecl>(Val: ME->getMemberDecl());
20896
20897 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
20898 // A bit-field cannot appear in a map clause.
20899 //
20900 if (FD->isBitField()) {
20901 if (!NoDiagnose) {
20902 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20903 << ME->getSourceRange() << getOpenMPClauseNameForDiag(CKind);
20904 return false;
20905 }
20906 if (RelevantExpr)
20907 return false;
20908 return Visit(E);
20909 }
20910
20911 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20912 // If the type of a list item is a reference to a type T then the type
20913 // will be considered to be T for all purposes of this clause.
20914 QualType CurType = BaseE->getType().getNonReferenceType();
20915
20916 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
20917 // A list item cannot be a variable that is a member of a structure with
20918 // a union type.
20919 //
20920 if (CurType->isUnionType()) {
20921 if (!NoDiagnose) {
20922 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20923 << ME->getSourceRange();
20924 return false;
20925 }
20926 return RelevantExpr || Visit(E);
20927 }
20928
20929 // If we got a member expression, we should not expect any array section
20930 // before that:
20931 //
20932 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
20933 // If a list item is an element of a structure, only the rightmost symbol
20934 // of the variable reference can be an array section.
20935 //
20936 AllowUnitySizeArraySection = false;
20937 AllowWholeSizeArraySection = false;
20938
20939 // Record the component.
20940 Components.emplace_back(Args&: ME, Args&: FD, Args&: IsNonContiguous);
20941 return RelevantExpr || Visit(E);
20942 }
20943
20944 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
20945 Expr *E = AE->getBase()->IgnoreParenImpCasts();
20946
20947 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
20948 if (!NoDiagnose) {
20949 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20950 << 0 << AE->getSourceRange();
20951 return false;
20952 }
20953 return RelevantExpr || Visit(E);
20954 }
20955
20956 // If we got an array subscript that express the whole dimension we
20957 // can have any array expressions before. If it only expressing part of
20958 // the dimension, we can only have unitary-size array expressions.
20959 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, AE, E->getType()))
20960 AllowWholeSizeArraySection = false;
20961
20962 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E->IgnoreParenCasts())) {
20963 Expr::EvalResult Result;
20964 if (!AE->getIdx()->isValueDependent() &&
20965 AE->getIdx()->EvaluateAsInt(Result, Ctx: SemaRef.getASTContext()) &&
20966 !Result.Val.getInt().isZero()) {
20967 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20968 diag::err_omp_invalid_map_this_expr);
20969 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20970 diag::note_omp_invalid_subscript_on_this_ptr_map);
20971 }
20972 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20973 RelevantExpr = TE;
20974 }
20975
20976 // Record the component - we don't have any declaration associated.
20977 Components.emplace_back(Args&: AE, Args: nullptr, Args&: IsNonContiguous);
20978
20979 return RelevantExpr || Visit(E);
20980 }
20981
20982 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
20983 // After OMP 5.0 Array section in reduction clause will be implicitly
20984 // mapped
20985 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20986 "Array sections cannot be implicitly mapped.");
20987 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20988 QualType CurType =
20989 ArraySectionExpr::getBaseOriginalType(Base: E).getCanonicalType();
20990
20991 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20992 // If the type of a list item is a reference to a type T then the type
20993 // will be considered to be T for all purposes of this clause.
20994 if (CurType->isReferenceType())
20995 CurType = CurType->getPointeeType();
20996
20997 bool IsPointer = CurType->isAnyPointerType();
20998
20999 if (!IsPointer && !CurType->isArrayType()) {
21000 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21001 << 0 << OASE->getSourceRange();
21002 return false;
21003 }
21004
21005 bool NotWhole =
21006 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
21007 bool NotUnity =
21008 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
21009
21010 if (AllowWholeSizeArraySection) {
21011 // Any array section is currently allowed. Allowing a whole size array
21012 // section implies allowing a unity array section as well.
21013 //
21014 // If this array section refers to the whole dimension we can still
21015 // accept other array sections before this one, except if the base is a
21016 // pointer. Otherwise, only unitary sections are accepted.
21017 if (NotWhole || IsPointer)
21018 AllowWholeSizeArraySection = false;
21019 } else if (DKind == OMPD_target_update &&
21020 SemaRef.getLangOpts().OpenMP >= 50) {
21021 if (IsPointer && !AllowAnotherPtr)
21022 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21023 << /*array of unknown bound */ 1;
21024 else
21025 IsNonContiguous = true;
21026 } else if (AllowUnitySizeArraySection && NotUnity) {
21027 // A unity or whole array section is not allowed and that is not
21028 // compatible with the properties of the current array section.
21029 if (NoDiagnose)
21030 return false;
21031 SemaRef.Diag(ELoc,
21032 diag::err_array_section_does_not_specify_contiguous_storage)
21033 << OASE->getSourceRange();
21034 return false;
21035 }
21036
21037 if (IsPointer)
21038 AllowAnotherPtr = false;
21039
21040 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E)) {
21041 Expr::EvalResult ResultR;
21042 Expr::EvalResult ResultL;
21043 if (!OASE->getLength()->isValueDependent() &&
21044 OASE->getLength()->EvaluateAsInt(Result&: ResultR, Ctx: SemaRef.getASTContext()) &&
21045 !ResultR.Val.getInt().isOne()) {
21046 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21047 diag::err_omp_invalid_map_this_expr);
21048 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21049 diag::note_omp_invalid_length_on_this_ptr_mapping);
21050 }
21051 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
21052 OASE->getLowerBound()->EvaluateAsInt(Result&: ResultL,
21053 Ctx: SemaRef.getASTContext()) &&
21054 !ResultL.Val.getInt().isZero()) {
21055 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21056 diag::err_omp_invalid_map_this_expr);
21057 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21058 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21059 }
21060 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21061 RelevantExpr = TE;
21062 }
21063
21064 // Record the component - we don't have any declaration associated.
21065 Components.emplace_back(Args&: OASE, Args: nullptr, /*IsNonContiguous=*/Args: false);
21066 return RelevantExpr || Visit(E);
21067 }
21068 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21069 Expr *Base = E->getBase();
21070
21071 // Record the component - we don't have any declaration associated.
21072 Components.emplace_back(Args&: E, Args: nullptr, Args&: IsNonContiguous);
21073
21074 return Visit(Base->IgnoreParenImpCasts());
21075 }
21076
21077 bool VisitUnaryOperator(UnaryOperator *UO) {
21078 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
21079 UO->getOpcode() != UO_Deref) {
21080 emitErrorMsg();
21081 return false;
21082 }
21083 if (!RelevantExpr) {
21084 // Record the component if haven't found base decl.
21085 Components.emplace_back(Args&: UO, Args: nullptr, /*IsNonContiguous=*/Args: false);
21086 }
21087 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
21088 }
21089 bool VisitBinaryOperator(BinaryOperator *BO) {
21090 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
21091 emitErrorMsg();
21092 return false;
21093 }
21094
21095 // Pointer arithmetic is the only thing we expect to happen here so after we
21096 // make sure the binary operator is a pointer type, the only thing we need
21097 // to do is to visit the subtree that has the same type as root (so that we
21098 // know the other subtree is just an offset)
21099 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
21100 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
21101 Components.emplace_back(Args&: BO, Args: nullptr, Args: false);
21102 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
21103 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
21104 "Either LHS or RHS have base decl inside");
21105 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
21106 return RelevantExpr || Visit(LE);
21107 return RelevantExpr || Visit(RE);
21108 }
21109 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21110 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21111 RelevantExpr = CTE;
21112 Components.emplace_back(Args&: CTE, Args: nullptr, Args&: IsNonContiguous);
21113 return true;
21114 }
21115 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21116 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21117 Components.emplace_back(Args&: COCE, Args: nullptr, Args&: IsNonContiguous);
21118 return true;
21119 }
21120 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21121 Expr *Source = E->getSourceExpr();
21122 if (!Source) {
21123 emitErrorMsg();
21124 return false;
21125 }
21126 return Visit(Source);
21127 }
21128 bool VisitStmt(Stmt *) {
21129 emitErrorMsg();
21130 return false;
21131 }
21132 const Expr *getFoundBase() const { return RelevantExpr; }
21133 explicit MapBaseChecker(
21134 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
21135 OMPClauseMappableExprCommon::MappableExprComponentList &Components,
21136 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21137 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21138 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21139};
21140} // namespace
21141
21142/// Return the expression of the base of the mappable expression or null if it
21143/// cannot be determined and do all the necessary checks to see if the
21144/// expression is valid as a standalone mappable expression. In the process,
21145/// record all the components of the expression.
21146static const Expr *checkMapClauseExpressionBase(
21147 Sema &SemaRef, Expr *E,
21148 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
21149 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
21150 SourceLocation ELoc = E->getExprLoc();
21151 SourceRange ERange = E->getSourceRange();
21152 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21153 ERange);
21154 if (Checker.Visit(E->IgnoreParens())) {
21155 // Check if the highest dimension array section has length specified
21156 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21157 (CKind == OMPC_to || CKind == OMPC_from)) {
21158 auto CI = CurComponents.rbegin();
21159 auto CE = CurComponents.rend();
21160 for (; CI != CE; ++CI) {
21161 const auto *OASE =
21162 dyn_cast<ArraySectionExpr>(Val: CI->getAssociatedExpression());
21163 if (!OASE)
21164 continue;
21165 if (OASE && OASE->getLength())
21166 break;
21167 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
21168 << ERange;
21169 }
21170 }
21171 return Checker.getFoundBase();
21172 }
21173 return nullptr;
21174}
21175
21176// Return true if expression E associated with value VD has conflicts with other
21177// map information.
21178static bool checkMapConflicts(
21179 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21180 bool CurrentRegionOnly,
21181 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
21182 OpenMPClauseKind CKind) {
21183 assert(VD && E);
21184 SourceLocation ELoc = E->getExprLoc();
21185 SourceRange ERange = E->getSourceRange();
21186
21187 // In order to easily check the conflicts we need to match each component of
21188 // the expression under test with the components of the expressions that are
21189 // already in the stack.
21190
21191 assert(!CurComponents.empty() && "Map clause expression with no components!");
21192 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21193 "Map clause expression with unexpected base!");
21194
21195 // Variables to help detecting enclosing problems in data environment nests.
21196 bool IsEnclosedByDataEnvironmentExpr = false;
21197 const Expr *EnclosingExpr = nullptr;
21198
21199 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21200 VD, CurrentRegionOnly,
21201 Check: [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21202 ERange, CKind, &EnclosingExpr,
21203 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
21204 StackComponents,
21205 OpenMPClauseKind Kind) {
21206 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21207 return false;
21208 assert(!StackComponents.empty() &&
21209 "Map clause expression with no components!");
21210 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21211 "Map clause expression with unexpected base!");
21212 (void)VD;
21213
21214 // The whole expression in the stack.
21215 const Expr *RE = StackComponents.front().getAssociatedExpression();
21216
21217 // Expressions must start from the same base. Here we detect at which
21218 // point both expressions diverge from each other and see if we can
21219 // detect if the memory referred to both expressions is contiguous and
21220 // do not overlap.
21221 auto CI = CurComponents.rbegin();
21222 auto CE = CurComponents.rend();
21223 auto SI = StackComponents.rbegin();
21224 auto SE = StackComponents.rend();
21225 for (; CI != CE && SI != SE; ++CI, ++SI) {
21226
21227 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21228 // At most one list item can be an array item derived from a given
21229 // variable in map clauses of the same construct.
21230 if (CurrentRegionOnly &&
21231 (isa<ArraySubscriptExpr>(Val: CI->getAssociatedExpression()) ||
21232 isa<ArraySectionExpr>(Val: CI->getAssociatedExpression()) ||
21233 isa<OMPArrayShapingExpr>(Val: CI->getAssociatedExpression())) &&
21234 (isa<ArraySubscriptExpr>(Val: SI->getAssociatedExpression()) ||
21235 isa<ArraySectionExpr>(Val: SI->getAssociatedExpression()) ||
21236 isa<OMPArrayShapingExpr>(Val: SI->getAssociatedExpression()))) {
21237 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21238 diag::err_omp_multiple_array_items_in_map_clause)
21239 << CI->getAssociatedExpression()->getSourceRange();
21240 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21241 diag::note_used_here)
21242 << SI->getAssociatedExpression()->getSourceRange();
21243 return true;
21244 }
21245
21246 // Do both expressions have the same kind?
21247 if (CI->getAssociatedExpression()->getStmtClass() !=
21248 SI->getAssociatedExpression()->getStmtClass())
21249 break;
21250
21251 // Are we dealing with different variables/fields?
21252 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21253 break;
21254 }
21255 // Check if the extra components of the expressions in the enclosing
21256 // data environment are redundant for the current base declaration.
21257 // If they are, the maps completely overlap, which is legal.
21258 for (; SI != SE; ++SI) {
21259 QualType Type;
21260 if (const auto *ASE =
21261 dyn_cast<ArraySubscriptExpr>(Val: SI->getAssociatedExpression())) {
21262 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21263 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
21264 Val: SI->getAssociatedExpression())) {
21265 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21266 Type = ArraySectionExpr::getBaseOriginalType(Base: E).getCanonicalType();
21267 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21268 Val: SI->getAssociatedExpression())) {
21269 Type = OASE->getBase()->getType()->getPointeeType();
21270 }
21271 if (Type.isNull() || Type->isAnyPointerType() ||
21272 checkArrayExpressionDoesNotReferToWholeSize(
21273 SemaRef, E: SI->getAssociatedExpression(), BaseQTy: Type))
21274 break;
21275 }
21276
21277 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21278 // List items of map clauses in the same construct must not share
21279 // original storage.
21280 //
21281 // If the expressions are exactly the same or one is a subset of the
21282 // other, it means they are sharing storage.
21283 if (CI == CE && SI == SE) {
21284 if (CurrentRegionOnly) {
21285 if (CKind == OMPC_map) {
21286 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21287 } else {
21288 assert(CKind == OMPC_to || CKind == OMPC_from);
21289 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21290 << ERange;
21291 }
21292 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21293 << RE->getSourceRange();
21294 return true;
21295 }
21296 // If we find the same expression in the enclosing data environment,
21297 // that is legal.
21298 IsEnclosedByDataEnvironmentExpr = true;
21299 return false;
21300 }
21301
21302 QualType DerivedType =
21303 std::prev(x: CI)->getAssociatedDeclaration()->getType();
21304 SourceLocation DerivedLoc =
21305 std::prev(x: CI)->getAssociatedExpression()->getExprLoc();
21306
21307 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21308 // If the type of a list item is a reference to a type T then the type
21309 // will be considered to be T for all purposes of this clause.
21310 DerivedType = DerivedType.getNonReferenceType();
21311
21312 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21313 // A variable for which the type is pointer and an array section
21314 // derived from that variable must not appear as list items of map
21315 // clauses of the same construct.
21316 //
21317 // Also, cover one of the cases in:
21318 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21319 // If any part of the original storage of a list item has corresponding
21320 // storage in the device data environment, all of the original storage
21321 // must have corresponding storage in the device data environment.
21322 //
21323 if (DerivedType->isAnyPointerType()) {
21324 if (CI == CE || SI == SE) {
21325 SemaRef.Diag(
21326 DerivedLoc,
21327 diag::err_omp_pointer_mapped_along_with_derived_section)
21328 << DerivedLoc;
21329 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21330 << RE->getSourceRange();
21331 return true;
21332 }
21333 if (CI->getAssociatedExpression()->getStmtClass() !=
21334 SI->getAssociatedExpression()->getStmtClass() ||
21335 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21336 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21337 assert(CI != CE && SI != SE);
21338 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21339 << DerivedLoc;
21340 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21341 << RE->getSourceRange();
21342 return true;
21343 }
21344 }
21345
21346 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21347 // List items of map clauses in the same construct must not share
21348 // original storage.
21349 //
21350 // An expression is a subset of the other.
21351 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21352 if (CKind == OMPC_map) {
21353 if (CI != CE || SI != SE) {
21354 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21355 // a pointer.
21356 auto Begin =
21357 CI != CE ? CurComponents.begin() : StackComponents.begin();
21358 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21359 auto It = Begin;
21360 while (It != End && !It->getAssociatedDeclaration())
21361 std::advance(i&: It, n: 1);
21362 assert(It != End &&
21363 "Expected at least one component with the declaration.");
21364 if (It != Begin && It->getAssociatedDeclaration()
21365 ->getType()
21366 .getCanonicalType()
21367 ->isAnyPointerType()) {
21368 IsEnclosedByDataEnvironmentExpr = false;
21369 EnclosingExpr = nullptr;
21370 return false;
21371 }
21372 }
21373 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21374 } else {
21375 assert(CKind == OMPC_to || CKind == OMPC_from);
21376 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21377 << ERange;
21378 }
21379 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21380 << RE->getSourceRange();
21381 return true;
21382 }
21383
21384 // The current expression uses the same base as other expression in the
21385 // data environment but does not contain it completely.
21386 if (!CurrentRegionOnly && SI != SE)
21387 EnclosingExpr = RE;
21388
21389 // The current expression is a subset of the expression in the data
21390 // environment.
21391 IsEnclosedByDataEnvironmentExpr |=
21392 (!CurrentRegionOnly && CI != CE && SI == SE);
21393
21394 return false;
21395 });
21396
21397 if (CurrentRegionOnly)
21398 return FoundError;
21399
21400 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21401 // If any part of the original storage of a list item has corresponding
21402 // storage in the device data environment, all of the original storage must
21403 // have corresponding storage in the device data environment.
21404 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21405 // If a list item is an element of a structure, and a different element of
21406 // the structure has a corresponding list item in the device data environment
21407 // prior to a task encountering the construct associated with the map clause,
21408 // then the list item must also have a corresponding list item in the device
21409 // data environment prior to the task encountering the construct.
21410 //
21411 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21412 SemaRef.Diag(ELoc,
21413 diag::err_omp_original_storage_is_shared_and_does_not_contain)
21414 << ERange;
21415 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
21416 << EnclosingExpr->getSourceRange();
21417 return true;
21418 }
21419
21420 return FoundError;
21421}
21422
21423// Look up the user-defined mapper given the mapper name and mapped type, and
21424// build a reference to it.
21425static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
21426 CXXScopeSpec &MapperIdScopeSpec,
21427 const DeclarationNameInfo &MapperId,
21428 QualType Type,
21429 Expr *UnresolvedMapper) {
21430 if (MapperIdScopeSpec.isInvalid())
21431 return ExprError();
21432 // Get the actual type for the array type.
21433 if (Type->isArrayType()) {
21434 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
21435 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
21436 }
21437 // Find all user-defined mappers with the given MapperId.
21438 SmallVector<UnresolvedSet<8>, 4> Lookups;
21439 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21440 Lookup.suppressDiagnostics();
21441 if (S) {
21442 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &MapperIdScopeSpec,
21443 /*ObjectType=*/QualType())) {
21444 NamedDecl *D = Lookup.getRepresentativeDecl();
21445 while (S && !S->isDeclScope(D))
21446 S = S->getParent();
21447 if (S)
21448 S = S->getParent();
21449 Lookups.emplace_back();
21450 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
21451 Lookup.clear();
21452 }
21453 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(Val: UnresolvedMapper)) {
21454 // Extract the user-defined mappers with the given MapperId.
21455 Lookups.push_back(Elt: UnresolvedSet<8>());
21456 for (NamedDecl *D : ULE->decls()) {
21457 auto *DMD = cast<OMPDeclareMapperDecl>(D);
21458 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
21459 Lookups.back().addDecl(DMD);
21460 }
21461 }
21462 // Defer the lookup for dependent types. The results will be passed through
21463 // UnresolvedMapper on instantiation.
21464 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21465 Type->isInstantiationDependentType() ||
21466 Type->containsUnexpandedParameterPack() ||
21467 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21468 return !D->isInvalidDecl() &&
21469 (D->getType()->isDependentType() ||
21470 D->getType()->isInstantiationDependentType() ||
21471 D->getType()->containsUnexpandedParameterPack());
21472 })) {
21473 UnresolvedSet<8> URS;
21474 for (const UnresolvedSet<8> &Set : Lookups) {
21475 if (Set.empty())
21476 continue;
21477 URS.append(I: Set.begin(), E: Set.end());
21478 }
21479 return UnresolvedLookupExpr::Create(
21480 Context: SemaRef.Context, /*NamingClass=*/nullptr,
21481 QualifierLoc: MapperIdScopeSpec.getWithLocInContext(Context&: SemaRef.Context), NameInfo: MapperId,
21482 /*ADL=*/RequiresADL: false, Begin: URS.begin(), End: URS.end(), /*KnownDependent=*/false,
21483 /*KnownInstantiationDependent=*/false);
21484 }
21485 SourceLocation Loc = MapperId.getLoc();
21486 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21487 // The type must be of struct, union or class type in C and C++
21488 if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
21489 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21490 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
21491 return ExprError();
21492 }
21493 // Perform argument dependent lookup.
21494 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21495 argumentDependentLookup(SemaRef, Id: MapperId, Loc, Ty: Type, Lookups);
21496 // Return the first user-defined mapper with the desired type.
21497 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21498 Lookups, Gen: [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21499 if (!D->isInvalidDecl() &&
21500 SemaRef.Context.hasSameType(T1: D->getType(), T2: Type))
21501 return D;
21502 return nullptr;
21503 }))
21504 return SemaRef.BuildDeclRefExpr(D: VD, Ty: Type, VK: VK_LValue, Loc);
21505 // Find the first user-defined mapper with a type derived from the desired
21506 // type.
21507 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21508 Lookups, Gen: [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21509 if (!D->isInvalidDecl() &&
21510 SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: D->getType()) &&
21511 !Type.isMoreQualifiedThan(other: D->getType(),
21512 Ctx: SemaRef.getASTContext()))
21513 return D;
21514 return nullptr;
21515 })) {
21516 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21517 /*DetectVirtual=*/false);
21518 if (SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: VD->getType(), Paths)) {
21519 if (!Paths.isAmbiguous(BaseType: SemaRef.Context.getCanonicalType(
21520 T: VD->getType().getUnqualifiedType()))) {
21521 if (SemaRef.CheckBaseClassAccess(
21522 AccessLoc: Loc, Base: VD->getType(), Derived: Type, Path: Paths.front(),
21523 /*DiagID=*/0) != Sema::AR_inaccessible) {
21524 return SemaRef.BuildDeclRefExpr(D: VD, Ty: Type, VK: VK_LValue, Loc);
21525 }
21526 }
21527 }
21528 }
21529 // Report error if a mapper is specified, but cannot be found.
21530 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
21531 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
21532 << Type << MapperId.getName();
21533 return ExprError();
21534 }
21535 return ExprEmpty();
21536}
21537
21538namespace {
21539// Utility struct that gathers all the related lists associated with a mappable
21540// expression.
21541struct MappableVarListInfo {
21542 // The list of expressions.
21543 ArrayRef<Expr *> VarList;
21544 // The list of processed expressions.
21545 SmallVector<Expr *, 16> ProcessedVarList;
21546 // The mappble components for each expression.
21547 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
21548 // The base declaration of the variable.
21549 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
21550 // The reference to the user-defined mapper associated with every expression.
21551 SmallVector<Expr *, 16> UDMapperList;
21552
21553 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
21554 // We have a list of components and base declarations for each entry in the
21555 // variable list.
21556 VarComponents.reserve(N: VarList.size());
21557 VarBaseDeclarations.reserve(N: VarList.size());
21558 }
21559};
21560} // namespace
21561
21562static DeclRefExpr *buildImplicitMap(Sema &S, QualType BaseType,
21563 DSAStackTy *Stack,
21564 SmallVectorImpl<OMPClause *> &Maps) {
21565
21566 const RecordDecl *RD = BaseType->getAsRecordDecl();
21567 SourceRange Range = RD->getSourceRange();
21568 DeclarationNameInfo ImplicitName;
21569 // Dummy variable _s for Mapper.
21570 VarDecl *VD = buildVarDecl(SemaRef&: S, Loc: Range.getEnd(), Type: BaseType, Name: "_s");
21571 DeclRefExpr *MapperVarRef =
21572 buildDeclRefExpr(S, D: VD, Ty: BaseType, Loc: SourceLocation());
21573
21574 // Create implicit map clause for mapper.
21575 SmallVector<Expr *, 4> SExprs;
21576 for (auto *FD : RD->fields()) {
21577 Expr *BE = S.BuildMemberExpr(
21578 Base: MapperVarRef, /*IsArrow=*/false, OpLoc: Range.getBegin(),
21579 NNS: NestedNameSpecifierLoc(), TemplateKWLoc: Range.getBegin(), Member: FD,
21580 FoundDecl: DeclAccessPair::make(D: FD, AS: FD->getAccess()),
21581 /*HadMultipleCandidates=*/false,
21582 MemberNameInfo: DeclarationNameInfo(FD->getDeclName(), FD->getSourceRange().getBegin()),
21583 Ty: FD->getType(), VK: VK_LValue, OK: OK_Ordinary);
21584 SExprs.push_back(Elt: BE);
21585 }
21586 CXXScopeSpec MapperIdScopeSpec;
21587 DeclarationNameInfo MapperId;
21588 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
21589
21590 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
21591 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
21592 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
21593 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
21594 OMPVarListLocTy());
21595 Maps.push_back(Elt: MapClause);
21596 return MapperVarRef;
21597}
21598
21599static ExprResult buildImplicitMapper(Sema &S, QualType BaseType,
21600 DSAStackTy *Stack) {
21601
21602 // Build impilicit map for mapper
21603 SmallVector<OMPClause *, 4> Maps;
21604 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
21605
21606 const RecordDecl *RD = BaseType->getAsRecordDecl();
21607 // AST context is RD's ParentASTContext().
21608 ASTContext &Ctx = RD->getParentASTContext();
21609 // DeclContext is RD's DeclContext.
21610 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
21611
21612 // Create implicit default mapper for "RD".
21613 DeclarationName MapperId;
21614 auto &DeclNames = Ctx.DeclarationNames;
21615 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get(Name: "default"));
21616 auto *DMD = OMPDeclareMapperDecl::Create(C&: Ctx, DC: DCT, L: SourceLocation(), Name: MapperId,
21617 T: BaseType, VarName: MapperId, Clauses: Maps, PrevDeclInScope: nullptr);
21618 Scope *Scope = S.getScopeForContext(Ctx: DCT);
21619 if (Scope)
21620 S.PushOnScopeChains(D: DMD, S: Scope, /*AddToContext=*/false);
21621 DCT->addDecl(D: DMD);
21622 DMD->setAccess(clang::AS_none);
21623 auto *VD = cast<DeclRefExpr>(Val: MapperVarRef)->getDecl();
21624 VD->setDeclContext(DMD);
21625 VD->setLexicalDeclContext(DMD);
21626 DMD->addDecl(VD);
21627 DMD->setMapperVarRef(MapperVarRef);
21628 FieldDecl *FD = *RD->field_begin();
21629 // create mapper refence.
21630 return DeclRefExpr::Create(Ctx, NestedNameSpecifierLoc{}, FD->getLocation(),
21631 DMD, false, SourceLocation(), BaseType, VK_LValue);
21632}
21633
21634// Look up the user-defined mapper given the mapper name and mapper type,
21635// return true if found one.
21636static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
21637 CXXScopeSpec &MapperIdScopeSpec,
21638 const DeclarationNameInfo &MapperId,
21639 QualType Type) {
21640 // Find all user-defined mappers with the given MapperId.
21641 SmallVector<UnresolvedSet<8>, 4> Lookups;
21642 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21643 Lookup.suppressDiagnostics();
21644 while (S && SemaRef.LookupParsedName(R&: Lookup, S, SS: &MapperIdScopeSpec,
21645 /*ObjectType=*/QualType())) {
21646 NamedDecl *D = Lookup.getRepresentativeDecl();
21647 while (S && !S->isDeclScope(D))
21648 S = S->getParent();
21649 if (S)
21650 S = S->getParent();
21651 Lookups.emplace_back();
21652 Lookups.back().append(I: Lookup.begin(), E: Lookup.end());
21653 Lookup.clear();
21654 }
21655 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21656 Type->isInstantiationDependentType() ||
21657 Type->containsUnexpandedParameterPack() ||
21658 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21659 return !D->isInvalidDecl() &&
21660 (D->getType()->isDependentType() ||
21661 D->getType()->isInstantiationDependentType() ||
21662 D->getType()->containsUnexpandedParameterPack());
21663 }))
21664 return false;
21665 // Perform argument dependent lookup.
21666 SourceLocation Loc = MapperId.getLoc();
21667 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21668 argumentDependentLookup(SemaRef, Id: MapperId, Loc, Ty: Type, Lookups);
21669 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
21670 Lookups, Gen: [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21671 if (!D->isInvalidDecl() &&
21672 SemaRef.Context.hasSameType(T1: D->getType(), T2: Type))
21673 return D;
21674 return nullptr;
21675 }))
21676 return true;
21677 // Find the first user-defined mapper with a type derived from the desired
21678 // type.
21679 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21680 Lookups, Gen: [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21681 if (!D->isInvalidDecl() &&
21682 SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: D->getType()) &&
21683 !Type.isMoreQualifiedThan(other: D->getType(), Ctx: SemaRef.getASTContext()))
21684 return D;
21685 return nullptr;
21686 });
21687 if (!VD)
21688 return false;
21689 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21690 /*DetectVirtual=*/false);
21691 if (SemaRef.IsDerivedFrom(Loc, Derived: Type, Base: VD->getType(), Paths)) {
21692 bool IsAmbiguous = !Paths.isAmbiguous(
21693 BaseType: SemaRef.Context.getCanonicalType(T: VD->getType().getUnqualifiedType()));
21694 if (IsAmbiguous)
21695 return false;
21696 if (SemaRef.CheckBaseClassAccess(AccessLoc: Loc, Base: VD->getType(), Derived: Type, Path: Paths.front(),
21697 /*DiagID=*/0) != Sema::AR_inaccessible)
21698 return true;
21699 }
21700 return false;
21701}
21702
21703static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
21704 QualType CanonType, const Expr *E) {
21705
21706 // DFS over data members in structures/classes.
21707 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(1,
21708 {CanonType, nullptr});
21709 llvm::DenseMap<const Type *, bool> Visited;
21710 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
21711 while (!Types.empty()) {
21712 auto [BaseType, CurFD] = Types.pop_back_val();
21713 while (ParentChain.back().second == 0)
21714 ParentChain.pop_back();
21715 --ParentChain.back().second;
21716 if (BaseType.isNull())
21717 continue;
21718 // Only structs/classes are allowed to have mappers.
21719 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
21720 if (!RD)
21721 continue;
21722 auto It = Visited.find(BaseType.getTypePtr());
21723 if (It == Visited.end()) {
21724 // Try to find the associated user-defined mapper.
21725 CXXScopeSpec MapperIdScopeSpec;
21726 DeclarationNameInfo DefaultMapperId;
21727 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
21728 ID: &S.Context.Idents.get(Name: "default")));
21729 DefaultMapperId.setLoc(E->getExprLoc());
21730 bool HasUDMapper =
21731 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
21732 DefaultMapperId, BaseType);
21733 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
21734 }
21735 // Found default mapper.
21736 if (It->second)
21737 return true;
21738 // Check for the "default" mapper for data members.
21739 bool FirstIter = true;
21740 for (FieldDecl *FD : RD->fields()) {
21741 if (!FD)
21742 continue;
21743 QualType FieldTy = FD->getType();
21744 if (FieldTy.isNull() ||
21745 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
21746 continue;
21747 if (FirstIter) {
21748 FirstIter = false;
21749 ParentChain.emplace_back(CurFD, 1);
21750 } else {
21751 ++ParentChain.back().second;
21752 }
21753 Types.emplace_back(FieldTy, FD);
21754 }
21755 }
21756 return false;
21757}
21758
21759// Check the validity of the provided variable list for the provided clause kind
21760// \a CKind. In the check process the valid expressions, mappable expression
21761// components, variables, and user-defined mappers are extracted and used to
21762// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21763// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
21764// and \a MapperId are expected to be valid if the clause kind is 'map'.
21765static void checkMappableExpressionList(
21766 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
21767 MappableVarListInfo &MVLI, SourceLocation StartLoc,
21768 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
21769 ArrayRef<Expr *> UnresolvedMappers,
21770 OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
21771 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
21772 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
21773 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
21774 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21775 "Unexpected clause kind with mappable expressions!");
21776 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
21777
21778 // If the identifier of user-defined mapper is not specified, it is "default".
21779 // We do not change the actual name in this clause to distinguish whether a
21780 // mapper is specified explicitly, i.e., it is not explicitly specified when
21781 // MapperId.getName() is empty.
21782 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
21783 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
21784 MapperId.setName(DeclNames.getIdentifier(
21785 ID: &SemaRef.getASTContext().Idents.get(Name: "default")));
21786 MapperId.setLoc(StartLoc);
21787 }
21788
21789 // Iterators to find the current unresolved mapper expression.
21790 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21791 bool UpdateUMIt = false;
21792 Expr *UnresolvedMapper = nullptr;
21793
21794 bool HasHoldModifier =
21795 llvm::is_contained(Range&: Modifiers, Element: OMPC_MAP_MODIFIER_ompx_hold);
21796
21797 // Keep track of the mappable components and base declarations in this clause.
21798 // Each entry in the list is going to have a list of components associated. We
21799 // record each set of the components so that we can build the clause later on.
21800 // In the end we should have the same amount of declarations and component
21801 // lists.
21802
21803 for (Expr *RE : MVLI.VarList) {
21804 assert(RE && "Null expr in omp to/from/map clause");
21805 SourceLocation ELoc = RE->getExprLoc();
21806
21807 // Find the current unresolved mapper expression.
21808 if (UpdateUMIt && UMIt != UMEnd) {
21809 UMIt++;
21810 assert(
21811 UMIt != UMEnd &&
21812 "Expect the size of UnresolvedMappers to match with that of VarList");
21813 }
21814 UpdateUMIt = true;
21815 if (UMIt != UMEnd)
21816 UnresolvedMapper = *UMIt;
21817
21818 const Expr *VE = RE->IgnoreParenLValueCasts();
21819
21820 if (VE->isValueDependent() || VE->isTypeDependent() ||
21821 VE->isInstantiationDependent() ||
21822 VE->containsUnexpandedParameterPack()) {
21823 // Try to find the associated user-defined mapper.
21824 ExprResult ER = buildUserDefinedMapperRef(
21825 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21826 Type: VE->getType().getCanonicalType(), UnresolvedMapper);
21827 if (ER.isInvalid())
21828 continue;
21829 MVLI.UDMapperList.push_back(Elt: ER.get());
21830 // We can only analyze this information once the missing information is
21831 // resolved.
21832 MVLI.ProcessedVarList.push_back(Elt: RE);
21833 continue;
21834 }
21835
21836 Expr *SimpleExpr = RE->IgnoreParenCasts();
21837
21838 if (!RE->isLValue()) {
21839 if (SemaRef.getLangOpts().OpenMP < 50) {
21840 SemaRef.Diag(
21841 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21842 << RE->getSourceRange();
21843 } else {
21844 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21845 << getOpenMPClauseNameForDiag(CKind) << RE->getSourceRange();
21846 }
21847 continue;
21848 }
21849
21850 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
21851 ValueDecl *CurDeclaration = nullptr;
21852
21853 // Obtain the array or member expression bases if required. Also, fill the
21854 // components array with all the components identified in the process.
21855 const Expr *BE =
21856 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
21857 DSAS->getCurrentDirective(), NoDiagnose);
21858 if (!BE)
21859 continue;
21860
21861 assert(!CurComponents.empty() &&
21862 "Invalid mappable expression information.");
21863
21864 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: BE)) {
21865 // Add store "this" pointer to class in DSAStackTy for future checking
21866 DSAS->addMappedClassesQualTypes(QT: TE->getType());
21867 // Try to find the associated user-defined mapper.
21868 ExprResult ER = buildUserDefinedMapperRef(
21869 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21870 Type: VE->getType().getCanonicalType(), UnresolvedMapper);
21871 if (ER.isInvalid())
21872 continue;
21873 MVLI.UDMapperList.push_back(Elt: ER.get());
21874 // Skip restriction checking for variable or field declarations
21875 MVLI.ProcessedVarList.push_back(Elt: RE);
21876 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
21877 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
21878 in_end: CurComponents.end());
21879 MVLI.VarBaseDeclarations.push_back(Elt: nullptr);
21880 continue;
21881 }
21882
21883 // For the following checks, we rely on the base declaration which is
21884 // expected to be associated with the last component. The declaration is
21885 // expected to be a variable or a field (if 'this' is being mapped).
21886 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21887 assert(CurDeclaration && "Null decl on map clause.");
21888 assert(
21889 CurDeclaration->isCanonicalDecl() &&
21890 "Expecting components to have associated only canonical declarations.");
21891
21892 auto *VD = dyn_cast<VarDecl>(Val: CurDeclaration);
21893 const auto *FD = dyn_cast<FieldDecl>(Val: CurDeclaration);
21894
21895 assert((VD || FD) && "Only variables or fields are expected here!");
21896 (void)FD;
21897
21898 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
21899 // threadprivate variables cannot appear in a map clause.
21900 // OpenMP 4.5 [2.10.5, target update Construct]
21901 // threadprivate variables cannot appear in a from clause.
21902 if (VD && DSAS->isThreadPrivate(D: VD)) {
21903 if (NoDiagnose)
21904 continue;
21905 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21906 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21907 << getOpenMPClauseNameForDiag(CKind);
21908 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
21909 continue;
21910 }
21911
21912 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21913 // A list item cannot appear in both a map clause and a data-sharing
21914 // attribute clause on the same construct.
21915
21916 // Check conflicts with other map clause expressions. We check the conflicts
21917 // with the current construct separately from the enclosing data
21918 // environment, because the restrictions are different. We only have to
21919 // check conflicts across regions for the map clauses.
21920 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21921 /*CurrentRegionOnly=*/true, CurComponents, CKind))
21922 break;
21923 if (CKind == OMPC_map &&
21924 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
21925 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21926 /*CurrentRegionOnly=*/false, CurComponents, CKind))
21927 break;
21928
21929 // OpenMP 4.5 [2.10.5, target update Construct]
21930 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21931 // If the type of a list item is a reference to a type T then the type will
21932 // be considered to be T for all purposes of this clause.
21933 auto I = llvm::find_if(
21934 Range&: CurComponents,
21935 P: [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
21936 return MC.getAssociatedDeclaration();
21937 });
21938 assert(I != CurComponents.end() && "Null decl on map clause.");
21939 (void)I;
21940 QualType Type;
21941 auto *ASE = dyn_cast<ArraySubscriptExpr>(Val: VE->IgnoreParens());
21942 auto *OASE = dyn_cast<ArraySectionExpr>(Val: VE->IgnoreParens());
21943 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(Val: VE->IgnoreParens());
21944 if (ASE) {
21945 Type = ASE->getType().getNonReferenceType();
21946 } else if (OASE) {
21947 QualType BaseType =
21948 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
21949 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21950 Type = ATy->getElementType();
21951 else
21952 Type = BaseType->getPointeeType();
21953 Type = Type.getNonReferenceType();
21954 } else if (OAShE) {
21955 Type = OAShE->getBase()->getType()->getPointeeType();
21956 } else {
21957 Type = VE->getType();
21958 }
21959
21960 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
21961 // A list item in a to or from clause must have a mappable type.
21962 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21963 // A list item must have a mappable type.
21964 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
21965 DSAS, Type, /*FullCheck=*/true))
21966 continue;
21967
21968 if (CKind == OMPC_map) {
21969 // target enter data
21970 // OpenMP [2.10.2, Restrictions, p. 99]
21971 // A map-type must be specified in all map clauses and must be either
21972 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
21973 // no map type is present.
21974 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
21975 if (DKind == OMPD_target_enter_data &&
21976 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21977 SemaRef.getLangOpts().OpenMP >= 52)) {
21978 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21979 << (IsMapTypeImplicit ? 1 : 0)
21980 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21981 << getOpenMPDirectiveName(DKind, OMPVersion);
21982 continue;
21983 }
21984
21985 // target exit_data
21986 // OpenMP [2.10.3, Restrictions, p. 102]
21987 // A map-type must be specified in all map clauses and must be either
21988 // from, release, or delete. Starting with OpenMP 5.2 the default map
21989 // type is `from` if no map type is present.
21990 if (DKind == OMPD_target_exit_data &&
21991 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21992 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
21993 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21994 << (IsMapTypeImplicit ? 1 : 0)
21995 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21996 << getOpenMPDirectiveName(DKind, OMPVersion);
21997 continue;
21998 }
21999
22000 // The 'ompx_hold' modifier is specifically intended to be used on a
22001 // 'target' or 'target data' directive to prevent data from being unmapped
22002 // during the associated statement. It is not permitted on a 'target
22003 // enter data' or 'target exit data' directive, which have no associated
22004 // statement.
22005 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
22006 HasHoldModifier) {
22007 SemaRef.Diag(StartLoc,
22008 diag::err_omp_invalid_map_type_modifier_for_directive)
22009 << getOpenMPSimpleClauseTypeName(OMPC_map,
22010 OMPC_MAP_MODIFIER_ompx_hold)
22011 << getOpenMPDirectiveName(DKind, OMPVersion);
22012 continue;
22013 }
22014
22015 // target, target data
22016 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22017 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22018 // A map-type in a map clause must be to, from, tofrom or alloc
22019 if ((DKind == OMPD_target_data ||
22020 isOpenMPTargetExecutionDirective(DKind)) &&
22021 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
22022 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
22023 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22024 << (IsMapTypeImplicit ? 1 : 0)
22025 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22026 << getOpenMPDirectiveName(DKind, OMPVersion);
22027 continue;
22028 }
22029
22030 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22031 // A list item cannot appear in both a map clause and a data-sharing
22032 // attribute clause on the same construct
22033 //
22034 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22035 // A list item cannot appear in both a map clause and a data-sharing
22036 // attribute clause on the same construct unless the construct is a
22037 // combined construct.
22038 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
22039 isOpenMPTargetExecutionDirective(DKind)) ||
22040 DKind == OMPD_target)) {
22041 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22042 if (isOpenMPPrivate(DVar.CKind)) {
22043 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22044 << getOpenMPClauseNameForDiag(DVar.CKind)
22045 << getOpenMPClauseNameForDiag(OMPC_map)
22046 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
22047 OMPVersion);
22048 reportOriginalDsa(SemaRef, Stack: DSAS, D: CurDeclaration, DVar);
22049 continue;
22050 }
22051 }
22052 }
22053
22054 // Try to find the associated user-defined mapper.
22055 ExprResult ER = buildUserDefinedMapperRef(
22056 SemaRef, S: DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22057 Type: Type.getCanonicalType(), UnresolvedMapper);
22058 if (ER.isInvalid())
22059 continue;
22060
22061 // If no user-defined mapper is found, we need to create an implicit one for
22062 // arrays/array-sections on structs that have members that have
22063 // user-defined mappers. This is needed to ensure that the mapper for the
22064 // member is invoked when mapping each element of the array/array-section.
22065 if (!ER.get()) {
22066 QualType BaseType;
22067
22068 if (isa<ArraySectionExpr>(Val: VE)) {
22069 BaseType = VE->getType().getCanonicalType();
22070 if (BaseType->isSpecificBuiltinType(K: BuiltinType::ArraySection)) {
22071 const auto *OASE = cast<ArraySectionExpr>(Val: VE->IgnoreParenImpCasts());
22072 QualType BType =
22073 ArraySectionExpr::getBaseOriginalType(Base: OASE->getBase());
22074 QualType ElemType;
22075 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
22076 ElemType = ATy->getElementType();
22077 else
22078 ElemType = BType->getPointeeType();
22079 BaseType = ElemType.getCanonicalType();
22080 }
22081 } else if (VE->getType()->isArrayType()) {
22082 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
22083 const QualType ElemType = AT->getElementType();
22084 BaseType = ElemType.getCanonicalType();
22085 }
22086
22087 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
22088 isImplicitMapperNeeded(S&: SemaRef, Stack: DSAS, CanonType: BaseType, E: VE)) {
22089 ER = buildImplicitMapper(S&: SemaRef, BaseType, Stack: DSAS);
22090 }
22091 }
22092 MVLI.UDMapperList.push_back(Elt: ER.get());
22093
22094 // Save the current expression.
22095 MVLI.ProcessedVarList.push_back(Elt: RE);
22096
22097 // Store the components in the stack so that they can be used to check
22098 // against other clauses later on.
22099 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
22100 /*WhereFoundClauseKind=*/OMPC_map);
22101
22102 // Save the components and declaration to create the clause. For purposes of
22103 // the clause creation, any component list that has base 'this' uses
22104 // null as base declaration.
22105 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
22106 MVLI.VarComponents.back().append(in_start: CurComponents.begin(),
22107 in_end: CurComponents.end());
22108 MVLI.VarBaseDeclarations.push_back(Elt: isa<MemberExpr>(Val: BE) ? nullptr
22109 : CurDeclaration);
22110 }
22111}
22112
22113OMPClause *SemaOpenMP::ActOnOpenMPMapClause(
22114 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
22115 ArrayRef<SourceLocation> MapTypeModifiersLoc,
22116 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22117 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
22118 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22119 const OMPVarListLocTy &Locs, bool NoDiagnose,
22120 ArrayRef<Expr *> UnresolvedMappers) {
22121 OpenMPMapModifierKind Modifiers[] = {
22122 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22123 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22124 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22125 OMPC_MAP_MODIFIER_unknown};
22126 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
22127
22128 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
22129 BuiltinType::OMPIterator))
22130 Diag(IteratorModifier->getExprLoc(),
22131 diag::err_omp_map_modifier_not_iterator);
22132
22133 // Process map-type-modifiers, flag errors for duplicate modifiers.
22134 unsigned Count = 0;
22135 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22136 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
22137 llvm::is_contained(Range&: Modifiers, Element: MapTypeModifiers[I])) {
22138 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22139 continue;
22140 }
22141 assert(Count < NumberOfOMPMapClauseModifiers &&
22142 "Modifiers exceed the allowed number of map type modifiers");
22143 Modifiers[Count] = MapTypeModifiers[I];
22144 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22145 ++Count;
22146 }
22147
22148 MappableVarListInfo MVLI(VarList);
22149 checkMappableExpressionList(SemaRef, DSAStack, OMPC_map, MVLI, Locs.StartLoc,
22150 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22151 MapType, Modifiers, IsMapTypeImplicit,
22152 NoDiagnose);
22153
22154 // We need to produce a map clause even if we don't have variables so that
22155 // other diagnostics related with non-existing map clauses are accurate.
22156 return OMPMapClause::Create(
22157 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22158 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22159 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()),
22160 MapperId, MapType, IsMapTypeImplicit, MapLoc);
22161}
22162
22163QualType SemaOpenMP::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
22164 TypeResult ParsedType) {
22165 assert(ParsedType.isUsable());
22166
22167 QualType ReductionType = SemaRef.GetTypeFromParser(Ty: ParsedType.get());
22168 if (ReductionType.isNull())
22169 return QualType();
22170
22171 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22172 // A type name in a declare reduction directive cannot be a function type, an
22173 // array type, a reference type, or a type qualified with const, volatile or
22174 // restrict.
22175 if (ReductionType.hasQualifiers()) {
22176 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22177 return QualType();
22178 }
22179
22180 if (ReductionType->isFunctionType()) {
22181 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22182 return QualType();
22183 }
22184 if (ReductionType->isReferenceType()) {
22185 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22186 return QualType();
22187 }
22188 if (ReductionType->isArrayType()) {
22189 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22190 return QualType();
22191 }
22192 return ReductionType;
22193}
22194
22195SemaOpenMP::DeclGroupPtrTy
22196SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveStart(
22197 Scope *S, DeclContext *DC, DeclarationName Name,
22198 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22199 AccessSpecifier AS, Decl *PrevDeclInScope) {
22200 SmallVector<Decl *, 8> Decls;
22201 Decls.reserve(N: ReductionTypes.size());
22202
22203 LookupResult Lookup(SemaRef, Name, SourceLocation(),
22204 Sema::LookupOMPReductionName,
22205 SemaRef.forRedeclarationInCurContext());
22206 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22207 // A reduction-identifier may not be re-declared in the current scope for the
22208 // same type or for a type that is compatible according to the base language
22209 // rules.
22210 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22211 OMPDeclareReductionDecl *PrevDRD = nullptr;
22212 bool InCompoundScope = true;
22213 if (S != nullptr) {
22214 // Find previous declaration with the same name not referenced in other
22215 // declarations.
22216 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
22217 InCompoundScope =
22218 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22219 SemaRef.LookupName(R&: Lookup, S);
22220 SemaRef.FilterLookupForScope(R&: Lookup, Ctx: DC, S, /*ConsiderLinkage=*/false,
22221 /*AllowInlineNamespace=*/false);
22222 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22223 LookupResult::Filter Filter = Lookup.makeFilter();
22224 while (Filter.hasNext()) {
22225 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Val: Filter.next());
22226 if (InCompoundScope) {
22227 UsedAsPrevious.try_emplace(Key: PrevDecl, Args: false);
22228 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
22229 UsedAsPrevious[D] = true;
22230 }
22231 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22232 PrevDecl->getLocation();
22233 }
22234 Filter.done();
22235 if (InCompoundScope) {
22236 for (const auto &PrevData : UsedAsPrevious) {
22237 if (!PrevData.second) {
22238 PrevDRD = PrevData.first;
22239 break;
22240 }
22241 }
22242 }
22243 } else if (PrevDeclInScope != nullptr) {
22244 auto *PrevDRDInScope = PrevDRD =
22245 cast<OMPDeclareReductionDecl>(Val: PrevDeclInScope);
22246 do {
22247 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22248 PrevDRDInScope->getLocation();
22249 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22250 } while (PrevDRDInScope != nullptr);
22251 }
22252 for (const auto &TyData : ReductionTypes) {
22253 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22254 bool Invalid = false;
22255 if (I != PreviousRedeclTypes.end()) {
22256 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22257 << TyData.first;
22258 Diag(I->second, diag::note_previous_definition);
22259 Invalid = true;
22260 }
22261 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22262 auto *DRD = OMPDeclareReductionDecl::Create(
22263 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
22264 DC->addDecl(DRD);
22265 DRD->setAccess(AS);
22266 Decls.push_back(DRD);
22267 if (Invalid)
22268 DRD->setInvalidDecl();
22269 else
22270 PrevDRD = DRD;
22271 }
22272
22273 return DeclGroupPtrTy::make(
22274 P: DeclGroupRef::Create(C&: getASTContext(), Decls: Decls.begin(), NumDecls: Decls.size()));
22275}
22276
22277void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
22278 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
22279
22280 // Enter new function scope.
22281 SemaRef.PushFunctionScope();
22282 SemaRef.setFunctionHasBranchProtectedScope();
22283 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
22284
22285 if (S != nullptr)
22286 SemaRef.PushDeclContext(S, DRD);
22287 else
22288 SemaRef.CurContext = DRD;
22289
22290 SemaRef.PushExpressionEvaluationContext(
22291 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
22292
22293 QualType ReductionType = DRD->getType();
22294 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22295 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22296 // uses semantics of argument handles by value, but it should be passed by
22297 // reference. C lang does not support references, so pass all parameters as
22298 // pointers.
22299 // Create 'T omp_in;' variable.
22300 VarDecl *OmpInParm =
22301 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_in");
22302 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22303 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22304 // uses semantics of argument handles by value, but it should be passed by
22305 // reference. C lang does not support references, so pass all parameters as
22306 // pointers.
22307 // Create 'T omp_out;' variable.
22308 VarDecl *OmpOutParm =
22309 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_out");
22310 if (S != nullptr) {
22311 SemaRef.PushOnScopeChains(OmpInParm, S);
22312 SemaRef.PushOnScopeChains(OmpOutParm, S);
22313 } else {
22314 DRD->addDecl(OmpInParm);
22315 DRD->addDecl(OmpOutParm);
22316 }
22317 Expr *InE =
22318 ::buildDeclRefExpr(S&: SemaRef, D: OmpInParm, Ty: ReductionType, Loc: D->getLocation());
22319 Expr *OutE =
22320 ::buildDeclRefExpr(S&: SemaRef, D: OmpOutParm, Ty: ReductionType, Loc: D->getLocation());
22321 DRD->setCombinerData(InE, OutE);
22322}
22323
22324void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D,
22325 Expr *Combiner) {
22326 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
22327 SemaRef.DiscardCleanupsInEvaluationContext();
22328 SemaRef.PopExpressionEvaluationContext();
22329
22330 SemaRef.PopDeclContext();
22331 SemaRef.PopFunctionScopeInfo();
22332
22333 if (Combiner != nullptr)
22334 DRD->setCombiner(Combiner);
22335 else
22336 DRD->setInvalidDecl();
22337}
22338
22339VarDecl *SemaOpenMP::ActOnOpenMPDeclareReductionInitializerStart(Scope *S,
22340 Decl *D) {
22341 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
22342
22343 // Enter new function scope.
22344 SemaRef.PushFunctionScope();
22345 SemaRef.setFunctionHasBranchProtectedScope();
22346
22347 if (S != nullptr)
22348 SemaRef.PushDeclContext(S, DRD);
22349 else
22350 SemaRef.CurContext = DRD;
22351
22352 SemaRef.PushExpressionEvaluationContext(
22353 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
22354
22355 QualType ReductionType = DRD->getType();
22356 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22357 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22358 // uses semantics of argument handles by value, but it should be passed by
22359 // reference. C lang does not support references, so pass all parameters as
22360 // pointers.
22361 // Create 'T omp_priv;' variable.
22362 VarDecl *OmpPrivParm =
22363 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_priv");
22364 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22365 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22366 // uses semantics of argument handles by value, but it should be passed by
22367 // reference. C lang does not support references, so pass all parameters as
22368 // pointers.
22369 // Create 'T omp_orig;' variable.
22370 VarDecl *OmpOrigParm =
22371 buildVarDecl(SemaRef, Loc: D->getLocation(), Type: ReductionType, Name: "omp_orig");
22372 if (S != nullptr) {
22373 SemaRef.PushOnScopeChains(OmpPrivParm, S);
22374 SemaRef.PushOnScopeChains(OmpOrigParm, S);
22375 } else {
22376 DRD->addDecl(OmpPrivParm);
22377 DRD->addDecl(OmpOrigParm);
22378 }
22379 Expr *OrigE =
22380 ::buildDeclRefExpr(S&: SemaRef, D: OmpOrigParm, Ty: ReductionType, Loc: D->getLocation());
22381 Expr *PrivE =
22382 ::buildDeclRefExpr(S&: SemaRef, D: OmpPrivParm, Ty: ReductionType, Loc: D->getLocation());
22383 DRD->setInitializerData(OrigE, PrivE);
22384 return OmpPrivParm;
22385}
22386
22387void SemaOpenMP::ActOnOpenMPDeclareReductionInitializerEnd(
22388 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
22389 auto *DRD = cast<OMPDeclareReductionDecl>(Val: D);
22390 SemaRef.DiscardCleanupsInEvaluationContext();
22391 SemaRef.PopExpressionEvaluationContext();
22392
22393 SemaRef.PopDeclContext();
22394 SemaRef.PopFunctionScopeInfo();
22395
22396 if (Initializer != nullptr) {
22397 DRD->setInitializer(E: Initializer, IK: OMPDeclareReductionInitKind::Call);
22398 } else if (OmpPrivParm->hasInit()) {
22399 DRD->setInitializer(E: OmpPrivParm->getInit(),
22400 IK: OmpPrivParm->isDirectInit()
22401 ? OMPDeclareReductionInitKind::Direct
22402 : OMPDeclareReductionInitKind::Copy);
22403 } else {
22404 DRD->setInvalidDecl();
22405 }
22406}
22407
22408SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveEnd(
22409 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22410 for (Decl *D : DeclReductions.get()) {
22411 if (IsValid) {
22412 if (S)
22413 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(Val: D), S,
22414 /*AddToContext=*/false);
22415 } else {
22416 D->setInvalidDecl();
22417 }
22418 }
22419 return DeclReductions;
22420}
22421
22422TypeResult SemaOpenMP::ActOnOpenMPDeclareMapperVarDecl(Scope *S,
22423 Declarator &D) {
22424 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
22425 QualType T = TInfo->getType();
22426 if (D.isInvalidType())
22427 return true;
22428
22429 if (getLangOpts().CPlusPlus) {
22430 // Check that there are no default arguments (C++ only).
22431 SemaRef.CheckExtraCXXDefaultArguments(D);
22432 }
22433
22434 return SemaRef.CreateParsedType(T, TInfo);
22435}
22436
22437QualType SemaOpenMP::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
22438 TypeResult ParsedType) {
22439 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
22440
22441 QualType MapperType = SemaRef.GetTypeFromParser(Ty: ParsedType.get());
22442 assert(!MapperType.isNull() && "Expect valid mapper type");
22443
22444 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22445 // The type must be of struct, union or class type in C and C++
22446 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22447 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22448 return QualType();
22449 }
22450 return MapperType;
22451}
22452
22453SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareMapperDirective(
22454 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22455 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
22456 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22457 LookupResult Lookup(SemaRef, Name, SourceLocation(),
22458 Sema::LookupOMPMapperName,
22459 SemaRef.forRedeclarationInCurContext());
22460 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22461 // A mapper-identifier may not be redeclared in the current scope for the
22462 // same type or for a type that is compatible according to the base language
22463 // rules.
22464 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22465 OMPDeclareMapperDecl *PrevDMD = nullptr;
22466 bool InCompoundScope = true;
22467 if (S != nullptr) {
22468 // Find previous declaration with the same name not referenced in other
22469 // declarations.
22470 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
22471 InCompoundScope =
22472 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22473 SemaRef.LookupName(R&: Lookup, S);
22474 SemaRef.FilterLookupForScope(R&: Lookup, Ctx: DC, S, /*ConsiderLinkage=*/false,
22475 /*AllowInlineNamespace=*/false);
22476 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22477 LookupResult::Filter Filter = Lookup.makeFilter();
22478 while (Filter.hasNext()) {
22479 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Val: Filter.next());
22480 if (InCompoundScope) {
22481 UsedAsPrevious.try_emplace(Key: PrevDecl, Args: false);
22482 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22483 UsedAsPrevious[D] = true;
22484 }
22485 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22486 PrevDecl->getLocation();
22487 }
22488 Filter.done();
22489 if (InCompoundScope) {
22490 for (const auto &PrevData : UsedAsPrevious) {
22491 if (!PrevData.second) {
22492 PrevDMD = PrevData.first;
22493 break;
22494 }
22495 }
22496 }
22497 } else if (PrevDeclInScope) {
22498 auto *PrevDMDInScope = PrevDMD =
22499 cast<OMPDeclareMapperDecl>(Val: PrevDeclInScope);
22500 do {
22501 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22502 PrevDMDInScope->getLocation();
22503 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22504 } while (PrevDMDInScope != nullptr);
22505 }
22506 const auto I = PreviousRedeclTypes.find(Val: MapperType.getCanonicalType());
22507 bool Invalid = false;
22508 if (I != PreviousRedeclTypes.end()) {
22509 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22510 << MapperType << Name;
22511 Diag(I->second, diag::note_previous_definition);
22512 Invalid = true;
22513 }
22514 // Build expressions for implicit maps of data members with 'default'
22515 // mappers.
22516 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
22517 if (getLangOpts().OpenMP >= 50)
22518 processImplicitMapsWithDefaultMappers(S&: SemaRef, DSAStack,
22519 Clauses&: ClausesWithImplicit);
22520 auto *DMD = OMPDeclareMapperDecl::Create(C&: getASTContext(), DC, L: StartLoc, Name,
22521 T: MapperType, VarName: VN, Clauses: ClausesWithImplicit,
22522 PrevDeclInScope: PrevDMD);
22523 if (S)
22524 SemaRef.PushOnScopeChains(D: DMD, S);
22525 else
22526 DC->addDecl(D: DMD);
22527 DMD->setAccess(AS);
22528 if (Invalid)
22529 DMD->setInvalidDecl();
22530
22531 auto *VD = cast<DeclRefExpr>(Val: MapperVarRef)->getDecl();
22532 VD->setDeclContext(DMD);
22533 VD->setLexicalDeclContext(DMD);
22534 DMD->addDecl(VD);
22535 DMD->setMapperVarRef(MapperVarRef);
22536
22537 return DeclGroupPtrTy::make(P: DeclGroupRef(DMD));
22538}
22539
22540ExprResult SemaOpenMP::ActOnOpenMPDeclareMapperDirectiveVarDecl(
22541 Scope *S, QualType MapperType, SourceLocation StartLoc,
22542 DeclarationName VN) {
22543 TypeSourceInfo *TInfo =
22544 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
22545 auto *VD = VarDecl::Create(
22546 C&: getASTContext(), DC: getASTContext().getTranslationUnitDecl(), StartLoc,
22547 IdLoc: StartLoc, Id: VN.getAsIdentifierInfo(), T: MapperType, TInfo, S: SC_None);
22548 if (S)
22549 SemaRef.PushOnScopeChains(D: VD, S, /*AddToContext=*/false);
22550 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
22551 DSAStack->addDeclareMapperVarRef(Ref: E);
22552 return E;
22553}
22554
22555void SemaOpenMP::ActOnOpenMPIteratorVarDecl(VarDecl *VD) {
22556 if (DSAStack->getDeclareMapperVarRef())
22557 DSAStack->addIteratorVarDecl(VD);
22558}
22559
22560bool SemaOpenMP::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
22561 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22562 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22563 if (const auto *DRE = cast_or_null<DeclRefExpr>(Val: Ref)) {
22564 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22565 return true;
22566 if (VD->isUsableInConstantExpressions(C: getASTContext()))
22567 return true;
22568 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22569 return true;
22570 return false;
22571 }
22572 return true;
22573}
22574
22575const ValueDecl *SemaOpenMP::getOpenMPDeclareMapperVarName() const {
22576 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22577 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22578}
22579
22580OMPClause *SemaOpenMP::ActOnOpenMPNumTeamsClause(ArrayRef<Expr *> VarList,
22581 SourceLocation StartLoc,
22582 SourceLocation LParenLoc,
22583 SourceLocation EndLoc) {
22584 if (VarList.empty())
22585 return nullptr;
22586
22587 for (Expr *ValExpr : VarList) {
22588 // OpenMP [teams Constrcut, Restrictions]
22589 // The num_teams expression must evaluate to a positive integer value.
22590 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
22591 /*StrictlyPositive=*/true))
22592 return nullptr;
22593 }
22594
22595 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22596 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
22597 DKind, OMPC_num_teams, getLangOpts().OpenMP);
22598 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22599 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22600 LParenLoc, EndLoc, VarList,
22601 /*PreInit=*/nullptr);
22602
22603 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22604 SmallVector<Expr *, 3> Vars;
22605 for (Expr *ValExpr : VarList) {
22606 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
22607 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
22608 Vars.push_back(Elt: ValExpr);
22609 }
22610
22611 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22612 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22613 LParenLoc, EndLoc, Vars, PreInit);
22614}
22615
22616OMPClause *SemaOpenMP::ActOnOpenMPThreadLimitClause(ArrayRef<Expr *> VarList,
22617 SourceLocation StartLoc,
22618 SourceLocation LParenLoc,
22619 SourceLocation EndLoc) {
22620 if (VarList.empty())
22621 return nullptr;
22622
22623 for (Expr *ValExpr : VarList) {
22624 // OpenMP [teams Constrcut, Restrictions]
22625 // The thread_limit expression must evaluate to a positive integer value.
22626 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
22627 /*StrictlyPositive=*/true))
22628 return nullptr;
22629 }
22630
22631 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22632 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
22633 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
22634 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22635 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
22636 StartLoc, LParenLoc, EndLoc, VarList,
22637 /*PreInit=*/nullptr);
22638
22639 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22640 SmallVector<Expr *, 3> Vars;
22641 for (Expr *ValExpr : VarList) {
22642 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
22643 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
22644 Vars.push_back(Elt: ValExpr);
22645 }
22646
22647 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22648 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
22649 LParenLoc, EndLoc, Vars, PreInit);
22650}
22651
22652OMPClause *SemaOpenMP::ActOnOpenMPPriorityClause(Expr *Priority,
22653 SourceLocation StartLoc,
22654 SourceLocation LParenLoc,
22655 SourceLocation EndLoc) {
22656 Expr *ValExpr = Priority;
22657 Stmt *HelperValStmt = nullptr;
22658 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22659
22660 // OpenMP [2.9.1, task Constrcut]
22661 // The priority-value is a non-negative numerical scalar expression.
22662 if (!isNonNegativeIntegerValue(
22663 ValExpr, SemaRef, OMPC_priority,
22664 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22665 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22666 return nullptr;
22667
22668 return new (getASTContext()) OMPPriorityClause(
22669 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22670}
22671
22672OMPClause *SemaOpenMP::ActOnOpenMPGrainsizeClause(
22673 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22674 SourceLocation StartLoc, SourceLocation LParenLoc,
22675 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22676 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22677 "Unexpected grainsize modifier in OpenMP < 51.");
22678
22679 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22680 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22681 OMPC_GRAINSIZE_unknown);
22682 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22683 << Values << getOpenMPClauseNameForDiag(OMPC_grainsize);
22684 return nullptr;
22685 }
22686
22687 Expr *ValExpr = Grainsize;
22688 Stmt *HelperValStmt = nullptr;
22689 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22690
22691 // OpenMP [2.9.2, taskloop Constrcut]
22692 // The parameter of the grainsize clause must be a positive integer
22693 // expression.
22694 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
22695 /*StrictlyPositive=*/true,
22696 /*BuildCapture=*/true,
22697 DSAStack->getCurrentDirective(),
22698 &CaptureRegion, &HelperValStmt))
22699 return nullptr;
22700
22701 return new (getASTContext())
22702 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22703 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22704}
22705
22706OMPClause *SemaOpenMP::ActOnOpenMPNumTasksClause(
22707 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
22708 SourceLocation StartLoc, SourceLocation LParenLoc,
22709 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22710 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22711 "Unexpected num_tasks modifier in OpenMP < 51.");
22712
22713 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
22714 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
22715 OMPC_NUMTASKS_unknown);
22716 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22717 << Values << getOpenMPClauseNameForDiag(OMPC_num_tasks);
22718 return nullptr;
22719 }
22720
22721 Expr *ValExpr = NumTasks;
22722 Stmt *HelperValStmt = nullptr;
22723 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22724
22725 // OpenMP [2.9.2, taskloop Constrcut]
22726 // The parameter of the num_tasks clause must be a positive integer
22727 // expression.
22728 if (!isNonNegativeIntegerValue(
22729 ValExpr, SemaRef, OMPC_num_tasks,
22730 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22731 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22732 return nullptr;
22733
22734 return new (getASTContext())
22735 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22736 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22737}
22738
22739OMPClause *SemaOpenMP::ActOnOpenMPHintClause(Expr *Hint,
22740 SourceLocation StartLoc,
22741 SourceLocation LParenLoc,
22742 SourceLocation EndLoc) {
22743 // OpenMP [2.13.2, critical construct, Description]
22744 // ... where hint-expression is an integer constant expression that evaluates
22745 // to a valid lock hint.
22746 ExprResult HintExpr =
22747 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
22748 if (HintExpr.isInvalid())
22749 return nullptr;
22750 return new (getASTContext())
22751 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22752}
22753
22754/// Tries to find omp_event_handle_t type.
22755static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
22756 DSAStackTy *Stack) {
22757 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22758 if (!OMPEventHandleT.isNull())
22759 return true;
22760 IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name: "omp_event_handle_t");
22761 ParsedType PT = S.getTypeName(II: *II, NameLoc: Loc, S: S.getCurScope());
22762 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22763 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22764 return false;
22765 }
22766 Stack->setOMPEventHandleT(PT.get());
22767 return true;
22768}
22769
22770OMPClause *SemaOpenMP::ActOnOpenMPDetachClause(Expr *Evt,
22771 SourceLocation StartLoc,
22772 SourceLocation LParenLoc,
22773 SourceLocation EndLoc) {
22774 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22775 !Evt->isInstantiationDependent() &&
22776 !Evt->containsUnexpandedParameterPack()) {
22777 if (!findOMPEventHandleT(S&: SemaRef, Loc: Evt->getExprLoc(), DSAStack))
22778 return nullptr;
22779 // OpenMP 5.0, 2.10.1 task Construct.
22780 // event-handle is a variable of the omp_event_handle_t type.
22781 auto *Ref = dyn_cast<DeclRefExpr>(Val: Evt->IgnoreParenImpCasts());
22782 if (!Ref) {
22783 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22784 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22785 return nullptr;
22786 }
22787 auto *VD = dyn_cast_or_null<VarDecl>(Val: Ref->getDecl());
22788 if (!VD) {
22789 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22790 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22791 return nullptr;
22792 }
22793 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
22794 VD->getType()) ||
22795 VD->getType().isConstant(getASTContext())) {
22796 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22797 << "omp_event_handle_t" << 1 << VD->getType()
22798 << Evt->getSourceRange();
22799 return nullptr;
22800 }
22801 // OpenMP 5.0, 2.10.1 task Construct
22802 // [detach clause]... The event-handle will be considered as if it was
22803 // specified on a firstprivate clause.
22804 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
22805 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22806 DVar.RefExpr) {
22807 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
22808 << getOpenMPClauseNameForDiag(DVar.CKind)
22809 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
22810 reportOriginalDsa(SemaRef, DSAStack, VD, DVar);
22811 return nullptr;
22812 }
22813 }
22814
22815 return new (getASTContext())
22816 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
22817}
22818
22819OMPClause *SemaOpenMP::ActOnOpenMPDistScheduleClause(
22820 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
22821 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
22822 SourceLocation EndLoc) {
22823 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
22824 std::string Values;
22825 Values += "'";
22826 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
22827 Values += "'";
22828 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22829 << Values << getOpenMPClauseNameForDiag(OMPC_dist_schedule);
22830 return nullptr;
22831 }
22832 Expr *ValExpr = ChunkSize;
22833 Stmt *HelperValStmt = nullptr;
22834 if (ChunkSize) {
22835 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
22836 !ChunkSize->isInstantiationDependent() &&
22837 !ChunkSize->containsUnexpandedParameterPack()) {
22838 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
22839 ExprResult Val =
22840 PerformOpenMPImplicitIntegerConversion(Loc: ChunkSizeLoc, Op: ChunkSize);
22841 if (Val.isInvalid())
22842 return nullptr;
22843
22844 ValExpr = Val.get();
22845
22846 // OpenMP [2.7.1, Restrictions]
22847 // chunk_size must be a loop invariant integer expression with a positive
22848 // value.
22849 if (std::optional<llvm::APSInt> Result =
22850 ValExpr->getIntegerConstantExpr(Ctx: getASTContext())) {
22851 if (Result->isSigned() && !Result->isStrictlyPositive()) {
22852 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22853 << "dist_schedule" << /*strictly positive*/ 1
22854 << ChunkSize->getSourceRange();
22855 return nullptr;
22856 }
22857 } else if (getOpenMPCaptureRegionForClause(
22858 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22859 getLangOpts().OpenMP) != OMPD_unknown &&
22860 !SemaRef.CurContext->isDependentContext()) {
22861 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
22862 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22863 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
22864 HelperValStmt = buildPreInits(getASTContext(), Captures);
22865 }
22866 }
22867 }
22868
22869 return new (getASTContext())
22870 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
22871 Kind, ValExpr, HelperValStmt);
22872}
22873
22874OMPClause *SemaOpenMP::ActOnOpenMPDefaultmapClause(
22875 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
22876 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
22877 SourceLocation KindLoc, SourceLocation EndLoc) {
22878 if (getLangOpts().OpenMP < 50) {
22879 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22880 Kind != OMPC_DEFAULTMAP_scalar) {
22881 std::string Value;
22882 SourceLocation Loc;
22883 Value += "'";
22884 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22885 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22886 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22887 Loc = MLoc;
22888 } else {
22889 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22890 OMPC_DEFAULTMAP_scalar);
22891 Loc = KindLoc;
22892 }
22893 Value += "'";
22894 Diag(Loc, diag::err_omp_unexpected_clause_value)
22895 << Value << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22896 return nullptr;
22897 }
22898 } else {
22899 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
22900 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
22901 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
22902 if (!isDefaultmapKind || !isDefaultmapModifier) {
22903 StringRef KindValue = getLangOpts().OpenMP < 52
22904 ? "'scalar', 'aggregate', 'pointer'"
22905 : "'scalar', 'aggregate', 'pointer', 'all'";
22906 if (getLangOpts().OpenMP == 50) {
22907 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
22908 "'firstprivate', 'none', 'default'";
22909 if (!isDefaultmapKind && isDefaultmapModifier) {
22910 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22911 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22912 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22913 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22914 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22915 } else {
22916 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22917 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22918 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22919 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22920 }
22921 } else {
22922 StringRef ModifierValue =
22923 "'alloc', 'from', 'to', 'tofrom', "
22924 "'firstprivate', 'none', 'default', 'present'";
22925 if (!isDefaultmapKind && isDefaultmapModifier) {
22926 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22927 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22928 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22929 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22930 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22931 } else {
22932 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22933 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22934 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22935 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22936 }
22937 }
22938 return nullptr;
22939 }
22940
22941 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
22942 // At most one defaultmap clause for each category can appear on the
22943 // directive.
22944 if (DSAStack->checkDefaultmapCategory(VariableCategory: Kind)) {
22945 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22946 return nullptr;
22947 }
22948 }
22949 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
22950 // Variable category is not specified - mark all categories.
22951 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_aggregate, Loc: StartLoc);
22952 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_scalar, Loc: StartLoc);
22953 DSAStack->setDefaultDMAAttr(M, Kind: OMPC_DEFAULTMAP_pointer, Loc: StartLoc);
22954 } else {
22955 DSAStack->setDefaultDMAAttr(M, Kind, Loc: StartLoc);
22956 }
22957
22958 return new (getASTContext())
22959 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
22960}
22961
22962bool SemaOpenMP::ActOnStartOpenMPDeclareTargetContext(
22963 DeclareTargetContextInfo &DTCI) {
22964 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
22965 if (!CurLexicalContext->isFileContext() &&
22966 !CurLexicalContext->isExternCContext() &&
22967 !CurLexicalContext->isExternCXXContext() &&
22968 !isa<CXXRecordDecl>(Val: CurLexicalContext) &&
22969 !isa<ClassTemplateDecl>(Val: CurLexicalContext) &&
22970 !isa<ClassTemplatePartialSpecializationDecl>(Val: CurLexicalContext) &&
22971 !isa<ClassTemplateSpecializationDecl>(Val: CurLexicalContext)) {
22972 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
22973 return false;
22974 }
22975
22976 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22977 if (getLangOpts().HIP)
22978 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
22979
22980 DeclareTargetNesting.push_back(Elt: DTCI);
22981 return true;
22982}
22983
22984const SemaOpenMP::DeclareTargetContextInfo
22985SemaOpenMP::ActOnOpenMPEndDeclareTargetDirective() {
22986 assert(!DeclareTargetNesting.empty() &&
22987 "check isInOpenMPDeclareTargetContext() first!");
22988 return DeclareTargetNesting.pop_back_val();
22989}
22990
22991void SemaOpenMP::ActOnFinishedOpenMPDeclareTargetContext(
22992 DeclareTargetContextInfo &DTCI) {
22993 for (auto &It : DTCI.ExplicitlyMapped)
22994 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
22995}
22996
22997void SemaOpenMP::DiagnoseUnterminatedOpenMPDeclareTarget() {
22998 if (DeclareTargetNesting.empty())
22999 return;
23000 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23001 unsigned OMPVersion = getLangOpts().OpenMP;
23002 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
23003 << getOpenMPDirectiveName(DTCI.Kind, OMPVersion);
23004}
23005
23006NamedDecl *SemaOpenMP::lookupOpenMPDeclareTargetName(
23007 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
23008 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
23009 SemaRef.LookupParsedName(R&: Lookup, S: CurScope, SS: &ScopeSpec,
23010 /*ObjectType=*/QualType(),
23011 /*AllowBuiltinCreation=*/true);
23012
23013 if (Lookup.isAmbiguous())
23014 return nullptr;
23015 Lookup.suppressDiagnostics();
23016
23017 if (!Lookup.isSingleResult()) {
23018 VarOrFuncDeclFilterCCC CCC(SemaRef);
23019 if (TypoCorrection Corrected =
23020 SemaRef.CorrectTypo(Typo: Id, LookupKind: Sema::LookupOrdinaryName, S: CurScope, SS: nullptr,
23021 CCC, Mode: CorrectTypoKind::ErrorRecovery)) {
23022 SemaRef.diagnoseTypo(Corrected,
23023 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
23024 << Id.getName());
23025 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
23026 return nullptr;
23027 }
23028
23029 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
23030 return nullptr;
23031 }
23032
23033 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
23034 if (!isa<VarDecl>(Val: ND) && !isa<FunctionDecl>(Val: ND) &&
23035 !isa<FunctionTemplateDecl>(Val: ND)) {
23036 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
23037 return nullptr;
23038 }
23039 return ND;
23040}
23041
23042void SemaOpenMP::ActOnOpenMPDeclareTargetName(
23043 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
23044 DeclareTargetContextInfo &DTCI) {
23045 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
23046 isa<FunctionTemplateDecl>(ND)) &&
23047 "Expected variable, function or function template.");
23048
23049 if (auto *VD = dyn_cast<VarDecl>(Val: ND)) {
23050 // Only global variables can be marked as declare target.
23051 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23052 !VD->isStaticDataMember()) {
23053 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
23054 << VD->getNameAsString();
23055 return;
23056 }
23057 }
23058 // Diagnose marking after use as it may lead to incorrect diagnosis and
23059 // codegen.
23060 if (getLangOpts().OpenMP >= 50 &&
23061 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
23062 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
23063
23064 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23065 if (getLangOpts().HIP)
23066 Diag(Loc, diag::warn_hip_omp_target_directives);
23067
23068 // Explicit declare target lists have precedence.
23069 const unsigned Level = -1;
23070
23071 auto *VD = cast<ValueDecl>(Val: ND);
23072 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23073 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23074 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
23075 (*ActiveAttr)->getLevel() == Level) {
23076 Diag(Loc, diag::err_omp_device_type_mismatch)
23077 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
23078 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23079 (*ActiveAttr)->getDevType());
23080 return;
23081 }
23082 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
23083 (*ActiveAttr)->getLevel() == Level) {
23084 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
23085 return;
23086 }
23087
23088 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
23089 return;
23090
23091 Expr *IndirectE = nullptr;
23092 bool IsIndirect = false;
23093 if (DTCI.Indirect) {
23094 IndirectE = *DTCI.Indirect;
23095 if (!IndirectE)
23096 IsIndirect = true;
23097 }
23098 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23099 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
23100 SourceRange(Loc, Loc));
23101 ND->addAttr(A: A);
23102 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
23103 ML->DeclarationMarkedOpenMPDeclareTarget(D: ND, Attr: A);
23104 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
23105 if (auto *VD = dyn_cast<VarDecl>(Val: ND);
23106 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
23107 VD->hasGlobalStorage())
23108 ActOnOpenMPDeclareTargetInitializer(ND);
23109}
23110
23111static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
23112 Sema &SemaRef, Decl *D) {
23113 if (!D || !isa<VarDecl>(Val: D))
23114 return;
23115 auto *VD = cast<VarDecl>(Val: D);
23116 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
23117 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
23118 if (SemaRef.LangOpts.OpenMP >= 50 &&
23119 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23120 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
23121 VD->hasGlobalStorage()) {
23122 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
23123 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
23124 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23125 // If a lambda declaration and definition appears between a
23126 // declare target directive and the matching end declare target
23127 // directive, all variables that are captured by the lambda
23128 // expression must also appear in a to clause.
23129 SemaRef.Diag(VD->getLocation(),
23130 diag::err_omp_lambda_capture_in_declare_target_not_to);
23131 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
23132 << VD << 0 << SR;
23133 return;
23134 }
23135 }
23136 if (MapTy)
23137 return;
23138 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
23139 SemaRef.Diag(SL, diag::note_used_here) << SR;
23140}
23141
23142static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
23143 Sema &SemaRef, DSAStackTy *Stack,
23144 ValueDecl *VD) {
23145 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23146 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
23147 /*FullCheck=*/false);
23148}
23149
23150void SemaOpenMP::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
23151 SourceLocation IdLoc) {
23152 if (!D || D->isInvalidDecl())
23153 return;
23154 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
23155 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
23156 if (auto *VD = dyn_cast<VarDecl>(Val: D)) {
23157 // Only global variables can be marked as declare target.
23158 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23159 !VD->isStaticDataMember())
23160 return;
23161 // 2.10.6: threadprivate variable cannot appear in a declare target
23162 // directive.
23163 if (DSAStack->isThreadPrivate(D: VD)) {
23164 Diag(SL, diag::err_omp_threadprivate_in_target);
23165 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
23166 return;
23167 }
23168 }
23169 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: D))
23170 D = FTD->getTemplatedDecl();
23171 if (auto *FD = dyn_cast<FunctionDecl>(Val: D)) {
23172 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23173 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23174 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23175 Diag(IdLoc, diag::err_omp_function_in_link_clause);
23176 Diag(FD->getLocation(), diag::note_defined_here) << FD;
23177 return;
23178 }
23179 }
23180 if (auto *VD = dyn_cast<ValueDecl>(Val: D)) {
23181 // Problem if any with var declared with incomplete type will be reported
23182 // as normal, so no need to check it here.
23183 if ((E || !VD->getType()->isIncompleteType()) &&
23184 !checkValueDeclInTarget(SL, SR, SemaRef, DSAStack, VD))
23185 return;
23186 if (!E && isInOpenMPDeclareTargetContext()) {
23187 // Checking declaration inside declare target region.
23188 if (isa<VarDecl>(Val: D) || isa<FunctionDecl>(Val: D) ||
23189 isa<FunctionTemplateDecl>(Val: D)) {
23190 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23191 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23192 unsigned Level = DeclareTargetNesting.size();
23193 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23194 return;
23195 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23196 Expr *IndirectE = nullptr;
23197 bool IsIndirect = false;
23198 if (DTCI.Indirect) {
23199 IndirectE = *DTCI.Indirect;
23200 if (!IndirectE)
23201 IsIndirect = true;
23202 }
23203 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23204 getASTContext(),
23205 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23206 : OMPDeclareTargetDeclAttr::MT_To,
23207 DTCI.DT, IndirectE, IsIndirect, Level,
23208 SourceRange(DTCI.Loc, DTCI.Loc));
23209 D->addAttr(A: A);
23210 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
23211 ML->DeclarationMarkedOpenMPDeclareTarget(D, Attr: A);
23212 }
23213 return;
23214 }
23215 }
23216 if (!E)
23217 return;
23218 checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), SemaRef, D);
23219}
23220
23221/// This class visits every VarDecl that the initializer references and adds
23222/// OMPDeclareTargetDeclAttr to each of them.
23223class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
23224 SmallVector<VarDecl *> DeclVector;
23225 Attr *A;
23226
23227public:
23228 /// A StmtVisitor class function that visits all DeclRefExpr and adds
23229 /// OMPDeclareTargetDeclAttr to them.
23230 void VisitDeclRefExpr(DeclRefExpr *Node) {
23231 if (auto *VD = dyn_cast<VarDecl>(Val: Node->getDecl())) {
23232 VD->addAttr(A);
23233 DeclVector.push_back(Elt: VD);
23234 }
23235 }
23236 /// A function that iterates across each of the Expr's children.
23237 void VisitExpr(Expr *Ex) {
23238 for (auto *Child : Ex->children()) {
23239 Visit(Child);
23240 }
23241 }
23242 /// A function that keeps a record of all the Decls that are variables, has
23243 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23244 /// each Decl one at a time and use the inherited 'visit' functions to look
23245 /// for DeclRefExpr.
23246 void declareTargetInitializer(Decl *TD) {
23247 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
23248 DeclVector.push_back(Elt: cast<VarDecl>(Val: TD));
23249 llvm::SmallDenseSet<Decl *> Visited;
23250 while (!DeclVector.empty()) {
23251 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23252 if (!Visited.insert(TargetVarDecl).second)
23253 continue;
23254
23255 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
23256 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
23257 if (Expr *Ex = TargetVarDecl->getInit())
23258 Visit(Ex);
23259 }
23260 }
23261 }
23262};
23263
23264/// Adding OMPDeclareTargetDeclAttr to variables with static storage
23265/// duration that are referenced in the initializer expression list of
23266/// variables with static storage duration in declare target directive.
23267void SemaOpenMP::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) {
23268 GlobalDeclRefChecker Checker;
23269 if (isa<VarDecl>(Val: TargetDecl))
23270 Checker.declareTargetInitializer(TD: TargetDecl);
23271}
23272
23273OMPClause *SemaOpenMP::ActOnOpenMPToClause(
23274 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23275 ArrayRef<SourceLocation> MotionModifiersLoc,
23276 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23277 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23278 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23279 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23280 OMPC_MOTION_MODIFIER_unknown};
23281 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23282
23283 // Process motion-modifiers, flag errors for duplicate modifiers.
23284 unsigned Count = 0;
23285 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23286 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23287 llvm::is_contained(Range&: Modifiers, Element: MotionModifiers[I])) {
23288 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23289 continue;
23290 }
23291 assert(Count < NumberOfOMPMotionModifiers &&
23292 "Modifiers exceed the allowed number of motion modifiers");
23293 Modifiers[Count] = MotionModifiers[I];
23294 ModifiersLoc[Count] = MotionModifiersLoc[I];
23295 ++Count;
23296 }
23297
23298 MappableVarListInfo MVLI(VarList);
23299 checkMappableExpressionList(SemaRef, DSAStack, OMPC_to, MVLI, Locs.StartLoc,
23300 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23301 if (MVLI.ProcessedVarList.empty())
23302 return nullptr;
23303
23304 return OMPToClause::Create(
23305 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23306 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23307 MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()), MapperId);
23308}
23309
23310OMPClause *SemaOpenMP::ActOnOpenMPFromClause(
23311 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23312 ArrayRef<SourceLocation> MotionModifiersLoc,
23313 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23314 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23315 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23316 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23317 OMPC_MOTION_MODIFIER_unknown};
23318 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23319
23320 // Process motion-modifiers, flag errors for duplicate modifiers.
23321 unsigned Count = 0;
23322 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23323 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23324 llvm::is_contained(Range&: Modifiers, Element: MotionModifiers[I])) {
23325 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23326 continue;
23327 }
23328 assert(Count < NumberOfOMPMotionModifiers &&
23329 "Modifiers exceed the allowed number of motion modifiers");
23330 Modifiers[Count] = MotionModifiers[I];
23331 ModifiersLoc[Count] = MotionModifiersLoc[I];
23332 ++Count;
23333 }
23334
23335 MappableVarListInfo MVLI(VarList);
23336 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
23337 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23338 if (MVLI.ProcessedVarList.empty())
23339 return nullptr;
23340
23341 return OMPFromClause::Create(
23342 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23343 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23344 MapperIdScopeSpec.getWithLocInContext(Context&: getASTContext()), MapperId);
23345}
23346
23347OMPClause *
23348SemaOpenMP::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
23349 const OMPVarListLocTy &Locs) {
23350 MappableVarListInfo MVLI(VarList);
23351 SmallVector<Expr *, 8> PrivateCopies;
23352 SmallVector<Expr *, 8> Inits;
23353
23354 for (Expr *RefExpr : VarList) {
23355 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
23356 SourceLocation ELoc;
23357 SourceRange ERange;
23358 Expr *SimpleRefExpr = RefExpr;
23359 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
23360 if (Res.second) {
23361 // It will be analyzed later.
23362 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
23363 PrivateCopies.push_back(Elt: nullptr);
23364 Inits.push_back(Elt: nullptr);
23365 }
23366 ValueDecl *D = Res.first;
23367 if (!D)
23368 continue;
23369
23370 QualType Type = D->getType();
23371 Type = Type.getNonReferenceType().getUnqualifiedType();
23372
23373 auto *VD = dyn_cast<VarDecl>(Val: D);
23374
23375 // Item should be a pointer or reference to pointer.
23376 if (!Type->isPointerType()) {
23377 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23378 << 0 << RefExpr->getSourceRange();
23379 continue;
23380 }
23381
23382 // Build the private variable and the expression that refers to it.
23383 auto VDPrivate =
23384 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
23385 D->hasAttrs() ? &D->getAttrs() : nullptr,
23386 VD ? cast<DeclRefExpr>(Val: SimpleRefExpr) : nullptr);
23387 if (VDPrivate->isInvalidDecl())
23388 continue;
23389
23390 SemaRef.CurContext->addDecl(D: VDPrivate);
23391 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
23392 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23393
23394 // Add temporary variable to initialize the private copy of the pointer.
23395 VarDecl *VDInit =
23396 buildVarDecl(SemaRef, Loc: RefExpr->getExprLoc(), Type, Name: ".devptr.temp");
23397 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
23398 S&: SemaRef, D: VDInit, Ty: RefExpr->getType(), Loc: RefExpr->getExprLoc());
23399 SemaRef.AddInitializerToDecl(
23400 dcl: VDPrivate, init: SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
23401 /*DirectInit=*/false);
23402
23403 // If required, build a capture to implement the privatization initialized
23404 // with the current list item value.
23405 DeclRefExpr *Ref = nullptr;
23406 if (!VD)
23407 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
23408 MVLI.ProcessedVarList.push_back(Elt: VD ? RefExpr->IgnoreParens() : Ref);
23409 PrivateCopies.push_back(VDPrivateRefExpr);
23410 Inits.push_back(VDInitRefExpr);
23411
23412 // We need to add a data sharing attribute for this variable to make sure it
23413 // is correctly captured. A variable that shows up in a use_device_ptr has
23414 // similar properties of a first private variable.
23415 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23416
23417 // Create a mappable component for the list item. List items in this clause
23418 // only need a component.
23419 MVLI.VarBaseDeclarations.push_back(Elt: D);
23420 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
23421 MVLI.VarComponents.back().emplace_back(Args&: SimpleRefExpr, Args&: D,
23422 /*IsNonContiguous=*/Args: false);
23423 }
23424
23425 if (MVLI.ProcessedVarList.empty())
23426 return nullptr;
23427
23428 return OMPUseDevicePtrClause::Create(
23429 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
23430 MVLI.VarBaseDeclarations, MVLI.VarComponents);
23431}
23432
23433OMPClause *
23434SemaOpenMP::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
23435 const OMPVarListLocTy &Locs) {
23436 MappableVarListInfo MVLI(VarList);
23437
23438 for (Expr *RefExpr : VarList) {
23439 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
23440 SourceLocation ELoc;
23441 SourceRange ERange;
23442 Expr *SimpleRefExpr = RefExpr;
23443 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
23444 /*AllowArraySection=*/true);
23445 if (Res.second) {
23446 // It will be analyzed later.
23447 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
23448 }
23449 ValueDecl *D = Res.first;
23450 if (!D)
23451 continue;
23452 auto *VD = dyn_cast<VarDecl>(Val: D);
23453
23454 // If required, build a capture to implement the privatization initialized
23455 // with the current list item value.
23456 DeclRefExpr *Ref = nullptr;
23457 if (!VD)
23458 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
23459 MVLI.ProcessedVarList.push_back(Elt: VD ? RefExpr->IgnoreParens() : Ref);
23460
23461 // We need to add a data sharing attribute for this variable to make sure it
23462 // is correctly captured. A variable that shows up in a use_device_addr has
23463 // similar properties of a first private variable.
23464 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23465
23466 // Create a mappable component for the list item. List items in this clause
23467 // only need a component.
23468 MVLI.VarBaseDeclarations.push_back(Elt: D);
23469 MVLI.VarComponents.emplace_back();
23470 Expr *Component = SimpleRefExpr;
23471 if (VD && (isa<ArraySectionExpr>(Val: RefExpr->IgnoreParenImpCasts()) ||
23472 isa<ArraySubscriptExpr>(Val: RefExpr->IgnoreParenImpCasts())))
23473 Component =
23474 SemaRef.DefaultFunctionArrayLvalueConversion(E: SimpleRefExpr).get();
23475 MVLI.VarComponents.back().emplace_back(Args&: Component, Args&: D,
23476 /*IsNonContiguous=*/Args: false);
23477 }
23478
23479 if (MVLI.ProcessedVarList.empty())
23480 return nullptr;
23481
23482 return OMPUseDeviceAddrClause::Create(
23483 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23484 MVLI.VarComponents);
23485}
23486
23487OMPClause *
23488SemaOpenMP::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
23489 const OMPVarListLocTy &Locs) {
23490 MappableVarListInfo MVLI(VarList);
23491 for (Expr *RefExpr : VarList) {
23492 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
23493 SourceLocation ELoc;
23494 SourceRange ERange;
23495 Expr *SimpleRefExpr = RefExpr;
23496 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
23497 if (Res.second) {
23498 // It will be analyzed later.
23499 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
23500 }
23501 ValueDecl *D = Res.first;
23502 if (!D)
23503 continue;
23504
23505 QualType Type = D->getType();
23506 // item should be a pointer or array or reference to pointer or array
23507 if (!Type.getNonReferenceType()->isPointerType() &&
23508 !Type.getNonReferenceType()->isArrayType()) {
23509 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23510 << 0 << RefExpr->getSourceRange();
23511 continue;
23512 }
23513
23514 // Check if the declaration in the clause does not show up in any data
23515 // sharing attribute.
23516 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23517 if (isOpenMPPrivate(DVar.CKind)) {
23518 unsigned OMPVersion = getLangOpts().OpenMP;
23519 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23520 << getOpenMPClauseNameForDiag(DVar.CKind)
23521 << getOpenMPClauseNameForDiag(OMPC_is_device_ptr)
23522 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
23523 OMPVersion);
23524 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
23525 continue;
23526 }
23527
23528 const Expr *ConflictExpr;
23529 if (DSAStack->checkMappableExprComponentListsForDecl(
23530 VD: D, /*CurrentRegionOnly=*/true,
23531 Check: [&ConflictExpr](
23532 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23533 OpenMPClauseKind) -> bool {
23534 ConflictExpr = R.front().getAssociatedExpression();
23535 return true;
23536 })) {
23537 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23538 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23539 << ConflictExpr->getSourceRange();
23540 continue;
23541 }
23542
23543 // Store the components in the stack so that they can be used to check
23544 // against other clauses later on.
23545 OMPClauseMappableExprCommon::MappableComponent MC(
23546 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23547 DSAStack->addMappableExpressionComponents(
23548 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23549
23550 // Record the expression we've just processed.
23551 MVLI.ProcessedVarList.push_back(Elt: SimpleRefExpr);
23552
23553 // Create a mappable component for the list item. List items in this clause
23554 // only need a component. We use a null declaration to signal fields in
23555 // 'this'.
23556 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23557 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23558 "Unexpected device pointer expression!");
23559 MVLI.VarBaseDeclarations.push_back(
23560 Elt: isa<DeclRefExpr>(Val: SimpleRefExpr) ? D : nullptr);
23561 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
23562 MVLI.VarComponents.back().push_back(Elt: MC);
23563 }
23564
23565 if (MVLI.ProcessedVarList.empty())
23566 return nullptr;
23567
23568 return OMPIsDevicePtrClause::Create(
23569 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23570 MVLI.VarComponents);
23571}
23572
23573OMPClause *
23574SemaOpenMP::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
23575 const OMPVarListLocTy &Locs) {
23576 MappableVarListInfo MVLI(VarList);
23577 for (Expr *RefExpr : VarList) {
23578 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23579 SourceLocation ELoc;
23580 SourceRange ERange;
23581 Expr *SimpleRefExpr = RefExpr;
23582 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
23583 /*AllowArraySection=*/true);
23584 if (Res.second) {
23585 // It will be analyzed later.
23586 MVLI.ProcessedVarList.push_back(Elt: RefExpr);
23587 }
23588 ValueDecl *D = Res.first;
23589 if (!D)
23590 continue;
23591
23592 // Check if the declaration in the clause does not show up in any data
23593 // sharing attribute.
23594 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23595 if (isOpenMPPrivate(DVar.CKind)) {
23596 unsigned OMPVersion = getLangOpts().OpenMP;
23597 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23598 << getOpenMPClauseNameForDiag(DVar.CKind)
23599 << getOpenMPClauseNameForDiag(OMPC_has_device_addr)
23600 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
23601 OMPVersion);
23602 reportOriginalDsa(SemaRef, DSAStack, D, DVar);
23603 continue;
23604 }
23605
23606 const Expr *ConflictExpr;
23607 if (DSAStack->checkMappableExprComponentListsForDecl(
23608 VD: D, /*CurrentRegionOnly=*/true,
23609 Check: [&ConflictExpr](
23610 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23611 OpenMPClauseKind) -> bool {
23612 ConflictExpr = R.front().getAssociatedExpression();
23613 return true;
23614 })) {
23615 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23616 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23617 << ConflictExpr->getSourceRange();
23618 continue;
23619 }
23620
23621 // Store the components in the stack so that they can be used to check
23622 // against other clauses later on.
23623 Expr *Component = SimpleRefExpr;
23624 auto *VD = dyn_cast<VarDecl>(Val: D);
23625 if (VD && (isa<ArraySectionExpr>(Val: RefExpr->IgnoreParenImpCasts()) ||
23626 isa<ArraySubscriptExpr>(Val: RefExpr->IgnoreParenImpCasts())))
23627 Component =
23628 SemaRef.DefaultFunctionArrayLvalueConversion(E: SimpleRefExpr).get();
23629 OMPClauseMappableExprCommon::MappableComponent MC(
23630 Component, D, /*IsNonContiguous=*/false);
23631 DSAStack->addMappableExpressionComponents(
23632 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23633
23634 // Record the expression we've just processed.
23635 if (!VD && !SemaRef.CurContext->isDependentContext()) {
23636 DeclRefExpr *Ref =
23637 buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/true);
23638 assert(Ref && "has_device_addr capture failed");
23639 MVLI.ProcessedVarList.push_back(Ref);
23640 } else
23641 MVLI.ProcessedVarList.push_back(Elt: RefExpr->IgnoreParens());
23642
23643 // Create a mappable component for the list item. List items in this clause
23644 // only need a component. We use a null declaration to signal fields in
23645 // 'this'.
23646 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23647 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23648 "Unexpected device pointer expression!");
23649 MVLI.VarBaseDeclarations.push_back(
23650 Elt: isa<DeclRefExpr>(Val: SimpleRefExpr) ? D : nullptr);
23651 MVLI.VarComponents.resize(N: MVLI.VarComponents.size() + 1);
23652 MVLI.VarComponents.back().push_back(Elt: MC);
23653 }
23654
23655 if (MVLI.ProcessedVarList.empty())
23656 return nullptr;
23657
23658 return OMPHasDeviceAddrClause::Create(
23659 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23660 MVLI.VarComponents);
23661}
23662
23663OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause(
23664 Expr *Allocator, Expr *Alignment,
23665 OpenMPAllocateClauseModifier FirstAllocateModifier,
23666 SourceLocation FirstAllocateModifierLoc,
23667 OpenMPAllocateClauseModifier SecondAllocateModifier,
23668 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
23669 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23670 SourceLocation EndLoc) {
23671 if (Allocator) {
23672 // Allocator expression is dependent - skip it for now and build the
23673 // allocator when instantiated.
23674 bool AllocDependent =
23675 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
23676 Allocator->isInstantiationDependent() ||
23677 Allocator->containsUnexpandedParameterPack());
23678 if (!AllocDependent) {
23679 // OpenMP [2.11.4 allocate Clause, Description]
23680 // allocator is an expression of omp_allocator_handle_t type.
23681 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: Allocator->getExprLoc(), DSAStack))
23682 return nullptr;
23683
23684 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(E: Allocator);
23685 if (AllocatorRes.isInvalid())
23686 return nullptr;
23687 AllocatorRes = SemaRef.PerformImplicitConversion(
23688 From: AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
23689 Action: AssignmentAction::Initializing,
23690 /*AllowExplicit=*/true);
23691 if (AllocatorRes.isInvalid())
23692 return nullptr;
23693 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
23694 }
23695 } else {
23696 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23697 // allocate clauses that appear on a target construct or on constructs in a
23698 // target region must specify an allocator expression unless a requires
23699 // directive with the dynamic_allocators clause is present in the same
23700 // compilation unit.
23701 if (getLangOpts().OpenMPIsTargetDevice &&
23702 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23703 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
23704 }
23705 if (Alignment) {
23706 bool AlignmentDependent = Alignment->isTypeDependent() ||
23707 Alignment->isValueDependent() ||
23708 Alignment->isInstantiationDependent() ||
23709 Alignment->containsUnexpandedParameterPack();
23710 if (!AlignmentDependent) {
23711 ExprResult AlignResult =
23712 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
23713 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
23714 }
23715 }
23716 // Analyze and build list of variables.
23717 SmallVector<Expr *, 8> Vars;
23718 for (Expr *RefExpr : VarList) {
23719 assert(RefExpr && "NULL expr in OpenMP private clause.");
23720 SourceLocation ELoc;
23721 SourceRange ERange;
23722 Expr *SimpleRefExpr = RefExpr;
23723 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
23724 if (Res.second) {
23725 // It will be analyzed later.
23726 Vars.push_back(Elt: RefExpr);
23727 }
23728 ValueDecl *D = Res.first;
23729 if (!D)
23730 continue;
23731
23732 auto *VD = dyn_cast<VarDecl>(Val: D);
23733 DeclRefExpr *Ref = nullptr;
23734 if (!VD && !SemaRef.CurContext->isDependentContext())
23735 Ref = buildCapture(S&: SemaRef, D, CaptureExpr: SimpleRefExpr, /*WithInit=*/false);
23736 Vars.push_back(Elt: (VD || SemaRef.CurContext->isDependentContext())
23737 ? RefExpr->IgnoreParens()
23738 : Ref);
23739 }
23740
23741 if (Vars.empty())
23742 return nullptr;
23743
23744 if (Allocator)
23745 DSAStack->addInnerAllocatorExpr(E: Allocator);
23746
23747 return OMPAllocateClause::Create(
23748 C: getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
23749 Modifier1: FirstAllocateModifier, Modifier1Loc: FirstAllocateModifierLoc, Modifier2: SecondAllocateModifier,
23750 Modifier2Loc: SecondAllocateModifierLoc, EndLoc, VL: Vars);
23751}
23752
23753OMPClause *SemaOpenMP::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
23754 SourceLocation StartLoc,
23755 SourceLocation LParenLoc,
23756 SourceLocation EndLoc) {
23757 SmallVector<Expr *, 8> Vars;
23758 for (Expr *RefExpr : VarList) {
23759 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23760 SourceLocation ELoc;
23761 SourceRange ERange;
23762 Expr *SimpleRefExpr = RefExpr;
23763 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange);
23764 if (Res.second)
23765 // It will be analyzed later.
23766 Vars.push_back(Elt: RefExpr);
23767 ValueDecl *D = Res.first;
23768 if (!D)
23769 continue;
23770
23771 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23772 // A list-item cannot appear in more than one nontemporal clause.
23773 if (const Expr *PrevRef =
23774 DSAStack->addUniqueNontemporal(D, NewDE: SimpleRefExpr)) {
23775 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23776 << 0 << getOpenMPClauseNameForDiag(OMPC_nontemporal) << ERange;
23777 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23778 << getOpenMPClauseNameForDiag(OMPC_nontemporal);
23779 continue;
23780 }
23781
23782 Vars.push_back(Elt: RefExpr);
23783 }
23784
23785 if (Vars.empty())
23786 return nullptr;
23787
23788 return OMPNontemporalClause::Create(C: getASTContext(), StartLoc, LParenLoc,
23789 EndLoc, VL: Vars);
23790}
23791
23792StmtResult SemaOpenMP::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
23793 Stmt *AStmt,
23794 SourceLocation StartLoc,
23795 SourceLocation EndLoc) {
23796 if (!AStmt)
23797 return StmtError();
23798
23799 SemaRef.setFunctionHasBranchProtectedScope();
23800
23801 return OMPScopeDirective::Create(C: getASTContext(), StartLoc, EndLoc, Clauses,
23802 AssociatedStmt: AStmt);
23803}
23804
23805OMPClause *SemaOpenMP::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
23806 SourceLocation StartLoc,
23807 SourceLocation LParenLoc,
23808 SourceLocation EndLoc) {
23809 SmallVector<Expr *, 8> Vars;
23810 for (Expr *RefExpr : VarList) {
23811 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23812 SourceLocation ELoc;
23813 SourceRange ERange;
23814 Expr *SimpleRefExpr = RefExpr;
23815 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
23816 /*AllowArraySection=*/true);
23817 if (Res.second)
23818 // It will be analyzed later.
23819 Vars.push_back(Elt: RefExpr);
23820 ValueDecl *D = Res.first;
23821 if (!D)
23822 continue;
23823
23824 const DSAStackTy::DSAVarData DVar =
23825 DSAStack->getTopDSA(D, /*FromParent=*/true);
23826 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23827 // A list item that appears in the inclusive or exclusive clause must appear
23828 // in a reduction clause with the inscan modifier on the enclosing
23829 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23830 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23831 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23832 << RefExpr->getSourceRange();
23833
23834 if (DSAStack->getParentDirective() != OMPD_unknown)
23835 DSAStack->markDeclAsUsedInScanDirective(D);
23836 Vars.push_back(Elt: RefExpr);
23837 }
23838
23839 if (Vars.empty())
23840 return nullptr;
23841
23842 return OMPInclusiveClause::Create(C: getASTContext(), StartLoc, LParenLoc,
23843 EndLoc, VL: Vars);
23844}
23845
23846OMPClause *SemaOpenMP::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
23847 SourceLocation StartLoc,
23848 SourceLocation LParenLoc,
23849 SourceLocation EndLoc) {
23850 SmallVector<Expr *, 8> Vars;
23851 for (Expr *RefExpr : VarList) {
23852 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23853 SourceLocation ELoc;
23854 SourceRange ERange;
23855 Expr *SimpleRefExpr = RefExpr;
23856 auto Res = getPrivateItem(S&: SemaRef, RefExpr&: SimpleRefExpr, ELoc, ERange,
23857 /*AllowArraySection=*/true);
23858 if (Res.second)
23859 // It will be analyzed later.
23860 Vars.push_back(Elt: RefExpr);
23861 ValueDecl *D = Res.first;
23862 if (!D)
23863 continue;
23864
23865 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
23866 DSAStackTy::DSAVarData DVar;
23867 if (ParentDirective != OMPD_unknown)
23868 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
23869 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23870 // A list item that appears in the inclusive or exclusive clause must appear
23871 // in a reduction clause with the inscan modifier on the enclosing
23872 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23873 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23874 DVar.Modifier != OMPC_REDUCTION_inscan) {
23875 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23876 << RefExpr->getSourceRange();
23877 } else {
23878 DSAStack->markDeclAsUsedInScanDirective(D);
23879 }
23880 Vars.push_back(Elt: RefExpr);
23881 }
23882
23883 if (Vars.empty())
23884 return nullptr;
23885
23886 return OMPExclusiveClause::Create(C: getASTContext(), StartLoc, LParenLoc,
23887 EndLoc, VL: Vars);
23888}
23889
23890/// Tries to find omp_alloctrait_t type.
23891static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
23892 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23893 if (!OMPAlloctraitT.isNull())
23894 return true;
23895 IdentifierInfo &II = S.PP.getIdentifierTable().get(Name: "omp_alloctrait_t");
23896 ParsedType PT = S.getTypeName(II, NameLoc: Loc, S: S.getCurScope());
23897 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23898 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
23899 return false;
23900 }
23901 Stack->setOMPAlloctraitT(PT.get());
23902 return true;
23903}
23904
23905OMPClause *SemaOpenMP::ActOnOpenMPUsesAllocatorClause(
23906 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
23907 ArrayRef<UsesAllocatorsData> Data) {
23908 ASTContext &Context = getASTContext();
23909 // OpenMP [2.12.5, target Construct]
23910 // allocator is an identifier of omp_allocator_handle_t type.
23911 if (!findOMPAllocatorHandleT(S&: SemaRef, Loc: StartLoc, DSAStack))
23912 return nullptr;
23913 // OpenMP [2.12.5, target Construct]
23914 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
23915 if (llvm::any_of(
23916 Range&: Data,
23917 P: [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
23918 !findOMPAlloctraitT(S&: SemaRef, Loc: StartLoc, DSAStack))
23919 return nullptr;
23920 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
23921 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23922 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
23923 StringRef Allocator =
23924 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23925 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
23926 PredefinedAllocators.insert(SemaRef.LookupSingleName(
23927 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
23928 }
23929
23930 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
23931 for (const UsesAllocatorsData &D : Data) {
23932 Expr *AllocatorExpr = nullptr;
23933 // Check allocator expression.
23934 if (D.Allocator->isTypeDependent()) {
23935 AllocatorExpr = D.Allocator;
23936 } else {
23937 // Traits were specified - need to assign new allocator to the specified
23938 // allocator, so it must be an lvalue.
23939 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
23940 auto *DRE = dyn_cast<DeclRefExpr>(Val: AllocatorExpr);
23941 bool IsPredefinedAllocator = false;
23942 if (DRE) {
23943 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23944 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
23945 IsPredefinedAllocator =
23946 AllocatorTy !=
23947 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23948 }
23949 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
23950 QualType AllocatorExprType = AllocatorExpr->getType();
23951 bool IsTypeCompatible = IsPredefinedAllocator;
23952 IsTypeCompatible = IsTypeCompatible ||
23953 Context.hasSameUnqualifiedType(T1: AllocatorExprType,
23954 T2: OMPAllocatorHandleT);
23955 IsTypeCompatible =
23956 IsTypeCompatible ||
23957 Context.typesAreCompatible(T1: AllocatorExprType, T2: OMPAllocatorHandleT);
23958 bool IsNonConstantLValue =
23959 !AllocatorExprType.isConstant(Ctx: Context) && AllocatorExpr->isLValue();
23960 if (!DRE || !IsTypeCompatible ||
23961 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23962 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23963 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
23964 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
23965 continue;
23966 }
23967 // OpenMP [2.12.5, target Construct]
23968 // Predefined allocators appearing in a uses_allocators clause cannot have
23969 // traits specified.
23970 if (IsPredefinedAllocator && D.AllocatorTraits) {
23971 Diag(D.AllocatorTraits->getExprLoc(),
23972 diag::err_omp_predefined_allocator_with_traits)
23973 << D.AllocatorTraits->getSourceRange();
23974 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23975 << cast<NamedDecl>(DRE->getDecl())->getName()
23976 << D.Allocator->getSourceRange();
23977 continue;
23978 }
23979 // OpenMP [2.12.5, target Construct]
23980 // Non-predefined allocators appearing in a uses_allocators clause must
23981 // have traits specified.
23982 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
23983 Diag(D.Allocator->getExprLoc(),
23984 diag::err_omp_nonpredefined_allocator_without_traits);
23985 continue;
23986 }
23987 // No allocator traits - just convert it to rvalue.
23988 if (!D.AllocatorTraits)
23989 AllocatorExpr = SemaRef.DefaultLvalueConversion(E: AllocatorExpr).get();
23990 DSAStack->addUsesAllocatorsDecl(
23991 DRE->getDecl(),
23992 IsPredefinedAllocator
23993 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23994 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23995 }
23996 Expr *AllocatorTraitsExpr = nullptr;
23997 if (D.AllocatorTraits) {
23998 if (D.AllocatorTraits->isTypeDependent()) {
23999 AllocatorTraitsExpr = D.AllocatorTraits;
24000 } else {
24001 // OpenMP [2.12.5, target Construct]
24002 // Arrays that contain allocator traits that appear in a uses_allocators
24003 // clause must be constant arrays, have constant values and be defined
24004 // in the same scope as the construct in which the clause appears.
24005 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
24006 // Check that traits expr is a constant array.
24007 QualType TraitTy;
24008 if (const ArrayType *Ty =
24009 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
24010 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
24011 TraitTy = ConstArrayTy->getElementType();
24012 if (TraitTy.isNull() ||
24013 !(Context.hasSameUnqualifiedType(T1: TraitTy,
24014 DSAStack->getOMPAlloctraitT()) ||
24015 Context.typesAreCompatible(T1: TraitTy, DSAStack->getOMPAlloctraitT(),
24016 /*CompareUnqualified=*/true))) {
24017 Diag(D.AllocatorTraits->getExprLoc(),
24018 diag::err_omp_expected_array_alloctraits)
24019 << AllocatorTraitsExpr->getType();
24020 continue;
24021 }
24022 // Do not map by default allocator traits if it is a standalone
24023 // variable.
24024 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: AllocatorTraitsExpr))
24025 DSAStack->addUsesAllocatorsDecl(
24026 DRE->getDecl(),
24027 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
24028 }
24029 }
24030 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
24031 NewD.Allocator = AllocatorExpr;
24032 NewD.AllocatorTraits = AllocatorTraitsExpr;
24033 NewD.LParenLoc = D.LParenLoc;
24034 NewD.RParenLoc = D.RParenLoc;
24035 }
24036 return OMPUsesAllocatorsClause::Create(C: getASTContext(), StartLoc, LParenLoc,
24037 EndLoc, Data: NewData);
24038}
24039
24040OMPClause *SemaOpenMP::ActOnOpenMPAffinityClause(
24041 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24042 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
24043 SmallVector<Expr *, 8> Vars;
24044 for (Expr *RefExpr : Locators) {
24045 assert(RefExpr && "NULL expr in OpenMP shared clause.");
24046 if (isa<DependentScopeDeclRefExpr>(Val: RefExpr) || RefExpr->isTypeDependent()) {
24047 // It will be analyzed later.
24048 Vars.push_back(Elt: RefExpr);
24049 continue;
24050 }
24051
24052 SourceLocation ELoc = RefExpr->getExprLoc();
24053 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
24054
24055 if (!SimpleExpr->isLValue()) {
24056 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24057 << 1 << 0 << RefExpr->getSourceRange();
24058 continue;
24059 }
24060
24061 ExprResult Res;
24062 {
24063 Sema::TentativeAnalysisScope Trap(SemaRef);
24064 Res = SemaRef.CreateBuiltinUnaryOp(OpLoc: ELoc, Opc: UO_AddrOf, InputExpr: SimpleExpr);
24065 }
24066 if (!Res.isUsable() && !isa<ArraySectionExpr>(Val: SimpleExpr) &&
24067 !isa<OMPArrayShapingExpr>(Val: SimpleExpr)) {
24068 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24069 << 1 << 0 << RefExpr->getSourceRange();
24070 continue;
24071 }
24072 Vars.push_back(Elt: SimpleExpr);
24073 }
24074
24075 return OMPAffinityClause::Create(C: getASTContext(), StartLoc, LParenLoc,
24076 ColonLoc, EndLoc, Modifier, Locators: Vars);
24077}
24078
24079OMPClause *SemaOpenMP::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
24080 SourceLocation KindLoc,
24081 SourceLocation StartLoc,
24082 SourceLocation LParenLoc,
24083 SourceLocation EndLoc) {
24084 if (Kind == OMPC_BIND_unknown) {
24085 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24086 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
24087 /*Last=*/unsigned(OMPC_BIND_unknown))
24088 << getOpenMPClauseNameForDiag(OMPC_bind);
24089 return nullptr;
24090 }
24091
24092 return OMPBindClause::Create(C: getASTContext(), K: Kind, KLoc: KindLoc, StartLoc,
24093 LParenLoc, EndLoc);
24094}
24095
24096OMPClause *SemaOpenMP::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
24097 SourceLocation StartLoc,
24098 SourceLocation LParenLoc,
24099 SourceLocation EndLoc) {
24100 Expr *ValExpr = Size;
24101 Stmt *HelperValStmt = nullptr;
24102
24103 // OpenMP [2.5, Restrictions]
24104 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24105 // value.
24106 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
24107 /*StrictlyPositive=*/false))
24108 return nullptr;
24109
24110 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24111 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
24112 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
24113 if (CaptureRegion != OMPD_unknown &&
24114 !SemaRef.CurContext->isDependentContext()) {
24115 ValExpr = SemaRef.MakeFullExpr(Arg: ValExpr).get();
24116 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24117 ValExpr = tryBuildCapture(SemaRef, Capture: ValExpr, Captures).get();
24118 HelperValStmt = buildPreInits(getASTContext(), Captures);
24119 }
24120
24121 return new (getASTContext()) OMPXDynCGroupMemClause(
24122 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24123}
24124
24125OMPClause *SemaOpenMP::ActOnOpenMPDoacrossClause(
24126 OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
24127 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
24128 SourceLocation LParenLoc, SourceLocation EndLoc) {
24129
24130 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
24131 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
24132 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
24133 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
24134 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24135 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_doacross);
24136 return nullptr;
24137 }
24138
24139 SmallVector<Expr *, 8> Vars;
24140 DSAStackTy::OperatorOffsetTy OpsOffs;
24141 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
24142 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
24143 SemaRef,
24144 IsSource: DepType == OMPC_DOACROSS_source ||
24145 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
24146 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
24147 VarList, DSAStack, EndLoc);
24148 Vars = VarOffset.Vars;
24149 OpsOffs = VarOffset.OpsOffs;
24150 TotalDepCount = VarOffset.TotalDepCount;
24151 auto *C = OMPDoacrossClause::Create(C: getASTContext(), StartLoc, LParenLoc,
24152 EndLoc, DepType, DepLoc, ColonLoc, VL: Vars,
24153 NumLoops: TotalDepCount.getZExtValue());
24154 if (DSAStack->isParentOrderedRegion())
24155 DSAStack->addDoacrossDependClause(C: C, OpsOffs);
24156 return C;
24157}
24158
24159OMPClause *SemaOpenMP::ActOnOpenMPXAttributeClause(ArrayRef<const Attr *> Attrs,
24160 SourceLocation StartLoc,
24161 SourceLocation LParenLoc,
24162 SourceLocation EndLoc) {
24163 return new (getASTContext())
24164 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
24165}
24166
24167OMPClause *SemaOpenMP::ActOnOpenMPXBareClause(SourceLocation StartLoc,
24168 SourceLocation EndLoc) {
24169 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
24170}
24171
24172OMPClause *SemaOpenMP::ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc,
24173 SourceLocation LParenLoc,
24174 SourceLocation EndLoc) {
24175 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
24176}
24177
24178OMPClause *SemaOpenMP::ActOnOpenMPDirectivePresenceClause(
24179 OpenMPClauseKind CK, llvm::ArrayRef<OpenMPDirectiveKind> DKVec,
24180 SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc) {
24181 switch (CK) {
24182 case OMPC_absent:
24183 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
24184 case OMPC_contains:
24185 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
24186 default:
24187 llvm_unreachable("Unexpected OpenMP clause");
24188 }
24189}
24190
24191OMPClause *SemaOpenMP::ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK,
24192 SourceLocation Loc,
24193 SourceLocation RLoc) {
24194 switch (CK) {
24195 case OMPC_no_openmp:
24196 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
24197 case OMPC_no_openmp_routines:
24198 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
24199 case OMPC_no_parallelism:
24200 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
24201 case OMPC_no_openmp_constructs:
24202 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
24203 default:
24204 llvm_unreachable("Unexpected OpenMP clause");
24205 }
24206}
24207
24208ExprResult SemaOpenMP::ActOnOMPArraySectionExpr(
24209 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
24210 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
24211 Expr *Stride, SourceLocation RBLoc) {
24212 ASTContext &Context = getASTContext();
24213 if (Base->hasPlaceholderType() &&
24214 !Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
24215 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base);
24216 if (Result.isInvalid())
24217 return ExprError();
24218 Base = Result.get();
24219 }
24220 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
24221 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: LowerBound);
24222 if (Result.isInvalid())
24223 return ExprError();
24224 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
24225 if (Result.isInvalid())
24226 return ExprError();
24227 LowerBound = Result.get();
24228 }
24229 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
24230 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Length);
24231 if (Result.isInvalid())
24232 return ExprError();
24233 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
24234 if (Result.isInvalid())
24235 return ExprError();
24236 Length = Result.get();
24237 }
24238 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
24239 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Stride);
24240 if (Result.isInvalid())
24241 return ExprError();
24242 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
24243 if (Result.isInvalid())
24244 return ExprError();
24245 Stride = Result.get();
24246 }
24247
24248 // Build an unanalyzed expression if either operand is type-dependent.
24249 if (Base->isTypeDependent() ||
24250 (LowerBound &&
24251 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
24252 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
24253 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
24254 return new (Context) ArraySectionExpr(
24255 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
24256 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24257 }
24258
24259 // Perform default conversions.
24260 QualType OriginalTy = ArraySectionExpr::getBaseOriginalType(Base);
24261 QualType ResultTy;
24262 if (OriginalTy->isAnyPointerType()) {
24263 ResultTy = OriginalTy->getPointeeType();
24264 } else if (OriginalTy->isArrayType()) {
24265 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
24266 } else {
24267 return ExprError(
24268 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
24269 << Base->getSourceRange());
24270 }
24271 // C99 6.5.2.1p1
24272 if (LowerBound) {
24273 auto Res = PerformOpenMPImplicitIntegerConversion(Loc: LowerBound->getExprLoc(),
24274 Op: LowerBound);
24275 if (Res.isInvalid())
24276 return ExprError(Diag(LowerBound->getExprLoc(),
24277 diag::err_omp_typecheck_section_not_integer)
24278 << 0 << LowerBound->getSourceRange());
24279 LowerBound = Res.get();
24280
24281 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24282 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24283 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
24284 << 0 << LowerBound->getSourceRange();
24285 }
24286 if (Length) {
24287 auto Res =
24288 PerformOpenMPImplicitIntegerConversion(Loc: Length->getExprLoc(), Op: Length);
24289 if (Res.isInvalid())
24290 return ExprError(Diag(Length->getExprLoc(),
24291 diag::err_omp_typecheck_section_not_integer)
24292 << 1 << Length->getSourceRange());
24293 Length = Res.get();
24294
24295 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24296 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24297 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
24298 << 1 << Length->getSourceRange();
24299 }
24300 if (Stride) {
24301 ExprResult Res =
24302 PerformOpenMPImplicitIntegerConversion(Loc: Stride->getExprLoc(), Op: Stride);
24303 if (Res.isInvalid())
24304 return ExprError(Diag(Stride->getExprLoc(),
24305 diag::err_omp_typecheck_section_not_integer)
24306 << 1 << Stride->getSourceRange());
24307 Stride = Res.get();
24308
24309 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24310 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24311 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
24312 << 1 << Stride->getSourceRange();
24313 }
24314
24315 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
24316 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
24317 // type. Note that functions are not objects, and that (in C99 parlance)
24318 // incomplete types are not object types.
24319 if (ResultTy->isFunctionType()) {
24320 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
24321 << ResultTy << Base->getSourceRange();
24322 return ExprError();
24323 }
24324
24325 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
24326 diag::err_omp_section_incomplete_type, Base))
24327 return ExprError();
24328
24329 if (LowerBound && !OriginalTy->isAnyPointerType()) {
24330 Expr::EvalResult Result;
24331 if (LowerBound->EvaluateAsInt(Result, Ctx: Context)) {
24332 // OpenMP 5.0, [2.1.5 Array Sections]
24333 // The array section must be a subset of the original array.
24334 llvm::APSInt LowerBoundValue = Result.Val.getInt();
24335 if (LowerBoundValue.isNegative()) {
24336 Diag(LowerBound->getExprLoc(),
24337 diag::err_omp_section_not_subset_of_array)
24338 << LowerBound->getSourceRange();
24339 return ExprError();
24340 }
24341 }
24342 }
24343
24344 if (Length) {
24345 Expr::EvalResult Result;
24346 if (Length->EvaluateAsInt(Result, Ctx: Context)) {
24347 // OpenMP 5.0, [2.1.5 Array Sections]
24348 // The length must evaluate to non-negative integers.
24349 llvm::APSInt LengthValue = Result.Val.getInt();
24350 if (LengthValue.isNegative()) {
24351 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
24352 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
24353 << Length->getSourceRange();
24354 return ExprError();
24355 }
24356 }
24357 } else if (ColonLocFirst.isValid() &&
24358 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
24359 !OriginalTy->isVariableArrayType()))) {
24360 // OpenMP 5.0, [2.1.5 Array Sections]
24361 // When the size of the array dimension is not known, the length must be
24362 // specified explicitly.
24363 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
24364 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
24365 return ExprError();
24366 }
24367
24368 if (Stride) {
24369 Expr::EvalResult Result;
24370 if (Stride->EvaluateAsInt(Result, Ctx: Context)) {
24371 // OpenMP 5.0, [2.1.5 Array Sections]
24372 // The stride must evaluate to a positive integer.
24373 llvm::APSInt StrideValue = Result.Val.getInt();
24374 if (!StrideValue.isStrictlyPositive()) {
24375 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
24376 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
24377 << Stride->getSourceRange();
24378 return ExprError();
24379 }
24380 }
24381 }
24382
24383 if (!Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
24384 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(E: Base);
24385 if (Result.isInvalid())
24386 return ExprError();
24387 Base = Result.get();
24388 }
24389 return new (Context) ArraySectionExpr(
24390 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
24391 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24392}
24393
24394ExprResult SemaOpenMP::ActOnOMPArrayShapingExpr(
24395 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
24396 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
24397 ASTContext &Context = getASTContext();
24398 if (Base->hasPlaceholderType()) {
24399 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base);
24400 if (Result.isInvalid())
24401 return ExprError();
24402 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
24403 if (Result.isInvalid())
24404 return ExprError();
24405 Base = Result.get();
24406 }
24407 QualType BaseTy = Base->getType();
24408 // Delay analysis of the types/expressions if instantiation/specialization is
24409 // required.
24410 if (!BaseTy->isPointerType() && Base->isTypeDependent())
24411 return OMPArrayShapingExpr::Create(Context, T: Context.DependentTy, Op: Base,
24412 L: LParenLoc, R: RParenLoc, Dims, BracketRanges: Brackets);
24413 if (!BaseTy->isPointerType() ||
24414 (!Base->isTypeDependent() &&
24415 BaseTy->getPointeeType()->isIncompleteType()))
24416 return ExprError(Diag(Base->getExprLoc(),
24417 diag::err_omp_non_pointer_type_array_shaping_base)
24418 << Base->getSourceRange());
24419
24420 SmallVector<Expr *, 4> NewDims;
24421 bool ErrorFound = false;
24422 for (Expr *Dim : Dims) {
24423 if (Dim->hasPlaceholderType()) {
24424 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Dim);
24425 if (Result.isInvalid()) {
24426 ErrorFound = true;
24427 continue;
24428 }
24429 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
24430 if (Result.isInvalid()) {
24431 ErrorFound = true;
24432 continue;
24433 }
24434 Dim = Result.get();
24435 }
24436 if (!Dim->isTypeDependent()) {
24437 ExprResult Result =
24438 PerformOpenMPImplicitIntegerConversion(Loc: Dim->getExprLoc(), Op: Dim);
24439 if (Result.isInvalid()) {
24440 ErrorFound = true;
24441 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
24442 << Dim->getSourceRange();
24443 continue;
24444 }
24445 Dim = Result.get();
24446 Expr::EvalResult EvResult;
24447 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(Result&: EvResult, Ctx: Context)) {
24448 // OpenMP 5.0, [2.1.4 Array Shaping]
24449 // Each si is an integral type expression that must evaluate to a
24450 // positive integer.
24451 llvm::APSInt Value = EvResult.Val.getInt();
24452 if (!Value.isStrictlyPositive()) {
24453 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
24454 << toString(Value, /*Radix=*/10, /*Signed=*/true)
24455 << Dim->getSourceRange();
24456 ErrorFound = true;
24457 continue;
24458 }
24459 }
24460 }
24461 NewDims.push_back(Elt: Dim);
24462 }
24463 if (ErrorFound)
24464 return ExprError();
24465 return OMPArrayShapingExpr::Create(Context, T: Context.OMPArrayShapingTy, Op: Base,
24466 L: LParenLoc, R: RParenLoc, Dims: NewDims, BracketRanges: Brackets);
24467}
24468
24469ExprResult SemaOpenMP::ActOnOMPIteratorExpr(Scope *S,
24470 SourceLocation IteratorKwLoc,
24471 SourceLocation LLoc,
24472 SourceLocation RLoc,
24473 ArrayRef<OMPIteratorData> Data) {
24474 ASTContext &Context = getASTContext();
24475 SmallVector<OMPIteratorExpr::IteratorDefinition, 4> ID;
24476 bool IsCorrect = true;
24477 for (const OMPIteratorData &D : Data) {
24478 TypeSourceInfo *TInfo = nullptr;
24479 SourceLocation StartLoc;
24480 QualType DeclTy;
24481 if (!D.Type.getAsOpaquePtr()) {
24482 // OpenMP 5.0, 2.1.6 Iterators
24483 // In an iterator-specifier, if the iterator-type is not specified then
24484 // the type of that iterator is of int type.
24485 DeclTy = Context.IntTy;
24486 StartLoc = D.DeclIdentLoc;
24487 } else {
24488 DeclTy = Sema::GetTypeFromParser(Ty: D.Type, TInfo: &TInfo);
24489 StartLoc = TInfo->getTypeLoc().getBeginLoc();
24490 }
24491
24492 bool IsDeclTyDependent = DeclTy->isDependentType() ||
24493 DeclTy->containsUnexpandedParameterPack() ||
24494 DeclTy->isInstantiationDependentType();
24495 if (!IsDeclTyDependent) {
24496 if (!DeclTy->isIntegralType(Ctx: Context) && !DeclTy->isAnyPointerType()) {
24497 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24498 // The iterator-type must be an integral or pointer type.
24499 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24500 << DeclTy;
24501 IsCorrect = false;
24502 continue;
24503 }
24504 if (DeclTy.isConstant(Ctx: Context)) {
24505 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24506 // The iterator-type must not be const qualified.
24507 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24508 << DeclTy;
24509 IsCorrect = false;
24510 continue;
24511 }
24512 }
24513
24514 // Iterator declaration.
24515 assert(D.DeclIdent && "Identifier expected.");
24516 // Always try to create iterator declarator to avoid extra error messages
24517 // about unknown declarations use.
24518 auto *VD =
24519 VarDecl::Create(C&: Context, DC: SemaRef.CurContext, StartLoc, IdLoc: D.DeclIdentLoc,
24520 Id: D.DeclIdent, T: DeclTy, TInfo, S: SC_None);
24521 VD->setImplicit();
24522 if (S) {
24523 // Check for conflicting previous declaration.
24524 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
24525 LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
24526 RedeclarationKind::ForVisibleRedeclaration);
24527 Previous.suppressDiagnostics();
24528 SemaRef.LookupName(R&: Previous, S);
24529
24530 SemaRef.FilterLookupForScope(R&: Previous, Ctx: SemaRef.CurContext, S,
24531 /*ConsiderLinkage=*/false,
24532 /*AllowInlineNamespace=*/false);
24533 if (!Previous.empty()) {
24534 NamedDecl *Old = Previous.getRepresentativeDecl();
24535 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
24536 Diag(Old->getLocation(), diag::note_previous_definition);
24537 } else {
24538 SemaRef.PushOnScopeChains(D: VD, S);
24539 }
24540 } else {
24541 SemaRef.CurContext->addDecl(D: VD);
24542 }
24543
24544 /// Act on the iterator variable declaration.
24545 ActOnOpenMPIteratorVarDecl(VD: VD);
24546
24547 Expr *Begin = D.Range.Begin;
24548 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
24549 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
24550 From: Begin, ToType: DeclTy, Action: AssignmentAction::Converting);
24551 Begin = BeginRes.get();
24552 }
24553 Expr *End = D.Range.End;
24554 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
24555 ExprResult EndRes = SemaRef.PerformImplicitConversion(
24556 From: End, ToType: DeclTy, Action: AssignmentAction::Converting);
24557 End = EndRes.get();
24558 }
24559 Expr *Step = D.Range.Step;
24560 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
24561 if (!Step->getType()->isIntegralType(Ctx: Context)) {
24562 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
24563 << Step << Step->getSourceRange();
24564 IsCorrect = false;
24565 continue;
24566 }
24567 std::optional<llvm::APSInt> Result =
24568 Step->getIntegerConstantExpr(Ctx: Context);
24569 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
24570 // If the step expression of a range-specification equals zero, the
24571 // behavior is unspecified.
24572 if (Result && Result->isZero()) {
24573 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
24574 << Step << Step->getSourceRange();
24575 IsCorrect = false;
24576 continue;
24577 }
24578 }
24579 if (!Begin || !End || !IsCorrect) {
24580 IsCorrect = false;
24581 continue;
24582 }
24583 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
24584 IDElem.IteratorDecl = VD;
24585 IDElem.AssignmentLoc = D.AssignLoc;
24586 IDElem.Range.Begin = Begin;
24587 IDElem.Range.End = End;
24588 IDElem.Range.Step = Step;
24589 IDElem.ColonLoc = D.ColonLoc;
24590 IDElem.SecondColonLoc = D.SecColonLoc;
24591 }
24592 if (!IsCorrect) {
24593 // Invalidate all created iterator declarations if error is found.
24594 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24595 if (Decl *ID = D.IteratorDecl)
24596 ID->setInvalidDecl();
24597 }
24598 return ExprError();
24599 }
24600 SmallVector<OMPIteratorHelperData, 4> Helpers;
24601 if (!SemaRef.CurContext->isDependentContext()) {
24602 // Build number of ityeration for each iteration range.
24603 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
24604 // ((Begini-Stepi-1-Endi) / -Stepi);
24605 for (OMPIteratorExpr::IteratorDefinition &D : ID) {
24606 // (Endi - Begini)
24607 ExprResult Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Sub,
24608 LHSExpr: D.Range.End, RHSExpr: D.Range.Begin);
24609 if (!Res.isUsable()) {
24610 IsCorrect = false;
24611 continue;
24612 }
24613 ExprResult St, St1;
24614 if (D.Range.Step) {
24615 St = D.Range.Step;
24616 // (Endi - Begini) + Stepi
24617 Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add, LHSExpr: Res.get(),
24618 RHSExpr: St.get());
24619 if (!Res.isUsable()) {
24620 IsCorrect = false;
24621 continue;
24622 }
24623 // (Endi - Begini) + Stepi - 1
24624 Res = SemaRef.CreateBuiltinBinOp(
24625 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: Res.get(),
24626 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 1).get());
24627 if (!Res.isUsable()) {
24628 IsCorrect = false;
24629 continue;
24630 }
24631 // ((Endi - Begini) + Stepi - 1) / Stepi
24632 Res = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Div, LHSExpr: Res.get(),
24633 RHSExpr: St.get());
24634 if (!Res.isUsable()) {
24635 IsCorrect = false;
24636 continue;
24637 }
24638 St1 = SemaRef.CreateBuiltinUnaryOp(OpLoc: D.AssignmentLoc, Opc: UO_Minus,
24639 InputExpr: D.Range.Step);
24640 // (Begini - Endi)
24641 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
24642 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: D.Range.Begin, RHSExpr: D.Range.End);
24643 if (!Res1.isUsable()) {
24644 IsCorrect = false;
24645 continue;
24646 }
24647 // (Begini - Endi) - Stepi
24648 Res1 = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add, LHSExpr: Res1.get(),
24649 RHSExpr: St1.get());
24650 if (!Res1.isUsable()) {
24651 IsCorrect = false;
24652 continue;
24653 }
24654 // (Begini - Endi) - Stepi - 1
24655 Res1 = SemaRef.CreateBuiltinBinOp(
24656 OpLoc: D.AssignmentLoc, Opc: BO_Sub, LHSExpr: Res1.get(),
24657 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 1).get());
24658 if (!Res1.isUsable()) {
24659 IsCorrect = false;
24660 continue;
24661 }
24662 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
24663 Res1 = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Div, LHSExpr: Res1.get(),
24664 RHSExpr: St1.get());
24665 if (!Res1.isUsable()) {
24666 IsCorrect = false;
24667 continue;
24668 }
24669 // Stepi > 0.
24670 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
24671 OpLoc: D.AssignmentLoc, Opc: BO_GT, LHSExpr: D.Range.Step,
24672 RHSExpr: SemaRef.ActOnIntegerConstant(Loc: D.AssignmentLoc, Val: 0).get());
24673 if (!CmpRes.isUsable()) {
24674 IsCorrect = false;
24675 continue;
24676 }
24677 Res = SemaRef.ActOnConditionalOp(QuestionLoc: D.AssignmentLoc, ColonLoc: D.AssignmentLoc,
24678 CondExpr: CmpRes.get(), LHSExpr: Res.get(), RHSExpr: Res1.get());
24679 if (!Res.isUsable()) {
24680 IsCorrect = false;
24681 continue;
24682 }
24683 }
24684 Res = SemaRef.ActOnFinishFullExpr(Expr: Res.get(), /*DiscardedValue=*/false);
24685 if (!Res.isUsable()) {
24686 IsCorrect = false;
24687 continue;
24688 }
24689
24690 // Build counter update.
24691 // Build counter.
24692 auto *CounterVD = VarDecl::Create(C&: Context, DC: SemaRef.CurContext,
24693 StartLoc: D.IteratorDecl->getBeginLoc(),
24694 IdLoc: D.IteratorDecl->getBeginLoc(), Id: nullptr,
24695 T: Res.get()->getType(), TInfo: nullptr, S: SC_None);
24696 CounterVD->setImplicit();
24697 ExprResult RefRes =
24698 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
24699 D.IteratorDecl->getBeginLoc());
24700 // Build counter update.
24701 // I = Begini + counter * Stepi;
24702 ExprResult UpdateRes;
24703 if (D.Range.Step) {
24704 UpdateRes = SemaRef.CreateBuiltinBinOp(
24705 OpLoc: D.AssignmentLoc, Opc: BO_Mul,
24706 LHSExpr: SemaRef.DefaultLvalueConversion(E: RefRes.get()).get(), RHSExpr: St.get());
24707 } else {
24708 UpdateRes = SemaRef.DefaultLvalueConversion(E: RefRes.get());
24709 }
24710 if (!UpdateRes.isUsable()) {
24711 IsCorrect = false;
24712 continue;
24713 }
24714 UpdateRes = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Add,
24715 LHSExpr: D.Range.Begin, RHSExpr: UpdateRes.get());
24716 if (!UpdateRes.isUsable()) {
24717 IsCorrect = false;
24718 continue;
24719 }
24720 ExprResult VDRes =
24721 SemaRef.BuildDeclRefExpr(cast<VarDecl>(Val: D.IteratorDecl),
24722 cast<VarDecl>(Val: D.IteratorDecl)->getType(),
24723 VK_LValue, D.IteratorDecl->getBeginLoc());
24724 UpdateRes = SemaRef.CreateBuiltinBinOp(OpLoc: D.AssignmentLoc, Opc: BO_Assign,
24725 LHSExpr: VDRes.get(), RHSExpr: UpdateRes.get());
24726 if (!UpdateRes.isUsable()) {
24727 IsCorrect = false;
24728 continue;
24729 }
24730 UpdateRes =
24731 SemaRef.ActOnFinishFullExpr(Expr: UpdateRes.get(), /*DiscardedValue=*/true);
24732 if (!UpdateRes.isUsable()) {
24733 IsCorrect = false;
24734 continue;
24735 }
24736 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
24737 OpLoc: D.AssignmentLoc, Opc: UO_PreInc, InputExpr: RefRes.get());
24738 if (!CounterUpdateRes.isUsable()) {
24739 IsCorrect = false;
24740 continue;
24741 }
24742 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(Expr: CounterUpdateRes.get(),
24743 /*DiscardedValue=*/true);
24744 if (!CounterUpdateRes.isUsable()) {
24745 IsCorrect = false;
24746 continue;
24747 }
24748 OMPIteratorHelperData &HD = Helpers.emplace_back();
24749 HD.CounterVD = CounterVD;
24750 HD.Upper = Res.get();
24751 HD.Update = UpdateRes.get();
24752 HD.CounterUpdate = CounterUpdateRes.get();
24753 }
24754 } else {
24755 Helpers.assign(NumElts: ID.size(), Elt: {});
24756 }
24757 if (!IsCorrect) {
24758 // Invalidate all created iterator declarations if error is found.
24759 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24760 if (Decl *ID = D.IteratorDecl)
24761 ID->setInvalidDecl();
24762 }
24763 return ExprError();
24764 }
24765 return OMPIteratorExpr::Create(Context, T: Context.OMPIteratorTy, IteratorKwLoc,
24766 L: LLoc, R: RLoc, Data: ID, Helpers);
24767}
24768
24769/// Check if \p AssumptionStr is a known assumption and warn if not.
24770static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc,
24771 StringRef AssumptionStr) {
24772 if (llvm::KnownAssumptionStrings.count(Key: AssumptionStr))
24773 return;
24774
24775 unsigned BestEditDistance = 3;
24776 StringRef Suggestion;
24777 for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
24778 unsigned EditDistance =
24779 AssumptionStr.edit_distance(Other: KnownAssumptionIt.getKey());
24780 if (EditDistance < BestEditDistance) {
24781 Suggestion = KnownAssumptionIt.getKey();
24782 BestEditDistance = EditDistance;
24783 }
24784 }
24785
24786 if (!Suggestion.empty())
24787 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
24788 << AssumptionStr << Suggestion;
24789 else
24790 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
24791 << AssumptionStr;
24792}
24793
24794void SemaOpenMP::handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL) {
24795 // Handle the case where the attribute has a text message.
24796 StringRef Str;
24797 SourceLocation AttrStrLoc;
24798 if (!SemaRef.checkStringLiteralArgumentAttr(Attr: AL, ArgNum: 0, Str, ArgLocation: &AttrStrLoc))
24799 return;
24800
24801 checkOMPAssumeAttr(S&: SemaRef, Loc: AttrStrLoc, AssumptionStr: Str);
24802
24803 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
24804}
24805
24806SemaOpenMP::SemaOpenMP(Sema &S)
24807 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
24808

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

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